Rollup merge of #139615 - nnethercote:rm-name_or_empty, r=jdonszelmann

Remove `name_or_empty`

Another step towards #137978.

r? ``@jdonszelmann``
This commit is contained in:
Matthias Krüger 2025-04-18 05:16:29 +02:00 committed by GitHub
commit 540fb228af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 309 additions and 226 deletions

View file

@ -305,8 +305,8 @@ impl MetaItem {
if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None }
}
pub fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
pub fn name(&self) -> Option<Symbol> {
self.ident().map(|ident| ident.name)
}
pub fn has_name(&self, name: Symbol) -> bool {
@ -511,13 +511,14 @@ impl MetaItemInner {
}
}
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
/// For a single-segment meta item, returns its identifier; otherwise, returns `None`.
pub fn ident(&self) -> Option<Ident> {
self.meta_item().and_then(|meta_item| meta_item.ident())
}
pub fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
pub fn name(&self) -> Option<Symbol> {
self.ident().map(|ident| ident.name)
}
/// Returns `true` if this list item is a MetaItem with a name of `name`.
@ -738,9 +739,9 @@ pub trait AttributeExt: Debug {
fn id(&self) -> AttrId;
/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
/// return the name of the attribute, else return the empty identifier.
fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
/// return the name of the attribute; otherwise, returns `None`.
fn name(&self) -> Option<Symbol> {
self.ident().map(|ident| ident.name)
}
/// Get the meta item list, `#[attr(meta item list)]`
@ -752,7 +753,7 @@ pub trait AttributeExt: Debug {
/// Gets the span of the value literal, as string, when using `#[attr = value]`
fn value_span(&self) -> Option<Span>;
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
/// For a single-segment attribute, returns its ident; otherwise, returns `None`.
fn ident(&self) -> Option<Ident>;
/// Checks whether the path of this attribute matches the name.
@ -770,6 +771,11 @@ pub trait AttributeExt: Debug {
self.ident().map(|x| x.name == name).unwrap_or(false)
}
#[inline]
fn has_any_name(&self, names: &[Symbol]) -> bool {
names.iter().any(|&name| self.has_name(name))
}
/// get the span of the entire attribute
fn span(&self) -> Span;
@ -813,8 +819,8 @@ impl Attribute {
AttributeExt::id(self)
}
pub fn name_or_empty(&self) -> Symbol {
AttributeExt::name_or_empty(self)
pub fn name(&self) -> Option<Symbol> {
AttributeExt::name(self)
}
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
@ -846,6 +852,11 @@ impl Attribute {
AttributeExt::has_name(self, name)
}
#[inline]
pub fn has_any_name(&self, names: &[Symbol]) -> bool {
AttributeExt::has_any_name(self, names)
}
pub fn span(&self) -> Span {
AttributeExt::span(self)
}

View file

@ -1310,7 +1310,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// create a fake body so that the entire rest of the compiler doesn't have to deal with
// this as a special case.
return self.lower_fn_body(decl, contract, |this| {
if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) {
if attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic)) {
let span = this.lower_span(span);
let empty_block = hir::Block {
hir_id: this.next_id(),

View file

@ -347,7 +347,7 @@ impl<'a> AstValidator<'a> {
sym::forbid,
sym::warn,
];
!arr.contains(&attr.name_or_empty()) && rustc_attr_parsing::is_builtin_attr(*attr)
!attr.has_any_name(&arr) && rustc_attr_parsing::is_builtin_attr(*attr)
})
.for_each(|attr| {
if attr.is_doc_comment() {
@ -947,8 +947,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
self.check_defaultness(item.span, *defaultness);
let is_intrinsic =
item.attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic);
let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
if body.is_none() && !is_intrinsic {
self.dcx().emit_err(errors::FnWithoutBody {
span: item.span,

View file

@ -102,7 +102,7 @@ pub fn eval_condition(
};
match &cfg.kind {
MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
MetaItemKind::List(mis) if cfg.has_name(sym::version) => {
try_gate_cfg(sym::version, cfg.span, sess, features);
let (min_version, span) = match &mis[..] {
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
@ -149,18 +149,18 @@ pub fn eval_condition(
// The unwraps below may look dangerous, but we've already asserted
// that they won't fail with the loop above.
match cfg.name_or_empty() {
sym::any => mis
match cfg.name() {
Some(sym::any) => mis
.iter()
// We don't use any() here, because we want to evaluate all cfg condition
// as eval_condition can (and does) extra checks
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
sym::all => mis
Some(sym::all) => mis
.iter()
// We don't use all() here, because we want to evaluate all cfg condition
// as eval_condition can (and does) extra checks
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
sym::not => {
Some(sym::not) => {
let [mi] = mis.as_slice() else {
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
return false;
@ -168,7 +168,7 @@ pub fn eval_condition(
!eval_condition(mi, sess, features, eval)
}
sym::target => {
Some(sym::target) => {
if let Some(features) = features
&& !features.cfg_target_compact()
{

View file

@ -222,7 +222,7 @@ impl<'sess> AttributeParser<'sess> {
// if we're only looking for a single attribute,
// skip all the ones we don't care about
if let Some(expected) = self.parse_only {
if attr.name_or_empty() != expected {
if !attr.has_name(expected) {
continue;
}
}
@ -232,7 +232,7 @@ impl<'sess> AttributeParser<'sess> {
// that's expanded right? But no, sometimes, when parsing attributes on macros,
// we already use the lowering logic and these are still there. So, when `omit_doc`
// is set we *also* want to ignore these
if omit_doc == OmitDoc::Skip && attr.name_or_empty() == sym::doc {
if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
continue;
}
@ -250,7 +250,7 @@ impl<'sess> AttributeParser<'sess> {
}))
}
// // FIXME: make doc attributes go through a proper attribute parser
// ast::AttrKind::Normal(n) if n.name_or_empty() == sym::doc => {
// ast::AttrKind::Normal(n) if n.has_name(sym::doc) => {
// let p = GenericMetaItemParser::from_attr(&n, self.dcx());
//
// attributes.push(Attribute::Parsed(AttributeKind::DocComment {

View file

@ -527,15 +527,14 @@ impl<'a> TraitDef<'a> {
item.attrs
.iter()
.filter(|a| {
[
a.has_any_name(&[
sym::allow,
sym::warn,
sym::deny,
sym::forbid,
sym::stable,
sym::unstable,
]
.contains(&a.name_or_empty())
])
})
.cloned(),
);

View file

@ -346,20 +346,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
no_sanitize_span = Some(attr.span());
if let Some(list) = attr.meta_item_list() {
for item in list.iter() {
match item.name_or_empty() {
sym::address => {
match item.name() {
Some(sym::address) => {
codegen_fn_attrs.no_sanitize |=
SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
}
sym::cfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
sym::kcfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
sym::memory => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY,
sym::memtag => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG,
sym::shadow_call_stack => {
Some(sym::cfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
Some(sym::kcfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
Some(sym::memory) => {
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY
}
Some(sym::memtag) => {
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG
}
Some(sym::shadow_call_stack) => {
codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK
}
sym::thread => codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD,
sym::hwaddress => {
Some(sym::thread) => {
codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD
}
Some(sym::hwaddress) => {
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
}
_ => {
@ -420,9 +426,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
continue;
};
let attrib_to_write = match meta_item.name_or_empty() {
sym::prefix_nops => &mut prefix,
sym::entry_nops => &mut entry,
let attrib_to_write = match meta_item.name() {
Some(sym::prefix_nops) => &mut prefix,
Some(sym::entry_nops) => &mut entry,
_ => {
tcx.dcx().emit_err(errors::UnexpectedParameterName {
span: item.span(),
@ -786,8 +792,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
let attrs = tcx.get_attrs(id, sym::rustc_autodiff);
let attrs =
attrs.filter(|attr| attr.name_or_empty() == sym::rustc_autodiff).collect::<Vec<_>>();
let attrs = attrs.filter(|attr| attr.has_name(sym::rustc_autodiff)).collect::<Vec<_>>();
// check for exactly one autodiff attribute on placeholder functions.
// There should only be one, since we generate a new placeholder per ad macro.

View file

@ -824,10 +824,10 @@ impl SyntaxExtension {
return Err(item.span);
}
match item.name_or_empty() {
sym::no => Ok(CollapseMacroDebuginfo::No),
sym::external => Ok(CollapseMacroDebuginfo::External),
sym::yes => Ok(CollapseMacroDebuginfo::Yes),
match item.name() {
Some(sym::no) => Ok(CollapseMacroDebuginfo::No),
Some(sym::external) => Ok(CollapseMacroDebuginfo::External),
Some(sym::yes) => Ok(CollapseMacroDebuginfo::Yes),
_ => Err(item.path.span),
}
}

View file

@ -2053,8 +2053,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
) -> Node::OutputTy {
loop {
return match self.take_first_attr(&mut node) {
Some((attr, pos, derives)) => match attr.name_or_empty() {
sym::cfg => {
Some((attr, pos, derives)) => match attr.name() {
Some(sym::cfg) => {
let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos);
if res {
continue;
@ -2071,7 +2071,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
}
Default::default()
}
sym::cfg_attr => {
Some(sym::cfg_attr) => {
self.expand_cfg_attr(&mut node, &attr, pos);
continue;
}
@ -2144,8 +2144,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
) {
loop {
return match self.take_first_attr(node) {
Some((attr, pos, derives)) => match attr.name_or_empty() {
sym::cfg => {
Some((attr, pos, derives)) => match attr.name() {
Some(sym::cfg) => {
let span = attr.span;
if self.expand_cfg_true(node, attr, pos).0 {
continue;
@ -2154,7 +2154,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
node.expand_cfg_false(self, pos, span);
continue;
}
sym::cfg_attr => {
Some(sym::cfg_attr) => {
self.expand_cfg_attr(node, &attr, pos);
continue;
}

View file

@ -1237,7 +1237,7 @@ impl AttributeExt for Attribute {
Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => {
Some((*comment, *kind))
}
Attribute::Unparsed(_) if self.name_or_empty() == sym::doc => {
Attribute::Unparsed(_) if self.has_name(sym::doc) => {
self.value_str().map(|s| (s, CommentKind::Line))
}
_ => None,
@ -1262,8 +1262,8 @@ impl Attribute {
}
#[inline]
pub fn name_or_empty(&self) -> Symbol {
AttributeExt::name_or_empty(self)
pub fn name(&self) -> Option<Symbol> {
AttributeExt::name(self)
}
#[inline]
@ -1301,6 +1301,11 @@ impl Attribute {
AttributeExt::has_name(self, name)
}
#[inline]
pub fn has_any_name(&self, names: &[Symbol]) -> bool {
AttributeExt::has_any_name(self, names)
}
#[inline]
pub fn span(&self) -> Span {
AttributeExt::span(self)

View file

@ -488,7 +488,7 @@ fn parse_never_type_options_attr(
item.span(),
format!(
"unknown or duplicate never type option: `{}` (supported: `fallback`, `diverging_block_default`)",
item.name_or_empty()
item.name().unwrap()
),
);
}

View file

@ -2334,8 +2334,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
let attrs = self.fcx.tcx.hir_attrs(hir_id);
for attr in attrs {
if sym::doc == attr.name_or_empty() {
} else if sym::rustc_confusables == attr.name_or_empty() {
if attr.has_name(sym::doc) {
// do nothing
} else if attr.has_name(sym::rustc_confusables) {
let Some(confusables) = attr.meta_item_list() else {
continue;
};
@ -2355,7 +2356,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
continue;
};
for v in values {
if v.name_or_empty() != sym::alias {
if !v.has_name(sym::alias) {
continue;
}
if let Some(nested) = v.meta_item_list() {

View file

@ -93,7 +93,7 @@ incremental_undefined_clean_dirty_assertions =
incremental_undefined_clean_dirty_assertions_item =
clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
incremental_unknown_item = unknown item `{$name}`
incremental_unknown_rustc_clean_argument = unknown `rustc_clean` argument
incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}

View file

@ -107,11 +107,10 @@ pub(crate) struct NotLoaded<'a> {
}
#[derive(Diagnostic)]
#[diag(incremental_unknown_item)]
pub(crate) struct UnknownItem {
#[diag(incremental_unknown_rustc_clean_argument)]
pub(crate) struct UnknownRustcCleanArgument {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
#[derive(Diagnostic)]

View file

@ -405,8 +405,7 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
debug!("check_config: searching for cfg {:?}", value);
cfg = Some(config.contains(&(value, None)));
} else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) {
tcx.dcx()
.emit_err(errors::UnknownItem { span: attr.span(), name: item.name_or_empty() });
tcx.dcx().emit_err(errors::UnknownRustcCleanArgument { span: item.span() });
}
}

View file

@ -249,7 +249,7 @@ impl Level {
/// Converts an `Attribute` to a level.
pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option<LintExpectationId>)> {
Self::from_symbol(attr.name_or_empty(), || Some(attr.id()))
attr.name().and_then(|name| Self::from_symbol(name, || Some(attr.id())))
}
/// Converts a `Symbol` to a level.

View file

@ -226,8 +226,8 @@ impl<'tcx> Collector<'tcx> {
let mut wasm_import_module = None;
let mut import_name_type = None;
for item in items.iter() {
match item.name_or_empty() {
sym::name => {
match item.name() {
Some(sym::name) => {
if name.is_some() {
sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
continue;
@ -242,7 +242,7 @@ impl<'tcx> Collector<'tcx> {
}
name = Some((link_name, span));
}
sym::kind => {
Some(sym::kind) => {
if kind.is_some() {
sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
continue;
@ -304,7 +304,7 @@ impl<'tcx> Collector<'tcx> {
};
kind = Some(link_kind);
}
sym::modifiers => {
Some(sym::modifiers) => {
if modifiers.is_some() {
sess.dcx()
.emit_err(errors::MultipleLinkModifiers { span: item.span() });
@ -316,7 +316,7 @@ impl<'tcx> Collector<'tcx> {
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
sym::cfg => {
Some(sym::cfg) => {
if cfg.is_some() {
sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
continue;
@ -346,7 +346,7 @@ impl<'tcx> Collector<'tcx> {
}
cfg = Some(link_cfg.clone());
}
sym::wasm_import_module => {
Some(sym::wasm_import_module) => {
if wasm_import_module.is_some() {
sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
continue;
@ -357,7 +357,7 @@ impl<'tcx> Collector<'tcx> {
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
sym::import_name_type => {
Some(sym::import_name_type) => {
if import_name_type.is_some() {
sess.dcx()
.emit_err(errors::MultipleImportNameType { span: item.span() });

View file

@ -821,7 +821,9 @@ struct AnalyzeAttrState<'a> {
#[inline]
fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> bool {
let mut should_encode = false;
if !rustc_feature::encode_cross_crate(attr.name_or_empty()) {
if let Some(name) = attr.name()
&& !rustc_feature::encode_cross_crate(name)
{
// Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
} else if attr.doc_str().is_some() {
// We keep all doc comments reachable to rustdoc because they might be "imported" into

View file

@ -103,8 +103,9 @@ fn parse_attribute(attr: &Attribute) -> MirPhase {
let mut dialect: Option<String> = None;
let mut phase: Option<String> = None;
// Not handling errors properly for this internal attribute; will just abort on errors.
for nested in meta_items {
let name = nested.name_or_empty();
let name = nested.name().unwrap();
let value = nested.value_str().unwrap().as_str().to_string();
match name.as_str() {
"dialect" => {

View file

@ -485,7 +485,7 @@ fn construct_fn<'tcx>(
};
if let Some(custom_mir_attr) =
tcx.hir_attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
tcx.hir_attrs(fn_id).iter().find(|attr| attr.has_name(sym::custom_mir))
{
return custom::build_custom_mir(
tcx,

View file

@ -113,7 +113,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
apply_adjustments: tcx
.hir_attrs(hir_id)
.iter()
.all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
.all(|attr| !attr.has_name(rustc_span::sym::custom_mir)),
}
}

View file

@ -109,27 +109,29 @@ impl RustcMirAttrs {
.flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter()));
for attr in rustc_mir_attrs {
let attr_result = if attr.has_name(sym::borrowck_graphviz_postflow) {
Self::set_field(&mut ret.basename_and_suffix, tcx, &attr, |s| {
let path = PathBuf::from(s.to_string());
match path.file_name() {
Some(_) => Ok(path),
None => {
tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() });
let attr_result = match attr.name() {
Some(name @ sym::borrowck_graphviz_postflow) => {
Self::set_field(&mut ret.basename_and_suffix, tcx, name, &attr, |s| {
let path = PathBuf::from(s.to_string());
match path.file_name() {
Some(_) => Ok(path),
None => {
tcx.dcx().emit_err(PathMustEndInFilename { span: attr.span() });
Err(())
}
}
})
}
Some(name @ sym::borrowck_graphviz_format) => {
Self::set_field(&mut ret.formatter, tcx, name, &attr, |s| match s {
sym::two_phase => Ok(s),
_ => {
tcx.dcx().emit_err(UnknownFormatter { span: attr.span() });
Err(())
}
}
})
} else if attr.has_name(sym::borrowck_graphviz_format) {
Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s {
sym::two_phase => Ok(s),
_ => {
tcx.dcx().emit_err(UnknownFormatter { span: attr.span() });
Err(())
}
})
} else {
Ok(())
})
}
_ => Ok(()),
};
result = result.and(attr_result);
@ -141,12 +143,12 @@ impl RustcMirAttrs {
fn set_field<T>(
field: &mut Option<T>,
tcx: TyCtxt<'_>,
name: Symbol,
attr: &ast::MetaItemInner,
mapper: impl FnOnce(Symbol) -> Result<T, ()>,
) -> Result<(), ()> {
if field.is_some() {
tcx.dcx()
.emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name_or_empty() });
tcx.dcx().emit_err(DuplicateValuesFor { span: attr.span(), name });
return Err(());
}
@ -156,7 +158,7 @@ impl RustcMirAttrs {
Ok(())
} else {
tcx.dcx()
.emit_err(RequiresAnArgument { span: attr.span(), name: attr.name_or_empty() });
.emit_err(RequiresAnArgument { span: attr.span(), name: attr.name().unwrap() });
Err(())
}
}

View file

@ -404,7 +404,7 @@ passes_invalid_attr_at_crate_level =
passes_invalid_attr_at_crate_level_item =
the inner attribute doesn't annotate this {$kind}
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
passes_invalid_macro_export_arguments = invalid `#[macro_export]` argument
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
@ -771,8 +771,8 @@ passes_unreachable_due_to_uninhabited = unreachable {$descr}
.label_orig = any code following this expression is unreachable
.note = this expression has type `{$ty}`, which is uninhabited
passes_unrecognized_field =
unrecognized field name `{$name}`
passes_unrecognized_argument =
unrecognized argument
passes_unstable_attr_for_already_stable_feature =
can't mark as unstable using an already stable feature

View file

@ -9,7 +9,7 @@ use rustc_span::sym;
use rustc_target::callconv::FnAbi;
use super::layout_test::ensure_wf;
use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField};
use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedArgument};
pub fn test_abi(tcx: TyCtxt<'_>) {
if !tcx.features().rustc_attrs() {
@ -77,8 +77,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
// The `..` are the names of fields to dump.
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
match meta_item.name_or_empty() {
sym::debug => {
match meta_item.name() {
Some(sym::debug) => {
let fn_name = tcx.item_name(item_def_id.into());
tcx.dcx().emit_err(AbiOf {
span: tcx.def_span(item_def_id),
@ -88,8 +88,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
});
}
name => {
tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
_ => {
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
}
}
}
@ -118,8 +118,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
}
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
match meta_item.name_or_empty() {
sym::debug => {
match meta_item.name() {
Some(sym::debug) => {
let ty::FnPtr(sig_tys, hdr) = ty.kind() else {
span_bug!(
meta_item.span(),
@ -138,7 +138,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
let fn_name = tcx.item_name(item_def_id.into());
tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) });
}
sym::assert_eq => {
Some(sym::assert_eq) => {
let ty::Tuple(fields) = ty.kind() else {
span_bug!(
meta_item.span(),
@ -188,8 +188,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
});
}
}
name => {
tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
_ => {
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
}
}
}

View file

@ -523,9 +523,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
if let Some(list) = attr.meta_item_list() {
for item in list.iter() {
let sym = item.name_or_empty();
let sym = item.name();
match sym {
sym::address | sym::hwaddress => {
Some(s @ sym::address | s @ sym::hwaddress) => {
let is_valid =
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
if !is_valid {
@ -533,7 +533,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
attr_span: item.span(),
defn_span: span,
accepted_kind: "a function or static",
attr_str: sym.as_str(),
attr_str: s.as_str(),
});
}
}
@ -544,7 +544,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
attr_span: item.span(),
defn_span: span,
accepted_kind: "a function",
attr_str: sym.as_str(),
attr_str: &match sym {
Some(name) => name.to_string(),
None => "...".to_string(),
},
});
}
}
@ -561,12 +564,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
allowed_target: Target,
) {
if target != allowed_target {
let path = attr.path();
let path: Vec<_> = path.iter().map(|s| s.as_str()).collect();
let attr_name = path.join("::");
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span(),
errors::OnlyHasEffectOn {
attr_name: attr.name_or_empty(),
attr_name,
target_name: allowed_target.name().replace(' ', "_"),
},
);
@ -589,7 +595,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// * `#[track_caller]`
// * `#[test]`, `#[ignore]`, `#[should_panic]`
//
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains
// accurate.
const ALLOW_LIST: &[rustc_span::Symbol] = &[
// conditional compilation
sym::cfg_trace,
@ -672,11 +679,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) {
if !other_attr.has_any_name(ALLOW_LIST) {
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
span: other_attr.span(),
naked_span: attr.span(),
attr: other_attr.name_or_empty(),
attr: other_attr.name().unwrap(),
});
return;
@ -1150,7 +1157,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
) {
match target {
Target::Use | Target::ExternCrate => {
let do_inline = meta.name_or_empty() == sym::inline;
let do_inline = meta.has_name(sym::inline);
if let Some((prev_inline, prev_span)) = *specified_inline {
if do_inline != prev_inline {
let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
@ -1260,8 +1267,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) {
if let Some(metas) = meta.meta_item_list() {
for i_meta in metas {
match (i_meta.name_or_empty(), i_meta.meta_item()) {
(sym::attr | sym::no_crate_inject, _) => {}
match (i_meta.name(), i_meta.meta_item()) {
(Some(sym::attr | sym::no_crate_inject), _) => {}
(_, Some(m)) => {
self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
@ -1322,61 +1329,63 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
if let Some(list) = attr.meta_item_list() {
for meta in &list {
if let Some(i_meta) = meta.meta_item() {
match i_meta.name_or_empty() {
sym::alias => {
match i_meta.name() {
Some(sym::alias) => {
if self.check_attr_not_crate_level(meta, hir_id, "alias") {
self.check_doc_alias(meta, hir_id, target, aliases);
}
}
sym::keyword => {
Some(sym::keyword) => {
if self.check_attr_not_crate_level(meta, hir_id, "keyword") {
self.check_doc_keyword(meta, hir_id);
}
}
sym::fake_variadic => {
Some(sym::fake_variadic) => {
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
self.check_doc_fake_variadic(meta, hir_id);
}
}
sym::search_unbox => {
Some(sym::search_unbox) => {
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
self.check_doc_search_unbox(meta, hir_id);
}
}
sym::test => {
Some(sym::test) => {
if self.check_attr_crate_level(attr, meta, hir_id) {
self.check_test_attr(meta, hir_id);
}
}
sym::html_favicon_url
| sym::html_logo_url
| sym::html_playground_url
| sym::issue_tracker_base_url
| sym::html_root_url
| sym::html_no_source => {
Some(
sym::html_favicon_url
| sym::html_logo_url
| sym::html_playground_url
| sym::issue_tracker_base_url
| sym::html_root_url
| sym::html_no_source,
) => {
self.check_attr_crate_level(attr, meta, hir_id);
}
sym::cfg_hide => {
Some(sym::cfg_hide) => {
if self.check_attr_crate_level(attr, meta, hir_id) {
self.check_doc_cfg_hide(meta, hir_id);
}
}
sym::inline | sym::no_inline => {
Some(sym::inline | sym::no_inline) => {
self.check_doc_inline(attr, meta, hir_id, target, specified_inline)
}
sym::masked => self.check_doc_masked(attr, meta, hir_id, target),
Some(sym::masked) => self.check_doc_masked(attr, meta, hir_id, target),
sym::cfg | sym::hidden | sym::notable_trait => {}
Some(sym::cfg | sym::hidden | sym::notable_trait) => {}
sym::rust_logo => {
Some(sym::rust_logo) => {
if self.check_attr_crate_level(attr, meta, hir_id)
&& !self.tcx.features().rustdoc_internals()
{
@ -2299,7 +2308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
let name = attr.name_or_empty();
let name = attr.name().unwrap();
match target {
Target::ExternCrate | Target::Mod => {}
_ => {
@ -2331,12 +2340,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
attr.span(),
errors::MacroExport::TooManyItems,
);
} else if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
} else if !meta_item_list[0].has_name(sym::local_inner_macros) {
self.tcx.emit_node_span_lint(
INVALID_MACRO_EXPORT_ARGUMENTS,
hir_id,
meta_item_list[0].span(),
errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() },
errors::MacroExport::InvalidArgument,
);
}
} else {
@ -2381,33 +2390,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
// Warn on useless empty attributes.
let note = if (matches!(
attr.name_or_empty(),
sym::macro_use
| sym::allow
| sym::expect
| sym::warn
| sym::deny
| sym::forbid
| sym::feature
| sym::target_feature
) && attr.meta_item_list().is_some_and(|list| list.is_empty()))
let note = if attr.has_any_name(&[
sym::macro_use,
sym::allow,
sym::expect,
sym::warn,
sym::deny,
sym::forbid,
sym::feature,
sym::target_feature,
]) && attr.meta_item_list().is_some_and(|list| list.is_empty())
{
errors::UnusedNote::EmptyList { name: attr.name_or_empty() }
} else if matches!(
attr.name_or_empty(),
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
) && let Some(meta) = attr.meta_item_list()
errors::UnusedNote::EmptyList { name: attr.name().unwrap() }
} else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
&& let Some(meta) = attr.meta_item_list()
&& let [meta] = meta.as_slice()
&& let Some(item) = meta.meta_item()
&& let MetaItemKind::NameValue(_) = &item.kind
&& item.path == sym::reason
{
errors::UnusedNote::NoLints { name: attr.name_or_empty() }
} else if matches!(
attr.name_or_empty(),
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
) && let Some(meta) = attr.meta_item_list()
errors::UnusedNote::NoLints { name: attr.name().unwrap() }
} else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
&& let Some(meta) = attr.meta_item_list()
&& meta.iter().any(|meta| {
meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
})
@ -2440,7 +2444,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
return;
}
}
} else if attr.name_or_empty() == sym::default_method_body_is_const {
} else if attr.has_name(sym::default_method_body_is_const) {
errors::UnusedNote::DefaultMethodBodyConst
} else {
return;
@ -2897,10 +2901,11 @@ fn check_duplicates(
if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() {
return;
}
let attr_name = attr.name().unwrap();
match duplicates {
DuplicatesOk => {}
WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => {
match seen.entry(attr.name_or_empty()) {
match seen.entry(attr_name) {
Entry::Occupied(mut entry) => {
let (this, other) = if matches!(duplicates, FutureWarnPreceding) {
let to_remove = entry.insert(attr.span());
@ -2927,7 +2932,7 @@ fn check_duplicates(
}
}
}
ErrorFollowing | ErrorPreceding => match seen.entry(attr.name_or_empty()) {
ErrorFollowing | ErrorPreceding => match seen.entry(attr_name) {
Entry::Occupied(mut entry) => {
let (this, other) = if matches!(duplicates, ErrorPreceding) {
let to_remove = entry.insert(attr.span());
@ -2935,11 +2940,7 @@ fn check_duplicates(
} else {
(attr.span(), *entry.get())
};
tcx.dcx().emit_err(errors::UnusedMultiple {
this,
other,
name: attr.name_or_empty(),
});
tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name });
}
Entry::Vacant(entry) => {
entry.insert(attr.span());

View file

@ -28,17 +28,17 @@ impl DebuggerVisualizerCollector<'_> {
return;
};
let (visualizer_type, visualizer_path) =
match (meta_item.name_or_empty(), meta_item.value_str()) {
(sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value),
(sym::gdb_script_file, Some(value)) => {
(DebuggerVisualizerType::GdbPrettyPrinter, value)
}
(_, _) => {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
return;
}
};
let (visualizer_type, visualizer_path) = match (meta_item.name(), meta_item.value_str())
{
(Some(sym::natvis_file), Some(value)) => (DebuggerVisualizerType::Natvis, value),
(Some(sym::gdb_script_file), Some(value)) => {
(DebuggerVisualizerType::GdbPrettyPrinter, value)
}
(_, _) => {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
return;
}
};
let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) {
Ok(file) => file,

View file

@ -756,7 +756,7 @@ pub(crate) enum MacroExport {
OnDeclMacro,
#[diag(passes_invalid_macro_export_arguments)]
UnknownItem { name: Symbol },
InvalidArgument,
#[diag(passes_invalid_macro_export_arguments_too_many_items)]
TooManyItems,
@ -1045,11 +1045,10 @@ pub(crate) struct AbiInvalidAttribute {
}
#[derive(Diagnostic)]
#[diag(passes_unrecognized_field)]
pub(crate) struct UnrecognizedField {
#[diag(passes_unrecognized_argument)]
pub(crate) struct UnrecognizedArgument {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
#[derive(Diagnostic)]
@ -1433,7 +1432,7 @@ pub(crate) struct UselessAssignment<'a> {
#[derive(LintDiagnostic)]
#[diag(passes_only_has_effect_on)]
pub(crate) struct OnlyHasEffectOn {
pub attr_name: Symbol,
pub attr_name: String,
pub target_name: String,
}

View file

@ -13,7 +13,7 @@ use rustc_trait_selection::traits;
use crate::errors::{
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
LayoutSize, UnrecognizedField,
LayoutSize, UnrecognizedArgument,
};
pub fn test_layout(tcx: TyCtxt<'_>) {
@ -79,28 +79,28 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
// The `..` are the names of fields to dump.
let meta_items = attr.meta_item_list().unwrap_or_default();
for meta_item in meta_items {
match meta_item.name_or_empty() {
match meta_item.name() {
// FIXME: this never was about ABI and now this dump arg is confusing
sym::abi => {
Some(sym::abi) => {
tcx.dcx().emit_err(LayoutAbi {
span,
abi: format!("{:?}", ty_layout.backend_repr),
});
}
sym::align => {
Some(sym::align) => {
tcx.dcx().emit_err(LayoutAlign {
span,
align: format!("{:?}", ty_layout.align),
});
}
sym::size => {
Some(sym::size) => {
tcx.dcx()
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
}
sym::homogeneous_aggregate => {
Some(sym::homogeneous_aggregate) => {
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
span,
homogeneous_aggregate: format!(
@ -111,15 +111,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
});
}
sym::debug => {
Some(sym::debug) => {
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
// FIXME: using the `Debug` impl here isn't ideal.
let ty_layout = format!("{:#?}", *ty_layout);
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
}
name => {
tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
_ => {
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
}
}
}

View file

@ -1186,6 +1186,7 @@ symbols! {
instruction_set,
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
integral,
internal_features,
into_async_iter_into_iter,
into_future,
into_iter,

View file

@ -788,7 +788,7 @@ impl Item {
}
_ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
}
} else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) {
} else if attr.has_any_name(ALLOWED_ATTRIBUTES) {
Some(
rustc_hir_pretty::attribute_to_string(&tcx, attr)
.replace("\\\n", "")

View file

@ -412,9 +412,7 @@ pub(crate) fn run_global_ctxt(
// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
for attr in krate.module.attrs.lists(sym::doc) {
let name = attr.name_or_empty();
if attr.is_word() && name == sym::document_private_items {
if attr.is_word() && attr.has_name(sym::document_private_items) {
ctxt.render_options.document_private = true;
}
}

View file

@ -345,7 +345,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool {
let mut is_extern_crate = false;
if !info.has_global_allocator
&& item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator)
&& item.attrs.iter().any(|attr| attr.has_name(sym::global_allocator))
{
info.has_global_allocator = true;
}
@ -377,7 +377,7 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
}
let mut prev_span_hi = 0;
let not_crate_attrs = [sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect];
let not_crate_attrs = &[sym::forbid, sym::allow, sym::warn, sym::deny, sym::expect];
let parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No);
let result = match parsed {
@ -386,17 +386,13 @@ fn parse_source(source: &str, crate_name: &Option<&str>) -> Result<ParseSourceIn
&& let Some(ref body) = fn_item.body =>
{
for attr in &item.attrs {
let attr_name = attr.name_or_empty();
if attr.style == AttrStyle::Outer || not_crate_attrs.contains(&attr_name) {
if attr.style == AttrStyle::Outer || attr.has_any_name(not_crate_attrs) {
// There is one exception to these attributes:
// `#![allow(internal_features)]`. If this attribute is used, we need to
// consider it only as a crate-level attribute.
if attr_name == sym::allow
if attr.has_name(sym::allow)
&& let Some(list) = attr.meta_item_list()
&& list.iter().any(|sub_attr| {
sub_attr.name_or_empty().as_str() == "internal_features"
})
&& list.iter().any(|sub_attr| sub_attr.has_name(sym::internal_features))
{
push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
} else {

View file

@ -521,23 +521,23 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// Crawl the crate attributes looking for attributes which control how we're
// going to emit HTML
for attr in krate.module.attrs.lists(sym::doc) {
match (attr.name_or_empty(), attr.value_str()) {
(sym::html_favicon_url, Some(s)) => {
match (attr.name(), attr.value_str()) {
(Some(sym::html_favicon_url), Some(s)) => {
layout.favicon = s.to_string();
}
(sym::html_logo_url, Some(s)) => {
(Some(sym::html_logo_url), Some(s)) => {
layout.logo = s.to_string();
}
(sym::html_playground_url, Some(s)) => {
(Some(sym::html_playground_url), Some(s)) => {
playground = Some(markdown::Playground {
crate_name: Some(krate.name(tcx)),
url: s.to_string(),
});
}
(sym::issue_tracker_base_url, Some(s)) => {
(Some(sym::issue_tracker_base_url), Some(s)) => {
issue_tracker_base_url = Some(s.to_string());
}
(sym::html_no_source, None) if attr.is_word() => {
(Some(sym::html_no_source), None) if attr.is_word() => {
include_sources = false;
}
_ => {}

View file

@ -2363,14 +2363,14 @@ pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
.any(|attr| attr.name_or_empty() == sym::no_std)
.any(|attr| attr.has_name(sym::no_std))
}
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
cx.tcx
.hir_attrs(hir::CRATE_HIR_ID)
.iter()
.any(|attr| attr.name_or_empty() == sym::no_core)
.any(|attr| attr.has_name(sym::no_core))
}
/// Check if parent of a hir node is a trait implementation block.

View file

@ -52,3 +52,6 @@ type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible
#[rustc_abi(assert_eq)]
type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time
#[rustc_abi("assert_eq")] //~ ERROR unrecognized argument
type Bad = u32;

View file

@ -906,6 +906,12 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str)));
= help: the trait `Sized` is not implemented for `str`
= note: only the last element of a tuple may have a dynamically sized type
error: unrecognized argument
--> $DIR/debug.rs:56:13
|
LL | #[rustc_abi("assert_eq")]
| ^^^^^^^^^^^
error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions
--> $DIR/debug.rs:29:5
|
@ -1004,6 +1010,6 @@ error: fn_abi_of(assoc_test) = FnAbi {
LL | fn assoc_test(&self) { }
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 11 previous errors
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -39,13 +39,17 @@
// Notably, `should_panic` is a `AttributeType::Normal` attribute that is checked separately.
#![deny(unused_attributes)]
struct Foo {
#[should_panic::skip]
//~^ ERROR failed to resolve
//~| ERROR `#[should_panic::skip]` only has an effect on functions
pub field: u8,
#[should_panic::a::b::c]
//~^ ERROR failed to resolve
//~| ERROR `#[should_panic::a::b::c]` only has an effect on functions
pub field2: u8,
}

View file

@ -1,21 +1,39 @@
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic`
--> $DIR/check-builtin-attr-ice.rs:43:7
--> $DIR/check-builtin-attr-ice.rs:45:7
|
LL | #[should_panic::skip]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic`
--> $DIR/check-builtin-attr-ice.rs:47:7
--> $DIR/check-builtin-attr-ice.rs:50:7
|
LL | #[should_panic::a::b::c]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `deny`
--> $DIR/check-builtin-attr-ice.rs:55:7
--> $DIR/check-builtin-attr-ice.rs:59:7
|
LL | #[deny::skip]
| ^^^^ use of unresolved module or unlinked crate `deny`
error: aborting due to 3 previous errors
error: `#[should_panic::skip]` only has an effect on functions
--> $DIR/check-builtin-attr-ice.rs:45:5
|
LL | #[should_panic::skip]
| ^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/check-builtin-attr-ice.rs:42:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: `#[should_panic::a::b::c]` only has an effect on functions
--> $DIR/check-builtin-attr-ice.rs:50:5
|
LL | #[should_panic::a::b::c]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0433`.

View file

@ -10,11 +10,17 @@ note: the lint level is defined here
LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `not_local_inner_macros` isn't a valid `#[macro_export]` argument
error: invalid `#[macro_export]` argument
--> $DIR/invalid_macro_export_argument.rs:13:16
|
LL | #[macro_export(not_local_inner_macros)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: invalid `#[macro_export]` argument
--> $DIR/invalid_macro_export_argument.rs:33:16
|
LL | #[macro_export("blah")]
| ^^^^^^
error: aborting due to 3 previous errors

View file

@ -11,7 +11,7 @@ macro_rules! a {
}
#[macro_export(not_local_inner_macros)]
//[deny]~^ ERROR `not_local_inner_macros` isn't a valid `#[macro_export]` argument
//[deny]~^ ERROR invalid `#[macro_export]` argument
macro_rules! b {
() => ()
}
@ -30,4 +30,10 @@ macro_rules! e {
() => ()
}
#[macro_export("blah")]
//[deny]~^ ERROR invalid `#[macro_export]` argument
macro_rules! f {
() => ()
}
fn main() {}

View file

@ -38,3 +38,8 @@ fn valid() {}
#[no_sanitize(address)]
static VALID : i32 = 0;
#[no_sanitize("address")]
//~^ ERROR `#[no_sanitize(...)]` should be applied to a function
//~| ERROR invalid argument for `no_sanitize`
static VALID2 : i32 = 0;

View file

@ -59,5 +59,22 @@ LL | #[no_sanitize(address, memory)]
LL | static INVALID : i32 = 0;
| ------------------------- not a function
error: aborting due to 7 previous errors
error: `#[no_sanitize(...)]` should be applied to a function
--> $DIR/no-sanitize.rs:42:15
|
LL | #[no_sanitize("address")]
| ^^^^^^^^^
...
LL | static VALID2 : i32 = 0;
| ------------------------ not a function
error: invalid argument for `no_sanitize`
--> $DIR/no-sanitize.rs:42:15
|
LL | #[no_sanitize("address")]
| ^^^^^^^^^
|
= note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
error: aborting due to 9 previous errors