@@ -242,54 +242,40 @@ pub fn find_stability(
242242 attrs : & [ Attribute ] ,
243243 item_sp : Span ,
244244) -> Option < ( Stability , Span ) > {
245- let mut stab : Option < ( Stability , Span ) > = None ;
245+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
246246 let mut allowed_through_unstable_modules = false ;
247247
248248 for attr in attrs {
249249 match attr. name_or_empty ( ) {
250250 sym:: rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true ,
251251 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 ( ) {
255253 break ;
256254 }
257-
258- if let Some ( level) = parse_unstability ( sess, attr) {
259- stab = Some ( ( Stability { level } , attr. span ) ) ;
260- }
261255 }
262256 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 ( ) {
266258 break ;
267259 }
268- if let Some ( level) = parse_stability ( sess, attr) {
269- stab = Some ( ( Stability { level } , attr. span ) ) ;
270- }
271260 }
272261 _ => { }
273262 }
274263 }
275264
276265 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+ }
285270 _ => {
286271 sess. dcx ( )
287272 . emit_err ( session_diagnostics:: RustcAllowedUnstablePairing { span : item_sp } ) ;
288273 }
289274 }
290275 }
291276
292- stab
277+ let ( level, stab_sp) = level?;
278+ Some ( ( Stability { level } , stab_sp) )
293279}
294280
295281/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
@@ -303,104 +289,69 @@ pub fn find_const_stability(
303289 item_sp : Span ,
304290 is_const_fn : bool ,
305291) -> Option < ( ConstStability , Span ) > {
306- let mut const_stab : Option < ( ConstStability , Span ) > = None ;
292+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
307293 let mut promotable = false ;
308294 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- } ;
313295
314296 for attr in attrs {
315297 match attr. name_or_empty ( ) {
316298 sym:: rustc_promotable => promotable = true ,
317299 sym:: rustc_const_stable_indirect => const_stable_indirect = Some ( attr. span ) ,
318300 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 ( ) {
322302 break ;
323303 }
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- }
335304 }
336305 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 ( ) {
340307 break ;
341308 }
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- }
352309 }
353310 _ => { }
354311 }
355312 }
356313
357314 // 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)
365319 }
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 {
375323 span : item_sp,
376- } )
324+ } ) ;
377325 }
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)
382327 }
383328 }
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+ } ;
402348
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) )
404355}
405356
406357/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
@@ -409,23 +360,54 @@ pub fn find_body_stability(
409360 sess : & Session ,
410361 attrs : & [ Attribute ] ,
411362) -> Option < ( DefaultBodyStability , Span ) > {
412- let mut body_stab : Option < ( DefaultBodyStability , Span ) > = None ;
363+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
413364
414365 for attr in attrs {
415366 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 ( ) {
419368 break ;
420369 }
421-
422- if let Some ( level) = parse_unstability ( sess, attr) {
423- body_stab = Some ( ( DefaultBodyStability { level } , attr. span ) ) ;
424- }
425370 }
426371 }
427372
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 ( ( ) )
429411}
430412
431413fn insert_or_error ( sess : & Session , meta : & MetaItem , item : & mut Option < Symbol > ) -> Option < ( ) > {
0 commit comments