Skip to content

Commit b53e6a8

Browse files
committed
Auto merge of #45880 - arielb1:never-coerce, r=<try>
[needs crater] 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`.
2 parents 3707db9 + 491d128 commit b53e6a8

File tree

8 files changed

+51
-7
lines changed

8 files changed

+51
-7
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(LATE_BOUND_LIFETIME_ARGUMENTS),
248248
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
249249
},
250+
FutureIncompatibleInfo {
251+
id: LintId::of(COERCE_NEVER),
252+
reference: "issue #42869 <https://github.com/rust-lang/rust/issues/42869>",
253+
},
250254
]);
251255

252256
// Register renamed and removed lints

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.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,21 @@ note: lint level defined here
1010
14 | #![deny(unreachable_code)]
1111
| ^^^^^^^^^^^^^^^^
1212

13+
error: cannot coerce `{integer}` to !
14+
--> $DIR/expr_unary.rs:18:28
15+
|
16+
18 | let x: ! = ! { return; 22 };
17+
| ^^
18+
|
19+
= note: #[deny(coerce_never)] on by default
20+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
21+
= note: for more information, see issue #42869 <https://github.com/rust-lang/rust/issues/42869>
22+
1323
error[E0600]: cannot apply unary operator `!` to type `!`
1424
--> $DIR/expr_unary.rs:18:16
1525
|
1626
18 | let x: ! = ! { return; 22 };
1727
| ^^^^^^^^^^^^^^^^
1828

19-
error: aborting due to 2 previous errors
29+
error: aborting due to 3 previous errors
2030

0 commit comments

Comments
 (0)