]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/builtin.rs
Rollup merge of #100200 - petrochenkov:zgccld2, r=lqd,Mark-Simulacrum
[rust.git] / compiler / rustc_lint / src / builtin.rs
1 //! Lints in the Rust compiler.
2 //!
3 //! This contains lints which can feasibly be implemented as their own
4 //! AST visitor. Also see `rustc_session::lint::builtin`, which contains the
5 //! definitions of lints that are emitted directly inside the main compiler.
6 //!
7 //! To add a new lint to rustc, declare it here using `declare_lint!()`.
8 //! Then add code to emit the new lint in the appropriate circumstances.
9 //! You can do that in an existing `LintPass` if it makes sense, or in a
10 //! new `LintPass`, or using `Session::add_lint` elsewhere in the
11 //! compiler. Only do the latter if the check can't be written cleanly as a
12 //! `LintPass` (also, note that such lints will need to be defined in
13 //! `rustc_session::lint::builtin`, not here).
14 //!
15 //! If you define a new `EarlyLintPass`, you will also need to add it to the
16 //! `add_early_builtin!` or `add_early_builtin_with_new!` invocation in
17 //! `lib.rs`. Use the former for unit-like structs and the latter for structs
18 //! with a `pub fn new()`.
19 //!
20 //! If you define a new `LateLintPass`, you will also need to add it to the
21 //! `late_lint_methods!` invocation in `lib.rs`.
22
23 use crate::{
24     errors::BuiltinEllpisisInclusiveRangePatterns,
25     types::{transparent_newtype_field, CItemKind},
26     EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
27 };
28 use rustc_ast::attr;
29 use rustc_ast::tokenstream::{TokenStream, TokenTree};
30 use rustc_ast::visit::{FnCtxt, FnKind};
31 use rustc_ast::{self as ast, *};
32 use rustc_ast_pretty::pprust::{self, expr_to_string};
33 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
34 use rustc_data_structures::stack::ensure_sufficient_stack;
35 use rustc_errors::{
36     fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
37     LintDiagnosticBuilder, MultiSpan,
38 };
39 use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
40 use rustc_hir as hir;
41 use rustc_hir::def::{DefKind, Res};
42 use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
43 use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind, PredicateOrigin};
44 use rustc_index::vec::Idx;
45 use rustc_middle::lint::in_external_macro;
46 use rustc_middle::ty::layout::{LayoutError, LayoutOf};
47 use rustc_middle::ty::print::with_no_trimmed_paths;
48 use rustc_middle::ty::subst::GenericArgKind;
49 use rustc_middle::ty::Instance;
50 use rustc_middle::ty::{self, Ty, TyCtxt};
51 use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
52 use rustc_span::edition::Edition;
53 use rustc_span::source_map::Spanned;
54 use rustc_span::symbol::{kw, sym, Ident, Symbol};
55 use rustc_span::{BytePos, InnerSpan, Span};
56 use rustc_target::abi::VariantIdx;
57 use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
58
59 use crate::nonstandard_style::{method_context, MethodLateContext};
60
61 use std::fmt::Write;
62
63 // hardwired lints from librustc_middle
64 pub use rustc_session::lint::builtin::*;
65
66 declare_lint! {
67     /// The `while_true` lint detects `while true { }`.
68     ///
69     /// ### Example
70     ///
71     /// ```rust,no_run
72     /// while true {
73     ///
74     /// }
75     /// ```
76     ///
77     /// {{produces}}
78     ///
79     /// ### Explanation
80     ///
81     /// `while true` should be replaced with `loop`. A `loop` expression is
82     /// the preferred way to write an infinite loop because it more directly
83     /// expresses the intent of the loop.
84     WHILE_TRUE,
85     Warn,
86     "suggest using `loop { }` instead of `while true { }`"
87 }
88
89 declare_lint_pass!(WhileTrue => [WHILE_TRUE]);
90
91 /// Traverse through any amount of parenthesis and return the first non-parens expression.
92 fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
93     while let ast::ExprKind::Paren(sub) = &expr.kind {
94         expr = sub;
95     }
96     expr
97 }
98
99 impl EarlyLintPass for WhileTrue {
100     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
101         if let ast::ExprKind::While(cond, _, label) = &e.kind {
102             if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
103                 if let ast::LitKind::Bool(true) = lit.kind {
104                     if !lit.span.from_expansion() {
105                         let condition_span = e.span.with_hi(cond.span.hi());
106                         cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
107                             lint.build(fluent::lint::builtin_while_true)
108                                 .span_suggestion_short(
109                                     condition_span,
110                                     fluent::lint::suggestion,
111                                     format!(
112                                         "{}loop",
113                                         label.map_or_else(String::new, |label| format!(
114                                             "{}: ",
115                                             label.ident,
116                                         ))
117                                     ),
118                                     Applicability::MachineApplicable,
119                                 )
120                                 .emit();
121                         })
122                     }
123                 }
124             }
125         }
126     }
127 }
128
129 declare_lint! {
130     /// The `box_pointers` lints use of the Box type.
131     ///
132     /// ### Example
133     ///
134     /// ```rust,compile_fail
135     /// #![deny(box_pointers)]
136     /// struct Foo {
137     ///     x: Box<isize>,
138     /// }
139     /// ```
140     ///
141     /// {{produces}}
142     ///
143     /// ### Explanation
144     ///
145     /// This lint is mostly historical, and not particularly useful. `Box<T>`
146     /// used to be built into the language, and the only way to do heap
147     /// allocation. Today's Rust can call into other allocators, etc.
148     BOX_POINTERS,
149     Allow,
150     "use of owned (Box type) heap memory"
151 }
152
153 declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
154
155 impl BoxPointers {
156     fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) {
157         for leaf in ty.walk() {
158             if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
159                 if leaf_ty.is_box() {
160                     cx.struct_span_lint(BOX_POINTERS, span, |lint| {
161                         lint.build(fluent::lint::builtin_box_pointers).set_arg("ty", ty).emit();
162                     });
163                 }
164             }
165         }
166     }
167 }
168
169 impl<'tcx> LateLintPass<'tcx> for BoxPointers {
170     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
171         match it.kind {
172             hir::ItemKind::Fn(..)
173             | hir::ItemKind::TyAlias(..)
174             | hir::ItemKind::Enum(..)
175             | hir::ItemKind::Struct(..)
176             | hir::ItemKind::Union(..) => {
177                 self.check_heap_type(cx, it.span, cx.tcx.type_of(it.def_id))
178             }
179             _ => (),
180         }
181
182         // If it's a struct, we also have to check the fields' types
183         match it.kind {
184             hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
185                 for struct_field in struct_def.fields() {
186                     let def_id = cx.tcx.hir().local_def_id(struct_field.hir_id);
187                     self.check_heap_type(cx, struct_field.span, cx.tcx.type_of(def_id));
188                 }
189             }
190             _ => (),
191         }
192     }
193
194     fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
195         let ty = cx.typeck_results().node_type(e.hir_id);
196         self.check_heap_type(cx, e.span, ty);
197     }
198 }
199
200 declare_lint! {
201     /// The `non_shorthand_field_patterns` lint detects using `Struct { x: x }`
202     /// instead of `Struct { x }` in a pattern.
203     ///
204     /// ### Example
205     ///
206     /// ```rust
207     /// struct Point {
208     ///     x: i32,
209     ///     y: i32,
210     /// }
211     ///
212     ///
213     /// fn main() {
214     ///     let p = Point {
215     ///         x: 5,
216     ///         y: 5,
217     ///     };
218     ///
219     ///     match p {
220     ///         Point { x: x, y: y } => (),
221     ///     }
222     /// }
223     /// ```
224     ///
225     /// {{produces}}
226     ///
227     /// ### Explanation
228     ///
229     /// The preferred style is to avoid the repetition of specifying both the
230     /// field name and the binding name if both identifiers are the same.
231     NON_SHORTHAND_FIELD_PATTERNS,
232     Warn,
233     "using `Struct { x: x }` instead of `Struct { x }` in a pattern"
234 }
235
236 declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]);
237
238 impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
239     fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) {
240         if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind {
241             let variant = cx
242                 .typeck_results()
243                 .pat_ty(pat)
244                 .ty_adt_def()
245                 .expect("struct pattern type is not an ADT")
246                 .variant_of_res(cx.qpath_res(qpath, pat.hir_id));
247             for fieldpat in field_pats {
248                 if fieldpat.is_shorthand {
249                     continue;
250                 }
251                 if fieldpat.span.from_expansion() {
252                     // Don't lint if this is a macro expansion: macro authors
253                     // shouldn't have to worry about this kind of style issue
254                     // (Issue #49588)
255                     continue;
256                 }
257                 if let PatKind::Binding(binding_annot, _, ident, None) = fieldpat.pat.kind {
258                     if cx.tcx.find_field_index(ident, &variant)
259                         == Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
260                     {
261                         cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| {
262                             let binding = match binding_annot {
263                                 hir::BindingAnnotation::Unannotated => None,
264                                 hir::BindingAnnotation::Mutable => Some("mut"),
265                                 hir::BindingAnnotation::Ref => Some("ref"),
266                                 hir::BindingAnnotation::RefMut => Some("ref mut"),
267                             };
268                             let suggested_ident = if let Some(binding) = binding {
269                                 format!("{} {}", binding, ident)
270                             } else {
271                                 ident.to_string()
272                             };
273                             lint.build(fluent::lint::builtin_non_shorthand_field_patterns)
274                                 .set_arg("ident", ident.clone())
275                                 .span_suggestion(
276                                     fieldpat.span,
277                                     fluent::lint::suggestion,
278                                     suggested_ident,
279                                     Applicability::MachineApplicable,
280                                 )
281                                 .emit();
282                         });
283                     }
284                 }
285             }
286         }
287     }
288 }
289
290 declare_lint! {
291     /// The `unsafe_code` lint catches usage of `unsafe` code.
292     ///
293     /// ### Example
294     ///
295     /// ```rust,compile_fail
296     /// #![deny(unsafe_code)]
297     /// fn main() {
298     ///     unsafe {
299     ///
300     ///     }
301     /// }
302     /// ```
303     ///
304     /// {{produces}}
305     ///
306     /// ### Explanation
307     ///
308     /// This lint is intended to restrict the usage of `unsafe`, which can be
309     /// difficult to use correctly.
310     UNSAFE_CODE,
311     Allow,
312     "usage of `unsafe` code"
313 }
314
315 declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
316
317 impl UnsafeCode {
318     fn report_unsafe(
319         &self,
320         cx: &EarlyContext<'_>,
321         span: Span,
322         decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
323     ) {
324         // This comes from a macro that has `#[allow_internal_unsafe]`.
325         if span.allows_unsafe() {
326             return;
327         }
328
329         cx.struct_span_lint(UNSAFE_CODE, span, decorate);
330     }
331
332     fn report_overridden_symbol_name(
333         &self,
334         cx: &EarlyContext<'_>,
335         span: Span,
336         msg: DiagnosticMessage,
337     ) {
338         self.report_unsafe(cx, span, |lint| {
339             lint.build(msg).note(fluent::lint::builtin_overridden_symbol_name).emit();
340         })
341     }
342
343     fn report_overridden_symbol_section(
344         &self,
345         cx: &EarlyContext<'_>,
346         span: Span,
347         msg: DiagnosticMessage,
348     ) {
349         self.report_unsafe(cx, span, |lint| {
350             lint.build(msg).note(fluent::lint::builtin_overridden_symbol_section).emit();
351         })
352     }
353 }
354
355 impl EarlyLintPass for UnsafeCode {
356     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
357         if attr.has_name(sym::allow_internal_unsafe) {
358             self.report_unsafe(cx, attr.span, |lint| {
359                 lint.build(fluent::lint::builtin_allow_internal_unsafe).emit();
360             });
361         }
362     }
363
364     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
365         if let ast::ExprKind::Block(ref blk, _) = e.kind {
366             // Don't warn about generated blocks; that'll just pollute the output.
367             if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
368                 self.report_unsafe(cx, blk.span, |lint| {
369                     lint.build(fluent::lint::builtin_unsafe_block).emit();
370                 });
371             }
372         }
373     }
374
375     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
376         match it.kind {
377             ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
378                 .report_unsafe(cx, it.span, |lint| {
379                     lint.build(fluent::lint::builtin_unsafe_trait).emit();
380                 }),
381
382             ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
383                 .report_unsafe(cx, it.span, |lint| {
384                     lint.build(fluent::lint::builtin_unsafe_impl).emit();
385                 }),
386
387             ast::ItemKind::Fn(..) => {
388                 if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
389                     self.report_overridden_symbol_name(
390                         cx,
391                         attr.span,
392                         fluent::lint::builtin_no_mangle_fn,
393                     );
394                 }
395
396                 if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
397                     self.report_overridden_symbol_name(
398                         cx,
399                         attr.span,
400                         fluent::lint::builtin_export_name_fn,
401                     );
402                 }
403
404                 if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::link_section) {
405                     self.report_overridden_symbol_section(
406                         cx,
407                         attr.span,
408                         fluent::lint::builtin_link_section_fn,
409                     );
410                 }
411             }
412
413             ast::ItemKind::Static(..) => {
414                 if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
415                     self.report_overridden_symbol_name(
416                         cx,
417                         attr.span,
418                         fluent::lint::builtin_no_mangle_static,
419                     );
420                 }
421
422                 if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
423                     self.report_overridden_symbol_name(
424                         cx,
425                         attr.span,
426                         fluent::lint::builtin_export_name_static,
427                     );
428                 }
429
430                 if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::link_section) {
431                     self.report_overridden_symbol_section(
432                         cx,
433                         attr.span,
434                         fluent::lint::builtin_link_section_static,
435                     );
436                 }
437             }
438
439             _ => {}
440         }
441     }
442
443     fn check_impl_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
444         if let ast::AssocItemKind::Fn(..) = it.kind {
445             if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
446                 self.report_overridden_symbol_name(
447                     cx,
448                     attr.span,
449                     fluent::lint::builtin_no_mangle_method,
450                 );
451             }
452             if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
453                 self.report_overridden_symbol_name(
454                     cx,
455                     attr.span,
456                     fluent::lint::builtin_export_name_method,
457                 );
458             }
459         }
460     }
461
462     fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast::NodeId) {
463         if let FnKind::Fn(
464             ctxt,
465             _,
466             ast::FnSig { header: ast::FnHeader { unsafety: ast::Unsafe::Yes(_), .. }, .. },
467             _,
468             _,
469             body,
470         ) = fk
471         {
472             let msg = match ctxt {
473                 FnCtxt::Foreign => return,
474                 FnCtxt::Free => fluent::lint::builtin_decl_unsafe_fn,
475                 FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method,
476                 FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method,
477             };
478             self.report_unsafe(cx, span, |lint| {
479                 lint.build(msg).emit();
480             });
481         }
482     }
483 }
484
485 declare_lint! {
486     /// The `missing_docs` lint detects missing documentation for public items.
487     ///
488     /// ### Example
489     ///
490     /// ```rust,compile_fail
491     /// #![deny(missing_docs)]
492     /// pub fn foo() {}
493     /// ```
494     ///
495     /// {{produces}}
496     ///
497     /// ### Explanation
498     ///
499     /// This lint is intended to ensure that a library is well-documented.
500     /// Items without documentation can be difficult for users to understand
501     /// how to use properly.
502     ///
503     /// This lint is "allow" by default because it can be noisy, and not all
504     /// projects may want to enforce everything to be documented.
505     pub MISSING_DOCS,
506     Allow,
507     "detects missing documentation for public members",
508     report_in_external_macro
509 }
510
511 pub struct MissingDoc {
512     /// Stack of whether `#[doc(hidden)]` is set at each level which has lint attributes.
513     doc_hidden_stack: Vec<bool>,
514 }
515
516 impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
517
518 fn has_doc(attr: &ast::Attribute) -> bool {
519     if attr.is_doc_comment() {
520         return true;
521     }
522
523     if !attr.has_name(sym::doc) {
524         return false;
525     }
526
527     if attr.value_str().is_some() {
528         return true;
529     }
530
531     if let Some(list) = attr.meta_item_list() {
532         for meta in list {
533             if meta.has_name(sym::hidden) {
534                 return true;
535             }
536         }
537     }
538
539     false
540 }
541
542 impl MissingDoc {
543     pub fn new() -> MissingDoc {
544         MissingDoc { doc_hidden_stack: vec![false] }
545     }
546
547     fn doc_hidden(&self) -> bool {
548         *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
549     }
550
551     fn check_missing_docs_attrs(
552         &self,
553         cx: &LateContext<'_>,
554         def_id: LocalDefId,
555         article: &'static str,
556         desc: &'static str,
557     ) {
558         // If we're building a test harness, then warning about
559         // documentation is probably not really relevant right now.
560         if cx.sess().opts.test {
561             return;
562         }
563
564         // `#[doc(hidden)]` disables missing_docs check.
565         if self.doc_hidden() {
566             return;
567         }
568
569         // Only check publicly-visible items, using the result from the privacy pass.
570         // It's an option so the crate root can also use this function (it doesn't
571         // have a `NodeId`).
572         if def_id != CRATE_DEF_ID {
573             if !cx.access_levels.is_exported(def_id) {
574                 return;
575             }
576         }
577
578         let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id));
579         let has_doc = attrs.iter().any(has_doc);
580         if !has_doc {
581             cx.struct_span_lint(MISSING_DOCS, cx.tcx.def_span(def_id), |lint| {
582                 lint.build(fluent::lint::builtin_missing_doc)
583                     .set_arg("article", article)
584                     .set_arg("desc", desc)
585                     .emit();
586             });
587         }
588     }
589 }
590
591 impl<'tcx> LateLintPass<'tcx> for MissingDoc {
592     fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
593         let doc_hidden = self.doc_hidden()
594             || attrs.iter().any(|attr| {
595                 attr.has_name(sym::doc)
596                     && match attr.meta_item_list() {
597                         None => false,
598                         Some(l) => attr::list_contains_name(&l, sym::hidden),
599                     }
600             });
601         self.doc_hidden_stack.push(doc_hidden);
602     }
603
604     fn exit_lint_attrs(&mut self, _: &LateContext<'_>, _attrs: &[ast::Attribute]) {
605         self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
606     }
607
608     fn check_crate(&mut self, cx: &LateContext<'_>) {
609         self.check_missing_docs_attrs(cx, CRATE_DEF_ID, "the", "crate");
610     }
611
612     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
613         match it.kind {
614             hir::ItemKind::Trait(..) => {
615                 // Issue #11592: traits are always considered exported, even when private.
616                 if cx.tcx.visibility(it.def_id)
617                     == ty::Visibility::Restricted(
618                         cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(),
619                     )
620                 {
621                     return;
622                 }
623             }
624             hir::ItemKind::TyAlias(..)
625             | hir::ItemKind::Fn(..)
626             | hir::ItemKind::Macro(..)
627             | hir::ItemKind::Mod(..)
628             | hir::ItemKind::Enum(..)
629             | hir::ItemKind::Struct(..)
630             | hir::ItemKind::Union(..)
631             | hir::ItemKind::Const(..)
632             | hir::ItemKind::Static(..) => {}
633
634             _ => return,
635         };
636
637         let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
638
639         self.check_missing_docs_attrs(cx, it.def_id, article, desc);
640     }
641
642     fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
643         let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
644
645         self.check_missing_docs_attrs(cx, trait_item.def_id, article, desc);
646     }
647
648     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
649         // If the method is an impl for a trait, don't doc.
650         if method_context(cx, impl_item.hir_id()) == MethodLateContext::TraitImpl {
651             return;
652         }
653
654         // If the method is an impl for an item with docs_hidden, don't doc.
655         if method_context(cx, impl_item.hir_id()) == MethodLateContext::PlainImpl {
656             let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
657             let impl_ty = cx.tcx.type_of(parent);
658             let outerdef = match impl_ty.kind() {
659                 ty::Adt(def, _) => Some(def.did()),
660                 ty::Foreign(def_id) => Some(*def_id),
661                 _ => None,
662             };
663             let is_hidden = match outerdef {
664                 Some(id) => cx.tcx.is_doc_hidden(id),
665                 None => false,
666             };
667             if is_hidden {
668                 return;
669             }
670         }
671
672         let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
673         self.check_missing_docs_attrs(cx, impl_item.def_id, article, desc);
674     }
675
676     fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) {
677         let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id());
678         self.check_missing_docs_attrs(cx, foreign_item.def_id, article, desc);
679     }
680
681     fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) {
682         if !sf.is_positional() {
683             let def_id = cx.tcx.hir().local_def_id(sf.hir_id);
684             self.check_missing_docs_attrs(cx, def_id, "a", "struct field")
685         }
686     }
687
688     fn check_variant(&mut self, cx: &LateContext<'_>, v: &hir::Variant<'_>) {
689         self.check_missing_docs_attrs(cx, cx.tcx.hir().local_def_id(v.id), "a", "variant");
690     }
691 }
692
693 declare_lint! {
694     /// The `missing_copy_implementations` lint detects potentially-forgotten
695     /// implementations of [`Copy`].
696     ///
697     /// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
698     ///
699     /// ### Example
700     ///
701     /// ```rust,compile_fail
702     /// #![deny(missing_copy_implementations)]
703     /// pub struct Foo {
704     ///     pub field: i32
705     /// }
706     /// # fn main() {}
707     /// ```
708     ///
709     /// {{produces}}
710     ///
711     /// ### Explanation
712     ///
713     /// Historically (before 1.0), types were automatically marked as `Copy`
714     /// if possible. This was changed so that it required an explicit opt-in
715     /// by implementing the `Copy` trait. As part of this change, a lint was
716     /// added to alert if a copyable type was not marked `Copy`.
717     ///
718     /// This lint is "allow" by default because this code isn't bad; it is
719     /// common to write newtypes like this specifically so that a `Copy` type
720     /// is no longer `Copy`. `Copy` types can result in unintended copies of
721     /// large data which can impact performance.
722     pub MISSING_COPY_IMPLEMENTATIONS,
723     Allow,
724     "detects potentially-forgotten implementations of `Copy`"
725 }
726
727 declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]);
728
729 impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
730     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
731         if !cx.access_levels.is_reachable(item.def_id) {
732             return;
733         }
734         let (def, ty) = match item.kind {
735             hir::ItemKind::Struct(_, ref ast_generics) => {
736                 if !ast_generics.params.is_empty() {
737                     return;
738                 }
739                 let def = cx.tcx.adt_def(item.def_id);
740                 (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
741             }
742             hir::ItemKind::Union(_, ref ast_generics) => {
743                 if !ast_generics.params.is_empty() {
744                     return;
745                 }
746                 let def = cx.tcx.adt_def(item.def_id);
747                 (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
748             }
749             hir::ItemKind::Enum(_, ref ast_generics) => {
750                 if !ast_generics.params.is_empty() {
751                     return;
752                 }
753                 let def = cx.tcx.adt_def(item.def_id);
754                 (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
755             }
756             _ => return,
757         };
758         if def.has_dtor(cx.tcx) {
759             return;
760         }
761         let param_env = ty::ParamEnv::empty();
762         if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
763             return;
764         }
765         if can_type_implement_copy(
766             cx.tcx,
767             param_env,
768             ty,
769             traits::ObligationCause::misc(item.span, item.hir_id()),
770         )
771         .is_ok()
772         {
773             cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
774                 lint.build(fluent::lint::builtin_missing_copy_impl).emit();
775             })
776         }
777     }
778 }
779
780 declare_lint! {
781     /// The `missing_debug_implementations` lint detects missing
782     /// implementations of [`fmt::Debug`].
783     ///
784     /// [`fmt::Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html
785     ///
786     /// ### Example
787     ///
788     /// ```rust,compile_fail
789     /// #![deny(missing_debug_implementations)]
790     /// pub struct Foo;
791     /// # fn main() {}
792     /// ```
793     ///
794     /// {{produces}}
795     ///
796     /// ### Explanation
797     ///
798     /// Having a `Debug` implementation on all types can assist with
799     /// debugging, as it provides a convenient way to format and display a
800     /// value. Using the `#[derive(Debug)]` attribute will automatically
801     /// generate a typical implementation, or a custom implementation can be
802     /// added by manually implementing the `Debug` trait.
803     ///
804     /// This lint is "allow" by default because adding `Debug` to all types can
805     /// have a negative impact on compile time and code size. It also requires
806     /// boilerplate to be added to every type, which can be an impediment.
807     MISSING_DEBUG_IMPLEMENTATIONS,
808     Allow,
809     "detects missing implementations of Debug"
810 }
811
812 #[derive(Default)]
813 pub struct MissingDebugImplementations {
814     impling_types: Option<LocalDefIdSet>,
815 }
816
817 impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
818
819 impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
820     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
821         if !cx.access_levels.is_reachable(item.def_id) {
822             return;
823         }
824
825         match item.kind {
826             hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) => {}
827             _ => return,
828         }
829
830         let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else {
831             return
832         };
833
834         if self.impling_types.is_none() {
835             let mut impls = LocalDefIdSet::default();
836             cx.tcx.for_each_impl(debug, |d| {
837                 if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
838                     if let Some(def_id) = ty_def.did().as_local() {
839                         impls.insert(def_id);
840                     }
841                 }
842             });
843
844             self.impling_types = Some(impls);
845             debug!("{:?}", self.impling_types);
846         }
847
848         if !self.impling_types.as_ref().unwrap().contains(&item.def_id) {
849             cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| {
850                 lint.build(fluent::lint::builtin_missing_debug_impl)
851                     .set_arg("debug", cx.tcx.def_path_str(debug))
852                     .emit();
853             });
854         }
855     }
856 }
857
858 declare_lint! {
859     /// The `anonymous_parameters` lint detects anonymous parameters in trait
860     /// definitions.
861     ///
862     /// ### Example
863     ///
864     /// ```rust,edition2015,compile_fail
865     /// #![deny(anonymous_parameters)]
866     /// // edition 2015
867     /// pub trait Foo {
868     ///     fn foo(usize);
869     /// }
870     /// fn main() {}
871     /// ```
872     ///
873     /// {{produces}}
874     ///
875     /// ### Explanation
876     ///
877     /// This syntax is mostly a historical accident, and can be worked around
878     /// quite easily by adding an `_` pattern or a descriptive identifier:
879     ///
880     /// ```rust
881     /// trait Foo {
882     ///     fn foo(_: usize);
883     /// }
884     /// ```
885     ///
886     /// This syntax is now a hard error in the 2018 edition. In the 2015
887     /// edition, this lint is "warn" by default. This lint
888     /// enables the [`cargo fix`] tool with the `--edition` flag to
889     /// automatically transition old code from the 2015 edition to 2018. The
890     /// tool will run this lint and automatically apply the
891     /// suggested fix from the compiler (which is to add `_` to each
892     /// parameter). This provides a completely automated way to update old
893     /// code for a new edition. See [issue #41686] for more details.
894     ///
895     /// [issue #41686]: https://github.com/rust-lang/rust/issues/41686
896     /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
897     pub ANONYMOUS_PARAMETERS,
898     Warn,
899     "detects anonymous parameters",
900     @future_incompatible = FutureIncompatibleInfo {
901         reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
902         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
903     };
904 }
905
906 declare_lint_pass!(
907     /// Checks for use of anonymous parameters (RFC 1685).
908     AnonymousParameters => [ANONYMOUS_PARAMETERS]
909 );
910
911 impl EarlyLintPass for AnonymousParameters {
912     fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
913         if cx.sess().edition() != Edition::Edition2015 {
914             // This is a hard error in future editions; avoid linting and erroring
915             return;
916         }
917         if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind {
918             for arg in sig.decl.inputs.iter() {
919                 if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
920                     if ident.name == kw::Empty {
921                         cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| {
922                             let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
923
924                             let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
925                                 (snip.as_str(), Applicability::MachineApplicable)
926                             } else {
927                                 ("<type>", Applicability::HasPlaceholders)
928                             };
929
930                             lint.build(fluent::lint::builtin_anonymous_params)
931                                 .span_suggestion(
932                                     arg.pat.span,
933                                     fluent::lint::suggestion,
934                                     format!("_: {}", ty_snip),
935                                     appl,
936                                 )
937                                 .emit();
938                         })
939                     }
940                 }
941             }
942         }
943     }
944 }
945
946 /// Check for use of attributes which have been deprecated.
947 #[derive(Clone)]
948 pub struct DeprecatedAttr {
949     // This is not free to compute, so we want to keep it around, rather than
950     // compute it for every attribute.
951     depr_attrs: Vec<&'static BuiltinAttribute>,
952 }
953
954 impl_lint_pass!(DeprecatedAttr => []);
955
956 impl DeprecatedAttr {
957     pub fn new() -> DeprecatedAttr {
958         DeprecatedAttr { depr_attrs: deprecated_attributes() }
959     }
960 }
961
962 impl EarlyLintPass for DeprecatedAttr {
963     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
964         for BuiltinAttribute { name, gate, .. } in &self.depr_attrs {
965             if attr.ident().map(|ident| ident.name) == Some(*name) {
966                 if let &AttributeGate::Gated(
967                     Stability::Deprecated(link, suggestion),
968                     name,
969                     reason,
970                     _,
971                 ) = gate
972                 {
973                     cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
974                         // FIXME(davidtwco) translatable deprecated attr
975                         lint.build(fluent::lint::builtin_deprecated_attr_link)
976                             .set_arg("name", name)
977                             .set_arg("reason", reason)
978                             .set_arg("link", link)
979                             .span_suggestion_short(
980                                 attr.span,
981                                 suggestion.map(|s| s.into()).unwrap_or(
982                                     fluent::lint::builtin_deprecated_attr_default_suggestion,
983                                 ),
984                                 "",
985                                 Applicability::MachineApplicable,
986                             )
987                             .emit();
988                     });
989                 }
990                 return;
991             }
992         }
993         if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
994             cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
995                 lint.build(fluent::lint::builtin_deprecated_attr_used)
996                     .set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
997                     .span_suggestion_short(
998                         attr.span,
999                         fluent::lint::builtin_deprecated_attr_default_suggestion,
1000                         "",
1001                         Applicability::MachineApplicable,
1002                     )
1003                     .emit();
1004             });
1005         }
1006     }
1007 }
1008
1009 fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) {
1010     use rustc_ast::token::CommentKind;
1011
1012     let mut attrs = attrs.iter().peekable();
1013
1014     // Accumulate a single span for sugared doc comments.
1015     let mut sugared_span: Option<Span> = None;
1016
1017     while let Some(attr) = attrs.next() {
1018         let is_doc_comment = attr.is_doc_comment();
1019         if is_doc_comment {
1020             sugared_span =
1021                 Some(sugared_span.map_or(attr.span, |span| span.with_hi(attr.span.hi())));
1022         }
1023
1024         if attrs.peek().map_or(false, |next_attr| next_attr.is_doc_comment()) {
1025             continue;
1026         }
1027
1028         let span = sugared_span.take().unwrap_or(attr.span);
1029
1030         if is_doc_comment || attr.has_name(sym::doc) {
1031             cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
1032                 let mut err = lint.build(fluent::lint::builtin_unused_doc_comment);
1033                 err.set_arg("kind", node_kind);
1034                 err.span_label(node_span, fluent::lint::label);
1035                 match attr.kind {
1036                     AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
1037                         err.help(fluent::lint::plain_help);
1038                     }
1039                     AttrKind::DocComment(CommentKind::Block, _) => {
1040                         err.help(fluent::lint::block_help);
1041                     }
1042                 }
1043                 err.emit();
1044             });
1045         }
1046     }
1047 }
1048
1049 impl EarlyLintPass for UnusedDocComment {
1050     fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
1051         let kind = match stmt.kind {
1052             ast::StmtKind::Local(..) => "statements",
1053             // Disabled pending discussion in #78306
1054             ast::StmtKind::Item(..) => return,
1055             // expressions will be reported by `check_expr`.
1056             ast::StmtKind::Empty
1057             | ast::StmtKind::Semi(_)
1058             | ast::StmtKind::Expr(_)
1059             | ast::StmtKind::MacCall(_) => return,
1060         };
1061
1062         warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs());
1063     }
1064
1065     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
1066         let arm_span = arm.pat.span.with_hi(arm.body.span.hi());
1067         warn_if_doc(cx, arm_span, "match arms", &arm.attrs);
1068     }
1069
1070     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
1071         warn_if_doc(cx, expr.span, "expressions", &expr.attrs);
1072     }
1073
1074     fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) {
1075         warn_if_doc(cx, param.ident.span, "generic parameters", &param.attrs);
1076     }
1077
1078     fn check_block(&mut self, cx: &EarlyContext<'_>, block: &ast::Block) {
1079         warn_if_doc(cx, block.span, "blocks", &block.attrs());
1080     }
1081
1082     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
1083         if let ast::ItemKind::ForeignMod(_) = item.kind {
1084             warn_if_doc(cx, item.span, "extern blocks", &item.attrs);
1085         }
1086     }
1087 }
1088
1089 declare_lint! {
1090     /// The `no_mangle_const_items` lint detects any `const` items with the
1091     /// [`no_mangle` attribute].
1092     ///
1093     /// [`no_mangle` attribute]: https://doc.rust-lang.org/reference/abi.html#the-no_mangle-attribute
1094     ///
1095     /// ### Example
1096     ///
1097     /// ```rust,compile_fail
1098     /// #[no_mangle]
1099     /// const FOO: i32 = 5;
1100     /// ```
1101     ///
1102     /// {{produces}}
1103     ///
1104     /// ### Explanation
1105     ///
1106     /// Constants do not have their symbols exported, and therefore, this
1107     /// probably means you meant to use a [`static`], not a [`const`].
1108     ///
1109     /// [`static`]: https://doc.rust-lang.org/reference/items/static-items.html
1110     /// [`const`]: https://doc.rust-lang.org/reference/items/constant-items.html
1111     NO_MANGLE_CONST_ITEMS,
1112     Deny,
1113     "const items will not have their symbols exported"
1114 }
1115
1116 declare_lint! {
1117     /// The `no_mangle_generic_items` lint detects generic items that must be
1118     /// mangled.
1119     ///
1120     /// ### Example
1121     ///
1122     /// ```rust
1123     /// #[no_mangle]
1124     /// fn foo<T>(t: T) {
1125     ///
1126     /// }
1127     /// ```
1128     ///
1129     /// {{produces}}
1130     ///
1131     /// ### Explanation
1132     ///
1133     /// A function with generics must have its symbol mangled to accommodate
1134     /// the generic parameter. The [`no_mangle` attribute] has no effect in
1135     /// this situation, and should be removed.
1136     ///
1137     /// [`no_mangle` attribute]: https://doc.rust-lang.org/reference/abi.html#the-no_mangle-attribute
1138     NO_MANGLE_GENERIC_ITEMS,
1139     Warn,
1140     "generic items must be mangled"
1141 }
1142
1143 declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]);
1144
1145 impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
1146     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
1147         let attrs = cx.tcx.hir().attrs(it.hir_id());
1148         let check_no_mangle_on_generic_fn = |no_mangle_attr: &ast::Attribute,
1149                                              impl_generics: Option<&hir::Generics<'_>>,
1150                                              generics: &hir::Generics<'_>,
1151                                              span| {
1152             for param in
1153                 generics.params.iter().chain(impl_generics.map(|g| g.params).into_iter().flatten())
1154             {
1155                 match param.kind {
1156                     GenericParamKind::Lifetime { .. } => {}
1157                     GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1158                         cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| {
1159                             lint.build(fluent::lint::builtin_no_mangle_generic)
1160                                 .span_suggestion_short(
1161                                     no_mangle_attr.span,
1162                                     fluent::lint::suggestion,
1163                                     "",
1164                                     // Use of `#[no_mangle]` suggests FFI intent; correct
1165                                     // fix may be to monomorphize source by hand
1166                                     Applicability::MaybeIncorrect,
1167                                 )
1168                                 .emit();
1169                         });
1170                         break;
1171                     }
1172                 }
1173             }
1174         };
1175         match it.kind {
1176             hir::ItemKind::Fn(.., ref generics, _) => {
1177                 if let Some(no_mangle_attr) = cx.sess().find_by_name(attrs, sym::no_mangle) {
1178                     check_no_mangle_on_generic_fn(no_mangle_attr, None, generics, it.span);
1179                 }
1180             }
1181             hir::ItemKind::Const(..) => {
1182                 if cx.sess().contains_name(attrs, sym::no_mangle) {
1183                     // Const items do not refer to a particular location in memory, and therefore
1184                     // don't have anything to attach a symbol to
1185                     cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| {
1186                         let mut err = lint.build(fluent::lint::builtin_const_no_mangle);
1187
1188                         // account for "pub const" (#45562)
1189                         let start = cx
1190                             .tcx
1191                             .sess
1192                             .source_map()
1193                             .span_to_snippet(it.span)
1194                             .map(|snippet| snippet.find("const").unwrap_or(0))
1195                             .unwrap_or(0) as u32;
1196                         // `const` is 5 chars
1197                         let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
1198                         err.span_suggestion(
1199                             const_span,
1200                             fluent::lint::suggestion,
1201                             "pub static",
1202                             Applicability::MachineApplicable,
1203                         );
1204                         err.emit();
1205                     });
1206                 }
1207             }
1208             hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => {
1209                 for it in *items {
1210                     if let hir::AssocItemKind::Fn { .. } = it.kind {
1211                         if let Some(no_mangle_attr) = cx
1212                             .sess()
1213                             .find_by_name(cx.tcx.hir().attrs(it.id.hir_id()), sym::no_mangle)
1214                         {
1215                             check_no_mangle_on_generic_fn(
1216                                 no_mangle_attr,
1217                                 Some(generics),
1218                                 cx.tcx.hir().get_generics(it.id.def_id).unwrap(),
1219                                 it.span,
1220                             );
1221                         }
1222                     }
1223                 }
1224             }
1225             _ => {}
1226         }
1227     }
1228 }
1229
1230 declare_lint! {
1231     /// The `mutable_transmutes` lint catches transmuting from `&T` to `&mut
1232     /// T` because it is [undefined behavior].
1233     ///
1234     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1235     ///
1236     /// ### Example
1237     ///
1238     /// ```rust,compile_fail
1239     /// unsafe {
1240     ///     let y = std::mem::transmute::<&i32, &mut i32>(&5);
1241     /// }
1242     /// ```
1243     ///
1244     /// {{produces}}
1245     ///
1246     /// ### Explanation
1247     ///
1248     /// Certain assumptions are made about aliasing of data, and this transmute
1249     /// violates those assumptions. Consider using [`UnsafeCell`] instead.
1250     ///
1251     /// [`UnsafeCell`]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html
1252     MUTABLE_TRANSMUTES,
1253     Deny,
1254     "transmuting &T to &mut T is undefined behavior, even if the reference is unused"
1255 }
1256
1257 declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);
1258
1259 impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
1260     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
1261         if let Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) =
1262             get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
1263         {
1264             if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
1265                 cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
1266                     lint.build(fluent::lint::builtin_mutable_transmutes).emit();
1267                 });
1268             }
1269         }
1270
1271         fn get_transmute_from_to<'tcx>(
1272             cx: &LateContext<'tcx>,
1273             expr: &hir::Expr<'_>,
1274         ) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
1275             let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
1276                 cx.qpath_res(qpath, expr.hir_id)
1277             } else {
1278                 return None;
1279             };
1280             if let Res::Def(DefKind::Fn, did) = def {
1281                 if !def_id_is_transmute(cx, did) {
1282                     return None;
1283                 }
1284                 let sig = cx.typeck_results().node_type(expr.hir_id).fn_sig(cx.tcx);
1285                 let from = sig.inputs().skip_binder()[0];
1286                 let to = sig.output().skip_binder();
1287                 return Some((from, to));
1288             }
1289             None
1290         }
1291
1292         fn def_id_is_transmute(cx: &LateContext<'_>, def_id: DefId) -> bool {
1293             cx.tcx.is_intrinsic(def_id) && cx.tcx.item_name(def_id) == sym::transmute
1294         }
1295     }
1296 }
1297
1298 declare_lint! {
1299     /// The `unstable_features` is deprecated and should no longer be used.
1300     UNSTABLE_FEATURES,
1301     Allow,
1302     "enabling unstable features (deprecated. do not use)"
1303 }
1304
1305 declare_lint_pass!(
1306     /// Forbids using the `#[feature(...)]` attribute
1307     UnstableFeatures => [UNSTABLE_FEATURES]
1308 );
1309
1310 impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
1311     fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
1312         if attr.has_name(sym::feature) {
1313             if let Some(items) = attr.meta_item_list() {
1314                 for item in items {
1315                     cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
1316                         lint.build(fluent::lint::builtin_unstable_features).emit();
1317                     });
1318                 }
1319             }
1320         }
1321     }
1322 }
1323
1324 declare_lint! {
1325     /// The `unreachable_pub` lint triggers for `pub` items not reachable from
1326     /// the crate root.
1327     ///
1328     /// ### Example
1329     ///
1330     /// ```rust,compile_fail
1331     /// #![deny(unreachable_pub)]
1332     /// mod foo {
1333     ///     pub mod bar {
1334     ///
1335     ///     }
1336     /// }
1337     /// ```
1338     ///
1339     /// {{produces}}
1340     ///
1341     /// ### Explanation
1342     ///
1343     /// A bare `pub` visibility may be misleading if the item is not actually
1344     /// publicly exported from the crate. The `pub(crate)` visibility is
1345     /// recommended to be used instead, which more clearly expresses the intent
1346     /// that the item is only visible within its own crate.
1347     ///
1348     /// This lint is "allow" by default because it will trigger for a large
1349     /// amount existing Rust code, and has some false-positives. Eventually it
1350     /// is desired for this to become warn-by-default.
1351     pub UNREACHABLE_PUB,
1352     Allow,
1353     "`pub` items not reachable from crate root"
1354 }
1355
1356 declare_lint_pass!(
1357     /// Lint for items marked `pub` that aren't reachable from other crates.
1358     UnreachablePub => [UNREACHABLE_PUB]
1359 );
1360
1361 impl UnreachablePub {
1362     fn perform_lint(
1363         &self,
1364         cx: &LateContext<'_>,
1365         what: &str,
1366         def_id: LocalDefId,
1367         vis_span: Span,
1368         exportable: bool,
1369     ) {
1370         let mut applicability = Applicability::MachineApplicable;
1371         if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) {
1372             if vis_span.from_expansion() {
1373                 applicability = Applicability::MaybeIncorrect;
1374             }
1375             let def_span = cx.tcx.def_span(def_id);
1376             cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
1377                 let mut err = lint.build(fluent::lint::builtin_unreachable_pub);
1378                 err.set_arg("what", what);
1379
1380                 err.span_suggestion(
1381                     vis_span,
1382                     fluent::lint::suggestion,
1383                     "pub(crate)",
1384                     applicability,
1385                 );
1386                 if exportable {
1387                     err.help(fluent::lint::help);
1388                 }
1389                 err.emit();
1390             });
1391         }
1392     }
1393 }
1394
1395 impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
1396     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
1397         // Do not warn for fake `use` statements.
1398         if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind {
1399             return;
1400         }
1401         self.perform_lint(cx, "item", item.def_id, item.vis_span, true);
1402     }
1403
1404     fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
1405         self.perform_lint(cx, "item", foreign_item.def_id, foreign_item.vis_span, true);
1406     }
1407
1408     fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
1409         let def_id = cx.tcx.hir().local_def_id(field.hir_id);
1410         self.perform_lint(cx, "field", def_id, field.vis_span, false);
1411     }
1412
1413     fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
1414         // Only lint inherent impl items.
1415         if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() {
1416             self.perform_lint(cx, "item", impl_item.def_id, impl_item.vis_span, false);
1417         }
1418     }
1419 }
1420
1421 declare_lint! {
1422     /// The `type_alias_bounds` lint detects bounds in type aliases.
1423     ///
1424     /// ### Example
1425     ///
1426     /// ```rust
1427     /// type SendVec<T: Send> = Vec<T>;
1428     /// ```
1429     ///
1430     /// {{produces}}
1431     ///
1432     /// ### Explanation
1433     ///
1434     /// The trait bounds in a type alias are currently ignored, and should not
1435     /// be included to avoid confusion. This was previously allowed
1436     /// unintentionally; this may become a hard error in the future.
1437     TYPE_ALIAS_BOUNDS,
1438     Warn,
1439     "bounds in type aliases are not enforced"
1440 }
1441
1442 declare_lint_pass!(
1443     /// Lint for trait and lifetime bounds in type aliases being mostly ignored.
1444     /// They are relevant when using associated types, but otherwise neither checked
1445     /// at definition site nor enforced at use site.
1446     TypeAliasBounds => [TYPE_ALIAS_BOUNDS]
1447 );
1448
1449 impl TypeAliasBounds {
1450     fn is_type_variable_assoc(qpath: &hir::QPath<'_>) -> bool {
1451         match *qpath {
1452             hir::QPath::TypeRelative(ref ty, _) => {
1453                 // If this is a type variable, we found a `T::Assoc`.
1454                 match ty.kind {
1455                     hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
1456                         matches!(path.res, Res::Def(DefKind::TyParam, _))
1457                     }
1458                     _ => false,
1459                 }
1460             }
1461             hir::QPath::Resolved(..) | hir::QPath::LangItem(..) => false,
1462         }
1463     }
1464
1465     fn suggest_changing_assoc_types(ty: &hir::Ty<'_>, err: &mut Diagnostic) {
1466         // Access to associates types should use `<T as Bound>::Assoc`, which does not need a
1467         // bound.  Let's see if this type does that.
1468
1469         // We use a HIR visitor to walk the type.
1470         use rustc_hir::intravisit::{self, Visitor};
1471         struct WalkAssocTypes<'a> {
1472             err: &'a mut Diagnostic,
1473         }
1474         impl Visitor<'_> for WalkAssocTypes<'_> {
1475             fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) {
1476                 if TypeAliasBounds::is_type_variable_assoc(qpath) {
1477                     self.err.span_help(span, fluent::lint::builtin_type_alias_bounds_help);
1478                 }
1479                 intravisit::walk_qpath(self, qpath, id, span)
1480             }
1481         }
1482
1483         // Let's go for a walk!
1484         let mut visitor = WalkAssocTypes { err };
1485         visitor.visit_ty(ty);
1486     }
1487 }
1488
1489 impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
1490     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
1491         let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else {
1492             return
1493         };
1494         if let hir::TyKind::OpaqueDef(..) = ty.kind {
1495             // Bounds are respected for `type X = impl Trait`
1496             return;
1497         }
1498         // There must not be a where clause
1499         if type_alias_generics.predicates.is_empty() {
1500             return;
1501         }
1502
1503         let mut where_spans = Vec::new();
1504         let mut inline_spans = Vec::new();
1505         let mut inline_sugg = Vec::new();
1506         for p in type_alias_generics.predicates {
1507             let span = p.span();
1508             if p.in_where_clause() {
1509                 where_spans.push(span);
1510             } else {
1511                 for b in p.bounds() {
1512                     inline_spans.push(b.span());
1513                 }
1514                 inline_sugg.push((span, String::new()));
1515             }
1516         }
1517
1518         let mut suggested_changing_assoc_types = false;
1519         if !where_spans.is_empty() {
1520             cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
1521                 let mut err = lint.build(fluent::lint::builtin_type_alias_where_clause);
1522                 err.set_span(where_spans);
1523                 err.span_suggestion(
1524                     type_alias_generics.where_clause_span,
1525                     fluent::lint::suggestion,
1526                     "",
1527                     Applicability::MachineApplicable,
1528                 );
1529                 if !suggested_changing_assoc_types {
1530                     TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
1531                     suggested_changing_assoc_types = true;
1532                 }
1533                 err.emit();
1534             });
1535         }
1536
1537         if !inline_spans.is_empty() {
1538             cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
1539                 let mut err = lint.build(fluent::lint::builtin_type_alias_generic_bounds);
1540                 err.set_span(inline_spans);
1541                 err.multipart_suggestion(
1542                     fluent::lint::suggestion,
1543                     inline_sugg,
1544                     Applicability::MachineApplicable,
1545                 );
1546                 if !suggested_changing_assoc_types {
1547                     TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
1548                 }
1549                 err.emit();
1550             });
1551         }
1552     }
1553 }
1554
1555 declare_lint_pass!(
1556     /// Lint constants that are erroneous.
1557     /// Without this lint, we might not get any diagnostic if the constant is
1558     /// unused within this crate, even though downstream crates can't use it
1559     /// without producing an error.
1560     UnusedBrokenConst => []
1561 );
1562
1563 impl<'tcx> LateLintPass<'tcx> for UnusedBrokenConst {
1564     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
1565         match it.kind {
1566             hir::ItemKind::Const(_, body_id) => {
1567                 let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
1568                 // trigger the query once for all constants since that will already report the errors
1569                 cx.tcx.ensure().const_eval_poly(def_id);
1570             }
1571             hir::ItemKind::Static(_, _, body_id) => {
1572                 let def_id = cx.tcx.hir().body_owner_def_id(body_id).to_def_id();
1573                 cx.tcx.ensure().eval_static_initializer(def_id);
1574             }
1575             _ => {}
1576         }
1577     }
1578 }
1579
1580 declare_lint! {
1581     /// The `trivial_bounds` lint detects trait bounds that don't depend on
1582     /// any type parameters.
1583     ///
1584     /// ### Example
1585     ///
1586     /// ```rust
1587     /// #![feature(trivial_bounds)]
1588     /// pub struct A where i32: Copy;
1589     /// ```
1590     ///
1591     /// {{produces}}
1592     ///
1593     /// ### Explanation
1594     ///
1595     /// Usually you would not write a trait bound that you know is always
1596     /// true, or never true. However, when using macros, the macro may not
1597     /// know whether or not the constraint would hold or not at the time when
1598     /// generating the code. Currently, the compiler does not alert you if the
1599     /// constraint is always true, and generates an error if it is never true.
1600     /// The `trivial_bounds` feature changes this to be a warning in both
1601     /// cases, giving macros more freedom and flexibility to generate code,
1602     /// while still providing a signal when writing non-macro code that
1603     /// something is amiss.
1604     ///
1605     /// See [RFC 2056] for more details. This feature is currently only
1606     /// available on the nightly channel, see [tracking issue #48214].
1607     ///
1608     /// [RFC 2056]: https://github.com/rust-lang/rfcs/blob/master/text/2056-allow-trivial-where-clause-constraints.md
1609     /// [tracking issue #48214]: https://github.com/rust-lang/rust/issues/48214
1610     TRIVIAL_BOUNDS,
1611     Warn,
1612     "these bounds don't depend on an type parameters"
1613 }
1614
1615 declare_lint_pass!(
1616     /// Lint for trait and lifetime bounds that don't depend on type parameters
1617     /// which either do nothing, or stop the item from being used.
1618     TrivialConstraints => [TRIVIAL_BOUNDS]
1619 );
1620
1621 impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
1622     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
1623         use rustc_middle::ty::visit::TypeVisitable;
1624         use rustc_middle::ty::PredicateKind::*;
1625
1626         if cx.tcx.features().trivial_bounds {
1627             let predicates = cx.tcx.predicates_of(item.def_id);
1628             for &(predicate, span) in predicates.predicates {
1629                 let predicate_kind_name = match predicate.kind().skip_binder() {
1630                     Trait(..) => "trait",
1631                     TypeOutlives(..) |
1632                     RegionOutlives(..) => "lifetime",
1633
1634                     // Ignore projections, as they can only be global
1635                     // if the trait bound is global
1636                     Projection(..) |
1637                     // Ignore bounds that a user can't type
1638                     WellFormed(..) |
1639                     ObjectSafe(..) |
1640                     ClosureKind(..) |
1641                     Subtype(..) |
1642                     Coerce(..) |
1643                     ConstEvaluatable(..) |
1644                     ConstEquate(..) |
1645                     TypeWellFormedFromEnv(..) => continue,
1646                 };
1647                 if predicate.is_global() {
1648                     cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
1649                         lint.build(fluent::lint::builtin_trivial_bounds)
1650                             .set_arg("predicate_kind_name", predicate_kind_name)
1651                             .set_arg("predicate", predicate)
1652                             .emit();
1653                     });
1654                 }
1655             }
1656         }
1657     }
1658 }
1659
1660 declare_lint_pass!(
1661     /// Does nothing as a lint pass, but registers some `Lint`s
1662     /// which are used by other parts of the compiler.
1663     SoftLints => [
1664         WHILE_TRUE,
1665         BOX_POINTERS,
1666         NON_SHORTHAND_FIELD_PATTERNS,
1667         UNSAFE_CODE,
1668         MISSING_DOCS,
1669         MISSING_COPY_IMPLEMENTATIONS,
1670         MISSING_DEBUG_IMPLEMENTATIONS,
1671         ANONYMOUS_PARAMETERS,
1672         UNUSED_DOC_COMMENTS,
1673         NO_MANGLE_CONST_ITEMS,
1674         NO_MANGLE_GENERIC_ITEMS,
1675         MUTABLE_TRANSMUTES,
1676         UNSTABLE_FEATURES,
1677         UNREACHABLE_PUB,
1678         TYPE_ALIAS_BOUNDS,
1679         TRIVIAL_BOUNDS
1680     ]
1681 );
1682
1683 declare_lint! {
1684     /// The `ellipsis_inclusive_range_patterns` lint detects the [`...` range
1685     /// pattern], which is deprecated.
1686     ///
1687     /// [`...` range pattern]: https://doc.rust-lang.org/reference/patterns.html#range-patterns
1688     ///
1689     /// ### Example
1690     ///
1691     /// ```rust,edition2018
1692     /// let x = 123;
1693     /// match x {
1694     ///     0...100 => {}
1695     ///     _ => {}
1696     /// }
1697     /// ```
1698     ///
1699     /// {{produces}}
1700     ///
1701     /// ### Explanation
1702     ///
1703     /// The `...` range pattern syntax was changed to `..=` to avoid potential
1704     /// confusion with the [`..` range expression]. Use the new form instead.
1705     ///
1706     /// [`..` range expression]: https://doc.rust-lang.org/reference/expressions/range-expr.html
1707     pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
1708     Warn,
1709     "`...` range patterns are deprecated",
1710     @future_incompatible = FutureIncompatibleInfo {
1711         reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>",
1712         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
1713     };
1714 }
1715
1716 #[derive(Default)]
1717 pub struct EllipsisInclusiveRangePatterns {
1718     /// If `Some(_)`, suppress all subsequent pattern
1719     /// warnings for better diagnostics.
1720     node_id: Option<ast::NodeId>,
1721 }
1722
1723 impl_lint_pass!(EllipsisInclusiveRangePatterns => [ELLIPSIS_INCLUSIVE_RANGE_PATTERNS]);
1724
1725 impl EarlyLintPass for EllipsisInclusiveRangePatterns {
1726     fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat) {
1727         if self.node_id.is_some() {
1728             // Don't recursively warn about patterns inside range endpoints.
1729             return;
1730         }
1731
1732         use self::ast::{PatKind, RangeSyntax::DotDotDot};
1733
1734         /// If `pat` is a `...` pattern, return the start and end of the range, as well as the span
1735         /// corresponding to the ellipsis.
1736         fn matches_ellipsis_pat(pat: &ast::Pat) -> Option<(Option<&Expr>, &Expr, Span)> {
1737             match &pat.kind {
1738                 PatKind::Range(
1739                     a,
1740                     Some(b),
1741                     Spanned { span, node: RangeEnd::Included(DotDotDot) },
1742                 ) => Some((a.as_deref(), b, *span)),
1743                 _ => None,
1744             }
1745         }
1746
1747         let (parenthesise, endpoints) = match &pat.kind {
1748             PatKind::Ref(subpat, _) => (true, matches_ellipsis_pat(&subpat)),
1749             _ => (false, matches_ellipsis_pat(pat)),
1750         };
1751
1752         if let Some((start, end, join)) = endpoints {
1753             let msg = fluent::lint::builtin_ellipsis_inclusive_range_patterns;
1754             let suggestion = fluent::lint::suggestion;
1755             if parenthesise {
1756                 self.node_id = Some(pat.id);
1757                 let end = expr_to_string(&end);
1758                 let replace = match start {
1759                     Some(start) => format!("&({}..={})", expr_to_string(&start), end),
1760                     None => format!("&(..={})", end),
1761                 };
1762                 if join.edition() >= Edition::Edition2021 {
1763                     cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
1764                         span: pat.span,
1765                         suggestion: pat.span,
1766                         replace,
1767                     });
1768                 } else {
1769                     cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| {
1770                         lint.build(msg)
1771                             .span_suggestion(
1772                                 pat.span,
1773                                 suggestion,
1774                                 replace,
1775                                 Applicability::MachineApplicable,
1776                             )
1777                             .emit();
1778                     });
1779                 }
1780             } else {
1781                 let replace = "..=";
1782                 if join.edition() >= Edition::Edition2021 {
1783                     cx.sess().emit_err(BuiltinEllpisisInclusiveRangePatterns {
1784                         span: pat.span,
1785                         suggestion: join,
1786                         replace: replace.to_string(),
1787                     });
1788                 } else {
1789                     cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| {
1790                         lint.build(msg)
1791                             .span_suggestion_short(
1792                                 join,
1793                                 suggestion,
1794                                 replace,
1795                                 Applicability::MachineApplicable,
1796                             )
1797                             .emit();
1798                     });
1799                 }
1800             };
1801         }
1802     }
1803
1804     fn check_pat_post(&mut self, _cx: &EarlyContext<'_>, pat: &ast::Pat) {
1805         if let Some(node_id) = self.node_id {
1806             if pat.id == node_id {
1807                 self.node_id = None
1808             }
1809         }
1810     }
1811 }
1812
1813 declare_lint! {
1814     /// The `unnameable_test_items` lint detects [`#[test]`][test] functions
1815     /// that are not able to be run by the test harness because they are in a
1816     /// position where they are not nameable.
1817     ///
1818     /// [test]: https://doc.rust-lang.org/reference/attributes/testing.html#the-test-attribute
1819     ///
1820     /// ### Example
1821     ///
1822     /// ```rust,test
1823     /// fn main() {
1824     ///     #[test]
1825     ///     fn foo() {
1826     ///         // This test will not fail because it does not run.
1827     ///         assert_eq!(1, 2);
1828     ///     }
1829     /// }
1830     /// ```
1831     ///
1832     /// {{produces}}
1833     ///
1834     /// ### Explanation
1835     ///
1836     /// In order for the test harness to run a test, the test function must be
1837     /// located in a position where it can be accessed from the crate root.
1838     /// This generally means it must be defined in a module, and not anywhere
1839     /// else such as inside another function. The compiler previously allowed
1840     /// this without an error, so a lint was added as an alert that a test is
1841     /// not being used. Whether or not this should be allowed has not yet been
1842     /// decided, see [RFC 2471] and [issue #36629].
1843     ///
1844     /// [RFC 2471]: https://github.com/rust-lang/rfcs/pull/2471#issuecomment-397414443
1845     /// [issue #36629]: https://github.com/rust-lang/rust/issues/36629
1846     UNNAMEABLE_TEST_ITEMS,
1847     Warn,
1848     "detects an item that cannot be named being marked as `#[test_case]`",
1849     report_in_external_macro
1850 }
1851
1852 pub struct UnnameableTestItems {
1853     boundary: Option<LocalDefId>, // Id of the item under which things are not nameable
1854     items_nameable: bool,
1855 }
1856
1857 impl_lint_pass!(UnnameableTestItems => [UNNAMEABLE_TEST_ITEMS]);
1858
1859 impl UnnameableTestItems {
1860     pub fn new() -> Self {
1861         Self { boundary: None, items_nameable: true }
1862     }
1863 }
1864
1865 impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
1866     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
1867         if self.items_nameable {
1868             if let hir::ItemKind::Mod(..) = it.kind {
1869             } else {
1870                 self.items_nameable = false;
1871                 self.boundary = Some(it.def_id);
1872             }
1873             return;
1874         }
1875
1876         let attrs = cx.tcx.hir().attrs(it.hir_id());
1877         if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
1878             cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
1879                 lint.build(fluent::lint::builtin_unnameable_test_items).emit();
1880             });
1881         }
1882     }
1883
1884     fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) {
1885         if !self.items_nameable && self.boundary == Some(it.def_id) {
1886             self.items_nameable = true;
1887         }
1888     }
1889 }
1890
1891 declare_lint! {
1892     /// The `keyword_idents` lint detects edition keywords being used as an
1893     /// identifier.
1894     ///
1895     /// ### Example
1896     ///
1897     /// ```rust,edition2015,compile_fail
1898     /// #![deny(keyword_idents)]
1899     /// // edition 2015
1900     /// fn dyn() {}
1901     /// ```
1902     ///
1903     /// {{produces}}
1904     ///
1905     /// ### Explanation
1906     ///
1907     /// Rust [editions] allow the language to evolve without breaking
1908     /// backwards compatibility. This lint catches code that uses new keywords
1909     /// that are added to the language that are used as identifiers (such as a
1910     /// variable name, function name, etc.). If you switch the compiler to a
1911     /// new edition without updating the code, then it will fail to compile if
1912     /// you are using a new keyword as an identifier.
1913     ///
1914     /// You can manually change the identifiers to a non-keyword, or use a
1915     /// [raw identifier], for example `r#dyn`, to transition to a new edition.
1916     ///
1917     /// This lint solves the problem automatically. It is "allow" by default
1918     /// because the code is perfectly valid in older editions. The [`cargo
1919     /// fix`] tool with the `--edition` flag will switch this lint to "warn"
1920     /// and automatically apply the suggested fix from the compiler (which is
1921     /// to use a raw identifier). This provides a completely automated way to
1922     /// update old code for a new edition.
1923     ///
1924     /// [editions]: https://doc.rust-lang.org/edition-guide/
1925     /// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
1926     /// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
1927     pub KEYWORD_IDENTS,
1928     Allow,
1929     "detects edition keywords being used as an identifier",
1930     @future_incompatible = FutureIncompatibleInfo {
1931         reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
1932         reason: FutureIncompatibilityReason::EditionError(Edition::Edition2018),
1933     };
1934 }
1935
1936 declare_lint_pass!(
1937     /// Check for uses of edition keywords used as an identifier.
1938     KeywordIdents => [KEYWORD_IDENTS]
1939 );
1940
1941 struct UnderMacro(bool);
1942
1943 impl KeywordIdents {
1944     fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: TokenStream) {
1945         for tt in tokens.into_trees() {
1946             match tt {
1947                 // Only report non-raw idents.
1948                 TokenTree::Token(token, _) => {
1949                     if let Some((ident, false)) = token.ident() {
1950                         self.check_ident_token(cx, UnderMacro(true), ident);
1951                     }
1952                 }
1953                 TokenTree::Delimited(_, _, tts) => self.check_tokens(cx, tts),
1954             }
1955         }
1956     }
1957
1958     fn check_ident_token(
1959         &mut self,
1960         cx: &EarlyContext<'_>,
1961         UnderMacro(under_macro): UnderMacro,
1962         ident: Ident,
1963     ) {
1964         let next_edition = match cx.sess().edition() {
1965             Edition::Edition2015 => {
1966                 match ident.name {
1967                     kw::Async | kw::Await | kw::Try => Edition::Edition2018,
1968
1969                     // rust-lang/rust#56327: Conservatively do not
1970                     // attempt to report occurrences of `dyn` within
1971                     // macro definitions or invocations, because `dyn`
1972                     // can legitimately occur as a contextual keyword
1973                     // in 2015 code denoting its 2018 meaning, and we
1974                     // do not want rustfix to inject bugs into working
1975                     // code by rewriting such occurrences.
1976                     //
1977                     // But if we see `dyn` outside of a macro, we know
1978                     // its precise role in the parsed AST and thus are
1979                     // assured this is truly an attempt to use it as
1980                     // an identifier.
1981                     kw::Dyn if !under_macro => Edition::Edition2018,
1982
1983                     _ => return,
1984                 }
1985             }
1986
1987             // There are no new keywords yet for the 2018 edition and beyond.
1988             _ => return,
1989         };
1990
1991         // Don't lint `r#foo`.
1992         if cx.sess().parse_sess.raw_identifier_spans.borrow().contains(&ident.span) {
1993             return;
1994         }
1995
1996         cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| {
1997             lint.build(fluent::lint::builtin_keyword_idents)
1998                 .set_arg("kw", ident.clone())
1999                 .set_arg("next", next_edition)
2000                 .span_suggestion(
2001                     ident.span,
2002                     fluent::lint::suggestion,
2003                     format!("r#{}", ident),
2004                     Applicability::MachineApplicable,
2005                 )
2006                 .emit();
2007         });
2008     }
2009 }
2010
2011 impl EarlyLintPass for KeywordIdents {
2012     fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef, _id: ast::NodeId) {
2013         self.check_tokens(cx, mac_def.body.inner_tokens());
2014     }
2015     fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
2016         self.check_tokens(cx, mac.args.inner_tokens());
2017     }
2018     fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
2019         self.check_ident_token(cx, UnderMacro(false), ident);
2020     }
2021 }
2022
2023 declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMENTS]);
2024
2025 impl ExplicitOutlivesRequirements {
2026     fn lifetimes_outliving_lifetime<'tcx>(
2027         inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
2028         def_id: DefId,
2029     ) -> Vec<ty::Region<'tcx>> {
2030         inferred_outlives
2031             .iter()
2032             .filter_map(|(pred, _)| match pred.kind().skip_binder() {
2033                 ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
2034                     ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b),
2035                     _ => None,
2036                 },
2037                 _ => None,
2038             })
2039             .collect()
2040     }
2041
2042     fn lifetimes_outliving_type<'tcx>(
2043         inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)],
2044         index: u32,
2045     ) -> Vec<ty::Region<'tcx>> {
2046         inferred_outlives
2047             .iter()
2048             .filter_map(|(pred, _)| match pred.kind().skip_binder() {
2049                 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => {
2050                     a.is_param(index).then_some(b)
2051                 }
2052                 _ => None,
2053             })
2054             .collect()
2055     }
2056
2057     fn collect_outlives_bound_spans<'tcx>(
2058         &self,
2059         tcx: TyCtxt<'tcx>,
2060         bounds: &hir::GenericBounds<'_>,
2061         inferred_outlives: &[ty::Region<'tcx>],
2062     ) -> Vec<(usize, Span)> {
2063         use rustc_middle::middle::resolve_lifetime::Region;
2064
2065         bounds
2066             .iter()
2067             .enumerate()
2068             .filter_map(|(i, bound)| {
2069                 if let hir::GenericBound::Outlives(lifetime) = bound {
2070                     let is_inferred = match tcx.named_region(lifetime.hir_id) {
2071                         Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| {
2072                             if let ty::ReEarlyBound(ebr) = **r {
2073                                 ebr.def_id == def_id
2074                             } else {
2075                                 false
2076                             }
2077                         }),
2078                         _ => false,
2079                     };
2080                     is_inferred.then_some((i, bound.span()))
2081                 } else {
2082                     None
2083                 }
2084             })
2085             .filter(|(_, span)| !in_external_macro(tcx.sess, *span))
2086             .collect()
2087     }
2088
2089     fn consolidate_outlives_bound_spans(
2090         &self,
2091         lo: Span,
2092         bounds: &hir::GenericBounds<'_>,
2093         bound_spans: Vec<(usize, Span)>,
2094     ) -> Vec<Span> {
2095         if bounds.is_empty() {
2096             return Vec::new();
2097         }
2098         if bound_spans.len() == bounds.len() {
2099             let (_, last_bound_span) = bound_spans[bound_spans.len() - 1];
2100             // If all bounds are inferable, we want to delete the colon, so
2101             // start from just after the parameter (span passed as argument)
2102             vec![lo.to(last_bound_span)]
2103         } else {
2104             let mut merged = Vec::new();
2105             let mut last_merged_i = None;
2106
2107             let mut from_start = true;
2108             for (i, bound_span) in bound_spans {
2109                 match last_merged_i {
2110                     // If the first bound is inferable, our span should also eat the leading `+`.
2111                     None if i == 0 => {
2112                         merged.push(bound_span.to(bounds[1].span().shrink_to_lo()));
2113                         last_merged_i = Some(0);
2114                     }
2115                     // If consecutive bounds are inferable, merge their spans
2116                     Some(h) if i == h + 1 => {
2117                         if let Some(tail) = merged.last_mut() {
2118                             // Also eat the trailing `+` if the first
2119                             // more-than-one bound is inferable
2120                             let to_span = if from_start && i < bounds.len() {
2121                                 bounds[i + 1].span().shrink_to_lo()
2122                             } else {
2123                                 bound_span
2124                             };
2125                             *tail = tail.to(to_span);
2126                             last_merged_i = Some(i);
2127                         } else {
2128                             bug!("another bound-span visited earlier");
2129                         }
2130                     }
2131                     _ => {
2132                         // When we find a non-inferable bound, subsequent inferable bounds
2133                         // won't be consecutive from the start (and we'll eat the leading
2134                         // `+` rather than the trailing one)
2135                         from_start = false;
2136                         merged.push(bounds[i - 1].span().shrink_to_hi().to(bound_span));
2137                         last_merged_i = Some(i);
2138                     }
2139                 }
2140             }
2141             merged
2142         }
2143     }
2144 }
2145
2146 impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
2147     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
2148         use rustc_middle::middle::resolve_lifetime::Region;
2149
2150         let def_id = item.def_id;
2151         if let hir::ItemKind::Struct(_, ref hir_generics)
2152         | hir::ItemKind::Enum(_, ref hir_generics)
2153         | hir::ItemKind::Union(_, ref hir_generics) = item.kind
2154         {
2155             let inferred_outlives = cx.tcx.inferred_outlives_of(def_id);
2156             if inferred_outlives.is_empty() {
2157                 return;
2158             }
2159
2160             let ty_generics = cx.tcx.generics_of(def_id);
2161
2162             let mut bound_count = 0;
2163             let mut lint_spans = Vec::new();
2164             let mut where_lint_spans = Vec::new();
2165             let mut dropped_predicate_count = 0;
2166             let num_predicates = hir_generics.predicates.len();
2167             for (i, where_predicate) in hir_generics.predicates.iter().enumerate() {
2168                 let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate {
2169                     hir::WherePredicate::RegionPredicate(predicate) => {
2170                         if let Some(Region::EarlyBound(region_def_id)) =
2171                             cx.tcx.named_region(predicate.lifetime.hir_id)
2172                         {
2173                             (
2174                                 Self::lifetimes_outliving_lifetime(
2175                                     inferred_outlives,
2176                                     region_def_id,
2177                                 ),
2178                                 &predicate.bounds,
2179                                 predicate.span,
2180                                 predicate.in_where_clause,
2181                             )
2182                         } else {
2183                             continue;
2184                         }
2185                     }
2186                     hir::WherePredicate::BoundPredicate(predicate) => {
2187                         // FIXME we can also infer bounds on associated types,
2188                         // and should check for them here.
2189                         match predicate.bounded_ty.kind {
2190                             hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
2191                                 let Res::Def(DefKind::TyParam, def_id) = path.res else {
2192                                     continue
2193                                 };
2194                                 let index = ty_generics.param_def_id_to_index[&def_id];
2195                                 (
2196                                     Self::lifetimes_outliving_type(inferred_outlives, index),
2197                                     &predicate.bounds,
2198                                     predicate.span,
2199                                     predicate.origin == PredicateOrigin::WhereClause,
2200                                 )
2201                             }
2202                             _ => {
2203                                 continue;
2204                             }
2205                         }
2206                     }
2207                     _ => continue,
2208                 };
2209                 if relevant_lifetimes.is_empty() {
2210                     continue;
2211                 }
2212
2213                 let bound_spans =
2214                     self.collect_outlives_bound_spans(cx.tcx, bounds, &relevant_lifetimes);
2215                 bound_count += bound_spans.len();
2216
2217                 let drop_predicate = bound_spans.len() == bounds.len();
2218                 if drop_predicate {
2219                     dropped_predicate_count += 1;
2220                 }
2221
2222                 if drop_predicate && !in_where_clause {
2223                     lint_spans.push(span);
2224                 } else if drop_predicate && i + 1 < num_predicates {
2225                     // If all the bounds on a predicate were inferable and there are
2226                     // further predicates, we want to eat the trailing comma.
2227                     let next_predicate_span = hir_generics.predicates[i + 1].span();
2228                     where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo()));
2229                 } else {
2230                     where_lint_spans.extend(self.consolidate_outlives_bound_spans(
2231                         span.shrink_to_lo(),
2232                         bounds,
2233                         bound_spans,
2234                     ));
2235                 }
2236             }
2237
2238             // If all predicates are inferable, drop the entire clause
2239             // (including the `where`)
2240             if hir_generics.has_where_clause_predicates && dropped_predicate_count == num_predicates
2241             {
2242                 let where_span = hir_generics.where_clause_span;
2243                 // Extend the where clause back to the closing `>` of the
2244                 // generics, except for tuple struct, which have the `where`
2245                 // after the fields of the struct.
2246                 let full_where_span =
2247                     if let hir::ItemKind::Struct(hir::VariantData::Tuple(..), _) = item.kind {
2248                         where_span
2249                     } else {
2250                         hir_generics.span.shrink_to_hi().to(where_span)
2251                     };
2252                 lint_spans.push(full_where_span);
2253             } else {
2254                 lint_spans.extend(where_lint_spans);
2255             }
2256
2257             if !lint_spans.is_empty() {
2258                 cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| {
2259                     lint.build(fluent::lint::builtin_explicit_outlives)
2260                         .set_arg("count", bound_count)
2261                         .multipart_suggestion(
2262                             fluent::lint::suggestion,
2263                             lint_spans
2264                                 .into_iter()
2265                                 .map(|span| (span, String::new()))
2266                                 .collect::<Vec<_>>(),
2267                             Applicability::MachineApplicable,
2268                         )
2269                         .emit();
2270                 });
2271             }
2272         }
2273     }
2274 }
2275
2276 declare_lint! {
2277     /// The `incomplete_features` lint detects unstable features enabled with
2278     /// the [`feature` attribute] that may function improperly in some or all
2279     /// cases.
2280     ///
2281     /// [`feature` attribute]: https://doc.rust-lang.org/nightly/unstable-book/
2282     ///
2283     /// ### Example
2284     ///
2285     /// ```rust
2286     /// #![feature(generic_const_exprs)]
2287     /// ```
2288     ///
2289     /// {{produces}}
2290     ///
2291     /// ### Explanation
2292     ///
2293     /// Although it is encouraged for people to experiment with unstable
2294     /// features, some of them are known to be incomplete or faulty. This lint
2295     /// is a signal that the feature has not yet been finished, and you may
2296     /// experience problems with it.
2297     pub INCOMPLETE_FEATURES,
2298     Warn,
2299     "incomplete features that may function improperly in some or all cases"
2300 }
2301
2302 declare_lint_pass!(
2303     /// Check for used feature gates in `INCOMPLETE_FEATURES` in `rustc_feature/src/active.rs`.
2304     IncompleteFeatures => [INCOMPLETE_FEATURES]
2305 );
2306
2307 impl EarlyLintPass for IncompleteFeatures {
2308     fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
2309         let features = cx.sess().features_untracked();
2310         features
2311             .declared_lang_features
2312             .iter()
2313             .map(|(name, span, _)| (name, span))
2314             .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span)))
2315             .filter(|(&name, _)| features.incomplete(name))
2316             .for_each(|(&name, &span)| {
2317                 cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| {
2318                     let mut builder = lint.build(fluent::lint::builtin_incomplete_features);
2319                     builder.set_arg("name", name);
2320                     if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) {
2321                         builder.set_arg("n", n);
2322                         builder.note(fluent::lint::note);
2323                     }
2324                     if HAS_MIN_FEATURES.contains(&name) {
2325                         builder.help(fluent::lint::help);
2326                     }
2327                     builder.emit();
2328                 })
2329             });
2330     }
2331 }
2332
2333 const HAS_MIN_FEATURES: &[Symbol] = &[sym::specialization];
2334
2335 declare_lint! {
2336     /// The `invalid_value` lint detects creating a value that is not valid,
2337     /// such as a null reference.
2338     ///
2339     /// ### Example
2340     ///
2341     /// ```rust,no_run
2342     /// # #![allow(unused)]
2343     /// unsafe {
2344     ///     let x: &'static i32 = std::mem::zeroed();
2345     /// }
2346     /// ```
2347     ///
2348     /// {{produces}}
2349     ///
2350     /// ### Explanation
2351     ///
2352     /// In some situations the compiler can detect that the code is creating
2353     /// an invalid value, which should be avoided.
2354     ///
2355     /// In particular, this lint will check for improper use of
2356     /// [`mem::zeroed`], [`mem::uninitialized`], [`mem::transmute`], and
2357     /// [`MaybeUninit::assume_init`] that can cause [undefined behavior]. The
2358     /// lint should provide extra information to indicate what the problem is
2359     /// and a possible solution.
2360     ///
2361     /// [`mem::zeroed`]: https://doc.rust-lang.org/std/mem/fn.zeroed.html
2362     /// [`mem::uninitialized`]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html
2363     /// [`mem::transmute`]: https://doc.rust-lang.org/std/mem/fn.transmute.html
2364     /// [`MaybeUninit::assume_init`]: https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#method.assume_init
2365     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
2366     pub INVALID_VALUE,
2367     Warn,
2368     "an invalid value is being created (such as a null reference)"
2369 }
2370
2371 declare_lint_pass!(InvalidValue => [INVALID_VALUE]);
2372
2373 impl<'tcx> LateLintPass<'tcx> for InvalidValue {
2374     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
2375         #[derive(Debug, Copy, Clone, PartialEq)]
2376         enum InitKind {
2377             Zeroed,
2378             Uninit,
2379         }
2380
2381         /// Information about why a type cannot be initialized this way.
2382         /// Contains an error message and optionally a span to point at.
2383         type InitError = (String, Option<Span>);
2384
2385         /// Test if this constant is all-0.
2386         fn is_zero(expr: &hir::Expr<'_>) -> bool {
2387             use hir::ExprKind::*;
2388             use rustc_ast::LitKind::*;
2389             match &expr.kind {
2390                 Lit(lit) => {
2391                     if let Int(i, _) = lit.node {
2392                         i == 0
2393                     } else {
2394                         false
2395                     }
2396                 }
2397                 Tup(tup) => tup.iter().all(is_zero),
2398                 _ => false,
2399             }
2400         }
2401
2402         /// Determine if this expression is a "dangerous initialization".
2403         fn is_dangerous_init(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<InitKind> {
2404             if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind {
2405                 // Find calls to `mem::{uninitialized,zeroed}` methods.
2406                 if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
2407                     let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
2408                     match cx.tcx.get_diagnostic_name(def_id) {
2409                         Some(sym::mem_zeroed) => return Some(InitKind::Zeroed),
2410                         Some(sym::mem_uninitialized) => return Some(InitKind::Uninit),
2411                         Some(sym::transmute) if is_zero(&args[0]) => return Some(InitKind::Zeroed),
2412                         _ => {}
2413                     }
2414                 }
2415             } else if let hir::ExprKind::MethodCall(_, ref args, _) = expr.kind {
2416                 // Find problematic calls to `MaybeUninit::assume_init`.
2417                 let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
2418                 if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {
2419                     // This is a call to *some* method named `assume_init`.
2420                     // See if the `self` parameter is one of the dangerous constructors.
2421                     if let hir::ExprKind::Call(ref path_expr, _) = args[0].kind {
2422                         if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
2423                             let def_id = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()?;
2424                             match cx.tcx.get_diagnostic_name(def_id) {
2425                                 Some(sym::maybe_uninit_zeroed) => return Some(InitKind::Zeroed),
2426                                 Some(sym::maybe_uninit_uninit) => return Some(InitKind::Uninit),
2427                                 _ => {}
2428                             }
2429                         }
2430                     }
2431                 }
2432             }
2433
2434             None
2435         }
2436
2437         /// Test if this enum has several actually "existing" variants.
2438         /// Zero-sized uninhabited variants do not always have a tag assigned and thus do not "exist".
2439         fn is_multi_variant<'tcx>(adt: ty::AdtDef<'tcx>) -> bool {
2440             // As an approximation, we only count dataless variants. Those are definitely inhabited.
2441             let existing_variants = adt.variants().iter().filter(|v| v.fields.is_empty()).count();
2442             existing_variants > 1
2443         }
2444
2445         /// Return `Some` only if we are sure this type does *not*
2446         /// allow zero initialization.
2447         fn ty_find_init_error<'tcx>(
2448             cx: &LateContext<'tcx>,
2449             ty: Ty<'tcx>,
2450             init: InitKind,
2451         ) -> Option<InitError> {
2452             use rustc_type_ir::sty::TyKind::*;
2453             match ty.kind() {
2454                 // Primitive types that don't like 0 as a value.
2455                 Ref(..) => Some(("references must be non-null".to_string(), None)),
2456                 Adt(..) if ty.is_box() => Some(("`Box` must be non-null".to_string(), None)),
2457                 FnPtr(..) => Some(("function pointers must be non-null".to_string(), None)),
2458                 Never => Some(("the `!` type has no valid value".to_string(), None)),
2459                 RawPtr(tm) if matches!(tm.ty.kind(), Dynamic(..)) =>
2460                 // raw ptr to dyn Trait
2461                 {
2462                     Some(("the vtable of a wide raw pointer must be non-null".to_string(), None))
2463                 }
2464                 // Primitive types with other constraints.
2465                 Bool if init == InitKind::Uninit => {
2466                     Some(("booleans must be either `true` or `false`".to_string(), None))
2467                 }
2468                 Char if init == InitKind::Uninit => {
2469                     Some(("characters must be a valid Unicode codepoint".to_string(), None))
2470                 }
2471                 Int(_) | Uint(_) if init == InitKind::Uninit => {
2472                     Some(("integers must not be uninitialized".to_string(), None))
2473                 }
2474                 Float(_) if init == InitKind::Uninit => {
2475                     Some(("floats must not be uninitialized".to_string(), None))
2476                 }
2477                 RawPtr(_) if init == InitKind::Uninit => {
2478                     Some(("raw pointers must not be uninitialized".to_string(), None))
2479                 }
2480                 // Recurse and checks for some compound types.
2481                 Adt(adt_def, substs) if !adt_def.is_union() => {
2482                     // First check if this ADT has a layout attribute (like `NonNull` and friends).
2483                     use std::ops::Bound;
2484                     match cx.tcx.layout_scalar_valid_range(adt_def.did()) {
2485                         // We exploit here that `layout_scalar_valid_range` will never
2486                         // return `Bound::Excluded`.  (And we have tests checking that we
2487                         // handle the attribute correctly.)
2488                         (Bound::Included(lo), _) if lo > 0 => {
2489                             return Some((format!("`{}` must be non-null", ty), None));
2490                         }
2491                         (Bound::Included(_), _) | (_, Bound::Included(_))
2492                             if init == InitKind::Uninit =>
2493                         {
2494                             return Some((
2495                                 format!(
2496                                     "`{}` must be initialized inside its custom valid range",
2497                                     ty,
2498                                 ),
2499                                 None,
2500                             ));
2501                         }
2502                         _ => {}
2503                     }
2504                     // Now, recurse.
2505                     match adt_def.variants().len() {
2506                         0 => Some(("enums with no variants have no valid value".to_string(), None)),
2507                         1 => {
2508                             // Struct, or enum with exactly one variant.
2509                             // Proceed recursively, check all fields.
2510                             let variant = &adt_def.variant(VariantIdx::from_u32(0));
2511                             variant.fields.iter().find_map(|field| {
2512                                 ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(
2513                                     |(mut msg, span)| {
2514                                         if span.is_none() {
2515                                             // Point to this field, should be helpful for figuring
2516                                             // out where the source of the error is.
2517                                             let span = cx.tcx.def_span(field.did);
2518                                             write!(
2519                                                 &mut msg,
2520                                                 " (in this {} field)",
2521                                                 adt_def.descr()
2522                                             )
2523                                             .unwrap();
2524                                             (msg, Some(span))
2525                                         } else {
2526                                             // Just forward.
2527                                             (msg, span)
2528                                         }
2529                                     },
2530                                 )
2531                             })
2532                         }
2533                         // Multi-variant enum.
2534                         _ => {
2535                             if init == InitKind::Uninit && is_multi_variant(*adt_def) {
2536                                 let span = cx.tcx.def_span(adt_def.did());
2537                                 Some((
2538                                     "enums have to be initialized to a variant".to_string(),
2539                                     Some(span),
2540                                 ))
2541                             } else {
2542                                 // In principle, for zero-initialization we could figure out which variant corresponds
2543                                 // to tag 0, and check that... but for now we just accept all zero-initializations.
2544                                 None
2545                             }
2546                         }
2547                     }
2548                 }
2549                 Tuple(..) => {
2550                     // Proceed recursively, check all fields.
2551                     ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
2552                 }
2553                 Array(ty, len) => {
2554                     if matches!(len.try_eval_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
2555                         // Array length known at array non-empty -- recurse.
2556                         ty_find_init_error(cx, *ty, init)
2557                     } else {
2558                         // Empty array or size unknown.
2559                         None
2560                     }
2561                 }
2562                 // Conservative fallback.
2563                 _ => None,
2564             }
2565         }
2566
2567         if let Some(init) = is_dangerous_init(cx, expr) {
2568             // This conjures an instance of a type out of nothing,
2569             // using zeroed or uninitialized memory.
2570             // We are extremely conservative with what we warn about.
2571             let conjured_ty = cx.typeck_results().expr_ty(expr);
2572             if let Some((msg, span)) =
2573                 with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
2574             {
2575                 // FIXME(davidtwco): make translatable
2576                 cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| {
2577                     let mut err = lint.build(&format!(
2578                         "the type `{}` does not permit {}",
2579                         conjured_ty,
2580                         match init {
2581                             InitKind::Zeroed => "zero-initialization",
2582                             InitKind::Uninit => "being left uninitialized",
2583                         },
2584                     ));
2585                     err.span_label(expr.span, "this code causes undefined behavior when executed");
2586                     err.span_label(
2587                         expr.span,
2588                         "help: use `MaybeUninit<T>` instead, \
2589                             and only call `assume_init` after initialization is done",
2590                     );
2591                     if let Some(span) = span {
2592                         err.span_note(span, &msg);
2593                     } else {
2594                         err.note(&msg);
2595                     }
2596                     err.emit();
2597                 });
2598             }
2599         }
2600     }
2601 }
2602
2603 declare_lint! {
2604     /// The `clashing_extern_declarations` lint detects when an `extern fn`
2605     /// has been declared with the same name but different types.
2606     ///
2607     /// ### Example
2608     ///
2609     /// ```rust
2610     /// mod m {
2611     ///     extern "C" {
2612     ///         fn foo();
2613     ///     }
2614     /// }
2615     ///
2616     /// extern "C" {
2617     ///     fn foo(_: u32);
2618     /// }
2619     /// ```
2620     ///
2621     /// {{produces}}
2622     ///
2623     /// ### Explanation
2624     ///
2625     /// Because two symbols of the same name cannot be resolved to two
2626     /// different functions at link time, and one function cannot possibly
2627     /// have two types, a clashing extern declaration is almost certainly a
2628     /// mistake. Check to make sure that the `extern` definitions are correct
2629     /// and equivalent, and possibly consider unifying them in one location.
2630     ///
2631     /// This lint does not run between crates because a project may have
2632     /// dependencies which both rely on the same extern function, but declare
2633     /// it in a different (but valid) way. For example, they may both declare
2634     /// an opaque type for one or more of the arguments (which would end up
2635     /// distinct types), or use types that are valid conversions in the
2636     /// language the `extern fn` is defined in. In these cases, the compiler
2637     /// can't say that the clashing declaration is incorrect.
2638     pub CLASHING_EXTERN_DECLARATIONS,
2639     Warn,
2640     "detects when an extern fn has been declared with the same name but different types"
2641 }
2642
2643 pub struct ClashingExternDeclarations {
2644     /// Map of function symbol name to the first-seen hir id for that symbol name.. If seen_decls
2645     /// contains an entry for key K, it means a symbol with name K has been seen by this lint and
2646     /// the symbol should be reported as a clashing declaration.
2647     // FIXME: Technically, we could just store a &'tcx str here without issue; however, the
2648     // `impl_lint_pass` macro doesn't currently support lints parametric over a lifetime.
2649     seen_decls: FxHashMap<Symbol, HirId>,
2650 }
2651
2652 /// Differentiate between whether the name for an extern decl came from the link_name attribute or
2653 /// just from declaration itself. This is important because we don't want to report clashes on
2654 /// symbol name if they don't actually clash because one or the other links against a symbol with a
2655 /// different name.
2656 enum SymbolName {
2657     /// The name of the symbol + the span of the annotation which introduced the link name.
2658     Link(Symbol, Span),
2659     /// No link name, so just the name of the symbol.
2660     Normal(Symbol),
2661 }
2662
2663 impl SymbolName {
2664     fn get_name(&self) -> Symbol {
2665         match self {
2666             SymbolName::Link(s, _) | SymbolName::Normal(s) => *s,
2667         }
2668     }
2669 }
2670
2671 impl ClashingExternDeclarations {
2672     pub(crate) fn new() -> Self {
2673         ClashingExternDeclarations { seen_decls: FxHashMap::default() }
2674     }
2675     /// Insert a new foreign item into the seen set. If a symbol with the same name already exists
2676     /// for the item, return its HirId without updating the set.
2677     fn insert(&mut self, tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> Option<HirId> {
2678         let did = fi.def_id.to_def_id();
2679         let instance = Instance::new(did, ty::List::identity_for_item(tcx, did));
2680         let name = Symbol::intern(tcx.symbol_name(instance).name);
2681         if let Some(&hir_id) = self.seen_decls.get(&name) {
2682             // Avoid updating the map with the new entry when we do find a collision. We want to
2683             // make sure we're always pointing to the first definition as the previous declaration.
2684             // This lets us avoid emitting "knock-on" diagnostics.
2685             Some(hir_id)
2686         } else {
2687             self.seen_decls.insert(name, fi.hir_id())
2688         }
2689     }
2690
2691     /// Get the name of the symbol that's linked against for a given extern declaration. That is,
2692     /// the name specified in a #[link_name = ...] attribute if one was specified, else, just the
2693     /// symbol's name.
2694     fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> SymbolName {
2695         if let Some((overridden_link_name, overridden_link_name_span)) =
2696             tcx.codegen_fn_attrs(fi.def_id).link_name.map(|overridden_link_name| {
2697                 // FIXME: Instead of searching through the attributes again to get span
2698                 // information, we could have codegen_fn_attrs also give span information back for
2699                 // where the attribute was defined. However, until this is found to be a
2700                 // bottleneck, this does just fine.
2701                 (
2702                     overridden_link_name,
2703                     tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span,
2704                 )
2705             })
2706         {
2707             SymbolName::Link(overridden_link_name, overridden_link_name_span)
2708         } else {
2709             SymbolName::Normal(fi.ident.name)
2710         }
2711     }
2712
2713     /// Checks whether two types are structurally the same enough that the declarations shouldn't
2714     /// clash. We need this so we don't emit a lint when two modules both declare an extern struct,
2715     /// with the same members (as the declarations shouldn't clash).
2716     fn structurally_same_type<'tcx>(
2717         cx: &LateContext<'tcx>,
2718         a: Ty<'tcx>,
2719         b: Ty<'tcx>,
2720         ckind: CItemKind,
2721     ) -> bool {
2722         fn structurally_same_type_impl<'tcx>(
2723             seen_types: &mut FxHashSet<(Ty<'tcx>, Ty<'tcx>)>,
2724             cx: &LateContext<'tcx>,
2725             a: Ty<'tcx>,
2726             b: Ty<'tcx>,
2727             ckind: CItemKind,
2728         ) -> bool {
2729             debug!("structurally_same_type_impl(cx, a = {:?}, b = {:?})", a, b);
2730             let tcx = cx.tcx;
2731
2732             // Given a transparent newtype, reach through and grab the inner
2733             // type unless the newtype makes the type non-null.
2734             let non_transparent_ty = |ty: Ty<'tcx>| -> Ty<'tcx> {
2735                 let mut ty = ty;
2736                 loop {
2737                     if let ty::Adt(def, substs) = *ty.kind() {
2738                         let is_transparent = def.repr().transparent();
2739                         let is_non_null = crate::types::nonnull_optimization_guaranteed(tcx, def);
2740                         debug!(
2741                             "non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
2742                             ty, is_transparent, is_non_null
2743                         );
2744                         if is_transparent && !is_non_null {
2745                             debug_assert!(def.variants().len() == 1);
2746                             let v = &def.variant(VariantIdx::new(0));
2747                             ty = transparent_newtype_field(tcx, v)
2748                                 .expect(
2749                                     "single-variant transparent structure with zero-sized field",
2750                                 )
2751                                 .ty(tcx, substs);
2752                             continue;
2753                         }
2754                     }
2755                     debug!("non_transparent_ty -> {:?}", ty);
2756                     return ty;
2757                 }
2758             };
2759
2760             let a = non_transparent_ty(a);
2761             let b = non_transparent_ty(b);
2762
2763             if !seen_types.insert((a, b)) {
2764                 // We've encountered a cycle. There's no point going any further -- the types are
2765                 // structurally the same.
2766                 return true;
2767             }
2768             let tcx = cx.tcx;
2769             if a == b {
2770                 // All nominally-same types are structurally same, too.
2771                 true
2772             } else {
2773                 // Do a full, depth-first comparison between the two.
2774                 use rustc_type_ir::sty::TyKind::*;
2775                 let a_kind = a.kind();
2776                 let b_kind = b.kind();
2777
2778                 let compare_layouts = |a, b| -> Result<bool, LayoutError<'tcx>> {
2779                     debug!("compare_layouts({:?}, {:?})", a, b);
2780                     let a_layout = &cx.layout_of(a)?.layout.abi();
2781                     let b_layout = &cx.layout_of(b)?.layout.abi();
2782                     debug!(
2783                         "comparing layouts: {:?} == {:?} = {}",
2784                         a_layout,
2785                         b_layout,
2786                         a_layout == b_layout
2787                     );
2788                     Ok(a_layout == b_layout)
2789                 };
2790
2791                 #[allow(rustc::usage_of_ty_tykind)]
2792                 let is_primitive_or_pointer = |kind: &ty::TyKind<'_>| {
2793                     kind.is_primitive() || matches!(kind, RawPtr(..) | Ref(..))
2794                 };
2795
2796                 ensure_sufficient_stack(|| {
2797                     match (a_kind, b_kind) {
2798                         (Adt(a_def, _), Adt(b_def, _)) => {
2799                             // We can immediately rule out these types as structurally same if
2800                             // their layouts differ.
2801                             match compare_layouts(a, b) {
2802                                 Ok(false) => return false,
2803                                 _ => (), // otherwise, continue onto the full, fields comparison
2804                             }
2805
2806                             // Grab a flattened representation of all fields.
2807                             let a_fields = a_def.variants().iter().flat_map(|v| v.fields.iter());
2808                             let b_fields = b_def.variants().iter().flat_map(|v| v.fields.iter());
2809
2810                             // Perform a structural comparison for each field.
2811                             a_fields.eq_by(
2812                                 b_fields,
2813                                 |&ty::FieldDef { did: a_did, .. },
2814                                  &ty::FieldDef { did: b_did, .. }| {
2815                                     structurally_same_type_impl(
2816                                         seen_types,
2817                                         cx,
2818                                         tcx.type_of(a_did),
2819                                         tcx.type_of(b_did),
2820                                         ckind,
2821                                     )
2822                                 },
2823                             )
2824                         }
2825                         (Array(a_ty, a_const), Array(b_ty, b_const)) => {
2826                             // For arrays, we also check the constness of the type.
2827                             a_const.kind() == b_const.kind()
2828                                 && structurally_same_type_impl(seen_types, cx, *a_ty, *b_ty, ckind)
2829                         }
2830                         (Slice(a_ty), Slice(b_ty)) => {
2831                             structurally_same_type_impl(seen_types, cx, *a_ty, *b_ty, ckind)
2832                         }
2833                         (RawPtr(a_tymut), RawPtr(b_tymut)) => {
2834                             a_tymut.mutbl == b_tymut.mutbl
2835                                 && structurally_same_type_impl(
2836                                     seen_types, cx, a_tymut.ty, b_tymut.ty, ckind,
2837                                 )
2838                         }
2839                         (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
2840                             // For structural sameness, we don't need the region to be same.
2841                             a_mut == b_mut
2842                                 && structurally_same_type_impl(seen_types, cx, *a_ty, *b_ty, ckind)
2843                         }
2844                         (FnDef(..), FnDef(..)) => {
2845                             let a_poly_sig = a.fn_sig(tcx);
2846                             let b_poly_sig = b.fn_sig(tcx);
2847
2848                             // We don't compare regions, but leaving bound regions around ICEs, so
2849                             // we erase them.
2850                             let a_sig = tcx.erase_late_bound_regions(a_poly_sig);
2851                             let b_sig = tcx.erase_late_bound_regions(b_poly_sig);
2852
2853                             (a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
2854                                 == (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
2855                                 && a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
2856                                     structurally_same_type_impl(seen_types, cx, *a, *b, ckind)
2857                                 })
2858                                 && structurally_same_type_impl(
2859                                     seen_types,
2860                                     cx,
2861                                     a_sig.output(),
2862                                     b_sig.output(),
2863                                     ckind,
2864                                 )
2865                         }
2866                         (Tuple(a_substs), Tuple(b_substs)) => {
2867                             a_substs.iter().eq_by(b_substs.iter(), |a_ty, b_ty| {
2868                                 structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
2869                             })
2870                         }
2871                         // For these, it's not quite as easy to define structural-sameness quite so easily.
2872                         // For the purposes of this lint, take the conservative approach and mark them as
2873                         // not structurally same.
2874                         (Dynamic(..), Dynamic(..))
2875                         | (Error(..), Error(..))
2876                         | (Closure(..), Closure(..))
2877                         | (Generator(..), Generator(..))
2878                         | (GeneratorWitness(..), GeneratorWitness(..))
2879                         | (Projection(..), Projection(..))
2880                         | (Opaque(..), Opaque(..)) => false,
2881
2882                         // These definitely should have been caught above.
2883                         (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
2884
2885                         // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
2886                         // enum layout optimisation is being applied.
2887                         (Adt(..), other_kind) | (other_kind, Adt(..))
2888                             if is_primitive_or_pointer(other_kind) =>
2889                         {
2890                             let (primitive, adt) =
2891                                 if is_primitive_or_pointer(a.kind()) { (a, b) } else { (b, a) };
2892                             if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) {
2893                                 ty == primitive
2894                             } else {
2895                                 compare_layouts(a, b).unwrap_or(false)
2896                             }
2897                         }
2898                         // Otherwise, just compare the layouts. This may fail to lint for some
2899                         // incompatible types, but at the very least, will stop reads into
2900                         // uninitialised memory.
2901                         _ => compare_layouts(a, b).unwrap_or(false),
2902                     }
2903                 })
2904             }
2905         }
2906         let mut seen_types = FxHashSet::default();
2907         structurally_same_type_impl(&mut seen_types, cx, a, b, ckind)
2908     }
2909 }
2910
2911 impl_lint_pass!(ClashingExternDeclarations => [CLASHING_EXTERN_DECLARATIONS]);
2912
2913 impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
2914     fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, this_fi: &hir::ForeignItem<'_>) {
2915         trace!("ClashingExternDeclarations: check_foreign_item: {:?}", this_fi);
2916         if let ForeignItemKind::Fn(..) = this_fi.kind {
2917             let tcx = cx.tcx;
2918             if let Some(existing_hid) = self.insert(tcx, this_fi) {
2919                 let existing_decl_ty = tcx.type_of(tcx.hir().local_def_id(existing_hid));
2920                 let this_decl_ty = tcx.type_of(this_fi.def_id);
2921                 debug!(
2922                     "ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
2923                     existing_hid, existing_decl_ty, this_fi.def_id, this_decl_ty
2924                 );
2925                 // Check that the declarations match.
2926                 if !Self::structurally_same_type(
2927                     cx,
2928                     existing_decl_ty,
2929                     this_decl_ty,
2930                     CItemKind::Declaration,
2931                 ) {
2932                     let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner());
2933                     let orig = Self::name_of_extern_decl(tcx, orig_fi);
2934
2935                     // We want to ensure that we use spans for both decls that include where the
2936                     // name was defined, whether that was from the link_name attribute or not.
2937                     let get_relevant_span =
2938                         |fi: &hir::ForeignItem<'_>| match Self::name_of_extern_decl(tcx, fi) {
2939                             SymbolName::Normal(_) => fi.span,
2940                             SymbolName::Link(_, annot_span) => fi.span.to(annot_span),
2941                         };
2942                     // Finally, emit the diagnostic.
2943                     tcx.struct_span_lint_hir(
2944                         CLASHING_EXTERN_DECLARATIONS,
2945                         this_fi.hir_id(),
2946                         get_relevant_span(this_fi),
2947                         |lint| {
2948                             let mut expected_str = DiagnosticStyledString::new();
2949                             expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false);
2950                             let mut found_str = DiagnosticStyledString::new();
2951                             found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true);
2952
2953                             lint.build(if orig.get_name() == this_fi.ident.name {
2954                                 fluent::lint::builtin_clashing_extern_same_name
2955                             } else {
2956                                 fluent::lint::builtin_clashing_extern_diff_name
2957                             })
2958                             .set_arg("this_fi", this_fi.ident.name)
2959                             .set_arg("orig", orig.get_name())
2960                             .span_label(
2961                                 get_relevant_span(orig_fi),
2962                                 fluent::lint::previous_decl_label,
2963                             )
2964                             .span_label(get_relevant_span(this_fi), fluent::lint::mismatch_label)
2965                             // FIXME(davidtwco): translatable expected/found
2966                             .note_expected_found(&"", expected_str, &"", found_str)
2967                             .emit();
2968                         },
2969                     );
2970                 }
2971             }
2972         }
2973     }
2974 }
2975
2976 declare_lint! {
2977     /// The `deref_nullptr` lint detects when an null pointer is dereferenced,
2978     /// which causes [undefined behavior].
2979     ///
2980     /// ### Example
2981     ///
2982     /// ```rust,no_run
2983     /// # #![allow(unused)]
2984     /// use std::ptr;
2985     /// unsafe {
2986     ///     let x = &*ptr::null::<i32>();
2987     ///     let x = ptr::addr_of!(*ptr::null::<i32>());
2988     ///     let x = *(0 as *const i32);
2989     /// }
2990     /// ```
2991     ///
2992     /// {{produces}}
2993     ///
2994     /// ### Explanation
2995     ///
2996     /// Dereferencing a null pointer causes [undefined behavior] even as a place expression,
2997     /// like `&*(0 as *const i32)` or `addr_of!(*(0 as *const i32))`.
2998     ///
2999     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
3000     pub DEREF_NULLPTR,
3001     Warn,
3002     "detects when an null pointer is dereferenced"
3003 }
3004
3005 declare_lint_pass!(DerefNullPtr => [DEREF_NULLPTR]);
3006
3007 impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
3008     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) {
3009         /// test if expression is a null ptr
3010         fn is_null_ptr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
3011             match &expr.kind {
3012                 rustc_hir::ExprKind::Cast(ref expr, ref ty) => {
3013                     if let rustc_hir::TyKind::Ptr(_) = ty.kind {
3014                         return is_zero(expr) || is_null_ptr(cx, expr);
3015                     }
3016                 }
3017                 // check for call to `core::ptr::null` or `core::ptr::null_mut`
3018                 rustc_hir::ExprKind::Call(ref path, _) => {
3019                     if let rustc_hir::ExprKind::Path(ref qpath) = path.kind {
3020                         if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() {
3021                             return matches!(
3022                                 cx.tcx.get_diagnostic_name(def_id),
3023                                 Some(sym::ptr_null | sym::ptr_null_mut)
3024                             );
3025                         }
3026                     }
3027                 }
3028                 _ => {}
3029             }
3030             false
3031         }
3032
3033         /// test if expression is the literal `0`
3034         fn is_zero(expr: &hir::Expr<'_>) -> bool {
3035             match &expr.kind {
3036                 rustc_hir::ExprKind::Lit(ref lit) => {
3037                     if let LitKind::Int(a, _) = lit.node {
3038                         return a == 0;
3039                     }
3040                 }
3041                 _ => {}
3042             }
3043             false
3044         }
3045
3046         if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
3047             if is_null_ptr(cx, expr_deref) {
3048                 cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
3049                     let mut err = lint.build(fluent::lint::builtin_deref_nullptr);
3050                     err.span_label(expr.span, fluent::lint::label);
3051                     err.emit();
3052                 });
3053             }
3054         }
3055     }
3056 }
3057
3058 declare_lint! {
3059     /// The `named_asm_labels` lint detects the use of named labels in the
3060     /// inline `asm!` macro.
3061     ///
3062     /// ### Example
3063     ///
3064     /// ```rust,compile_fail
3065     /// use std::arch::asm;
3066     ///
3067     /// fn main() {
3068     ///     unsafe {
3069     ///         asm!("foo: bar");
3070     ///     }
3071     /// }
3072     /// ```
3073     ///
3074     /// {{produces}}
3075     ///
3076     /// ### Explanation
3077     ///
3078     /// LLVM is allowed to duplicate inline assembly blocks for any
3079     /// reason, for example when it is in a function that gets inlined. Because
3080     /// of this, GNU assembler [local labels] *must* be used instead of labels
3081     /// with a name. Using named labels might cause assembler or linker errors.
3082     ///
3083     /// See the explanation in [Rust By Example] for more details.
3084     ///
3085     /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
3086     /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels
3087     pub NAMED_ASM_LABELS,
3088     Deny,
3089     "named labels in inline assembly",
3090 }
3091
3092 declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]);
3093
3094 impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
3095     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
3096         if let hir::Expr {
3097             kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, .. }),
3098             ..
3099         } = expr
3100         {
3101             for (template_sym, template_snippet, template_span) in template_strs.iter() {
3102                 let template_str = template_sym.as_str();
3103                 let find_label_span = |needle: &str| -> Option<Span> {
3104                     if let Some(template_snippet) = template_snippet {
3105                         let snippet = template_snippet.as_str();
3106                         if let Some(pos) = snippet.find(needle) {
3107                             let end = pos
3108                                 + snippet[pos..]
3109                                     .find(|c| c == ':')
3110                                     .unwrap_or(snippet[pos..].len() - 1);
3111                             let inner = InnerSpan::new(pos, end);
3112                             return Some(template_span.from_inner(inner));
3113                         }
3114                     }
3115
3116                     None
3117                 };
3118
3119                 let mut found_labels = Vec::new();
3120
3121                 // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
3122                 let statements = template_str.split(|c| matches!(c, '\n' | ';'));
3123                 for statement in statements {
3124                     // If there's a comment, trim it from the statement
3125                     let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
3126                     let mut start_idx = 0;
3127                     for (idx, _) in statement.match_indices(':') {
3128                         let possible_label = statement[start_idx..idx].trim();
3129                         let mut chars = possible_label.chars();
3130                         let Some(c) = chars.next() else {
3131                             // Empty string means a leading ':' in this section, which is not a label
3132                             break
3133                         };
3134                         // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
3135                         if (c.is_alphabetic() || matches!(c, '.' | '_'))
3136                             && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
3137                         {
3138                             found_labels.push(possible_label);
3139                         } else {
3140                             // If we encounter a non-label, there cannot be any further labels, so stop checking
3141                             break;
3142                         }
3143
3144                         start_idx = idx + 1;
3145                     }
3146                 }
3147
3148                 debug!("NamedAsmLabels::check_expr(): found_labels: {:#?}", &found_labels);
3149
3150                 if found_labels.len() > 0 {
3151                     let spans = found_labels
3152                         .into_iter()
3153                         .filter_map(|label| find_label_span(label))
3154                         .collect::<Vec<Span>>();
3155                     // If there were labels but we couldn't find a span, combine the warnings and use the template span
3156                     let target_spans: MultiSpan =
3157                         if spans.len() > 0 { spans.into() } else { (*template_span).into() };
3158
3159                     cx.lookup_with_diagnostics(
3160                             NAMED_ASM_LABELS,
3161                             Some(target_spans),
3162                             |diag| {
3163                                 diag.build(fluent::lint::builtin_asm_labels).emit();
3164                             },
3165                             BuiltinLintDiagnostics::NamedAsmLabel(
3166                                 "only local labels of the form `<number>:` should be used in inline asm"
3167                                     .to_string(),
3168                             ),
3169                         );
3170                 }
3171             }
3172         }
3173     }
3174 }
3175
3176 declare_lint! {
3177     /// The `special_module_name` lint detects module
3178     /// declarations for files that have a special meaning.
3179     ///
3180     /// ### Example
3181     ///
3182     /// ```rust,compile_fail
3183     /// mod lib;
3184     ///
3185     /// fn main() {
3186     ///     lib::run();
3187     /// }
3188     /// ```
3189     ///
3190     /// {{produces}}
3191     ///
3192     /// ### Explanation
3193     ///
3194     /// Cargo recognizes `lib.rs` and `main.rs` as the root of a
3195     /// library or binary crate, so declaring them as modules
3196     /// will lead to miscompilation of the crate unless configured
3197     /// explicitly.
3198     ///
3199     /// To access a library from a binary target within the same crate,
3200     /// use `your_crate_name::` as the path path instead of `lib::`:
3201     ///
3202     /// ```rust,compile_fail
3203     /// // bar/src/lib.rs
3204     /// fn run() {
3205     ///     // ...
3206     /// }
3207     ///
3208     /// // bar/src/main.rs
3209     /// fn main() {
3210     ///     bar::run();
3211     /// }
3212     /// ```
3213     ///
3214     /// Binary targets cannot be used as libraries and so declaring
3215     /// one as a module is not allowed.
3216     pub SPECIAL_MODULE_NAME,
3217     Warn,
3218     "module declarations for files with a special meaning",
3219 }
3220
3221 declare_lint_pass!(SpecialModuleName => [SPECIAL_MODULE_NAME]);
3222
3223 impl EarlyLintPass for SpecialModuleName {
3224     fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
3225         for item in &krate.items {
3226             if let ast::ItemKind::Mod(
3227                 _,
3228                 ast::ModKind::Unloaded | ast::ModKind::Loaded(_, ast::Inline::No, _),
3229             ) = item.kind
3230             {
3231                 if item.attrs.iter().any(|a| a.has_name(sym::path)) {
3232                     continue;
3233                 }
3234
3235                 match item.ident.name.as_str() {
3236                     "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
3237                         lint.build("found module declaration for lib.rs")
3238                             .note("lib.rs is the root of this crate's library target")
3239                             .help("to refer to it from other targets, use the library's name as the path")
3240                             .emit()
3241                     }),
3242                     "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
3243                         lint.build("found module declaration for main.rs")
3244                             .note("a binary crate cannot be used as library")
3245                             .emit()
3246                     }),
3247                     _ => continue
3248                 }
3249             }
3250         }
3251     }
3252 }