rust/src/librustc/lint/builtin.rs

595 lines
17 KiB
Rust
Raw Normal View History

//! Some lints that are built in to the compiler.
//!
//! These are the built-in lints that are emitted direct in the main
//! compiler code, rather than using their own custom pass. Those
//! lints are all available in `rustc_lint::builtin`.
2019-02-05 11:20:45 -06:00
use crate::lint::{LintPass, LateLintPass, LintArray};
use crate::session::Session;
2019-02-08 20:24:02 -06:00
use errors::{Applicability, DiagnosticBuilder};
2018-04-21 09:18:38 -05:00
use syntax::ast;
2018-08-18 05:14:03 -05:00
use syntax::source_map::Span;
declare_lint! {
pub EXCEEDING_BITSHIFTS,
Deny,
"shift exceeds the type's number of bits"
}
declare_lint! {
pub CONST_ERR,
Deny,
"constant evaluation detected erroneous expression"
}
declare_lint! {
pub UNUSED_IMPORTS,
Warn,
"imports that are never used"
}
declare_lint! {
pub UNUSED_EXTERN_CRATES,
Allow,
"extern crates that are never used"
}
2014-09-11 12:14:43 -05:00
declare_lint! {
pub UNUSED_QUALIFICATIONS,
Allow,
"detects unnecessarily qualified names"
}
declare_lint! {
pub UNKNOWN_LINTS,
Warn,
"unrecognized lint attribute"
}
declare_lint! {
pub UNUSED_VARIABLES,
Warn,
"detect variables which are not used in any way"
}
declare_lint! {
pub UNUSED_ASSIGNMENTS,
Warn,
"detect assignments that will never be read"
}
declare_lint! {
pub DEAD_CODE,
Warn,
"detect unused, unexported items"
}
declare_lint! {
pub UNREACHABLE_CODE,
Warn,
"detects unreachable code paths",
2018-07-21 05:36:18 -05:00
report_in_external_macro: true
}
declare_lint! {
pub UNREACHABLE_PATTERNS,
Warn,
"detects unreachable patterns"
}
2017-05-11 03:26:07 -05:00
declare_lint! {
pub UNUSED_MACROS,
Warn,
"detects macros that were not used"
}
declare_lint! {
pub WARNINGS,
Warn,
"mass-change the level for lints which produce warnings"
}
declare_lint! {
2015-01-16 12:25:16 -06:00
pub UNUSED_FEATURES,
Warn,
"unused features found in crate-level #[feature] directives"
}
declare_lint! {
pub STABLE_FEATURES,
Warn,
"stable features found in #[feature] directive"
}
declare_lint! {
pub UNKNOWN_CRATE_TYPES,
Deny,
"unknown crate type found in #[crate_type] directive"
}
Add trivial cast lints. This permits all coercions to be performed in casts, but adds lints to warn in those cases. Part of this patch moves cast checking to a later stage of type checking. We acquire obligations to check casts as part of type checking where we previously checked them. Once we have type checked a function or module, then we check any cast obligations which have been acquired. That means we have more type information available to check casts (this was crucial to making coercions work properly in place of some casts), but it means that casts cannot feed input into type inference. [breaking change] * Adds two new lints for trivial casts and trivial numeric casts, these are warn by default, but can cause errors if you build with warnings as errors. Previously, trivial numeric casts and casts to trait objects were allowed. * The unused casts lint has gone. * Interactions between casting and type inference have changed in subtle ways. Two ways this might manifest are: - You may need to 'direct' casts more with extra type information, for example, in some cases where `foo as _ as T` succeeded, you may now need to specify the type for `_` - Casts do not influence inference of integer types. E.g., the following used to type check: ``` let x = 42; let y = &x as *const u32; ``` Because the cast would inform inference that `x` must have type `u32`. This no longer applies and the compiler will fallback to `i32` for `x` and thus there will be a type error in the cast. The solution is to add more type information: ``` let x: u32 = 42; let y = &x as *const u32; ```
2015-03-19 23:15:27 -05:00
declare_lint! {
2015-03-23 17:23:34 -05:00
pub TRIVIAL_CASTS,
Allow,
Add trivial cast lints. This permits all coercions to be performed in casts, but adds lints to warn in those cases. Part of this patch moves cast checking to a later stage of type checking. We acquire obligations to check casts as part of type checking where we previously checked them. Once we have type checked a function or module, then we check any cast obligations which have been acquired. That means we have more type information available to check casts (this was crucial to making coercions work properly in place of some casts), but it means that casts cannot feed input into type inference. [breaking change] * Adds two new lints for trivial casts and trivial numeric casts, these are warn by default, but can cause errors if you build with warnings as errors. Previously, trivial numeric casts and casts to trait objects were allowed. * The unused casts lint has gone. * Interactions between casting and type inference have changed in subtle ways. Two ways this might manifest are: - You may need to 'direct' casts more with extra type information, for example, in some cases where `foo as _ as T` succeeded, you may now need to specify the type for `_` - Casts do not influence inference of integer types. E.g., the following used to type check: ``` let x = 42; let y = &x as *const u32; ``` Because the cast would inform inference that `x` must have type `u32`. This no longer applies and the compiler will fallback to `i32` for `x` and thus there will be a type error in the cast. The solution is to add more type information: ``` let x: u32 = 42; let y = &x as *const u32; ```
2015-03-19 23:15:27 -05:00
"detects trivial casts which could be removed"
}
declare_lint! {
2015-03-23 17:23:34 -05:00
pub TRIVIAL_NUMERIC_CASTS,
Allow,
Add trivial cast lints. This permits all coercions to be performed in casts, but adds lints to warn in those cases. Part of this patch moves cast checking to a later stage of type checking. We acquire obligations to check casts as part of type checking where we previously checked them. Once we have type checked a function or module, then we check any cast obligations which have been acquired. That means we have more type information available to check casts (this was crucial to making coercions work properly in place of some casts), but it means that casts cannot feed input into type inference. [breaking change] * Adds two new lints for trivial casts and trivial numeric casts, these are warn by default, but can cause errors if you build with warnings as errors. Previously, trivial numeric casts and casts to trait objects were allowed. * The unused casts lint has gone. * Interactions between casting and type inference have changed in subtle ways. Two ways this might manifest are: - You may need to 'direct' casts more with extra type information, for example, in some cases where `foo as _ as T` succeeded, you may now need to specify the type for `_` - Casts do not influence inference of integer types. E.g., the following used to type check: ``` let x = 42; let y = &x as *const u32; ``` Because the cast would inform inference that `x` must have type `u32`. This no longer applies and the compiler will fallback to `i32` for `x` and thus there will be a type error in the cast. The solution is to add more type information: ``` let x: u32 = 42; let y = &x as *const u32; ```
2015-03-19 23:15:27 -05:00
"detects trivial casts of numeric types which could be removed"
}
2015-11-26 11:56:20 -06:00
declare_lint! {
pub PRIVATE_IN_PUBLIC,
Warn,
2015-11-26 11:56:20 -06:00
"detect private items in public interfaces not caught by the old implementation"
}
2018-12-15 06:00:15 -06:00
declare_lint! {
pub EXPORTED_PRIVATE_DEPENDENCIES,
2018-12-15 06:00:15 -06:00
Warn,
"public interface leaks type from a private dependency"
}
declare_lint! {
pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
Deny,
"detect public re-exports of private extern crates"
}
declare_lint! {
pub INVALID_TYPE_PARAM_DEFAULT,
Deny,
"type parameter default erroneously allowed in invalid location"
}
declare_lint! {
pub RENAMED_AND_REMOVED_LINTS,
Warn,
"lints that have been renamed or removed"
}
declare_lint! {
pub SAFE_EXTERN_STATICS,
Deny,
"safe access to extern statics was erroneously allowed"
}
declare_lint! {
pub SAFE_PACKED_BORROWS,
Warn,
"safe borrows of fields of packed structs were was erroneously allowed"
}
declare_lint! {
pub PATTERNS_IN_FNS_WITHOUT_BODY,
Warn,
"patterns in functions without body were erroneously allowed"
}
2016-11-14 03:31:03 -06:00
declare_lint! {
pub LEGACY_DIRECTORY_OWNERSHIP,
Deny,
"non-inline, non-`#[path]` modules (e.g., `mod foo;`) were erroneously allowed in some files \
2016-11-14 03:31:03 -06:00
not named `mod.rs`"
}
declare_lint! {
pub LEGACY_CONSTRUCTOR_VISIBILITY,
Deny,
"detects use of struct constructors that would be invisible with new visibility rules"
}
2017-02-25 21:25:22 -06:00
declare_lint! {
pub MISSING_FRAGMENT_SPECIFIER,
Deny,
2017-02-25 21:25:22 -06:00
"detects missing fragment specifiers in unused `macro_rules!` patterns"
}
2017-05-26 08:20:53 -05:00
declare_lint! {
pub PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
Deny,
2017-05-26 08:20:53 -05:00
"detects parenthesized generic parameters in type and module names"
}
declare_lint! {
pub LATE_BOUND_LIFETIME_ARGUMENTS,
Warn,
"detects generic lifetime arguments in path segments with late bound lifetime parameters"
}
declare_lint! {
pub INCOHERENT_FUNDAMENTAL_IMPLS,
Deny,
"potentially-conflicting impls were erroneously allowed"
}
declare_lint! {
pub ORDER_DEPENDENT_TRAIT_OBJECTS,
Deny,
2018-12-14 11:28:30 -06:00
"trait-object types were treated as different depending on marker-trait order"
}
declare_lint! {
pub DEPRECATED,
Warn,
"detects use of deprecated items",
2018-07-21 05:36:18 -05:00
report_in_external_macro: true
}
declare_lint! {
pub UNUSED_UNSAFE,
Warn,
"unnecessary use of an `unsafe` block"
}
declare_lint! {
pub UNUSED_MUT,
Warn,
"detect mut variables which don't need to be mutable"
}
declare_lint! {
pub UNCONDITIONAL_RECURSION,
Warn,
"functions that cannot return without calling themselves"
}
declare_lint! {
2018-05-18 17:13:53 -05:00
pub SINGLE_USE_LIFETIMES,
Allow,
"detects lifetime parameters that are only used once"
}
declare_lint! {
2018-05-18 17:13:53 -05:00
pub UNUSED_LIFETIMES,
Allow,
"detects lifetime parameters that are never used"
}
declare_lint! {
pub TYVAR_BEHIND_RAW_POINTER,
Warn,
"raw pointer to an inference variable"
}
2018-02-01 14:40:10 -06:00
declare_lint! {
2018-05-18 17:13:53 -05:00
pub ELIDED_LIFETIMES_IN_PATHS,
2018-02-01 14:40:10 -06:00
Allow,
"hidden lifetime parameters in types are deprecated"
2018-02-01 14:40:10 -06:00
}
2018-02-23 00:14:08 -06:00
declare_lint! {
2018-05-18 17:13:53 -05:00
pub BARE_TRAIT_OBJECTS,
2018-03-06 19:32:29 -06:00
Allow,
"suggest using `dyn Trait` for trait objects"
2018-02-23 00:14:08 -06:00
}
declare_lint! {
2018-05-18 17:13:53 -05:00
pub ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
Allow,
"fully qualified paths that start with a module name \
instead of `crate`, `self`, or an extern crate name"
}
declare_lint! {
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
Warn,
"floating-point literals cannot be used in patterns"
}
declare_lint! {
2018-05-18 17:13:53 -05:00
pub UNSTABLE_NAME_COLLISIONS,
Warn,
"detects name collision with an existing but unstable method"
}
declare_lint! {
pub IRREFUTABLE_LET_PATTERNS,
Warn,
"detects irrefutable patterns in if-let and while-let statements"
}
declare_lint! {
pub UNUSED_LABELS,
Allow,
"detects labels that are never used"
}
2018-04-21 09:18:38 -05:00
declare_lint! {
pub DUPLICATE_MACRO_EXPORTS,
Deny,
"detects duplicate macro exports"
}
declare_lint! {
2018-06-13 14:17:15 -05:00
pub INTRA_DOC_LINK_RESOLUTION_FAILURE,
Warn,
2018-12-10 14:59:44 -06:00
"failures in resolving intra-doc link targets"
}
2018-09-17 17:25:50 -05:00
declare_lint! {
pub MISSING_DOC_CODE_EXAMPLES,
2018-09-17 17:25:50 -05:00
Allow,
2018-12-10 14:59:44 -06:00
"detects publicly-exported items without code samples in their documentation"
2018-09-17 17:25:50 -05:00
}
2018-10-25 17:55:12 -05:00
declare_lint! {
pub PRIVATE_DOC_TESTS,
Allow,
2018-12-10 14:59:44 -06:00
"detects code samples in docs of private items not documented by rustdoc"
2018-10-25 17:55:12 -05:00
}
declare_lint! {
pub WHERE_CLAUSES_OBJECT_SAFETY,
Warn,
"checks the object safety of where clauses"
}
declare_lint! {
pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
Warn,
"detects proc macro derives using inaccessible names from parent modules"
}
declare_lint! {
pub MACRO_USE_EXTERN_CRATE,
Allow,
"the `#[macro_use]` attribute is now deprecated in favor of using macros \
via the module system"
}
declare_lint! {
pub MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
Deny,
"macro-expanded `macro_export` macros from the current crate \
cannot be referred to by absolute paths"
}
in which inferable outlives-requirements are linted RFC 2093 (tracking issue #44493) lets us leave off commonsensically inferable `T: 'a` outlives requirements. (A separate feature-gate was split off for the case of 'static lifetimes, for which questions still remain.) Detecting these was requested as an idioms-2018 lint. It turns out that issuing a correct, autofixable suggestion here is somewhat subtle in the presence of other bounds and generic parameters. Basically, we want to handle these three cases: • One outlives-bound. We want to drop the bound altogether, including the colon— MyStruct<'a, T: 'a> ^^^^ help: remove this bound • An outlives bound first, followed by a trait bound. We want to delete the outlives bound and the following plus sign (and hopefully get the whitespace right, too)— MyStruct<'a, T: 'a + MyTrait> ^^^^^ help: remove this bound • An outlives bound after a trait bound. We want to delete the outlives lifetime and the preceding plus sign— MyStruct<'a, T: MyTrait + 'a> ^^^^^ help: remove this bound This gets (slightly) even more complicated in the case of where clauses, where we want to drop the where clause altogether if there's just the one bound. Hopefully the comments are enough to explain what's going on! A script (in Python, sorry) was used to generate the hopefully-sufficiently-exhaustive UI test input. Some of these are split off into a different file because rust-lang-nursery/rustfix#141 (and, causally upstream of that, #53934) prevents them from being `run-rustfix`-tested. We also make sure to include a UI test of a case (copied from RFC 2093) where the outlives-bound can't be inferred. Special thanks to Niko Matsakis for pointing out the `inferred_outlives_of` query, rather than blindly stripping outlives requirements as if we weren't a production compiler and didn't care. This concerns #52042.
2018-08-26 14:22:04 -05:00
declare_lint! {
pub EXPLICIT_OUTLIVES_REQUIREMENTS,
Allow,
"outlives requirements can be inferred"
}
declare_lint! {
pub DUPLICATE_MATCHER_BINDING_NAME,
Deny,
"duplicate macro matcher binding name"
}
/// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
pub mod parser {
declare_lint! {
pub QUESTION_MARK_MACRO_SEP,
2018-07-13 23:48:15 -05:00
Allow,
"detects the use of `?` as a macro separator"
}
declare_lint! {
pub ILL_FORMED_ATTRIBUTE_INPUT,
Warn,
"ill-formed attribute inputs that were previously accepted and used in practice"
}
}
declare_lint! {
pub DEPRECATED_IN_FUTURE,
Allow,
"detects use of items that will be deprecated in a future version",
report_in_external_macro: true
}
declare_lint! {
pub AMBIGUOUS_ASSOCIATED_ITEMS,
Warn,
"ambiguous associated items"
}
declare_lint! {
pub NESTED_IMPL_TRAIT,
Warn,
"nested occurrence of `impl Trait` type"
}
declare_lint! {
pub MUTABLE_BORROW_RESERVATION_CONFLICT,
Warn,
"reservation of a two-phased borrow conflicts with other shared borrows"
}
declare_lint_pass! {
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
HardwiredLints => [
ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
EXCEEDING_BITSHIFTS,
UNUSED_IMPORTS,
UNUSED_EXTERN_CRATES,
UNUSED_QUALIFICATIONS,
UNKNOWN_LINTS,
UNUSED_VARIABLES,
UNUSED_ASSIGNMENTS,
DEAD_CODE,
UNREACHABLE_CODE,
UNREACHABLE_PATTERNS,
UNUSED_MACROS,
WARNINGS,
UNUSED_FEATURES,
STABLE_FEATURES,
UNKNOWN_CRATE_TYPES,
TRIVIAL_CASTS,
TRIVIAL_NUMERIC_CASTS,
PRIVATE_IN_PUBLIC,
EXPORTED_PRIVATE_DEPENDENCIES,
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
INVALID_TYPE_PARAM_DEFAULT,
CONST_ERR,
RENAMED_AND_REMOVED_LINTS,
SAFE_EXTERN_STATICS,
SAFE_PACKED_BORROWS,
PATTERNS_IN_FNS_WITHOUT_BODY,
LEGACY_DIRECTORY_OWNERSHIP,
LEGACY_CONSTRUCTOR_VISIBILITY,
MISSING_FRAGMENT_SPECIFIER,
PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
LATE_BOUND_LIFETIME_ARGUMENTS,
INCOHERENT_FUNDAMENTAL_IMPLS,
ORDER_DEPENDENT_TRAIT_OBJECTS,
DEPRECATED,
UNUSED_UNSAFE,
UNUSED_MUT,
UNCONDITIONAL_RECURSION,
SINGLE_USE_LIFETIMES,
UNUSED_LIFETIMES,
UNUSED_LABELS,
TYVAR_BEHIND_RAW_POINTER,
ELIDED_LIFETIMES_IN_PATHS,
BARE_TRAIT_OBJECTS,
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
UNSTABLE_NAME_COLLISIONS,
IRREFUTABLE_LET_PATTERNS,
DUPLICATE_MACRO_EXPORTS,
INTRA_DOC_LINK_RESOLUTION_FAILURE,
MISSING_DOC_CODE_EXAMPLES,
PRIVATE_DOC_TESTS,
WHERE_CLAUSES_OBJECT_SAFETY,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
parser::QUESTION_MARK_MACRO_SEP,
parser::ILL_FORMED_ATTRIBUTE_INPUT,
DEPRECATED_IN_FUTURE,
AMBIGUOUS_ASSOCIATED_ITEMS,
NESTED_IMPL_TRAIT,
DUPLICATE_MATCHER_BINDING_NAME,
MUTABLE_BORROW_RESERVATION_CONFLICT,
]
}
// this could be a closure, but then implementing derive traits
// becomes hacky (and it gets allocated)
#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
pub enum BuiltinLintDiagnostics {
Normal,
2018-04-19 21:51:53 -05:00
BareTraitObject(Span, /* is_global */ bool),
AbsPathWithModule(Span),
2018-04-21 09:18:38 -05:00
DuplicatedMacroExports(ast::Ident, Span, Span),
ProcMacroDeriveResolutionFallback(Span),
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
ElidedLifetimesInPaths(usize, Span, bool, Span, String),
UnknownCrateTypes(Span, String, String),
UnusedImports(String, Vec<(Span, String)>),
NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span },
RedundantImport(Vec<(Span, bool)>, ast::Ident),
}
impl BuiltinLintDiagnostics {
pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder<'_>) {
match self {
BuiltinLintDiagnostics::Normal => (),
BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
2018-08-18 05:14:09 -05:00
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
2018-05-04 16:12:33 -05:00
Ok(ref s) if is_global => (format!("dyn ({})", s),
Applicability::MachineApplicable),
Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
2018-07-28 07:40:32 -05:00
Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders)
};
db.span_suggestion(span, "use `dyn`", sugg, app);
}
2018-04-19 21:51:53 -05:00
BuiltinLintDiagnostics::AbsPathWithModule(span) => {
2018-08-18 05:14:09 -05:00
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
2018-04-19 21:51:53 -05:00
Ok(ref s) => {
// FIXME(Manishearth) ideally the emitting code
// can tell us whether or not this is global
let opt_colon = if s.trim_start().starts_with("::") {
2018-04-19 21:51:53 -05:00
""
} else {
"::"
};
2018-05-04 16:12:33 -05:00
(format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
2018-04-19 21:51:53 -05:00
}
2018-07-28 07:40:32 -05:00
Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders)
2018-04-19 21:51:53 -05:00
};
db.span_suggestion(span, "use `crate`", sugg, app);
2018-04-19 21:51:53 -05:00
}
2018-04-21 09:18:38 -05:00
BuiltinLintDiagnostics::DuplicatedMacroExports(ident, earlier_span, later_span) => {
db.span_label(later_span, format!("`{}` already exported", ident));
db.span_note(earlier_span, "previous macro export is now shadowed");
}
BuiltinLintDiagnostics::ProcMacroDeriveResolutionFallback(span) => {
db.span_label(span, "names from parent modules are not \
accessible without an explicit import");
}
BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def) => {
db.span_note(span_def, "the macro is defined here");
}
BuiltinLintDiagnostics::ElidedLifetimesInPaths(
n, path_span, incl_angl_brckt, insertion_span, anon_lts
) => {
let (replace_span, suggestion) = if incl_angl_brckt {
(insertion_span, anon_lts)
} else {
// When possible, prefer a suggestion that replaces the whole
// `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, `
// at a point (which makes for an ugly/confusing label)
2018-08-18 05:14:09 -05:00
if let Ok(snippet) = sess.source_map().span_to_snippet(path_span) {
// But our spans can get out of whack due to macros; if the place we think
// we want to insert `'_` isn't even within the path expression's span, we
// should bail out of making any suggestion rather than panicking on a
// subtract-with-overflow or string-slice-out-out-bounds (!)
// FIXME: can we do better?
if insertion_span.lo().0 < path_span.lo().0 {
return;
}
let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize;
if insertion_index > snippet.len() {
return;
}
let (before, after) = snippet.split_at(insertion_index);
(path_span, format!("{}{}{}", before, anon_lts, after))
} else {
(insertion_span, anon_lts)
}
};
db.span_suggestion(
replace_span,
&format!("indicate the anonymous lifetime{}", if n >= 2 { "s" } else { "" }),
suggestion,
Applicability::MachineApplicable
);
}
BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => {
db.span_suggestion(span, &note, sugg, Applicability::MaybeIncorrect);
}
BuiltinLintDiagnostics::UnusedImports(message, replaces) => {
if !replaces.is_empty() {
db.tool_only_multipart_suggestion(
&message,
replaces,
Applicability::MachineApplicable,
);
}
}
BuiltinLintDiagnostics::NestedImplTrait {
outer_impl_trait_span, inner_impl_trait_span
} => {
db.span_label(outer_impl_trait_span, "outer `impl Trait`");
db.span_label(inner_impl_trait_span, "nested `impl Trait` here");
}
2019-03-16 11:38:12 -05:00
BuiltinLintDiagnostics::RedundantImport(spans, ident) => {
for (span, is_imported) in spans {
let introduced = if is_imported { "imported" } else { "defined" };
2019-03-16 11:38:12 -05:00
db.span_label(
span,
2019-03-17 15:07:57 -05:00
format!("the item `{}` is already {} here", ident, introduced)
2019-03-16 11:38:12 -05:00
);
}
}
}
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HardwiredLints {}