Skip to content

Commit 31fe67c

Browse files
leoyvensMark-Simulacrum
authored andcommitted
Fix fn main() -> impl Trait for non-Termination trait
Fixes rust-lang#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
1 parent 4c67e70 commit 31fe67c

File tree

4 files changed

+44
-7
lines changed

4 files changed

+44
-7
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,13 +1035,13 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
10351035
let mut fcx = FnCtxt::new(inherited, param_env, body.value.id);
10361036
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
10371037

1038-
let ret_ty = fn_sig.output();
1039-
fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType);
1040-
let ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &ret_ty);
1041-
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
1038+
let declared_ret_ty = fn_sig.output();
1039+
fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
1040+
let revealed_ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &declared_ret_ty);
1041+
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
10421042
fn_sig = fcx.tcx.mk_fn_sig(
10431043
fn_sig.inputs().iter().cloned(),
1044-
ret_ty,
1044+
revealed_ret_ty,
10451045
fn_sig.variadic,
10461046
fn_sig.unsafety,
10471047
fn_sig.abi
@@ -1123,15 +1123,15 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
11231123
actual_return_ty = fcx.next_diverging_ty_var(
11241124
TypeVariableOrigin::DivergingFn(span));
11251125
}
1126-
fcx.demand_suptype(span, ret_ty, actual_return_ty);
1126+
fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
11271127

11281128
// Check that the main return type implements the termination trait.
11291129
if let Some(term_id) = fcx.tcx.lang_items().termination() {
11301130
if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
11311131
if id == fn_id {
11321132
match fcx.sess().entry_type.get() {
11331133
Some(config::EntryMain) => {
1134-
let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
1134+
let substs = fcx.tcx.mk_substs(iter::once(Kind::from(declared_ret_ty)));
11351135
let trait_ref = ty::TraitRef::new(term_id, substs);
11361136
let return_ty_span = decl.output.span();
11371137
let cause = traits::ObligationCause::new(
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(termination_trait_lib)]
12+
13+
fn main() -> impl std::process::Termination { }
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Tests that an `impl Trait` that is not `impl Termination` will not work.
12+
fn main() -> impl Copy { }
13+
//~^ ERROR `main` has invalid return type `impl std::marker::Copy`
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0277]: `main` has invalid return type `impl std::marker::Copy`
2+
--> $DIR/termination-trait-impl-trait.rs:12:14
3+
|
4+
LL | fn main() -> impl Copy { }
5+
| ^^^^^^^^^ `main` can only return types that implement `std::process::Termination`
6+
|
7+
= help: consider using `()`, or a `Result`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)