use super::removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
-use crate::ast::{
- self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind,
- PatKind, RangeEnd, VariantData,
-};
-use crate::attr::{self, check_builtin_attribute};
+use crate::ast::{self, AssocTyConstraint, AssocTyConstraintKind, NodeId};
+use crate::ast::{GenericParam, GenericParamKind, PatKind, RangeEnd, VariantData};
+use crate::attr;
use crate::source_map::Spanned;
use crate::edition::{ALL_EDITIONS, Edition};
use crate::visit::{self, FnKind, Visitor};
-use crate::token;
use crate::sess::ParseSess;
use crate::symbol::{Symbol, sym};
-use crate::tokenstream::TokenTree;
use errors::{Applicability, DiagnosticBuilder, Handler};
use rustc_data_structures::fx::FxHashMap;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use log::debug;
+use rustc_error_codes::*;
+
+
use std::env;
+use std::num::NonZeroU32;
#[derive(Copy, Clone, Debug)]
pub enum Stability {
PostExpansionVisitor { parse_sess, features }.visit_attribute(attr)
}
-fn find_lang_feature_issue(feature: Symbol) -> Option<u32> {
+fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
// FIXME (#28244): enforce that active features have issue numbers
- // assert!(info.issue.is_some())
- info.issue
+ // assert!(info.issue().is_some())
+ info.issue()
} else {
// search in Accepted, Removed, or Stable Removed features
- let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
+ let found = ACCEPTED_FEATURES
+ .iter()
+ .chain(REMOVED_FEATURES)
+ .chain(STABLE_REMOVED_FEATURES)
.find(|t| t.name == feature);
match found {
- Some(&Feature { issue, .. }) => issue,
- None => panic!("Feature `{}` is not declared anywhere", feature),
+ Some(found) => found.issue(),
+ None => panic!("feature `{}` is not declared anywhere", feature),
}
}
}
pub enum GateIssue {
Language,
- Library(Option<u32>)
+ Library(Option<NonZeroU32>)
}
#[derive(Debug, Copy, Clone, PartialEq)]
GateStrength::Soft => diag.struct_span_warn(span, explain),
};
- match issue {
- None | Some(0) => {} // We still accept `0` as a stand-in for backwards compatibility
- Some(n) => {
- err.note(&format!(
- "for more information, see https://github.com/rust-lang/rust/issues/{}",
- n,
- ));
- }
+ if let Some(n) = issue {
+ err.note(&format!(
+ "for more information, see https://github.com/rust-lang/rust/issues/{}",
+ n,
+ ));
}
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
}
}
+ fn check_extern(&self, ext: ast::Extern) {
+ if let ast::Extern::Explicit(abi) = ext {
+ self.check_abi(abi);
+ }
+ }
+
fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
let has_fields = variants.iter().any(|variant| match variant.data {
VariantData::Tuple(..) | VariantData::Struct(..) => true,
);
}
}
+
+ /// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
+ fn check_impl_trait(&self, ty: &ast::Ty) {
+ struct ImplTraitVisitor<'a> {
+ vis: &'a PostExpansionVisitor<'a>,
+ }
+ impl Visitor<'_> for ImplTraitVisitor<'_> {
+ fn visit_ty(&mut self, ty: &ast::Ty) {
+ if let ast::TyKind::ImplTrait(..) = ty.kind {
+ gate_feature_post!(
+ &self.vis,
+ type_alias_impl_trait,
+ ty.span,
+ "`impl Trait` in type aliases is unstable"
+ );
+ }
+ visit::walk_ty(self, ty);
+ }
+ }
+ ImplTraitVisitor { vis: self }.visit_ty(ty);
+ }
}
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if let Some((.., AttributeGate::Gated(_, name, descr, has_feature))) = attr_info {
gate_feature_fn!(self, has_feature, attr.span, name, descr, GateStrength::Hard);
}
- // Check input tokens for built-in and key-value attributes.
- match attr_info {
- // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
- Some((name, _, template, _)) if name != sym::rustc_dummy =>
- check_builtin_attribute(self.parse_sess, attr, name, template),
- _ => if let Some(TokenTree::Token(token)) =
- attr.get_normal_item().tokens.trees().next() {
- if token == token::Eq {
- // All key-value attributes are restricted to meta-item syntax.
- attr.parse_meta(self.parse_sess).map_err(|mut err| err.emit()).ok();
- }
- }
- }
// Check unstable flavors of the `#[doc]` attribute.
if attr.check_name(sym::doc) {
for nested_meta in attr.meta_item_list().unwrap_or_default() {
fn visit_item(&mut self, i: &'a ast::Item) {
match i.kind {
ast::ItemKind::ForeignMod(ref foreign_module) => {
- self.check_abi(foreign_module.abi);
+ if let Some(abi) = foreign_module.abi {
+ self.check_abi(abi);
+ }
}
ast::ItemKind::Fn(..) => {
gate_feature_post!(&self, decl_macro, i.span, msg);
}
- ast::ItemKind::OpaqueTy(..) => {
- gate_feature_post!(
- &self,
- type_alias_impl_trait,
- i.span,
- "`impl Trait` in type aliases is unstable"
- );
- }
+ ast::ItemKind::TyAlias(ref ty, ..) => self.check_impl_trait(&ty),
_ => {}
}
fn visit_ty(&mut self, ty: &'a ast::Ty) {
match ty.kind {
ast::TyKind::BareFn(ref bare_fn_ty) => {
- self.check_abi(bare_fn_ty.abi);
+ self.check_extern(bare_fn_ty.ext);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span,
// Stability of const fn methods are covered in
// `visit_trait_item` and `visit_impl_item` below; this is
// because default methods don't pass through this point.
- self.check_abi(header.abi);
+ self.check_extern(header.ext);
}
if fn_decl.c_variadic() {
match ti.kind {
ast::TraitItemKind::Method(ref sig, ref block) => {
if block.is_none() {
- self.check_abi(sig.header.abi);
+ self.check_extern(sig.header.ext);
}
if sig.decl.c_variadic() {
gate_feature_post!(&self, c_variadic, ti.span,
}
}
ast::TraitItemKind::Type(_, ref default) => {
- // We use three if statements instead of something like match guards so that all
- // of these errors can be emitted if all cases apply.
- if default.is_some() {
+ if let Some(ty) = default {
+ self.check_impl_trait(ty);
gate_feature_post!(&self, associated_type_defaults, ti.span,
"associated type defaults are unstable");
}
"C-variadic functions are unstable");
}
}
- ast::ImplItemKind::OpaqueTy(..) => {
- gate_feature_post!(
- &self,
- type_alias_impl_trait,
- ii.span,
- "`impl Trait` in type aliases is unstable"
- );
- }
- ast::ImplItemKind::TyAlias(_) => {
+ ast::ImplItemKind::TyAlias(ref ty) => {
+ self.check_impl_trait(ty);
self.check_gat(&ii.generics, ii.span);
}
_ => {}