Rollup merge of #65193 - Mark-Simulacrum:lockless-lintstore, r=nikomatsakis
Lockless LintStore This removes mutability from the lint store after registration. Each commit stands alone, for the most part, though they don't make sense out of sequence. The intent here is to move LintStore to a more parallel-friendly architecture, although also just a cleaner one from an implementation perspective. Specifically, this has the following changes: * We no longer implicitly register lints when registering lint passes * For the most part this means that registration calls now likely want to call something like: `lint_store.register_lints(&Pass::get_lints())` as well as `register_*_pass`. * In theory this is a simplification as it's much easier for folks to just register lints and then have passes that implement whichever lint however they want, rather than necessarily tying passes to lints. * Lint passes still have a list of associated lints, but a followup PR could plausibly change that * This list must be known for a given pass type, not instance, i.e., `fn get_lints()` is the signature instead of `fn get_lints(&self)` as before. * We do not store pass objects, instead storing constructor functions. This means we always get new passes when running lints (this happens approximately once though for a given compiler session, so no behavior change is expected). * Registration API is _much_ simpler: generally all functions are just taking `Fn() -> PassObject` rather than several different `bool`s.
This commit is contained in:
commit
7c043e284a
@ -3483,6 +3483,7 @@ dependencies = [
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_interface",
|
||||
"rustc_lint",
|
||||
"rustc_metadata",
|
||||
"rustc_mir",
|
||||
"rustc_plugin",
|
||||
|
@ -4,11 +4,12 @@
|
||||
//! compiler code, rather than using their own custom pass. Those
|
||||
//! lints are all available in `rustc_lint::builtin`.
|
||||
|
||||
use crate::lint::{LintPass, LateLintPass, LintArray};
|
||||
use crate::lint::{LintPass, LateLintPass, LintArray, FutureIncompatibleInfo};
|
||||
use crate::middle::stability;
|
||||
use crate::session::Session;
|
||||
use errors::{Applicability, DiagnosticBuilder, pluralise};
|
||||
use syntax::ast;
|
||||
use syntax::edition::Edition;
|
||||
use syntax::source_map::Span;
|
||||
use syntax::symbol::Symbol;
|
||||
|
||||
@ -22,7 +23,7 @@ declare_lint! {
|
||||
pub CONST_ERR,
|
||||
Deny,
|
||||
"constant evaluation detected erroneous expression",
|
||||
report_in_external_macro: true
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -71,7 +72,7 @@ declare_lint! {
|
||||
pub UNREACHABLE_CODE,
|
||||
Warn,
|
||||
"detects unreachable code paths",
|
||||
report_in_external_macro: true
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -131,7 +132,11 @@ declare_lint! {
|
||||
declare_lint! {
|
||||
pub PRIVATE_IN_PUBLIC,
|
||||
Warn,
|
||||
"detect private items in public interfaces not caught by the old implementation"
|
||||
"detect private items in public interfaces not caught by the old implementation",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -143,13 +148,21 @@ declare_lint! {
|
||||
declare_lint! {
|
||||
pub PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
||||
Deny,
|
||||
"detect public re-exports of private extern crates"
|
||||
"detect public re-exports of private extern crates",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub INVALID_TYPE_PARAM_DEFAULT,
|
||||
Deny,
|
||||
"type parameter default erroneously allowed in invalid location"
|
||||
"type parameter default erroneously allowed in invalid location",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -161,63 +174,99 @@ declare_lint! {
|
||||
declare_lint! {
|
||||
pub SAFE_EXTERN_STATICS,
|
||||
Deny,
|
||||
"safe access to extern statics was erroneously allowed"
|
||||
"safe access to extern statics was erroneously allowed",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub SAFE_PACKED_BORROWS,
|
||||
Warn,
|
||||
"safe borrows of fields of packed structs were was erroneously allowed"
|
||||
"safe borrows of fields of packed structs were was erroneously allowed",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
Warn,
|
||||
"patterns in functions without body were erroneously allowed"
|
||||
"patterns in functions without body were erroneously allowed",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub LEGACY_DIRECTORY_OWNERSHIP,
|
||||
Deny,
|
||||
"non-inline, non-`#[path]` modules (e.g., `mod foo;`) were erroneously allowed in some files \
|
||||
not named `mod.rs`"
|
||||
not named `mod.rs`",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub LEGACY_CONSTRUCTOR_VISIBILITY,
|
||||
Deny,
|
||||
"detects use of struct constructors that would be invisible with new visibility rules"
|
||||
"detects use of struct constructors that would be invisible with new visibility rules",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub MISSING_FRAGMENT_SPECIFIER,
|
||||
Deny,
|
||||
"detects missing fragment specifiers in unused `macro_rules!` patterns"
|
||||
"detects missing fragment specifiers in unused `macro_rules!` patterns",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
|
||||
Deny,
|
||||
"detects parenthesized generic parameters in type and module names"
|
||||
"detects parenthesized generic parameters in type and module names",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub LATE_BOUND_LIFETIME_ARGUMENTS,
|
||||
Warn,
|
||||
"detects generic lifetime arguments in path segments with late bound lifetime parameters"
|
||||
"detects generic lifetime arguments in path segments with late bound lifetime parameters",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub ORDER_DEPENDENT_TRAIT_OBJECTS,
|
||||
Deny,
|
||||
"trait-object types were treated as different depending on marker-trait order"
|
||||
"trait-object types were treated as different depending on marker-trait order",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub DEPRECATED,
|
||||
Warn,
|
||||
"detects use of deprecated items",
|
||||
report_in_external_macro: true
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -253,7 +302,11 @@ declare_lint! {
|
||||
declare_lint! {
|
||||
pub TYVAR_BEHIND_RAW_POINTER,
|
||||
Warn,
|
||||
"raw pointer to an inference variable"
|
||||
"raw pointer to an inference variable",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -272,19 +325,33 @@ declare_lint! {
|
||||
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"
|
||||
instead of `crate`, `self`, or an extern crate name",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #53130 <https://github.com/rust-lang/rust/issues/53130>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
|
||||
Warn,
|
||||
"floating-point literals cannot be used in patterns"
|
||||
"floating-point literals cannot be used in patterns",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub UNSTABLE_NAME_COLLISIONS,
|
||||
Warn,
|
||||
"detects name collision with an existing but unstable method"
|
||||
"detects name collision with an existing but unstable method",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
|
||||
edition: None,
|
||||
// Note: this item represents future incompatibility of all unstable functions in the
|
||||
// standard library, and thus should never be removed or changed to an error.
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -302,7 +369,11 @@ declare_lint! {
|
||||
declare_lint! {
|
||||
pub DUPLICATE_MACRO_EXPORTS,
|
||||
Deny,
|
||||
"detects duplicate macro exports"
|
||||
"detects duplicate macro exports",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -326,13 +397,21 @@ declare_lint! {
|
||||
declare_lint! {
|
||||
pub WHERE_CLAUSES_OBJECT_SAFETY,
|
||||
Warn,
|
||||
"checks the object safety of where clauses"
|
||||
"checks the object safety of where clauses",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||
Warn,
|
||||
"detects proc macro derives using inaccessible names from parent modules"
|
||||
"detects proc macro derives using inaccessible names from parent modules",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -346,7 +425,11 @@ 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"
|
||||
cannot be referred to by absolute paths",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -359,7 +442,11 @@ declare_lint! {
|
||||
pub INDIRECT_STRUCTURAL_MATCH,
|
||||
// defaulting to allow until rust-lang/rust#62614 is fixed.
|
||||
Allow,
|
||||
"pattern with const indirectly referencing non-`#[structural_match]` type"
|
||||
"pattern with const indirectly referencing non-`#[structural_match]` type",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
/// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
|
||||
@ -367,7 +454,11 @@ pub mod parser {
|
||||
declare_lint! {
|
||||
pub ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
Warn,
|
||||
"ill-formed attribute inputs that were previously accepted and used in practice"
|
||||
"ill-formed attribute inputs that were previously accepted and used in practice",
|
||||
@future_incompatible = super::FutureIncompatibleInfo {
|
||||
reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
@ -387,31 +478,47 @@ declare_lint! {
|
||||
pub DEPRECATED_IN_FUTURE,
|
||||
Allow,
|
||||
"detects use of items that will be deprecated in a future version",
|
||||
report_in_external_macro: true
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||
Deny,
|
||||
"ambiguous associated items"
|
||||
"ambiguous associated items",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub NESTED_IMPL_TRAIT,
|
||||
Warn,
|
||||
"nested occurrence of `impl Trait` type"
|
||||
"nested occurrence of `impl Trait` type",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #59014 <https://github.com/rust-lang/rust/issues/59014>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub MUTABLE_BORROW_RESERVATION_CONFLICT,
|
||||
Warn,
|
||||
"reservation of a two-phased borrow conflicts with other shared borrows"
|
||||
"reservation of a two-phased borrow conflicts with other shared borrows",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub SOFT_UNSTABLE,
|
||||
Deny,
|
||||
"a feature gate that doesn't break dependent crates"
|
||||
"a feature gate that doesn't break dependent crates",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass! {
|
||||
|
@ -22,11 +22,11 @@ use crate::hir::intravisit as hir_visit;
|
||||
use crate::hir::intravisit::Visitor;
|
||||
use crate::hir::map::{definitions::DisambiguatedDefPathData, DefPathData};
|
||||
use crate::lint::{EarlyLintPass, LateLintPass, EarlyLintPassObject, LateLintPassObject};
|
||||
use crate::lint::{LintArray, Level, Lint, LintId, LintPass, LintBuffer};
|
||||
use crate::lint::{Level, Lint, LintId, LintPass, LintBuffer, FutureIncompatibleInfo};
|
||||
use crate::lint::builtin::BuiltinLintDiagnostics;
|
||||
use crate::lint::levels::{LintLevelSets, LintLevelsBuilder};
|
||||
use crate::middle::privacy::AccessLevels;
|
||||
use crate::session::{config, early_error, Session};
|
||||
use crate::session::Session;
|
||||
use crate::ty::{self, print::Printer, subst::GenericArg, TyCtxt, Ty};
|
||||
use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
@ -35,10 +35,9 @@ use crate::util::common::time;
|
||||
use errors::DiagnosticBuilder;
|
||||
use std::slice;
|
||||
use std::default::Default as StdDefault;
|
||||
use rustc_data_structures::sync::{ReadGuard, Lock, ParallelIterator, join, par_iter};
|
||||
use rustc_data_structures::sync::{self, ParallelIterator, join, par_iter};
|
||||
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
|
||||
use syntax::ast;
|
||||
use syntax::edition;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax::visit as ast_visit;
|
||||
use syntax_pos::{MultiSpan, Span, symbol::Symbol};
|
||||
@ -50,24 +49,25 @@ use syntax_pos::{MultiSpan, Span, symbol::Symbol};
|
||||
pub struct LintStore {
|
||||
/// Registered lints. The bool is true if the lint was
|
||||
/// added by a plugin.
|
||||
lints: Vec<(&'static Lint, bool)>,
|
||||
lints: Vec<&'static Lint>,
|
||||
|
||||
/// Trait objects for each lint pass.
|
||||
/// This is only `None` while performing a lint pass.
|
||||
pre_expansion_passes: Option<Vec<EarlyLintPassObject>>,
|
||||
early_passes: Option<Vec<EarlyLintPassObject>>,
|
||||
late_passes: Lock<Option<Vec<LateLintPassObject>>>,
|
||||
late_module_passes: Vec<LateLintPassObject>,
|
||||
/// Constructor functions for each variety of lint pass.
|
||||
///
|
||||
/// These should only be called once, but since we want to avoid locks or
|
||||
/// interior mutability, we don't enforce this (and lints should, in theory,
|
||||
/// be compatible with being constructed more than once, though not
|
||||
/// necessarily in a sane manner. This is safe though.)
|
||||
pre_expansion_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
|
||||
early_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
|
||||
late_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
|
||||
/// This is unique in that we construct them per-module, so not once.
|
||||
late_module_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
|
||||
|
||||
/// Lints indexed by name.
|
||||
by_name: FxHashMap<String, TargetLint>,
|
||||
|
||||
/// Map of registered lint groups to what lints they expand to.
|
||||
lint_groups: FxHashMap<&'static str, LintGroup>,
|
||||
|
||||
/// Extra info for future incompatibility lints, describing the
|
||||
/// issue or RFC that caused the incompatibility.
|
||||
future_incompatible: FxHashMap<LintId, FutureIncompatibleInfo>,
|
||||
}
|
||||
|
||||
/// Lints that are buffered up early on in the `Session` before the
|
||||
@ -81,18 +81,6 @@ pub struct BufferedEarlyLint {
|
||||
pub diagnostic: BuiltinLintDiagnostics,
|
||||
}
|
||||
|
||||
/// Extra information for a future incompatibility lint. See the call
|
||||
/// to `register_future_incompatible` in `librustc_lint/lib.rs` for
|
||||
/// guidelines.
|
||||
pub struct FutureIncompatibleInfo {
|
||||
pub id: LintId,
|
||||
/// e.g., a URL for an issue/PR/RFC or error code
|
||||
pub reference: &'static str,
|
||||
/// If this is an edition fixing lint, the edition in which
|
||||
/// this lint becomes obsolete
|
||||
pub edition: Option<edition::Edition>,
|
||||
}
|
||||
|
||||
/// The target of the `by_name` map, which accounts for renaming/deprecation.
|
||||
enum TargetLint {
|
||||
/// A direct lint target
|
||||
@ -142,17 +130,16 @@ impl LintStore {
|
||||
pub fn new() -> LintStore {
|
||||
LintStore {
|
||||
lints: vec![],
|
||||
pre_expansion_passes: Some(vec![]),
|
||||
early_passes: Some(vec![]),
|
||||
late_passes: Lock::new(Some(vec![])),
|
||||
pre_expansion_passes: vec![],
|
||||
early_passes: vec![],
|
||||
late_passes: vec![],
|
||||
late_module_passes: vec![],
|
||||
by_name: Default::default(),
|
||||
future_incompatible: Default::default(),
|
||||
lint_groups: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] {
|
||||
pub fn get_lints<'t>(&'t self) -> &'t [&'static Lint] {
|
||||
&self.lints
|
||||
}
|
||||
|
||||
@ -168,101 +155,66 @@ impl LintStore {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn register_early_pass(&mut self,
|
||||
sess: Option<&Session>,
|
||||
from_plugin: bool,
|
||||
register_only: bool,
|
||||
pass: EarlyLintPassObject) {
|
||||
self.push_pass(sess, from_plugin, &pass);
|
||||
if !register_only {
|
||||
self.early_passes.as_mut().unwrap().push(pass);
|
||||
}
|
||||
pub fn register_early_pass(
|
||||
&mut self,
|
||||
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync
|
||||
) {
|
||||
self.early_passes.push(Box::new(pass));
|
||||
}
|
||||
|
||||
pub fn register_pre_expansion_pass(
|
||||
&mut self,
|
||||
sess: Option<&Session>,
|
||||
from_plugin: bool,
|
||||
register_only: bool,
|
||||
pass: EarlyLintPassObject,
|
||||
pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync,
|
||||
) {
|
||||
self.push_pass(sess, from_plugin, &pass);
|
||||
if !register_only {
|
||||
self.pre_expansion_passes.as_mut().unwrap().push(pass);
|
||||
}
|
||||
self.pre_expansion_passes.push(Box::new(pass));
|
||||
}
|
||||
|
||||
pub fn register_late_pass(&mut self,
|
||||
sess: Option<&Session>,
|
||||
from_plugin: bool,
|
||||
register_only: bool,
|
||||
per_module: bool,
|
||||
pass: LateLintPassObject) {
|
||||
self.push_pass(sess, from_plugin, &pass);
|
||||
if !register_only {
|
||||
if per_module {
|
||||
self.late_module_passes.push(pass);
|
||||
} else {
|
||||
self.late_passes.lock().as_mut().unwrap().push(pass);
|
||||
}
|
||||
}
|
||||
pub fn register_late_pass(
|
||||
&mut self,
|
||||
pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
|
||||
) {
|
||||
self.late_passes.push(Box::new(pass));
|
||||
}
|
||||
|
||||
pub fn register_late_mod_pass(
|
||||
&mut self,
|
||||
pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
|
||||
) {
|
||||
self.late_module_passes.push(Box::new(pass));
|
||||
}
|
||||
|
||||
// Helper method for register_early/late_pass
|
||||
fn push_pass<P: LintPass + ?Sized + 'static>(&mut self,
|
||||
sess: Option<&Session>,
|
||||
from_plugin: bool,
|
||||
pass: &Box<P>) {
|
||||
for lint in pass.get_lints() {
|
||||
self.lints.push((lint, from_plugin));
|
||||
pub fn register_lints(&mut self, lints: &[&'static Lint]) {
|
||||
for lint in lints {
|
||||
self.lints.push(lint);
|
||||
|
||||
let id = LintId::of(lint);
|
||||
if self.by_name.insert(lint.name_lower(), Id(id)).is_some() {
|
||||
let msg = format!("duplicate specification of lint {}", lint.name_lower());
|
||||
match (sess, from_plugin) {
|
||||
// We load builtin lints first, so a duplicate is a compiler bug.
|
||||
// Use early_error when handling -W help with no crate.
|
||||
(None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
|
||||
(Some(_), false) => bug!("{}", msg),
|
||||
bug!("duplicate specification of lint {}", lint.name_lower())
|
||||
}
|
||||
|
||||
// A duplicate name from a plugin is a user error.
|
||||
(Some(sess), true) => sess.err(&msg[..]),
|
||||
if let Some(FutureIncompatibleInfo { edition, .. }) = lint.future_incompatible {
|
||||
if let Some(edition) = edition {
|
||||
self.lint_groups.entry(edition.lint_name())
|
||||
.or_insert(LintGroup {
|
||||
lint_ids: vec![],
|
||||
from_plugin: lint.is_plugin,
|
||||
depr: None,
|
||||
})
|
||||
.lint_ids.push(id);
|
||||
}
|
||||
|
||||
self.lint_groups.entry("future_incompatible")
|
||||
.or_insert(LintGroup {
|
||||
lint_ids: vec![],
|
||||
from_plugin: lint.is_plugin,
|
||||
depr: None,
|
||||
})
|
||||
.lint_ids.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_future_incompatible(&mut self,
|
||||
sess: Option<&Session>,
|
||||
lints: Vec<FutureIncompatibleInfo>) {
|
||||
|
||||
for edition in edition::ALL_EDITIONS {
|
||||
let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id)
|
||||
.collect::<Vec<_>>();
|
||||
if !lints.is_empty() {
|
||||
self.register_group(sess, false, edition.lint_name(), None, lints)
|
||||
}
|
||||
}
|
||||
|
||||
let mut future_incompatible = Vec::with_capacity(lints.len());
|
||||
for lint in lints {
|
||||
future_incompatible.push(lint.id);
|
||||
self.future_incompatible.insert(lint.id, lint);
|
||||
}
|
||||
|
||||
self.register_group(
|
||||
sess,
|
||||
false,
|
||||
"future_incompatible",
|
||||
None,
|
||||
future_incompatible,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn future_incompatible(&self, id: LintId) -> Option<&FutureIncompatibleInfo> {
|
||||
self.future_incompatible.get(&id)
|
||||
}
|
||||
|
||||
pub fn register_group_alias(
|
||||
&mut self,
|
||||
lint_name: &'static str,
|
||||
@ -277,7 +229,6 @@ impl LintStore {
|
||||
|
||||
pub fn register_group(
|
||||
&mut self,
|
||||
sess: Option<&Session>,
|
||||
from_plugin: bool,
|
||||
name: &'static str,
|
||||
deprecated_name: Option<&'static str>,
|
||||
@ -300,16 +251,7 @@ impl LintStore {
|
||||
}
|
||||
|
||||
if !new {
|
||||
let msg = format!("duplicate specification of lint group {}", name);
|
||||
match (sess, from_plugin) {
|
||||
// We load builtin lints first, so a duplicate is a compiler bug.
|
||||
// Use early_error when handling -W help with no crate.
|
||||
(None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
|
||||
(Some(_), false) => bug!("{}", msg),
|
||||
|
||||
// A duplicate name from a plugin is a user error.
|
||||
(Some(sess), true) => sess.err(&msg[..]),
|
||||
}
|
||||
bug!("duplicate specification of lint group {}", name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,7 +464,7 @@ pub struct LateContext<'a, 'tcx> {
|
||||
pub access_levels: &'a AccessLevels,
|
||||
|
||||
/// The store of registered lints and the lint levels.
|
||||
lint_store: ReadGuard<'a, LintStore>,
|
||||
lint_store: &'tcx LintStore,
|
||||
|
||||
last_node_with_lint_attrs: hir::HirId,
|
||||
|
||||
@ -550,7 +492,7 @@ pub struct EarlyContext<'a> {
|
||||
builder: LintLevelsBuilder<'a>,
|
||||
|
||||
/// The store of registered lints and the lint levels.
|
||||
lint_store: ReadGuard<'a, LintStore>,
|
||||
lint_store: &'a LintStore,
|
||||
|
||||
buffered: LintBuffer,
|
||||
}
|
||||
@ -639,14 +581,15 @@ pub trait LintContext: Sized {
|
||||
impl<'a> EarlyContext<'a> {
|
||||
fn new(
|
||||
sess: &'a Session,
|
||||
lint_store: &'a LintStore,
|
||||
krate: &'a ast::Crate,
|
||||
buffered: LintBuffer,
|
||||
) -> EarlyContext<'a> {
|
||||
EarlyContext {
|
||||
sess,
|
||||
krate,
|
||||
lint_store: sess.lint_store.borrow(),
|
||||
builder: LintLevelSets::builder(sess),
|
||||
lint_store,
|
||||
builder: LintLevelSets::builder(sess, lint_store),
|
||||
buffered,
|
||||
}
|
||||
}
|
||||
@ -681,7 +624,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
||||
f: F)
|
||||
where F: FnOnce(&mut Self)
|
||||
{
|
||||
let push = self.context.builder.push(attrs);
|
||||
let push = self.context.builder.push(attrs, &self.context.lint_store);
|
||||
self.check_id(id);
|
||||
self.enter_attrs(attrs);
|
||||
f(self);
|
||||
@ -1355,10 +1298,6 @@ impl LintPass for LateLintPassObjects<'_> {
|
||||
fn name(&self) -> &'static str {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn get_lints(&self) -> LintArray {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! expand_late_lint_pass_impl_methods {
|
||||
@ -1393,7 +1332,7 @@ fn late_lint_mod_pass<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
|
||||
tables: &ty::TypeckTables::empty(None),
|
||||
param_env: ty::ParamEnv::empty(),
|
||||
access_levels,
|
||||
lint_store: tcx.sess.lint_store.borrow(),
|
||||
lint_store: &tcx.lint_store,
|
||||
last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
|
||||
generics: None,
|
||||
only_module: true,
|
||||
@ -1425,8 +1364,8 @@ pub fn late_lint_mod<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(
|
||||
|
||||
late_lint_mod_pass(tcx, module_def_id, builtin_lints);
|
||||
|
||||
let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes
|
||||
.iter().map(|pass| pass.fresh_late_pass()).collect();
|
||||
let mut passes: Vec<_> = tcx.lint_store.late_module_passes
|
||||
.iter().map(|pass| (pass)()).collect();
|
||||
|
||||
if !passes.is_empty() {
|
||||
late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
|
||||
@ -1443,7 +1382,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
|
||||
tables: &ty::TypeckTables::empty(None),
|
||||
param_env: ty::ParamEnv::empty(),
|
||||
access_levels,
|
||||
lint_store: tcx.sess.lint_store.borrow(),
|
||||
lint_store: &tcx.lint_store,
|
||||
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
|
||||
generics: None,
|
||||
only_module: false,
|
||||
@ -1467,7 +1406,8 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc
|
||||
}
|
||||
|
||||
fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
|
||||
let mut passes = tcx.sess.lint_store.borrow().late_passes.lock().take().unwrap();
|
||||
let mut passes = tcx.lint_store
|
||||
.late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
|
||||
|
||||
if !tcx.sess.opts.debugging_opts.no_interleave_lints {
|
||||
if !passes.is_empty() {
|
||||
@ -1482,8 +1422,8 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b
|
||||
});
|
||||
}
|
||||
|
||||
let mut passes: Vec<_> = tcx.sess.lint_store.borrow().late_module_passes
|
||||
.iter().map(|pass| pass.fresh_late_pass()).collect();
|
||||
let mut passes: Vec<_> = tcx.lint_store.late_module_passes
|
||||
.iter().map(|pass| (pass)()).collect();
|
||||
|
||||
for pass in &mut passes {
|
||||
time(tcx.sess, &format!("running late module lint: {}", pass.name()), || {
|
||||
@ -1491,9 +1431,6 @@ fn late_lint_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tcx>, b
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Put the passes back in the session.
|
||||
*tcx.sess.lint_store.borrow().late_passes.lock() = Some(passes);
|
||||
}
|
||||
|
||||
/// Performs lint checking on a crate.
|
||||
@ -1525,10 +1462,6 @@ impl LintPass for EarlyLintPassObjects<'_> {
|
||||
fn name(&self) -> &'static str {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn get_lints(&self) -> LintArray {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! expand_early_lint_pass_impl_methods {
|
||||
@ -1553,12 +1486,13 @@ early_lint_methods!(early_lint_pass_impl, []);
|
||||
|
||||
fn early_lint_crate<T: EarlyLintPass>(
|
||||
sess: &Session,
|
||||
lint_store: &LintStore,
|
||||
krate: &ast::Crate,
|
||||
pass: T,
|
||||
buffered: LintBuffer,
|
||||
) -> LintBuffer {
|
||||
let mut cx = EarlyContextAndPass {
|
||||
context: EarlyContext::new(sess, krate, buffered),
|
||||
context: EarlyContext::new(sess, lint_store, krate, buffered),
|
||||
pass,
|
||||
};
|
||||
|
||||
@ -1577,28 +1511,30 @@ fn early_lint_crate<T: EarlyLintPass>(
|
||||
|
||||
pub fn check_ast_crate<T: EarlyLintPass>(
|
||||
sess: &Session,
|
||||
lint_store: &LintStore,
|
||||
krate: &ast::Crate,
|
||||
pre_expansion: bool,
|
||||
builtin_lints: T,
|
||||
) {
|
||||
let (mut passes, mut buffered) = if pre_expansion {
|
||||
let (mut passes, mut buffered): (Vec<_>, _) = if pre_expansion {
|
||||
(
|
||||
sess.lint_store.borrow_mut().pre_expansion_passes.take().unwrap(),
|
||||
lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect(),
|
||||
LintBuffer::default(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
sess.lint_store.borrow_mut().early_passes.take().unwrap(),
|
||||
lint_store.early_passes.iter().map(|p| (p)()).collect(),
|
||||
sess.buffered_lints.borrow_mut().take().unwrap(),
|
||||
)
|
||||
};
|
||||
|
||||
if !sess.opts.debugging_opts.no_interleave_lints {
|
||||
buffered = early_lint_crate(sess, krate, builtin_lints, buffered);
|
||||
buffered = early_lint_crate(sess, lint_store, krate, builtin_lints, buffered);
|
||||
|
||||
if !passes.is_empty() {
|
||||
buffered = early_lint_crate(
|
||||
sess,
|
||||
lint_store,
|
||||
krate,
|
||||
EarlyLintPassObjects { lints: &mut passes[..] },
|
||||
buffered,
|
||||
@ -1609,6 +1545,7 @@ pub fn check_ast_crate<T: EarlyLintPass>(
|
||||
buffered = time(sess, &format!("running lint: {}", pass.name()), || {
|
||||
early_lint_crate(
|
||||
sess,
|
||||
lint_store,
|
||||
krate,
|
||||
EarlyLintPassObjects { lints: slice::from_mut(pass) },
|
||||
buffered,
|
||||
@ -1617,13 +1554,6 @@ pub fn check_ast_crate<T: EarlyLintPass>(
|
||||
}
|
||||
}
|
||||
|
||||
// Put the lint store levels and passes back in the session.
|
||||
if pre_expansion {
|
||||
sess.lint_store.borrow_mut().pre_expansion_passes = Some(passes);
|
||||
} else {
|
||||
sess.lint_store.borrow_mut().early_passes = Some(passes);
|
||||
}
|
||||
|
||||
// All of the buffered lints should have been emitted at this point.
|
||||
// If not, that means that we somehow buffered a lint for a node id
|
||||
// that was not lint-checked (perhaps it doesn't exist?). This is a bug.
|
||||
@ -1653,7 +1583,7 @@ impl Decodable for LintId {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
|
||||
let s = d.read_str()?;
|
||||
ty::tls::with(|tcx| {
|
||||
match tcx.sess.lint_store.borrow().find_lints(&s) {
|
||||
match tcx.lint_store.find_lints(&s) {
|
||||
Ok(ids) => {
|
||||
if ids.len() != 0 {
|
||||
panic!("invalid lint-id `{}`", s);
|
||||
|
@ -3,7 +3,7 @@ use std::cmp;
|
||||
use crate::hir::HirId;
|
||||
use crate::ich::StableHashingContext;
|
||||
use crate::lint::builtin;
|
||||
use crate::lint::context::CheckLintNameResult;
|
||||
use crate::lint::context::{LintStore, CheckLintNameResult};
|
||||
use crate::lint::{self, Lint, LintId, Level, LintSource};
|
||||
use crate::session::Session;
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
@ -35,21 +35,20 @@ enum LintSet {
|
||||
}
|
||||
|
||||
impl LintLevelSets {
|
||||
pub fn new(sess: &Session) -> LintLevelSets {
|
||||
pub fn new(sess: &Session, lint_store: &LintStore) -> LintLevelSets {
|
||||
let mut me = LintLevelSets {
|
||||
list: Vec::new(),
|
||||
lint_cap: Level::Forbid,
|
||||
};
|
||||
me.process_command_line(sess);
|
||||
me.process_command_line(sess, lint_store);
|
||||
return me
|
||||
}
|
||||
|
||||
pub fn builder(sess: &Session) -> LintLevelsBuilder<'_> {
|
||||
LintLevelsBuilder::new(sess, LintLevelSets::new(sess))
|
||||
pub fn builder<'a>(sess: &'a Session, store: &LintStore) -> LintLevelsBuilder<'a> {
|
||||
LintLevelsBuilder::new(sess, LintLevelSets::new(sess, store))
|
||||
}
|
||||
|
||||
fn process_command_line(&mut self, sess: &Session) {
|
||||
let store = sess.lint_store.borrow();
|
||||
fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
|
||||
let mut specs = FxHashMap::default();
|
||||
self.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
|
||||
|
||||
@ -186,9 +185,8 @@ impl<'a> LintLevelsBuilder<'a> {
|
||||
/// #[allow]
|
||||
///
|
||||
/// Don't forget to call `pop`!
|
||||
pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush {
|
||||
pub fn push(&mut self, attrs: &[ast::Attribute], store: &LintStore) -> BuilderPush {
|
||||
let mut specs = FxHashMap::default();
|
||||
let store = self.sess.lint_store.borrow();
|
||||
let sess = self.sess;
|
||||
let bad_attr = |span| {
|
||||
struct_span_err!(sess, span, E0452, "malformed lint attribute input")
|
||||
|
@ -45,7 +45,7 @@ use syntax_pos::Span;
|
||||
|
||||
pub use crate::lint::context::{LateContext, EarlyContext, LintContext, LintStore,
|
||||
check_crate, check_ast_crate, late_lint_mod, CheckLintNameResult,
|
||||
FutureIncompatibleInfo, BufferedEarlyLint,};
|
||||
BufferedEarlyLint,};
|
||||
|
||||
/// Specification of a single lint.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -76,9 +76,35 @@ pub struct Lint {
|
||||
|
||||
/// `true` if this lint is reported even inside expansions of external macros.
|
||||
pub report_in_external_macro: bool,
|
||||
|
||||
pub future_incompatible: Option<FutureIncompatibleInfo>,
|
||||
|
||||
pub is_plugin: bool,
|
||||
}
|
||||
|
||||
/// Extra information for a future incompatibility lint.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct FutureIncompatibleInfo {
|
||||
/// e.g., a URL for an issue/PR/RFC or error code
|
||||
pub reference: &'static str,
|
||||
/// If this is an edition fixing lint, the edition in which
|
||||
/// this lint becomes obsolete
|
||||
pub edition: Option<Edition>,
|
||||
}
|
||||
|
||||
impl Lint {
|
||||
pub const fn default_fields_for_macro() -> Self {
|
||||
Lint {
|
||||
name: "",
|
||||
default_level: Level::Forbid,
|
||||
desc: "",
|
||||
edition_lint_opts: None,
|
||||
is_plugin: false,
|
||||
report_in_external_macro: false,
|
||||
future_incompatible: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`.
|
||||
pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self {
|
||||
match lint_id {
|
||||
@ -105,18 +131,21 @@ impl Lint {
|
||||
#[macro_export]
|
||||
macro_rules! declare_lint {
|
||||
($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
|
||||
declare_lint!{$vis $NAME, $Level, $desc, false}
|
||||
declare_lint!(
|
||||
$vis $NAME, $Level, $desc,
|
||||
);
|
||||
);
|
||||
($vis: vis $NAME: ident, $Level: ident, $desc: expr, report_in_external_macro: $rep: expr) => (
|
||||
declare_lint!{$vis $NAME, $Level, $desc, $rep}
|
||||
);
|
||||
($vis: vis $NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
|
||||
($vis: vis $NAME: ident, $Level: ident, $desc: expr,
|
||||
$(@future_incompatible = $fi:expr;)? $($v:ident),*) => (
|
||||
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
|
||||
name: stringify!($NAME),
|
||||
default_level: $crate::lint::$Level,
|
||||
desc: $desc,
|
||||
edition_lint_opts: None,
|
||||
report_in_external_macro: $external,
|
||||
is_plugin: false,
|
||||
$($v: true,)*
|
||||
$(future_incompatible: Some($fi),)*
|
||||
..$crate::lint::Lint::default_fields_for_macro()
|
||||
};
|
||||
);
|
||||
($vis: vis $NAME: ident, $Level: ident, $desc: expr,
|
||||
@ -128,6 +157,7 @@ macro_rules! declare_lint {
|
||||
desc: $desc,
|
||||
edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)),
|
||||
report_in_external_macro: false,
|
||||
is_plugin: false,
|
||||
};
|
||||
);
|
||||
}
|
||||
@ -156,6 +186,8 @@ macro_rules! declare_tool_lint {
|
||||
desc: $desc,
|
||||
edition_lint_opts: None,
|
||||
report_in_external_macro: $external,
|
||||
future_incompatible: None,
|
||||
is_plugin: true,
|
||||
};
|
||||
);
|
||||
}
|
||||
@ -173,14 +205,6 @@ pub type LintArray = Vec<&'static Lint>;
|
||||
|
||||
pub trait LintPass {
|
||||
fn name(&self) -> &'static str;
|
||||
|
||||
/// Gets descriptions of the lints this `LintPass` object can emit.
|
||||
///
|
||||
/// N.B., there is no enforcement that the object only emits lints it registered.
|
||||
/// And some `rustc` internal `LintPass`es register lints to be emitted by other
|
||||
/// parts of the compiler. If you want enforced access restrictions for your
|
||||
/// `Lint`, make it a private `static` item in its own module.
|
||||
fn get_lints(&self) -> LintArray;
|
||||
}
|
||||
|
||||
/// Implements `LintPass for $name` with the given list of `Lint` statics.
|
||||
@ -189,7 +213,9 @@ macro_rules! impl_lint_pass {
|
||||
($name:ident => [$($lint:expr),* $(,)?]) => {
|
||||
impl LintPass for $name {
|
||||
fn name(&self) -> &'static str { stringify!($name) }
|
||||
fn get_lints(&self) -> LintArray { $crate::lint_array!($($lint),*) }
|
||||
}
|
||||
impl $name {
|
||||
pub fn get_lints() -> LintArray { $crate::lint_array!($($lint),*) }
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -287,9 +313,6 @@ macro_rules! expand_lint_pass_methods {
|
||||
macro_rules! declare_late_lint_pass {
|
||||
([], [$hir:tt], [$($methods:tt)*]) => (
|
||||
pub trait LateLintPass<'a, $hir>: LintPass {
|
||||
fn fresh_late_pass(&self) -> LateLintPassObject {
|
||||
panic!()
|
||||
}
|
||||
expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]);
|
||||
}
|
||||
)
|
||||
@ -327,6 +350,12 @@ macro_rules! declare_combined_late_lint_pass {
|
||||
$($passes: $constructor,)*
|
||||
}
|
||||
}
|
||||
|
||||
$v fn get_lints() -> LintArray {
|
||||
let mut lints = Vec::new();
|
||||
$(lints.extend_from_slice(&$passes::get_lints());)*
|
||||
lints
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name {
|
||||
@ -337,12 +366,6 @@ macro_rules! declare_combined_late_lint_pass {
|
||||
fn name(&self) -> &'static str {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn get_lints(&self) -> LintArray {
|
||||
let mut lints = Vec::new();
|
||||
$(lints.extend_from_slice(&self.$passes.get_lints());)*
|
||||
lints
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -454,6 +477,12 @@ macro_rules! declare_combined_early_lint_pass {
|
||||
$($passes: $constructor,)*
|
||||
}
|
||||
}
|
||||
|
||||
$v fn get_lints() -> LintArray {
|
||||
let mut lints = Vec::new();
|
||||
$(lints.extend_from_slice(&$passes::get_lints());)*
|
||||
lints
|
||||
}
|
||||
}
|
||||
|
||||
impl EarlyLintPass for $name {
|
||||
@ -464,12 +493,6 @@ macro_rules! declare_combined_early_lint_pass {
|
||||
fn name(&self) -> &'static str {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn get_lints(&self) -> LintArray {
|
||||
let mut lints = Vec::new();
|
||||
$(lints.extend_from_slice(&self.$passes.get_lints());)*
|
||||
lints
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -649,9 +672,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
|
||||
};
|
||||
|
||||
// Check for future incompatibility lints and issue a stronger warning.
|
||||
let lints = sess.lint_store.borrow();
|
||||
let lint_id = LintId::of(lint);
|
||||
let future_incompatible = lints.future_incompatible(lint_id);
|
||||
let future_incompatible = lint.future_incompatible;
|
||||
|
||||
// If this code originates in a foreign macro, aka something that this crate
|
||||
// did not itself author, then it's likely that there's nothing this crate
|
||||
@ -755,13 +777,15 @@ pub fn maybe_lint_level_root(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
|
||||
|
||||
fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
let store = &tcx.lint_store;
|
||||
let mut builder = LintLevelMapBuilder {
|
||||
levels: LintLevelSets::builder(tcx.sess),
|
||||
levels: LintLevelSets::builder(tcx.sess, &store),
|
||||
tcx: tcx,
|
||||
store: store,
|
||||
};
|
||||
let krate = tcx.hir().krate();
|
||||
|
||||
let push = builder.levels.push(&krate.attrs);
|
||||
let push = builder.levels.push(&krate.attrs, &store);
|
||||
builder.levels.register_id(hir::CRATE_HIR_ID);
|
||||
for macro_def in &krate.exported_macros {
|
||||
builder.levels.register_id(macro_def.hir_id);
|
||||
@ -772,19 +796,20 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap {
|
||||
tcx.arena.alloc(builder.levels.build_map())
|
||||
}
|
||||
|
||||
struct LintLevelMapBuilder<'tcx> {
|
||||
struct LintLevelMapBuilder<'a, 'tcx> {
|
||||
levels: levels::LintLevelsBuilder<'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
store: &'a LintStore,
|
||||
}
|
||||
|
||||
impl LintLevelMapBuilder<'tcx> {
|
||||
impl LintLevelMapBuilder<'_, '_> {
|
||||
fn with_lint_attrs<F>(&mut self,
|
||||
id: hir::HirId,
|
||||
attrs: &[ast::Attribute],
|
||||
f: F)
|
||||
where F: FnOnce(&mut Self)
|
||||
{
|
||||
let push = self.levels.push(attrs);
|
||||
let push = self.levels.push(attrs, self.store);
|
||||
if push.changed {
|
||||
self.levels.register_id(id);
|
||||
}
|
||||
@ -793,7 +818,7 @@ impl LintLevelMapBuilder<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
|
||||
impl intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> {
|
||||
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
|
||||
intravisit::NestedVisitorMap::All(&self.tcx.hir())
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use crate::util::common::{duration_to_secs_str, ErrorReported};
|
||||
|
||||
use rustc_data_structures::base_n;
|
||||
use rustc_data_structures::sync::{
|
||||
self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, Ordering,
|
||||
self, Lrc, Lock, OneThread, Once, AtomicU64, AtomicUsize, Ordering,
|
||||
Ordering::SeqCst,
|
||||
};
|
||||
|
||||
@ -77,9 +77,11 @@ pub struct Session {
|
||||
/// if the value stored here has been affected by path remapping.
|
||||
pub working_dir: (PathBuf, bool),
|
||||
|
||||
// FIXME: `lint_store` and `buffered_lints` are not thread-safe,
|
||||
// but are only used in a single thread.
|
||||
pub lint_store: RwLock<lint::LintStore>,
|
||||
/// This is intended to be used from a single thread.
|
||||
///
|
||||
/// FIXME: there was a previous comment about this not being thread safe,
|
||||
/// but it's not clear how or why that's the case. The LintBuffer itself is certainly thread
|
||||
/// safe at least from a "Rust safety" standpoint.
|
||||
pub buffered_lints: Lock<Option<lint::LintBuffer>>,
|
||||
|
||||
/// Set of `(DiagnosticId, Option<Span>, message)` tuples tracking
|
||||
@ -1213,7 +1215,6 @@ fn build_session_(
|
||||
sysroot,
|
||||
local_crate_source_file,
|
||||
working_dir,
|
||||
lint_store: RwLock::new(lint::LintStore::new()),
|
||||
buffered_lints: Lock::new(Some(Default::default())),
|
||||
one_time_diagnostics: Default::default(),
|
||||
plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
|
||||
|
@ -1031,6 +1031,8 @@ pub struct GlobalCtxt<'tcx> {
|
||||
|
||||
pub sess: &'tcx Session,
|
||||
|
||||
pub lint_store: Lrc<lint::LintStore>,
|
||||
|
||||
pub dep_graph: DepGraph,
|
||||
|
||||
pub prof: SelfProfilerRef,
|
||||
@ -1192,6 +1194,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// reference to the context, to allow formatting values that need it.
|
||||
pub fn create_global_ctxt(
|
||||
s: &'tcx Session,
|
||||
lint_store: Lrc<lint::LintStore>,
|
||||
cstore: &'tcx CrateStoreDyn,
|
||||
local_providers: ty::query::Providers<'tcx>,
|
||||
extern_providers: ty::query::Providers<'tcx>,
|
||||
@ -1255,6 +1258,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
GlobalCtxt {
|
||||
sess: s,
|
||||
lint_store,
|
||||
cstore,
|
||||
arena: WorkerLocal::new(|_| Arena::default()),
|
||||
interners,
|
||||
|
@ -16,6 +16,7 @@ log = "0.4"
|
||||
env_logger = { version = "0.7", default-features = false }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_lint = { path = "../librustc_lint" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
errors = { path = "../librustc_errors", package = "rustc_errors" }
|
||||
rustc_metadata = { path = "../librustc_metadata" }
|
||||
|
@ -106,6 +106,8 @@ pub fn abort_on_err<T>(result: Result<T, ErrorReported>, sess: &Session) -> T {
|
||||
pub trait Callbacks {
|
||||
/// Called before creating the compiler instance
|
||||
fn config(&mut self, _config: &mut interface::Config) {}
|
||||
/// Called early during compilation to allow other drivers to easily register lints.
|
||||
fn extra_lints(&mut self, _ls: &mut lint::LintStore) {}
|
||||
/// Called after parsing. Return value instructs the compiler whether to
|
||||
/// continue the compilation afterwards (defaults to `Compilation::Continue`)
|
||||
fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation {
|
||||
@ -182,6 +184,7 @@ pub fn run_compiler(
|
||||
stderr: None,
|
||||
crate_name: None,
|
||||
lint_caps: Default::default(),
|
||||
register_lints: None,
|
||||
};
|
||||
callbacks.config(&mut config);
|
||||
config
|
||||
@ -202,9 +205,13 @@ pub fn run_compiler(
|
||||
interface::run_compiler(config, |compiler| {
|
||||
let sopts = &compiler.session().opts;
|
||||
if sopts.describe_lints {
|
||||
let lint_store = rustc_lint::new_lint_store(
|
||||
sopts.debugging_opts.no_interleave_lints,
|
||||
compiler.session().unstable_options(),
|
||||
);
|
||||
describe_lints(
|
||||
compiler.session(),
|
||||
&*compiler.session().lint_store.borrow(),
|
||||
&lint_store,
|
||||
false
|
||||
);
|
||||
return;
|
||||
@ -255,6 +262,7 @@ pub fn run_compiler(
|
||||
stderr: None,
|
||||
crate_name: None,
|
||||
lint_caps: Default::default(),
|
||||
register_lints: None,
|
||||
};
|
||||
|
||||
callbacks.config(&mut config);
|
||||
@ -321,12 +329,14 @@ pub fn run_compiler(
|
||||
return sess.compile_status();
|
||||
}
|
||||
|
||||
compiler.register_plugins()?;
|
||||
{
|
||||
let (_, _, lint_store) = &*compiler.register_plugins()?.peek();
|
||||
|
||||
// Lint plugins are registered; now we can process command line flags.
|
||||
if sess.opts.describe_lints {
|
||||
describe_lints(&sess, &sess.lint_store.borrow(), true);
|
||||
return sess.compile_status();
|
||||
// Lint plugins are registered; now we can process command line flags.
|
||||
if sess.opts.describe_lints {
|
||||
describe_lints(&sess, &lint_store, true);
|
||||
return sess.compile_status();
|
||||
}
|
||||
}
|
||||
|
||||
compiler.expansion()?;
|
||||
@ -835,8 +845,7 @@ Available lint options:
|
||||
|
||||
");
|
||||
|
||||
fn sort_lints(sess: &Session, lints: Vec<(&'static Lint, bool)>) -> Vec<&'static Lint> {
|
||||
let mut lints: Vec<_> = lints.into_iter().map(|(x, _)| x).collect();
|
||||
fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
|
||||
// The sort doesn't case-fold but it's doubtful we care.
|
||||
lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess), x.name));
|
||||
lints
|
||||
@ -852,7 +861,7 @@ Available lint options:
|
||||
let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints()
|
||||
.iter()
|
||||
.cloned()
|
||||
.partition(|&(_, p)| p);
|
||||
.partition(|&lint| lint.is_plugin);
|
||||
let plugin = sort_lints(sess, plugin);
|
||||
let builtin = sort_lints(sess, builtin);
|
||||
|
||||
|
@ -39,6 +39,7 @@ pub struct Compiler {
|
||||
pub(crate) queries: Queries,
|
||||
pub(crate) cstore: Lrc<CStore>,
|
||||
pub(crate) crate_name: Option<String>,
|
||||
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
@ -137,6 +138,13 @@ pub struct Config {
|
||||
|
||||
pub crate_name: Option<String>,
|
||||
pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
|
||||
|
||||
/// This is a callback from the driver that is called when we're registering lints;
|
||||
/// it is called during plugin registration when we have the LintStore in a non-shared state.
|
||||
///
|
||||
/// Note that if you find a Some here you probably want to call that function in the new
|
||||
/// function being registered.
|
||||
pub register_lints: Option<Box<dyn Fn(&Session, &mut lint::LintStore) + Send + Sync>>,
|
||||
}
|
||||
|
||||
pub fn run_compiler_in_existing_thread_pool<F, R>(config: Config, f: F) -> R
|
||||
@ -165,6 +173,7 @@ where
|
||||
output_file: config.output_file,
|
||||
queries: Default::default(),
|
||||
crate_name: config.crate_name,
|
||||
register_lints: config.register_lints,
|
||||
};
|
||||
|
||||
let _sess_abort_error = OnDrop(|| {
|
||||
|
@ -117,6 +117,7 @@ declare_box_region_type!(
|
||||
/// Returns `None` if we're aborting after handling -W help.
|
||||
pub fn configure_and_expand(
|
||||
sess: Lrc<Session>,
|
||||
lint_store: Lrc<lint::LintStore>,
|
||||
cstore: Lrc<CStore>,
|
||||
krate: ast::Crate,
|
||||
crate_name: &str,
|
||||
@ -134,6 +135,7 @@ pub fn configure_and_expand(
|
||||
let resolver_arenas = Resolver::arenas();
|
||||
let res = configure_and_expand_inner(
|
||||
sess,
|
||||
&lint_store,
|
||||
&*cstore,
|
||||
krate,
|
||||
&crate_name,
|
||||
@ -225,9 +227,10 @@ pub struct PluginInfo {
|
||||
pub fn register_plugins<'a>(
|
||||
sess: &'a Session,
|
||||
cstore: &'a CStore,
|
||||
register_lints: impl Fn(&Session, &mut lint::LintStore),
|
||||
mut krate: ast::Crate,
|
||||
crate_name: &str,
|
||||
) -> Result<(ast::Crate, PluginInfo)> {
|
||||
) -> Result<(ast::Crate, PluginInfo, Lrc<lint::LintStore>)> {
|
||||
krate = time(sess, "attributes injection", || {
|
||||
syntax_ext::cmdline_attrs::inject(
|
||||
krate, &sess.parse_sess, &sess.opts.debugging_opts.crate_attr
|
||||
@ -278,7 +281,14 @@ pub fn register_plugins<'a>(
|
||||
)
|
||||
});
|
||||
|
||||
let mut registry = Registry::new(sess, krate.span);
|
||||
let mut lint_store = rustc_lint::new_lint_store(
|
||||
sess.opts.debugging_opts.no_interleave_lints,
|
||||
sess.unstable_options(),
|
||||
);
|
||||
|
||||
(register_lints)(&sess, &mut lint_store);
|
||||
|
||||
let mut registry = Registry::new(sess, &mut lint_store, krate.span);
|
||||
|
||||
time(sess, "plugin registration", || {
|
||||
for registrar in registrars {
|
||||
@ -289,34 +299,20 @@ pub fn register_plugins<'a>(
|
||||
|
||||
let Registry {
|
||||
syntax_exts,
|
||||
early_lint_passes,
|
||||
late_lint_passes,
|
||||
lint_groups,
|
||||
llvm_passes,
|
||||
attributes,
|
||||
..
|
||||
} = registry;
|
||||
|
||||
let mut ls = sess.lint_store.borrow_mut();
|
||||
for pass in early_lint_passes {
|
||||
ls.register_early_pass(Some(sess), true, false, pass);
|
||||
}
|
||||
for pass in late_lint_passes {
|
||||
ls.register_late_pass(Some(sess), true, false, false, pass);
|
||||
}
|
||||
|
||||
for (name, (to, deprecated_name)) in lint_groups {
|
||||
ls.register_group(Some(sess), true, name, deprecated_name, to);
|
||||
}
|
||||
|
||||
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
|
||||
*sess.plugin_attributes.borrow_mut() = attributes;
|
||||
|
||||
Ok((krate, PluginInfo { syntax_exts }))
|
||||
Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store)))
|
||||
}
|
||||
|
||||
fn configure_and_expand_inner<'a>(
|
||||
sess: &'a Session,
|
||||
lint_store: &'a lint::LintStore,
|
||||
cstore: &'a CStore,
|
||||
mut krate: ast::Crate,
|
||||
crate_name: &str,
|
||||
@ -327,6 +323,7 @@ fn configure_and_expand_inner<'a>(
|
||||
time(sess, "pre-AST-expansion lint checks", || {
|
||||
lint::check_ast_crate(
|
||||
sess,
|
||||
lint_store,
|
||||
&krate,
|
||||
true,
|
||||
rustc_lint::BuiltinCombinedPreExpansionLintPass::new());
|
||||
@ -536,6 +533,7 @@ fn configure_and_expand_inner<'a>(
|
||||
|
||||
pub fn lower_to_hir(
|
||||
sess: &Session,
|
||||
lint_store: &lint::LintStore,
|
||||
cstore: &CStore,
|
||||
resolver: &mut Resolver<'_>,
|
||||
dep_graph: &DepGraph,
|
||||
@ -554,7 +552,13 @@ pub fn lower_to_hir(
|
||||
});
|
||||
|
||||
time(sess, "early lint checks", || {
|
||||
lint::check_ast_crate(sess, &krate, false, rustc_lint::BuiltinCombinedEarlyLintPass::new())
|
||||
lint::check_ast_crate(
|
||||
sess,
|
||||
lint_store,
|
||||
&krate,
|
||||
false,
|
||||
rustc_lint::BuiltinCombinedEarlyLintPass::new(),
|
||||
)
|
||||
});
|
||||
|
||||
// Discard hygiene data, which isn't required after lowering to HIR.
|
||||
@ -817,6 +821,7 @@ impl BoxedGlobalCtxt {
|
||||
|
||||
pub fn create_global_ctxt(
|
||||
compiler: &Compiler,
|
||||
lint_store: Lrc<lint::LintStore>,
|
||||
mut hir_forest: hir::map::Forest,
|
||||
defs: hir::map::Definitions,
|
||||
resolutions: Resolutions,
|
||||
@ -854,6 +859,7 @@ pub fn create_global_ctxt(
|
||||
|
||||
let gcx = TyCtxt::create_global_ctxt(
|
||||
sess,
|
||||
lint_store,
|
||||
cstore,
|
||||
local_providers,
|
||||
extern_providers,
|
||||
|
@ -2,9 +2,13 @@ use crate::interface::{Compiler, Result};
|
||||
use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo};
|
||||
|
||||
use rustc_incremental::DepGraphFuture;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc::session::config::{OutputFilenames, OutputType};
|
||||
use rustc::util::common::{time, ErrorReported};
|
||||
use rustc::hir;
|
||||
use rustc::lint;
|
||||
use rustc::session::Session;
|
||||
use rustc::lint::LintStore;
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use rustc::ty::steal::Steal;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
@ -74,8 +78,8 @@ pub(crate) struct Queries {
|
||||
dep_graph_future: Query<Option<DepGraphFuture>>,
|
||||
parse: Query<ast::Crate>,
|
||||
crate_name: Query<String>,
|
||||
register_plugins: Query<(ast::Crate, PluginInfo)>,
|
||||
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>)>,
|
||||
register_plugins: Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>,
|
||||
expansion: Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>,
|
||||
dep_graph: Query<DepGraph>,
|
||||
lower_to_hir: Query<(Steal<hir::map::Forest>, ExpansionResult)>,
|
||||
prepare_outputs: Query<OutputFilenames>,
|
||||
@ -106,14 +110,19 @@ impl Compiler {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo)>> {
|
||||
pub fn register_plugins(&self) -> Result<&Query<(ast::Crate, PluginInfo, Lrc<LintStore>)>> {
|
||||
self.queries.register_plugins.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let krate = self.parse()?.take();
|
||||
|
||||
let empty: &(dyn Fn(&Session, &mut lint::LintStore) + Sync + Send) = &|_, _| {};
|
||||
let result = passes::register_plugins(
|
||||
self.session(),
|
||||
self.cstore(),
|
||||
self.register_lints
|
||||
.as_ref()
|
||||
.map(|p| &**p)
|
||||
.unwrap_or_else(|| empty),
|
||||
krate,
|
||||
&crate_name,
|
||||
);
|
||||
@ -148,17 +157,20 @@ impl Compiler {
|
||||
|
||||
pub fn expansion(
|
||||
&self
|
||||
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>)>> {
|
||||
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
|
||||
self.queries.expansion.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let (krate, plugin_info) = self.register_plugins()?.take();
|
||||
let (krate, plugin_info, lint_store) = self.register_plugins()?.take();
|
||||
passes::configure_and_expand(
|
||||
self.sess.clone(),
|
||||
lint_store.clone(),
|
||||
self.cstore().clone(),
|
||||
krate,
|
||||
&crate_name,
|
||||
plugin_info,
|
||||
).map(|(krate, resolver)| (krate, Steal::new(Rc::new(RefCell::new(resolver)))))
|
||||
).map(|(krate, resolver)| {
|
||||
(krate, Steal::new(Rc::new(RefCell::new(resolver))), lint_store)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -185,9 +197,11 @@ impl Compiler {
|
||||
let peeked = expansion_result.peek();
|
||||
let krate = &peeked.0;
|
||||
let resolver = peeked.1.steal();
|
||||
let lint_store = &peeked.2;
|
||||
let hir = Steal::new(resolver.borrow_mut().access(|resolver| {
|
||||
passes::lower_to_hir(
|
||||
self.session(),
|
||||
lint_store,
|
||||
self.cstore(),
|
||||
resolver,
|
||||
&*self.dep_graph()?.peek(),
|
||||
@ -212,11 +226,13 @@ impl Compiler {
|
||||
self.queries.global_ctxt.compute(|| {
|
||||
let crate_name = self.crate_name()?.peek().clone();
|
||||
let outputs = self.prepare_outputs()?.peek().clone();
|
||||
let lint_store = self.expansion()?.peek().2.clone();
|
||||
let hir = self.lower_to_hir()?;
|
||||
let hir = hir.peek();
|
||||
let (ref hir_forest, ref expansion) = *hir;
|
||||
Ok(passes::create_global_ctxt(
|
||||
self,
|
||||
lint_store,
|
||||
hir_forest.steal(),
|
||||
expansion.defs.steal(),
|
||||
expansion.resolutions.steal(),
|
||||
|
@ -13,7 +13,6 @@ use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
|
||||
use rustc_errors::registry::Registry;
|
||||
use rustc_lint;
|
||||
use rustc_metadata::dynamic_lib::DynamicLibrary;
|
||||
use rustc_mir;
|
||||
use rustc_passes;
|
||||
@ -108,11 +107,6 @@ pub fn create_session(
|
||||
|
||||
let codegen_backend = get_codegen_backend(&sess);
|
||||
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
if sess.unstable_options() {
|
||||
rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
}
|
||||
|
||||
let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
|
||||
add_configuration(&mut cfg, &sess, &*codegen_backend);
|
||||
sess.parse_sess.config = cfg;
|
||||
|
@ -27,6 +27,7 @@ use rustc::hir::def::{Res, DefKind};
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::ty::{self, Ty, TyCtxt, layout::VariantIdx};
|
||||
use rustc::{lint, util};
|
||||
use rustc::lint::FutureIncompatibleInfo;
|
||||
use hir::Node;
|
||||
use util::nodemap::HirIdSet;
|
||||
use lint::{LateContext, LintContext, LintArray};
|
||||
@ -280,7 +281,7 @@ declare_lint! {
|
||||
pub MISSING_DOCS,
|
||||
Allow,
|
||||
"detects missing documentation for public members",
|
||||
report_in_external_macro: true
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
pub struct MissingDoc {
|
||||
@ -601,7 +602,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
|
||||
declare_lint! {
|
||||
pub ANONYMOUS_PARAMETERS,
|
||||
Allow,
|
||||
"detects anonymous parameters"
|
||||
"detects anonymous parameters",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
@ -1344,7 +1349,7 @@ declare_lint! {
|
||||
UNNAMEABLE_TEST_ITEMS,
|
||||
Warn,
|
||||
"detects an item that cannot be named being marked as `#[test_case]`",
|
||||
report_in_external_macro: true
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
pub struct UnnameableTestItems {
|
||||
@ -1393,7 +1398,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
|
||||
declare_lint! {
|
||||
pub KEYWORD_IDENTS,
|
||||
Allow,
|
||||
"detects edition keywords being used as an identifier"
|
||||
"detects edition keywords being used as an identifier",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
|
@ -33,27 +33,21 @@ use rustc::lint;
|
||||
use rustc::lint::{EarlyContext, LateContext, LateLintPass, EarlyLintPass, LintPass, LintArray};
|
||||
use rustc::lint::builtin::{
|
||||
BARE_TRAIT_OBJECTS,
|
||||
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
|
||||
ELIDED_LIFETIMES_IN_PATHS,
|
||||
EXPLICIT_OUTLIVES_REQUIREMENTS,
|
||||
INTRA_DOC_LINK_RESOLUTION_FAILURE,
|
||||
MISSING_DOC_CODE_EXAMPLES,
|
||||
PRIVATE_DOC_TESTS,
|
||||
parser::ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
};
|
||||
use rustc::session;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::query::Providers;
|
||||
use rustc::ty::TyCtxt;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::edition::Edition;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use session::Session;
|
||||
use lint::LintId;
|
||||
use lint::FutureIncompatibleInfo;
|
||||
|
||||
use redundant_semicolon::*;
|
||||
use nonstandard_style::*;
|
||||
@ -192,59 +186,60 @@ late_lint_passes!(declare_combined_late_pass, [pub BuiltinCombinedLateLintPass])
|
||||
|
||||
late_lint_mod_passes!(declare_combined_late_pass, [BuiltinCombinedModuleLateLintPass]);
|
||||
|
||||
pub fn new_lint_store(no_interleave_lints: bool, internal_lints: bool) -> lint::LintStore {
|
||||
let mut lint_store = lint::LintStore::new();
|
||||
|
||||
register_builtins(&mut lint_store, no_interleave_lints);
|
||||
if internal_lints {
|
||||
register_internals(&mut lint_store);
|
||||
}
|
||||
|
||||
lint_store
|
||||
}
|
||||
|
||||
/// Tell the `LintStore` about all the built-in lints (the ones
|
||||
/// defined in this crate and the ones defined in
|
||||
/// `rustc::lint::builtin`).
|
||||
pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
fn register_builtins(store: &mut lint::LintStore, no_interleave_lints: bool) {
|
||||
macro_rules! add_lint_group {
|
||||
($sess:ident, $name:expr, $($lint:ident),*) => (
|
||||
store.register_group($sess, false, $name, None, vec![$(LintId::of($lint)),*]);
|
||||
($name:expr, $($lint:ident),*) => (
|
||||
store.register_group(false, $name, None, vec![$(LintId::of($lint)),*]);
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! register_pass {
|
||||
($method:ident, $constructor:expr, [$($args:expr),*]) => (
|
||||
store.$method(sess, false, false, $($args,)* box $constructor);
|
||||
($method:ident, $ty:ident, $constructor:expr) => (
|
||||
store.register_lints(&$ty::get_lints());
|
||||
store.$method(|| box $constructor);
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! register_passes {
|
||||
([$method:ident, $args:tt], [$($passes:ident: $constructor:expr,)*]) => (
|
||||
($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
|
||||
$(
|
||||
register_pass!($method, $constructor, $args);
|
||||
register_pass!($method, $passes, $constructor);
|
||||
)*
|
||||
)
|
||||
}
|
||||
|
||||
if sess.map(|sess| sess.opts.debugging_opts.no_interleave_lints).unwrap_or(false) {
|
||||
pre_expansion_lint_passes!(register_passes, [register_pre_expansion_pass, []]);
|
||||
early_lint_passes!(register_passes, [register_early_pass, []]);
|
||||
late_lint_passes!(register_passes, [register_late_pass, [false]]);
|
||||
late_lint_mod_passes!(register_passes, [register_late_pass, [true]]);
|
||||
if no_interleave_lints {
|
||||
pre_expansion_lint_passes!(register_passes, register_pre_expansion_pass);
|
||||
early_lint_passes!(register_passes, register_early_pass);
|
||||
late_lint_passes!(register_passes, register_late_pass);
|
||||
late_lint_mod_passes!(register_passes, register_late_mod_pass);
|
||||
} else {
|
||||
store.register_pre_expansion_pass(
|
||||
sess,
|
||||
false,
|
||||
true,
|
||||
box BuiltinCombinedPreExpansionLintPass::new()
|
||||
);
|
||||
store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new());
|
||||
store.register_late_pass(
|
||||
sess, false, true, true, box BuiltinCombinedModuleLateLintPass::new()
|
||||
);
|
||||
store.register_late_pass(
|
||||
sess, false, true, false, box BuiltinCombinedLateLintPass::new()
|
||||
);
|
||||
store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
|
||||
store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
|
||||
store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
|
||||
store.register_lints(&BuiltinCombinedLateLintPass::get_lints());
|
||||
}
|
||||
|
||||
add_lint_group!(sess,
|
||||
"nonstandard_style",
|
||||
add_lint_group!("nonstandard_style",
|
||||
NON_CAMEL_CASE_TYPES,
|
||||
NON_SNAKE_CASE,
|
||||
NON_UPPER_CASE_GLOBALS);
|
||||
|
||||
add_lint_group!(sess,
|
||||
"unused",
|
||||
add_lint_group!("unused",
|
||||
UNUSED_IMPORTS,
|
||||
UNUSED_VARIABLES,
|
||||
UNUSED_ASSIGNMENTS,
|
||||
@ -265,8 +260,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
UNUSED_LABELS,
|
||||
UNUSED_PARENS);
|
||||
|
||||
add_lint_group!(sess,
|
||||
"rust_2018_idioms",
|
||||
add_lint_group!("rust_2018_idioms",
|
||||
BARE_TRAIT_OBJECTS,
|
||||
UNUSED_EXTERN_CRATES,
|
||||
ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
|
||||
@ -282,165 +276,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
// MACRO_USE_EXTERN_CRATE,
|
||||
);
|
||||
|
||||
add_lint_group!(sess,
|
||||
"rustdoc",
|
||||
add_lint_group!("rustdoc",
|
||||
INTRA_DOC_LINK_RESOLUTION_FAILURE,
|
||||
MISSING_DOC_CODE_EXAMPLES,
|
||||
PRIVATE_DOC_TESTS);
|
||||
|
||||
// Guidelines for creating a future incompatibility lint:
|
||||
//
|
||||
// - Create a lint defaulting to warn as normal, with ideally the same error
|
||||
// message you would normally give
|
||||
// - Add a suitable reference, typically an RFC or tracking issue. Go ahead
|
||||
// and include the full URL, sort items in ascending order of issue numbers.
|
||||
// - Later, change lint to error
|
||||
// - Eventually, remove lint
|
||||
store.register_future_incompatible(sess, vec![
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(PRIVATE_IN_PUBLIC),
|
||||
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),
|
||||
reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
|
||||
reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(DUPLICATE_MACRO_EXPORTS),
|
||||
reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(KEYWORD_IDENTS),
|
||||
reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(SAFE_EXTERN_STATICS),
|
||||
reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
|
||||
reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP),
|
||||
reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
|
||||
reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(MISSING_FRAGMENT_SPECIFIER),
|
||||
reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
|
||||
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(ANONYMOUS_PARAMETERS),
|
||||
reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
|
||||
reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
|
||||
reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(SAFE_PACKED_BORROWS),
|
||||
reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(ORDER_DEPENDENT_TRAIT_OBJECTS),
|
||||
reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
|
||||
reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(UNSTABLE_NAME_COLLISIONS),
|
||||
reference: "issue #48919 <https://github.com/rust-lang/rust/issues/48919>",
|
||||
edition: None,
|
||||
// Note: this item represents future incompatibility of all unstable functions in the
|
||||
// standard library, and thus should never be removed or changed to an error.
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE),
|
||||
reference: "issue #53130 <https://github.com/rust-lang/rust/issues/53130>",
|
||||
edition: Some(Edition::Edition2018),
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(WHERE_CLAUSES_OBJECT_SAFETY),
|
||||
reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK),
|
||||
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS),
|
||||
reference: "issue #52234 <https://github.com/rust-lang/rust/issues/52234>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(ILL_FORMED_ATTRIBUTE_INPUT),
|
||||
reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS),
|
||||
reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(NESTED_IMPL_TRAIT),
|
||||
reference: "issue #59014 <https://github.com/rust-lang/rust/issues/59014>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(MUTABLE_BORROW_RESERVATION_CONFLICT),
|
||||
reference: "issue #59159 <https://github.com/rust-lang/rust/issues/59159>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(INDIRECT_STRUCTURAL_MATCH),
|
||||
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
|
||||
edition: None,
|
||||
},
|
||||
FutureIncompatibleInfo {
|
||||
id: LintId::of(SOFT_UNSTABLE),
|
||||
reference: "issue #64266 <https://github.com/rust-lang/rust/issues/64266>",
|
||||
edition: None,
|
||||
},
|
||||
]);
|
||||
|
||||
// Register renamed and removed lints.
|
||||
store.register_renamed("single_use_lifetime", "single_use_lifetimes");
|
||||
store.register_renamed("elided_lifetime_in_path", "elided_lifetimes_in_paths");
|
||||
@ -496,12 +336,14 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
"converted into hard error, see https://github.com/rust-lang/rust/issues/46205");
|
||||
}
|
||||
|
||||
pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
|
||||
store.register_early_pass(sess, false, false, box LintPassImpl);
|
||||
store.register_late_pass(sess, false, false, false, box TyTyKind);
|
||||
fn register_internals(store: &mut lint::LintStore) {
|
||||
store.register_lints(&DefaultHashTypes::get_lints());
|
||||
store.register_early_pass(|| box DefaultHashTypes::new());
|
||||
store.register_lints(&LintPassImpl::get_lints());
|
||||
store.register_early_pass(|| box LintPassImpl);
|
||||
store.register_lints(&TyTyKind::get_lints());
|
||||
store.register_late_pass(|| box TyTyKind);
|
||||
store.register_group(
|
||||
sess,
|
||||
false,
|
||||
"rustc::internal",
|
||||
None,
|
||||
|
@ -25,7 +25,7 @@ declare_lint! {
|
||||
pub UNUSED_MUST_USE,
|
||||
Warn,
|
||||
"unused result of a type flagged as `#[must_use]`",
|
||||
report_in_external_macro: true
|
||||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
|
@ -1,8 +1,7 @@
|
||||
//! Used by plugin crates to tell `rustc` about the plugins they provide.
|
||||
|
||||
use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
|
||||
use rustc::lint::LintStore;
|
||||
use rustc::session::Session;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
||||
use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
|
||||
use syntax_expand::base::MacroExpanderFn;
|
||||
@ -26,6 +25,9 @@ pub struct Registry<'a> {
|
||||
/// from the plugin registrar.
|
||||
pub sess: &'a Session,
|
||||
|
||||
/// The `LintStore` allows plugins to register new lints.
|
||||
pub lint_store: &'a mut LintStore,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub args_hidden: Option<Vec<ast::NestedMetaItem>>,
|
||||
|
||||
@ -35,15 +37,6 @@ pub struct Registry<'a> {
|
||||
#[doc(hidden)]
|
||||
pub syntax_exts: Vec<NamedSyntaxExtension>,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub early_lint_passes: Vec<EarlyLintPassObject>,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub late_lint_passes: Vec<LateLintPassObject>,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub lint_groups: FxHashMap<&'static str, (Vec<LintId>, Option<&'static str>)>,
|
||||
|
||||
#[doc(hidden)]
|
||||
pub llvm_passes: Vec<String>,
|
||||
|
||||
@ -53,15 +46,13 @@ pub struct Registry<'a> {
|
||||
|
||||
impl<'a> Registry<'a> {
|
||||
#[doc(hidden)]
|
||||
pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
|
||||
pub fn new(sess: &'a Session, lint_store: &'a mut LintStore, krate_span: Span) -> Registry<'a> {
|
||||
Registry {
|
||||
sess,
|
||||
lint_store,
|
||||
args_hidden: None,
|
||||
krate_span,
|
||||
syntax_exts: vec![],
|
||||
early_lint_passes: vec![],
|
||||
late_lint_passes: vec![],
|
||||
lint_groups: FxHashMap::default(),
|
||||
llvm_passes: vec![],
|
||||
attributes: vec![],
|
||||
}
|
||||
@ -99,27 +90,6 @@ impl<'a> Registry<'a> {
|
||||
self.register_syntax_extension(Symbol::intern(name), ext);
|
||||
}
|
||||
|
||||
/// Register a compiler lint pass.
|
||||
pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) {
|
||||
self.early_lint_passes.push(lint_pass);
|
||||
}
|
||||
|
||||
/// Register a compiler lint pass.
|
||||
pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) {
|
||||
self.late_lint_passes.push(lint_pass);
|
||||
}
|
||||
/// Register a lint group.
|
||||
pub fn register_lint_group(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
deprecated_name: Option<&'static str>,
|
||||
to: Vec<&'static Lint>
|
||||
) {
|
||||
self.lint_groups.insert(name,
|
||||
(to.into_iter().map(|x| LintId::of(x)).collect(),
|
||||
deprecated_name));
|
||||
}
|
||||
|
||||
/// Register an LLVM pass.
|
||||
///
|
||||
/// Registration with LLVM itself is handled through static C++ objects with
|
||||
|
@ -5,7 +5,7 @@ use rustc::hir::HirId;
|
||||
use rustc::middle::cstore::CrateStore;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::ty::{Ty, TyCtxt};
|
||||
use rustc::lint::{self, LintPass};
|
||||
use rustc::lint;
|
||||
use rustc::session::config::ErrorOutputType;
|
||||
use rustc::session::DiagnosticOutput;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
@ -273,10 +273,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
||||
whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
|
||||
|
||||
let lints = || {
|
||||
lint::builtin::HardwiredLints
|
||||
.get_lints()
|
||||
lint::builtin::HardwiredLints::get_lints()
|
||||
.into_iter()
|
||||
.chain(rustc_lint::SoftLints.get_lints().into_iter())
|
||||
.chain(rustc_lint::SoftLints::get_lints().into_iter())
|
||||
};
|
||||
|
||||
let lint_opts = lints().filter_map(|lint| {
|
||||
@ -339,6 +338,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
|
||||
stderr: None,
|
||||
crate_name,
|
||||
lint_caps,
|
||||
register_lints: None,
|
||||
};
|
||||
|
||||
interface::run_compiler_in_existing_thread_pool(config, |compiler| {
|
||||
|
@ -77,6 +77,7 @@ pub fn run(options: Options) -> i32 {
|
||||
stderr: None,
|
||||
crate_name: options.crate_name.clone(),
|
||||
lint_caps: Default::default(),
|
||||
register_lints: None,
|
||||
};
|
||||
|
||||
let mut test_args = options.test_args.clone();
|
||||
|
@ -59,6 +59,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
|
||||
stderr: None,
|
||||
crate_name: None,
|
||||
lint_caps: Default::default(),
|
||||
register_lints: None,
|
||||
};
|
||||
|
||||
interface::run_compiler(config, |compiler| {
|
||||
|
@ -15,15 +15,14 @@ use syntax::symbol::Symbol;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit;
|
||||
use rustc::hir::map as hir_map;
|
||||
use hir::Node;
|
||||
use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
|
||||
use rustc::ty;
|
||||
use syntax::{ast, source_map};
|
||||
use syntax::source_map;
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_late_lint_pass(box MissingWhitelistedAttrPass);
|
||||
reg.lint_store.register_lints(&[&MISSING_WHITELISTED_ATTR]);
|
||||
reg.lint_store.register_late_pass(|| box MissingWhitelistedAttrPass);
|
||||
reg.register_attribute(Symbol::intern("whitelisted_attr"), Whitelisted);
|
||||
}
|
||||
|
||||
|
@ -7,24 +7,20 @@
|
||||
extern crate rustc_driver;
|
||||
extern crate syntax;
|
||||
|
||||
use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
|
||||
use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass};
|
||||
use rustc_driver::plugin::Registry;
|
||||
use rustc::hir;
|
||||
use syntax::attr;
|
||||
use syntax::symbol::Symbol;
|
||||
|
||||
macro_rules! fake_lint_pass {
|
||||
($struct:ident, $lints:expr, $($attr:expr),*) => {
|
||||
($struct:ident, $($attr:expr),*) => {
|
||||
struct $struct;
|
||||
|
||||
impl LintPass for $struct {
|
||||
fn name(&self) -> &'static str {
|
||||
stringify!($struct)
|
||||
}
|
||||
|
||||
fn get_lints(&self) -> LintArray {
|
||||
$lints
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct {
|
||||
@ -49,25 +45,29 @@ declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]");
|
||||
|
||||
fake_lint_pass! {
|
||||
PassOkay,
|
||||
lint_array!(CRATE_NOT_OKAY), // Single lint
|
||||
Symbol::intern("rustc_crate_okay")
|
||||
}
|
||||
|
||||
fake_lint_pass! {
|
||||
PassRedBlue,
|
||||
lint_array!(CRATE_NOT_RED, CRATE_NOT_BLUE), // Multiple lints
|
||||
Symbol::intern("rustc_crate_red"), Symbol::intern("rustc_crate_blue")
|
||||
}
|
||||
|
||||
fake_lint_pass! {
|
||||
PassGreyGreen,
|
||||
lint_array!(CRATE_NOT_GREY, CRATE_NOT_GREEN, ), // Trailing comma
|
||||
Symbol::intern("rustc_crate_grey"), Symbol::intern("rustc_crate_green")
|
||||
}
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_late_lint_pass(box PassOkay);
|
||||
reg.register_late_lint_pass(box PassRedBlue);
|
||||
reg.register_late_lint_pass(box PassGreyGreen);
|
||||
reg.lint_store.register_lints(&[
|
||||
&CRATE_NOT_OKAY,
|
||||
&CRATE_NOT_RED,
|
||||
&CRATE_NOT_BLUE,
|
||||
&CRATE_NOT_GREY,
|
||||
&CRATE_NOT_GREEN,
|
||||
]);
|
||||
reg.lint_store.register_late_pass(|| box PassOkay);
|
||||
reg.lint_store.register_late_pass(|| box PassRedBlue);
|
||||
reg.lint_store.register_late_pass(|| box PassGreyGreen);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
extern crate rustc_driver;
|
||||
extern crate syntax;
|
||||
|
||||
use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
|
||||
use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray};
|
||||
use rustc_driver::plugin::Registry;
|
||||
use rustc::hir;
|
||||
use syntax::attr;
|
||||
@ -32,5 +32,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_late_lint_pass(box Pass);
|
||||
reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]);
|
||||
reg.lint_store.register_late_pass(|| box Pass);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ extern crate rustc;
|
||||
extern crate rustc_driver;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
|
||||
use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LintArray, LintId};
|
||||
use rustc_driver::plugin::Registry;
|
||||
|
||||
declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
|
||||
@ -30,6 +30,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_late_lint_pass(box Pass);
|
||||
reg.register_lint_group("lint_me", None, vec![TEST_LINT, PLEASE_LINT]);
|
||||
reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]);
|
||||
reg.lint_store.register_late_pass(|| box Pass);
|
||||
reg.lint_store.register_group(true, "lint_me", None,
|
||||
vec![LintId::of(&TEST_LINT), LintId::of(&PLEASE_LINT)]);
|
||||
}
|
||||
|
@ -10,8 +10,7 @@ extern crate syntax;
|
||||
extern crate rustc;
|
||||
extern crate rustc_driver;
|
||||
|
||||
use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
|
||||
EarlyLintPassObject, LintArray};
|
||||
use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, LintArray};
|
||||
use rustc_driver::plugin::Registry;
|
||||
use syntax::ast;
|
||||
declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
|
||||
@ -28,5 +27,6 @@ impl EarlyLintPass for Pass {
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
|
||||
reg.lint_store.register_lints(&[&TEST_LINT]);
|
||||
reg.lint_store.register_early_pass(|| box Pass);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ extern crate syntax;
|
||||
extern crate rustc;
|
||||
extern crate rustc_driver;
|
||||
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
|
||||
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass, LintId};
|
||||
use rustc_driver::plugin::Registry;
|
||||
use syntax::ast;
|
||||
declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
|
||||
@ -40,6 +40,8 @@ impl EarlyLintPass for Pass {
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_early_lint_pass(box Pass);
|
||||
reg.register_lint_group("clippy::group", Some("clippy_group"), vec![TEST_LINT, TEST_GROUP]);
|
||||
reg.lint_store.register_lints(&[&TEST_RUSTC_TOOL_LINT, &TEST_LINT, &TEST_GROUP]);
|
||||
reg.lint_store.register_early_pass(|| box Pass);
|
||||
reg.lint_store.register_group(true, "clippy::group", Some("clippy_group"),
|
||||
vec![LintId::of(&TEST_LINT), LintId::of(&TEST_GROUP)]);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
extern crate rustc;
|
||||
|
||||
use rustc::lint::{LintArray, LintPass};
|
||||
use rustc::{declare_lint, declare_lint_pass, impl_lint_pass, lint_array};
|
||||
use rustc::{declare_lint, declare_lint_pass, impl_lint_pass};
|
||||
|
||||
declare_lint! {
|
||||
pub TEST_LINT,
|
||||
@ -17,10 +17,6 @@ declare_lint! {
|
||||
struct Foo;
|
||||
|
||||
impl LintPass for Foo { //~ERROR implementing `LintPass` by hand
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(TEST_LINT)
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"Foo"
|
||||
}
|
||||
@ -31,10 +27,6 @@ macro_rules! custom_lint_pass_macro {
|
||||
struct Custom;
|
||||
|
||||
impl LintPass for Custom { //~ERROR implementing `LintPass` by hand
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(TEST_LINT)
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"Custom"
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ LL | #![deny(rustc::lint_pass_impl_without_macro)]
|
||||
= help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
|
||||
|
||||
error: implementing `LintPass` by hand
|
||||
--> $DIR/lint_pass_impl_without_macro.rs:33:14
|
||||
--> $DIR/lint_pass_impl_without_macro.rs:29:14
|
||||
|
|
||||
LL | impl LintPass for Custom {
|
||||
| ^^^^^^^^
|
||||
|
Loading…
x
Reference in New Issue
Block a user