Change:
we’re stabilizing the combination of features that allows you to put in the return type of main as in . Amusing but unintended so it’s better to forbid this for now.
It's a bit late to change this. Does it cause any problem? AFAICT it just gives you a weird way to declare , but no new capability.
It doesn't give any new capability, I guess would even make sense in the return type of main. This bug could be considered a feature.
cc
Why this is an issue? returns and implements .
does not implement , which is required for the return type of .
Yea, it seems you can use any trait: Works on beta and nightly. So it'll probably work on this weeks stable You can't do anything stupid with this feature. The checks see right through the impl Trait to the real type (). I'd say adding a regression test that ensures that this corner case essentially ignores the anonymization of impl Trait is fine. We can add a deny by default lint that tells you that while this works, it's not pretty.
This seems fine to me and unless we care enough to stop the stable release we're not going to change this. cc though.
Hmm, I feel like we should just fix this. I doubt there are a lot of people taking advantage of it. I can put up some mentoring instructions. We can do a warning period if needed.
Fwiw I tried fixing by doing and got ICEs and stack oveflows which I couldn't debug so I gave up.
Hmm, I don't understand the stack overflows, but I think I would expect that patch to have no effect. The cause of the bug is that we are "instantiating" the impl Trait, here: In the process, we shadow the "original" with a new variable . This new will contain an inference variable used to find the "hidden" type underneath the . Later on, when we add the obligation that (where is the return type), we use this new variable: If we used the original (currently shadowed) , I think it would permit you to use but not other impl traits. (That said, it wouldn't be the end of the world if we just let this go, I suppose.)
As far as I understand we don't want to block 1.26 stable on this, right? In that case I think we should go with a lint instead of an hard error, since both of the features will be stabilized now.
I probably borked the state of my clone or something. Thanks for the explanation, makes perfect sense, will make a patch.

Discussion:
let mut fcx = FnCtxt::new(inherited, param_env, body.value.id); *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); <del> 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))); </del> <ins> 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))); </ins> fn_sig = fcx.tcx.mk_fn_sig( fn_sig.inputs().iter().cloned(), <del> ret_ty, </del> <ins> revealed_ret_ty, </ins> fn_sig.variadic, fn_sig.unsafety, fn_sig.abi

actual_return_ty = fcx.next_diverging_ty_var( TypeVariableOrigin::DivergingFn(span)); } <del> fcx.demand_suptype(span, ret_ty, actual_return_ty); </del> <ins> fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty); </ins> // Check that the main return type implements the termination trait. if let Some(term_id) = fcx.tcx.lang_items().termination() {

if id == fn_id { match entry_type { config::EntryMain => { <del> let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty))); </del> <ins> let substs = fcx.tcx.mk_substs(iter::once(Kind::from(declared_ret_ty))); </ins> let trait_ref = ty::TraitRef::new(term_id, substs); let return_ty_span = decl.output.span(); let cause = traits::ObligationCause::new(

<ins> // 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 { } </ins>

<ins> // 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` </ins>

<ins> 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`. </ins>