From 587566eda71847b5cd57bfb91b677f7dac653528 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Fri, 11 May 2018 11:29:04 -0300 Subject: [PATCH 1/2] Fix `fn main() -> impl Trait` for non-`Termination` trait Fixes #50595. This bug currently affects stable. Why I think we can go for hard error: - It will in stable for at most one cycle and there is no legitimate reason to abuse it, nor any known uses in the wild. - It only affects `bin` crates (which have a `main`), so there is little practical difference between a hard error or a deny lint, both are a one line fix. The fix was to just unshadow a variable. Thanks @nikomatsakis for the mentoring! r? @nikomatsakis --- src/librustc_typeck/check/mod.rs | 8 ++++---- .../termination-trait-for-impl-termination.rs | 13 +++++++++++++ .../termination-trait-impl-trait.rs | 13 +++++++++++++ .../termination-trait-impl-trait.stderr | 11 +++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs create mode 100644 src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs create mode 100644 src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index db859e42057e..f513b1f23ad4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1038,11 +1038,11 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let ret_ty = fn_sig.output(); fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType); - let ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &ret_ty); - fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); + let revealed_ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &ret_ty); + fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( fn_sig.inputs().iter().cloned(), - ret_ty, + revealed_ret_ty, fn_sig.variadic, fn_sig.unsafety, fn_sig.abi @@ -1124,7 +1124,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, actual_return_ty = fcx.next_diverging_ty_var( TypeVariableOrigin::DivergingFn(span)); } - fcx.demand_suptype(span, ret_ty, actual_return_ty); + fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty); // Check that the main return type implements the termination trait. if let Some(term_id) = fcx.tcx.lang_items().termination() { diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs new file mode 100644 index 000000000000..5bce3f8045ee --- /dev/null +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(termination_trait_lib)] + +fn main() -> impl std::process::Termination { } diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs new file mode 100644 index 000000000000..92d21864c748 --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that an `impl Trait` that is not `impl Termination` will not work. +fn main() -> impl Copy { } +//~^ ERROR `main` has invalid return type `impl std::marker::Copy` diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr new file mode 100644 index 000000000000..7485f3066bb2 --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr @@ -0,0 +1,11 @@ +error[E0277]: `main` has invalid return type `impl std::marker::Copy` + --> $DIR/termination-trait-impl-trait.rs:12:14 + | +LL | fn main() -> impl Copy { } + | ^^^^^^^^^ `main` can only return types that implement `std::process::Termination` + | + = help: consider using `()`, or a `Result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 0582d025e80e4557d7b9e1642ddec3f0188a1aac Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Tue, 15 May 2018 15:42:41 -0300 Subject: [PATCH 2/2] Rename ret_ty to declared_ret_ty --- src/librustc_typeck/check/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f513b1f23ad4..67ee79bc0011 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1036,9 +1036,9 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let mut fcx = FnCtxt::new(inherited, param_env, body.value.id); *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); - let ret_ty = fn_sig.output(); - fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType); - let revealed_ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &ret_ty); + let declared_ret_ty = fn_sig.output(); + fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); + let revealed_ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &declared_ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( fn_sig.inputs().iter().cloned(), @@ -1132,7 +1132,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, if id == fn_id { match entry_type { config::EntryMain => { - let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); + let substs = fcx.tcx.mk_substs(iter::once(Kind::from(declared_ret_ty))); let trait_ref = ty::TraitRef::new(term_id, substs); let return_ty_span = decl.output.span(); let cause = traits::ObligationCause::new(