about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2017-12-02 01:38:52 +0800
committerGitHub <noreply@github.com>2017-12-02 01:38:52 +0800
commit95f465d5355f559e9c1955a7e4774dc3e619ed63 (patch)
tree995f98cb302845ca94dddfcb041fd77177ed14d8 /src
parente3ed21272d5f50c37c09f2a7f06c40f56b6ac298 (diff)
parent5a00b7cb74ba1511c012c0163a29cd6972d64135 (diff)
downloadrust-95f465d5355f559e9c1955a7e4774dc3e619ed63.tar.gz
rust-95f465d5355f559e9c1955a7e4774dc3e619ed63.zip
Rollup merge of #45880 - arielb1:never-coerce, r=nikomatsakis
make coercions to `!` in unreachable code a hard error

This was added to cover up a lazy extra semicolon in #35849, but does
not actually make sense. This is removed as a part of the stabilization
of `never_type`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lint/builtin.rs9
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/librustc_typeck/check/coercion.rs11
-rw-r--r--src/test/compile-fail/coerce-to-bang-cast.rs3
-rw-r--r--src/test/compile-fail/coerce-to-bang.rs7
-rw-r--r--src/test/compile-fail/diverging-fn-tail-35849.rs10
-rw-r--r--src/test/run-pass/diverging-fn-tail-35849.rs2
-rw-r--r--src/test/ui/reachable/expr_unary.rs5
-rw-r--r--src/test/ui/reachable/expr_unary.stderr24
9 files changed, 63 insertions, 12 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index ef4a1c8c399..1008da1e937 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -222,6 +222,12 @@ declare_lint! {
     "detect mut variables which don't need to be mutable"
 }
 
+declare_lint! {
+    pub COERCE_NEVER,
+    Deny,
+    "detect coercion to !"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -263,7 +269,8 @@ impl LintPass for HardwiredLints {
             LATE_BOUND_LIFETIME_ARGUMENTS,
             DEPRECATED,
             UNUSED_UNSAFE,
-            UNUSED_MUT
+            UNUSED_MUT,
+            COERCE_NEVER
         )
     }
 }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index b4d439f0ba8..fc05f8f0dc2 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -247,6 +247,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             id: LintId::of(SAFE_PACKED_BORROWS),
             reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(COERCE_NEVER),
+            reference: "issue #46325 <https://github.com/rust-lang/rust/issues/46325>",
+        },
 
         ]);
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 94422f93e59..3e725d7ef41 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -66,6 +66,7 @@ use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::infer::{Coercion, InferResult, InferOk};
 use rustc::infer::type_variable::TypeVariableOrigin;
+use rustc::lint;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
 use rustc::ty::{self, LvaluePreference, TypeAndMut,
@@ -754,7 +755,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // type, but only if the source expression diverges.
         if target.is_never() && expr_diverges.always() {
             debug!("permit coercion to `!` because expr diverges");
-            return Ok(target);
+            if self.can_eq(self.param_env, source, target).is_err() {
+                self.tcx.lint_node(
+                    lint::builtin::COERCE_NEVER,
+                    expr.id,
+                    expr.span,
+                    &format!("cannot coerce `{}` to !", source)
+                );
+                return Ok(target);
+            }
         }
 
         let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs
index 0479f5cce65..0d5bf6cd68c 100644
--- a/src/test/compile-fail/coerce-to-bang-cast.rs
+++ b/src/test/compile-fail/coerce-to-bang-cast.rs
@@ -12,8 +12,11 @@
 
 fn foo(x: usize, y: !, z: usize) { }
 
+#[deny(coerce_never)]
 fn cast_a() {
     let y = {return; 22} as !;
+    //~^ ERROR cannot coerce `i32` to !
+    //~| hard error
 }
 
 fn cast_b() {
diff --git a/src/test/compile-fail/coerce-to-bang.rs b/src/test/compile-fail/coerce-to-bang.rs
index 870665bb49e..2cf568777d4 100644
--- a/src/test/compile-fail/coerce-to-bang.rs
+++ b/src/test/compile-fail/coerce-to-bang.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(never_type)]
+#![deny(coerce_never)]
 
 fn foo(x: usize, y: !, z: usize) { }
 
@@ -17,6 +18,8 @@ fn call_foo_a() {
     // the coercion to `!`, but within same expression. Not clear that
     // these are the rules we want.
     foo(return, 22, 44);
+    //~^ ERROR cannot coerce `{integer}` to !
+    //~| hard error
 }
 
 fn call_foo_b() {
@@ -36,6 +39,8 @@ fn call_foo_d() {
     let b = 22;
     let c = 44;
     foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
+    //~^ ERROR cannot coerce `{integer}` to !
+    //~| hard error
 }
 
 fn call_foo_e() {
@@ -75,6 +80,8 @@ fn tuple_a() {
 fn tuple_b() {
     // Divergence happens before coercion: OK
     let x: (usize, !, usize) = (return, 44, 66);
+    //~^ ERROR cannot coerce `{integer}` to !
+    //~| hard error
 }
 
 fn tuple_c() {
diff --git a/src/test/compile-fail/diverging-fn-tail-35849.rs b/src/test/compile-fail/diverging-fn-tail-35849.rs
index 3a27c084133..a91c000bbf7 100644
--- a/src/test/compile-fail/diverging-fn-tail-35849.rs
+++ b/src/test/compile-fail/diverging-fn-tail-35849.rs
@@ -8,9 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn _converge() -> ! {
-    42 //~ ERROR mismatched types
+#[deny(coerce_never)]
+fn assert_sizeof() -> ! {
+    unsafe {
+        ::std::mem::transmute::<f64, [u8; 8]>(panic!())
+            //~^ ERROR cannot coerce `[u8; 8]` to !
+            //~| hard error
+    }
 }
 
 fn main() { }
-
diff --git a/src/test/run-pass/diverging-fn-tail-35849.rs b/src/test/run-pass/diverging-fn-tail-35849.rs
index 6c05a02e718..dfd99bcc9fb 100644
--- a/src/test/run-pass/diverging-fn-tail-35849.rs
+++ b/src/test/run-pass/diverging-fn-tail-35849.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[allow(coerce_never)]
 fn assert_sizeof() -> ! {
     unsafe {
         ::std::mem::transmute::<f64, [u8; 8]>(panic!())
@@ -15,4 +16,3 @@ fn assert_sizeof() -> ! {
 }
 
 fn main() { }
-
diff --git a/src/test/ui/reachable/expr_unary.rs b/src/test/ui/reachable/expr_unary.rs
index 6cff3ff9644..ad12cb876fe 100644
--- a/src/test/ui/reachable/expr_unary.rs
+++ b/src/test/ui/reachable/expr_unary.rs
@@ -12,11 +12,14 @@
 #![allow(unused_assignments)]
 #![allow(dead_code)]
 #![deny(unreachable_code)]
+#![deny(coerce_never)]
 #![feature(never_type)]
 
 fn foo() {
     let x: ! = ! { return; 22 }; //~ ERROR unreachable
-    //~^ ERROR cannot apply unary operator `!` to type `!`
+    //~^ ERROR cannot coerce
+    //~| hard error
+    //~| ERROR cannot apply unary operator `!` to type `!`
 }
 
 fn main() { }
diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr
index f14824728a7..39120f0bdf9 100644
--- a/src/test/ui/reachable/expr_unary.stderr
+++ b/src/test/ui/reachable/expr_unary.stderr
@@ -1,7 +1,7 @@
 error: unreachable expression
-  --> $DIR/expr_unary.rs:18:28
+  --> $DIR/expr_unary.rs:19:28
    |
-18 |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
+19 |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
    |                            ^^
    |
 note: lint level defined here
@@ -10,11 +10,25 @@ note: lint level defined here
 14 | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
+error: cannot coerce `{integer}` to !
+  --> $DIR/expr_unary.rs:19:28
+   |
+19 |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
+   |                            ^^
+   |
+note: lint level defined here
+  --> $DIR/expr_unary.rs:15:9
+   |
+15 | #![deny(coerce_never)]
+   |         ^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46325 <https://github.com/rust-lang/rust/issues/46325>
+
 error[E0600]: cannot apply unary operator `!` to type `!`
-  --> $DIR/expr_unary.rs:18:16
+  --> $DIR/expr_unary.rs:19:16
    |
-18 |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
+19 |     let x: ! = ! { return; 22 }; //~ ERROR unreachable
    |                ^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors