@@ -256,54 +256,40 @@ pub fn find_stability(
256256 attrs : & [ Attribute ] ,
257257 item_sp : Span ,
258258) -> Option < ( Stability , Span ) > {
259- let mut stab : Option < ( Stability , Span ) > = None ;
259+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
260260 let mut allowed_through_unstable_modules = false ;
261261
262262 for attr in attrs {
263263 match attr. name_or_empty ( ) {
264264 sym:: rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true ,
265265 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 ( ) {
269267 break ;
270268 }
271-
272- if let Some ( level) = parse_unstability ( sess, attr) {
273- stab = Some ( ( Stability { level } , attr. span ) ) ;
274- }
275269 }
276270 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 ( ) {
280272 break ;
281273 }
282- if let Some ( level) = parse_stability ( sess, attr) {
283- stab = Some ( ( Stability { level } , attr. span ) ) ;
284- }
285274 }
286275 _ => { }
287276 }
288277 }
289278
290279 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+ }
299284 _ => {
300285 sess. dcx ( )
301286 . emit_err ( session_diagnostics:: RustcAllowedUnstablePairing { span : item_sp } ) ;
302287 }
303288 }
304289 }
305290
306- stab
291+ let ( level, stab_sp) = level?;
292+ Some ( ( Stability { level } , stab_sp) )
307293}
308294
309295/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
@@ -316,101 +302,69 @@ pub fn find_const_stability(
316302 item_sp : Span ,
317303 is_const_fn : bool ,
318304) -> Option < ( ConstStability , Span ) > {
319- let mut const_stab : Option < ( ConstStability , Span ) > = None ;
305+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
320306 let mut promotable = false ;
321307 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- } ;
326308
327309 for attr in attrs {
328310 match attr. name_or_empty ( ) {
329311 sym:: rustc_promotable => promotable = true ,
330312 sym:: rustc_const_stable_indirect => const_stable_indirect = Some ( attr. span ) ,
331313 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 ( ) {
335315 break ;
336316 }
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- }
348317 }
349318 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 ( ) {
353320 break ;
354321 }
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- }
365322 }
366323 _ => { }
367324 }
368325 }
369326
370327 // 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)
378332 }
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 {
388336 span : item_sp,
389- } )
337+ } ) ;
390338 }
339+ ( ConstStabilityLevel :: Stable { since } , stab_sp)
391340 }
392- _ => { }
393341 }
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+ } ;
412361
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) )
414368}
415369
416370/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
@@ -419,23 +373,54 @@ pub fn find_body_stability(
419373 sess : & Session ,
420374 attrs : & [ Attribute ] ,
421375) -> Option < ( DefaultBodyStability , Span ) > {
422- let mut body_stab : Option < ( DefaultBodyStability , Span ) > = None ;
376+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
423377
424378 for attr in attrs {
425379 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 ( ) {
429381 break ;
430382 }
431-
432- if let Some ( level) = parse_unstability ( sess, attr) {
433- body_stab = Some ( ( DefaultBodyStability { level } , attr. span ) ) ;
434- }
435383 }
436384 }
437385
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 ( ( ) )
439424}
440425
441426fn insert_or_error ( sess : & Session , meta : & MetaItem , item : & mut Option < Symbol > ) -> Option < ( ) > {
0 commit comments