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_hir::attrs::AttributeKind;
5use rustc_hir::def::Res;
6use rustc_hir::def_id::DefId;
7use rustc_hir::{Expr, ExprKind, HirId, find_attr};
8use rustc_middle::ty::{self, GenericArgsRef, PredicatePolarity};
9use rustc_session::{declare_lint_pass, declare_tool_lint};
10use rustc_span::hygiene::{ExpnKind, MacroKind};
11use rustc_span::{Span, sym};
12use {rustc_ast as ast, rustc_hir as hir};
13
14use crate::lints::{
15    BadOptAccessDiag, DefaultHashTypesDiag, ImplicitSysrootCrateImportDiag, LintPassByHand,
16    NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, SpanUseEqCtxtDiag,
17    SymbolInternStringLiteralDiag, TyQualified, TykindDiag, TykindKind, TypeIrDirectUse,
18    TypeIrInherentUsage, TypeIrTraitUsage,
19};
20use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
21
22#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
23    /// The `default_hash_type` lint detects use of [`std::collections::HashMap`] and
24    /// [`std::collections::HashSet`], suggesting the use of `FxHashMap`/`FxHashSet`.
25    ///
26    /// This can help as `FxHasher` can perform better than the default hasher. DOS protection is
27    /// not required as input is assumed to be trusted.
28    pub rustc::DEFAULT_HASH_TYPES,
29    Allow,
30    "forbid HashMap and HashSet and suggest the FxHash* variants",
31    report_in_external_macro: true
32}
33
34pub 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) -> DefaultHashTypes { *self }
}
impl ::rustc_lint_defs::LintPass for DefaultHashTypes {
    fn name(&self) -> &'static str { "DefaultHashTypes" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([DEFAULT_HASH_TYPES]))
    }
}
impl DefaultHashTypes {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([DEFAULT_HASH_TYPES]))
    }
}declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]);
35
36impl LateLintPass<'_> for DefaultHashTypes {
37    fn check_path(&mut self, cx: &LateContext<'_>, path: &hir::Path<'_>, hir_id: HirId) {
38        let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return };
39        if #[allow(non_exhaustive_omitted_patterns)] match cx.tcx.hir_node(hir_id) {
    hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. }) => true,
    _ => false,
}matches!(
40            cx.tcx.hir_node(hir_id),
41            hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. })
42        ) {
43            // Don't lint imports, only actual usages.
44            return;
45        }
46        let preferred = match cx.tcx.get_diagnostic_name(def_id) {
47            Some(sym::HashMap) => "FxHashMap",
48            Some(sym::HashSet) => "FxHashSet",
49            _ => return,
50        };
51        cx.emit_span_lint(
52            DEFAULT_HASH_TYPES,
53            path.span,
54            DefaultHashTypesDiag { preferred, used: cx.tcx.item_name(def_id) },
55        );
56    }
57}
58
59#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
60    /// The `potential_query_instability` lint detects use of methods which can lead to
61    /// potential query instability, such as iterating over a `HashMap`.
62    ///
63    /// Due to the [incremental compilation](https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation.html) model,
64    /// queries must return deterministic, stable results. `HashMap` iteration order can change
65    /// between compilations, and will introduce instability if query results expose the order.
66    pub rustc::POTENTIAL_QUERY_INSTABILITY,
67    Allow,
68    "require explicit opt-in when using potentially unstable methods or functions",
69    report_in_external_macro: true
70}
71
72#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
73    /// The `untracked_query_information` lint detects use of methods which leak information not
74    /// tracked by the query system, such as whether a `Steal<T>` value has already been stolen. In
75    /// order not to break incremental compilation, such methods must be used very carefully or not
76    /// at all.
77    pub rustc::UNTRACKED_QUERY_INFORMATION,
78    Allow,
79    "require explicit opt-in when accessing information not tracked by the query system",
80    report_in_external_macro: true
81}
82
83pub 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) -> QueryStability { *self }
}
impl ::rustc_lint_defs::LintPass for QueryStability {
    fn name(&self) -> &'static str { "QueryStability" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([POTENTIAL_QUERY_INSTABILITY,
                        UNTRACKED_QUERY_INFORMATION]))
    }
}
impl QueryStability {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([POTENTIAL_QUERY_INSTABILITY,
                        UNTRACKED_QUERY_INFORMATION]))
    }
}declare_lint_pass!(QueryStability => [POTENTIAL_QUERY_INSTABILITY, UNTRACKED_QUERY_INFORMATION]);
84
85impl<'tcx> LateLintPass<'tcx> for QueryStability {
86    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
87        if let Some((callee_def_id, span, generic_args, _recv, _args)) =
88            get_callee_span_generic_args_and_args(cx, expr)
89            && let Ok(Some(instance)) =
90                ty::Instance::try_resolve(cx.tcx, cx.typing_env(), callee_def_id, generic_args)
91        {
92            let def_id = instance.def_id();
93            if {
    {
            'done:
                {
                for i in cx.tcx.get_all_attrs(def_id) {
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(AttributeKind::RustcLintQueryInstability)
                            => {
                            break 'done Some(());
                        }
                        _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::RustcLintQueryInstability) {
94                cx.emit_span_lint(
95                    POTENTIAL_QUERY_INSTABILITY,
96                    span,
97                    QueryInstability { query: cx.tcx.item_name(def_id) },
98                );
99            } else if has_unstable_into_iter_predicate(cx, callee_def_id, generic_args) {
100                let call_span = span.with_hi(expr.span.hi());
101                cx.emit_span_lint(
102                    POTENTIAL_QUERY_INSTABILITY,
103                    call_span,
104                    QueryInstability { query: sym::into_iter },
105                );
106            }
107
108            if {
    {
            'done:
                {
                for i in cx.tcx.get_all_attrs(def_id) {
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(AttributeKind::RustcLintUntrackedQueryInformation)
                            => {
                            break 'done Some(());
                        }
                        _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(
109                cx.tcx.get_all_attrs(def_id),
110                AttributeKind::RustcLintUntrackedQueryInformation
111            ) {
112                cx.emit_span_lint(
113                    UNTRACKED_QUERY_INFORMATION,
114                    span,
115                    QueryUntracked { method: cx.tcx.item_name(def_id) },
116                );
117            }
118        }
119    }
120}
121
122fn has_unstable_into_iter_predicate<'tcx>(
123    cx: &LateContext<'tcx>,
124    callee_def_id: DefId,
125    generic_args: GenericArgsRef<'tcx>,
126) -> bool {
127    let Some(into_iterator_def_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator) else {
128        return false;
129    };
130    let Some(into_iter_fn_def_id) = cx.tcx.lang_items().into_iter_fn() else {
131        return false;
132    };
133    let predicates = cx.tcx.predicates_of(callee_def_id).instantiate(cx.tcx, generic_args);
134    for (predicate, _) in predicates {
135        let Some(trait_pred) = predicate.as_trait_clause() else {
136            continue;
137        };
138        if trait_pred.def_id() != into_iterator_def_id
139            || trait_pred.polarity() != PredicatePolarity::Positive
140        {
141            continue;
142        }
143        // `IntoIterator::into_iter` has no additional method args.
144        let into_iter_fn_args =
145            cx.tcx.instantiate_bound_regions_with_erased(trait_pred).trait_ref.args;
146        let Ok(Some(instance)) = ty::Instance::try_resolve(
147            cx.tcx,
148            cx.typing_env(),
149            into_iter_fn_def_id,
150            into_iter_fn_args,
151        ) else {
152            continue;
153        };
154        // Does the input type's `IntoIterator` implementation have the
155        // `rustc_lint_query_instability` attribute on its `into_iter` method?
156        if {
    {
            'done:
                {
                for i in cx.tcx.get_all_attrs(instance.def_id()) {
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(AttributeKind::RustcLintQueryInstability)
                            => {
                            break 'done Some(());
                        }
                        _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(
157            cx.tcx.get_all_attrs(instance.def_id()),
158            AttributeKind::RustcLintQueryInstability
159        ) {
160            return true;
161        }
162    }
163    false
164}
165
166/// Checks whether an expression is a function or method call and, if so, returns its `DefId`,
167/// `Span`, `GenericArgs`, and arguments. This is a slight augmentation of a similarly named Clippy
168/// function, `get_callee_generic_args_and_args`.
169fn get_callee_span_generic_args_and_args<'tcx>(
170    cx: &LateContext<'tcx>,
171    expr: &'tcx Expr<'tcx>,
172) -> Option<(DefId, Span, GenericArgsRef<'tcx>, Option<&'tcx Expr<'tcx>>, &'tcx [Expr<'tcx>])> {
173    if let ExprKind::Call(callee, args) = expr.kind
174        && let callee_ty = cx.typeck_results().expr_ty(callee)
175        && let ty::FnDef(callee_def_id, generic_args) = callee_ty.kind()
176    {
177        return Some((*callee_def_id, callee.span, generic_args, None, args));
178    }
179    if let ExprKind::MethodCall(segment, recv, args, _) = expr.kind
180        && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
181    {
182        let generic_args = cx.typeck_results().node_args(expr.hir_id);
183        return Some((method_def_id, segment.ident.span, generic_args, Some(recv), args));
184    }
185    None
186}
187
188#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
189    /// The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`,
190    /// where `ty::<kind>` would suffice.
191    pub rustc::USAGE_OF_TY_TYKIND,
192    Allow,
193    "usage of `ty::TyKind` outside of the `ty::sty` module",
194    report_in_external_macro: true
195}
196
197#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
198    /// The `usage_of_qualified_ty` lint detects usages of `ty::TyKind`,
199    /// where `Ty` should be used instead.
200    pub rustc::USAGE_OF_QUALIFIED_TY,
201    Allow,
202    "using `ty::{Ty,TyCtxt}` instead of importing it",
203    report_in_external_macro: true
204}
205
206pub 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) -> TyTyKind { *self }
}
impl ::rustc_lint_defs::LintPass for TyTyKind {
    fn name(&self) -> &'static str { "TyTyKind" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([USAGE_OF_TY_TYKIND,
                        USAGE_OF_QUALIFIED_TY]))
    }
}
impl TyTyKind {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([USAGE_OF_TY_TYKIND,
                        USAGE_OF_QUALIFIED_TY]))
    }
}declare_lint_pass!(TyTyKind => [
207    USAGE_OF_TY_TYKIND,
208    USAGE_OF_QUALIFIED_TY,
209]);
210
211impl<'tcx> LateLintPass<'tcx> for TyTyKind {
212    fn check_path(
213        &mut self,
214        cx: &LateContext<'tcx>,
215        path: &rustc_hir::Path<'tcx>,
216        _: rustc_hir::HirId,
217    ) {
218        if let Some(segment) = path.segments.iter().nth_back(1)
219            && lint_ty_kind_usage(cx, &segment.res)
220        {
221            let span =
222                path.span.with_hi(segment.args.map_or(segment.ident.span, |a| a.span_ext).hi());
223            cx.emit_span_lint(USAGE_OF_TY_TYKIND, path.span, TykindKind { suggestion: span });
224        }
225    }
226
227    fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) {
228        match &ty.kind {
229            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
230                if lint_ty_kind_usage(cx, &path.res) {
231                    let span = match cx.tcx.parent_hir_node(ty.hir_id) {
232                        hir::Node::PatExpr(hir::PatExpr {
233                            kind: hir::PatExprKind::Path(qpath),
234                            ..
235                        })
236                        | hir::Node::Pat(hir::Pat {
237                            kind:
238                                hir::PatKind::TupleStruct(qpath, ..) | hir::PatKind::Struct(qpath, ..),
239                            ..
240                        })
241                        | hir::Node::Expr(
242                            hir::Expr { kind: hir::ExprKind::Path(qpath), .. }
243                            | &hir::Expr { kind: hir::ExprKind::Struct(qpath, ..), .. },
244                        ) => {
245                            if let hir::QPath::TypeRelative(qpath_ty, ..) = qpath
246                                && qpath_ty.hir_id == ty.hir_id
247                            {
248                                Some(path.span)
249                            } else {
250                                None
251                            }
252                        }
253                        _ => None,
254                    };
255
256                    match span {
257                        Some(span) => {
258                            cx.emit_span_lint(
259                                USAGE_OF_TY_TYKIND,
260                                path.span,
261                                TykindKind { suggestion: span },
262                            );
263                        }
264                        None => cx.emit_span_lint(USAGE_OF_TY_TYKIND, path.span, TykindDiag),
265                    }
266                } else if !ty.span.from_expansion()
267                    && path.segments.len() > 1
268                    && let Some(ty) = is_ty_or_ty_ctxt(cx, path)
269                {
270                    cx.emit_span_lint(
271                        USAGE_OF_QUALIFIED_TY,
272                        path.span,
273                        TyQualified { ty, suggestion: path.span },
274                    );
275                }
276            }
277            _ => {}
278        }
279    }
280}
281
282fn lint_ty_kind_usage(cx: &LateContext<'_>, res: &Res) -> bool {
283    if let Some(did) = res.opt_def_id() {
284        cx.tcx.is_diagnostic_item(sym::TyKind, did) || cx.tcx.is_diagnostic_item(sym::IrTyKind, did)
285    } else {
286        false
287    }
288}
289
290fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, path: &hir::Path<'_>) -> Option<String> {
291    match &path.res {
292        Res::Def(_, def_id) => {
293            if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(*def_id) {
294                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())));
295            }
296        }
297        // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
298        Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
299            if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind()
300                && let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
301            {
302                return Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}<{1}>", name, args[0]))
    })format!("{}<{}>", name, args[0]));
303            }
304        }
305        _ => (),
306    }
307
308    None
309}
310
311fn gen_args(segment: &hir::PathSegment<'_>) -> String {
312    if let Some(args) = &segment.args {
313        let lifetimes = args
314            .args
315            .iter()
316            .filter_map(|arg| {
317                if let hir::GenericArg::Lifetime(lt) = arg {
318                    Some(lt.ident.to_string())
319                } else {
320                    None
321                }
322            })
323            .collect::<Vec<_>>();
324
325        if !lifetimes.is_empty() {
326            return ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", lifetimes.join(", ")))
    })format!("<{}>", lifetimes.join(", "));
327        }
328    }
329
330    String::new()
331}
332
333#[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`",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
334    /// The `non_glob_import_of_type_ir_inherent_item` lint detects
335    /// non-glob imports of module `rustc_type_ir::inherent`.
336    pub rustc::NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
337    Allow,
338    "non-glob import of `rustc_type_ir::inherent`",
339    report_in_external_macro: true
340}
341
342#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
343    /// The `usage_of_type_ir_inherent` lint detects usage of `rustc_type_ir::inherent`.
344    ///
345    /// This module should only be used within the trait solver.
346    pub rustc::USAGE_OF_TYPE_IR_INHERENT,
347    Allow,
348    "usage `rustc_type_ir::inherent` outside of trait system",
349    report_in_external_macro: true
350}
351
352#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
353    /// The `usage_of_type_ir_traits` lint detects usage of `rustc_type_ir::Interner`,
354    /// or `rustc_infer::InferCtxtLike`.
355    ///
356    /// Methods of this trait should only be used within the type system abstraction layer,
357    /// and in the generic next trait solver implementation. Look for an analogously named
358    /// method on `TyCtxt` or `InferCtxt` (respectively).
359    pub rustc::USAGE_OF_TYPE_IR_TRAITS,
360    Allow,
361    "usage `rustc_type_ir`-specific abstraction traits outside of trait system",
362    report_in_external_macro: true
363}
364#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
365    /// The `direct_use_of_rustc_type_ir` lint detects usage of `rustc_type_ir`.
366    ///
367    /// This module should only be used within the trait solver and some desirable
368    /// crates like rustc_middle.
369    pub rustc::DIRECT_USE_OF_RUSTC_TYPE_IR,
370    Allow,
371    "usage `rustc_type_ir` abstraction outside of trait system",
372    report_in_external_macro: true
373}
374
375pub 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) -> TypeIr { *self }
}
impl ::rustc_lint_defs::LintPass for TypeIr {
    fn name(&self) -> &'static str { "TypeIr" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([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 {
        <[_]>::into_vec(::alloc::boxed::box_new([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 => [DIRECT_USE_OF_RUSTC_TYPE_IR, NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_INHERENT, USAGE_OF_TYPE_IR_TRAITS]);
376
377impl<'tcx> LateLintPass<'tcx> for TypeIr {
378    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
379        let res_def_id = match expr.kind {
380            hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => path.res.opt_def_id(),
381            hir::ExprKind::Path(hir::QPath::TypeRelative(..)) | hir::ExprKind::MethodCall(..) => {
382                cx.typeck_results().type_dependent_def_id(expr.hir_id)
383            }
384            _ => return,
385        };
386        let Some(res_def_id) = res_def_id else {
387            return;
388        };
389        if let Some(assoc_item) = cx.tcx.opt_associated_item(res_def_id)
390            && let Some(trait_def_id) = assoc_item.trait_container(cx.tcx)
391            && (cx.tcx.is_diagnostic_item(sym::type_ir_interner, trait_def_id)
392                | cx.tcx.is_diagnostic_item(sym::type_ir_infer_ctxt_like, trait_def_id))
393        {
394            cx.emit_span_lint(USAGE_OF_TYPE_IR_TRAITS, expr.span, TypeIrTraitUsage);
395        }
396    }
397
398    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
399        let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return };
400
401        let is_mod_inherent = |res: Res| {
402            res.opt_def_id()
403                .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id))
404        };
405
406        // Path segments except for the final.
407        if let Some(seg) = path.segments.iter().find(|seg| is_mod_inherent(seg.res)) {
408            cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage);
409        }
410        // Final path resolutions, like `use rustc_type_ir::inherent`
411        else if let Some(type_ns) = path.res.type_ns
412            && is_mod_inherent(type_ns)
413        {
414            cx.emit_span_lint(
415                USAGE_OF_TYPE_IR_INHERENT,
416                path.segments.last().unwrap().ident.span,
417                TypeIrInherentUsage,
418            );
419        }
420
421        let (lo, hi, snippet) = match path.segments {
422            [.., penultimate, segment] if is_mod_inherent(penultimate.res) => {
423                (segment.ident.span, item.kind.ident().unwrap().span, "*")
424            }
425            [.., segment]
426                if let Some(type_ns) = path.res.type_ns
427                    && is_mod_inherent(type_ns)
428                    && let rustc_hir::UseKind::Single(ident) = kind =>
429            {
430                let (lo, snippet) =
431                    match cx.tcx.sess.source_map().span_to_snippet(path.span).as_deref() {
432                        Ok("self") => (path.span, "*"),
433                        _ => (segment.ident.span.shrink_to_hi(), "::*"),
434                    };
435                (lo, if segment.ident == ident { lo } else { ident.span }, snippet)
436            }
437            _ => return,
438        };
439        cx.emit_span_lint(
440            NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT,
441            path.span,
442            NonGlobImportTypeIrInherent { suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), snippet },
443        );
444    }
445
446    fn check_path(
447        &mut self,
448        cx: &LateContext<'tcx>,
449        path: &rustc_hir::Path<'tcx>,
450        _: rustc_hir::HirId,
451    ) {
452        if let Some(seg) = path.segments.iter().find(|seg| {
453            seg.res
454                .opt_def_id()
455                .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir, def_id))
456        }) {
457            cx.emit_span_lint(DIRECT_USE_OF_RUSTC_TYPE_IR, seg.ident.span, TypeIrDirectUse);
458        }
459    }
460}
461
462#[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",
            edition_lint_opts: None,
            report_in_external_macro: false,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
463    /// The `lint_pass_impl_without_macro` detects manual implementations of a lint
464    /// pass, without using [`declare_lint_pass`] or [`impl_lint_pass`].
465    pub rustc::LINT_PASS_IMPL_WITHOUT_MACRO,
466    Allow,
467    "`impl LintPass` without the `declare_lint_pass!` or `impl_lint_pass!` macros"
468}
469
470pub 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) -> LintPassImpl { *self }
}
impl ::rustc_lint_defs::LintPass for LintPassImpl {
    fn name(&self) -> &'static str { "LintPassImpl" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([LINT_PASS_IMPL_WITHOUT_MACRO]))
    }
}
impl LintPassImpl {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([LINT_PASS_IMPL_WITHOUT_MACRO]))
    }
}declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]);
471
472impl EarlyLintPass for LintPassImpl {
473    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
474        if let ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) = &item.kind
475            && let Some(last) = of_trait.trait_ref.path.segments.last()
476            && last.ident.name == sym::LintPass
477        {
478            let expn_data = of_trait.trait_ref.path.span.ctxt().outer_expn_data();
479            let call_site = expn_data.call_site;
480            if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass)
481                && call_site.ctxt().outer_expn_data().kind
482                    != ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass)
483            {
484                cx.emit_span_lint(
485                    LINT_PASS_IMPL_WITHOUT_MACRO,
486                    of_trait.trait_ref.path.span,
487                    LintPassByHand,
488                );
489            }
490        }
491    }
492}
493
494#[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",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
495    /// The `bad_opt_access` lint detects accessing options by field instead of
496    /// the wrapper function.
497    pub rustc::BAD_OPT_ACCESS,
498    Deny,
499    "prevent using options by field access when there is a wrapper function",
500    report_in_external_macro: true
501}
502
503pub 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) -> BadOptAccess { *self }
}
impl ::rustc_lint_defs::LintPass for BadOptAccess {
    fn name(&self) -> &'static str { "BadOptAccess" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([BAD_OPT_ACCESS]))
    }
}
impl BadOptAccess {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([BAD_OPT_ACCESS]))
    }
}declare_lint_pass!(BadOptAccess => [BAD_OPT_ACCESS]);
504
505impl LateLintPass<'_> for BadOptAccess {
506    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
507        let hir::ExprKind::Field(base, target) = expr.kind else { return };
508        let Some(adt_def) = cx.typeck_results().expr_ty(base).ty_adt_def() else { return };
509        // Skip types without `#[rustc_lint_opt_ty]` - only so that the rest of the lint can be
510        // avoided.
511        if !{
    {
            'done:
                {
                for i in cx.tcx.get_all_attrs(adt_def.did()) {
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(AttributeKind::RustcLintOptTy)
                            => {
                            break 'done Some(());
                        }
                        _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(cx.tcx.get_all_attrs(adt_def.did()), AttributeKind::RustcLintOptTy) {
512            return;
513        }
514
515        for field in adt_def.all_fields() {
516            if field.name == target.name
517                && let Some(lint_message) = {
    'done:
        {
        for i in cx.tcx.get_all_attrs(field.did) {
            let i: &rustc_hir::Attribute = i;
            match i {
                rustc_hir::Attribute::Parsed(AttributeKind::RustcLintOptDenyFieldAccess {
                    lint_message }) => {
                    break 'done Some(lint_message);
                }
                _ => {}
            }
        }
        None
    }
}find_attr!(cx.tcx.get_all_attrs(field.did), AttributeKind::RustcLintOptDenyFieldAccess { lint_message, } => lint_message)
518            {
519                cx.emit_span_lint(
520                    BAD_OPT_ACCESS,
521                    expr.span,
522                    BadOptAccessDiag { msg: lint_message.as_str() },
523                );
524            }
525        }
526    }
527}
528
529pub static SPAN_USE_EQ_CTXT: &::rustc_lint_defs::Lint =
    &::rustc_lint_defs::Lint {
            name: &"rustc::SPAN_USE_EQ_CTXT",
            default_level: ::rustc_lint_defs::Allow,
            desc: "forbid uses of `==` with `Span::ctxt`, suggest `Span::eq_ctxt` instead",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
530    pub rustc::SPAN_USE_EQ_CTXT,
531    Allow,
532    "forbid uses of `==` with `Span::ctxt`, suggest `Span::eq_ctxt` instead",
533    report_in_external_macro: true
534}
535
536pub struct SpanUseEqCtxt;
#[automatically_derived]
impl ::core::marker::Copy for SpanUseEqCtxt { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SpanUseEqCtxt { }
#[automatically_derived]
impl ::core::clone::Clone for SpanUseEqCtxt {
    #[inline]
    fn clone(&self) -> SpanUseEqCtxt { *self }
}
impl ::rustc_lint_defs::LintPass for SpanUseEqCtxt {
    fn name(&self) -> &'static str { "SpanUseEqCtxt" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([SPAN_USE_EQ_CTXT]))
    }
}
impl SpanUseEqCtxt {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([SPAN_USE_EQ_CTXT]))
    }
}declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
537
538impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
539    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
540        if let hir::ExprKind::Binary(
541            hir::BinOp { node: hir::BinOpKind::Eq | hir::BinOpKind::Ne, .. },
542            lhs,
543            rhs,
544        ) = expr.kind
545        {
546            if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
547                cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
548            }
549        }
550    }
551}
552
553fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
554    match &expr.kind {
555        hir::ExprKind::MethodCall(..) => cx
556            .typeck_results()
557            .type_dependent_def_id(expr.hir_id)
558            .is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)),
559
560        _ => false,
561    }
562}
563
564#[doc =
r" The `symbol_intern_string_literal` detects `Symbol::intern` 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`, suggesting preinterning instead",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
565    /// The `symbol_intern_string_literal` detects `Symbol::intern` being called on a string literal
566    pub rustc::SYMBOL_INTERN_STRING_LITERAL,
567    // rustc_driver crates out of the compiler can't/shouldn't add preinterned symbols;
568    // bootstrap will deny this manually
569    Allow,
570    "Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead",
571    report_in_external_macro: true
572}
573
574pub 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) -> SymbolInternStringLiteral { *self }
}
impl ::rustc_lint_defs::LintPass for SymbolInternStringLiteral {
    fn name(&self) -> &'static str { "SymbolInternStringLiteral" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([SYMBOL_INTERN_STRING_LITERAL]))
    }
}
impl SymbolInternStringLiteral {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([SYMBOL_INTERN_STRING_LITERAL]))
    }
}declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]);
575
576impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral {
577    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
578        if let hir::ExprKind::Call(path, [arg]) = expr.kind
579            && let hir::ExprKind::Path(ref qpath) = path.kind
580            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
581            && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id)
582            && let hir::ExprKind::Lit(kind) = arg.kind
583            && let rustc_ast::LitKind::Str(_, _) = kind.node
584        {
585            cx.emit_span_lint(
586                SYMBOL_INTERN_STRING_LITERAL,
587                kind.span,
588                SymbolInternStringLiteralDiag,
589            );
590        }
591    }
592}
593
594#[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`",
            edition_lint_opts: None,
            report_in_external_macro: true,
            future_incompatible: None,
            is_externally_loaded: true,
            crate_level_only: false,
            ..::rustc_lint_defs::Lint::default_fields_for_macro()
        };declare_tool_lint! {
595    /// The `implicit_sysroot_crate_import` detects use of `extern crate` to import non-sysroot crates
596    /// (e.g. crates.io deps) from the sysroot, which is dangerous because these crates are not guaranteed
597    /// to exist exactly once, and so may be missing entirely or appear multiple times resulting in ambiguity.
598    pub rustc::IMPLICIT_SYSROOT_CRATE_IMPORT,
599    Allow,
600    "Forbid uses of non-sysroot crates in `extern crate`",
601    report_in_external_macro: true
602}
603
604pub 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) -> ImplicitSysrootCrateImport { *self }
}
impl ::rustc_lint_defs::LintPass for ImplicitSysrootCrateImport {
    fn name(&self) -> &'static str { "ImplicitSysrootCrateImport" }
    fn get_lints(&self) -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([IMPLICIT_SYSROOT_CRATE_IMPORT]))
    }
}
impl ImplicitSysrootCrateImport {
    #[allow(unused)]
    pub fn lint_vec() -> ::rustc_lint_defs::LintVec {
        <[_]>::into_vec(::alloc::boxed::box_new([IMPLICIT_SYSROOT_CRATE_IMPORT]))
    }
}declare_lint_pass!(ImplicitSysrootCrateImport => [IMPLICIT_SYSROOT_CRATE_IMPORT]);
605
606impl EarlyLintPass for ImplicitSysrootCrateImport {
607    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
608        fn is_whitelisted(crate_name: &str) -> bool {
609            // Whitelist of allowed crates.
610            crate_name.starts_with("rustc_")
611                || #[allow(non_exhaustive_omitted_patterns)] match crate_name {
    "test" | "self" | "core" | "alloc" | "std" | "proc_macro" |
        "tikv_jemalloc_sys" => true,
    _ => false,
}matches!(
612                    crate_name,
613                    "test" | "self" | "core" | "alloc" | "std" | "proc_macro" | "tikv_jemalloc_sys"
614                )
615        }
616
617        if let ast::ItemKind::ExternCrate(original_name, imported_name) = &item.kind {
618            let name = original_name.as_ref().unwrap_or(&imported_name.name).as_str();
619            let externs = &cx.builder.sess().opts.externs;
620            if externs.get(name).is_none() && !is_whitelisted(name) {
621                cx.emit_span_lint(
622                    IMPLICIT_SYSROOT_CRATE_IMPORT,
623                    item.span,
624                    ImplicitSysrootCrateImportDiag { name },
625                );
626            }
627        }
628    }
629}