Skip to content

Commit 715d3f9

Browse files
authored
Out of cycle sync, as it is complicated and confusing to resolve merge conflicts on the Rust side. This needs review for eda3e64 and 4d8766c as well as the comment I'll leave below. changelog: none
2 parents 15180d4 + b3d35b1 commit 715d3f9

File tree

105 files changed

+437
-472
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+437
-472
lines changed

clippy_lints/src/arbitrary_source_item_ordering.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
362362
}
363363
} else if let ItemKind::ForeignMod { .. } = item.kind {
364364
continue;
365-
} else if let ItemKind::GlobalAsm(_) = item.kind {
365+
} else if let ItemKind::GlobalAsm { .. } = item.kind {
366366
continue;
367367
} else if let ItemKind::Use(path, use_kind) = item.kind {
368368
if path.segments.is_empty() {
@@ -467,7 +467,7 @@ fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleIte
467467
ItemKind::Macro(..) => Macro,
468468
ItemKind::Mod(..) => Mod,
469469
ItemKind::ForeignMod { .. } => ForeignMod,
470-
ItemKind::GlobalAsm(..) => GlobalAsm,
470+
ItemKind::GlobalAsm { .. } => GlobalAsm,
471471
ItemKind::TyAlias(..) => TyAlias,
472472
ItemKind::Enum(..) => Enum,
473473
ItemKind::Struct(..) => Struct,

clippy_lints/src/assigning_clones.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl<'tcx> LateLintPass<'tcx> for AssigningClones {
107107
&& !cx.tcx.is_builtin_derived(resolved_impl)
108108
// Don't suggest calling a function we're implementing.
109109
&& resolved_impl.as_local().is_none_or(|block_id| {
110-
cx.tcx.hir().parent_owner_iter(e.hir_id).all(|(id, _)| id.def_id != block_id)
110+
cx.tcx.hir_parent_owner_iter(e.hir_id).all(|(id, _)| id.def_id != block_id)
111111
})
112112
&& let resolved_assoc_items = cx.tcx.associated_items(resolved_impl)
113113
// Only suggest if `clone_from`/`clone_into` is explicitly implemented

clippy_lints/src/attrs/inline_always.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub(super) fn check(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Att
2020
span_lint(
2121
cx,
2222
INLINE_ALWAYS,
23-
attr.span,
23+
attr.span(),
2424
format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
2525
);
2626
}
+26-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
12
use rustc_hir::Attribute;
23
use rustc_lint::LateContext;
3-
use rustc_span::{Span, sym};
4+
use rustc_span::Span;
45

56
use clippy_utils::diagnostics::span_lint_and_then;
67
use clippy_utils::msrvs;
@@ -14,30 +15,30 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute],
1415
}
1516

1617
fn check_packed(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
17-
if let Some(items) = attrs.iter().find_map(|attr| {
18-
if attr.ident().is_some_and(|ident| matches!(ident.name, sym::repr)) {
19-
attr.meta_item_list()
20-
} else {
21-
None
22-
}
23-
}) && let Some(packed) = items
24-
.iter()
25-
.find(|item| item.ident().is_some_and(|ident| matches!(ident.name, sym::packed)))
26-
&& !items.iter().any(|item| {
27-
item.ident()
28-
.is_some_and(|ident| matches!(ident.name, sym::C | sym::Rust))
29-
})
30-
{
31-
span_lint_and_then(
32-
cx,
33-
REPR_PACKED_WITHOUT_ABI,
34-
item_span,
35-
"item uses `packed` representation without ABI-qualification",
36-
|diag| {
37-
diag.warn("unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI")
18+
if let Some(reprs) = find_attr!(attrs, AttributeKind::Repr(r) => r) {
19+
let packed_span = reprs
20+
.iter()
21+
.find(|(r, _)| matches!(r, ReprAttr::ReprPacked(..)))
22+
.map(|(_, s)| *s);
23+
24+
if let Some(packed_span) = packed_span
25+
&& !reprs
26+
.iter()
27+
.any(|(x, _)| *x == ReprAttr::ReprC || *x == ReprAttr::ReprRust)
28+
{
29+
span_lint_and_then(
30+
cx,
31+
REPR_PACKED_WITHOUT_ABI,
32+
item_span,
33+
"item uses `packed` representation without ABI-qualification",
34+
|diag| {
35+
diag.warn(
36+
"unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI",
37+
)
3838
.help("qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`")
39-
.span_label(packed.span(), "`packed` representation set here");
40-
},
41-
);
39+
.span_label(packed_span, "`packed` representation set here");
40+
},
41+
);
42+
}
4243
}
4344
}

clippy_lints/src/attrs/unnecessary_clippy_cfg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub(super) fn check(
1515
) {
1616
if cfg_attr.has_name(sym::clippy)
1717
&& let Some(ident) = behind_cfg_attr.ident()
18-
&& Level::from_symbol(ident.name, Some(attr.id)).is_some()
18+
&& Level::from_symbol(ident.name, || Some(attr.id)).is_some()
1919
&& let Some(items) = behind_cfg_attr.meta_item_list()
2020
{
2121
let nb_items = items.len();

clippy_lints/src/attrs/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub(super) fn is_word(nmi: &MetaItemInner, expected: Symbol) -> bool {
1717
}
1818

1919
pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
20-
Level::from_symbol(symbol, Some(attr_id)).is_some()
20+
Level::from_symbol(symbol, || Some(attr_id)).is_some()
2121
}
2222

2323
pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {

clippy_lints/src/default_union_representation.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2+
use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
23
use rustc_hir::{HirId, Item, ItemKind};
34
use rustc_lint::{LateContext, LateLintPass};
45
use rustc_middle::ty::layout::LayoutOf;
56
use rustc_middle::ty::{self, FieldDef};
67
use rustc_session::declare_lint_pass;
7-
use rustc_span::sym;
88

99
declare_clippy_lint! {
1010
/// ### What it does
@@ -97,16 +97,7 @@ fn is_zst<'tcx>(cx: &LateContext<'tcx>, field: &FieldDef, args: ty::GenericArgsR
9797
}
9898

9999
fn has_c_repr_attr(cx: &LateContext<'_>, hir_id: HirId) -> bool {
100-
cx.tcx.hir().attrs(hir_id).iter().any(|attr| {
101-
if attr.has_name(sym::repr) {
102-
if let Some(items) = attr.meta_item_list() {
103-
for item in items {
104-
if item.is_word() && matches!(item.name_or_empty(), sym::C) {
105-
return true;
106-
}
107-
}
108-
}
109-
}
110-
false
111-
})
100+
let attrs = cx.tcx.hir().attrs(hir_id);
101+
102+
find_attr!(attrs, AttributeKind::Repr(r) if r.iter().any(|(x, _)| *x == ReprAttr::ReprC))
112103
}

clippy_lints/src/doc/include_in_doc_without_cfg.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::snippet_opt;
3-
use rustc_ast::AttrStyle;
3+
use rustc_ast::{AttrArgs, AttrKind, AttrStyle, Attribute};
44
use rustc_errors::Applicability;
5-
use rustc_hir::{AttrArgs, AttrKind, Attribute};
6-
use rustc_lint::LateContext;
5+
use rustc_lint::EarlyContext;
76

87
use super::DOC_INCLUDE_WITHOUT_CFG;
98

10-
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
9+
pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
1110
for attr in attrs {
1211
if !attr.span.from_expansion()
1312
&& let AttrKind::Normal(ref item) = attr.kind
1413
&& attr.doc_str().is_some()
15-
&& let AttrArgs::Eq { expr: meta, .. } = &item.args
14+
&& let AttrArgs::Eq { expr: meta, .. } = &item.item.args
1615
&& !attr.span.contains(meta.span)
1716
// Since the `include_str` is already expanded at this point, we can only take the
1817
// whole attribute snippet and then modify for our suggestion.

clippy_lints/src/doc/missing_headers.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ pub fn check(
2424
if !check_private_items
2525
&& cx
2626
.tcx
27-
.hir()
28-
.parent_iter(owner_id.into())
27+
.hir_parent_iter(owner_id.into())
2928
.any(|(id, _node)| is_doc_hidden(cx.tcx.hir().attrs(id)))
3029
{
3130
return;

clippy_lints/src/doc/mod.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_data_structures::fx::FxHashSet;
2020
use rustc_errors::Applicability;
2121
use rustc_hir::intravisit::{self, Visitor};
2222
use rustc_hir::{AnonConst, Attribute, Expr, ImplItemKind, ItemKind, Node, Safety, TraitItemKind};
23-
use rustc_lint::{LateContext, LateLintPass, LintContext};
23+
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
2424
use rustc_middle::hir::nested_filter;
2525
use rustc_middle::ty;
2626
use rustc_resolve::rustdoc::{
@@ -600,6 +600,12 @@ impl_lint_pass!(Documentation => [
600600
DOC_INCLUDE_WITHOUT_CFG,
601601
]);
602602

603+
impl EarlyLintPass for Documentation {
604+
fn check_attributes(&mut self, cx: &EarlyContext<'_>, attrs: &[rustc_ast::Attribute]) {
605+
include_in_doc_without_cfg::check(cx, attrs);
606+
}
607+
}
608+
603609
impl<'tcx> LateLintPass<'tcx> for Documentation {
604610
fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
605611
let Some(headers) = check_attrs(cx, &self.valid_idents, attrs) else {
@@ -727,14 +733,13 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
727733
Some(("fake".into(), "fake".into()))
728734
}
729735

730-
include_in_doc_without_cfg::check(cx, attrs);
731736
if suspicious_doc_comments::check(cx, attrs) || is_doc_hidden(attrs) {
732737
return None;
733738
}
734739

735740
let (fragments, _) = attrs_to_doc_fragments(
736741
attrs.iter().filter_map(|attr| {
737-
if attr.span.in_external_macro(cx.sess().source_map()) {
742+
if attr.doc_str_and_comment_kind().is_none() || attr.span().in_external_macro(cx.sess().source_map()) {
738743
None
739744
} else {
740745
Some((attr, None))
@@ -1160,7 +1165,7 @@ impl<'tcx> Visitor<'tcx> for FindPanicUnwrap<'_, 'tcx> {
11601165
"assert" | "assert_eq" | "assert_ne"
11611166
)
11621167
{
1163-
self.is_const = self.cx.tcx.hir().is_inside_const_context(expr.hir_id);
1168+
self.is_const = self.cx.tcx.hir_is_inside_const_context(expr.hir_id);
11641169
self.panic_span = Some(macro_call.span);
11651170
}
11661171
}

clippy_lints/src/doc/suspicious_doc_comments.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use rustc_ast::AttrStyle;
33
use rustc_ast::token::CommentKind;
4+
use rustc_attr_parsing::AttributeKind;
45
use rustc_errors::Applicability;
56
use rustc_hir::Attribute;
67
use rustc_lint::LateContext;
@@ -36,15 +37,19 @@ fn collect_doc_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> {
3637
attrs
3738
.iter()
3839
.filter_map(|attr| {
39-
if let Some((sym, com_kind)) = attr.doc_str_and_comment_kind()
40-
&& let AttrStyle::Outer = attr.style
41-
&& let Some(com) = sym.as_str().strip_prefix('!')
40+
if let Attribute::Parsed(AttributeKind::DocComment {
41+
style: AttrStyle::Outer,
42+
kind,
43+
comment,
44+
..
45+
}) = attr
46+
&& let Some(com) = comment.as_str().strip_prefix('!')
4247
{
43-
let sugg = match com_kind {
48+
let sugg = match kind {
4449
CommentKind::Line => format!("//!{com}"),
4550
CommentKind::Block => format!("/*!{com}*/"),
4651
};
47-
Some((attr.span, sugg))
52+
Some((attr.span(), sugg))
4853
} else {
4954
None
5055
}

clippy_lints/src/doc/too_long_first_doc_paragraph.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_attr_parsing::AttributeKind;
12
use rustc_errors::Applicability;
23
use rustc_hir::{Attribute, Item, ItemKind};
34
use rustc_lint::LateContext;
@@ -43,9 +44,9 @@ pub(super) fn check(
4344
let mut should_suggest_empty_doc = false;
4445

4546
for attr in attrs {
46-
if let Some(doc) = attr.doc_str() {
47-
spans.push(attr.span);
48-
let doc = doc.as_str();
47+
if let Attribute::Parsed(AttributeKind::DocComment { span, comment, .. }) = attr {
48+
spans.push(span);
49+
let doc = comment.as_str();
4950
let doc = doc.trim();
5051
if spans.len() == 1 {
5152
// We make this suggestion only if the first doc line ends with a punctuation
@@ -82,7 +83,7 @@ pub(super) fn check(
8283
&& let new_span = first_span.with_hi(second_span.lo()).with_lo(first_span.hi())
8384
&& let Some(snippet) = snippet_opt(cx, new_span)
8485
{
85-
let Some(first) = snippet_opt(cx, first_span) else {
86+
let Some(first) = snippet_opt(cx, *first_span) else {
8687
return;
8788
};
8889
let Some(comment_form) = first.get(..3) else {

clippy_lints/src/escape.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
8080

8181
let parent_id = cx
8282
.tcx
83-
.hir()
84-
.get_parent_item(cx.tcx.local_def_id_to_hir_id(fn_def_id))
83+
.hir_get_parent_item(cx.tcx.local_def_id_to_hir_id(fn_def_id))
8584
.def_id;
8685

8786
let mut trait_self_ty = None;

clippy_lints/src/exit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
4747
&& let ExprKind::Path(ref path) = path_expr.kind
4848
&& let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id()
4949
&& cx.tcx.is_diagnostic_item(sym::process_exit, def_id)
50-
&& let parent = cx.tcx.hir().get_parent_item(e.hir_id)
50+
&& let parent = cx.tcx.hir_get_parent_item(e.hir_id)
5151
&& let OwnerNode::Item(Item{kind: ItemKind::Fn{ .. }, ..}) = cx.tcx.hir_owner_node(parent)
5252
// If the next item up is a function we check if it is an entry point
5353
// and only then emit a linter warning

clippy_lints/src/format_args.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_ast::{
1515
FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions,
1616
FormatPlaceholder, FormatTrait,
1717
};
18+
use rustc_attr_parsing::RustcVersion;
1819
use rustc_data_structures::fx::FxHashMap;
1920
use rustc_errors::Applicability;
2021
use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode};
@@ -206,17 +207,17 @@ pub struct FormatArgs<'tcx> {
206207
format_args: FormatArgsStorage,
207208
msrv: Msrv,
208209
ignore_mixed: bool,
209-
ty_feature_map: FxHashMap<Ty<'tcx>, Option<Symbol>>,
210+
ty_msrv_map: FxHashMap<Ty<'tcx>, Option<RustcVersion>>,
210211
}
211212

212213
impl<'tcx> FormatArgs<'tcx> {
213214
pub fn new(tcx: TyCtxt<'tcx>, conf: &'static Conf, format_args: FormatArgsStorage) -> Self {
214-
let ty_feature_map = make_ty_feature_map(tcx);
215+
let ty_msrv_map = make_ty_msrv_map(tcx);
215216
Self {
216217
format_args,
217218
msrv: conf.msrv.clone(),
218219
ignore_mixed: conf.allow_mixed_uninlined_format_args,
219-
ty_feature_map,
220+
ty_msrv_map,
220221
}
221222
}
222223
}
@@ -233,7 +234,8 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs<'tcx> {
233234
macro_call: &macro_call,
234235
format_args,
235236
ignore_mixed: self.ignore_mixed,
236-
ty_feature_map: &self.ty_feature_map,
237+
msrv: &self.msrv,
238+
ty_msrv_map: &self.ty_msrv_map,
237239
};
238240

239241
linter.check_templates();
@@ -253,7 +255,8 @@ struct FormatArgsExpr<'a, 'tcx> {
253255
macro_call: &'a MacroCall,
254256
format_args: &'a rustc_ast::FormatArgs,
255257
ignore_mixed: bool,
256-
ty_feature_map: &'a FxHashMap<Ty<'tcx>, Option<Symbol>>,
258+
msrv: &'a Msrv,
259+
ty_msrv_map: &'a FxHashMap<Ty<'tcx>, Option<RustcVersion>>,
257260
}
258261

259262
impl<'tcx> FormatArgsExpr<'_, 'tcx> {
@@ -538,19 +541,19 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> {
538541
fn can_display_format(&self, ty: Ty<'tcx>) -> bool {
539542
let ty = ty.peel_refs();
540543

541-
if let Some(feature) = self.ty_feature_map.get(&ty)
542-
&& feature.is_none_or(|feature| self.cx.tcx.features().enabled(feature))
544+
if let Some(msrv) = self.ty_msrv_map.get(&ty)
545+
&& msrv.is_none_or(|msrv| self.msrv.meets(msrv))
543546
{
544547
return true;
545548
}
546549

547-
// Even if `ty` is not in `self.ty_feature_map`, check whether `ty` implements `Deref` with
548-
// a `Target` that is in `self.ty_feature_map`.
550+
// Even if `ty` is not in `self.ty_msrv_map`, check whether `ty` implements `Deref` with
551+
// a `Target` that is in `self.ty_msrv_map`.
549552
if let Some(deref_trait_id) = self.cx.tcx.lang_items().deref_trait()
550553
&& implements_trait(self.cx, ty, deref_trait_id, &[])
551554
&& let Some(target_ty) = self.cx.get_associated_type(ty, deref_trait_id, "Target")
552-
&& let Some(feature) = self.ty_feature_map.get(&target_ty)
553-
&& feature.is_none_or(|feature| self.cx.tcx.features().enabled(feature))
555+
&& let Some(msrv) = self.ty_msrv_map.get(&target_ty)
556+
&& msrv.is_none_or(|msrv| self.msrv.meets(msrv))
554557
{
555558
return true;
556559
}
@@ -559,8 +562,8 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> {
559562
}
560563
}
561564

562-
fn make_ty_feature_map(tcx: TyCtxt<'_>) -> FxHashMap<Ty<'_>, Option<Symbol>> {
563-
[(sym::OsStr, Some(Symbol::intern("os_str_display"))), (sym::Path, None)]
565+
fn make_ty_msrv_map(tcx: TyCtxt<'_>) -> FxHashMap<Ty<'_>, Option<RustcVersion>> {
566+
[(sym::OsStr, Some(msrvs::OS_STR_DISPLAY)), (sym::Path, None)]
564567
.into_iter()
565568
.filter_map(|(name, feature)| {
566569
tcx.get_diagnostic_item(name).map(|def_id| {

0 commit comments

Comments
 (0)