diff options
| author | leonardo.yvens <leoyvens@gmail.com> | 2018-05-11 11:29:04 -0300 |
|---|---|---|
| committer | Mark Simulacrum <mark.simulacrum@gmail.com> | 2018-05-24 14:27:07 -0600 |
| commit | 31fe67cc069b73b827df925dfa87bc008a6876ee (patch) | |
| tree | 6fe3f4bf00aa7fd27d3e6e5d20b56918276acbb9 | |
| parent | 4c67e7069cfdc90047058145e420697c04dd1b3f (diff) | |
| download | rust-31fe67cc069b73b827df925dfa87bc008a6876ee.tar.gz rust-31fe67cc069b73b827df925dfa87bc008a6876ee.zip | |
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
4 files changed, 44 insertions, 7 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1443672c161..923f3d7b190 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1035,13 +1035,13 @@ 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 ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &ret_ty); - fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(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(), - ret_ty, + revealed_ret_ty, fn_sig.variadic, fn_sig.unsafety, fn_sig.abi @@ -1123,7 +1123,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() { @@ -1131,7 +1131,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, if id == fn_id { match fcx.sess().entry_type.get() { Some(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( 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 00000000000..5bce3f8045e --- /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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..92d21864c74 --- /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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 00000000000..7485f3066bb --- /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`. |
