Skip to main content

rustc_lint/
internal.rs

1//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
2//! Clippy.
3
4use rustc_ast as ast;
5use rustc_ast::{Pat, PatKind, Path};
6use rustc_attr_ir::find_attr;
7use rustc_hir as hir;
8use rustc_hir::def::Res;
9use rustc_hir::def_id::DefId;
10use rustc_hir::{Expr, ExprKind, HirId};
11use rustc_infer::infer::TyCtxtInferExt as _;
12use rustc_lint_defs::{declare_lint_pass, declare_tool_lint};
13use rustc_middle::ty::{self, ClausePolarity, GenericArgsRef};
14use rustc_span::hygiene::{ExpnKind, MacroKind};
15use rustc_span::{DUMMY_SP, Span, sym};
16use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
17use rustc_trait_selection::traits::{Obligation, ObligationCause};
18
19use crate::diagnostics::{
20    AttributeKindInFindAttr, BadOptAccessDiag, DefaultHashTypesDiag,
21    ImplicitSysrootCrateImportDiag, LintPassByHand, MissingGenericTypeVisitableDeriveDiag,
22    NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked,
23    RustcMustMatchExhaustivelyNotExhaustive, SymbolInternStringLiteralDiag, TyQualified,
24    TykindDiag, TykindKind, TypeIrDirectUse, TypeIrInherentUsage, TypeIrTraitUsage,
25};
26use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
27
28#[doc =
r" The `default_hash_type` lint detects use of [`std::collections::HashMap`] and"]
#[doc =
r" [`std::collections::HashSet`], suggesting the use of `FxHashMap`/`FxHashSet`."]
#[doc = r""]
#[doc =
r" This can help as `FxHasher` can perform better than the default hasher. DOS protection is"]
#[doc = r" not required as input is assumed to be trusted."]
pub static DEFAULT_HASH_TYPES: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::DEFAULT_HASH_TYPES",
            default_level: ::rustc_lint_defs::Allow,
            desc: "forbid HashMap and HashSet and suggest the FxHash* variants",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
29    /// The `default_hash_type` lint detects use of [`std::collections::HashMap`] and
30    /// [`std::collections::HashSet`], suggesting the use of `FxHashMap`/`FxHashSet`.
31    ///
32    /// This can help as `FxHasher` can perform better than the default hasher. DOS protection is
33    /// not required as input is assumed to be trusted.
34    pub rustc::DEFAULT_HASH_TYPES,
35    Allow,
36    "forbid HashMap and HashSet and suggest the FxHash* variants",
37    report_in_external_macro: true
38}
39
40pub struct DefaultHashTypes;
#[automatically_derived]
impl ::core::marker::Copy for DefaultHashTypes { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for DefaultHashTypes { }
#[automatically_derived]
impl ::core::clone::Clone for DefaultHashTypes {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for DefaultHashTypes {
    fn name(&self) -> &'static str { "DefaultHashTypes" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [DEFAULT_HASH_TYPES]))
    }
}
impl DefaultHashTypes {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [DEFAULT_HASH_TYPES]))
    }
}declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
41
42impl LateLintPass<'_> for DefaultHashTypes {
43    fn check_path(&mut self, cx: &LateContext<'_>, path: &hir::Path<'_>, hir_id: HirId) {
44        let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return };
45        if #[allow(non_exhaustive_omitted_patterns)] match cx.tcx.hir_node(hir_id) {
    hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. }) |
        hir::Node::NestedUseTree(_) => true,
    _ => false,
}matches!(
46            cx.tcx.hir_node(hir_id),
47            hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. })
48                | hir::Node::NestedUseTree(_)
49        ) {
50            // Don't lint imports, only actual usages.
51            return;
52        }
53        let preferred = match cx.tcx.get_diagnostic_name(def_id) {
54            Some(sym::HashMap) => "FxHashMap",
55            Some(sym::HashSet) => "FxHashSet",
56            _ => return,
57        };
58        cx.emit_span_lint(
59            DEFAULT_HASH_TYPES,
60            path.span,
61            DefaultHashTypesDiag { preferred, used: cx.tcx.item_name(def_id) },
62        );
63    }
64}
65
66#[doc =
r" The `potential_query_instability` lint detects use of methods which can lead to"]
#[doc = r" potential query instability, such as iterating over a `HashMap`."]
#[doc = r""]
#[doc =
r" Due to the [incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html) model,"]
#[doc =
r" queries must return deterministic, stable results. `HashMap` iteration order can change"]
#[doc =
r" between compilations, and will introduce instability if query results expose the order."]
pub static POTENTIAL_QUERY_INSTABILITY: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::POTENTIAL_QUERY_INSTABILITY",
            default_level: ::rustc_lint_defs::Allow,
            desc: "require explicit opt-in when using potentially unstable methods or functions",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
67    /// The `potential_query_instability` lint detects use of methods which can lead to
68    /// potential query instability, such as iterating over a `HashMap`.
69    ///
70    /// Due to the [incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html) model,
71    /// queries must return deterministic, stable results. `HashMap` iteration order can change
72    /// between compilations, and will introduce instability if query results expose the order.
73    pub rustc::POTENTIAL_QUERY_INSTABILITY,
74    Allow,
75    "require explicit opt-in when using potentially unstable methods or functions",
76    report_in_external_macro: true
77}
78
79#[doc =
r" The `untracked_query_information` lint detects use of methods which leak information not"]
#[doc =
r" tracked by the query system, such as whether a `Steal<T>` value has already been stolen. In"]
#[doc =
r" order not to break incremental compilation, such methods must be used very carefully or not"]
#[doc = r" at all."]
pub static UNTRACKED_QUERY_INFORMATION: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::UNTRACKED_QUERY_INFORMATION",
            default_level: ::rustc_lint_defs::Allow,
            desc: "require explicit opt-in when accessing information not tracked by the query system",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
80    /// The `untracked_query_information` lint detects use of methods which leak information not
81    /// tracked by the query system, such as whether a `Steal<T>` value has already been stolen. In
82    /// order not to break incremental compilation, such methods must be used very carefully or not
83    /// at all.
84    pub rustc::UNTRACKED_QUERY_INFORMATION,
85    Allow,
86    "require explicit opt-in when accessing information not tracked by the query system",
87    report_in_external_macro: true
88}
89
90pub struct QueryStability;
#[automatically_derived]
impl ::core::marker::Copy for QueryStability { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for QueryStability { }
#[automatically_derived]
impl ::core::clone::Clone for QueryStability {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for QueryStability {
    fn name(&self) -> &'static str { "QueryStability" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]))
    }
}
impl QueryStability {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]))
    }
}declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
91
92impl<'tcx> LateLintPass<'tcx> for QueryStability {
93    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
94        if let Some((callee_def_id, span, generic_args, _recv, _args)) =
95            get_callee_span_generic_args_and_args(cx, expr)
96            && let Ok(Some(instance)) =
97                ty::Instance::try_resolve(cx.tcx, cx.typing_env(), callee_def_id, generic_args)
98        {
99            let def_id = instance.def_id();
100            if {
        {
            'done:
                {
                for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &cx.tcx)
                    {
                    #[allow(unused_imports)]
                    use ::rustc_attr_ir::AttributeKind::*;
                    let i: &::rustc_attr_ir::Attribute = i;
                    match i {
                        ::rustc_attr_ir::Attribute::Parsed(RustcLintQueryInstability)
                            => {
                            break 'done Some(());
                        }
                        ::rustc_attr_ir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(cx.tcx, def_id, RustcLintQueryInstability) {
101                cx.emit_span_lint(
102                    POTENTIAL_QUERY_INSTABILITY,
103                    span,
104                    QueryInstability { query: cx.tcx.item_name(def_id) },
105                );
106            } else if has_unstable_into_iter_predicate(cx, callee_def_id, generic_args) {
107                let call_span = span.with_hi(expr.span.hi());
108                cx.emit_span_lint(
109                    POTENTIAL_QUERY_INSTABILITY,
110                    call_span,
111                    QueryInstability { query: sym::into_iter },
112                );
113            }
114
115            if {
        {
            'done:
                {
                for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &cx.tcx)
                    {
                    #[allow(unused_imports)]
                    use ::rustc_attr_ir::AttributeKind::*;
                    let i: &::rustc_attr_ir::Attribute = i;
                    match i {
                        ::rustc_attr_ir::Attribute::Parsed(RustcLintUntrackedQueryInformation)
                            => {
                            break 'done Some(());
                        }
                        ::rustc_attr_ir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(cx.tcx, def_id, RustcLintUntrackedQueryInformation) {
116                cx.emit_span_lint(
117                    UNTRACKED_QUERY_INFORMATION,
118                    span,
119                    QueryUntracked { method: cx.tcx.item_name(def_id) },
120                );
121            }
122        }
123    }
124}
125
126fn has_unstable_into_iter_predicate<'tcx>(
127    cx: &LateContext<'tcx>,
128    callee_def_id: DefId,
129    generic_args: GenericArgsRef<'tcx>,
130) -> bool {
131    let Some(into_iterator_def_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) else {
132        return false;
133    };
134    let Some(into_iter_fn_def_id) = cx.tcx.lang_items().into_iter_fn() else {
135        return false;
136    };
137    let clauses = cx.tcx.clauses_of(callee_def_id).instantiate(cx.tcx, generic_args);
138    for (clause, _) in clauses {
139        let Some(trait_clause) = clause.as_trait_clause() else {
140            continue;
141        };
142        if trait_clause.def_id() != into_iterator_def_id
143            || trait_clause.polarity() != ClausePolarity::Positive
144        {
145            continue;
146        }
147        // `IntoIterator::into_iter` has no additional method args.
148        let into_iter_fn_args = cx
149            .tcx
150            .instantiate_bound_regions_with_erased(trait_clause.skip_norm_wip())
151            .trait_ref
152            .args;
153        let Ok(Some(instance)) = ty::Instance::try_resolve(
154            cx.tcx,
155            cx.typing_env(),
156            into_iter_fn_def_id,
157            into_iter_fn_args,
158        ) else {
159            continue;
160        };
161        // Does the input type's `IntoIterator` implementation have the
162        // `rustc_lint_query_instability` attribute on its `into_iter` method?
163        if {
        {
            'done:
                {
                for i in
                    ::rustc_attr_ir::HasAttrs::get_attrs(instance.def_id(),
                        &cx.tcx) {
                    #[allow(unused_imports)]
                    use ::rustc_attr_ir::AttributeKind::*;
                    let i: &::rustc_attr_ir::Attribute = i;
                    match i {
                        ::rustc_attr_ir::Attribute::Parsed(RustcLintQueryInstability)
                            => {
                            break 'done Some(());
                        }
                        ::rustc_attr_ir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(cx.tcx, instance.def_id(), RustcLintQueryInstability) {
164            return true;
165        }
166    }
167    false
168}
169
170/// Checks whether an expression is a function or method call and, if so, returns its `DefId`,
171/// `Span`, `GenericArgs`, and arguments. This is a slight augmentation of a similarly named Clippy
172/// function, `get_callee_generic_args_and_args`.
173fn get_callee_span_generic_args_and_args<'tcx>(
174    cx: &LateContext<'tcx>,
175    expr: &'tcx Expr<'tcx>,
176) -> Option<(DefId, Span, GenericArgsRef<'tcx>, Option<&'tcx Expr<'tcx>>, &'tcx [Expr<'tcx>])> {
177    if let ExprKind::Call(callee, args) = expr.kind
178        && let callee_ty = cx.typeck_results().expr_ty(callee)
179        && let ty::FnDef(callee_def_id, generic_args) = callee_ty.kind()
180    {
181        return Some((
182            *callee_def_id,
183            callee.span,
184            generic_args.no_bound_vars().unwrap(),
185            None,
186            args,
187        ));
188    }
189    if let ExprKind::MethodCall(segment, recv, args, _) = expr.kind
190        && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
191    {
192        let generic_args = cx.typeck_results().node_args(expr.hir_id);
193        return Some((method_def_id, segment.ident.span, generic_args, Some(recv), args));
194    }
195    None
196}
197
198#[doc =
r" The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`,"]
#[doc = r" where `ty::<kind>` would suffice."]
pub static USAGE_OF_TY_TYKIND: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::USAGE_OF_TY_TYKIND",
            default_level: ::rustc_lint_defs::Allow,
            desc: "usage of `ty::TyKind` outside of the `ty::sty` module",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
199    /// The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`,
200    /// where `ty::<kind>` would suffice.
201    pub rustc::USAGE_OF_TY_TYKIND,
202    Allow,
203    "usage of `ty::TyKind` outside of the `ty::sty` module",
204    report_in_external_macro: true
205}
206
207#[doc = r" The `usage_of_qualified_ty` lint detects usages of `ty::TyKind`,"]
#[doc = r" where `Ty` should be used instead."]
pub static USAGE_OF_QUALIFIED_TY: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::USAGE_OF_QUALIFIED_TY",
            default_level: ::rustc_lint_defs::Allow,
            desc: "using `ty::{Ty,TyCtxt}` instead of importing it",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
208    /// The `usage_of_qualified_ty` lint detects usages of `ty::TyKind`,
209    /// where `Ty` should be used instead.
210    pub rustc::USAGE_OF_QUALIFIED_TY,
211    Allow,
212    "using `ty::{Ty,TyCtxt}` instead of importing it",
213    report_in_external_macro: true
214}
215
216pub struct TyTyKind;
#[automatically_derived]
impl ::core::marker::Copy for TyTyKind { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TyTyKind { }
#[automatically_derived]
impl ::core::clone::Clone for TyTyKind {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for TyTyKind {
    fn name(&self) -> &'static str { "TyTyKind" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [USAGE_OF_TY_TYKIND, USAGE_OF_QUALIFIED_TY]))
    }
}
impl TyTyKind {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [USAGE_OF_TY_TYKIND, USAGE_OF_QUALIFIED_TY]))
    }
}declare_lint_pass!(TyTyKind => [
217    USAGE_OF_TY_TYKIND,
218    USAGE_OF_QUALIFIED_TY,
219]);
220
221impl<'tcx> LateLintPass<'tcx> for TyTyKind {
222    fn check_path(
223        &mut self,
224        cx: &LateContext<'tcx>,
225        path: &rustc_hir::Path<'tcx>,
226        _: rustc_hir::HirId,
227    ) {
228        if let Some(segment) = path.segments.iter().nth_back(1)
229            && lint_ty_kind_usage(cx, &segment.res)
230        {
231            let span =
232                path.span.with_hi(segment.args.map_or(segment.ident.span, |a| a.span_ext).hi());
233            cx.emit_span_lint(USAGE_OF_TY_TYKIND, path.span, TykindKind { suggestion: span });
234        }
235    }
236
237    fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) {
238        match &ty.kind {
239            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
240                if lint_ty_kind_usage(cx, &path.res) {
241                    let span = match cx.tcx.parent_hir_node(ty.hir_id) {
242                        hir::Node::PatExpr(hir::PatExpr {
243                            kind: hir::PatExprKind::Path(qpath),
244                            ..
245                        })
246                        | hir::Node::Pat(hir::Pat {
247                            kind:
248                                hir::PatKind::TupleStruct(qpath, ..) | hir::PatKind::Struct(qpath, ..),
249                            ..
250                        })
251                        | hir::Node::Expr(
252                            hir::Expr { kind: hir::ExprKind::Path(qpath), .. }
253                            | &hir::Expr { kind: hir::ExprKind::Struct(qpath, ..), .. },
254                        ) => {
255                            if let hir::QPath::TypeRelative(qpath_ty, ..) = qpath
256                                && qpath_ty.hir_id == ty.hir_id
257                            {
258                                Some(path.span)
259                            } else {
260                                None
261                            }
262                        }
263                        _ => None,
264                    };
265
266                    match span {
267                        Some(span) => {
268                            cx.emit_span_lint(
269                                USAGE_OF_TY_TYKIND,
270                                path.span,
271                                TykindKind { suggestion: span },
272                            );
273                        }
274                        None => cx.emit_span_lint(USAGE_OF_TY_TYKIND, path.span, TykindDiag),
275                    }
276                } else if !ty.span.from_expansion()
277                    && path.segments.len() > 1
278                    && let Some(ty) = is_ty_or_ty_ctxt(cx, path)
279                {
280                    cx.emit_span_lint(
281                        USAGE_OF_QUALIFIED_TY,
282                        path.span,
283                        TyQualified { ty, suggestion: path.span },
284                    );
285                }
286            }
287            _ => {}
288        }
289    }
290}
291
292fn lint_ty_kind_usage(cx: &LateContext<'_>, res: &Res) -> bool {
293    if let Some(did) = res.opt_def_id() {
294        cx.tcx.is_diagnostic_item(sym::TyKind, did) || cx.tcx.is_diagnostic_item(sym::IrTyKind, did)
295    } else {
296        false
297    }
298}
299
300fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &hir::Path<'_>) -> Option<String> {
301    match path.res {
302        Res::Def(_, def_id) => {
303            if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id) {
304                return Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}", name,
                gen_args(path.segments.last().unwrap())))
    })format!("{}{}", name, gen_args(path.segments.last().unwrap())));
305            }
306        }
307        // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
308        Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
309            if let ty::Adt(adt, args) =
310                cx.tcx.type_of(did).instantiate_identity().skip_norm_wip().kind()
311                && let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
312            {
313                return Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}<{1}>", name, args[0]))
    })format!("{}<{}>", name, args[0]));
314            }
315        }
316        _ => (),
317    }
318
319    None
320}
321
322fn gen_args(segment: &hir::PathSegment<'_>) -> String {
323    if let Some(args) = &segment.args {
324        let lifetimes = args
325            .args
326            .iter()
327            .filter_map(|arg| {
328                if let hir::GenericArg::Lifetime(lt) = arg {
329                    Some(lt.ident.to_string())
330                } else {
331                    None
332                }
333            })
334            .collect::<Vec<_>>();
335
336        if !lifetimes.is_empty() {
337            return ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", lifetimes.join(", ")))
    })format!("<{}>", lifetimes.join(", "));
338        }
339    }
340
341    String::new()
342}
343
344#[doc = r" The `non_glob_import_of_type_ir_inherent_item` lint detects"]
#[doc = r" non-glob imports of module `rustc_type_ir::inherent`."]
pub static NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT",
            default_level: ::rustc_lint_defs::Allow,
            desc: "non-glob import of `rustc_type_ir::inherent`",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
345    /// The `non_glob_import_of_type_ir_inherent_item` lint detects
346    /// non-glob imports of module `rustc_type_ir::inherent`.
347    pub rustc::NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
348    Allow,
349    "non-glob import of `rustc_type_ir::inherent`",
350    report_in_external_macro: true
351}
352
353#[doc =
r" The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`."]
#[doc = r""]
#[doc = r" This module should only be used within the trait solver."]
pub static USAGE_OF_TYPE_IR_INHERENT: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::USAGE_OF_TYPE_IR_INHERENT",
            default_level: ::rustc_lint_defs::Allow,
            desc: "usage `rustc_type_ir::inherent` outside of trait system",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
354    /// The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`.
355    ///
356    /// This module should only be used within the trait solver.
357    pub rustc::USAGE_OF_TYPE_IR_INHERENT,
358    Allow,
359    "usage `rustc_type_ir::inherent` outside of trait system",
360    report_in_external_macro: true
361}
362
363#[doc =
r" The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`,"]
#[doc = r" or `rustc_infer::InferCtxtLike`."]
#[doc = r""]
#[doc =
r" Methods of this trait should only be used within the type system abstraction layer,"]
#[doc =
r" and in the generic next trait solver implementation. Look for an analogously named"]
#[doc = r" method on `TyCtxt` or `InferCtxt` (respectively)."]
pub static USAGE_OF_TYPE_IR_TRAITS: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::USAGE_OF_TYPE_IR_TRAITS",
            default_level: ::rustc_lint_defs::Allow,
            desc: "usage `rustc_type_ir`-specific abstraction traits outside of trait system",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
364    /// The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`,
365    /// or `rustc_infer::InferCtxtLike`.
366    ///
367    /// Methods of this trait should only be used within the type system abstraction layer,
368    /// and in the generic next trait solver implementation. Look for an analogously named
369    /// method on `TyCtxt` or `InferCtxt` (respectively).
370    pub rustc::USAGE_OF_TYPE_IR_TRAITS,
371    Allow,
372    "usage `rustc_type_ir`-specific abstraction traits outside of trait system",
373    report_in_external_macro: true
374}
375#[doc =
r" The `direct_use_of_rustc_type_ir` lint detects usage of `rustc_type_ir`."]
#[doc = r""]
#[doc =
r" This module should only be used within the trait solver and some desirable"]
#[doc = r" crates like rustc_middle."]
pub static DIRECT_USE_OF_RUSTC_TYPE_IR: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::DIRECT_USE_OF_RUSTC_TYPE_IR",
            default_level: ::rustc_lint_defs::Allow,
            desc: "usage `rustc_type_ir` abstraction outside of trait system",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
376    /// The `direct_use_of_rustc_type_ir` lint detects usage of `rustc_type_ir`.
377    ///
378    /// This module should only be used within the trait solver and some desirable
379    /// crates like rustc_middle.
380    pub rustc::DIRECT_USE_OF_RUSTC_TYPE_IR,
381    Allow,
382    "usage `rustc_type_ir` abstraction outside of trait system",
383    report_in_external_macro: true
384}
385
386pub struct TypeIr;
#[automatically_derived]
impl ::core::marker::Copy for TypeIr { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TypeIr { }
#[automatically_derived]
impl ::core::clone::Clone for TypeIr {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for TypeIr {
    fn name(&self) -> &'static str { "TypeIr" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [DIRECT_USE_OF_RUSTC_TYPE_IR,
                        NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
                        USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]))
    }
}
impl TypeIr {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [DIRECT_USE_OF_RUSTC_TYPE_IR,
                        NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
                        USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]))
    }
}declare_lint_pass!(TypeIr => [
387    DIRECT_USE_OF_RUSTC_TYPE_IR,
388    NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
389    USAGE_OF_TYPE_IR_INHERENT,
390    USAGE_OF_TYPE_IR_TRAITS
391]);
392
393impl<'tcx> LateLintPass<'tcx> for TypeIr {
394    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
395        let res_def_id = match expr.kind {
396            hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => path.res.opt_def_id(),
397            hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::MethodCall(..) => {
398                cx.typeck_results().type_dependent_def_id(expr.hir_id)
399            }
400            _ => return,
401        };
402        let Some(res_def_id) = res_def_id else {
403            return;
404        };
405        if let Some(assoc_item) = cx.tcx.opt_associated_item(res_def_id)
406            && let Some(trait_def_id) = assoc_item.trait_container(cx.tcx)
407            && (cx.tcx.is_diagnostic_item(sym::type_ir_interner, trait_def_id)
408                | cx.tcx.is_diagnostic_item(sym::type_ir_infer_ctxt_like, trait_def_id))
409        {
410            cx.emit_span_lint(USAGE_OF_TYPE_IR_TRAITS, expr.span, TypeIrTraitUsage);
411        }
412    }
413
414    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
415        let rustc_hir::ItemKind::Use(tree) = item.kind else {
416            return;
417        };
418
419        check_use(cx, tree, ::alloc::vec::Vec::new()vec![]);
420
421        fn check_use<'tcx>(
422            cx: &LateContext<'_>,
423            tree: hir::UseTree<'tcx>,
424            mut prefix: Vec<&'tcx hir::PathSegment<'tcx>>,
425        ) {
426            let is_mod_inherent = |res: Res| {
427                res.opt_def_id()
428                    .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id))
429            };
430
431            prefix.extend(tree.prefix.segments);
432
433            match tree.kind {
434                rustc_hir::UseKind::Single(_) | rustc_hir::UseKind::Glob => {}
435                rustc_hir::UseKind::Nested { items } => {
436                    for (nested, _, _) in items {
437                        check_use(cx, *nested, prefix.clone())
438                    }
439                }
440            }
441
442            // Path segments except for the final.
443            if let Some(seg) = prefix.iter().find(|seg| is_mod_inherent(seg.res)) {
444                cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage);
445            }
446            // Final path resolutions, like `use rustc_type_ir::inherent`
447            else if let Some(type_ns) = tree.prefix.res.type_ns
448                && is_mod_inherent(type_ns)
449            {
450                cx.emit_span_lint(
451                    USAGE_OF_TYPE_IR_INHERENT,
452                    prefix.last().unwrap().ident.span,
453                    TypeIrInherentUsage,
454                );
455            }
456
457            let (lo, hi, snippet) = match prefix {
458                [.., penultimate, segment]
459                    if is_mod_inherent(penultimate.res)
460                        && let rustc_hir::UseKind::Single(ident) = tree.kind =>
461                {
462                    (segment.ident.span, ident.span, "*")
463                }
464                [.., segment]
465                    if let Some(type_ns) = tree.prefix.res.type_ns
466                        && is_mod_inherent(type_ns)
467                        && let rustc_hir::UseKind::Single(ident) = tree.kind =>
468                {
469                    let (lo, snippet) =
470                        match cx.tcx.sess.source_map().span_to_snippet(tree.prefix.span).as_deref()
471                        {
472                            Ok("self") => (tree.prefix.span, "*"),
473                            _ => (segment.ident.span.shrink_to_hi(), "::*"),
474                        };
475                    (lo, if segment.ident == ident { lo } else { ident.span }, snippet)
476                }
477                _ => return,
478            };
479            cx.emit_span_lint(
480                NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
481                tree.prefix.span,
482                NonGlobImportTypeIrInherent {
483                    suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)),
484                    snippet,
485                },
486            );
487        }
488    }
489
490    fn check_path(
491        &mut self,
492        cx: &LateContext<'tcx>,
493        path: &rustc_hir::Path<'tcx>,
494        _: rustc_hir::HirId,
495    ) {
496        if let Some(seg) = path.segments.iter().find(|seg| {
497            seg.res
498                .opt_def_id()
499                .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir, def_id))
500        }) {
501            cx.emit_span_lint(DIRECT_USE_OF_RUSTC_TYPE_IR, seg.ident.span, TypeIrDirectUse);
502        }
503    }
504}
505
506#[doc =
r" The `lint_pass_impl_without_macro` detects manual implementations of a lint"]
#[doc = r" pass, without using [`declare_lint_pass`] or [`impl_lint_pass`]."]
pub static LINT_PASS_IMPL_WITHOUT_MACRO: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::LINT_PASS_IMPL_WITHOUT_MACRO",
            default_level: ::rustc_lint_defs::Allow,
            desc: "`impl LintPass` without the `declare_lint_pass!` or `impl_lint_pass!` macros",
            report_in_external_macro: false,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
507    /// The `lint_pass_impl_without_macro` detects manual implementations of a lint
508    /// pass, without using [`declare_lint_pass`] or [`impl_lint_pass`].
509    pub rustc::LINT_PASS_IMPL_WITHOUT_MACRO,
510    Allow,
511    "`impl LintPass` without the `declare_lint_pass!` or `impl_lint_pass!` macros"
512}
513
514pub struct LintPassImpl;
#[automatically_derived]
impl ::core::marker::Copy for LintPassImpl { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for LintPassImpl { }
#[automatically_derived]
impl ::core::clone::Clone for LintPassImpl {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for LintPassImpl {
    fn name(&self) -> &'static str { "LintPassImpl" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [LINT_PASS_IMPL_WITHOUT_MACRO]))
    }
}
impl LintPassImpl {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [LINT_PASS_IMPL_WITHOUT_MACRO]))
    }
}declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]);
515
516impl EarlyLintPass for LintPassImpl {
517    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
518        if let ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) = &item.kind
519            && let Some(last) = of_trait.trait_ref.path.segments.last()
520            && last.ident.name == sym::LintPass
521        {
522            let expn_data = of_trait.trait_ref.path.span.ctxt().outer_expn_data();
523            let call_site = expn_data.call_site;
524            if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass)
525                && call_site.ctxt().outer_expn_data().kind
526                    != ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass)
527            {
528                cx.emit_span_lint(
529                    LINT_PASS_IMPL_WITHOUT_MACRO,
530                    of_trait.trait_ref.path.span,
531                    LintPassByHand,
532                );
533            }
534        }
535    }
536}
537
538#[doc =
r" The `bad_opt_access` lint detects accessing options by field instead of"]
#[doc = r" the wrapper function."]
pub static BAD_OPT_ACCESS: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::BAD_OPT_ACCESS",
            default_level: ::rustc_lint_defs::Deny,
            desc: "prevent using options by field access when there is a wrapper function",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
539    /// The `bad_opt_access` lint detects accessing options by field instead of
540    /// the wrapper function.
541    pub rustc::BAD_OPT_ACCESS,
542    Deny,
543    "prevent using options by field access when there is a wrapper function",
544    report_in_external_macro: true
545}
546
547pub struct BadOptAccess;
#[automatically_derived]
impl ::core::marker::Copy for BadOptAccess { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for BadOptAccess { }
#[automatically_derived]
impl ::core::clone::Clone for BadOptAccess {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for BadOptAccess {
    fn name(&self) -> &'static str { "BadOptAccess" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [BAD_OPT_ACCESS]))
    }
}
impl BadOptAccess {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [BAD_OPT_ACCESS]))
    }
}declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]);
548
549impl LateLintPass<'_> for BadOptAccess {
550    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
551        let hir::ExprKind::Field(base, target) = expr.kind else { return };
552        let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return };
553        // Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be
554        // avoided.
555        if !{
        {
            'done:
                {
                for i in
                    ::rustc_attr_ir::HasAttrs::get_attrs(adt_def.did(), &cx.tcx)
                    {
                    #[allow(unused_imports)]
                    use ::rustc_attr_ir::AttributeKind::*;
                    let i: &::rustc_attr_ir::Attribute = i;
                    match i {
                        ::rustc_attr_ir::Attribute::Parsed(RustcLintOptTy) => {
                            break 'done Some(());
                        }
                        ::rustc_attr_ir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(cx.tcx, adt_def.did(), RustcLintOptTy) {
556            return;
557        }
558
559        for field in adt_def.all_fields() {
560            if field.name == target.name
561                && let Some(lint_message) = {
    {
        'done:
            {
            for i in ::rustc_attr_ir::HasAttrs::get_attrs(field.did, &cx.tcx)
                {
                #[allow(unused_imports)]
                use ::rustc_attr_ir::AttributeKind::*;
                let i: &::rustc_attr_ir::Attribute = i;
                match i {
                    ::rustc_attr_ir::Attribute::Parsed(RustcLintOptDenyFieldAccess {
                        lint_message }) => {
                        break 'done Some(lint_message);
                    }
                    ::rustc_attr_ir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }
}find_attr!(cx.tcx, field.did, RustcLintOptDenyFieldAccess { lint_message, } => lint_message)
562            {
563                cx.emit_span_lint(
564                    BAD_OPT_ACCESS,
565                    expr.span,
566                    BadOptAccessDiag { msg: lint_message.as_str() },
567                );
568            }
569        }
570    }
571}
572
573#[doc =
r" The `symbol_intern_string_literal` lint detects `Symbol::intern` or `Ident::from_str_and_span` being called on a string literal"]
pub static SYMBOL_INTERN_STRING_LITERAL: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::SYMBOL_INTERN_STRING_LITERAL",
            default_level: ::rustc_lint_defs::Allow,
            desc: "Forbid uses of string literals in `Symbol::intern` or `Ident::from_str_and_span`, suggesting preinterning instead",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
574    /// The `symbol_intern_string_literal` lint detects `Symbol::intern` or `Ident::from_str_and_span` being called on a string literal
575    pub rustc::SYMBOL_INTERN_STRING_LITERAL,
576    Allow,
577    "Forbid uses of string literals in `Symbol::intern` or `Ident::from_str_and_span`, suggesting preinterning instead",
578    report_in_external_macro: true
579}
580
581pub struct SymbolInternStringLiteral;
#[automatically_derived]
impl ::core::marker::Copy for SymbolInternStringLiteral { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SymbolInternStringLiteral { }
#[automatically_derived]
impl ::core::clone::Clone for SymbolInternStringLiteral {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for SymbolInternStringLiteral {
    fn name(&self) -> &'static str { "SymbolInternStringLiteral" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [SYMBOL_INTERN_STRING_LITERAL]))
    }
}
impl SymbolInternStringLiteral {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [SYMBOL_INTERN_STRING_LITERAL]))
    }
}declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
582
583impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
584    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
585        if let hir::ExprKind::Call(path, args) = expr.kind
586            && let hir::ExprKind::Path(ref qpath) = path.kind
587            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
588        {
589            let (arg, fn_name) = if cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
590                && let [arg] = args
591            {
592                (arg, "Symbol::intern")
593            } else if cx.tcx.is_diagnostic_item(sym::ident_from_str_and_span, def_id)
594                && let [arg, _] = args
595            {
596                (arg, "Ident::from_str_and_span")
597            } else {
598                return;
599            };
600            if let hir::ExprKind::Lit(kind) = arg.kind
601                && let rustc_ast::LitKind::Str(_, _) = kind.node
602            {
603                cx.emit_span_lint(
604                    SYMBOL_INTERN_STRING_LITERAL,
605                    kind.span,
606                    SymbolInternStringLiteralDiag { fn_name },
607                );
608            }
609        }
610    }
611}
612
613#[doc =
r" The `implicit_sysroot_crate_import` detects use of `extern crate` to import non-sysroot crates"]
#[doc =
r" (e.g. crates.io deps) from the sysroot, which is dangerous because these crates are not guaranteed"]
#[doc =
r" to exist exactly once, and so may be missing entirely or appear multiple times resulting in ambiguity."]
pub static IMPLICIT_SYSROOT_CRATE_IMPORT: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::IMPLICIT_SYSROOT_CRATE_IMPORT",
            default_level: ::rustc_lint_defs::Allow,
            desc: "Forbid uses of non-sysroot crates in `extern crate`",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
614    /// The `implicit_sysroot_crate_import` detects use of `extern crate` to import non-sysroot crates
615    /// (e.g. crates.io deps) from the sysroot, which is dangerous because these crates are not guaranteed
616    /// to exist exactly once, and so may be missing entirely or appear multiple times resulting in ambiguity.
617    pub rustc::IMPLICIT_SYSROOT_CRATE_IMPORT,
618    Allow,
619    "Forbid uses of non-sysroot crates in `extern crate`",
620    report_in_external_macro: true
621}
622
623pub struct ImplicitSysrootCrateImport;
#[automatically_derived]
impl ::core::marker::Copy for ImplicitSysrootCrateImport { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ImplicitSysrootCrateImport { }
#[automatically_derived]
impl ::core::clone::Clone for ImplicitSysrootCrateImport {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for ImplicitSysrootCrateImport {
    fn name(&self) -> &'static str { "ImplicitSysrootCrateImport" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [IMPLICIT_SYSROOT_CRATE_IMPORT]))
    }
}
impl ImplicitSysrootCrateImport {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [IMPLICIT_SYSROOT_CRATE_IMPORT]))
    }
}declare_lint_pass!(ImplicitSysrootCrateImport => [IMPLICIT_SYSROOT_CRATE_IMPORT]);
624
625impl EarlyLintPass for ImplicitSysrootCrateImport {
626    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
627        fn is_whitelisted(crate_name: &str) -> bool {
628            // Whitelist of allowed crates.
629            crate_name.starts_with("rustc_")
630                || #[allow(non_exhaustive_omitted_patterns)] match crate_name {
    "test" | "self" | "core" | "alloc" | "std" | "proc_macro" |
        "tikv_jemalloc_sys" => true,
    _ => false,
}matches!(
631                    crate_name,
632                    "test" | "self" | "core" | "alloc" | "std" | "proc_macro" | "tikv_jemalloc_sys"
633                )
634        }
635
636        if let ast::ItemKind::ExternCrate(original_name, imported_name) = &item.kind {
637            let name = original_name.as_ref().unwrap_or(&imported_name.name).as_str();
638            let externs = &cx.builder.sess().opts.externs;
639            if externs.get(name).is_none() && !is_whitelisted(name) {
640                cx.emit_span_lint(
641                    IMPLICIT_SYSROOT_CRATE_IMPORT,
642                    item.span,
643                    ImplicitSysrootCrateImportDiag { name },
644                );
645            }
646        }
647    }
648}
649
650pub static BAD_USE_OF_FIND_ATTR: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::BAD_USE_OF_FIND_ATTR",
            default_level: ::rustc_lint_defs::Allow,
            desc: "Forbid `AttributeKind::` as a prefix in `find_attr!` macros.",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
651    pub rustc::BAD_USE_OF_FIND_ATTR,
652    Allow,
653    "Forbid `AttributeKind::` as a prefix in `find_attr!` macros.",
654    report_in_external_macro: true
655}
656pub struct BadUseOfFindAttr;
#[automatically_derived]
impl ::core::marker::Copy for BadUseOfFindAttr { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for BadUseOfFindAttr { }
#[automatically_derived]
impl ::core::clone::Clone for BadUseOfFindAttr {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for BadUseOfFindAttr {
    fn name(&self) -> &'static str { "BadUseOfFindAttr" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [BAD_USE_OF_FIND_ATTR]))
    }
}
impl BadUseOfFindAttr {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [BAD_USE_OF_FIND_ATTR]))
    }
}declare_lint_pass!(BadUseOfFindAttr => [BAD_USE_OF_FIND_ATTR]);
657
658impl EarlyLintPass for BadUseOfFindAttr {
659    fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &rustc_ast::Arm) {
660        fn path_contains_attribute_kind(cx: &EarlyContext<'_>, path: &Path) {
661            for segment in &path.segments {
662                if segment.ident.as_str() == "AttributeKind" {
663                    cx.emit_span_lint(
664                        BAD_USE_OF_FIND_ATTR,
665                        segment.span(),
666                        AttributeKindInFindAttr,
667                    );
668                }
669            }
670        }
671
672        fn find_attr_kind_in_pat(cx: &EarlyContext<'_>, pat: &Pat) {
673            match &pat.kind {
674                PatKind::Struct(_, path, fields, _) => {
675                    path_contains_attribute_kind(cx, path);
676                    for field in fields {
677                        find_attr_kind_in_pat(cx, &field.pat);
678                    }
679                }
680                PatKind::TupleStruct(_, path, fields) => {
681                    path_contains_attribute_kind(cx, path);
682                    for field in fields {
683                        find_attr_kind_in_pat(cx, &field);
684                    }
685                }
686                PatKind::Or(options) => {
687                    for pat in options {
688                        find_attr_kind_in_pat(cx, pat);
689                    }
690                }
691                PatKind::Path(_, path) => {
692                    path_contains_attribute_kind(cx, path);
693                }
694                PatKind::Tuple(elems) => {
695                    for pat in elems {
696                        find_attr_kind_in_pat(cx, pat);
697                    }
698                }
699                PatKind::Deref(pat) => {
700                    find_attr_kind_in_pat(cx, pat);
701                }
702                PatKind::Ref(..) => {
703                    find_attr_kind_in_pat(cx, pat);
704                }
705                PatKind::Slice(elems) => {
706                    for pat in elems {
707                        find_attr_kind_in_pat(cx, pat);
708                    }
709                }
710
711                PatKind::Guard(pat, ..) => {
712                    find_attr_kind_in_pat(cx, pat);
713                }
714                PatKind::Paren(pat) => {
715                    find_attr_kind_in_pat(cx, pat);
716                }
717                PatKind::Expr(..)
718                | PatKind::Range(..)
719                | PatKind::MacCall(..)
720                | PatKind::Rest
721                | PatKind::Missing
722                | PatKind::Err(..)
723                | PatKind::Ident(..)
724                | PatKind::Never
725                | PatKind::Wild => {}
726            }
727        }
728
729        if let Some(expn_data) = arm.span.source_callee()
730            && let ExpnKind::Macro(_, name) = expn_data.kind
731            && name.as_str() == "find_attr"
732        {
733            find_attr_kind_in_pat(cx, &arm.pat);
734        }
735    }
736}
737
738pub static RUSTC_MUST_MATCH_EXHAUSTIVELY: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::RUSTC_MUST_MATCH_EXHAUSTIVELY",
            default_level: ::rustc_lint_defs::Allow,
            desc: "Forbids matches with wildcards, or if-let matching on enums marked with `#[rustc_must_match_exhaustively]`",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
739    pub rustc::RUSTC_MUST_MATCH_EXHAUSTIVELY,
740    Allow,
741    "Forbids matches with wildcards, or if-let matching on enums marked with `#[rustc_must_match_exhaustively]`",
742    report_in_external_macro: true
743}
744pub struct RustcMustMatchExhaustively;
#[automatically_derived]
impl ::core::marker::Copy for RustcMustMatchExhaustively { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for RustcMustMatchExhaustively { }
#[automatically_derived]
impl ::core::clone::Clone for RustcMustMatchExhaustively {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for RustcMustMatchExhaustively {
    fn name(&self) -> &'static str { "RustcMustMatchExhaustively" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [RUSTC_MUST_MATCH_EXHAUSTIVELY]))
    }
}
impl RustcMustMatchExhaustively {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [RUSTC_MUST_MATCH_EXHAUSTIVELY]))
    }
}declare_lint_pass!(RustcMustMatchExhaustively => [RUSTC_MUST_MATCH_EXHAUSTIVELY]);
745
746fn is_rustc_must_match_exhaustively(cx: &LateContext<'_>, id: HirId) -> Option<Span> {
747    let res = cx.typeck_results();
748
749    let ty = res.node_type(id);
750
751    let ty = if let ty::Ref(_, ty, _) = ty.kind() { *ty } else { ty };
752
753    if let Some(adt_def) = ty.ty_adt_def()
754        && adt_def.is_enum()
755    {
756        {
    {
        'done:
            {
            for i in
                ::rustc_attr_ir::HasAttrs::get_attrs(adt_def.did(), &cx.tcx) {
                #[allow(unused_imports)]
                use ::rustc_attr_ir::AttributeKind::*;
                let i: &::rustc_attr_ir::Attribute = i;
                match i {
                    ::rustc_attr_ir::Attribute::Parsed(RustcMustMatchExhaustively(span))
                        => {
                        break 'done Some(*span);
                    }
                    ::rustc_attr_ir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }
}find_attr!(cx.tcx, adt_def.did(), RustcMustMatchExhaustively(span) => *span)
757    } else {
758        None
759    }
760}
761
762fn pat_is_not_exhaustive_heuristic(pat: &hir::Pat<'_>) -> Option<(Span, &'static str)> {
763    match pat.kind {
764        hir::PatKind::Missing => None,
765        hir::PatKind::Wild => Some((pat.span, "because of this wildcard pattern")),
766        hir::PatKind::Binding(_, _, _, Some(pat)) => pat_is_not_exhaustive_heuristic(pat),
767        hir::PatKind::Binding(..) => Some((pat.span, "because of this variable binding")),
768        hir::PatKind::Struct(..) => None,
769        hir::PatKind::TupleStruct(..) => None,
770        hir::PatKind::Or(..) => None,
771        hir::PatKind::Never => None,
772        hir::PatKind::Tuple(..) => None,
773        hir::PatKind::Deref(pat) => pat_is_not_exhaustive_heuristic(&*pat),
774        hir::PatKind::Ref(pat, _, _) => pat_is_not_exhaustive_heuristic(&*pat),
775        hir::PatKind::Expr(..) => None,
776        hir::PatKind::Guard(..) => None,
777        hir::PatKind::Range(..) => None,
778        hir::PatKind::Slice(..) => None,
779        hir::PatKind::Err(..) => None,
780    }
781}
782
783impl<'tcx> LateLintPass<'tcx> for RustcMustMatchExhaustively {
784    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
785        match expr.kind {
786            // This is not perfect exhaustiveness checking, that's why this is just a rustc internal
787            // attribute. But it catches most reasonable cases
788            hir::ExprKind::Match(expr, arms, _) => {
789                if let Some(attr_span) = is_rustc_must_match_exhaustively(cx, expr.hir_id) {
790                    for arm in arms {
791                        if let Some((span, message)) = pat_is_not_exhaustive_heuristic(arm.pat) {
792                            cx.emit_span_lint(
793                                RUSTC_MUST_MATCH_EXHAUSTIVELY,
794                                expr.span,
795                                RustcMustMatchExhaustivelyNotExhaustive {
796                                    attr_span,
797                                    pat_span: span,
798                                    message,
799                                },
800                            );
801                        }
802                    }
803                }
804            }
805            hir::ExprKind::Let(expr, ..) => {
806                if let Some(attr_span) = is_rustc_must_match_exhaustively(cx, expr.init.hir_id) {
807                    cx.emit_span_lint(
808                        RUSTC_MUST_MATCH_EXHAUSTIVELY,
809                        expr.span,
810                        RustcMustMatchExhaustivelyNotExhaustive {
811                            attr_span,
812                            pat_span: expr.span,
813                            message: "using `if let` only matches on one variant (try using `match`)",
814                        },
815                    );
816                }
817            }
818            _ => {}
819        }
820    }
821
822    fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx rustc_hir::Stmt<'tcx>) {
823        match stmt.kind {
824            rustc_hir::StmtKind::Let(let_stmt) => {
825                if let_stmt.els.is_some()
826                    && let Some(attr_span) =
827                        is_rustc_must_match_exhaustively(cx, let_stmt.pat.hir_id)
828                {
829                    cx.emit_span_lint(
830                        RUSTC_MUST_MATCH_EXHAUSTIVELY,
831                        let_stmt.span,
832                        RustcMustMatchExhaustivelyNotExhaustive {
833                            attr_span,
834                            pat_span: let_stmt.pat.span,
835                            message: "using `let else` only matches on one variant (try using `match`)",
836                        },
837                    );
838                }
839            }
840            _ => {}
841        }
842    }
843}
844
845#[doc =
r" The `missing_generic_type_visitable_derive` lint detects types implementing `TypeVisitable`"]
#[doc = r" but not deriving `GenericTypeVisitable`."]
#[doc = r""]
#[doc =
r" `GenericTypeVisitable` is the analog of `TypeVisitable` used by rust-analyzer, and needs to"]
#[doc =
r" be implemented whenever `TypeVisitable` is. See [`rustc_type_ir::generic_visit`] for more"]
#[doc = r" information."]
pub static MISSING_GENERIC_TYPE_VISITABLE_DERIVE: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::MISSING_GENERIC_TYPE_VISITABLE_DERIVE",
            default_level: ::rustc_lint_defs::Allow,
            desc: "Forbid implementing `TypeVisitable` without deriving `GenericTypeVisitable`",
            report_in_external_macro: true,
            is_externally_loaded: true,
            ..
        };declare_tool_lint! {
846    /// The `missing_generic_type_visitable_derive` lint detects types implementing `TypeVisitable`
847    /// but not deriving `GenericTypeVisitable`.
848    ///
849    /// `GenericTypeVisitable` is the analog of `TypeVisitable` used by rust-analyzer, and needs to
850    /// be implemented whenever `TypeVisitable` is. See [`rustc_type_ir::generic_visit`] for more
851    /// information.
852    pub rustc::MISSING_GENERIC_TYPE_VISITABLE_DERIVE,
853    // This lint is meant to be manually enabled in selected crates (currently only `rustc_type_ir`)
854    Allow,
855    "Forbid implementing `TypeVisitable` without deriving `GenericTypeVisitable`",
856    report_in_external_macro: true
857}
858
859pub struct MissingGenericTypeVisitableDerive;
#[automatically_derived]
impl ::core::marker::Copy for MissingGenericTypeVisitableDerive { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for MissingGenericTypeVisitableDerive
    {
}
#[automatically_derived]
impl ::core::clone::Clone for MissingGenericTypeVisitableDerive {
    #[inline]
    fn clone(&self) -> Self { *self }
}
impl ::rustc_lint_defs::LintPass for MissingGenericTypeVisitableDerive {
    fn name(&self) -> &'static str { "MissingGenericTypeVisitableDerive" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [MISSING_GENERIC_TYPE_VISITABLE_DERIVE]))
    }
}
impl MissingGenericTypeVisitableDerive {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                [MISSING_GENERIC_TYPE_VISITABLE_DERIVE]))
    }
}declare_lint_pass!(MissingGenericTypeVisitableDerive => [MISSING_GENERIC_TYPE_VISITABLE_DERIVE]);
860
861impl<'tcx> LateLintPass<'tcx> for MissingGenericTypeVisitableDerive {
862    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
863        // lint ADTs except unions, as neither trait can be implemented on the latter
864        if #[allow(non_exhaustive_omitted_patterns)] match item.kind {
    hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) => true,
    _ => false,
}matches!(item.kind, hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..))
865            && let Some(regular_id) = cx.tcx.get_diagnostic_item(sym::TypeVisitable)
866            && let Some(generic_id) = cx.tcx.get_diagnostic_item(sym::GenericTypeVisitable)
867            && let (infcx, param_env) = cx.tcx.infer_ctxt().build_with_typing_env(cx.typing_env())
868            && let self_ty = {
869                let self_id = item.owner_id.to_def_id();
870                let args = infcx.fresh_args_for_item(DUMMY_SP, self_id);
871                cx.tcx.type_of(self_id).instantiate(cx.tcx, args).skip_norm_wip()
872            }
873            // check whether `Self: TypeVisitable<I>` holds for some `I`..
874            && {
875                let predicate =
876                    ty::TraitRef::new(cx.tcx, regular_id, [self_ty, infcx.next_ty_var(DUMMY_SP)]);
877                let obligation =
878                    Obligation::new(cx.tcx, ObligationCause::dummy(), param_env, predicate);
879
880                // NOTE: I initially went with `predicate_must_hold_modulo_regions` (which is what's
881                // used by Clippy's [`implements_trait`](https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html),
882                // but that returned `false` more often than I'd hoped, and so I went with the
883                // next-most strict function.
884                infcx.predicate_may_hold(&obligation)
885            }
886            // ..while `Self: GenericTypeVisitable<V>` doesn't
887            && {
888                let predicate =
889                    ty::TraitRef::new(cx.tcx, generic_id, [self_ty, infcx.next_ty_var(DUMMY_SP)]);
890                let obligation =
891                    Obligation::new(cx.tcx, ObligationCause::dummy(), param_env, predicate);
892
893                !infcx.predicate_may_hold(&obligation)
894            }
895        {
896            cx.emit_span_lint(
897                MISSING_GENERIC_TYPE_VISITABLE_DERIVE,
898                item.span,
899                MissingGenericTypeVisitableDeriveDiag,
900            );
901        }
902    }
903}