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