Auto merge of #150700 - Kobzol:rollup-02y1lh9, r=Kobzol

Rollup of 3 pull requests

Successful merges:

 - rust-lang/rust#149790 (Remove `Span` from segments of `AttrPath`)
 - rust-lang/rust#150384 (Tidying up tests/ui/issues 16 tests [7/N])
 - rust-lang/rust#150697 (relate.rs: tiny cleanup: eliminate temp vars 2)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2026-01-05 18:13:45 +00:00
commit 4fa80a5e73
56 changed files with 218 additions and 224 deletions

View file

@ -96,11 +96,11 @@ impl AttributeExt for Attribute {
}
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
fn ident(&self) -> Option<Ident> {
fn name(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::Normal(normal) => {
if let [ident] = &*normal.item.path.segments {
Some(ident.ident)
Some(ident.ident.name)
} else {
None
}
@ -109,9 +109,18 @@ impl AttributeExt for Attribute {
}
}
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
fn symbol_path(&self) -> Option<SmallVec<[Symbol; 1]>> {
match &self.kind {
AttrKind::Normal(p) => Some(p.item.path.segments.iter().map(|i| i.ident).collect()),
AttrKind::Normal(p) => {
Some(p.item.path.segments.iter().map(|i| i.ident.name).collect())
}
AttrKind::DocComment(_, _) => None,
}
}
fn path_span(&self) -> Option<Span> {
match &self.kind {
AttrKind::Normal(attr) => Some(attr.item.path.span),
AttrKind::DocComment(_, _) => None,
}
}
@ -794,9 +803,7 @@ pub trait AttributeExt: Debug {
/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
/// return the name of the attribute; otherwise, returns `None`.
fn name(&self) -> Option<Symbol> {
self.ident().map(|ident| ident.name)
}
fn name(&self) -> Option<Symbol>;
/// Get the meta item list, `#[attr(meta item list)]`
fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>>;
@ -807,9 +814,6 @@ 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 ident; otherwise, returns `None`.
fn ident(&self) -> Option<Ident>;
/// Checks whether the path of this attribute matches the name.
///
/// Matches one segment of the path to each element in `name`
@ -822,7 +826,7 @@ pub trait AttributeExt: Debug {
#[inline]
fn has_name(&self, name: Symbol) -> bool {
self.ident().map(|x| x.name == name).unwrap_or(false)
self.name().map(|x| x == name).unwrap_or(false)
}
#[inline]
@ -836,13 +840,13 @@ pub trait AttributeExt: Debug {
fn is_word(&self) -> bool;
fn path(&self) -> SmallVec<[Symbol; 1]> {
self.ident_path()
.map(|i| i.into_iter().map(|i| i.name).collect())
.unwrap_or(smallvec![sym::doc])
self.symbol_path().unwrap_or(smallvec![sym::doc])
}
fn path_span(&self) -> Option<Span>;
/// Returns None for doc comments
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>>;
fn symbol_path(&self) -> Option<SmallVec<[Symbol; 1]>>;
/// Returns the documentation if this is a doc comment or a sugared doc comment.
/// * `///doc` returns `Some("doc")`.
@ -903,10 +907,6 @@ impl Attribute {
AttributeExt::value_span(self)
}
pub fn ident(&self) -> Option<Ident> {
AttributeExt::ident(self)
}
pub fn path_matches(&self, name: &[Symbol]) -> bool {
AttributeExt::path_matches(self, name)
}
@ -938,10 +938,6 @@ impl Attribute {
AttributeExt::path(self)
}
pub fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
AttributeExt::ident_path(self)
}
pub fn doc_str(&self) -> Option<Symbol> {
AttributeExt::doc_str(self)
}

View file

@ -160,7 +160,7 @@ impl<'a> PostExpansionVisitor<'a> {
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
let attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name));
// Check feature gates for built-in attributes.
if let Some(BuiltinAttribute {
gate: AttributeGate::Gated { feature, message, check, notes, .. },

View file

@ -371,13 +371,7 @@ fn parse_cfg_attr_internal<'a>(
attribute.span,
attribute.get_normal_item().span(),
attribute.style,
AttrPath {
segments: attribute
.ident_path()
.expect("cfg_attr is not a doc comment")
.into_boxed_slice(),
span: attribute.span,
},
AttrPath { segments: attribute.path().into_boxed_slice(), span: attribute.span },
Some(attribute.get_normal_item().unsafety),
ParsedDescription::Attribute,
pred_span,

View file

@ -7,7 +7,7 @@ use rustc_hir::attrs::CfgEntry;
use rustc_parse::exp;
use rustc_parse::parser::Parser;
use rustc_session::Session;
use rustc_span::{ErrorGuaranteed, Ident, Span};
use rustc_span::{ErrorGuaranteed, Span, sym};
use crate::parser::MetaItemOrLitParser;
use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry};
@ -86,10 +86,7 @@ pub fn parse_cfg_select(
cfg_span,
cfg_span,
AttrStyle::Inner,
AttrPath {
segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(),
span: cfg_span,
},
AttrPath { segments: vec![sym::cfg_select].into_boxed_slice(), span: cfg_span },
None,
ParsedDescription::Macro,
cfg_span,

View file

@ -28,8 +28,7 @@ pub fn parse_version(s: Symbol) -> Option<RustcVersion> {
}
pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
attr.is_doc_comment().is_some()
|| attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
attr.is_doc_comment().is_some() || attr.name().is_some_and(|name| is_builtin_attr_name(name))
}
/// Parse a single integer.

View file

@ -36,7 +36,7 @@ pub type RefPathParser<'p> = PathParser<&'p Path>;
impl<P: Borrow<Path>> PathParser<P> {
pub fn get_attribute_path(&self) -> hir::AttrPath {
AttrPath {
segments: self.segments().copied().collect::<Vec<_>>().into_boxed_slice(),
segments: self.segments().map(|s| s.name).collect::<Vec<_>>().into_boxed_slice(),
span: self.span(),
}
}

View file

@ -22,7 +22,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
return;
}
let name = (attr_path.segments.len() == 1).then_some(attr_path.segments[0].name);
let name = (attr_path.segments.len() == 1).then_some(attr_path.segments[0]);
if let Some(name) = name
&& [sym::cfg_trace, sym::cfg_attr_trace].contains(&name)
{

View file

@ -104,7 +104,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
let name = cx.attr_path.clone();
let lint = if name.segments[0].name == sym::deprecated
let lint = if name.segments[0] == sym::deprecated
&& ![
Target::Closure,
Target::Expression,

View file

@ -27,7 +27,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
return;
}
let builtin_attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
let builtin_attr_info = attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name));
// Check input tokens for built-in and key-value attributes.
match builtin_attr_info {

View file

@ -13,7 +13,7 @@ use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpa
use rustc_hir::AttrPath;
use rustc_hir::attrs::CfgEntry;
use rustc_parse::exp;
use rustc_span::{ErrorGuaranteed, Ident, Span};
use rustc_span::{ErrorGuaranteed, Span, sym};
use crate::errors;
@ -47,7 +47,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
span,
span,
AttrStyle::Inner,
AttrPath { segments: vec![Ident::from_str("cfg")].into_boxed_slice(), span },
AttrPath { segments: vec![sym::cfg].into_boxed_slice(), span },
None,
ParsedDescription::Macro,
span,

View file

@ -47,10 +47,7 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
impl<'ast> visit::Visitor<'ast> for CfgFinder {
type Result = ControlFlow<()>;
fn visit_attribute(&mut self, attr: &'ast Attribute) -> ControlFlow<()> {
if attr
.ident()
.is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
{
if attr.name().is_some_and(|name| name == sym::cfg || name == sym::cfg_attr) {
ControlFlow::Break(())
} else {
ControlFlow::Continue(())

View file

@ -16,7 +16,7 @@ use rustc_middle::span_bug;
use rustc_middle::ty::{self as ty, Instance, TyCtxt};
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::{Ident, Span, Symbol, sym};
use rustc_span::{Span, Symbol, sym};
use rustc_target::spec::Os;
use crate::errors;
@ -327,7 +327,7 @@ fn process_builtin_attrs(
}
}
let Some(Ident { name, .. }) = attr.ident() else {
let Some(name) = attr.name() else {
continue;
};

View file

@ -2110,7 +2110,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
let mut attr_pos = None;
for (pos, attr) in item.attrs().iter().enumerate() {
if !attr.is_doc_comment() && !self.cx.expanded_inert_attrs.is_marked(attr) {
let name = attr.ident().map(|ident| ident.name);
let name = attr.name();
if name == Some(sym::cfg) || name == Some(sym::cfg_attr) {
cfg_pos = Some(pos); // a cfg attr found, no need to search anymore
break;
@ -2187,7 +2187,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
} else if rustc_attr_parsing::is_builtin_attr(attr)
&& !AttributeParser::<Early>::is_parsed_attribute(&attr.path())
{
let attr_name = attr.ident().unwrap().name;
let attr_name = attr.name().unwrap();
// `#[cfg]` and `#[cfg_attr]` are special - they are
// eagerly evaluated.
if attr_name != sym::cfg_trace && attr_name != sym::cfg_attr_trace {

View file

@ -1199,7 +1199,7 @@ pub enum AttrArgs {
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable)]
pub struct AttrPath {
pub segments: Box<[Ident]>,
pub segments: Box<[Symbol]>,
pub span: Span,
}
@ -1215,7 +1215,7 @@ impl AttrPath {
segments: path
.segments
.iter()
.map(|i| Ident { name: i.ident.name, span: lower_span(i.ident.span) })
.map(|i| i.ident.name)
.collect::<Vec<_>>()
.into_boxed_slice(),
span: lower_span(path.span),
@ -1225,7 +1225,11 @@ impl AttrPath {
impl fmt::Display for AttrPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", join_path_idents(&self.segments))
write!(
f,
"{}",
join_path_idents(self.segments.iter().map(|i| Ident { name: *i, span: DUMMY_SP }))
)
}
}
@ -1330,7 +1334,7 @@ impl AttributeExt for Attribute {
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
#[inline]
fn ident(&self) -> Option<Ident> {
fn name(&self) -> Option<Symbol> {
match &self {
Attribute::Unparsed(n) => {
if let [ident] = n.path.segments.as_ref() {
@ -1346,7 +1350,7 @@ impl AttributeExt for Attribute {
#[inline]
fn path_matches(&self, name: &[Symbol]) -> bool {
match &self {
Attribute::Unparsed(n) => n.path.segments.iter().map(|ident| &ident.name).eq(name),
Attribute::Unparsed(n) => n.path.segments.iter().eq(name),
_ => false,
}
}
@ -1382,13 +1386,20 @@ impl AttributeExt for Attribute {
}
#[inline]
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
fn symbol_path(&self) -> Option<SmallVec<[Symbol; 1]>> {
match &self {
Attribute::Unparsed(n) => Some(n.path.segments.iter().copied().collect()),
_ => None,
}
}
fn path_span(&self) -> Option<Span> {
match &self {
Attribute::Unparsed(attr) => Some(attr.path.span),
Attribute::Parsed(_) => None,
}
}
#[inline]
fn doc_str(&self) -> Option<Symbol> {
match &self {
@ -1468,11 +1479,6 @@ impl Attribute {
AttributeExt::value_span(self)
}
#[inline]
pub fn ident(&self) -> Option<Ident> {
AttributeExt::ident(self)
}
#[inline]
pub fn path_matches(&self, name: &[Symbol]) -> bool {
AttributeExt::path_matches(self, name)
@ -1508,11 +1514,6 @@ impl Attribute {
AttributeExt::path(self)
}
#[inline]
pub fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
AttributeExt::ident_path(self)
}
#[inline]
pub fn doc_str(&self) -> Option<Symbol> {
AttributeExt::doc_str(self)

View file

@ -22,7 +22,7 @@ use rustc_hir::{
TyPatKind,
};
use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, Ident, Span, Symbol, kw, sym};
use rustc_span::{DUMMY_SP, FileName, Ident, Span, Symbol, kw, sym};
use {rustc_ast as ast, rustc_hir as hir};
pub fn id_to_string(cx: &dyn rustc_hir::intravisit::HirTyCtxt<'_>, hir_id: HirId) -> String {
@ -136,7 +136,11 @@ impl<'a> State<'a> {
.path
.segments
.iter()
.map(|i| ast::PathSegment { ident: *i, args: None, id: DUMMY_NODE_ID })
.map(|i| ast::PathSegment {
ident: Ident { name: *i, span: DUMMY_SP },
args: None,
id: DUMMY_NODE_ID,
})
.collect(),
tokens: None,
};

View file

@ -86,9 +86,9 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool {
// NOTE: Builtin attributes like `cfg` and `cfg_attr` cannot be renamed via imports.
// Therefore, the absence of a literal `cfg` or `cfg_attr` guarantees that
// we don't need to do any eager expansion.
attrs.iter().any(|attr| {
attr.ident().is_some_and(|ident| ident.name == sym::cfg || ident.name == sym::cfg_attr)
})
attrs
.iter()
.any(|attr| attr.name().is_some_and(|ident| ident == sym::cfg || ident == sym::cfg_attr))
}
impl<'a> Parser<'a> {
@ -398,10 +398,8 @@ impl<'a> Parser<'a> {
/// - any single-segment, non-builtin attributes are present, e.g. `derive`,
/// `test`, `global_allocator`.
fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
attrs.iter().any(|attr| match attr.ident() {
attrs.iter().any(|attr| match attr.name() {
None => !attr.is_doc_comment(),
Some(ident) => {
ident.name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(ident.name)
}
Some(name) => name == sym::cfg_attr || !rustc_feature::is_builtin_attr_name(name),
})
}

View file

@ -391,7 +391,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
attr.path
.segments
.first()
.and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
.and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name))
{
match attr.style {
ast::AttrStyle::Outer => {
@ -428,7 +428,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
if let Attribute::Unparsed(unparsed_attr) = attr
&& let Some(BuiltinAttribute { duplicates, .. }) =
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name))
{
check_duplicates(
self.tcx,

View file

@ -24,7 +24,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for [hir::Attribute] {
.filter(|attr| {
attr.is_doc_comment().is_none()
// FIXME(jdonszelmann) have a better way to handle ignored attrs
&& !attr.ident().is_some_and(|ident| hcx.is_ignored_attr(ident.name))
&& !attr.name().is_some_and(|ident| hcx.is_ignored_attr(ident))
})
.collect();

View file

@ -216,11 +216,7 @@ impl<I: Interner> Relate<I> for ty::AliasTy<I> {
b: ty::AliasTy<I>,
) -> RelateResult<I, ty::AliasTy<I>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(a, b)
}))
Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.def_id, b.def_id)))
} else {
let cx = relation.cx();
let args = if let Some(variances) = cx.opt_alias_variances(a.kind(cx), a.def_id) {
@ -240,11 +236,7 @@ impl<I: Interner> Relate<I> for ty::AliasTerm<I> {
b: ty::AliasTerm<I>,
) -> RelateResult<I, ty::AliasTerm<I>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(a, b)
}))
Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.def_id, b.def_id)))
} else {
let args = match a.kind(relation.cx()) {
ty::AliasTermKind::OpaqueTy => relate_args_with_variances(
@ -275,11 +267,7 @@ impl<I: Interner> Relate<I> for ty::ExistentialProjection<I> {
b: ty::ExistentialProjection<I>,
) -> RelateResult<I, ty::ExistentialProjection<I>> {
if a.def_id != b.def_id {
Err(TypeError::ProjectionMismatched({
let a = a.def_id;
let b = b.def_id;
ExpectedFound::new(a, b)
}))
Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.def_id, b.def_id)))
} else {
let term = relation.relate_with_variance(
ty::Invariant,

View file

@ -859,8 +859,8 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
}
continue;
} else if !cfg_info.parent_is_doc_cfg
&& let Some(ident) = attr.ident()
&& matches!(ident.name, sym::cfg | sym::cfg_trace)
&& let Some(name) = attr.name()
&& matches!(name, sym::cfg | sym::cfg_trace)
&& let Some(attr) = single(attr.meta_item_list()?)
&& let Ok(new_cfg) = Cfg::parse(&attr)
{

View file

@ -2682,8 +2682,8 @@ fn add_without_unwanted_attributes<'hir>(
import_parent,
));
}
hir::Attribute::Unparsed(normal) if let [ident] = &*normal.path.segments => {
if is_inline || ident.name != sym::cfg_trace {
hir::Attribute::Unparsed(normal) if let [name] = &*normal.path.segments => {
if is_inline || *name != sym::cfg_trace {
// If it's not a `cfg()` attribute, we keep it.
attrs.push((Cow::Borrowed(attr), import_parent));
}

View file

@ -40,8 +40,8 @@ fn add_only_cfg_attributes(attrs: &mut Vec<Attribute>, new_attrs: &[Attribute])
new_attr.cfg = d.cfg.clone();
attrs.push(Attribute::Parsed(AttributeKind::Doc(Box::new(new_attr))));
} else if let Attribute::Unparsed(normal) = attr
&& let [ident] = &*normal.path.segments
&& ident.name == sym::cfg_trace
&& let [name] = &*normal.path.segments
&& *name == sym::cfg_trace
{
// If it's a `cfg()` attribute, we keep it.
attrs.push(attr.clone());

View file

@ -4,18 +4,19 @@ use clippy_utils::is_from_proc_macro;
use rustc_ast::{AttrStyle, Attribute};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, LintContext};
use rustc_ast::attr::AttributeExt;
// Separate each crate's features.
pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) {
if !attr.span.in_external_macro(cx.sess().source_map())
&& let AttrStyle::Outer = attr.style
&& let Some(ident) = attr.ident()
&& let Some(path_span) = attr.path_span()
&& !is_from_proc_macro(cx, attr)
{
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, ALLOW_ATTRIBUTES, ident.span, "#[allow] attribute found", |diag| {
span_lint_and_then(cx, ALLOW_ATTRIBUTES, path_span, "#[allow] attribute found", |diag| {
diag.span_suggestion(
ident.span,
path_span,
"replace it with",
"expect",
Applicability::MachineApplicable,

View file

@ -574,16 +574,16 @@ impl EarlyLintPass for PostExpansionEarlyAttributes {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
if let Some(items) = &attr.meta_item_list()
&& let Some(ident) = attr.ident()
&& let Some(name) = attr.name()
{
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
if matches!(name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
allow_attributes::check(cx, attr);
}
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
allow_attributes_without_reason::check(cx, ident.name, items, attr);
if matches!(name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
allow_attributes_without_reason::check(cx, name, items, attr);
}
if is_lint_level(ident.name, attr.id) {
blanket_clippy_restriction_lints::check(cx, ident.name, items);
if is_lint_level(name, attr.id) {
blanket_clippy_restriction_lints::check(cx, name, items);
}
if items.is_empty() || !attr.has_name(sym::deprecated) {
return;

View file

@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
return;
}
if let Some(lint_list) = &attr.meta_item_list()
&& attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id))
&& attr.name().is_some_and(|name| is_lint_level(name, attr.id))
{
for lint in lint_list {
match item.kind {

View file

@ -270,7 +270,7 @@ fn is_under_cfg_attribute(cx: &LateContext<'_>, hir_id: HirId) -> bool {
cx.tcx.hir_parent_id_iter(hir_id).any(|id| {
cx.tcx.hir_attrs(id).iter().any(|attr| {
matches!(
attr.ident().map(|ident| ident.name),
attr.name(),
Some(sym::cfg_trace | sym::cfg_attr_trace)
)
})

View file

@ -287,8 +287,8 @@ fn is_doc_attr(attr: &Attribute) -> bool {
match attr {
Attribute::Parsed(AttributeKind::DocComment { .. }) => true,
Attribute::Unparsed(attr)
if let [ident] = &*attr.path.segments
&& ident.name == sym::doc =>
if let [name] = &*attr.path.segments
&& *name == sym::doc =>
{
matches!(attr.args, AttrArgs::Eq { .. })
},

View file

@ -20,10 +20,11 @@ pub fn get_builtin_attr<'a, A: AttributeExt + 'a>(
name: Symbol,
) -> impl Iterator<Item = &'a A> {
attrs.iter().filter(move |attr| {
if let Some([clippy, segment2]) = attr.ident_path().as_deref()
&& clippy.name == sym::clippy
if let [clippy, segment2] = &*attr.path()
&& *clippy == sym::clippy
{
let new_name = match segment2.name {
let path_span = attr.path_span().expect("Clippy attributes are unparsed and have a span");
let new_name = match *segment2 {
sym::cyclomatic_complexity => Some("cognitive_complexity"),
sym::author
| sym::version
@ -35,7 +36,7 @@ pub fn get_builtin_attr<'a, A: AttributeExt + 'a>(
| sym::has_significant_drop
| sym::format_args => None,
_ => {
sess.dcx().span_err(segment2.span, "usage of unknown attribute");
sess.dcx().span_err(path_span, "usage of unknown attribute");
return false;
},
};
@ -43,17 +44,17 @@ pub fn get_builtin_attr<'a, A: AttributeExt + 'a>(
match new_name {
Some(new_name) => {
sess.dcx()
.struct_span_err(segment2.span, "usage of deprecated attribute")
.struct_span_err(path_span, "usage of deprecated attribute")
.with_span_suggestion(
segment2.span,
path_span,
"consider using",
new_name,
format!("clippy::{}", new_name),
Applicability::MachineApplicable,
)
.emit();
false
},
None => segment2.name == name,
None => *segment2 == name,
}
} else {
false

View file

@ -348,9 +348,9 @@ fn fn_kind_pat(tcx: TyCtxt<'_>, kind: &FnKind<'_>, body: &Body<'_>, hir_id: HirI
fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) {
match attr.kind {
AttrKind::Normal(..) => {
if let Some(ident) = attr.ident() {
if let Some(name) = attr.name() {
// NOTE: This will likely have false positives, like `allow = 1`
let ident_string = ident.to_string();
let ident_string = name.to_string();
if attr.style == AttrStyle::Outer {
(
Pat::OwnedMultiStr(vec!["#[".to_owned() + &ident_string, ident_string]),

View file

@ -1,8 +1,8 @@
error: usage of deprecated attribute
--> tests/ui/renamed_builtin_attr.rs:3:11
--> tests/ui/renamed_builtin_attr.rs:3:3
|
LL | #[clippy::cyclomatic_complexity = "1"]
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `cognitive_complexity`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `clippy::cognitive_complexity`
error: aborting due to 1 previous error

View file

@ -1,8 +1,8 @@
error: usage of unknown attribute
--> tests/ui/unknown_attribute.rs:3:11
--> tests/ui/unknown_attribute.rs:3:3
|
LL | #[clippy::unknown]
| ^^^^^^^
| ^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -336,8 +336,8 @@ impl Rewrite for ast::Attribute {
rewrite_doc_comment(snippet, shape.comment(context.config), context.config)
} else {
let should_skip = self
.ident()
.map(|s| context.skip_context.attributes.skip(s.name.as_str()))
.name()
.map(|s| context.skip_context.attributes.skip(s.as_str()))
.unwrap_or(false);
let prefix = attr_prefix(self);

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/26614>
//@ check-pass
trait Mirror {

View file

@ -0,0 +1,12 @@
//! regression test for <https://github.com/rust-lang/rust/issues/2428>
//@ run-pass
fn main() {
const QUUX: isize = 5;
enum Stuff {
Bar = QUUX,
}
assert_eq!(Stuff::Bar as isize, QUUX);
}

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/22403>
//@ run-pass
fn main() {
let x = Box::new([1, 2, 3]);

View file

@ -1,6 +1,6 @@
//! regression test for <https://github.com/rust-lang/rust/issues/41998>
//@ check-pass
fn main() {
if ('x' as char) < ('y' as char) {
print!("x");

View file

@ -0,0 +1,7 @@
//! regression test for <https://github.com/rust-lang/rust/issues/25180>
//@ check-pass
#![allow(dead_code)]
const X: &'static dyn Fn() = &|| println!("ICE here");
fn main() {}

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/29030>
//@ check-pass
#![allow(dead_code)]
#[derive(Debug)]

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/25394>
//@ check-pass
#![allow(dead_code)]
#[derive(Debug)]

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/33687>
//@ run-pass
#![feature(unboxed_closures)]
#![feature(fn_traits)]

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/20847>
//@ run-pass
#![feature(fn_traits)]

View file

@ -1,9 +0,0 @@
//@ check-pass
trait Common { fn dummy(&self) { } }
impl<'t, T> Common for (T, &'t T) {}
impl<'t, T> Common for (&'t T, T) {}
fn main() {}

View file

@ -1,6 +0,0 @@
//@ check-pass
trait A<T> {}
struct B<T> where B<T>: A<B<T>> { t: T }
fn main() {}

View file

@ -1,12 +0,0 @@
//@ run-pass
// Regression test for #20676. Error was that we didn't support
// UFCS-style calls to a method in `Trait` where `Self` was bound to a
// trait object of type `Trait`. See also `ufcs-trait-object.rs`.
use std::fmt;
fn main() {
let a: &dyn fmt::Debug = &1;
let _ = format!("{:?}", a);
}

View file

@ -1,8 +0,0 @@
//@ run-pass
fn main() {
match 42 {
x if x < 7 => (),
_ => ()
}
}

View file

@ -1,14 +0,0 @@
//@ run-pass
#![allow(non_upper_case_globals)]
pub fn main() {
let _foo = 100;
const quux: isize = 5;
enum Stuff {
Bar = quux
}
assert_eq!(Stuff::Bar as isize, quux);
}

View file

@ -1,11 +0,0 @@
//@ check-pass
#![allow(dead_code)]
struct Foo;
impl Foo {
fn new() -> Self { Foo }
fn bar() { Self::new(); }
}
fn main() {}

View file

@ -1,7 +0,0 @@
//@ check-pass
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
const x: &'static dyn Fn() = &|| println!("ICE here");
fn main() {}

View file

@ -1,11 +0,0 @@
//@ run-pass
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
fn main() {
const iter: i32 = 0;
for i in 1..10 {
println!("{}", i);
}
}

View file

@ -0,0 +1,15 @@
//! regression test for <https://github.com/rust-lang/rust/issues/27639>
//! Ensure that a constant named `iter` does not
//! interfere with the name resolution of the `iter` methods used internally
//! by `for` loops
//@ run-pass
#![allow(dead_code)]
#![allow(non_upper_case_globals)]
fn main() {
const iter: i32 = 0;
for i in 1..10 {
println!("{}", i);
}
}

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/20427>
//@ run-pass
#![allow(dead_code)]
#![allow(unused_variables)]
@ -31,17 +32,10 @@ mod char {
mod char_ {}
mod str {
use super::i8 as i8;
use super::i32_ as i32;
use super::i64_ as i64;
use super::u8_ as u8;
use super::f_ as f64;
use super::u16_ as u16;
use super::u32_ as u32;
use super::u64_ as u64;
use super::bool_ as bool;
use super::{bool_ as str};
use super::char_ as char;
use super::{
bool_ as bool, bool_ as str, char_ as char, f_ as f64, i8, i32_ as i32, i64_ as i64,
u8_ as u8, u16_ as u16, u32_ as u32, u64_ as u64,
};
}
}
@ -49,7 +43,9 @@ trait isize_ {
type isize;
}
fn usize<'usize>(usize: &'usize usize) -> &'usize usize { usize }
fn usize<'usize>(usize: &'usize usize) -> &'usize usize {
usize
}
mod reuse {
use std::mem::size_of;
@ -68,9 +64,10 @@ mod reuse {
mod guard {
pub fn check() {
use std::u8; // bring module u8 in scope
fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8
fn f() -> u8 {
// OK, resolves to primitive u8, not to std::u8
u8::max_value() // OK, resolves to associated function <u8>::max_value,
// not to non-existent std::u8::max_value
// not to non-existent std::u8::max_value
}
assert_eq!(f(), u8::MAX); // OK, resolves to std::u8::MAX
}
@ -79,7 +76,13 @@ mod guard {
fn main() {
let bool = true;
let _ = match bool {
str @ true => if str { i32 as i64 } else { i64 },
str @ true => {
if str {
i32 as i64
} else {
i64
}
}
false => i64,
};

View file

@ -0,0 +1,16 @@
//! regression test for <https://github.com/rust-lang/rust/issues/24389>
//@ check-pass
#![allow(dead_code)]
struct Foo;
impl Foo {
fn new() -> Self {
Foo
}
fn bar() {
Self::new();
}
}
fn main() {}

View file

@ -0,0 +1,12 @@
//! regression test for <https://github.com/rust-lang/rust/issues/19601>
//@ check-pass
trait A<T> {}
struct B<T>
where
B<T>: A<B<T>>,
{
t: T,
}
fn main() {}

View file

@ -0,0 +1,12 @@
//! regression test for <https://github.com/rust-lang/rust/issues/11384>
//@ check-pass
trait Common {
fn dummy(&self) {}
}
impl<'t, T> Common for (T, &'t T) {}
impl<'t, T> Common for (&'t T, T) {}
fn main() {}

View file

@ -0,0 +1,13 @@
//@ run-pass
//! Regression test for <https://github.com/rust-lang/rust/issues/20676>.
//! Error was that we didn't support
//! UFCS-style calls to a method in `Trait` where `Self` was bound to a
//! trait object of type `Trait`.
//! See also <https://github.com/rust-lang/rust/blob/ec2cc76/tests/ui/traits/ufcs-object.rs>.
use std::fmt;
fn main() {
let a: &dyn fmt::Debug = &1;
let _ = format!("{:?}", a);
}