@@ -225,54 +225,40 @@ pub fn find_stability(
225225 attrs : & [ Attribute ] ,
226226 item_sp : Span ,
227227) -> Option < ( Stability , Span ) > {
228- let mut stab : Option < ( Stability , Span ) > = None ;
228+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
229229 let mut allowed_through_unstable_modules = false ;
230230
231231 for attr in attrs {
232232 match attr. name_or_empty ( ) {
233233 sym:: rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true ,
234234 sym:: unstable => {
235- if stab. is_some ( ) {
236- sess. dcx ( )
237- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
235+ if try_add_unstability ( sess, attr, & mut level) . is_err ( ) {
238236 break ;
239237 }
240-
241- if let Some ( level) = parse_unstability ( sess, attr) {
242- stab = Some ( ( Stability { level } , attr. span ) ) ;
243- }
244238 }
245239 sym:: stable => {
246- if stab. is_some ( ) {
247- sess. dcx ( )
248- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
240+ if try_add_stability ( sess, attr, & mut level) . is_err ( ) {
249241 break ;
250242 }
251- if let Some ( level) = parse_stability ( sess, attr) {
252- stab = Some ( ( Stability { level } , attr. span ) ) ;
253- }
254243 }
255244 _ => { }
256245 }
257246 }
258247
259248 if allowed_through_unstable_modules {
260- match & mut stab {
261- Some ( (
262- Stability {
263- level : StabilityLevel :: Stable { allowed_through_unstable_modules, .. } ,
264- ..
265- } ,
266- _,
267- ) ) => * allowed_through_unstable_modules = true ,
249+ match & mut level {
250+ Some ( ( StabilityLevel :: Stable { allowed_through_unstable_modules, .. } , _) ) => {
251+ * allowed_through_unstable_modules = true
252+ }
268253 _ => {
269254 sess. dcx ( )
270255 . emit_err ( session_diagnostics:: RustcAllowedUnstablePairing { span : item_sp } ) ;
271256 }
272257 }
273258 }
274259
275- stab
260+ let ( level, stab_sp) = level?;
261+ Some ( ( Stability { level } , stab_sp) )
276262}
277263
278264/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
@@ -282,7 +268,7 @@ pub fn find_const_stability(
282268 attrs : & [ Attribute ] ,
283269 item_sp : Span ,
284270) -> Option < ( ConstStability , Span ) > {
285- let mut const_stab : Option < ( ConstStability , Span ) > = None ;
271+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
286272 let mut promotable = false ;
287273 let mut const_stable_indirect = false ;
288274
@@ -291,67 +277,38 @@ pub fn find_const_stability(
291277 sym:: rustc_promotable => promotable = true ,
292278 sym:: rustc_const_stable_indirect => const_stable_indirect = true ,
293279 sym:: rustc_const_unstable => {
294- if const_stab. is_some ( ) {
295- sess. dcx ( )
296- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
280+ if try_add_unstability ( sess, attr, & mut level) . is_err ( ) {
297281 break ;
298282 }
299-
300- if let Some ( level) = parse_unstability ( sess, attr) {
301- const_stab = Some ( (
302- ConstStability { level, const_stable_indirect : false , promotable : false } ,
303- attr. span ,
304- ) ) ;
305- }
306283 }
307284 sym:: rustc_const_stable => {
308- if const_stab. is_some ( ) {
309- sess. dcx ( )
310- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
285+ if try_add_stability ( sess, attr, & mut level) . is_err ( ) {
311286 break ;
312287 }
313- if let Some ( level) = parse_stability ( sess, attr) {
314- const_stab = Some ( (
315- ConstStability { level, const_stable_indirect : false , promotable : false } ,
316- attr. span ,
317- ) ) ;
318- }
319288 }
320289 _ => { }
321290 }
322291 }
323292
324293 // Merge promotable and const_stable_indirect into stability info
325- if promotable {
326- match & mut const_stab {
327- Some ( ( stab, _) ) => stab. promotable = promotable,
328- _ => {
329- _ = sess
330- . dcx ( )
331- . emit_err ( session_diagnostics:: RustcPromotablePairing { span : item_sp } )
332- }
294+ if let Some ( ( level, stab_sp) ) = level {
295+ if level. is_stable ( ) && const_stable_indirect {
296+ sess. dcx ( )
297+ . emit_err ( session_diagnostics:: RustcConstStableIndirectPairing { span : item_sp } ) ;
298+ const_stable_indirect = false ;
333299 }
334- }
335- if const_stable_indirect {
336- match & mut const_stab {
337- Some ( ( stab, _) ) => {
338- if stab. is_const_unstable ( ) {
339- stab. const_stable_indirect = true ;
340- } else {
341- _ = sess. dcx ( ) . emit_err ( session_diagnostics:: RustcConstStableIndirectPairing {
342- span : item_sp,
343- } )
344- }
345- }
346- _ => {
347- // This function has no const stability attribute, but has `const_stable_indirect`.
348- // We ignore that; unmarked functions are subject to recursive const stability
349- // checks by default so we do carry out the user's intent.
350- }
300+ let const_stab = ConstStability { level, const_stable_indirect, promotable } ;
301+
302+ Some ( ( const_stab, stab_sp) )
303+ } else {
304+ if promotable {
305+ sess. dcx ( ) . emit_err ( session_diagnostics:: RustcPromotablePairing { span : item_sp } ) ;
351306 }
307+ // This function has no const stability attribute, but may have `const_stable_indirect`.
308+ // We ignore that; unmarked functions are subject to recursive const stability
309+ // checks by default so we do carry out the user's intent.
310+ None
352311 }
353-
354- const_stab
355312}
356313
357314/// Calculates the const stability for a const function in a `-Zforce-unstable-if-unmarked` crate
@@ -375,23 +332,54 @@ pub fn find_body_stability(
375332 sess : & Session ,
376333 attrs : & [ Attribute ] ,
377334) -> Option < ( DefaultBodyStability , Span ) > {
378- let mut body_stab : Option < ( DefaultBodyStability , Span ) > = None ;
335+ let mut level : Option < ( StabilityLevel , Span ) > = None ;
379336
380337 for attr in attrs {
381338 if attr. has_name ( sym:: rustc_default_body_unstable) {
382- if body_stab. is_some ( ) {
383- sess. dcx ( )
384- . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ;
339+ if try_add_unstability ( sess, attr, & mut level) . is_err ( ) {
385340 break ;
386341 }
387-
388- if let Some ( level) = parse_unstability ( sess, attr) {
389- body_stab = Some ( ( DefaultBodyStability { level } , attr. span ) ) ;
390- }
391342 }
392343 }
393344
394- body_stab
345+ let ( level, stab_sp) = level?;
346+ Some ( ( DefaultBodyStability { level } , stab_sp) )
347+ }
348+
349+ /// Collects stability info from one `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
350+ /// attribute, `attr`. Emits an error if the info it collects is inconsistent.
351+ fn try_add_unstability (
352+ sess : & Session ,
353+ attr : & Attribute ,
354+ level : & mut Option < ( StabilityLevel , Span ) > ,
355+ ) -> Result < ( ) , ErrorGuaranteed > {
356+ if level. is_some ( ) {
357+ return Err ( sess
358+ . dcx ( )
359+ . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ) ;
360+ }
361+ if let Some ( new_level) = parse_unstability ( sess, attr) {
362+ * level = Some ( ( new_level, attr. span ) ) ;
363+ }
364+ Ok ( ( ) )
365+ }
366+
367+ /// Collects stability info from a single `stable`/`rustc_const_stable` attribute, `attr`.
368+ /// Emits an error if the info it collects is inconsistent.
369+ fn try_add_stability (
370+ sess : & Session ,
371+ attr : & Attribute ,
372+ level : & mut Option < ( StabilityLevel , Span ) > ,
373+ ) -> Result < ( ) , ErrorGuaranteed > {
374+ if level. is_some ( ) {
375+ return Err ( sess
376+ . dcx ( )
377+ . emit_err ( session_diagnostics:: MultipleStabilityLevels { span : attr. span } ) ) ;
378+ }
379+ if let Some ( new_level) = parse_stability ( sess, attr) {
380+ * level = Some ( ( new_level, attr. span ) ) ;
381+ }
382+ Ok ( ( ) )
395383}
396384
397385fn insert_or_error ( sess : & Session , meta : & MetaItem , item : & mut Option < Symbol > ) -> Option < ( ) > {
0 commit comments