about summary refs log tree commit diff
diff options
context:
space:
mode:
authorleonardo.yvens <leoyvens@gmail.com>2018-05-11 11:29:04 -0300
committerleonardo.yvens <leoyvens@gmail.com>2018-05-11 11:29:04 -0300
commit587566eda71847b5cd57bfb91b677f7dac653528 (patch)
tree6f5221893144087e003b926636108fdd47d8a236
parente5f80f2a4f016bf724a1cfb580619d71c8fd39ec (diff)
downloadrust-587566eda71847b5cd57bfb91b677f7dac653528.tar.gz
rust-587566eda71847b5cd57bfb91b677f7dac653528.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
-rw-r--r--src/librustc_typeck/check/mod.rs8
-rw-r--r--src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-impl-termination.rs13
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.rs13
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-impl-trait.stderr11
4 files changed, 41 insertions, 4 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index db859e42057..f513b1f23ad 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 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`.