mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Remove Session.used_attrs
and move logic to CheckAttrVisitor
Instead of updating global state to mark attributes as used, we now explicitly emit a warning when an attribute is used in an unsupported position. As a side effect, we are to emit more detailed warning messages (instead of just a generic "unused" message). `Session.check_name` is removed, since its only purpose was to mark the attribute as used. All of the callers are modified to use `Attribute.has_name` Additionally, `AttributeType::AssumedUsed` is removed - an 'assumed used' attribute is implemented by simply not performing any checks in `CheckAttrVisitor` for a particular attribute. We no longer emit unused attribute warnings for the `#[rustc_dummy]` attribute - it's an internal attribute used for tests, so it doesn't mark sense to treat it as 'unused'. With this commit, a large source of global untracked state is removed.
This commit is contained in:
parent
b6e334d873
commit
af46699f81
@ -4115,10 +4115,12 @@ dependencies = [
|
||||
"rustc_attr",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_lexer",
|
||||
"rustc_middle",
|
||||
"rustc_parse",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
|
@ -2281,7 +2281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
synthetic: param
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|attr| self.sess.check_name(attr, sym::rustc_synthetic))
|
||||
.filter(|attr| attr.has_name(sym::rustc_synthetic))
|
||||
.map(|_| hir::SyntheticTyParamKind::FromAttr)
|
||||
.next(),
|
||||
};
|
||||
|
@ -268,7 +268,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
gate_feature_fn!(self, has_feature, attr.span, name, descr);
|
||||
}
|
||||
// Check unstable flavors of the `#[doc]` attribute.
|
||||
if self.sess.check_name(attr, sym::doc) {
|
||||
if attr.has_name(sym::doc) {
|
||||
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
||||
macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
|
||||
$(if nested_meta.has_name(sym::$name) {
|
||||
@ -287,7 +287,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
|
||||
// Check for unstable modifiers on `#[link(..)]` attribute
|
||||
if self.sess.check_name(attr, sym::link) {
|
||||
if attr.has_name(sym::link) {
|
||||
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
||||
if nested_meta.has_name(sym::modifiers) {
|
||||
gate_feature_post!(
|
||||
@ -709,7 +709,7 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
|
||||
|
||||
if !sess.opts.unstable_features.is_nightly_build() {
|
||||
let lang_features = &sess.features_untracked().declared_lang_features;
|
||||
for attr in krate.attrs.iter().filter(|attr| sess.check_name(attr, sym::feature)) {
|
||||
for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
|
||||
let mut err = struct_span_err!(
|
||||
sess.parse_sess.span_diagnostic,
|
||||
attr.span,
|
||||
|
@ -166,8 +166,6 @@ where
|
||||
continue; // not a stability level
|
||||
}
|
||||
|
||||
sess.mark_attr_used(attr);
|
||||
|
||||
let meta = attr.meta();
|
||||
|
||||
if attr.has_name(sym::rustc_promotable) {
|
||||
@ -636,8 +634,7 @@ where
|
||||
let diagnostic = &sess.parse_sess.span_diagnostic;
|
||||
|
||||
'outer: for attr in attrs_iter {
|
||||
if !(sess.check_name(attr, sym::deprecated) || sess.check_name(attr, sym::rustc_deprecated))
|
||||
{
|
||||
if !(attr.has_name(sym::deprecated) || attr.has_name(sym::rustc_deprecated)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -700,17 +697,17 @@ where
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::note if sess.check_name(attr, sym::deprecated) => {
|
||||
sym::note if attr.has_name(sym::deprecated) => {
|
||||
if !get(mi, &mut note) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::reason if sess.check_name(attr, sym::rustc_deprecated) => {
|
||||
sym::reason if attr.has_name(sym::rustc_deprecated) => {
|
||||
if !get(mi, &mut note) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::suggestion if sess.check_name(attr, sym::rustc_deprecated) => {
|
||||
sym::suggestion if attr.has_name(sym::rustc_deprecated) => {
|
||||
if !get(mi, &mut suggestion) {
|
||||
continue 'outer;
|
||||
}
|
||||
@ -721,7 +718,7 @@ where
|
||||
meta.span(),
|
||||
AttrError::UnknownMetaItem(
|
||||
pprust::path_to_string(&mi.path),
|
||||
if sess.check_name(attr, sym::deprecated) {
|
||||
if attr.has_name(sym::deprecated) {
|
||||
&["since", "note"]
|
||||
} else {
|
||||
&["since", "reason", "suggestion"]
|
||||
@ -747,11 +744,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
if suggestion.is_some() && sess.check_name(attr, sym::deprecated) {
|
||||
if suggestion.is_some() && attr.has_name(sym::deprecated) {
|
||||
unreachable!("only allowed on rustc_deprecated")
|
||||
}
|
||||
|
||||
if sess.check_name(attr, sym::rustc_deprecated) {
|
||||
if attr.has_name(sym::rustc_deprecated) {
|
||||
if since.is_none() {
|
||||
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
|
||||
continue;
|
||||
@ -763,9 +760,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
sess.mark_attr_used(&attr);
|
||||
|
||||
let is_since_rustc_version = sess.check_name(attr, sym::rustc_deprecated);
|
||||
let is_since_rustc_version = attr.has_name(sym::rustc_deprecated);
|
||||
depr = Some((Deprecation { since, note, suggestion, is_since_rustc_version }, attr.span));
|
||||
}
|
||||
|
||||
@ -816,7 +811,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
||||
let diagnostic = &sess.parse_sess.span_diagnostic;
|
||||
if attr.has_name(sym::repr) {
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
sess.mark_attr_used(attr);
|
||||
for item in items {
|
||||
let mut recognised = false;
|
||||
if item.is_word() {
|
||||
@ -1015,14 +1009,13 @@ pub enum TransparencyError {
|
||||
}
|
||||
|
||||
pub fn find_transparency(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
macro_rules: bool,
|
||||
) -> (Transparency, Option<TransparencyError>) {
|
||||
let mut transparency = None;
|
||||
let mut error = None;
|
||||
for attr in attrs {
|
||||
if sess.check_name(attr, sym::rustc_macro_transparency) {
|
||||
if attr.has_name(sym::rustc_macro_transparency) {
|
||||
if let Some((_, old_span)) = transparency {
|
||||
error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span));
|
||||
break;
|
||||
|
@ -677,8 +677,6 @@ impl<'a> TraitDef<'a> {
|
||||
let self_type = cx.ty_path(path);
|
||||
|
||||
let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
|
||||
// Just mark it now since we know that it'll end up used downstream
|
||||
cx.sess.mark_attr_used(&attr);
|
||||
let opt_trait_ref = Some(trait_ref);
|
||||
let unused_qual = {
|
||||
let word = rustc_ast::attr::mk_nested_word_item(Ident::new(
|
||||
|
@ -260,11 +260,11 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.sess.check_name(attr, sym::proc_macro_derive) {
|
||||
if attr.has_name(sym::proc_macro_derive) {
|
||||
self.collect_custom_derive(item, attr);
|
||||
} else if self.sess.check_name(attr, sym::proc_macro_attribute) {
|
||||
} else if attr.has_name(sym::proc_macro_attribute) {
|
||||
self.collect_attr_proc_macro(item);
|
||||
} else if self.sess.check_name(attr, sym::proc_macro) {
|
||||
} else if attr.has_name(sym::proc_macro) {
|
||||
self.collect_bang_proc_macro(item);
|
||||
};
|
||||
|
||||
|
@ -188,8 +188,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
||||
let attrs = attrs
|
||||
.into_iter()
|
||||
.filter(|attr| {
|
||||
!self.sess.check_name(attr, sym::rustc_main)
|
||||
&& !self.sess.check_name(attr, sym::start)
|
||||
!attr.has_name(sym::rustc_main) && !attr.has_name(sym::start)
|
||||
})
|
||||
.chain(iter::once(allow_dead_code))
|
||||
.collect();
|
||||
|
@ -5,7 +5,7 @@ use rustc_ast::token::{DelimToken, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
|
||||
use rustc_ast::tokenstream::{DelimSpan, Spacing};
|
||||
use rustc_ast::tokenstream::{LazyTokenStream, TokenTree};
|
||||
use rustc_ast::{self as ast, AstLike, AttrItem, AttrStyle, Attribute, MetaItem};
|
||||
use rustc_ast::{self as ast, AstLike, AttrStyle, Attribute, MetaItem};
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::map_in_place::MapInPlace;
|
||||
@ -14,7 +14,7 @@ use rustc_feature::{Feature, Features, State as FeatureState};
|
||||
use rustc_feature::{
|
||||
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
|
||||
};
|
||||
use rustc_parse::{parse_in, validate_attr};
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edition::{Edition, ALL_EDITIONS};
|
||||
@ -75,7 +75,7 @@ fn get_features(
|
||||
// Process the edition umbrella feature-gates first, to ensure
|
||||
// `edition_enabled_features` is completed before it's queried.
|
||||
for attr in krate_attrs {
|
||||
if !sess.check_name(attr, sym::feature) {
|
||||
if !attr.has_name(sym::feature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -108,7 +108,7 @@ fn get_features(
|
||||
}
|
||||
|
||||
for attr in krate_attrs {
|
||||
if !sess.check_name(attr, sym::feature) {
|
||||
if !attr.has_name(sym::feature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -237,11 +237,6 @@ macro_rules! configure {
|
||||
};
|
||||
}
|
||||
|
||||
const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
|
||||
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
|
||||
<https://doc.rust-lang.org/reference/conditional-compilation.html\
|
||||
#the-cfg_attr-attribute>";
|
||||
|
||||
impl<'a> StripUnconfigured<'a> {
|
||||
pub fn configure<T: AstLike>(&mut self, mut node: T) -> Option<T> {
|
||||
self.process_cfg_attrs(&mut node);
|
||||
@ -349,7 +344,8 @@ impl<'a> StripUnconfigured<'a> {
|
||||
return vec![attr];
|
||||
}
|
||||
|
||||
let (cfg_predicate, expanded_attrs) = match self.parse_cfg_attr(&attr) {
|
||||
let (cfg_predicate, expanded_attrs) =
|
||||
match rustc_parse::parse_cfg_attr(&attr, &self.sess.parse_sess) {
|
||||
None => return vec![],
|
||||
Some(r) => r,
|
||||
};
|
||||
@ -359,9 +355,6 @@ impl<'a> StripUnconfigured<'a> {
|
||||
return vec![attr];
|
||||
}
|
||||
|
||||
// At this point we know the attribute is considered used.
|
||||
self.sess.mark_attr_used(&attr);
|
||||
|
||||
if !attr::cfg_matches(&cfg_predicate, &self.sess.parse_sess, self.features) {
|
||||
return vec![];
|
||||
}
|
||||
@ -415,46 +408,10 @@ impl<'a> StripUnconfigured<'a> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn parse_cfg_attr(&self, attr: &Attribute) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
|
||||
match attr.get_normal_item().args {
|
||||
ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
|
||||
let msg = "wrong `cfg_attr` delimiters";
|
||||
validate_attr::check_meta_bad_delim(&self.sess.parse_sess, dspan, delim, msg);
|
||||
match parse_in(&self.sess.parse_sess, tts.clone(), "`cfg_attr` input", |p| {
|
||||
p.parse_cfg_attr()
|
||||
}) {
|
||||
Ok(r) => return Some(r),
|
||||
Err(mut e) => {
|
||||
e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
|
||||
.note(CFG_ATTR_NOTE_REF)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => self.error_malformed_cfg_attr_missing(attr.span),
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn error_malformed_cfg_attr_missing(&self, span: Span) {
|
||||
self.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.struct_span_err(span, "malformed `cfg_attr` attribute input")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"missing condition and attribute",
|
||||
CFG_ATTR_GRAMMAR_HELP.to_string(),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.note(CFG_ATTR_NOTE_REF)
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Determines if a node with the given attributes should be included in this configuration.
|
||||
fn in_cfg(&self, attrs: &[Attribute]) -> bool {
|
||||
attrs.iter().all(|attr| {
|
||||
if !is_cfg(self.sess, attr) {
|
||||
if !is_cfg(attr) {
|
||||
return true;
|
||||
}
|
||||
let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) {
|
||||
@ -500,7 +457,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||
//
|
||||
// N.B., this is intentionally not part of the visit_expr() function
|
||||
// in order for filter_map_expr() to be able to avoid this check
|
||||
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(self.sess, a)) {
|
||||
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
|
||||
let msg = "removing an expression is not supported in this position";
|
||||
self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
|
||||
}
|
||||
@ -536,6 +493,6 @@ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a Meta
|
||||
}
|
||||
}
|
||||
|
||||
fn is_cfg(sess: &Session, attr: &Attribute) -> bool {
|
||||
sess.check_name(attr, sym::cfg)
|
||||
fn is_cfg(attr: &Attribute) -> bool {
|
||||
attr.has_name(sym::cfg)
|
||||
}
|
||||
|
@ -753,11 +753,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||
}
|
||||
}
|
||||
}
|
||||
SyntaxExtensionKind::NonMacroAttr { mark_used } => {
|
||||
SyntaxExtensionKind::NonMacroAttr { mark_used: _ } => {
|
||||
self.cx.expanded_inert_attrs.mark(&attr);
|
||||
if *mark_used {
|
||||
self.cx.sess.mark_attr_used(&attr);
|
||||
}
|
||||
item.visit_attrs(|attrs| attrs.insert(pos, attr));
|
||||
fragment_kind.expect_from_annotatables(iter::once(item))
|
||||
}
|
||||
|
@ -535,7 +535,7 @@ pub fn compile_declarative_macro(
|
||||
|
||||
valid &= macro_check::check_meta_variables(&sess.parse_sess, def.id, def.span, &lhses, &rhses);
|
||||
|
||||
let (transparency, transparency_error) = attr::find_transparency(sess, &def.attrs, macro_rules);
|
||||
let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
|
||||
match transparency_error {
|
||||
Some(TransparencyError::UnknownTransparency(value, span)) => {
|
||||
diag.span_err(span, &format!("unknown macro transparency: `{}`", value))
|
||||
|
@ -52,11 +52,6 @@ pub enum AttributeType {
|
||||
/// by the compiler before the unused_attribute check
|
||||
Normal,
|
||||
|
||||
/// Builtin attribute that may not be consumed by the compiler
|
||||
/// before the unused_attribute check. These attributes
|
||||
/// will be ignored by the unused_attribute lint
|
||||
AssumedUsed,
|
||||
|
||||
/// Builtin attribute that is only allowed at the crate level
|
||||
CrateLevel,
|
||||
}
|
||||
@ -186,7 +181,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"),
|
||||
),
|
||||
// FIXME(Centril): This can be used on stable but shouldn't.
|
||||
ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")),
|
||||
ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name")),
|
||||
|
||||
// Macros:
|
||||
ungated!(automatically_derived, Normal, template!(Word)),
|
||||
@ -206,7 +201,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
|
||||
ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
|
||||
ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
|
||||
ungated!(must_use, AssumedUsed, template!(Word, NameValueStr: "reason")),
|
||||
ungated!(must_use, Normal, template!(Word, NameValueStr: "reason")),
|
||||
// FIXME(#14407)
|
||||
ungated!(
|
||||
deprecated, Normal,
|
||||
@ -224,16 +219,16 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
|
||||
// ABI, linking, symbols, and FFI
|
||||
ungated!(
|
||||
link, AssumedUsed,
|
||||
link, Normal,
|
||||
template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#),
|
||||
),
|
||||
ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")),
|
||||
ungated!(no_link, AssumedUsed, template!(Word)),
|
||||
ungated!(repr, AssumedUsed, template!(List: "C")),
|
||||
ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")),
|
||||
ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")),
|
||||
ungated!(no_mangle, AssumedUsed, template!(Word)),
|
||||
ungated!(used, AssumedUsed, template!(Word)),
|
||||
ungated!(link_name, Normal, template!(NameValueStr: "name")),
|
||||
ungated!(no_link, Normal, template!(Word)),
|
||||
ungated!(repr, Normal, template!(List: "C")),
|
||||
ungated!(export_name, Normal, template!(NameValueStr: "name")),
|
||||
ungated!(link_section, Normal, template!(NameValueStr: "name")),
|
||||
ungated!(no_mangle, Normal, template!(Word)),
|
||||
ungated!(used, Normal, template!(Word)),
|
||||
|
||||
// Limits:
|
||||
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")),
|
||||
@ -256,37 +251,37 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// Modules, prelude, and resolution:
|
||||
ungated!(path, Normal, template!(NameValueStr: "file")),
|
||||
ungated!(no_std, CrateLevel, template!(Word)),
|
||||
ungated!(no_implicit_prelude, Normal, template!(Word)),
|
||||
ungated!(non_exhaustive, AssumedUsed, template!(Word)),
|
||||
ungated!(no_implicit_prelude, CrateLevel, template!(Word)),
|
||||
ungated!(non_exhaustive, Normal, template!(Word)),
|
||||
|
||||
// Runtime
|
||||
ungated!(windows_subsystem, AssumedUsed, template!(NameValueStr: "windows|console")),
|
||||
ungated!(windows_subsystem, Normal, template!(NameValueStr: "windows|console")),
|
||||
ungated!(panic_handler, Normal, template!(Word)), // RFC 2070
|
||||
|
||||
// Code generation:
|
||||
ungated!(inline, AssumedUsed, template!(Word, List: "always|never")),
|
||||
ungated!(cold, AssumedUsed, template!(Word)),
|
||||
ungated!(no_builtins, AssumedUsed, template!(Word)),
|
||||
ungated!(target_feature, AssumedUsed, template!(List: r#"enable = "name""#)),
|
||||
ungated!(track_caller, AssumedUsed, template!(Word)),
|
||||
ungated!(inline, Normal, template!(Word, List: "always|never")),
|
||||
ungated!(cold, Normal, template!(Word)),
|
||||
ungated!(no_builtins, Normal, template!(Word)),
|
||||
ungated!(target_feature, Normal, template!(List: r#"enable = "name""#)),
|
||||
ungated!(track_caller, Normal, template!(Word)),
|
||||
gated!(
|
||||
no_sanitize, AssumedUsed,
|
||||
no_sanitize, Normal,
|
||||
template!(List: "address, memory, thread"),
|
||||
experimental!(no_sanitize)
|
||||
),
|
||||
gated!(no_coverage, AssumedUsed, template!(Word), experimental!(no_coverage)),
|
||||
gated!(no_coverage, Normal, template!(Word), experimental!(no_coverage)),
|
||||
|
||||
// FIXME: #14408 assume docs are used since rustdoc looks at them.
|
||||
ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")),
|
||||
ungated!(doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string")),
|
||||
|
||||
// ==========================================================================
|
||||
// Unstable attributes:
|
||||
// ==========================================================================
|
||||
|
||||
// Linking:
|
||||
gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)),
|
||||
gated!(naked, Normal, template!(Word), naked_functions, experimental!(naked)),
|
||||
gated!(
|
||||
link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib,
|
||||
link_ordinal, Normal, template!(List: "ordinal"), raw_dylib,
|
||||
experimental!(link_ordinal)
|
||||
),
|
||||
|
||||
@ -311,23 +306,23 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
"custom test frameworks are an unstable feature",
|
||||
),
|
||||
// RFC #1268
|
||||
gated!(marker, AssumedUsed, template!(Word), marker_trait_attr, experimental!(marker)),
|
||||
gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)),
|
||||
gated!(
|
||||
thread_local, AssumedUsed, template!(Word),
|
||||
thread_local, Normal, template!(Word),
|
||||
"`#[thread_local]` is an experimental feature, and does not currently handle destructors",
|
||||
),
|
||||
gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)),
|
||||
// RFC 2412
|
||||
gated!(
|
||||
optimize, AssumedUsed, template!(List: "size|speed"), optimize_attribute,
|
||||
optimize, Normal, template!(List: "size|speed"), optimize_attribute,
|
||||
experimental!(optimize),
|
||||
),
|
||||
// RFC 2867
|
||||
gated!(instruction_set, AssumedUsed, template!(List: "set"), isa_attribute, experimental!(instruction_set)),
|
||||
gated!(instruction_set, Normal, template!(List: "set"), isa_attribute, experimental!(instruction_set)),
|
||||
|
||||
gated!(ffi_returns_twice, AssumedUsed, template!(Word), experimental!(ffi_returns_twice)),
|
||||
gated!(ffi_pure, AssumedUsed, template!(Word), experimental!(ffi_pure)),
|
||||
gated!(ffi_const, AssumedUsed, template!(Word), experimental!(ffi_const)),
|
||||
gated!(ffi_returns_twice, Normal, template!(Word), experimental!(ffi_returns_twice)),
|
||||
gated!(ffi_pure, Normal, template!(Word), experimental!(ffi_pure)),
|
||||
gated!(ffi_const, Normal, template!(Word), experimental!(ffi_const)),
|
||||
gated!(
|
||||
register_attr, CrateLevel, template!(List: "attr1, attr2, ..."),
|
||||
experimental!(register_attr),
|
||||
@ -337,10 +332,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
experimental!(register_tool),
|
||||
),
|
||||
|
||||
gated!(cmse_nonsecure_entry, AssumedUsed, template!(Word), experimental!(cmse_nonsecure_entry)),
|
||||
gated!(cmse_nonsecure_entry, Normal, template!(Word), experimental!(cmse_nonsecure_entry)),
|
||||
// RFC 2632
|
||||
gated!(
|
||||
default_method_body_is_const, AssumedUsed, template!(Word), const_trait_impl,
|
||||
default_method_body_is_const, Normal, template!(Word), const_trait_impl,
|
||||
"`default_method_body_is_const` is a temporary placeholder for declaring default bodies \
|
||||
as `const`, which may be removed or renamed in the future."
|
||||
),
|
||||
@ -353,26 +348,26 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// FIXME(#14407) -- only looked at on-demand so we can't
|
||||
// guarantee they'll have already been checked.
|
||||
ungated!(
|
||||
rustc_deprecated, AssumedUsed,
|
||||
rustc_deprecated, Normal,
|
||||
template!(List: r#"since = "version", reason = "...""#)
|
||||
),
|
||||
// FIXME(#14407)
|
||||
ungated!(stable, AssumedUsed, template!(List: r#"feature = "name", since = "version""#)),
|
||||
ungated!(stable, Normal, template!(List: r#"feature = "name", since = "version""#)),
|
||||
// FIXME(#14407)
|
||||
ungated!(
|
||||
unstable, AssumedUsed,
|
||||
unstable, Normal,
|
||||
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
|
||||
),
|
||||
// FIXME(#14407)
|
||||
ungated!(rustc_const_unstable, AssumedUsed, template!(List: r#"feature = "name""#)),
|
||||
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#)),
|
||||
// FIXME(#14407)
|
||||
ungated!(rustc_const_stable, AssumedUsed, template!(List: r#"feature = "name""#)),
|
||||
ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#)),
|
||||
gated!(
|
||||
allow_internal_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."),
|
||||
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
|
||||
"allow_internal_unstable side-steps feature gating and stability checks",
|
||||
),
|
||||
gated!(
|
||||
rustc_allow_const_fn_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."),
|
||||
rustc_allow_const_fn_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
|
||||
"rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
|
||||
),
|
||||
gated!(
|
||||
@ -384,7 +379,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// Internal attributes: Type system related:
|
||||
// ==========================================================================
|
||||
|
||||
gated!(fundamental, AssumedUsed, template!(Word), experimental!(fundamental)),
|
||||
gated!(fundamental, Normal, template!(Word), experimental!(fundamental)),
|
||||
gated!(
|
||||
may_dangle, Normal, template!(Word), dropck_eyepatch,
|
||||
"`may_dangle` has unstable semantics and may be removed in the future",
|
||||
@ -394,26 +389,26 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// Internal attributes: Runtime related:
|
||||
// ==========================================================================
|
||||
|
||||
rustc_attr!(rustc_allocator, AssumedUsed, template!(Word), IMPL_DETAIL),
|
||||
rustc_attr!(rustc_allocator_nounwind, AssumedUsed, template!(Word), IMPL_DETAIL),
|
||||
rustc_attr!(rustc_allocator, Normal, template!(Word), IMPL_DETAIL),
|
||||
rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), IMPL_DETAIL),
|
||||
gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)),
|
||||
gated!(
|
||||
default_lib_allocator, AssumedUsed, template!(Word), allocator_internals,
|
||||
default_lib_allocator, Normal, template!(Word), allocator_internals,
|
||||
experimental!(default_lib_allocator),
|
||||
),
|
||||
gated!(
|
||||
needs_allocator, Normal, template!(Word), allocator_internals,
|
||||
experimental!(needs_allocator),
|
||||
),
|
||||
gated!(panic_runtime, AssumedUsed, template!(Word), experimental!(panic_runtime)),
|
||||
gated!(needs_panic_runtime, AssumedUsed, template!(Word), experimental!(needs_panic_runtime)),
|
||||
gated!(panic_runtime, Normal, template!(Word), experimental!(panic_runtime)),
|
||||
gated!(needs_panic_runtime, Normal, template!(Word), experimental!(needs_panic_runtime)),
|
||||
gated!(
|
||||
compiler_builtins, AssumedUsed, template!(Word),
|
||||
compiler_builtins, Normal, template!(Word),
|
||||
"the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
|
||||
which contains compiler-rt intrinsics and will never be stable",
|
||||
),
|
||||
gated!(
|
||||
profiler_runtime, AssumedUsed, template!(Word),
|
||||
profiler_runtime, Normal, template!(Word),
|
||||
"the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
|
||||
which contains the profiler runtime and will never be stable",
|
||||
),
|
||||
@ -423,23 +418,23 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// ==========================================================================
|
||||
|
||||
gated!(
|
||||
linkage, AssumedUsed, template!(NameValueStr: "external|internal|..."),
|
||||
linkage, Normal, template!(NameValueStr: "external|internal|..."),
|
||||
"the `linkage` attribute is experimental and not portable across platforms",
|
||||
),
|
||||
rustc_attr!(rustc_std_internal_symbol, AssumedUsed, template!(Word), INTERNAL_UNSTABLE),
|
||||
rustc_attr!(rustc_std_internal_symbol, Normal, template!(Word), INTERNAL_UNSTABLE),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes, Macro related:
|
||||
// ==========================================================================
|
||||
|
||||
rustc_attr!(
|
||||
rustc_builtin_macro, AssumedUsed,
|
||||
rustc_builtin_macro, Normal,
|
||||
template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"),
|
||||
IMPL_DETAIL,
|
||||
),
|
||||
rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE),
|
||||
rustc_attr!(
|
||||
rustc_macro_transparency, AssumedUsed,
|
||||
rustc_macro_transparency, Normal,
|
||||
template!(NameValueStr: "transparent|semitransparent|opaque"),
|
||||
"used internally for testing macro hygiene",
|
||||
),
|
||||
@ -449,7 +444,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
// ==========================================================================
|
||||
|
||||
rustc_attr!(
|
||||
rustc_on_unimplemented, AssumedUsed,
|
||||
rustc_on_unimplemented, Normal,
|
||||
template!(
|
||||
List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
|
||||
NameValueStr: "message"
|
||||
@ -457,31 +452,31 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
INTERNAL_UNSTABLE
|
||||
),
|
||||
// Enumerates "identity-like" conversion methods to suggest on type mismatch.
|
||||
rustc_attr!(rustc_conversion_suggestion, AssumedUsed, template!(Word), INTERNAL_UNSTABLE),
|
||||
rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes, Const related:
|
||||
// ==========================================================================
|
||||
|
||||
rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL),
|
||||
rustc_attr!(rustc_legacy_const_generics, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE),
|
||||
rustc_attr!(rustc_promotable, Normal, template!(Word), IMPL_DETAIL),
|
||||
rustc_attr!(rustc_legacy_const_generics, Normal, template!(List: "N"), INTERNAL_UNSTABLE),
|
||||
|
||||
// ==========================================================================
|
||||
// Internal attributes, Layout related:
|
||||
// ==========================================================================
|
||||
|
||||
rustc_attr!(
|
||||
rustc_layout_scalar_valid_range_start, AssumedUsed, template!(List: "value"),
|
||||
rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"),
|
||||
"the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
|
||||
niche optimizations in libcore and will never be stable",
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_layout_scalar_valid_range_end, AssumedUsed, template!(List: "value"),
|
||||
rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"),
|
||||
"the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
|
||||
niche optimizations in libcore and will never be stable",
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_nonnull_optimization_guaranteed, AssumedUsed, template!(Word),
|
||||
rustc_nonnull_optimization_guaranteed, Normal, template!(Word),
|
||||
"the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \
|
||||
niche optimizations in libcore and will never be stable",
|
||||
),
|
||||
@ -506,7 +501,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
),
|
||||
gated!(
|
||||
// Used in resolve:
|
||||
prelude_import, AssumedUsed, template!(Word),
|
||||
prelude_import, Normal, template!(Word),
|
||||
"`#[prelude_import]` is for use by rustc only",
|
||||
),
|
||||
gated!(
|
||||
@ -514,7 +509,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
"unboxed_closures are still evolving",
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_inherit_overflow_checks, AssumedUsed, template!(Word),
|
||||
rustc_inherit_overflow_checks, Normal, template!(Word),
|
||||
"the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
|
||||
overflow checking behavior of several libcore functions that are inlined \
|
||||
across crates and will never be stable",
|
||||
@ -556,41 +551,41 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
|
||||
rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),
|
||||
rustc_attr!(
|
||||
TEST, rustc_error, AssumedUsed,
|
||||
TEST, rustc_error, Normal,
|
||||
template!(Word, List: "delay_span_bug_from_inside_query")
|
||||
),
|
||||
rustc_attr!(TEST, rustc_dump_user_substs, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_evaluate_where_clauses, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_if_this_changed, AssumedUsed, template!(Word, List: "DepNode")),
|
||||
rustc_attr!(TEST, rustc_then_this_would_need, AssumedUsed, template!(List: "DepNode")),
|
||||
rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode")),
|
||||
rustc_attr!(TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode")),
|
||||
rustc_attr!(
|
||||
TEST, rustc_clean, AssumedUsed,
|
||||
TEST, rustc_clean, Normal,
|
||||
template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
|
||||
),
|
||||
rustc_attr!(
|
||||
TEST, rustc_partition_reused, AssumedUsed,
|
||||
TEST, rustc_partition_reused, Normal,
|
||||
template!(List: r#"cfg = "...", module = "...""#),
|
||||
),
|
||||
rustc_attr!(
|
||||
TEST, rustc_partition_codegened, AssumedUsed,
|
||||
TEST, rustc_partition_codegened, Normal,
|
||||
template!(List: r#"cfg = "...", module = "...""#),
|
||||
),
|
||||
rustc_attr!(
|
||||
TEST, rustc_expected_cgu_reuse, AssumedUsed,
|
||||
TEST, rustc_expected_cgu_reuse, Normal,
|
||||
template!(List: r#"cfg = "...", module = "...", kind = "...""#),
|
||||
),
|
||||
rustc_attr!(TEST, rustc_synthetic, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_symbol_name, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_polymorphize_error, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_def_path, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_mir, AssumedUsed, template!(List: "arg1, arg2, ...")),
|
||||
rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_dump_env_program_clauses, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_object_lifetime_default, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_dump_vtable, AssumedUsed, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_synthetic, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_def_path, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ...")),
|
||||
rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word)),
|
||||
rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)),
|
||||
gated!(
|
||||
omit_gdb_pretty_printer_section, AssumedUsed, template!(Word),
|
||||
omit_gdb_pretty_printer_section, Normal, template!(Word),
|
||||
"the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
|
||||
),
|
||||
];
|
||||
|
@ -123,7 +123,7 @@ impl IfThisChanged<'tcx> {
|
||||
let def_path_hash = self.tcx.def_path_hash(def_id.to_def_id());
|
||||
let attrs = self.tcx.hir().attrs(hir_id);
|
||||
for attr in attrs {
|
||||
if self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) {
|
||||
if attr.has_name(sym::rustc_if_this_changed) {
|
||||
let dep_node_interned = self.argument(attr);
|
||||
let dep_node = match dep_node_interned {
|
||||
None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner),
|
||||
@ -138,7 +138,7 @@ impl IfThisChanged<'tcx> {
|
||||
},
|
||||
};
|
||||
self.if_this_changed.push((attr.span, def_id.to_def_id(), dep_node));
|
||||
} else if self.tcx.sess.check_name(attr, sym::rustc_then_this_would_need) {
|
||||
} else if attr.has_name(sym::rustc_then_this_would_need) {
|
||||
let dep_node_interned = self.argument(attr);
|
||||
let dep_node = match dep_node_interned {
|
||||
Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) {
|
||||
|
@ -57,12 +57,11 @@ struct AssertModuleSource<'tcx> {
|
||||
|
||||
impl AssertModuleSource<'tcx> {
|
||||
fn check_attr(&self, attr: &ast::Attribute) {
|
||||
let (expected_reuse, comp_kind) =
|
||||
if self.tcx.sess.check_name(attr, sym::rustc_partition_reused) {
|
||||
let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) {
|
||||
(CguReuse::PreLto, ComparisonKind::AtLeast)
|
||||
} else if self.tcx.sess.check_name(attr, sym::rustc_partition_codegened) {
|
||||
} else if attr.has_name(sym::rustc_partition_codegened) {
|
||||
(CguReuse::No, ComparisonKind::Exact)
|
||||
} else if self.tcx.sess.check_name(attr, sym::rustc_expected_cgu_reuse) {
|
||||
} else if attr.has_name(sym::rustc_expected_cgu_reuse) {
|
||||
match self.field(attr, sym::kind) {
|
||||
sym::no => (CguReuse::No, ComparisonKind::Exact),
|
||||
sym::pre_dash_lto => (CguReuse::PreLto, ComparisonKind::Exact),
|
||||
|
@ -159,7 +159,7 @@ pub struct DirtyCleanVisitor<'tcx> {
|
||||
impl DirtyCleanVisitor<'tcx> {
|
||||
/// Possibly "deserialize" the attribute into a clean/dirty assertion
|
||||
fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option<Assertion> {
|
||||
if !self.tcx.sess.check_name(attr, sym::rustc_clean) {
|
||||
if !attr.has_name(sym::rustc_clean) {
|
||||
// skip: not rustc_clean/dirty
|
||||
return None;
|
||||
}
|
||||
@ -427,7 +427,7 @@ pub struct FindAllAttrs<'tcx> {
|
||||
|
||||
impl FindAllAttrs<'tcx> {
|
||||
fn is_active_attr(&mut self, attr: &Attribute) -> bool {
|
||||
if self.tcx.sess.check_name(attr, sym::rustc_clean) && check_config(self.tcx, attr) {
|
||||
if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ impl<'tcx> Queries<'tcx> {
|
||||
};
|
||||
|
||||
let attrs = &*tcx.get_attrs(def_id);
|
||||
let attrs = attrs.iter().filter(|attr| tcx.sess.check_name(attr, sym::rustc_error));
|
||||
let attrs = attrs.iter().filter(|attr| attr.has_name(sym::rustc_error));
|
||||
for attr in attrs {
|
||||
match attr.meta_item_list() {
|
||||
// Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`.
|
||||
|
@ -488,13 +488,13 @@ pub fn get_codegen_sysroot(
|
||||
}
|
||||
|
||||
pub(crate) fn check_attr_crate_type(
|
||||
sess: &Session,
|
||||
_sess: &Session,
|
||||
attrs: &[ast::Attribute],
|
||||
lint_buffer: &mut LintBuffer,
|
||||
) {
|
||||
// Unconditionally collect crate types from attributes to make them used
|
||||
for a in attrs.iter() {
|
||||
if sess.check_name(a, sym::crate_type) {
|
||||
if a.has_name(sym::crate_type) {
|
||||
if let Some(n) = a.value_str() {
|
||||
if categorize_crate_type(n).is_some() {
|
||||
return;
|
||||
@ -552,7 +552,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<C
|
||||
let attr_types: Vec<CrateType> = attrs
|
||||
.iter()
|
||||
.filter_map(|a| {
|
||||
if session.check_name(a, sym::crate_type) {
|
||||
if a.has_name(sym::crate_type) {
|
||||
match a.value_str() {
|
||||
Some(s) => categorize_crate_type(s),
|
||||
_ => None,
|
||||
|
@ -46,7 +46,6 @@ use rustc_middle::ty::subst::{GenericArgKind, Subst};
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
|
||||
use rustc_session::lint::FutureIncompatibilityReason;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
@ -344,7 +343,7 @@ impl UnsafeCode {
|
||||
|
||||
impl EarlyLintPass for UnsafeCode {
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
|
||||
if cx.sess().check_name(attr, sym::allow_internal_unsafe) {
|
||||
if attr.has_name(sym::allow_internal_unsafe) {
|
||||
self.report_unsafe(cx, attr.span, |lint| {
|
||||
lint.build(
|
||||
"`allow_internal_unsafe` allows defining \
|
||||
@ -492,12 +491,12 @@ pub struct MissingDoc {
|
||||
|
||||
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
|
||||
|
||||
fn has_doc(sess: &Session, attr: &ast::Attribute) -> bool {
|
||||
fn has_doc(attr: &ast::Attribute) -> bool {
|
||||
if attr.is_doc_comment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if !sess.check_name(attr, sym::doc) {
|
||||
if !attr.has_name(sym::doc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -554,7 +553,7 @@ impl MissingDoc {
|
||||
}
|
||||
|
||||
let attrs = cx.tcx.get_attrs(def_id.to_def_id());
|
||||
let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
|
||||
let has_doc = attrs.iter().any(has_doc);
|
||||
if !has_doc {
|
||||
cx.struct_span_lint(
|
||||
MISSING_DOCS,
|
||||
@ -568,10 +567,10 @@ impl MissingDoc {
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
||||
fn enter_lint_attrs(&mut self, cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
|
||||
fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
|
||||
let doc_hidden = self.doc_hidden()
|
||||
|| attrs.iter().any(|attr| {
|
||||
cx.sess().check_name(attr, sym::doc)
|
||||
attr.has_name(sym::doc)
|
||||
&& match attr.meta_item_list() {
|
||||
None => false,
|
||||
Some(l) => attr::list_contains_name(&l, sym::hidden),
|
||||
@ -595,7 +594,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
||||
}
|
||||
|
||||
let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
|
||||
let has_doc = attrs.iter().any(|a| has_doc(cx.sess(), a));
|
||||
let has_doc = attrs.iter().any(has_doc);
|
||||
if !has_doc {
|
||||
cx.struct_span_lint(
|
||||
MISSING_DOCS,
|
||||
@ -999,7 +998,7 @@ impl EarlyLintPass for DeprecatedAttr {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if cx.sess().check_name(attr, sym::no_start) || cx.sess().check_name(attr, sym::crate_id) {
|
||||
if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
|
||||
let path_str = pprust::path_to_string(&attr.get_normal_item().path);
|
||||
let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str);
|
||||
lint_deprecated_attr(cx, attr, &msg, None);
|
||||
@ -1028,7 +1027,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
|
||||
|
||||
let span = sugared_span.take().unwrap_or(attr.span);
|
||||
|
||||
if is_doc_comment || cx.sess().check_name(attr, sym::doc) {
|
||||
if is_doc_comment || attr.has_name(sym::doc) {
|
||||
cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
|
||||
let mut err = lint.build("unused doc comment");
|
||||
err.span_label(
|
||||
@ -1301,7 +1300,7 @@ declare_lint_pass!(
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
|
||||
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
|
||||
if cx.sess().check_name(attr, sym::feature) {
|
||||
if attr.has_name(sym::feature) {
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
for item in items {
|
||||
cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
|
||||
@ -2771,7 +2770,7 @@ impl ClashingExternDeclarations {
|
||||
overridden_link_name,
|
||||
tcx.get_attrs(fi.def_id.to_def_id())
|
||||
.iter()
|
||||
.find(|at| tcx.sess.check_name(at, sym::link_name))
|
||||
.find(|at| at.has_name(sym::link_name))
|
||||
.unwrap()
|
||||
.span,
|
||||
)
|
||||
|
@ -236,8 +236,6 @@ impl<'s> LintLevelsBuilder<'s> {
|
||||
Some(lvl) => lvl,
|
||||
};
|
||||
|
||||
self.sess.mark_attr_used(attr);
|
||||
|
||||
let mut metas = unwrap_or!(attr.meta_item_list(), continue);
|
||||
|
||||
if metas.is_empty() {
|
||||
|
@ -151,8 +151,6 @@ macro_rules! late_lint_passes {
|
||||
// FIXME: Look into regression when this is used as a module lint
|
||||
// May Depend on constants elsewhere
|
||||
UnusedBrokenConst: UnusedBrokenConst,
|
||||
// Uses attr::is_used which is untracked, can't be an incremental module pass.
|
||||
UnusedAttributes: UnusedAttributes::new(),
|
||||
// Needs to run after UnusedAttributes as it marks all `feature` attributes as used.
|
||||
UnstableFeatures: UnstableFeatures,
|
||||
// Tracks state across modules
|
||||
|
@ -669,9 +669,7 @@ enum FfiResult<'tcx> {
|
||||
}
|
||||
|
||||
crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtDef) -> bool {
|
||||
tcx.get_attrs(def.did)
|
||||
.iter()
|
||||
.any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed))
|
||||
tcx.get_attrs(def.did).iter().any(|a| a.has_name(sym::rustc_nonnull_optimization_guaranteed))
|
||||
}
|
||||
|
||||
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that
|
||||
|
@ -4,21 +4,16 @@ use rustc_ast as ast;
|
||||
use rustc_ast::util::parser;
|
||||
use rustc_ast::{ExprKind, StmtKind};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{pluralize, Applicability};
|
||||
use rustc_feature::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::adjustment;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::lint::builtin::UNUSED_ATTRIBUTES;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
declare_lint! {
|
||||
/// The `unused_must_use` lint detects unused result of a type flagged as
|
||||
/// `#[must_use]`.
|
||||
@ -308,7 +303,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
||||
descr_post_path: &str,
|
||||
) -> bool {
|
||||
for attr in cx.tcx.get_attrs(def_id).iter() {
|
||||
if cx.sess().check_name(attr, sym::must_use) {
|
||||
if attr.has_name(sym::must_use) {
|
||||
cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
|
||||
let msg = format!(
|
||||
"unused {}`{}`{} that must be used",
|
||||
@ -382,62 +377,6 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct UnusedAttributes {
|
||||
builtin_attributes: &'static FxHashMap<Symbol, &'static BuiltinAttribute>,
|
||||
}
|
||||
|
||||
impl UnusedAttributes {
|
||||
pub fn new() -> Self {
|
||||
UnusedAttributes { builtin_attributes: &*BUILTIN_ATTRIBUTE_MAP }
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for UnusedAttributes {
|
||||
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
|
||||
debug!("checking attribute: {:?}", attr);
|
||||
|
||||
if attr.is_doc_comment() {
|
||||
return;
|
||||
}
|
||||
|
||||
let attr_info = attr.ident().and_then(|ident| self.builtin_attributes.get(&ident.name));
|
||||
|
||||
if let Some(&&(name, ty, ..)) = attr_info {
|
||||
if let AttributeType::AssumedUsed = ty {
|
||||
debug!("{:?} is AssumedUsed", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if !cx.sess().is_attr_used(attr) {
|
||||
debug!("emitting warning for: {:?}", attr);
|
||||
cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| {
|
||||
// Mark as used to avoid duplicate warnings.
|
||||
cx.sess().mark_attr_used(attr);
|
||||
lint.build("unused attribute").emit()
|
||||
});
|
||||
// Is it a builtin attribute that must be used at the crate level?
|
||||
if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) {
|
||||
cx.struct_span_lint(UNUSED_ATTRIBUTES, attr.span, |lint| {
|
||||
let msg = match attr.style {
|
||||
ast::AttrStyle::Outer => {
|
||||
"crate-level attribute should be an inner attribute: add an exclamation \
|
||||
mark: `#![foo]`"
|
||||
}
|
||||
ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
|
||||
};
|
||||
lint.build(msg).emit()
|
||||
});
|
||||
}
|
||||
} else {
|
||||
debug!("Attr was used: {:?}", attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum UnusedDelimsCtx {
|
||||
FunctionArg,
|
||||
|
@ -3042,6 +3042,7 @@ declare_lint_pass! {
|
||||
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
|
||||
UNSUPPORTED_CALLING_CONVENTIONS,
|
||||
BREAK_WITH_LABEL_AND_LOOP,
|
||||
UNUSED_ATTRIBUTES,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -44,8 +44,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
|
||||
|
||||
// Process all of the #[link(..)]-style arguments
|
||||
let sess = &self.tcx.sess;
|
||||
for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| sess.check_name(a, sym::link))
|
||||
{
|
||||
for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) {
|
||||
let items = match m.meta_item_list() {
|
||||
Some(item) => item,
|
||||
None => continue,
|
||||
|
@ -48,7 +48,7 @@ pub fn get_recursion_limit(krate_attrs: &[Attribute], sess: &Session) -> Limit {
|
||||
|
||||
fn get_limit(krate_attrs: &[Attribute], sess: &Session, name: Symbol, default: usize) -> Limit {
|
||||
for attr in krate_attrs {
|
||||
if !sess.check_name(attr, name) {
|
||||
if !attr.has_name(name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1136,7 +1136,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
|
||||
let attrs = self.get_attrs(def_id);
|
||||
let get = |name| {
|
||||
let attr = match attrs.iter().find(|a| self.sess.check_name(a, name)) {
|
||||
let attr = match attrs.iter().find(|a| a.has_name(name)) {
|
||||
Some(attr) => attr,
|
||||
None => return Bound::Unbounded,
|
||||
};
|
||||
|
@ -338,7 +338,7 @@ impl RustcMirAttrs {
|
||||
|
||||
let rustc_mir_attrs = attrs
|
||||
.iter()
|
||||
.filter(|attr| tcx.sess.check_name(attr, sym::rustc_mir))
|
||||
.filter(|attr| attr.has_name(sym::rustc_mir))
|
||||
.flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter()));
|
||||
|
||||
for attr in rustc_mir_attrs {
|
||||
|
@ -30,12 +30,12 @@ pub struct MoveDataParamEnv<'tcx> {
|
||||
}
|
||||
|
||||
pub(crate) fn has_rustc_mir_with(
|
||||
sess: &Session,
|
||||
_sess: &Session,
|
||||
attrs: &[ast::Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<MetaItem> {
|
||||
for attr in attrs {
|
||||
if sess.check_name(attr, sym::rustc_mir) {
|
||||
if attr.has_name(sym::rustc_mir) {
|
||||
let items = attr.meta_item_list();
|
||||
for item in items.iter().flat_map(|l| l.iter()) {
|
||||
match item.meta_item() {
|
||||
|
@ -204,11 +204,7 @@ fn emit_unused_generic_params_error<'tcx>(
|
||||
unused_parameters: &FiniteBitSet<u32>,
|
||||
) {
|
||||
let base_def_id = tcx.closure_base_def_id(def_id);
|
||||
if !tcx
|
||||
.get_attrs(base_def_id)
|
||||
.iter()
|
||||
.any(|a| tcx.sess.check_name(a, sym::rustc_polymorphize_error))
|
||||
{
|
||||
if !tcx.get_attrs(base_def_id).iter().any(|a| a.has_name(sym::rustc_polymorphize_error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,10 @@ use rustc_ast::tokenstream::{AttrAnnotatedTokenStream, AttrAnnotatedTokenTree};
|
||||
use rustc_ast::tokenstream::{Spacing, TokenStream};
|
||||
use rustc_ast::AstLike;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_ast::{AttrItem, MetaItem};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Diagnostic, FatalError, Level, PResult};
|
||||
use rustc_errors::{Applicability, Diagnostic, FatalError, Level, PResult};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::{FileName, SourceFile, Span};
|
||||
|
||||
@ -324,3 +325,44 @@ pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
|
||||
let filename = FileName::macro_expansion_source_code(&source);
|
||||
parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
|
||||
}
|
||||
|
||||
pub fn parse_cfg_attr(
|
||||
attr: &Attribute,
|
||||
parse_sess: &ParseSess,
|
||||
) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
|
||||
match attr.get_normal_item().args {
|
||||
ast::MacArgs::Delimited(dspan, delim, ref tts) if !tts.is_empty() => {
|
||||
let msg = "wrong `cfg_attr` delimiters";
|
||||
crate::validate_attr::check_meta_bad_delim(parse_sess, dspan, delim, msg);
|
||||
match parse_in(parse_sess, tts.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) {
|
||||
Ok(r) => return Some(r),
|
||||
Err(mut e) => {
|
||||
e.help(&format!("the valid syntax is `{}`", CFG_ATTR_GRAMMAR_HELP))
|
||||
.note(CFG_ATTR_NOTE_REF)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => error_malformed_cfg_attr_missing(attr.span, parse_sess),
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
|
||||
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
|
||||
<https://doc.rust-lang.org/reference/conditional-compilation.html\
|
||||
#the-cfg_attr-attribute>";
|
||||
|
||||
fn error_malformed_cfg_attr_missing(span: Span, parse_sess: &ParseSess) {
|
||||
parse_sess
|
||||
.span_diagnostic
|
||||
.struct_span_err(span, "malformed `cfg_attr` attribute input")
|
||||
.span_suggestion(
|
||||
span,
|
||||
"missing condition and attribute",
|
||||
CFG_ATTR_GRAMMAR_HELP.to_string(),
|
||||
Applicability::HasPlaceholders,
|
||||
)
|
||||
.note(CFG_ATTR_NOTE_REF)
|
||||
.emit();
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
@ -18,3 +19,4 @@ rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
|
@ -8,8 +8,10 @@ use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
use rustc_ast::{AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
|
||||
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
|
||||
use rustc_data_structures::stable_set::FxHashSet;
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability};
|
||||
use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||
@ -66,9 +68,10 @@ impl CheckAttrVisitor<'tcx> {
|
||||
) {
|
||||
let mut is_valid = true;
|
||||
let mut specified_inline = None;
|
||||
let mut seen = FxHashSet::default();
|
||||
let attrs = self.tcx.hir().attrs(hir_id);
|
||||
for attr in attrs {
|
||||
is_valid &= match attr.name_or_empty() {
|
||||
let attr_is_valid = match attr.name_or_empty() {
|
||||
sym::inline => self.check_inline(hir_id, attr, span, target),
|
||||
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
|
||||
sym::marker => self.check_marker(hir_id, attr, span, target),
|
||||
@ -101,14 +104,66 @@ impl CheckAttrVisitor<'tcx> {
|
||||
sym::default_method_body_is_const => {
|
||||
self.check_default_method_body_is_const(attr, span, target)
|
||||
}
|
||||
sym::rustc_const_unstable
|
||||
| sym::rustc_const_stable
|
||||
| sym::unstable
|
||||
| sym::stable
|
||||
| sym::rustc_promotable => self.check_stability_promotable(&attr, span, target),
|
||||
_ => true,
|
||||
};
|
||||
is_valid &= attr_is_valid;
|
||||
|
||||
// lint-only checks
|
||||
match attr.name_or_empty() {
|
||||
sym::cold => self.check_cold(hir_id, attr, span, target),
|
||||
sym::link_name => self.check_link_name(hir_id, attr, span, target),
|
||||
sym::link_section => self.check_link_section(hir_id, attr, span, target),
|
||||
sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
|
||||
sym::deprecated | sym::rustc_deprecated => {
|
||||
self.check_deprecated(hir_id, attr, span, target)
|
||||
}
|
||||
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
|
||||
sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
|
||||
sym::cfg_attr => self.check_cfg_attr(hir_id, attr),
|
||||
sym::plugin_registrar => self.check_plugin_registrar(hir_id, attr, target),
|
||||
sym::macro_export => self.check_macro_export(hir_id, attr, target),
|
||||
sym::ignore | sym::should_panic | sym::proc_macro_derive => {
|
||||
self.check_generic_attr(hir_id, attr, target, &[Target::Fn])
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if hir_id != CRATE_HIR_ID {
|
||||
if let Some((_, AttributeType::CrateLevel, ..)) =
|
||||
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
|
||||
{
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
let msg = match attr.style {
|
||||
ast::AttrStyle::Outer => {
|
||||
"crate-level attribute should be an inner attribute: add an exclamation \
|
||||
mark: `#![foo]`"
|
||||
}
|
||||
ast::AttrStyle::Inner => "crate-level attribute should be in the root module",
|
||||
};
|
||||
lint.build(msg).emit()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Duplicate attributes
|
||||
match attr.name_or_empty() {
|
||||
name @ sym::macro_use => {
|
||||
let args = attr.meta_item_list().unwrap_or_else(Vec::new);
|
||||
let args: Vec<_> = args.iter().map(|arg| arg.name_or_empty()).collect();
|
||||
if !seen.insert((name, args)) {
|
||||
self.tcx.struct_span_lint_hir(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
|lint| lint.build("unused attribute").emit(),
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -211,6 +266,38 @@ impl CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_generic_attr(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
target: Target,
|
||||
allowed_targets: &[Target],
|
||||
) {
|
||||
if !allowed_targets.iter().any(|t| t == &target) {
|
||||
let name = attr.name_or_empty();
|
||||
let mut i = allowed_targets.iter();
|
||||
// Pluralize
|
||||
let b = i.next().map_or_else(String::new, |t| t.to_string() + "s");
|
||||
let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| {
|
||||
if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 {
|
||||
b.push_str(", and ");
|
||||
} else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 {
|
||||
b.push_str(" and ");
|
||||
} else {
|
||||
b.push_str(", ");
|
||||
}
|
||||
// Pluralize
|
||||
b.push_str(&(allowed_target.to_string() + "s"));
|
||||
b
|
||||
});
|
||||
//let supported_names = allowed_targets.iter().fold(String::new(), |msg, t| msg + ", " + &t.to_string());
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build(&format!("`#[{name}]` only has an effect on {}", supported_names))
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `#[naked]` is applied to a function definition.
|
||||
fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) -> bool {
|
||||
match target {
|
||||
@ -1555,6 +1642,72 @@ impl CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_stability_promotable(&self, attr: &Attribute, _span: &Span, target: Target) -> bool {
|
||||
match target {
|
||||
Target::Expression => {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(attr.span, "attribute cannot be applied to an expression")
|
||||
.emit();
|
||||
false
|
||||
}
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: &Span, target: Target) {
|
||||
match target {
|
||||
Target::Closure | Target::Expression | Target::Statement | Target::Arm => {
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build("attribute is ignored here").emit();
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
||||
let name = attr.name_or_empty();
|
||||
match target {
|
||||
Target::ExternCrate | Target::Mod => {}
|
||||
_ => {
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build(&format!(
|
||||
"`#[{name}]` only has an effect on `extern crate` and modules"
|
||||
))
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
||||
if target != Target::MacroDef {
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build(&format!("`#[macro_export]` only has an effect on macro definitions"))
|
||||
.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn check_cfg_attr(&self, hir_id: HirId, attr: &Attribute) {
|
||||
if let Some((_, attrs)) = rustc_parse::parse_cfg_attr(&attr, &self.tcx.sess.parse_sess) {
|
||||
if attrs.is_empty() {
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build("`#[cfg_attr]` does not expand to any attributes").emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
||||
if target != Target::Fn {
|
||||
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
|
||||
lint.build("`#[plugin_registrar]` only has an effect on functions").emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visitor<'tcx> for CheckAttrVisitor<'tcx> {
|
||||
@ -1675,7 +1828,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
||||
|
||||
for attr in attrs {
|
||||
for attr_to_check in ATTRS_TO_CHECK {
|
||||
if tcx.sess.check_name(attr, *attr_to_check) {
|
||||
if attr.has_name(*attr_to_check) {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
@ -1692,7 +1845,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
||||
|
||||
fn check_invalid_macro_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
||||
for attr in attrs {
|
||||
if tcx.sess.check_name(attr, sym::inline) {
|
||||
if attr.has_name(sym::inline) {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
|
@ -15,7 +15,6 @@ use rustc_hir as hir;
|
||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
@ -51,7 +50,7 @@ impl<'tcx> DiagnosticItemCollector<'tcx> {
|
||||
fn observe_item(&mut self, def_id: LocalDefId) {
|
||||
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let attrs = self.tcx.hir().attrs(hir_id);
|
||||
if let Some(name) = extract(&self.tcx.sess, attrs) {
|
||||
if let Some(name) = extract(attrs) {
|
||||
// insert into our table
|
||||
collect_item(self.tcx, &mut self.items, name, def_id.to_def_id());
|
||||
}
|
||||
@ -91,10 +90,10 @@ fn collect_item(
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
|
||||
fn extract(sess: &Session, attrs: &[ast::Attribute]) -> Option<Symbol> {
|
||||
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.p
|
||||
fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
|
||||
attrs.iter().find_map(|attr| {
|
||||
if sess.check_name(attr, sym::rustc_diagnostic_item) { attr.value_str() } else { None }
|
||||
if attr.has_name(sym::rustc_diagnostic_item) { attr.value_str() } else { None }
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ use crate::weak_lang_items;
|
||||
use rustc_middle::middle::cstore::ExternCrate;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_errors::{pluralize, struct_span_err};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
@ -57,7 +58,7 @@ impl LanguageItemCollector<'tcx> {
|
||||
|
||||
fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
|
||||
let attrs = self.tcx.hir().attrs(hir_id);
|
||||
let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
|
||||
let check_name = |attr: &Attribute, sym| attr.has_name(sym);
|
||||
if let Some((value, span)) = extract(check_name, &attrs) {
|
||||
match ITEM_REFS.get(&value).cloned() {
|
||||
// Known lang item with attribute on correct target.
|
||||
|
@ -27,7 +27,7 @@ impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> {
|
||||
| ItemKind::Struct(..)
|
||||
| ItemKind::Union(..) => {
|
||||
for attr in self.tcx.get_attrs(item.def_id.to_def_id()).iter() {
|
||||
if self.tcx.sess.check_name(attr, sym::rustc_layout) {
|
||||
if attr.has_name(sym::rustc_layout) {
|
||||
self.dump_layout_of(item.def_id, item, attr);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(format_args_capture)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(nll)]
|
||||
#![feature(min_specialization)]
|
||||
|
@ -33,9 +33,7 @@ impl LibFeatureCollector<'tcx> {
|
||||
|
||||
// Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`,
|
||||
// `#[rustc_const_unstable (..)]`).
|
||||
if let Some(stab_attr) =
|
||||
stab_attrs.iter().find(|stab_attr| self.tcx.sess.check_name(attr, **stab_attr))
|
||||
{
|
||||
if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) {
|
||||
let meta_item = attr.meta();
|
||||
if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta_item {
|
||||
let mut feature = None;
|
||||
|
@ -148,7 +148,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if self.tcx.features().staged_api {
|
||||
if let Some(a) = attrs.iter().find(|a| self.tcx.sess.check_name(a, sym::deprecated)) {
|
||||
if let Some(a) = attrs.iter().find(|a| a.has_name(sym::deprecated)) {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API")
|
||||
@ -350,7 +350,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
for attr in attrs {
|
||||
let name = attr.name_or_empty();
|
||||
if unstable_attrs.contains(&name) {
|
||||
self.tcx.sess.mark_attr_used(attr);
|
||||
struct_span_err!(
|
||||
self.tcx.sess,
|
||||
attr.span,
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Validity checking for weak lang items
|
||||
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
@ -96,7 +97,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, i: &hir::ForeignItem<'_>) {
|
||||
let check_name = |attr, sym| self.tcx.sess.check_name(attr, sym);
|
||||
let check_name = |attr: &Attribute, sym| attr.has_name(sym);
|
||||
let attrs = self.tcx.hir().attrs(i.hir_id());
|
||||
if let Some((lang_item, _)) = lang_items::extract(check_name, attrs) {
|
||||
self.register(lang_item, i.span);
|
||||
|
@ -32,7 +32,7 @@ pub fn load_plugins(
|
||||
let mut plugins = Vec::new();
|
||||
|
||||
for attr in &krate.attrs {
|
||||
if !sess.check_name(attr, sym::plugin) {
|
||||
if !attr.has_name(sym::plugin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -885,9 +885,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
|
||||
// Non-opaque macros cannot make other items more accessible than they already are.
|
||||
let attrs = self.tcx.hir().attrs(md.hir_id());
|
||||
if attr::find_transparency(&self.tcx.sess, &attrs, md.ast.macro_rules).0
|
||||
!= Transparency::Opaque
|
||||
{
|
||||
if attr::find_transparency(&attrs, md.ast.macro_rules).0 != Transparency::Opaque {
|
||||
// `#[macro_export]`-ed `macro_rules!` are `Public` since they
|
||||
// ignore their containing path to always appear at the crate root.
|
||||
if md.ast.macro_rules {
|
||||
|
@ -1059,7 +1059,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
let mut import_all = None;
|
||||
let mut single_imports = Vec::new();
|
||||
for attr in &item.attrs {
|
||||
if self.r.session.check_name(attr, sym::macro_use) {
|
||||
if attr.has_name(sym::macro_use) {
|
||||
if self.parent_scope.module.parent.is_some() {
|
||||
struct_span_err!(
|
||||
self.r.session,
|
||||
@ -1165,7 +1165,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
/// Returns `true` if this attribute list contains `macro_use`.
|
||||
fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
|
||||
for attr in attrs {
|
||||
if self.r.session.check_name(attr, sym::macro_escape) {
|
||||
if attr.has_name(sym::macro_escape) {
|
||||
let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`";
|
||||
let mut err = self.r.session.struct_span_warn(attr.span, msg);
|
||||
if let ast::AttrStyle::Inner = attr.style {
|
||||
@ -1173,7 +1173,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
} else if !self.r.session.check_name(attr, sym::macro_use) {
|
||||
} else if !attr.has_name(sym::macro_use) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2057,9 +2057,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
if let Some(def_id) = parent_def_id.as_local() {
|
||||
let parent_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
// lifetimes in `derive` expansions don't count (Issue #53738)
|
||||
if self.tcx.hir().attrs(parent_hir_id).iter().any(|attr| {
|
||||
self.tcx.sess.check_name(attr, sym::automatically_derived)
|
||||
}) {
|
||||
if self
|
||||
.tcx
|
||||
.hir()
|
||||
.attrs(parent_hir_id)
|
||||
.iter()
|
||||
.any(|attr| attr.has_name(sym::automatically_derived))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -3382,9 +3382,8 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
let parse_attrs = || {
|
||||
let attrs = self.cstore().item_attrs(def_id, self.session);
|
||||
let attr = attrs
|
||||
.iter()
|
||||
.find(|a| self.session.check_name(a, sym::rustc_legacy_const_generics))?;
|
||||
let attr =
|
||||
attrs.iter().find(|a| a.has_name(sym::rustc_legacy_const_generics))?;
|
||||
let mut ret = vec![];
|
||||
for meta in attr.meta_item_list()? {
|
||||
match meta.literal()?.kind {
|
||||
|
@ -213,8 +213,6 @@ pub struct Session {
|
||||
/// Set of enabled features for the current target.
|
||||
pub target_features: FxHashSet<Symbol>,
|
||||
|
||||
used_attrs: Lock<MarkedAttrs>,
|
||||
|
||||
/// `Span`s for `if` conditions that we have suggested turning into `if let`.
|
||||
pub if_let_suggestions: Lock<FxHashSet<Span>>,
|
||||
}
|
||||
@ -1066,39 +1064,14 @@ impl Session {
|
||||
== config::InstrumentCoverage::ExceptUnusedFunctions
|
||||
}
|
||||
|
||||
pub fn mark_attr_used(&self, attr: &Attribute) {
|
||||
self.used_attrs.lock().mark(attr)
|
||||
}
|
||||
|
||||
pub fn is_attr_used(&self, attr: &Attribute) -> bool {
|
||||
self.used_attrs.lock().is_marked(attr)
|
||||
}
|
||||
|
||||
/// Returns `true` if the attribute's path matches the argument. If it
|
||||
/// matches, then the attribute is marked as used.
|
||||
///
|
||||
/// This method should only be used by rustc, other tools can use
|
||||
/// `Attribute::has_name` instead, because only rustc is supposed to report
|
||||
/// the `unused_attributes` lint. (`MetaItem` and `NestedMetaItem` are
|
||||
/// produced by lowering an `Attribute` and don't have identity, so they
|
||||
/// only have the `has_name` method, and you need to mark the original
|
||||
/// `Attribute` as used when necessary.)
|
||||
pub fn check_name(&self, attr: &Attribute, name: Symbol) -> bool {
|
||||
let matches = attr.has_name(name);
|
||||
if matches {
|
||||
self.mark_attr_used(attr);
|
||||
}
|
||||
matches
|
||||
}
|
||||
|
||||
pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool {
|
||||
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
|
||||
.iter()
|
||||
.any(|kind| self.check_name(attr, *kind))
|
||||
.any(|kind| attr.has_name(*kind))
|
||||
}
|
||||
|
||||
pub fn contains_name(&self, attrs: &[Attribute], name: Symbol) -> bool {
|
||||
attrs.iter().any(|item| self.check_name(item, name))
|
||||
attrs.iter().any(|item| item.has_name(name))
|
||||
}
|
||||
|
||||
pub fn find_by_name<'a>(
|
||||
@ -1106,7 +1079,7 @@ impl Session {
|
||||
attrs: &'a [Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<&'a Attribute> {
|
||||
attrs.iter().find(|attr| self.check_name(attr, name))
|
||||
attrs.iter().find(|attr| attr.has_name(name))
|
||||
}
|
||||
|
||||
pub fn filter_by_name<'a>(
|
||||
@ -1114,7 +1087,7 @@ impl Session {
|
||||
attrs: &'a [Attribute],
|
||||
name: Symbol,
|
||||
) -> impl Iterator<Item = &'a Attribute> {
|
||||
attrs.iter().filter(move |attr| self.check_name(attr, name))
|
||||
attrs.iter().filter(move |attr| attr.has_name(name))
|
||||
}
|
||||
|
||||
pub fn first_attr_value_str_by_name(
|
||||
@ -1122,7 +1095,7 @@ impl Session {
|
||||
attrs: &[Attribute],
|
||||
name: Symbol,
|
||||
) -> Option<Symbol> {
|
||||
attrs.iter().find(|at| self.check_name(at, name)).and_then(|at| at.value_str())
|
||||
attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
|
||||
}
|
||||
}
|
||||
|
||||
@ -1359,7 +1332,6 @@ pub fn build_session(
|
||||
miri_unleashed_features: Lock::new(Default::default()),
|
||||
asm_arch,
|
||||
target_features: FxHashSet::default(),
|
||||
used_attrs: Lock::new(MarkedAttrs::new()),
|
||||
if_let_suggestions: Default::default(),
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,7 @@ impl SymbolNamesTest<'tcx> {
|
||||
fn process_attrs(&mut self, def_id: LocalDefId) {
|
||||
let tcx = self.tcx;
|
||||
for attr in tcx.get_attrs(def_id.to_def_id()).iter() {
|
||||
if tcx.sess.check_name(attr, SYMBOL_NAME) {
|
||||
if attr.has_name(SYMBOL_NAME) {
|
||||
let def_id = def_id.to_def_id();
|
||||
let instance = Instance::new(
|
||||
def_id,
|
||||
@ -47,7 +47,7 @@ impl SymbolNamesTest<'tcx> {
|
||||
tcx.sess.span_err(attr.span, &format!("demangling({})", demangling));
|
||||
tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling));
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, DEF_PATH) {
|
||||
} else if attr.has_name(DEF_PATH) {
|
||||
let path = with_no_trimmed_paths(|| tcx.def_path_str(def_id.to_def_id()));
|
||||
tcx.sess.span_err(attr.span, &format!("def-path({})", path));
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
//
|
||||
// FIXME? Other potential candidate methods: `as_ref` and
|
||||
// `as_mut`?
|
||||
.any(|a| self.sess().check_name(a, sym::rustc_conversion_suggestion))
|
||||
.any(|a| a.has_name(sym::rustc_conversion_suggestion))
|
||||
});
|
||||
|
||||
methods
|
||||
|
@ -21,6 +21,7 @@ use crate::constrained_generic_params as cgp;
|
||||
use crate::errors;
|
||||
use crate::middle::resolve_lifetime as rl;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_ast::{MetaItemKind, NestedMetaItem};
|
||||
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
|
||||
use rustc_data_structures::captures::Captures;
|
||||
@ -2769,11 +2770,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
let mut link_ordinal_span = None;
|
||||
let mut no_sanitize_span = None;
|
||||
for attr in attrs.iter() {
|
||||
if tcx.sess.check_name(attr, sym::cold) {
|
||||
if attr.has_name(sym::cold) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
|
||||
} else if tcx.sess.check_name(attr, sym::rustc_allocator) {
|
||||
} else if attr.has_name(sym::rustc_allocator) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
||||
} else if tcx.sess.check_name(attr, sym::ffi_returns_twice) {
|
||||
} else if attr.has_name(sym::ffi_returns_twice) {
|
||||
if tcx.is_foreign_item(id) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
|
||||
} else {
|
||||
@ -2786,9 +2787,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::ffi_pure) {
|
||||
} else if attr.has_name(sym::ffi_pure) {
|
||||
if tcx.is_foreign_item(id) {
|
||||
if attrs.iter().any(|a| tcx.sess.check_name(a, sym::ffi_const)) {
|
||||
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
|
||||
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
@ -2810,7 +2811,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::ffi_const) {
|
||||
} else if attr.has_name(sym::ffi_const) {
|
||||
if tcx.is_foreign_item(id) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
|
||||
} else {
|
||||
@ -2823,19 +2824,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::rustc_allocator_nounwind) {
|
||||
} else if attr.has_name(sym::rustc_allocator_nounwind) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
||||
} else if tcx.sess.check_name(attr, sym::naked) {
|
||||
} else if attr.has_name(sym::naked) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
|
||||
} else if tcx.sess.check_name(attr, sym::no_mangle) {
|
||||
} else if attr.has_name(sym::no_mangle) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
|
||||
} else if tcx.sess.check_name(attr, sym::no_coverage) {
|
||||
} else if attr.has_name(sym::no_coverage) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
|
||||
} else if tcx.sess.check_name(attr, sym::rustc_std_internal_symbol) {
|
||||
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||
} else if tcx.sess.check_name(attr, sym::used) {
|
||||
} else if attr.has_name(sym::used) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
|
||||
} else if tcx.sess.check_name(attr, sym::cmse_nonsecure_entry) {
|
||||
} else if attr.has_name(sym::cmse_nonsecure_entry) {
|
||||
if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
@ -2850,15 +2851,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY;
|
||||
} else if tcx.sess.check_name(attr, sym::thread_local) {
|
||||
} else if attr.has_name(sym::thread_local) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
|
||||
} else if tcx.sess.check_name(attr, sym::track_caller) {
|
||||
} else if attr.has_name(sym::track_caller) {
|
||||
if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust {
|
||||
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
|
||||
} else if tcx.sess.check_name(attr, sym::export_name) {
|
||||
} else if attr.has_name(sym::export_name) {
|
||||
if let Some(s) = attr.value_str() {
|
||||
if s.as_str().contains('\0') {
|
||||
// `#[export_name = ...]` will be converted to a null-terminated string,
|
||||
@ -2873,7 +2874,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
}
|
||||
codegen_fn_attrs.export_name = Some(s);
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::target_feature) {
|
||||
} else if attr.has_name(sym::target_feature) {
|
||||
if !tcx.is_closure(id) && tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal {
|
||||
if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
|
||||
// The `#[target_feature]` attribute is allowed on
|
||||
@ -2913,11 +2914,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
&supported_target_features,
|
||||
&mut codegen_fn_attrs.target_features,
|
||||
);
|
||||
} else if tcx.sess.check_name(attr, sym::linkage) {
|
||||
} else if attr.has_name(sym::linkage) {
|
||||
if let Some(val) = attr.value_str() {
|
||||
codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::link_section) {
|
||||
} else if attr.has_name(sym::link_section) {
|
||||
if let Some(val) = attr.value_str() {
|
||||
if val.as_str().bytes().any(|b| b == 0) {
|
||||
let msg = format!(
|
||||
@ -2930,14 +2931,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
codegen_fn_attrs.link_section = Some(val);
|
||||
}
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::link_name) {
|
||||
} else if attr.has_name(sym::link_name) {
|
||||
codegen_fn_attrs.link_name = attr.value_str();
|
||||
} else if tcx.sess.check_name(attr, sym::link_ordinal) {
|
||||
} else if attr.has_name(sym::link_ordinal) {
|
||||
link_ordinal_span = Some(attr.span);
|
||||
if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) {
|
||||
codegen_fn_attrs.link_ordinal = ordinal;
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::no_sanitize) {
|
||||
} else if attr.has_name(sym::no_sanitize) {
|
||||
no_sanitize_span = Some(attr.span);
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list.iter() {
|
||||
@ -2957,7 +2958,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if tcx.sess.check_name(attr, sym::instruction_set) {
|
||||
} else if attr.has_name(sym::instruction_set) {
|
||||
codegen_fn_attrs.instruction_set = match attr.meta().map(|i| i.kind) {
|
||||
Some(MetaItemKind::List(ref items)) => match items.as_slice() {
|
||||
[NestedMetaItem::MetaItem(set)] => {
|
||||
@ -3026,7 +3027,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
None
|
||||
}
|
||||
};
|
||||
} else if tcx.sess.check_name(attr, sym::repr) {
|
||||
} else if attr.has_name(sym::repr) {
|
||||
codegen_fn_attrs.alignment = match attr.meta_item_list() {
|
||||
Some(items) => match items.as_slice() {
|
||||
[item] => match item.name_value_literal() {
|
||||
@ -3064,12 +3065,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
return ia;
|
||||
}
|
||||
match attr.meta().map(|i| i.kind) {
|
||||
Some(MetaItemKind::Word) => {
|
||||
tcx.sess.mark_attr_used(attr);
|
||||
InlineAttr::Hint
|
||||
}
|
||||
Some(MetaItemKind::Word) => InlineAttr::Hint,
|
||||
Some(MetaItemKind::List(ref items)) => {
|
||||
tcx.sess.mark_attr_used(attr);
|
||||
inline_span = Some(attr.span);
|
||||
if items.len() != 1 {
|
||||
struct_span_err!(
|
||||
@ -3112,7 +3109,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
ia
|
||||
}
|
||||
Some(MetaItemKind::List(ref items)) => {
|
||||
tcx.sess.mark_attr_used(attr);
|
||||
inline_span = Some(attr.span);
|
||||
if items.len() != 1 {
|
||||
err(attr.span, "expected one argument");
|
||||
@ -3181,7 +3177,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||
if tcx.is_weak_lang_item(id) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||
}
|
||||
let check_name = |attr, sym| tcx.sess.check_name(attr, sym);
|
||||
let check_name = |attr: &Attribute, sym| attr.has_name(sym);
|
||||
if let Some(name) = weak_lang_items::link_name(check_name, &attrs) {
|
||||
codegen_fn_attrs.export_name = Some(name);
|
||||
codegen_fn_attrs.link_name = Some(name);
|
||||
|
@ -291,7 +291,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
}
|
||||
|
||||
for attr in tcx.get_attrs(main_def_id) {
|
||||
if tcx.sess.check_name(attr, sym::track_caller) {
|
||||
if attr.has_name(sym::track_caller) {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
@ -405,7 +405,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
|
||||
|
||||
let attrs = tcx.hir().attrs(start_id);
|
||||
for attr in attrs {
|
||||
if tcx.sess.check_name(attr, sym::track_caller) {
|
||||
if attr.has_name(sym::track_caller) {
|
||||
tcx.sess
|
||||
.struct_span_err(
|
||||
attr.span,
|
||||
|
@ -4,7 +4,5 @@
|
||||
#![feature(register_tool)]
|
||||
|
||||
#[register_attr(attr)] //~ ERROR crate-level attribute should be an inner attribute
|
||||
//~| ERROR unused attribute
|
||||
#[register_tool(tool)] //~ ERROR crate-level attribute should be an inner attribute
|
||||
//~| ERROR unused attribute
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: unused attribute
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
--> $DIR/register-attr-tool-unused.rs:6:1
|
||||
|
|
||||
LL | #[register_attr(attr)]
|
||||
@ -12,22 +12,10 @@ LL | #![deny(unused)]
|
||||
= note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
|
||||
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
--> $DIR/register-attr-tool-unused.rs:6:1
|
||||
|
|
||||
LL | #[register_attr(attr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/register-attr-tool-unused.rs:8:1
|
||||
--> $DIR/register-attr-tool-unused.rs:7:1
|
||||
|
|
||||
LL | #[register_tool(tool)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
--> $DIR/register-attr-tool-unused.rs:8:1
|
||||
|
|
||||
LL | #[register_tool(tool)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
|
||||
#![deny(unused)]
|
||||
|
||||
#[cfg_attr(FALSE,)] //~ ERROR unused attribute
|
||||
#[cfg_attr(FALSE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes
|
||||
fn _f() {}
|
||||
|
||||
#[cfg_attr(TRUE,)] //~ ERROR unused attribute
|
||||
#[cfg_attr(TRUE,)] //~ ERROR `#[cfg_attr]` does not expand to any attributes
|
||||
fn _g() {}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: unused attribute
|
||||
error: `#[cfg_attr]` does not expand to any attributes
|
||||
--> $DIR/cfg-attr-empty-is-unused.rs:7:1
|
||||
|
|
||||
LL | #[cfg_attr(FALSE,)]
|
||||
@ -11,7 +11,7 @@ LL | #![deny(unused)]
|
||||
| ^^^^^^
|
||||
= note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
|
||||
|
||||
error: unused attribute
|
||||
error: `#[cfg_attr]` does not expand to any attributes
|
||||
--> $DIR/cfg-attr-empty-is-unused.rs:10:1
|
||||
|
|
||||
LL | #[cfg_attr(TRUE,)]
|
||||
|
@ -13,7 +13,6 @@ pub struct ConstDefaultUnstable<const N: usize = 3>;
|
||||
|
||||
#[stable(feature = "const_default_unstable", since="none")]
|
||||
pub struct ConstDefaultStable<const N: usize = {
|
||||
#[stable(feature = "const_default_unstable_val", since="none")]
|
||||
3
|
||||
}>;
|
||||
|
||||
|
@ -49,14 +49,14 @@
|
||||
#![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs)
|
||||
// skipping testing of cfg
|
||||
// skipping testing of cfg_attr
|
||||
#![should_panic] //~ WARN unused attribute
|
||||
#![ignore] //~ WARN unused attribute
|
||||
#![should_panic] //~ WARN `#[should_panic]` only has an effect
|
||||
#![ignore] //~ WARN `#[ignore]` only has an effect on functions
|
||||
#![no_implicit_prelude]
|
||||
#![reexport_test_harness_main = "2900"]
|
||||
// see gated-link-args.rs
|
||||
// see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700"
|
||||
// (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600")
|
||||
#![proc_macro_derive()] //~ WARN unused attribute
|
||||
#![proc_macro_derive()] //~ WARN `#[proc_macro_derive]` only has an effect
|
||||
#![doc = "2400"]
|
||||
#![cold] //~ WARN attribute should be applied to a function
|
||||
//~^ WARN
|
||||
@ -182,35 +182,35 @@ mod macro_use {
|
||||
mod inner { #![macro_use] }
|
||||
|
||||
#[macro_use] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ `#[macro_use]` only has an effect
|
||||
|
||||
#[macro_use] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ `#[macro_use]` only has an effect
|
||||
|
||||
#[macro_use] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ `#[macro_use]` only has an effect
|
||||
|
||||
#[macro_use] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ `#[macro_use]` only has an effect
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_export]` only has an effect on macro definitions
|
||||
mod macro_export {
|
||||
mod inner { #![macro_export] }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_export]` only has an effect on macro definitions
|
||||
|
||||
#[macro_export] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_export]` only has an effect on macro definitions
|
||||
|
||||
#[macro_export] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_export]` only has an effect on macro definitions
|
||||
|
||||
#[macro_export] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_export]` only has an effect on macro definitions
|
||||
|
||||
#[macro_export] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_export]` only has an effect on macro definitions
|
||||
}
|
||||
|
||||
// At time of unit test authorship, if compiling without `--test` then
|
||||
@ -263,35 +263,32 @@ mod path {
|
||||
mod inner { #![path="3800"] }
|
||||
|
||||
#[path = "3800"] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[path]` only has an effect
|
||||
|
||||
#[path = "3800"] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[path]` only has an effect
|
||||
|
||||
#[path = "3800"] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[path]` only has an effect
|
||||
|
||||
#[path = "3800"] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[path]` only has an effect
|
||||
}
|
||||
|
||||
// Don't warn on `automatically_derived` - a custom derive
|
||||
// could reasonally annotate anything that it emits with
|
||||
// this attribute
|
||||
#[automatically_derived]
|
||||
//~^ WARN unused attribute
|
||||
mod automatically_derived {
|
||||
mod inner { #![automatically_derived] }
|
||||
//~^ WARN unused attribute
|
||||
|
||||
#[automatically_derived] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
|
||||
#[automatically_derived] struct S;
|
||||
//~^ WARN unused attribute
|
||||
|
||||
#[automatically_derived] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
|
||||
#[automatically_derived] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -335,79 +332,77 @@ mod no_mangle {
|
||||
}
|
||||
|
||||
#[should_panic]
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[should_panic]` only has an effect on
|
||||
mod should_panic {
|
||||
mod inner { #![should_panic] }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[should_panic]` only has an effect on
|
||||
|
||||
#[should_panic] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
|
||||
#[should_panic] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[should_panic]` only has an effect on
|
||||
|
||||
#[should_panic] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[should_panic]` only has an effect on
|
||||
|
||||
#[should_panic] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[should_panic]` only has an effect on
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[ignore]` only has an effect on functions
|
||||
mod ignore {
|
||||
mod inner { #![ignore] }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[ignore]` only has an effect on functions
|
||||
|
||||
#[ignore] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
|
||||
#[ignore] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[ignore]` only has an effect on functions
|
||||
|
||||
#[ignore] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[ignore]` only has an effect on functions
|
||||
|
||||
#[ignore] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[ignore]` only has an effect on functions
|
||||
}
|
||||
|
||||
#[no_implicit_prelude]
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute
|
||||
mod no_implicit_prelude {
|
||||
mod inner { #![no_implicit_prelude] }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute
|
||||
|
||||
#[no_implicit_prelude] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute
|
||||
|
||||
#[no_implicit_prelude] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute
|
||||
|
||||
#[no_implicit_prelude] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute
|
||||
|
||||
#[no_implicit_prelude] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute
|
||||
}
|
||||
|
||||
#[reexport_test_harness_main = "2900"]
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute should be
|
||||
mod reexport_test_harness_main {
|
||||
mod inner { #![reexport_test_harness_main="2900"] }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute should be
|
||||
|
||||
#[reexport_test_harness_main = "2900"] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute should be
|
||||
|
||||
#[reexport_test_harness_main = "2900"] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute should be
|
||||
|
||||
#[reexport_test_harness_main = "2900"] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute should be
|
||||
|
||||
#[reexport_test_harness_main = "2900"] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN crate-level attribute should be
|
||||
}
|
||||
|
||||
// Cannot feed "2700" to `#[macro_escape]` without signaling an error.
|
||||
@ -419,41 +414,35 @@ mod macro_escape {
|
||||
//~| HELP try an outer attribute: `#[macro_use]`
|
||||
|
||||
#[macro_escape] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_escape]` only has an effect
|
||||
|
||||
#[macro_escape] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_escape]` only has an effect
|
||||
|
||||
#[macro_escape] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_escape]` only has an effect
|
||||
|
||||
#[macro_escape] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN `#[macro_escape]` only has an effect
|
||||
}
|
||||
|
||||
#[no_std]
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod no_std {
|
||||
mod inner { #![no_std] }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be in the root module
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[no_std] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_std] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_std] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_std] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
// At time of authorship, #[proc_macro_derive = "2500"] signals error
|
||||
@ -633,104 +622,80 @@ mod windows_subsystem {
|
||||
// BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
|
||||
|
||||
#[crate_name = "0900"]
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod crate_name {
|
||||
mod inner { #![crate_name="0900"] }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be in the root module
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[crate_name = "0900"] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[crate_name = "0900"] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[crate_name = "0900"] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[crate_name = "0900"] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
#[crate_type = "0800"]
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod crate_type {
|
||||
mod inner { #![crate_type="0800"] }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be in the root module
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[crate_type = "0800"] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[crate_type = "0800"] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[crate_type = "0800"] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[crate_type = "0800"] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
#[feature(x0600)]
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod feature {
|
||||
mod inner { #![feature(x0600)] }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be in the root module
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[feature(x0600)] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[feature(x0600)] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[feature(x0600)] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[feature(x0600)] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
|
||||
#[no_main]
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod no_main_1 {
|
||||
mod inner { #![no_main] }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be in the root module
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[no_main] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_main] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_main] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[no_main] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
#[no_builtins]
|
||||
@ -747,53 +712,41 @@ mod no_builtins {
|
||||
}
|
||||
|
||||
#[recursion_limit="0200"]
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod recursion_limit {
|
||||
mod inner { #![recursion_limit="0200"] }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be in the root module
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[recursion_limit="0200"] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[recursion_limit="0200"] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[recursion_limit="0200"] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[recursion_limit="0200"] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
#[type_length_limit="0100"]
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod type_length_limit {
|
||||
mod inner { #![type_length_limit="0100"] }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be in the root module
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[type_length_limit="0100"] fn f() { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[type_length_limit="0100"] struct S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[type_length_limit="0100"] type T = S;
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
|
||||
#[type_length_limit="0100"] impl S { }
|
||||
//~^ WARN unused attribute
|
||||
//~| WARN crate-level attribute should be an inner attribute
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,7 @@
|
||||
#![deny(unused_attributes)]
|
||||
#![feature(plugin)]
|
||||
|
||||
#[plugin(bla)] //~ ERROR unused attribute
|
||||
//~^ ERROR should be an inner attribute
|
||||
#[plugin(bla)] //~ ERROR should be an inner attribute
|
||||
//~| WARN use of deprecated attribute `plugin`: compiler plugins are deprecated
|
||||
|
||||
fn main() {}
|
||||
|
@ -6,7 +6,7 @@ LL | #[plugin(bla)]
|
||||
|
|
||||
= note: `#[warn(deprecated)]` on by default
|
||||
|
||||
error: unused attribute
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
--> $DIR/invalid-plugin-attr.rs:4:1
|
||||
|
|
||||
LL | #[plugin(bla)]
|
||||
@ -18,11 +18,5 @@ note: the lint level is defined here
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
--> $DIR/invalid-plugin-attr.rs:4:1
|
||||
|
|
||||
LL | #[plugin(bla)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
@ -4,9 +4,7 @@
|
||||
#![deny(unused_attributes)]
|
||||
|
||||
mod a {
|
||||
#![crate_type = "bin"] //~ ERROR unused attribute
|
||||
//~^ ERROR should be in the root module
|
||||
#![crate_type = "bin"] //~ ERROR should be in the root module
|
||||
}
|
||||
|
||||
#[crate_type = "bin"] fn main() {} //~ ERROR unused attribute
|
||||
//~^ ERROR should be an inner
|
||||
#[crate_type = "bin"] fn main() {} //~ ERROR should be an inner
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: unused attribute
|
||||
error: crate-level attribute should be in the root module
|
||||
--> $DIR/lint-misplaced-attr.rs:7:5
|
||||
|
|
||||
LL | #![crate_type = "bin"]
|
||||
@ -10,23 +10,11 @@ note: the lint level is defined here
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: crate-level attribute should be in the root module
|
||||
--> $DIR/lint-misplaced-attr.rs:7:5
|
||||
|
|
||||
LL | #![crate_type = "bin"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/lint-misplaced-attr.rs:11:1
|
||||
|
|
||||
LL | #[crate_type = "bin"] fn main() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
--> $DIR/lint-misplaced-attr.rs:11:1
|
||||
--> $DIR/lint-misplaced-attr.rs:10:1
|
||||
|
|
||||
LL | #[crate_type = "bin"] fn main() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -4,10 +4,9 @@
|
||||
|
||||
// A sample of various built-in attributes.
|
||||
#[macro_export]
|
||||
#[macro_use] //~ ERROR unused attribute
|
||||
#[path="foo"] //~ ERROR unused attribute
|
||||
#[recursion_limit="1"] //~ ERROR unused attribute
|
||||
//~| ERROR crate-level attribute should be an inner attribute
|
||||
#[macro_use] //~ ERROR `#[macro_use]` only has an effect
|
||||
#[path="foo"] //~ ERROR #[path]` only has an effect
|
||||
#[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute
|
||||
macro_rules! foo {
|
||||
() => {};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: unused attribute
|
||||
error: `#[macro_use]` only has an effect on `extern crate` and modules
|
||||
--> $DIR/unused-attr-macro-rules.rs:7:1
|
||||
|
|
||||
LL | #[macro_use]
|
||||
@ -10,23 +10,17 @@ note: the lint level is defined here
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
error: `#[path]` only has an effect on modules
|
||||
--> $DIR/unused-attr-macro-rules.rs:8:1
|
||||
|
|
||||
LL | #[path="foo"]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr-macro-rules.rs:9:1
|
||||
|
|
||||
LL | #[recursion_limit="1"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
--> $DIR/unused-attr-macro-rules.rs:9:1
|
||||
|
|
||||
LL | #[recursion_limit="1"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,49 +0,0 @@
|
||||
#![deny(unused_attributes)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#![rustc_dummy] //~ ERROR unused attribute
|
||||
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
extern crate core;
|
||||
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
use std::collections;
|
||||
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
extern "C" {
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
fn foo();
|
||||
}
|
||||
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
mod foo {
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
pub enum Foo {
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
Bar,
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
fn bar(f: foo::Foo) {
|
||||
match f {
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
foo::Foo::Bar => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
struct Foo {
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
a: isize
|
||||
}
|
||||
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
trait Baz {
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
fn blah(&self);
|
||||
#[rustc_dummy] //~ ERROR unused attribute
|
||||
fn blah2(&self) {}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,98 +0,0 @@
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:4:1
|
||||
|
|
||||
LL | #![rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unused-attr.rs:1:9
|
||||
|
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:6:1
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:9:1
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:12:1
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:14:5
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:18:1
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:20:5
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:22:9
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:27:1
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:30:9
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:35:1
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:37:5
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:41:1
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:43:5
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/unused-attr.rs:45:5
|
||||
|
|
||||
LL | #[rustc_dummy]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user