Rollup merge of #50656 - leodasvacas:fix-impl-trait-in-main-ret, r=nikomatsakis

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
This commit is contained in:
kennytm 2018-05-16 23:22:47 +08:00 committed by GitHub
commit 5cc6fd35c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 7 deletions

View file

@ -1031,13 +1031,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
@ -1119,7 +1119,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() {
@ -1127,7 +1127,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(

View file

@ -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 { }

View file

@ -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`

View file

@ -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`.