]> git.lizzy.rs Git - rust.git/blob - src/librustc/lint/builtin.rs
Auto merge of #67596 - Mark-Simulacrum:tidy-silence-rustfmt, r=Centril
[rust.git] / src / librustc / lint / builtin.rs
1 //! Some lints that are built in to the compiler.
2 //!
3 //! These are the built-in lints that are emitted direct in the main
4 //! compiler code, rather than using their own custom pass. Those
5 //! lints are all available in `rustc_lint::builtin`.
6
7 use crate::lint::{FutureIncompatibleInfo, LateLintPass, LintArray, LintPass};
8 use crate::middle::stability;
9 use crate::session::Session;
10 use errors::{pluralize, Applicability, DiagnosticBuilder};
11 use rustc_session::declare_lint;
12 use syntax::ast;
13 use syntax::early_buffered_lints::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE};
14 use syntax::edition::Edition;
15 use syntax::source_map::Span;
16 use syntax::symbol::Symbol;
17
18 declare_lint! {
19     pub EXCEEDING_BITSHIFTS,
20     Deny,
21     "shift exceeds the type's number of bits"
22 }
23
24 declare_lint! {
25     pub CONST_ERR,
26     Deny,
27     "constant evaluation detected erroneous expression",
28     report_in_external_macro
29 }
30
31 declare_lint! {
32     pub UNUSED_IMPORTS,
33     Warn,
34     "imports that are never used"
35 }
36
37 declare_lint! {
38     pub UNUSED_EXTERN_CRATES,
39     Allow,
40     "extern crates that are never used"
41 }
42
43 declare_lint! {
44     pub UNUSED_QUALIFICATIONS,
45     Allow,
46     "detects unnecessarily qualified names"
47 }
48
49 declare_lint! {
50     pub UNKNOWN_LINTS,
51     Warn,
52     "unrecognized lint attribute"
53 }
54
55 declare_lint! {
56     pub UNUSED_VARIABLES,
57     Warn,
58     "detect variables which are not used in any way"
59 }
60
61 declare_lint! {
62     pub UNUSED_ASSIGNMENTS,
63     Warn,
64     "detect assignments that will never be read"
65 }
66
67 declare_lint! {
68     pub DEAD_CODE,
69     Warn,
70     "detect unused, unexported items"
71 }
72
73 declare_lint! {
74     pub UNUSED_ATTRIBUTES,
75     Warn,
76     "detects attributes that were not used by the compiler"
77 }
78
79 declare_lint! {
80     pub UNREACHABLE_CODE,
81     Warn,
82     "detects unreachable code paths",
83     report_in_external_macro
84 }
85
86 declare_lint! {
87     pub UNREACHABLE_PATTERNS,
88     Warn,
89     "detects unreachable patterns"
90 }
91
92 declare_lint! {
93     pub OVERLAPPING_PATTERNS,
94     Warn,
95     "detects overlapping patterns"
96 }
97
98 declare_lint! {
99     pub UNUSED_MACROS,
100     Warn,
101     "detects macros that were not used"
102 }
103
104 declare_lint! {
105     pub WARNINGS,
106     Warn,
107     "mass-change the level for lints which produce warnings"
108 }
109
110 declare_lint! {
111     pub UNUSED_FEATURES,
112     Warn,
113     "unused features found in crate-level `#[feature]` directives"
114 }
115
116 declare_lint! {
117     pub STABLE_FEATURES,
118     Warn,
119     "stable features found in `#[feature]` directive"
120 }
121
122 declare_lint! {
123     pub UNKNOWN_CRATE_TYPES,
124     Deny,
125     "unknown crate type found in `#[crate_type]` directive"
126 }
127
128 declare_lint! {
129     pub TRIVIAL_CASTS,
130     Allow,
131     "detects trivial casts which could be removed"
132 }
133
134 declare_lint! {
135     pub TRIVIAL_NUMERIC_CASTS,
136     Allow,
137     "detects trivial casts of numeric types which could be removed"
138 }
139
140 declare_lint! {
141     pub PRIVATE_IN_PUBLIC,
142     Warn,
143     "detect private items in public interfaces not caught by the old implementation",
144     @future_incompatible = FutureIncompatibleInfo {
145         reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
146         edition: None,
147     };
148 }
149
150 declare_lint! {
151     pub EXPORTED_PRIVATE_DEPENDENCIES,
152     Warn,
153     "public interface leaks type from a private dependency"
154 }
155
156 declare_lint! {
157     pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
158     Deny,
159     "detect public re-exports of private extern crates",
160     @future_incompatible = FutureIncompatibleInfo {
161         reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
162         edition: None,
163     };
164 }
165
166 declare_lint! {
167     pub INVALID_TYPE_PARAM_DEFAULT,
168     Deny,
169     "type parameter default erroneously allowed in invalid location",
170     @future_incompatible = FutureIncompatibleInfo {
171         reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
172         edition: None,
173     };
174 }
175
176 declare_lint! {
177     pub RENAMED_AND_REMOVED_LINTS,
178     Warn,
179     "lints that have been renamed or removed"
180 }
181
182 declare_lint! {
183     pub SAFE_PACKED_BORROWS,
184     Warn,
185     "safe borrows of fields of packed structs were was erroneously allowed",
186     @future_incompatible = FutureIncompatibleInfo {
187         reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
188         edition: None,
189     };
190 }
191
192 declare_lint! {
193     pub PATTERNS_IN_FNS_WITHOUT_BODY,
194     Deny,
195     "patterns in functions without body were erroneously allowed",
196     @future_incompatible = FutureIncompatibleInfo {
197         reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
198         edition: None,
199     };
200 }
201
202 declare_lint! {
203     pub MISSING_FRAGMENT_SPECIFIER,
204     Deny,
205     "detects missing fragment specifiers in unused `macro_rules!` patterns",
206     @future_incompatible = FutureIncompatibleInfo {
207         reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
208         edition: None,
209     };
210 }
211
212 declare_lint! {
213     pub LATE_BOUND_LIFETIME_ARGUMENTS,
214     Warn,
215     "detects generic lifetime arguments in path segments with late bound lifetime parameters",
216     @future_incompatible = FutureIncompatibleInfo {
217         reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
218         edition: None,
219     };
220 }
221
222 declare_lint! {
223     pub ORDER_DEPENDENT_TRAIT_OBJECTS,
224     Deny,
225     "trait-object types were treated as different depending on marker-trait order",
226     @future_incompatible = FutureIncompatibleInfo {
227         reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
228         edition: None,
229     };
230 }
231
232 declare_lint! {
233     pub DEPRECATED,
234     Warn,
235     "detects use of deprecated items",
236     report_in_external_macro
237 }
238
239 declare_lint! {
240     pub UNUSED_UNSAFE,
241     Warn,
242     "unnecessary use of an `unsafe` block"
243 }
244
245 declare_lint! {
246     pub UNUSED_MUT,
247     Warn,
248     "detect mut variables which don't need to be mutable"
249 }
250
251 declare_lint! {
252     pub UNCONDITIONAL_RECURSION,
253     Warn,
254     "functions that cannot return without calling themselves"
255 }
256
257 declare_lint! {
258     pub SINGLE_USE_LIFETIMES,
259     Allow,
260     "detects lifetime parameters that are only used once"
261 }
262
263 declare_lint! {
264     pub UNUSED_LIFETIMES,
265     Allow,
266     "detects lifetime parameters that are never used"
267 }
268
269 declare_lint! {
270     pub TYVAR_BEHIND_RAW_POINTER,
271     Warn,
272     "raw pointer to an inference variable",
273     @future_incompatible = FutureIncompatibleInfo {
274         reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
275         edition: Some(Edition::Edition2018),
276     };
277 }
278
279 declare_lint! {
280     pub ELIDED_LIFETIMES_IN_PATHS,
281     Allow,
282     "hidden lifetime parameters in types are deprecated"
283 }
284
285 declare_lint! {
286     pub BARE_TRAIT_OBJECTS,
287     Warn,
288     "suggest using `dyn Trait` for trait objects"
289 }
290
291 declare_lint! {
292     pub ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
293     Allow,
294     "fully qualified paths that start with a module name \
295      instead of `crate`, `self`, or an extern crate name",
296      @future_incompatible = FutureIncompatibleInfo {
297         reference: "issue #53130 <https://github.com/rust-lang/rust/issues/53130>",
298         edition: Some(Edition::Edition2018),
299      };
300 }
301
302 declare_lint! {
303     pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
304     Warn,
305     "floating-point literals cannot be used in patterns",
306     @future_incompatible = FutureIncompatibleInfo {
307         reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
308         edition: None,
309     };
310 }
311
312 declare_lint! {
313     pub UNSTABLE_NAME_COLLISIONS,
314     Warn,
315     "detects name collision with an existing but unstable method",
316     @future_incompatible = FutureIncompatibleInfo {
317         reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
318         edition: None,
319         // Note: this item represents future incompatibility of all unstable functions in the
320         //       standard library, and thus should never be removed or changed to an error.
321     };
322 }
323
324 declare_lint! {
325     pub IRREFUTABLE_LET_PATTERNS,
326     Warn,
327     "detects irrefutable patterns in if-let and while-let statements"
328 }
329
330 declare_lint! {
331     pub UNUSED_LABELS,
332     Warn,
333     "detects labels that are never used"
334 }
335
336 declare_lint! {
337     pub INTRA_DOC_LINK_RESOLUTION_FAILURE,
338     Warn,
339     "failures in resolving intra-doc link targets"
340 }
341
342 declare_lint! {
343     pub MISSING_DOC_CODE_EXAMPLES,
344     Allow,
345     "detects publicly-exported items without code samples in their documentation"
346 }
347
348 declare_lint! {
349     pub PRIVATE_DOC_TESTS,
350     Allow,
351     "detects code samples in docs of private items not documented by rustdoc"
352 }
353
354 declare_lint! {
355     pub WHERE_CLAUSES_OBJECT_SAFETY,
356     Warn,
357     "checks the object safety of where clauses",
358     @future_incompatible = FutureIncompatibleInfo {
359         reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
360         edition: None,
361     };
362 }
363
364 declare_lint! {
365     pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
366     Warn,
367     "detects proc macro derives using inaccessible names from parent modules",
368     @future_incompatible = FutureIncompatibleInfo {
369         reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
370         edition: None,
371     };
372 }
373
374 declare_lint! {
375     pub MACRO_USE_EXTERN_CRATE,
376     Allow,
377     "the `#[macro_use]` attribute is now deprecated in favor of using macros \
378      via the module system"
379 }
380
381 declare_lint! {
382     pub MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
383     Deny,
384     "macro-expanded `macro_export` macros from the current crate \
385      cannot be referred to by absolute paths",
386     @future_incompatible = FutureIncompatibleInfo {
387         reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
388         edition: None,
389     };
390 }
391
392 declare_lint! {
393     pub EXPLICIT_OUTLIVES_REQUIREMENTS,
394     Allow,
395     "outlives requirements can be inferred"
396 }
397
398 declare_lint! {
399     pub INDIRECT_STRUCTURAL_MATCH,
400     // defaulting to allow until rust-lang/rust#62614 is fixed.
401     Allow,
402     "pattern with const indirectly referencing non-`#[structural_match]` type",
403     @future_incompatible = FutureIncompatibleInfo {
404         reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
405         edition: None,
406     };
407 }
408
409 declare_lint! {
410     pub DEPRECATED_IN_FUTURE,
411     Allow,
412     "detects use of items that will be deprecated in a future version",
413     report_in_external_macro
414 }
415
416 declare_lint! {
417     pub AMBIGUOUS_ASSOCIATED_ITEMS,
418     Deny,
419     "ambiguous associated items",
420     @future_incompatible = FutureIncompatibleInfo {
421         reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
422         edition: None,
423     };
424 }
425
426 declare_lint! {
427     pub MUTABLE_BORROW_RESERVATION_CONFLICT,
428     Warn,
429     "reservation of a two-phased borrow conflicts with other shared borrows",
430     @future_incompatible = FutureIncompatibleInfo {
431         reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
432         edition: None,
433     };
434 }
435
436 declare_lint! {
437     pub SOFT_UNSTABLE,
438     Deny,
439     "a feature gate that doesn't break dependent crates",
440     @future_incompatible = FutureIncompatibleInfo {
441         reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
442         edition: None,
443     };
444 }
445
446 declare_lint_pass! {
447     /// Does nothing as a lint pass, but registers some `Lint`s
448     /// that are used by other parts of the compiler.
449     HardwiredLints => [
450         ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
451         EXCEEDING_BITSHIFTS,
452         UNUSED_IMPORTS,
453         UNUSED_EXTERN_CRATES,
454         UNUSED_QUALIFICATIONS,
455         UNKNOWN_LINTS,
456         UNUSED_VARIABLES,
457         UNUSED_ASSIGNMENTS,
458         DEAD_CODE,
459         UNREACHABLE_CODE,
460         UNREACHABLE_PATTERNS,
461         OVERLAPPING_PATTERNS,
462         UNUSED_MACROS,
463         WARNINGS,
464         UNUSED_FEATURES,
465         STABLE_FEATURES,
466         UNKNOWN_CRATE_TYPES,
467         TRIVIAL_CASTS,
468         TRIVIAL_NUMERIC_CASTS,
469         PRIVATE_IN_PUBLIC,
470         EXPORTED_PRIVATE_DEPENDENCIES,
471         PUB_USE_OF_PRIVATE_EXTERN_CRATE,
472         INVALID_TYPE_PARAM_DEFAULT,
473         CONST_ERR,
474         RENAMED_AND_REMOVED_LINTS,
475         SAFE_PACKED_BORROWS,
476         PATTERNS_IN_FNS_WITHOUT_BODY,
477         MISSING_FRAGMENT_SPECIFIER,
478         LATE_BOUND_LIFETIME_ARGUMENTS,
479         ORDER_DEPENDENT_TRAIT_OBJECTS,
480         DEPRECATED,
481         UNUSED_UNSAFE,
482         UNUSED_MUT,
483         UNCONDITIONAL_RECURSION,
484         SINGLE_USE_LIFETIMES,
485         UNUSED_LIFETIMES,
486         UNUSED_LABELS,
487         TYVAR_BEHIND_RAW_POINTER,
488         ELIDED_LIFETIMES_IN_PATHS,
489         BARE_TRAIT_OBJECTS,
490         ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
491         UNSTABLE_NAME_COLLISIONS,
492         IRREFUTABLE_LET_PATTERNS,
493         INTRA_DOC_LINK_RESOLUTION_FAILURE,
494         MISSING_DOC_CODE_EXAMPLES,
495         PRIVATE_DOC_TESTS,
496         WHERE_CLAUSES_OBJECT_SAFETY,
497         PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
498         MACRO_USE_EXTERN_CRATE,
499         MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
500         ILL_FORMED_ATTRIBUTE_INPUT,
501         META_VARIABLE_MISUSE,
502         DEPRECATED_IN_FUTURE,
503         AMBIGUOUS_ASSOCIATED_ITEMS,
504         MUTABLE_BORROW_RESERVATION_CONFLICT,
505         INDIRECT_STRUCTURAL_MATCH,
506         SOFT_UNSTABLE,
507     ]
508 }
509
510 // this could be a closure, but then implementing derive traits
511 // becomes hacky (and it gets allocated)
512 #[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
513 pub enum BuiltinLintDiagnostics {
514     Normal,
515     BareTraitObject(Span, /* is_global */ bool),
516     AbsPathWithModule(Span),
517     ProcMacroDeriveResolutionFallback(Span),
518     MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
519     ElidedLifetimesInPaths(usize, Span, bool, Span, String),
520     UnknownCrateTypes(Span, String, String),
521     UnusedImports(String, Vec<(Span, String)>),
522     RedundantImport(Vec<(Span, bool)>, ast::Ident),
523     DeprecatedMacro(Option<Symbol>, Span),
524 }
525
526 pub(crate) fn add_elided_lifetime_in_path_suggestion(
527     sess: &Session,
528     db: &mut DiagnosticBuilder<'_>,
529     n: usize,
530     path_span: Span,
531     incl_angl_brckt: bool,
532     insertion_span: Span,
533     anon_lts: String,
534 ) {
535     let (replace_span, suggestion) = if incl_angl_brckt {
536         (insertion_span, anon_lts)
537     } else {
538         // When possible, prefer a suggestion that replaces the whole
539         // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
540         // at a point (which makes for an ugly/confusing label)
541         if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
542             // But our spans can get out of whack due to macros; if the place we think
543             // we want to insert `'_` isn't even within the path expression's span, we
544             // should bail out of making any suggestion rather than panicking on a
545             // subtract-with-overflow or string-slice-out-out-bounds (!)
546             // FIXME: can we do better?
547             if insertion_span.lo().0 < path_span.lo().0 {
548                 return;
549             }
550             let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
551             if insertion_index > snippet.len() {
552                 return;
553             }
554             let (before, after) = snippet.split_at(insertion_index);
555             (path_span, format!("{}{}{}", before, anon_lts, after))
556         } else {
557             (insertion_span, anon_lts)
558         }
559     };
560     db.span_suggestion(
561         replace_span,
562         &format!("indicate the anonymous lifetime{}", pluralize!(n)),
563         suggestion,
564         Applicability::MachineApplicable,
565     );
566 }
567
568 impl BuiltinLintDiagnostics {
569     pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
570         match self {
571             BuiltinLintDiagnostics::Normal => (),
572             BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
573                 let (sugg, app) = match sess.source_map().span_to_snippet(span) {
574                     Ok(ref s) if is_global => {
575                         (format!("dyn ({})", s), Applicability::MachineApplicable)
576                     }
577                     Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
578                     Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
579                 };
580                 db.span_suggestion(span, "use `dyn`", sugg, app);
581             }
582             BuiltinLintDiagnostics::AbsPathWithModule(span) => {
583                 let (sugg, app) = match sess.source_map().span_to_snippet(span) {
584                     Ok(ref s) => {
585                         // FIXME(Manishearth) ideally the emitting code
586                         // can tell us whether or not this is global
587                         let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
588
589                         (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
590                     }
591                     Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
592                 };
593                 db.span_suggestion(span, "use `crate`", sugg, app);
594             }
595             BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
596                 db.span_label(
597                     span,
598                     "names from parent modules are not \
599                                      accessible without an explicit import",
600                 );
601             }
602             BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
603                 db.span_note(span_def, "the macro is defined here");
604             }
605             BuiltinLintDiagnostics::ElidedLifetimesInPaths(
606                 n,
607                 path_span,
608                 incl_angl_brckt,
609                 insertion_span,
610                 anon_lts,
611             ) => {
612                 add_elided_lifetime_in_path_suggestion(
613                     sess,
614                     db,
615                     n,
616                     path_span,
617                     incl_angl_brckt,
618                     insertion_span,
619                     anon_lts,
620                 );
621             }
622             BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
623                 db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
624             }
625             BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
626                 if !replaces.is_empty() {
627                     db.tool_only_multipart_suggestion(
628                         &message,
629                         replaces,
630                         Applicability::MachineApplicable,
631                     );
632                 }
633             }
634             BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
635                 for (span, is_imported) in spans {
636                     let introduced = if is_imported { "imported" } else { "defined" };
637                     db.span_label(
638                         span,
639                         format!("the item `{}` is already {} here", ident, introduced),
640                     );
641                 }
642             }
643             BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
644                 stability::deprecation_suggestion(db, suggestion, span)
645             }
646         }
647     }
648 }
649
650 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}