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