Skip to content

Commit 68e6f9c

Browse files
committed
Add #![feature(no_never_type_spontaneous_decay)]
1 parent e8e4ecf commit 68e6f9c

File tree

5 files changed

+46
-1
lines changed

5 files changed

+46
-1
lines changed

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ declare_features! (
213213
(internal, negative_bounds, "1.71.0", None),
214214
/// Turns off never type fallback altogether
215215
(unstable, no_never_type_fallback, "CURRENT_RUSTC_VERSION", None), // no tracking issue (yet?)
216+
/// Makes never type fallback always be `!`
217+
(unstable, no_never_type_spontaneous_decay, "CURRENT_RUSTC_VERSION", None), // no tracking issue (yet?)
216218
/// Allows using `#[omit_gdb_pretty_printer_section]`.
217219
(internal, omit_gdb_pretty_printer_section, "1.5.0", None),
218220
/// Set the maximum pattern complexity allowed (not limited by default).

compiler/rustc_hir_typeck/src/fallback.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ enum DivergingFallbackBehavior {
1212
FallbackToUnit,
1313
/// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken.
1414
FallbackToNiko,
15+
/// Always fallback to `!` (which should be equivalent to never falling back + not making
16+
/// never-to-any coercions unless necessary)
17+
FallbackToNever,
1518
/// Don't fallback at all
1619
Nope,
1720
}
@@ -91,9 +94,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
9194

9295
fn diverging_fallback_behavior(&self) -> DivergingFallbackBehavior {
9396
let niko = self.tcx.features().never_type_fallback;
97+
let never = self.tcx.features().no_never_type_spontaneous_decay;
9498
let nope = self.tcx.features().no_never_type_fallback;
9599

96-
if niko as u32 + nope as u32 > 1 {
100+
if niko as u32 + never as u32 + nope as u32 > 1 {
97101
self.tcx.dcx().err("can't enable multiple never type fallback features (`never_type_fallback`, `no_never_type_fallback`)");
98102
return DivergingFallbackBehavior::FallbackToUnit;
99103
}
@@ -102,6 +106,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
102106
return DivergingFallbackBehavior::FallbackToNiko;
103107
}
104108

109+
if never {
110+
return DivergingFallbackBehavior::FallbackToNever;
111+
}
112+
105113
if nope {
106114
return DivergingFallbackBehavior::Nope;
107115
}
@@ -419,6 +427,13 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
419427
diverging_fallback.insert(diverging_ty, self.tcx.types.never);
420428
}
421429
}
430+
FallbackToNever => {
431+
debug!(
432+
"fallback to ! - `feature(no_never_type_spontaneous_decay)`: {:?}",
433+
diverging_vid
434+
);
435+
diverging_fallback.insert(diverging_ty, self.tcx.types.never);
436+
}
422437
Nope => {
423438
debug!("not fallback - `feature(no_never_type_fallback)`: {:?}", diverging_vid);
424439
}

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1239,6 +1239,7 @@ symbols! {
12391239
no_main,
12401240
no_mangle,
12411241
no_never_type_fallback,
1242+
no_never_type_spontaneous_decay,
12421243
no_sanitize,
12431244
no_stack_check,
12441245
no_start,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn main() {
2+
// Because of the default never type fallback, this infers `?T = ?R = ()`, which makes this
3+
// fail because of the `T: Error` bound. However, with
4+
// `#![feature(no_never_type_spontaneous_decay)]` this would compile (it would infer
5+
// `?T = ?R = !` and `!: Error` can be satisfied)
6+
#[allow(unreachable_code)]
7+
polymorphic_only_never(return); //~ error: the trait bound `(): std::error::Error` is not satisfied
8+
}
9+
10+
fn polymorphic_only_never<T: std::error::Error>(_: T) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0277]: the trait bound `(): std::error::Error` is not satisfied
2+
--> $DIR/feature-gate-no-never-type-spontaneous-decay.rs:7:28
3+
|
4+
LL | polymorphic_only_never(return);
5+
| ---------------------- ^^^^^^ the trait `std::error::Error` is not implemented for `()`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
note: required by a bound in `polymorphic_only_never`
10+
--> $DIR/feature-gate-no-never-type-spontaneous-decay.rs:10:30
11+
|
12+
LL | fn polymorphic_only_never<T: std::error::Error>(_: T) {}
13+
| ^^^^^^^^^^^^^^^^^ required by this bound in `polymorphic_only_never`
14+
15+
error: aborting due to 1 previous error
16+
17+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)