@@ -6,6 +6,7 @@ mod suggestions;
66
77use crate :: coercion:: DynamicCoerceMany ;
88use crate :: fallback:: DivergingFallbackBehavior ;
9+ use crate :: fn_ctxt:: checks:: DivergingBlockBehavior ;
910use crate :: { CoroutineTypes , Diverges , EnclosingBreakables , Inherited } ;
1011use hir:: def_id:: CRATE_DEF_ID ;
1112use rustc_errors:: { DiagCtxt , ErrorGuaranteed } ;
@@ -112,6 +113,7 @@ pub struct FnCtxt<'a, 'tcx> {
112113 pub ( super ) fallback_has_occurred : Cell < bool > ,
113114
114115 pub ( super ) diverging_fallback_behavior : DivergingFallbackBehavior ,
116+ pub ( super ) diverging_block_behavior : DivergingBlockBehavior ,
115117}
116118
117119impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
@@ -120,7 +122,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
120122 param_env : ty:: ParamEnv < ' tcx > ,
121123 body_id : LocalDefId ,
122124 ) -> 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 ) ;
124127 FnCtxt {
125128 body_id,
126129 param_env,
@@ -137,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
137140 inh,
138141 fallback_has_occurred : Cell :: new ( false ) ,
139142 diverging_fallback_behavior,
143+ diverging_block_behavior,
140144 }
141145 }
142146
@@ -381,13 +385,16 @@ impl<'tcx> LoweredTy<'tcx> {
381385 }
382386}
383387
384- fn parse_never_type_options_attr ( tcx : TyCtxt < ' _ > ) -> DivergingFallbackBehavior {
388+ fn parse_never_type_options_attr (
389+ tcx : TyCtxt < ' _ > ,
390+ ) -> ( DivergingFallbackBehavior , DivergingBlockBehavior ) {
385391 use DivergingFallbackBehavior :: * ;
386392
387393 // Error handling is dubious here (unwraps), but that's probably fine for an internal attribute.
388394 // Just don't write incorrect attributes <3
389395
390396 let mut fallback = None ;
397+ let mut block = None ;
391398
392399 let items = tcx
393400 . get_attr ( CRATE_DEF_ID , sym:: rustc_never_type_options)
@@ -409,6 +416,18 @@ fn parse_never_type_options_attr(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior {
409416 continue ;
410417 }
411418
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+
412431 tcx. dcx ( ) . span_err (
413432 item. span ( ) ,
414433 format ! (
@@ -422,5 +441,7 @@ fn parse_never_type_options_attr(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior {
422441 if tcx. features ( ) . never_type_fallback { FallbackToNiko } else { FallbackToUnit }
423442 } ) ;
424443
425- fallback
444+ let block = block. unwrap_or_default ( ) ;
445+
446+ ( fallback, block)
426447}
0 commit comments