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