Skip to content

Commit ff53d6c

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 3c6fe0a commit ff53d6c

File tree

1 file changed

+58
-56
lines changed

1 file changed

+58
-56
lines changed

compiler/rustc_attr/src/builtin.rs

Lines changed: 58 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -214,54 +214,40 @@ pub fn find_stability(
214214
attrs: &[Attribute],
215215
item_sp: Span,
216216
) -> Option<(Stability, Span)> {
217-
let mut stab: Option<(Stability, Span)> = None;
217+
let mut level: Option<(StabilityLevel, Span)> = None;
218218
let mut allowed_through_unstable_modules = false;
219219

220220
for attr in attrs {
221221
match attr.name_or_empty() {
222222
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
223223
sym::unstable => {
224-
if stab.is_some() {
225-
sess.dcx()
226-
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
224+
if try_add_unstability(sess, attr, &mut level).is_err() {
227225
break;
228226
}
229-
230-
if let Some(level) = parse_unstability(sess, attr) {
231-
stab = Some((Stability { level }, attr.span));
232-
}
233227
}
234228
sym::stable => {
235-
if stab.is_some() {
236-
sess.dcx()
237-
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
229+
if try_add_stability(sess, attr, &mut level).is_err() {
238230
break;
239231
}
240-
if let Some(level) = parse_stability(sess, attr) {
241-
stab = Some((Stability { level }, attr.span));
242-
}
243232
}
244233
_ => {}
245234
}
246235
}
247236

248237
if allowed_through_unstable_modules {
249-
match &mut stab {
250-
Some((
251-
Stability {
252-
level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
253-
..
254-
},
255-
_,
256-
)) => *allowed_through_unstable_modules = true,
238+
match &mut level {
239+
Some((StabilityLevel::Stable { allowed_through_unstable_modules, .. }, _)) => {
240+
*allowed_through_unstable_modules = true
241+
}
257242
_ => {
258243
sess.dcx()
259244
.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
260245
}
261246
}
262247
}
263248

264-
stab
249+
let (level, stab_sp) = level?;
250+
Some((Stability { level }, stab_sp))
265251
}
266252

267253
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
@@ -271,50 +257,35 @@ pub fn find_const_stability(
271257
attrs: &[Attribute],
272258
item_sp: Span,
273259
) -> Option<(ConstStability, Span)> {
274-
let mut const_stab: Option<(ConstStability, Span)> = None;
260+
let mut level: Option<(StabilityLevel, Span)> = None;
275261
let mut promotable = false;
276262

277263
for attr in attrs {
278264
match attr.name_or_empty() {
279265
sym::rustc_promotable => promotable = true,
280266
sym::rustc_const_unstable => {
281-
if const_stab.is_some() {
282-
sess.dcx()
283-
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
267+
if try_add_unstability(sess, attr, &mut level).is_err() {
284268
break;
285269
}
286-
287-
if let Some(level) = parse_unstability(sess, attr) {
288-
const_stab = Some((ConstStability { level, promotable: false }, attr.span));
289-
}
290270
}
291271
sym::rustc_const_stable => {
292-
if const_stab.is_some() {
293-
sess.dcx()
294-
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
272+
if try_add_stability(sess, attr, &mut level).is_err() {
295273
break;
296274
}
297-
if let Some(level) = parse_stability(sess, attr) {
298-
const_stab = Some((ConstStability { level, promotable: false }, attr.span));
299-
}
300275
}
301276
_ => {}
302277
}
303278
}
304279

305280
// Merge the const-unstable info into the stability info
306-
if promotable {
307-
match &mut const_stab {
308-
Some((stab, _)) => stab.promotable = promotable,
309-
_ => {
310-
_ = sess
311-
.dcx()
312-
.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp })
313-
}
281+
if let Some((level, stab_sp)) = level {
282+
Some((ConstStability { level, promotable }, stab_sp))
283+
} else {
284+
if promotable {
285+
sess.dcx().emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp });
314286
}
287+
None
315288
}
316-
317-
const_stab
318289
}
319290

320291
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
@@ -323,23 +294,54 @@ pub fn find_body_stability(
323294
sess: &Session,
324295
attrs: &[Attribute],
325296
) -> Option<(DefaultBodyStability, Span)> {
326-
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
297+
let mut level: Option<(StabilityLevel, Span)> = None;
327298

328299
for attr in attrs {
329300
if attr.has_name(sym::rustc_default_body_unstable) {
330-
if body_stab.is_some() {
331-
sess.dcx()
332-
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
301+
if try_add_unstability(sess, attr, &mut level).is_err() {
333302
break;
334303
}
335-
336-
if let Some(level) = parse_unstability(sess, attr) {
337-
body_stab = Some((DefaultBodyStability { level }, attr.span));
338-
}
339304
}
340305
}
341306

342-
body_stab
307+
let (level, stab_sp) = level?;
308+
Some((DefaultBodyStability { level }, stab_sp))
309+
}
310+
311+
/// Collects stability info from one `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
312+
/// attribute, `attr`. Emits an error if the info it collects is inconsistent.
313+
fn try_add_unstability(
314+
sess: &Session,
315+
attr: &Attribute,
316+
level: &mut Option<(StabilityLevel, Span)>,
317+
) -> Result<(), ErrorGuaranteed> {
318+
if level.is_some() {
319+
return Err(sess
320+
.dcx()
321+
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span }));
322+
}
323+
if let Some(new_level) = parse_unstability(sess, attr) {
324+
*level = Some((new_level, attr.span));
325+
}
326+
Ok(())
327+
}
328+
329+
/// Collects stability info from a single `stable`/`rustc_const_stable` attribute, `attr`.
330+
/// Emits an error if the info it collects is inconsistent.
331+
fn try_add_stability(
332+
sess: &Session,
333+
attr: &Attribute,
334+
level: &mut Option<(StabilityLevel, Span)>,
335+
) -> Result<(), ErrorGuaranteed> {
336+
if level.is_some() {
337+
return Err(sess
338+
.dcx()
339+
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span }));
340+
}
341+
if let Some(new_level) = parse_stability(sess, attr) {
342+
*level = Some((new_level, attr.span));
343+
}
344+
Ok(())
343345
}
344346

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

0 commit comments

Comments
 (0)