diff options
| -rw-r--r-- | compiler/rustc_attr/src/builtin.rs | 206 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/base.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/stability.rs | 8 |
3 files changed, 101 insertions, 117 deletions
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 08d75d85779..ccc5eedfe26 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -232,118 +232,89 @@ pub fn find_stability( sess: &Session, attrs: &[Attribute], item_sp: Span, -) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>) -{ - find_stability_generic(sess, attrs.iter(), item_sp) +) -> Option<(Stability, Span)> { + let mut stab: Option<(Stability, Span)> = None; + let mut allowed_through_unstable_modules = false; + + for attr in attrs { + match attr.name_or_empty() { + sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true, + sym::unstable => { + if stab.is_some() { + handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels); + break; + } + + if let Some((feature, level)) = parse_unstability(sess, attr) { + stab = Some((Stability { level, feature }, attr.span)); + } + } + sym::stable => { + if stab.is_some() { + handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels); + break; + } + if let Some((feature, level)) = parse_stability(sess, attr) { + stab = Some((Stability { level, feature }, attr.span)); + } + } + _ => {} + } + } + + if allowed_through_unstable_modules { + match &mut stab { + Some(( + Stability { + level: StabilityLevel::Stable { allowed_through_unstable_modules, .. }, + .. + }, + _, + )) => *allowed_through_unstable_modules = true, + _ => { + sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp }); + } + } + } + + stab } -fn find_stability_generic<'a, I>( +/// Collects stability info from all stability attributes in `attrs`. +/// Returns `None` if no stability attributes are found. +pub fn find_const_stability( sess: &Session, - attrs_iter: I, + attrs: &[Attribute], item_sp: Span, -) -> (Option<(Stability, Span)>, Option<(ConstStability, Span)>, Option<(DefaultBodyStability, Span)>) -where - I: Iterator<Item = &'a Attribute>, -{ - let mut stab: Option<(Stability, Span)> = None; +) -> Option<(ConstStability, Span)> { let mut const_stab: Option<(ConstStability, Span)> = None; - let mut body_stab: Option<(DefaultBodyStability, Span)> = None; let mut promotable = false; - let mut allowed_through_unstable_modules = false; - - for attr in attrs_iter { - if ![ - sym::rustc_const_unstable, - sym::rustc_const_stable, - sym::unstable, - sym::stable, - sym::rustc_promotable, - sym::rustc_allowed_through_unstable_modules, - sym::rustc_default_body_unstable, - ] - .iter() - .any(|&s| attr.has_name(s)) - { - continue; // not a stability level - } - let meta = attr.meta(); - - if attr.has_name(sym::rustc_promotable) { - promotable = true; - } else if attr.has_name(sym::rustc_allowed_through_unstable_modules) { - allowed_through_unstable_modules = true; - } else if let Some(meta) = &meta { - let meta_name = meta.name_or_empty(); - match meta_name { - sym::rustc_const_unstable | sym::rustc_default_body_unstable | sym::unstable => { - if meta_name == sym::unstable && stab.is_some() { - handle_errors( - &sess.parse_sess, - attr.span, - AttrError::MultipleStabilityLevels, - ); - break; - } else if meta_name == sym::rustc_const_unstable && const_stab.is_some() { - handle_errors( - &sess.parse_sess, - attr.span, - AttrError::MultipleStabilityLevels, - ); - break; - } else if meta_name == sym::rustc_default_body_unstable && body_stab.is_some() { - handle_errors( - &sess.parse_sess, - attr.span, - AttrError::MultipleStabilityLevels, - ); - break; - } + for attr in attrs { + match attr.name_or_empty() { + sym::rustc_promotable => promotable = true, + sym::rustc_const_unstable => { + if const_stab.is_some() { + handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels); + break; + } - if let Some((feature, level)) = parse_unstability(sess, attr) { - if sym::unstable == meta_name { - stab = Some((Stability { level, feature }, attr.span)); - } else if sym::rustc_const_unstable == meta_name { - const_stab = Some(( - ConstStability { level, feature, promotable: false }, - attr.span, - )); - } else if sym::rustc_default_body_unstable == meta_name { - body_stab = Some((DefaultBodyStability { level, feature }, attr.span)); - } else { - unreachable!("Unknown stability attribute {meta_name}"); - } - } + if let Some((feature, level)) = parse_unstability(sess, attr) { + const_stab = + Some((ConstStability { level, feature, promotable: false }, attr.span)); } - sym::rustc_const_stable | sym::stable => { - if meta_name == sym::stable && stab.is_some() { - handle_errors( - &sess.parse_sess, - attr.span, - AttrError::MultipleStabilityLevels, - ); - break; - } else if meta_name == sym::rustc_const_stable && const_stab.is_some() { - handle_errors( - &sess.parse_sess, - attr.span, - AttrError::MultipleStabilityLevels, - ); - break; - } - if let Some((feature, level)) = parse_stability(sess, attr) { - if sym::stable == meta_name { - stab = Some((Stability { level, feature }, attr.span)); - } else { - const_stab = Some(( - ConstStability { level, feature, promotable: false }, - attr.span, - )); - } - } + } + sym::rustc_const_stable => { + if const_stab.is_some() { + handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels); + break; + } + if let Some((feature, level)) = parse_stability(sess, attr) { + const_stab = + Some((ConstStability { level, feature, promotable: false }, attr.span)); } - _ => unreachable!(), } + _ => {} } } @@ -355,22 +326,31 @@ where } } - if allowed_through_unstable_modules { - match &mut stab { - Some(( - Stability { - level: StabilityLevel::Stable { allowed_through_unstable_modules, .. }, - .. - }, - _, - )) => *allowed_through_unstable_modules = true, - _ => { - sess.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp }); + const_stab +} + +/// Collects stability info from all stability attributes in `attrs`. +/// Returns `None` if no stability attributes are found. +pub fn find_body_stability( + sess: &Session, + attrs: &[Attribute], +) -> Option<(DefaultBodyStability, Span)> { + let mut body_stab: Option<(DefaultBodyStability, Span)> = None; + + for attr in attrs { + if attr.has_name(sym::rustc_default_body_unstable) { + if body_stab.is_some() { + handle_errors(&sess.parse_sess, attr.span, AttrError::MultipleStabilityLevels); + break; + } + + if let Some((feature, level)) = parse_unstability(sess, attr) { + body_stab = Some((DefaultBodyStability { level, feature }, attr.span)); } } } - (stab, const_stab, body_stab) + body_stab } fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index d32af10914e..caa2a201c75 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -793,7 +793,9 @@ impl SyntaxExtension { ) }) .unwrap_or_else(|| (None, helper_attrs)); - let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span); + let stability = attr::find_stability(&sess, attrs, span); + let const_stability = attr::find_const_stability(&sess, attrs, span); + let body_stability = attr::find_body_stability(&sess, attrs); if let Some((_, sp)) = const_stability { sess.emit_err(errors::MacroConstStability { span: sp, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 6d0cfea00d1..4a1ba19c920 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -159,7 +159,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { return; } - let (stab, const_stab, body_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp); + let stab = attr::find_stability(&self.tcx.sess, attrs, item_sp); + let const_stab = attr::find_const_stability(&self.tcx.sess, attrs, item_sp); + let body_stab = attr::find_body_stability(&self.tcx.sess, attrs); let mut const_span = None; let const_stab = const_stab.map(|(const_stab, const_span_node)| { @@ -742,8 +744,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { let features = self.tcx.features(); if features.staged_api { let attrs = self.tcx.hir().attrs(item.hir_id()); - let (stab, const_stab, _) = - attr::find_stability(&self.tcx.sess, attrs, item.span); + let stab = attr::find_stability(&self.tcx.sess, attrs, item.span); + let const_stab = attr::find_const_stability(&self.tcx.sess, attrs, item.span); // If this impl block has an #[unstable] attribute, give an // error if all involved types and traits are stable, because |
