Skip to content

Commit 8946fda

Browse files
committed
Edition 2024: don't special case diverging blocks
1 parent 0e3235f commit 8946fda

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,18 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
4646
use std::iter;
4747
use std::mem;
4848

49-
#[derive(Clone, Copy, Default)]
49+
#[derive(Clone, Copy)]
5050
pub enum DivergingBlockBehavior {
51-
/// This is the current stable behavior:
51+
/// This is edition <= 2021 behavior:
5252
///
5353
/// ```rust
5454
/// {
5555
/// return;
5656
/// } // block has type = !, even though we are supposedly dropping it with `;`
5757
/// ```
58-
#[default]
5958
Never,
6059

61-
/// Alternative behavior:
60+
/// This is edition >= 2024 behavior:
6261
///
6362
/// ```ignore (very-unstable-new-attribute)
6463
/// #![rustc_never_type_options(diverging_block_default = "unit")]

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,16 @@ fn parse_never_type_options_attr(
441441
if tcx.features().never_type_fallback { FallbackToNiko } else { FallbackToUnit }
442442
});
443443

444-
let block = block.unwrap_or_default();
444+
let block = block.unwrap_or_else(|| default_diverging_block_behavior(tcx));
445445

446446
(fallback, block)
447447
}
448+
449+
/// Returns the edition-based default diverging block behavior
450+
fn default_diverging_block_behavior(tcx: TyCtxt<'_>) -> DivergingBlockBehavior {
451+
if tcx.sess.edition().at_least_rust_2024() {
452+
return DivergingBlockBehavior::Unit;
453+
}
454+
455+
DivergingBlockBehavior::Never
456+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/diverging-block.rs:15:18
3+
|
4+
LL | let _: u32 = {
5+
| __________________^
6+
LL | | return;
7+
LL | | };
8+
| |_____^ expected `u32`, found `()`
9+
10+
error[E0308]: `if` and `else` have incompatible types
11+
--> $DIR/diverging-block.rs:25:9
12+
|
13+
LL | / if true {
14+
LL | | return;
15+
| | ------- expected because of this
16+
LL | | } else {
17+
LL | | 0_u32
18+
| | ^^^^^ expected `()`, found `u32`
19+
LL | | };
20+
| |_____- `if` and `else` have incompatible types
21+
22+
error: aborting due to 2 previous errors
23+
24+
For more information about this error, try `rustc --explain E0308`.

tests/ui/editions/diverging-block.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ revisions: e2021 e2024
2+
//
3+
//@[e2021] edition: 2021
4+
//@[e2024] edition: 2024
5+
//@[e2024] compile-flags: -Zunstable-options
6+
//
7+
//@[e2021] check-pass
8+
//@[e2024] check-fail
9+
10+
fn main() {
11+
// a diverging block, with no tail expression.
12+
//
13+
// edition <= 2021: the block has type `!`, which then can be coerced.
14+
// edition >= 2024: the block has type `()`, as with any block with no tail.
15+
let _: u32 = { //[e2024]~ error: mismatched types
16+
return;
17+
};
18+
}
19+
20+
fn _f() {
21+
// Same as the above, but with an if
22+
if true {
23+
return;
24+
} else {
25+
0_u32 //[e2024]~ error: `if` and `else` have incompatible types
26+
};
27+
}

0 commit comments

Comments
 (0)