Replace infallible name_or_empty
methods with fallible name
methods.
I'm removing empty identifiers everywhere, because in practice they always mean "no identifier" rather than "empty identifier". (An empty identifier is impossible.) It's better to use `Option` to mean "no identifier" because you then can't forget about the "no identifier" possibility. Some specifics: - When testing an attribute for a single name, the commit uses the `has_name` method. - When testing an attribute for multiple names, the commit uses the new `has_any_name` method. - When using `match` on an attribute, the match arms now have `Some` on them. In the tests, we now avoid printing empty identifiers by not printing the identifier in the `error:` line at all, instead letting the carets point out the problem.
This commit is contained in:
parent
7e1f2f9c54
commit
2fef0a30ae
40 changed files with 217 additions and 203 deletions
|
@ -305,8 +305,8 @@ impl MetaItem {
|
||||||
if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None }
|
if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_or_empty(&self) -> Symbol {
|
pub fn name(&self) -> Option<Symbol> {
|
||||||
self.ident().unwrap_or_else(Ident::empty).name
|
self.ident().map(|ident| ident.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_name(&self, name: Symbol) -> bool {
|
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> {
|
pub fn ident(&self) -> Option<Ident> {
|
||||||
self.meta_item().and_then(|meta_item| meta_item.ident())
|
self.meta_item().and_then(|meta_item| meta_item.ident())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_or_empty(&self) -> Symbol {
|
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||||
self.ident().unwrap_or_else(Ident::empty).name
|
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`.
|
/// 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;
|
fn id(&self) -> AttrId;
|
||||||
|
|
||||||
/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
|
/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
|
||||||
/// return the name of the attribute, else return the empty identifier.
|
/// return the name of the attribute; otherwise, returns `None`.
|
||||||
fn name_or_empty(&self) -> Symbol {
|
fn name(&self) -> Option<Symbol> {
|
||||||
self.ident().unwrap_or_else(Ident::empty).name
|
self.ident().map(|ident| ident.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the meta item list, `#[attr(meta item list)]`
|
/// 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]`
|
/// Gets the span of the value literal, as string, when using `#[attr = value]`
|
||||||
fn value_span(&self) -> Option<Span>;
|
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>;
|
fn ident(&self) -> Option<Ident>;
|
||||||
|
|
||||||
/// Checks whether the path of this attribute matches the name.
|
/// 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)
|
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
|
/// get the span of the entire attribute
|
||||||
fn span(&self) -> Span;
|
fn span(&self) -> Span;
|
||||||
|
|
||||||
|
@ -813,8 +819,8 @@ impl Attribute {
|
||||||
AttributeExt::id(self)
|
AttributeExt::id(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_or_empty(&self) -> Symbol {
|
pub fn name(&self) -> Option<Symbol> {
|
||||||
AttributeExt::name_or_empty(self)
|
AttributeExt::name(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
|
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
|
||||||
|
@ -846,6 +852,11 @@ impl Attribute {
|
||||||
AttributeExt::has_name(self, name)
|
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 {
|
pub fn span(&self) -> Span {
|
||||||
AttributeExt::span(self)
|
AttributeExt::span(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// create a fake body so that the entire rest of the compiler doesn't have to deal with
|
||||||
// this as a special case.
|
// this as a special case.
|
||||||
return self.lower_fn_body(decl, contract, |this| {
|
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 span = this.lower_span(span);
|
||||||
let empty_block = hir::Block {
|
let empty_block = hir::Block {
|
||||||
hir_id: this.next_id(),
|
hir_id: this.next_id(),
|
||||||
|
|
|
@ -347,7 +347,7 @@ impl<'a> AstValidator<'a> {
|
||||||
sym::forbid,
|
sym::forbid,
|
||||||
sym::warn,
|
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| {
|
.for_each(|attr| {
|
||||||
if attr.is_doc_comment() {
|
if attr.is_doc_comment() {
|
||||||
|
@ -945,8 +945,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
|
||||||
self.check_defaultness(item.span, *defaultness);
|
self.check_defaultness(item.span, *defaultness);
|
||||||
|
|
||||||
let is_intrinsic =
|
let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
|
||||||
item.attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic);
|
|
||||||
if body.is_none() && !is_intrinsic {
|
if body.is_none() && !is_intrinsic {
|
||||||
self.dcx().emit_err(errors::FnWithoutBody {
|
self.dcx().emit_err(errors::FnWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
|
|
|
@ -117,7 +117,7 @@ pub fn eval_condition(
|
||||||
};
|
};
|
||||||
|
|
||||||
match &cfg.kind {
|
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);
|
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||||
let (min_version, span) = match &mis[..] {
|
let (min_version, span) = match &mis[..] {
|
||||||
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
||||||
|
@ -164,18 +164,18 @@ pub fn eval_condition(
|
||||||
|
|
||||||
// The unwraps below may look dangerous, but we've already asserted
|
// The unwraps below may look dangerous, but we've already asserted
|
||||||
// that they won't fail with the loop above.
|
// that they won't fail with the loop above.
|
||||||
match cfg.name_or_empty() {
|
match cfg.name() {
|
||||||
sym::any => mis
|
Some(sym::any) => mis
|
||||||
.iter()
|
.iter()
|
||||||
// We don't use any() here, because we want to evaluate all cfg condition
|
// We don't use any() here, because we want to evaluate all cfg condition
|
||||||
// as eval_condition can (and does) extra checks
|
// as eval_condition can (and does) extra checks
|
||||||
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
||||||
sym::all => mis
|
Some(sym::all) => mis
|
||||||
.iter()
|
.iter()
|
||||||
// We don't use all() here, because we want to evaluate all cfg condition
|
// We don't use all() here, because we want to evaluate all cfg condition
|
||||||
// as eval_condition can (and does) extra checks
|
// as eval_condition can (and does) extra checks
|
||||||
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
||||||
sym::not => {
|
Some(sym::not) => {
|
||||||
let [mi] = mis.as_slice() else {
|
let [mi] = mis.as_slice() else {
|
||||||
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||||
return false;
|
return false;
|
||||||
|
@ -183,7 +183,7 @@ pub fn eval_condition(
|
||||||
|
|
||||||
!eval_condition(mi, sess, features, eval)
|
!eval_condition(mi, sess, features, eval)
|
||||||
}
|
}
|
||||||
sym::target => {
|
Some(sym::target) => {
|
||||||
if let Some(features) = features
|
if let Some(features) = features
|
||||||
&& !features.cfg_target_compact()
|
&& !features.cfg_target_compact()
|
||||||
{
|
{
|
||||||
|
|
|
@ -222,7 +222,7 @@ impl<'sess> AttributeParser<'sess> {
|
||||||
// if we're only looking for a single attribute,
|
// if we're only looking for a single attribute,
|
||||||
// skip all the ones we don't care about
|
// skip all the ones we don't care about
|
||||||
if let Some(expected) = self.parse_only {
|
if let Some(expected) = self.parse_only {
|
||||||
if attr.name_or_empty() != expected {
|
if !attr.has_name(expected) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,7 @@ impl<'sess> AttributeParser<'sess> {
|
||||||
// that's expanded right? But no, sometimes, when parsing attributes on macros,
|
// 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`
|
// we already use the lowering logic and these are still there. So, when `omit_doc`
|
||||||
// is set we *also* want to ignore these
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ impl<'sess> AttributeParser<'sess> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
// // FIXME: make doc attributes go through a proper attribute parser
|
// // 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());
|
// let p = GenericMetaItemParser::from_attr(&n, self.dcx());
|
||||||
//
|
//
|
||||||
// attributes.push(Attribute::Parsed(AttributeKind::DocComment {
|
// attributes.push(Attribute::Parsed(AttributeKind::DocComment {
|
||||||
|
|
|
@ -527,15 +527,14 @@ impl<'a> TraitDef<'a> {
|
||||||
item.attrs
|
item.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|a| {
|
.filter(|a| {
|
||||||
[
|
a.has_any_name(&[
|
||||||
sym::allow,
|
sym::allow,
|
||||||
sym::warn,
|
sym::warn,
|
||||||
sym::deny,
|
sym::deny,
|
||||||
sym::forbid,
|
sym::forbid,
|
||||||
sym::stable,
|
sym::stable,
|
||||||
sym::unstable,
|
sym::unstable,
|
||||||
]
|
])
|
||||||
.contains(&a.name_or_empty())
|
|
||||||
})
|
})
|
||||||
.cloned(),
|
.cloned(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -345,20 +345,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
no_sanitize_span = Some(attr.span());
|
no_sanitize_span = Some(attr.span());
|
||||||
if let Some(list) = attr.meta_item_list() {
|
if let Some(list) = attr.meta_item_list() {
|
||||||
for item in list.iter() {
|
for item in list.iter() {
|
||||||
match item.name_or_empty() {
|
match item.name() {
|
||||||
sym::address => {
|
Some(sym::address) => {
|
||||||
codegen_fn_attrs.no_sanitize |=
|
codegen_fn_attrs.no_sanitize |=
|
||||||
SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
|
SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
|
||||||
}
|
}
|
||||||
sym::cfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
|
Some(sym::cfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI,
|
||||||
sym::kcfi => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
|
Some(sym::kcfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI,
|
||||||
sym::memory => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY,
|
Some(sym::memory) => {
|
||||||
sym::memtag => codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG,
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY
|
||||||
sym::shadow_call_stack => {
|
}
|
||||||
|
Some(sym::memtag) => {
|
||||||
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG
|
||||||
|
}
|
||||||
|
Some(sym::shadow_call_stack) => {
|
||||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK
|
||||||
}
|
}
|
||||||
sym::thread => codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD,
|
Some(sym::thread) => {
|
||||||
sym::hwaddress => {
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD
|
||||||
|
}
|
||||||
|
Some(sym::hwaddress) => {
|
||||||
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
|
codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -419,9 +425,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let attrib_to_write = match meta_item.name_or_empty() {
|
let attrib_to_write = match meta_item.name() {
|
||||||
sym::prefix_nops => &mut prefix,
|
Some(sym::prefix_nops) => &mut prefix,
|
||||||
sym::entry_nops => &mut entry,
|
Some(sym::entry_nops) => &mut entry,
|
||||||
_ => {
|
_ => {
|
||||||
tcx.dcx().emit_err(errors::UnexpectedParameterName {
|
tcx.dcx().emit_err(errors::UnexpectedParameterName {
|
||||||
span: item.span(),
|
span: item.span(),
|
||||||
|
@ -785,8 +791,7 @@ impl<'a> MixedExportNameAndNoMangleState<'a> {
|
||||||
fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
|
fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
|
||||||
let attrs = tcx.get_attrs(id, sym::rustc_autodiff);
|
let attrs = tcx.get_attrs(id, sym::rustc_autodiff);
|
||||||
|
|
||||||
let attrs =
|
let attrs = attrs.filter(|attr| attr.has_name(sym::rustc_autodiff)).collect::<Vec<_>>();
|
||||||
attrs.filter(|attr| attr.name_or_empty() == sym::rustc_autodiff).collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// check for exactly one autodiff attribute on placeholder functions.
|
// check for exactly one autodiff attribute on placeholder functions.
|
||||||
// There should only be one, since we generate a new placeholder per ad macro.
|
// There should only be one, since we generate a new placeholder per ad macro.
|
||||||
|
|
|
@ -824,10 +824,10 @@ impl SyntaxExtension {
|
||||||
return Err(item.span);
|
return Err(item.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
match item.name_or_empty() {
|
match item.name() {
|
||||||
sym::no => Ok(CollapseMacroDebuginfo::No),
|
Some(sym::no) => Ok(CollapseMacroDebuginfo::No),
|
||||||
sym::external => Ok(CollapseMacroDebuginfo::External),
|
Some(sym::external) => Ok(CollapseMacroDebuginfo::External),
|
||||||
sym::yes => Ok(CollapseMacroDebuginfo::Yes),
|
Some(sym::yes) => Ok(CollapseMacroDebuginfo::Yes),
|
||||||
_ => Err(item.path.span),
|
_ => Err(item.path.span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2053,8 +2053,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
) -> Node::OutputTy {
|
) -> Node::OutputTy {
|
||||||
loop {
|
loop {
|
||||||
return match self.take_first_attr(&mut node) {
|
return match self.take_first_attr(&mut node) {
|
||||||
Some((attr, pos, derives)) => match attr.name_or_empty() {
|
Some((attr, pos, derives)) => match attr.name() {
|
||||||
sym::cfg => {
|
Some(sym::cfg) => {
|
||||||
let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos);
|
let (res, meta_item) = self.expand_cfg_true(&mut node, attr, pos);
|
||||||
if res {
|
if res {
|
||||||
continue;
|
continue;
|
||||||
|
@ -2071,7 +2071,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
}
|
}
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
sym::cfg_attr => {
|
Some(sym::cfg_attr) => {
|
||||||
self.expand_cfg_attr(&mut node, &attr, pos);
|
self.expand_cfg_attr(&mut node, &attr, pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2144,8 +2144,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
return match self.take_first_attr(node) {
|
return match self.take_first_attr(node) {
|
||||||
Some((attr, pos, derives)) => match attr.name_or_empty() {
|
Some((attr, pos, derives)) => match attr.name() {
|
||||||
sym::cfg => {
|
Some(sym::cfg) => {
|
||||||
let span = attr.span;
|
let span = attr.span;
|
||||||
if self.expand_cfg_true(node, attr, pos).0 {
|
if self.expand_cfg_true(node, attr, pos).0 {
|
||||||
continue;
|
continue;
|
||||||
|
@ -2154,7 +2154,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
||||||
node.expand_cfg_false(self, pos, span);
|
node.expand_cfg_false(self, pos, span);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sym::cfg_attr => {
|
Some(sym::cfg_attr) => {
|
||||||
self.expand_cfg_attr(node, &attr, pos);
|
self.expand_cfg_attr(node, &attr, pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1237,7 +1237,7 @@ impl AttributeExt for Attribute {
|
||||||
Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => {
|
Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => {
|
||||||
Some((*comment, *kind))
|
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))
|
self.value_str().map(|s| (s, CommentKind::Line))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -1262,8 +1262,8 @@ impl Attribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn name_or_empty(&self) -> Symbol {
|
pub fn name(&self) -> Option<Symbol> {
|
||||||
AttributeExt::name_or_empty(self)
|
AttributeExt::name(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1301,6 +1301,11 @@ impl Attribute {
|
||||||
AttributeExt::has_name(self, name)
|
AttributeExt::has_name(self, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn has_any_name(&self, names: &[Symbol]) -> bool {
|
||||||
|
AttributeExt::has_any_name(self, names)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
AttributeExt::span(self)
|
AttributeExt::span(self)
|
||||||
|
|
|
@ -488,7 +488,7 @@ fn parse_never_type_options_attr(
|
||||||
item.span(),
|
item.span(),
|
||||||
format!(
|
format!(
|
||||||
"unknown or duplicate never type option: `{}` (supported: `fallback`, `diverging_block_default`)",
|
"unknown or duplicate never type option: `{}` (supported: `fallback`, `diverging_block_default`)",
|
||||||
item.name_or_empty()
|
item.name().unwrap()
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
|
||||||
let attrs = self.fcx.tcx.hir_attrs(hir_id);
|
let attrs = self.fcx.tcx.hir_attrs(hir_id);
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if sym::doc == attr.name_or_empty() {
|
if attr.has_name(sym::doc) {
|
||||||
} else if sym::rustc_confusables == attr.name_or_empty() {
|
// do nothing
|
||||||
|
} else if attr.has_name(sym::rustc_confusables) {
|
||||||
let Some(confusables) = attr.meta_item_list() else {
|
let Some(confusables) = attr.meta_item_list() else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -2355,7 +2356,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
for v in values {
|
for v in values {
|
||||||
if v.name_or_empty() != sym::alias {
|
if !v.has_name(sym::alias) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(nested) = v.meta_item_list() {
|
if let Some(nested) = v.meta_item_list() {
|
||||||
|
|
|
@ -93,7 +93,7 @@ incremental_undefined_clean_dirty_assertions =
|
||||||
incremental_undefined_clean_dirty_assertions_item =
|
incremental_undefined_clean_dirty_assertions_item =
|
||||||
clean/dirty auto-assertions not yet defined for Node::Item.node={$kind}
|
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}
|
incremental_unrecognized_depnode = unrecognized `DepNode` variant: {$name}
|
||||||
|
|
||||||
|
|
|
@ -107,11 +107,10 @@ pub(crate) struct NotLoaded<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(incremental_unknown_item)]
|
#[diag(incremental_unknown_rustc_clean_argument)]
|
||||||
pub(crate) struct UnknownItem {
|
pub(crate) struct UnknownRustcCleanArgument {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub name: Symbol,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -405,8 +405,7 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
|
||||||
debug!("check_config: searching for cfg {:?}", value);
|
debug!("check_config: searching for cfg {:?}", value);
|
||||||
cfg = Some(config.contains(&(value, None)));
|
cfg = Some(config.contains(&(value, None)));
|
||||||
} else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) {
|
} else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) {
|
||||||
tcx.dcx()
|
tcx.dcx().emit_err(errors::UnknownRustcCleanArgument { span: item.span() });
|
||||||
.emit_err(errors::UnknownItem { span: attr.span(), name: item.name_or_empty() });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ impl Level {
|
||||||
|
|
||||||
/// Converts an `Attribute` to a level.
|
/// Converts an `Attribute` to a level.
|
||||||
pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option<LintExpectationId>)> {
|
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.
|
/// Converts a `Symbol` to a level.
|
||||||
|
|
|
@ -226,8 +226,8 @@ impl<'tcx> Collector<'tcx> {
|
||||||
let mut wasm_import_module = None;
|
let mut wasm_import_module = None;
|
||||||
let mut import_name_type = None;
|
let mut import_name_type = None;
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
match item.name_or_empty() {
|
match item.name() {
|
||||||
sym::name => {
|
Some(sym::name) => {
|
||||||
if name.is_some() {
|
if name.is_some() {
|
||||||
sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
|
sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
|
||||||
continue;
|
continue;
|
||||||
|
@ -242,7 +242,7 @@ impl<'tcx> Collector<'tcx> {
|
||||||
}
|
}
|
||||||
name = Some((link_name, span));
|
name = Some((link_name, span));
|
||||||
}
|
}
|
||||||
sym::kind => {
|
Some(sym::kind) => {
|
||||||
if kind.is_some() {
|
if kind.is_some() {
|
||||||
sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
|
sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
|
||||||
continue;
|
continue;
|
||||||
|
@ -304,7 +304,7 @@ impl<'tcx> Collector<'tcx> {
|
||||||
};
|
};
|
||||||
kind = Some(link_kind);
|
kind = Some(link_kind);
|
||||||
}
|
}
|
||||||
sym::modifiers => {
|
Some(sym::modifiers) => {
|
||||||
if modifiers.is_some() {
|
if modifiers.is_some() {
|
||||||
sess.dcx()
|
sess.dcx()
|
||||||
.emit_err(errors::MultipleLinkModifiers { span: item.span() });
|
.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()));
|
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
|
||||||
}
|
}
|
||||||
sym::cfg => {
|
Some(sym::cfg) => {
|
||||||
if cfg.is_some() {
|
if cfg.is_some() {
|
||||||
sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
|
sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
|
||||||
continue;
|
continue;
|
||||||
|
@ -346,7 +346,7 @@ impl<'tcx> Collector<'tcx> {
|
||||||
}
|
}
|
||||||
cfg = Some(link_cfg.clone());
|
cfg = Some(link_cfg.clone());
|
||||||
}
|
}
|
||||||
sym::wasm_import_module => {
|
Some(sym::wasm_import_module) => {
|
||||||
if wasm_import_module.is_some() {
|
if wasm_import_module.is_some() {
|
||||||
sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
|
sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
|
||||||
continue;
|
continue;
|
||||||
|
@ -357,7 +357,7 @@ impl<'tcx> Collector<'tcx> {
|
||||||
};
|
};
|
||||||
wasm_import_module = Some((link_wasm_import_module, item.span()));
|
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() {
|
if import_name_type.is_some() {
|
||||||
sess.dcx()
|
sess.dcx()
|
||||||
.emit_err(errors::MultipleImportNameType { span: item.span() });
|
.emit_err(errors::MultipleImportNameType { span: item.span() });
|
||||||
|
|
|
@ -821,7 +821,9 @@ struct AnalyzeAttrState<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> bool {
|
fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> bool {
|
||||||
let mut should_encode = false;
|
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.
|
// Attributes not marked encode-cross-crate don't need to be encoded for downstream crates.
|
||||||
} else if attr.doc_str().is_some() {
|
} else if attr.doc_str().is_some() {
|
||||||
// We keep all doc comments reachable to rustdoc because they might be "imported" into
|
// We keep all doc comments reachable to rustdoc because they might be "imported" into
|
||||||
|
|
|
@ -103,8 +103,9 @@ fn parse_attribute(attr: &Attribute) -> MirPhase {
|
||||||
let mut dialect: Option<String> = None;
|
let mut dialect: Option<String> = None;
|
||||||
let mut phase: 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 {
|
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();
|
let value = nested.value_str().unwrap().as_str().to_string();
|
||||||
match name.as_str() {
|
match name.as_str() {
|
||||||
"dialect" => {
|
"dialect" => {
|
||||||
|
|
|
@ -485,7 +485,7 @@ fn construct_fn<'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(custom_mir_attr) =
|
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(
|
return custom::build_custom_mir(
|
||||||
tcx,
|
tcx,
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
||||||
apply_adjustments: tcx
|
apply_adjustments: tcx
|
||||||
.hir_attrs(hir_id)
|
.hir_attrs(hir_id)
|
||||||
.iter()
|
.iter()
|
||||||
.all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
|
.all(|attr| !attr.has_name(rustc_span::sym::custom_mir)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,9 +144,10 @@ impl RustcMirAttrs {
|
||||||
attr: &ast::MetaItemInner,
|
attr: &ast::MetaItemInner,
|
||||||
mapper: impl FnOnce(Symbol) -> Result<T, ()>,
|
mapper: impl FnOnce(Symbol) -> Result<T, ()>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
|
// Unwrapping the name is safe because this is only called when `has_name` has succeeded.
|
||||||
if field.is_some() {
|
if field.is_some() {
|
||||||
tcx.dcx()
|
tcx.dcx()
|
||||||
.emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name_or_empty() });
|
.emit_err(DuplicateValuesFor { span: attr.span(), name: attr.name().unwrap() });
|
||||||
|
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
@ -156,7 +157,7 @@ impl RustcMirAttrs {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
tcx.dcx()
|
tcx.dcx()
|
||||||
.emit_err(RequiresAnArgument { span: attr.span(), name: attr.name_or_empty() });
|
.emit_err(RequiresAnArgument { span: attr.span(), name: attr.name().unwrap() });
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -404,7 +404,7 @@ passes_invalid_attr_at_crate_level =
|
||||||
passes_invalid_attr_at_crate_level_item =
|
passes_invalid_attr_at_crate_level_item =
|
||||||
the inner attribute doesn't annotate this {$kind}
|
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
|
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
|
.label_orig = any code following this expression is unreachable
|
||||||
.note = this expression has type `{$ty}`, which is uninhabited
|
.note = this expression has type `{$ty}`, which is uninhabited
|
||||||
|
|
||||||
passes_unrecognized_field =
|
passes_unrecognized_argument =
|
||||||
unrecognized field name `{$name}`
|
unrecognized argument
|
||||||
|
|
||||||
passes_unstable_attr_for_already_stable_feature =
|
passes_unstable_attr_for_already_stable_feature =
|
||||||
can't mark as unstable using an already stable feature
|
can't mark as unstable using an already stable feature
|
||||||
|
|
|
@ -9,7 +9,7 @@ use rustc_span::sym;
|
||||||
use rustc_target::callconv::FnAbi;
|
use rustc_target::callconv::FnAbi;
|
||||||
|
|
||||||
use super::layout_test::ensure_wf;
|
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<'_>) {
|
pub fn test_abi(tcx: TyCtxt<'_>) {
|
||||||
if !tcx.features().rustc_attrs() {
|
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.
|
// The `..` are the names of fields to dump.
|
||||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||||
for meta_item in meta_items {
|
for meta_item in meta_items {
|
||||||
match meta_item.name_or_empty() {
|
match meta_item.name() {
|
||||||
sym::debug => {
|
Some(sym::debug) => {
|
||||||
let fn_name = tcx.item_name(item_def_id.into());
|
let fn_name = tcx.item_name(item_def_id.into());
|
||||||
tcx.dcx().emit_err(AbiOf {
|
tcx.dcx().emit_err(AbiOf {
|
||||||
span: tcx.def_span(item_def_id),
|
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();
|
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||||
for meta_item in meta_items {
|
for meta_item in meta_items {
|
||||||
match meta_item.name_or_empty() {
|
match meta_item.name() {
|
||||||
sym::debug => {
|
Some(sym::debug) => {
|
||||||
let ty::FnPtr(sig_tys, hdr) = ty.kind() else {
|
let ty::FnPtr(sig_tys, hdr) = ty.kind() else {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
meta_item.span(),
|
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());
|
let fn_name = tcx.item_name(item_def_id.into());
|
||||||
tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) });
|
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 {
|
let ty::Tuple(fields) = ty.kind() else {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
meta_item.span(),
|
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() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -523,9 +523,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
|
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
|
||||||
if let Some(list) = attr.meta_item_list() {
|
if let Some(list) = attr.meta_item_list() {
|
||||||
for item in list.iter() {
|
for item in list.iter() {
|
||||||
let sym = item.name_or_empty();
|
let sym = item.name();
|
||||||
match sym {
|
match sym {
|
||||||
sym::address | sym::hwaddress => {
|
Some(s @ sym::address | s @ sym::hwaddress) => {
|
||||||
let is_valid =
|
let is_valid =
|
||||||
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
|
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
|
||||||
if !is_valid {
|
if !is_valid {
|
||||||
|
@ -533,7 +533,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
attr_span: item.span(),
|
attr_span: item.span(),
|
||||||
defn_span: span,
|
defn_span: span,
|
||||||
accepted_kind: "a function or static",
|
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(),
|
attr_span: item.span(),
|
||||||
defn_span: span,
|
defn_span: span,
|
||||||
accepted_kind: "a function",
|
accepted_kind: "a function",
|
||||||
attr_str: sym.as_str(),
|
attr_str: &match sym {
|
||||||
|
Some(name) => name.to_string(),
|
||||||
|
None => "...".to_string(),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,7 +595,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
// * `#[track_caller]`
|
// * `#[track_caller]`
|
||||||
// * `#[test]`, `#[ignore]`, `#[should_panic]`
|
// * `#[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] = &[
|
const ALLOW_LIST: &[rustc_span::Symbol] = &[
|
||||||
// conditional compilation
|
// conditional compilation
|
||||||
sym::cfg_trace,
|
sym::cfg_trace,
|
||||||
|
@ -675,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 {
|
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
|
||||||
span: other_attr.span(),
|
span: other_attr.span(),
|
||||||
naked_span: attr.span(),
|
naked_span: attr.span(),
|
||||||
attr: other_attr.name_or_empty(),
|
attr: other_attr.name().unwrap(),
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1153,7 +1157,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
) {
|
) {
|
||||||
match target {
|
match target {
|
||||||
Target::Use | Target::ExternCrate => {
|
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 let Some((prev_inline, prev_span)) = *specified_inline {
|
||||||
if do_inline != prev_inline {
|
if do_inline != prev_inline {
|
||||||
let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
|
let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
|
||||||
|
@ -1263,8 +1267,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) {
|
fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) {
|
||||||
if let Some(metas) = meta.meta_item_list() {
|
if let Some(metas) = meta.meta_item_list() {
|
||||||
for i_meta in metas {
|
for i_meta in metas {
|
||||||
match (i_meta.name_or_empty(), i_meta.meta_item()) {
|
match (i_meta.name(), i_meta.meta_item()) {
|
||||||
(sym::attr | sym::no_crate_inject, _) => {}
|
(Some(sym::attr | sym::no_crate_inject), _) => {}
|
||||||
(_, Some(m)) => {
|
(_, Some(m)) => {
|
||||||
self.tcx.emit_node_span_lint(
|
self.tcx.emit_node_span_lint(
|
||||||
INVALID_DOC_ATTRIBUTES,
|
INVALID_DOC_ATTRIBUTES,
|
||||||
|
@ -1325,61 +1329,63 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
if let Some(list) = attr.meta_item_list() {
|
if let Some(list) = attr.meta_item_list() {
|
||||||
for meta in &list {
|
for meta in &list {
|
||||||
if let Some(i_meta) = meta.meta_item() {
|
if let Some(i_meta) = meta.meta_item() {
|
||||||
match i_meta.name_or_empty() {
|
match i_meta.name() {
|
||||||
sym::alias => {
|
Some(sym::alias) => {
|
||||||
if self.check_attr_not_crate_level(meta, hir_id, "alias") {
|
if self.check_attr_not_crate_level(meta, hir_id, "alias") {
|
||||||
self.check_doc_alias(meta, hir_id, target, aliases);
|
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") {
|
if self.check_attr_not_crate_level(meta, hir_id, "keyword") {
|
||||||
self.check_doc_keyword(meta, hir_id);
|
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") {
|
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
|
||||||
self.check_doc_fake_variadic(meta, hir_id);
|
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") {
|
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
|
||||||
self.check_doc_search_unbox(meta, hir_id);
|
self.check_doc_search_unbox(meta, hir_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::test => {
|
Some(sym::test) => {
|
||||||
if self.check_attr_crate_level(attr, meta, hir_id) {
|
if self.check_attr_crate_level(attr, meta, hir_id) {
|
||||||
self.check_test_attr(meta, hir_id);
|
self.check_test_attr(meta, hir_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(
|
||||||
sym::html_favicon_url
|
sym::html_favicon_url
|
||||||
| sym::html_logo_url
|
| sym::html_logo_url
|
||||||
| sym::html_playground_url
|
| sym::html_playground_url
|
||||||
| sym::issue_tracker_base_url
|
| sym::issue_tracker_base_url
|
||||||
| sym::html_root_url
|
| sym::html_root_url
|
||||||
| sym::html_no_source => {
|
| sym::html_no_source,
|
||||||
|
) => {
|
||||||
self.check_attr_crate_level(attr, meta, hir_id);
|
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) {
|
if self.check_attr_crate_level(attr, meta, hir_id) {
|
||||||
self.check_doc_cfg_hide(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)
|
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)
|
if self.check_attr_crate_level(attr, meta, hir_id)
|
||||||
&& !self.tcx.features().rustdoc_internals()
|
&& !self.tcx.features().rustdoc_internals()
|
||||||
{
|
{
|
||||||
|
@ -2302,7 +2308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
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 {
|
match target {
|
||||||
Target::ExternCrate | Target::Mod => {}
|
Target::ExternCrate | Target::Mod => {}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -2334,12 +2340,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
attr.span(),
|
attr.span(),
|
||||||
errors::MacroExport::TooManyItems,
|
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(
|
self.tcx.emit_node_span_lint(
|
||||||
INVALID_MACRO_EXPORT_ARGUMENTS,
|
INVALID_MACRO_EXPORT_ARGUMENTS,
|
||||||
hir_id,
|
hir_id,
|
||||||
meta_item_list[0].span(),
|
meta_item_list[0].span(),
|
||||||
errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() },
|
errors::MacroExport::InvalidArgument,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2384,33 +2390,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn on useless empty attributes.
|
// Warn on useless empty attributes.
|
||||||
let note = if (matches!(
|
let note = if attr.has_any_name(&[
|
||||||
attr.name_or_empty(),
|
sym::macro_use,
|
||||||
sym::macro_use
|
sym::allow,
|
||||||
| sym::allow
|
sym::expect,
|
||||||
| sym::expect
|
sym::warn,
|
||||||
| sym::warn
|
sym::deny,
|
||||||
| sym::deny
|
sym::forbid,
|
||||||
| sym::forbid
|
sym::feature,
|
||||||
| sym::feature
|
sym::target_feature,
|
||||||
| sym::target_feature
|
]) && attr.meta_item_list().is_some_and(|list| list.is_empty())
|
||||||
) && attr.meta_item_list().is_some_and(|list| list.is_empty()))
|
|
||||||
{
|
{
|
||||||
errors::UnusedNote::EmptyList { name: attr.name_or_empty() }
|
errors::UnusedNote::EmptyList { name: attr.name().unwrap() }
|
||||||
} else if matches!(
|
} else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
|
||||||
attr.name_or_empty(),
|
&& let Some(meta) = attr.meta_item_list()
|
||||||
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
|
|
||||||
) && let Some(meta) = attr.meta_item_list()
|
|
||||||
&& let [meta] = meta.as_slice()
|
&& let [meta] = meta.as_slice()
|
||||||
&& let Some(item) = meta.meta_item()
|
&& let Some(item) = meta.meta_item()
|
||||||
&& let MetaItemKind::NameValue(_) = &item.kind
|
&& let MetaItemKind::NameValue(_) = &item.kind
|
||||||
&& item.path == sym::reason
|
&& item.path == sym::reason
|
||||||
{
|
{
|
||||||
errors::UnusedNote::NoLints { name: attr.name_or_empty() }
|
errors::UnusedNote::NoLints { name: attr.name().unwrap() }
|
||||||
} else if matches!(
|
} else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
|
||||||
attr.name_or_empty(),
|
&& let Some(meta) = attr.meta_item_list()
|
||||||
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
|
|
||||||
) && let Some(meta) = attr.meta_item_list()
|
|
||||||
&& meta.iter().any(|meta| {
|
&& meta.iter().any(|meta| {
|
||||||
meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
|
meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
|
||||||
})
|
})
|
||||||
|
@ -2443,7 +2444,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
return;
|
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
|
errors::UnusedNote::DefaultMethodBodyConst
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -2900,10 +2901,11 @@ fn check_duplicates(
|
||||||
if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() {
|
if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let attr_name = attr.name().unwrap();
|
||||||
match duplicates {
|
match duplicates {
|
||||||
DuplicatesOk => {}
|
DuplicatesOk => {}
|
||||||
WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => {
|
WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => {
|
||||||
match seen.entry(attr.name_or_empty()) {
|
match seen.entry(attr_name) {
|
||||||
Entry::Occupied(mut entry) => {
|
Entry::Occupied(mut entry) => {
|
||||||
let (this, other) = if matches!(duplicates, FutureWarnPreceding) {
|
let (this, other) = if matches!(duplicates, FutureWarnPreceding) {
|
||||||
let to_remove = entry.insert(attr.span());
|
let to_remove = entry.insert(attr.span());
|
||||||
|
@ -2930,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) => {
|
Entry::Occupied(mut entry) => {
|
||||||
let (this, other) = if matches!(duplicates, ErrorPreceding) {
|
let (this, other) = if matches!(duplicates, ErrorPreceding) {
|
||||||
let to_remove = entry.insert(attr.span());
|
let to_remove = entry.insert(attr.span());
|
||||||
|
@ -2938,11 +2940,7 @@ fn check_duplicates(
|
||||||
} else {
|
} else {
|
||||||
(attr.span(), *entry.get())
|
(attr.span(), *entry.get())
|
||||||
};
|
};
|
||||||
tcx.dcx().emit_err(errors::UnusedMultiple {
|
tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name });
|
||||||
this,
|
|
||||||
other,
|
|
||||||
name: attr.name_or_empty(),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Entry::Vacant(entry) => {
|
Entry::Vacant(entry) => {
|
||||||
entry.insert(attr.span());
|
entry.insert(attr.span());
|
||||||
|
|
|
@ -28,10 +28,10 @@ impl DebuggerVisualizerCollector<'_> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let (visualizer_type, visualizer_path) =
|
let (visualizer_type, visualizer_path) = match (meta_item.name(), meta_item.value_str())
|
||||||
match (meta_item.name_or_empty(), meta_item.value_str()) {
|
{
|
||||||
(sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value),
|
(Some(sym::natvis_file), Some(value)) => (DebuggerVisualizerType::Natvis, value),
|
||||||
(sym::gdb_script_file, Some(value)) => {
|
(Some(sym::gdb_script_file), Some(value)) => {
|
||||||
(DebuggerVisualizerType::GdbPrettyPrinter, value)
|
(DebuggerVisualizerType::GdbPrettyPrinter, value)
|
||||||
}
|
}
|
||||||
(_, _) => {
|
(_, _) => {
|
||||||
|
|
|
@ -756,7 +756,7 @@ pub(crate) enum MacroExport {
|
||||||
OnDeclMacro,
|
OnDeclMacro,
|
||||||
|
|
||||||
#[diag(passes_invalid_macro_export_arguments)]
|
#[diag(passes_invalid_macro_export_arguments)]
|
||||||
UnknownItem { name: Symbol },
|
InvalidArgument,
|
||||||
|
|
||||||
#[diag(passes_invalid_macro_export_arguments_too_many_items)]
|
#[diag(passes_invalid_macro_export_arguments_too_many_items)]
|
||||||
TooManyItems,
|
TooManyItems,
|
||||||
|
@ -1045,11 +1045,10 @@ pub(crate) struct AbiInvalidAttribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(passes_unrecognized_field)]
|
#[diag(passes_unrecognized_argument)]
|
||||||
pub(crate) struct UnrecognizedField {
|
pub(crate) struct UnrecognizedArgument {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub name: Symbol,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -13,7 +13,7 @@ use rustc_trait_selection::traits;
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
|
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
|
||||||
LayoutSize, UnrecognizedField,
|
LayoutSize, UnrecognizedArgument,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn test_layout(tcx: TyCtxt<'_>) {
|
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.
|
// The `..` are the names of fields to dump.
|
||||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||||
for meta_item in meta_items {
|
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
|
// FIXME: this never was about ABI and now this dump arg is confusing
|
||||||
sym::abi => {
|
Some(sym::abi) => {
|
||||||
tcx.dcx().emit_err(LayoutAbi {
|
tcx.dcx().emit_err(LayoutAbi {
|
||||||
span,
|
span,
|
||||||
abi: format!("{:?}", ty_layout.backend_repr),
|
abi: format!("{:?}", ty_layout.backend_repr),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::align => {
|
Some(sym::align) => {
|
||||||
tcx.dcx().emit_err(LayoutAlign {
|
tcx.dcx().emit_err(LayoutAlign {
|
||||||
span,
|
span,
|
||||||
align: format!("{:?}", ty_layout.align),
|
align: format!("{:?}", ty_layout.align),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::size => {
|
Some(sym::size) => {
|
||||||
tcx.dcx()
|
tcx.dcx()
|
||||||
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
|
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::homogeneous_aggregate => {
|
Some(sym::homogeneous_aggregate) => {
|
||||||
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
|
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
|
||||||
span,
|
span,
|
||||||
homogeneous_aggregate: format!(
|
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);
|
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
|
||||||
// FIXME: using the `Debug` impl here isn't ideal.
|
// FIXME: using the `Debug` impl here isn't ideal.
|
||||||
let ty_layout = format!("{:#?}", *ty_layout);
|
let ty_layout = format!("{:#?}", *ty_layout);
|
||||||
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, 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() });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1185,6 +1185,7 @@ symbols! {
|
||||||
instruction_set,
|
instruction_set,
|
||||||
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
|
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
|
||||||
integral,
|
integral,
|
||||||
|
internal_features,
|
||||||
into_async_iter_into_iter,
|
into_async_iter_into_iter,
|
||||||
into_future,
|
into_future,
|
||||||
into_iter,
|
into_iter,
|
||||||
|
|
|
@ -788,7 +788,7 @@ impl Item {
|
||||||
}
|
}
|
||||||
_ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)),
|
_ => 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(
|
Some(
|
||||||
rustc_hir_pretty::attribute_to_string(&tcx, attr)
|
rustc_hir_pretty::attribute_to_string(&tcx, attr)
|
||||||
.replace("\\\n", "")
|
.replace("\\\n", "")
|
||||||
|
|
|
@ -412,9 +412,7 @@ pub(crate) fn run_global_ctxt(
|
||||||
// Process all of the crate attributes, extracting plugin metadata along
|
// Process all of the crate attributes, extracting plugin metadata along
|
||||||
// with the passes which we are supposed to run.
|
// with the passes which we are supposed to run.
|
||||||
for attr in krate.module.attrs.lists(sym::doc) {
|
for attr in krate.module.attrs.lists(sym::doc) {
|
||||||
let name = attr.name_or_empty();
|
if attr.is_word() && attr.has_name(sym::document_private_items) {
|
||||||
|
|
||||||
if attr.is_word() && name == sym::document_private_items {
|
|
||||||
ctxt.render_options.document_private = true;
|
ctxt.render_options.document_private = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) -> bool {
|
||||||
let mut is_extern_crate = false;
|
let mut is_extern_crate = false;
|
||||||
if !info.has_global_allocator
|
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;
|
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 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 parsed = parser.parse_item(rustc_parse::parser::ForceCollect::No);
|
||||||
|
|
||||||
let result = match parsed {
|
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 =>
|
&& let Some(ref body) = fn_item.body =>
|
||||||
{
|
{
|
||||||
for attr in &item.attrs {
|
for attr in &item.attrs {
|
||||||
let attr_name = attr.name_or_empty();
|
if attr.style == AttrStyle::Outer || attr.has_any_name(not_crate_attrs) {
|
||||||
|
|
||||||
if attr.style == AttrStyle::Outer || not_crate_attrs.contains(&attr_name) {
|
|
||||||
// There is one exception to these attributes:
|
// There is one exception to these attributes:
|
||||||
// `#![allow(internal_features)]`. If this attribute is used, we need to
|
// `#![allow(internal_features)]`. If this attribute is used, we need to
|
||||||
// consider it only as a crate-level attribute.
|
// 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()
|
&& let Some(list) = attr.meta_item_list()
|
||||||
&& list.iter().any(|sub_attr| {
|
&& list.iter().any(|sub_attr| sub_attr.has_name(sym::internal_features))
|
||||||
sub_attr.name_or_empty().as_str() == "internal_features"
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
|
push_to_s(&mut info.crate_attrs, source, attr.span, &mut prev_span_hi);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -521,23 +521,23 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||||
// Crawl the crate attributes looking for attributes which control how we're
|
// Crawl the crate attributes looking for attributes which control how we're
|
||||||
// going to emit HTML
|
// going to emit HTML
|
||||||
for attr in krate.module.attrs.lists(sym::doc) {
|
for attr in krate.module.attrs.lists(sym::doc) {
|
||||||
match (attr.name_or_empty(), attr.value_str()) {
|
match (attr.name(), attr.value_str()) {
|
||||||
(sym::html_favicon_url, Some(s)) => {
|
(Some(sym::html_favicon_url), Some(s)) => {
|
||||||
layout.favicon = s.to_string();
|
layout.favicon = s.to_string();
|
||||||
}
|
}
|
||||||
(sym::html_logo_url, Some(s)) => {
|
(Some(sym::html_logo_url), Some(s)) => {
|
||||||
layout.logo = s.to_string();
|
layout.logo = s.to_string();
|
||||||
}
|
}
|
||||||
(sym::html_playground_url, Some(s)) => {
|
(Some(sym::html_playground_url), Some(s)) => {
|
||||||
playground = Some(markdown::Playground {
|
playground = Some(markdown::Playground {
|
||||||
crate_name: Some(krate.name(tcx)),
|
crate_name: Some(krate.name(tcx)),
|
||||||
url: s.to_string(),
|
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());
|
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;
|
include_sources = false;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -2363,14 +2363,14 @@ pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
|
||||||
cx.tcx
|
cx.tcx
|
||||||
.hir_attrs(hir::CRATE_HIR_ID)
|
.hir_attrs(hir::CRATE_HIR_ID)
|
||||||
.iter()
|
.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 {
|
pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
|
||||||
cx.tcx
|
cx.tcx
|
||||||
.hir_attrs(hir::CRATE_HIR_ID)
|
.hir_attrs(hir::CRATE_HIR_ID)
|
||||||
.iter()
|
.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.
|
/// Check if parent of a hir node is a trait implementation block.
|
||||||
|
|
|
@ -53,5 +53,5 @@ type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible
|
||||||
#[rustc_abi(assert_eq)]
|
#[rustc_abi(assert_eq)]
|
||||||
type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time
|
type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time
|
||||||
|
|
||||||
#[rustc_abi("assert_eq")] //~ ERROR unrecognized field name ``
|
#[rustc_abi("assert_eq")] //~ ERROR unrecognized argument
|
||||||
type Bad = u32;
|
type Bad = u32;
|
||||||
|
|
|
@ -906,7 +906,7 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str)));
|
||||||
= help: the trait `Sized` is not implemented for `str`
|
= help: the trait `Sized` is not implemented for `str`
|
||||||
= note: only the last element of a tuple may have a dynamically sized type
|
= note: only the last element of a tuple may have a dynamically sized type
|
||||||
|
|
||||||
error: unrecognized field name ``
|
error: unrecognized argument
|
||||||
--> $DIR/debug.rs:56:13
|
--> $DIR/debug.rs:56:13
|
||||||
|
|
|
|
||||||
LL | #[rustc_abi("assert_eq")]
|
LL | #[rustc_abi("assert_eq")]
|
||||||
|
|
|
@ -10,13 +10,13 @@ note: the lint level is defined here
|
||||||
LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))]
|
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
|
--> $DIR/invalid_macro_export_argument.rs:13:16
|
||||||
|
|
|
|
||||||
LL | #[macro_export(not_local_inner_macros)]
|
LL | #[macro_export(not_local_inner_macros)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `` isn't a valid `#[macro_export]` argument
|
error: invalid `#[macro_export]` argument
|
||||||
--> $DIR/invalid_macro_export_argument.rs:33:16
|
--> $DIR/invalid_macro_export_argument.rs:33:16
|
||||||
|
|
|
|
||||||
LL | #[macro_export("blah")]
|
LL | #[macro_export("blah")]
|
||||||
|
|
|
@ -11,7 +11,7 @@ macro_rules! a {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export(not_local_inner_macros)]
|
#[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 {
|
macro_rules! b {
|
||||||
() => ()
|
() => ()
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ macro_rules! e {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export("blah")]
|
#[macro_export("blah")]
|
||||||
//[deny]~^ ERROR `` isn't a valid `#[macro_export]` argument
|
//[deny]~^ ERROR invalid `#[macro_export]` argument
|
||||||
macro_rules! f {
|
macro_rules! f {
|
||||||
() => ()
|
() => ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,6 @@ fn valid() {}
|
||||||
static VALID : i32 = 0;
|
static VALID : i32 = 0;
|
||||||
|
|
||||||
#[no_sanitize("address")]
|
#[no_sanitize("address")]
|
||||||
//~^ ERROR `#[no_sanitize()]` should be applied to a function
|
//~^ ERROR `#[no_sanitize(...)]` should be applied to a function
|
||||||
//~| ERROR invalid argument for `no_sanitize`
|
//~| ERROR invalid argument for `no_sanitize`
|
||||||
static VALID2 : i32 = 0;
|
static VALID2 : i32 = 0;
|
||||||
|
|
|
@ -59,7 +59,7 @@ LL | #[no_sanitize(address, memory)]
|
||||||
LL | static INVALID : i32 = 0;
|
LL | static INVALID : i32 = 0;
|
||||||
| ------------------------- not a function
|
| ------------------------- not a function
|
||||||
|
|
||||||
error: `#[no_sanitize()]` should be applied to a function
|
error: `#[no_sanitize(...)]` should be applied to a function
|
||||||
--> $DIR/no-sanitize.rs:42:15
|
--> $DIR/no-sanitize.rs:42:15
|
||||||
|
|
|
|
||||||
LL | #[no_sanitize("address")]
|
LL | #[no_sanitize("address")]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue