diff options
| -rw-r--r-- | src/librustc_passes/stability.rs | 246 |
1 files changed, 129 insertions, 117 deletions
diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 99f005c29e8..7d93666b1a6 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -58,144 +58,156 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { ) where F: FnOnce(&mut Self), { - if self.tcx.features().staged_api { - // This crate explicitly wants staged API. - debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs); - if let Some(..) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { - self.tcx.sess.span_err( - item_sp, - "`#[deprecated]` cannot be used in staged API; \ - use `#[rustc_deprecated]` instead", - ); - } - let (stab, const_stab) = - attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp); - if let Some(const_stab) = const_stab { - let const_stab = self.tcx.intern_const_stability(const_stab); - self.index.const_stab_map.insert(hir_id, const_stab); + if !self.tcx.features().staged_api { + self.forbid_staged_api_attrs(hir_id, attrs, item_sp, kind, visit_children); + return; + } + + // This crate explicitly wants staged API. + debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs); + if let Some(..) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { + self.tcx.sess.span_err( + item_sp, + "`#[deprecated]` cannot be used in staged API; \ + use `#[rustc_deprecated]` instead", + ); + } + let (stab, const_stab) = + attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp); + if let Some(const_stab) = const_stab { + let const_stab = self.tcx.intern_const_stability(const_stab); + self.index.const_stab_map.insert(hir_id, const_stab); + } + if let Some(mut stab) = stab { + // Error if prohibited, or can't inherit anything from a container. + if kind == AnnotationKind::Prohibited + || (kind == AnnotationKind::Container + && stab.level.is_stable() + && stab.rustc_depr.is_none()) + { + self.tcx.sess.span_err(item_sp, "This stability annotation is useless"); } - if let Some(mut stab) = stab { - // Error if prohibited, or can't inherit anything from a container. - if kind == AnnotationKind::Prohibited - || (kind == AnnotationKind::Container - && stab.level.is_stable() - && stab.rustc_depr.is_none()) - { - self.tcx.sess.span_err(item_sp, "This stability annotation is useless"); - } - debug!("annotate: found {:?}", stab); - // If parent is deprecated and we're not, inherit this by merging - // deprecated_since and its reason. - if let Some(parent_stab) = self.parent_stab { - if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() { - stab.rustc_depr = parent_stab.rustc_depr - } + debug!("annotate: found {:?}", stab); + // If parent is deprecated and we're not, inherit this by merging + // deprecated_since and its reason. + if let Some(parent_stab) = self.parent_stab { + if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() { + stab.rustc_depr = parent_stab.rustc_depr } + } - let stab = self.tcx.intern_stability(stab); - - // Check if deprecated_since < stable_since. If it is, - // this is *almost surely* an accident. - if let ( - &Some(attr::RustcDeprecation { since: dep_since, .. }), - &attr::Stable { since: stab_since }, - ) = (&stab.rustc_depr, &stab.level) + let stab = self.tcx.intern_stability(stab); + + // Check if deprecated_since < stable_since. If it is, + // this is *almost surely* an accident. + if let ( + &Some(attr::RustcDeprecation { since: dep_since, .. }), + &attr::Stable { since: stab_since }, + ) = (&stab.rustc_depr, &stab.level) + { + // Explicit version of iter::order::lt to handle parse errors properly + for (dep_v, stab_v) in + dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) { - // Explicit version of iter::order::lt to handle parse errors properly - for (dep_v, stab_v) in - dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) - { - if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::<u64>(), stab_v.parse()) { - match dep_v.cmp(&stab_v) { - Ordering::Less => { - self.tcx.sess.span_err( - item_sp, - "An API can't be stabilized \ - after it is deprecated", - ); - break; - } - Ordering::Equal => continue, - Ordering::Greater => break, + if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::<u64>(), stab_v.parse()) { + match dep_v.cmp(&stab_v) { + Ordering::Less => { + self.tcx.sess.span_err( + item_sp, + "An API can't be stabilized \ + after it is deprecated", + ); + break; } - } else { - // Act like it isn't less because the question is now nonsensical, - // and this makes us not do anything else interesting. - self.tcx.sess.span_err( - item_sp, - "Invalid stability or deprecation \ - version found", - ); - break; + Ordering::Equal => continue, + Ordering::Greater => break, } + } else { + // Act like it isn't less because the question is now nonsensical, + // and this makes us not do anything else interesting. + self.tcx.sess.span_err( + item_sp, + "Invalid stability or deprecation \ + version found", + ); + break; } } + } - self.index.stab_map.insert(hir_id, stab); + self.index.stab_map.insert(hir_id, stab); - let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); - visit_children(self); - self.parent_stab = orig_parent_stab; - } else { - debug!("annotate: not found, parent = {:?}", self.parent_stab); - if let Some(stab) = self.parent_stab { - if stab.level.is_unstable() { - self.index.stab_map.insert(hir_id, stab); - } - } - visit_children(self); - } + let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); + visit_children(self); + self.parent_stab = orig_parent_stab; } else { - // Emit errors for non-staged-api crates. - let unstable_attrs = [ - sym::unstable, - sym::stable, - sym::rustc_deprecated, - sym::rustc_const_unstable, - sym::rustc_const_stable, - ]; - for attr in attrs { - let name = attr.name_or_empty(); - if unstable_attrs.contains(&name) { - attr::mark_used(attr); - struct_span_err!( - self.tcx.sess, - attr.span, - E0734, - "stability attributes may not be used outside of the standard library", - ) - .emit(); - } - } - - // Propagate unstability. This can happen even for non-staged-api crates in case - // -Zforce-unstable-if-unmarked is set. + debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } } + visit_children(self); + } + } - if let Some(depr) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { - if kind == AnnotationKind::Prohibited { - self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless"); - } + fn forbid_staged_api_attrs( + &mut self, + hir_id: HirId, + attrs: &[Attribute], + item_sp: Span, + kind: AnnotationKind, + visit_children: impl FnOnce(&mut Self), + ) { + // Emit errors for non-staged-api crates. + let unstable_attrs = [ + sym::unstable, + sym::stable, + sym::rustc_deprecated, + sym::rustc_const_unstable, + sym::rustc_const_stable, + ]; + for attr in attrs { + let name = attr.name_or_empty(); + if unstable_attrs.contains(&name) { + attr::mark_used(attr); + struct_span_err!( + self.tcx.sess, + attr.span, + E0734, + "stability attributes may not be used outside of the standard library", + ) + .emit(); + } + } - // `Deprecation` is just two pointers, no need to intern it - let depr_entry = DeprecationEntry::local(depr, hir_id); - self.index.depr_map.insert(hir_id, depr_entry.clone()); - - let orig_parent_depr = replace(&mut self.parent_depr, Some(depr_entry)); - visit_children(self); - self.parent_depr = orig_parent_depr; - } else if let Some(parent_depr) = self.parent_depr.clone() { - self.index.depr_map.insert(hir_id, parent_depr); - visit_children(self); - } else { - visit_children(self); + // Propagate unstability. This can happen even for non-staged-api crates in case + // -Zforce-unstable-if-unmarked is set. + if let Some(stab) = self.parent_stab { + if stab.level.is_unstable() { + self.index.stab_map.insert(hir_id, stab); } } + + if let Some(depr) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { + if kind == AnnotationKind::Prohibited { + self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless"); + } + + // `Deprecation` is just two pointers, no need to intern it + let depr_entry = DeprecationEntry::local(depr, hir_id); + self.index.depr_map.insert(hir_id, depr_entry.clone()); + + let orig_parent_depr = replace(&mut self.parent_depr, Some(depr_entry)); + visit_children(self); + self.parent_depr = orig_parent_depr; + } else if let Some(parent_depr) = self.parent_depr.clone() { + self.index.depr_map.insert(hir_id, parent_depr); + visit_children(self); + } else { + visit_children(self); + } } } |
