Skip to content

Commit 235de09

Browse files
committed
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`.
1 parent 7745a7a commit 235de09

File tree

9 files changed

+63
-12
lines changed

9 files changed

+63
-12
lines changed

src/librustc/lint/builtin.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ declare_lint! {
222222
"detect mut variables which don't need to be mutable"
223223
}
224224

225+
declare_lint! {
226+
pub COERCE_NEVER,
227+
Deny,
228+
"detect coercion to !"
229+
}
230+
225231
/// Does nothing as a lint pass, but registers some `Lint`s
226232
/// which are used by other parts of the compiler.
227233
#[derive(Copy, Clone)]
@@ -263,7 +269,8 @@ impl LintPass for HardwiredLints {
263269
LATE_BOUND_LIFETIME_ARGUMENTS,
264270
DEPRECATED,
265271
UNUSED_UNSAFE,
266-
UNUSED_MUT
272+
UNUSED_MUT,
273+
COERCE_NEVER
267274
)
268275
}
269276
}

src/librustc_lint/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
247247
id: LintId::of(SAFE_PACKED_BORROWS),
248248
reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
249249
},
250+
FutureIncompatibleInfo {
251+
id: LintId::of(COERCE_NEVER),
252+
reference: "issue #46325 <https://github.com/rust-lang/rust/issues/42869>",
253+
},
250254

251255
]);
252256

src/librustc_typeck/check/coercion.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ use rustc::hir;
6666
use rustc::hir::def_id::DefId;
6767
use rustc::infer::{Coercion, InferResult, InferOk};
6868
use rustc::infer::type_variable::TypeVariableOrigin;
69+
use rustc::lint;
6970
use rustc::traits::{self, ObligationCause, ObligationCauseCode};
7071
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
7172
use rustc::ty::{self, LvaluePreference, TypeAndMut,
@@ -754,7 +755,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
754755
// type, but only if the source expression diverges.
755756
if target.is_never() && expr_diverges.always() {
756757
debug!("permit coercion to `!` because expr diverges");
757-
return Ok(target);
758+
if self.can_eq(self.param_env, source, target).is_err() {
759+
self.tcx.lint_node(
760+
lint::builtin::COERCE_NEVER,
761+
expr.id,
762+
expr.span,
763+
&format!("cannot coerce `{}` to !", source)
764+
);
765+
return Ok(target);
766+
}
758767
}
759768

760769
let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);

src/test/compile-fail/coerce-to-bang-cast.rs

+3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212

1313
fn foo(x: usize, y: !, z: usize) { }
1414

15+
#[deny(coerce_never)]
1516
fn cast_a() {
1617
let y = {return; 22} as !;
18+
//~^ ERROR cannot coerce `i32` to !
19+
//~| hard error
1720
}
1821

1922
fn cast_b() {

src/test/compile-fail/coerce-to-bang.rs

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![feature(never_type)]
12+
#![deny(coerce_never)]
1213

1314
fn foo(x: usize, y: !, z: usize) { }
1415

@@ -17,6 +18,8 @@ fn call_foo_a() {
1718
// the coercion to `!`, but within same expression. Not clear that
1819
// these are the rules we want.
1920
foo(return, 22, 44);
21+
//~^ ERROR cannot coerce `{integer}` to !
22+
//~| hard error
2023
}
2124

2225
fn call_foo_b() {
@@ -36,6 +39,8 @@ fn call_foo_d() {
3639
let b = 22;
3740
let c = 44;
3841
foo(a, b, c); // ... and hence a reference to `a` is expected to diverge.
42+
//~^ ERROR cannot coerce `{integer}` to !
43+
//~| hard error
3944
}
4045

4146
fn call_foo_e() {
@@ -75,6 +80,8 @@ fn tuple_a() {
7580
fn tuple_b() {
7681
// Divergence happens before coercion: OK
7782
let x: (usize, !, usize) = (return, 44, 66);
83+
//~^ ERROR cannot coerce `{integer}` to !
84+
//~| hard error
7885
}
7986

8087
fn tuple_c() {

src/test/compile-fail/diverging-fn-tail-35849.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
fn _converge() -> ! {
12-
42 //~ ERROR mismatched types
11+
#[deny(coerce_never)]
12+
fn assert_sizeof() -> ! {
13+
unsafe {
14+
::std::mem::transmute::<f64, [u8; 8]>(panic!())
15+
//~^ ERROR cannot coerce `[u8; 8]` to !
16+
//~| hard error
17+
}
1318
}
1419

1520
fn main() { }
16-

src/test/run-pass/diverging-fn-tail-35849.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
#[allow(coerce_never)]
1112
fn assert_sizeof() -> ! {
1213
unsafe {
1314
::std::mem::transmute::<f64, [u8; 8]>(panic!())
1415
}
1516
}
1617

1718
fn main() { }
18-

src/test/ui/reachable/expr_unary.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
#![allow(unused_assignments)]
1313
#![allow(dead_code)]
1414
#![deny(unreachable_code)]
15+
#![deny(coerce_never)]
1516
#![feature(never_type)]
1617

1718
fn foo() {
1819
let x: ! = ! { return; 22 }; //~ ERROR unreachable
19-
//~^ ERROR cannot apply unary operator `!` to type `!`
20+
//~^ ERROR cannot coerce
21+
//~| hard error
22+
//~| ERROR cannot apply unary operator `!` to type `!`
2023
}
2124

2225
fn main() { }
+19-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
error: unreachable expression
2-
--> $DIR/expr_unary.rs:18:28
2+
--> $DIR/expr_unary.rs:19:28
33
|
4-
18 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
4+
19 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
55
| ^^
66
|
77
note: lint level defined here
@@ -10,11 +10,25 @@ note: lint level defined here
1010
14 | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
1212

13+
error: cannot coerce `{integer}` to !
14+
--> $DIR/expr_unary.rs:19:28
15+
|
16+
19 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
17+
| ^^
18+
|
19+
note: lint level defined here
20+
--> $DIR/expr_unary.rs:15:9
21+
|
22+
15 | #![deny(coerce_never)]
23+
| ^^^^^^^^^^^^
24+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
25+
= note: for more information, see issue #46325 <https://github.com/rust-lang/rust/issues/42869>
26+
1327
error[E0600]: cannot apply unary operator `!` to type `!`
14-
--> $DIR/expr_unary.rs:18:16
28+
--> $DIR/expr_unary.rs:19:16
1529
|
16-
18 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
30+
19 | let x: ! = ! { return; 22 }; //~ ERROR unreachable
1731
| ^^^^^^^^^^^^^^^^
1832

19-
error: aborting due to 2 previous errors
33+
error: aborting due to 3 previous errors
2034

0 commit comments

Comments
 (0)