@@ -256,54 +256,40 @@ pub fn find_stability(
256
256
attrs : & [ Attribute ] ,
257
257
item_sp : Span ,
258
258
) -> Option < ( Stability , Span ) > {
259
- let mut stab : Option < ( Stability , Span ) > = None ;
259
+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
260
260
let mut allowed_through_unstable_modules = false ;
261
261
262
262
for attr in attrs {
263
263
match attr. name_or_empty ( ) {
264
264
sym:: rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true ,
265
265
sym:: unstable => {
266
- if stab. is_some ( ) {
267
- sess. dcx ( )
268
- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
266
+ if try_add_unstability ( sess, attr, & mut level) . is_err ( ) {
269
267
break ;
270
268
}
271
-
272
- if let Some ( level) = parse_unstability ( sess, attr) {
273
- stab = Some ( ( Stability { level } , attr. span ) ) ;
274
- }
275
269
}
276
270
sym:: stable => {
277
- if stab. is_some ( ) {
278
- sess. dcx ( )
279
- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
271
+ if try_add_stability ( sess, attr, & mut level) . is_err ( ) {
280
272
break ;
281
273
}
282
- if let Some ( level) = parse_stability ( sess, attr) {
283
- stab = Some ( ( Stability { level } , attr. span ) ) ;
284
- }
285
274
}
286
275
_ => { }
287
276
}
288
277
}
289
278
290
279
if allowed_through_unstable_modules {
291
- match & mut stab {
292
- Some ( (
293
- Stability {
294
- level : StabilityLevel :: Stable { allowed_through_unstable_modules, .. } ,
295
- ..
296
- } ,
297
- _,
298
- ) ) => * allowed_through_unstable_modules = true ,
280
+ match & mut level {
281
+ Some ( ( StabilityLevel :: Stable { allowed_through_unstable_modules, .. } , _) ) => {
282
+ * allowed_through_unstable_modules = true
283
+ }
299
284
_ => {
300
285
sess. dcx ( )
301
286
. emit_err ( session_diagnostics:: RustcAllowedUnstablePairing { span : item_sp } ) ;
302
287
}
303
288
}
304
289
}
305
290
306
- stab
291
+ let ( level, stab_sp) = level?;
292
+ Some ( ( Stability { level } , stab_sp) )
307
293
}
308
294
309
295
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
@@ -316,101 +302,69 @@ pub fn find_const_stability(
316
302
item_sp : Span ,
317
303
is_const_fn : bool ,
318
304
) -> Option < ( ConstStability , Span ) > {
319
- let mut const_stab : Option < ( ConstStability , Span ) > = None ;
305
+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
320
306
let mut promotable = false ;
321
307
let mut const_stable_indirect = None ;
322
- let const_stability_level = |level| match level {
323
- StabilityLevel :: Unstable { unstables, .. } => ConstStabilityLevel :: Unstable { unstables } ,
324
- StabilityLevel :: Stable { since, .. } => ConstStabilityLevel :: Stable { since } ,
325
- } ;
326
308
327
309
for attr in attrs {
328
310
match attr. name_or_empty ( ) {
329
311
sym:: rustc_promotable => promotable = true ,
330
312
sym:: rustc_const_stable_indirect => const_stable_indirect = Some ( attr. span ) ,
331
313
sym:: rustc_const_unstable => {
332
- if const_stab. is_some ( ) {
333
- sess. dcx ( )
334
- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
314
+ if try_add_unstability ( sess, attr, & mut level) . is_err ( ) {
335
315
break ;
336
316
}
337
-
338
- if let Some ( level) = parse_unstability ( sess, attr) {
339
- const_stab = Some ( (
340
- ConstStability {
341
- level : const_stability_level ( level) ,
342
- const_stable_indirect : false ,
343
- promotable : false ,
344
- } ,
345
- attr. span ,
346
- ) ) ;
347
- }
348
317
}
349
318
sym:: rustc_const_stable => {
350
- if const_stab. is_some ( ) {
351
- sess. dcx ( )
352
- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
319
+ if try_add_stability ( sess, attr, & mut level) . is_err ( ) {
353
320
break ;
354
321
}
355
- if let Some ( level) = parse_stability ( sess, attr) {
356
- const_stab = Some ( (
357
- ConstStability {
358
- level : const_stability_level ( level) ,
359
- const_stable_indirect : false ,
360
- promotable : false ,
361
- } ,
362
- attr. span ,
363
- ) ) ;
364
- }
365
322
}
366
323
_ => { }
367
324
}
368
325
}
369
326
370
327
// Merge promotable and const_stable_indirect into stability info
371
- if promotable {
372
- match & mut const_stab {
373
- Some ( ( stab, _) ) => stab. promotable = promotable,
374
- _ => {
375
- _ = sess
376
- . dcx ( )
377
- . emit_err ( session_diagnostics:: RustcPromotablePairing { span : item_sp } )
328
+ let ( level, stab_sp) = if let Some ( ( level, stab_sp) ) = level {
329
+ match level {
330
+ StabilityLevel :: Unstable { unstables, .. } => {
331
+ ( ConstStabilityLevel :: Unstable { unstables } , stab_sp)
378
332
}
379
- }
380
- }
381
- if const_stable_indirect. is_some ( ) {
382
- match & mut const_stab {
383
- Some ( ( stab, _) ) => {
384
- if stab. is_const_unstable ( ) {
385
- stab. const_stable_indirect = true ;
386
- } else {
387
- _ = sess. dcx ( ) . emit_err ( session_diagnostics:: RustcConstStableIndirectPairing {
333
+ StabilityLevel :: Stable { since, .. } => {
334
+ if const_stable_indirect. is_some ( ) {
335
+ sess. dcx ( ) . emit_err ( session_diagnostics:: RustcConstStableIndirectPairing {
388
336
span : item_sp,
389
- } )
337
+ } ) ;
390
338
}
339
+ ( ConstStabilityLevel :: Stable { since } , stab_sp)
391
340
}
392
- _ => { }
393
341
}
394
- }
395
- // Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const
396
- // fn` get *some* marker, since we are a staged_api crate and therefore will do recursive const
397
- // stability checks for them. We need to do this because the default for whether an unmarked
398
- // function enforces recursive stability differs between staged-api crates and force-unmarked
399
- // crates: in force-unmarked crates, only functions *explicitly* marked `const_stable_indirect`
400
- // enforce recursive stability. Therefore when `lookup_const_stability` is `None`, we have to
401
- // assume the function does not have recursive stability. All functions that *do* have recursive
402
- // stability must explicitly record this, and so that's what we do for all `const fn` in a
403
- // staged_api crate.
404
- if ( is_const_fn || const_stable_indirect. is_some ( ) ) && const_stab. is_none ( ) {
405
- let c = ConstStability {
406
- level : ConstStabilityLevel :: ImplicitUnstable ,
407
- const_stable_indirect : const_stable_indirect. is_some ( ) ,
408
- promotable : false ,
409
- } ;
410
- const_stab = Some ( ( c, const_stable_indirect. unwrap_or ( DUMMY_SP ) ) ) ;
411
- }
342
+ } else {
343
+ if promotable {
344
+ sess. dcx ( ) . emit_err ( session_diagnostics:: RustcPromotablePairing { span : item_sp } ) ;
345
+ }
346
+ // Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all
347
+ // `const fn` get *some* marker, since we are a staged_api crate and therefore will do
348
+ // recursive const stability checks for them. We need to do this because the default for
349
+ // whether an unmarked function enforces recursive stability differs between staged-api
350
+ // crates and force-unmarked crates: in force-unmarked crates, only functions *explicitly*
351
+ // marked `const_stable_indirect` enforce recursive stability. Therefore when
352
+ // `lookup_const_stability` is `None`, we have to assume the function does not have
353
+ // recursive stability. All functions that *do* have recursive stability must explicitly
354
+ // record this, and so that's what we do for all `const fn` in a staged_api crate.
355
+ if is_const_fn || const_stable_indirect. is_some ( ) {
356
+ ( ConstStabilityLevel :: ImplicitUnstable , const_stable_indirect. unwrap_or ( DUMMY_SP ) )
357
+ } else {
358
+ return None ;
359
+ }
360
+ } ;
412
361
413
- const_stab
362
+ let const_stab = ConstStability {
363
+ level,
364
+ const_stable_indirect : const_stable_indirect. is_some ( ) ,
365
+ promotable,
366
+ } ;
367
+ Some ( ( const_stab, stab_sp) )
414
368
}
415
369
416
370
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
@@ -419,23 +373,54 @@ pub fn find_body_stability(
419
373
sess : & Session ,
420
374
attrs : & [ Attribute ] ,
421
375
) -> Option < ( DefaultBodyStability , Span ) > {
422
- let mut body_stab : Option < ( DefaultBodyStability , Span ) > = None ;
376
+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
423
377
424
378
for attr in attrs {
425
379
if attr. has_name ( sym:: rustc_default_body_unstable) {
426
- if body_stab. is_some ( ) {
427
- sess. dcx ( )
428
- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
380
+ if try_add_unstability ( sess, attr, & mut level) . is_err ( ) {
429
381
break ;
430
382
}
431
-
432
- if let Some ( level) = parse_unstability ( sess, attr) {
433
- body_stab = Some ( ( DefaultBodyStability { level } , attr. span ) ) ;
434
- }
435
383
}
436
384
}
437
385
438
- body_stab
386
+ let ( level, stab_sp) = level?;
387
+ Some ( ( DefaultBodyStability { level } , stab_sp) )
388
+ }
389
+
390
+ /// Collects stability info from one `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
391
+ /// attribute, `attr`. Emits an error if the info it collects is inconsistent.
392
+ fn try_add_unstability (
393
+ sess : & Session ,
394
+ attr : & Attribute ,
395
+ level : & mut Option < ( StabilityLevel , Span ) > ,
396
+ ) -> Result < ( ) , ErrorGuaranteed > {
397
+ if level. is_some ( ) {
398
+ return Err ( sess
399
+ . dcx ( )
400
+ . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ) ;
401
+ }
402
+ if let Some ( new_level) = parse_unstability ( sess, attr) {
403
+ * level = Some ( ( new_level, attr. span ) ) ;
404
+ }
405
+ Ok ( ( ) )
406
+ }
407
+
408
+ /// Collects stability info from a single `stable`/`rustc_const_stable` attribute, `attr`.
409
+ /// Emits an error if the info it collects is inconsistent.
410
+ fn try_add_stability (
411
+ sess : & Session ,
412
+ attr : & Attribute ,
413
+ level : & mut Option < ( StabilityLevel , Span ) > ,
414
+ ) -> Result < ( ) , ErrorGuaranteed > {
415
+ if level. is_some ( ) {
416
+ return Err ( sess
417
+ . dcx ( )
418
+ . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ) ;
419
+ }
420
+ if let Some ( new_level) = parse_stability ( sess, attr) {
421
+ * level = Some ( ( new_level, attr. span ) ) ;
422
+ }
423
+ Ok ( ( ) )
439
424
}
440
425
441
426
fn insert_or_error ( sess : & Session , meta : & MetaItem , item : & mut Option < Symbol > ) -> Option < ( ) > {
0 commit comments