@@ -6,6 +6,7 @@ mod suggestions;
6
6
7
7
use crate :: coercion:: DynamicCoerceMany ;
8
8
use crate :: fallback:: DivergingFallbackBehavior ;
9
+ use crate :: fn_ctxt:: checks:: DivergingBlockBehavior ;
9
10
use crate :: { CoroutineTypes , Diverges , EnclosingBreakables , Inherited } ;
10
11
use hir:: def_id:: CRATE_DEF_ID ;
11
12
use rustc_errors:: { DiagCtxt , ErrorGuaranteed } ;
@@ -112,6 +113,7 @@ pub struct FnCtxt<'a, 'tcx> {
112
113
pub ( super ) fallback_has_occurred : Cell < bool > ,
113
114
114
115
pub ( super ) diverging_fallback_behavior : DivergingFallbackBehavior ,
116
+ pub ( super ) diverging_block_behavior : DivergingBlockBehavior ,
115
117
}
116
118
117
119
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
@@ -120,7 +122,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
120
122
param_env : ty:: ParamEnv < ' tcx > ,
121
123
body_id : LocalDefId ,
122
124
) -> FnCtxt < ' a , ' tcx > {
123
- let diverging_fallback_behavior = parse_never_type_options_attr ( inh. tcx ) ;
125
+ let ( diverging_fallback_behavior, diverging_block_behavior) =
126
+ parse_never_type_options_attr ( inh. tcx ) ;
124
127
FnCtxt {
125
128
body_id,
126
129
param_env,
@@ -137,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
137
140
inh,
138
141
fallback_has_occurred : Cell :: new ( false ) ,
139
142
diverging_fallback_behavior,
143
+ diverging_block_behavior,
140
144
}
141
145
}
142
146
@@ -381,13 +385,16 @@ impl<'tcx> LoweredTy<'tcx> {
381
385
}
382
386
}
383
387
384
- fn parse_never_type_options_attr ( tcx : TyCtxt < ' _ > ) -> DivergingFallbackBehavior {
388
+ fn parse_never_type_options_attr (
389
+ tcx : TyCtxt < ' _ > ,
390
+ ) -> ( DivergingFallbackBehavior , DivergingBlockBehavior ) {
385
391
use DivergingFallbackBehavior :: * ;
386
392
387
393
// Error handling is dubious here (unwraps), but that's probably fine for an internal attribute.
388
394
// Just don't write incorrect attributes <3
389
395
390
396
let mut fallback = None ;
397
+ let mut block = None ;
391
398
392
399
let items = tcx
393
400
. get_attr ( CRATE_DEF_ID , sym:: rustc_never_type_options)
@@ -409,6 +416,18 @@ fn parse_never_type_options_attr(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior {
409
416
continue ;
410
417
}
411
418
419
+ if item. has_name ( sym:: diverging_block_default) && fallback. is_none ( ) {
420
+ let mode = item. value_str ( ) . unwrap ( ) ;
421
+ match mode {
422
+ sym:: unit => block = Some ( DivergingBlockBehavior :: Unit ) ,
423
+ sym:: never => block = Some ( DivergingBlockBehavior :: Never ) ,
424
+ _ => {
425
+ tcx. dcx ( ) . span_err ( item. span ( ) , format ! ( "unknown diverging block default: `{mode}` (supported: `unit` and `never`)" ) ) ;
426
+ }
427
+ } ;
428
+ continue ;
429
+ }
430
+
412
431
tcx. dcx ( ) . span_err (
413
432
item. span ( ) ,
414
433
format ! (
@@ -422,5 +441,7 @@ fn parse_never_type_options_attr(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior {
422
441
if tcx. features ( ) . never_type_fallback { FallbackToNiko } else { FallbackToUnit }
423
442
} ) ;
424
443
425
- fallback
444
+ let block = block. unwrap_or_default ( ) ;
445
+
446
+ ( fallback, block)
426
447
}
0 commit comments