Skip to content

Commit 83f81a0

Browse files
committed
factor out some commonalities in the find_stability family of functions
the logic for adding unstable attrs gets a bit messier when supporting multiple instances thereof. this keeps that from being duplicated in 3 places.
1 parent d4c79c8 commit 83f81a0

File tree

1 file changed

+67
-79
lines changed

1 file changed

+67
-79
lines changed

compiler/rustc_attr/src/builtin.rs

Lines changed: 67 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -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

397385
fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -> Option<()> {

0 commit comments

Comments
 (0)