Skip to content

Allow lint passes to be bound by TyCtxt #101501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 8, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
@@ -50,6 +50,10 @@ use std::cell::Cell;
use std::iter;
use std::slice;

type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync;
type LateLintPassFactory =
dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::Send + sync::Sync;

/// Information about the registered lints.
///
/// This is basically the subset of `Context` that we can
@@ -64,11 +68,11 @@ pub struct LintStore {
/// 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.)
pub pre_expansion_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
pub early_passes: Vec<Box<dyn Fn() -> EarlyLintPassObject + sync::Send + sync::Sync>>,
pub late_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
pub pre_expansion_passes: Vec<Box<EarlyLintPassFactory>>,
pub early_passes: Vec<Box<EarlyLintPassFactory>>,
pub late_passes: Vec<Box<LateLintPassFactory>>,
/// This is unique in that we construct them per-module, so not once.
pub late_module_passes: Vec<Box<dyn Fn() -> LateLintPassObject + sync::Send + sync::Sync>>,
pub late_module_passes: Vec<Box<LateLintPassFactory>>,

/// Lints indexed by name.
by_name: FxHashMap<String, TargetLint>,
@@ -186,14 +190,20 @@ impl LintStore {

pub fn register_late_pass(
&mut self,
pass: impl Fn() -> LateLintPassObject + 'static + sync::Send + sync::Sync,
pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
+ '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,
pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx>
+ 'static
+ sync::Send
+ sync::Sync,
) {
self.late_module_passes.push(Box::new(pass));
}
@@ -558,7 +568,7 @@ pub trait LintPassObject: Sized {}

impl LintPassObject for EarlyLintPassObject {}

impl LintPassObject for LateLintPassObject {}
impl LintPassObject for LateLintPassObject<'_> {}

pub trait LintContext: Sized {
type PassObject: LintPassObject;
@@ -949,8 +959,8 @@ impl<'a> EarlyContext<'a> {
}
}

impl LintContext for LateContext<'_> {
type PassObject = LateLintPassObject;
impl<'tcx> LintContext for LateContext<'tcx> {
type PassObject = LateLintPassObject<'tcx>;

/// Gets the overall compiler `Session` object.
fn sess(&self) -> &Session {
15 changes: 8 additions & 7 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
@@ -306,12 +306,12 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
}
}

struct LateLintPassObjects<'a> {
lints: &'a mut [LateLintPassObject],
struct LateLintPassObjects<'a, 'tcx> {
lints: &'a mut [LateLintPassObject<'tcx>],
}

#[allow(rustc::lint_pass_impl_without_macro)]
impl LintPass for LateLintPassObjects<'_> {
impl LintPass for LateLintPassObjects<'_, '_> {
fn name(&self) -> &'static str {
panic!()
}
@@ -329,7 +329,7 @@ macro_rules! expand_late_lint_pass_impl_methods {

macro_rules! late_lint_pass_impl {
([], [$hir:tt], $methods:tt) => {
impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_> {
impl<$hir> LateLintPass<$hir> for LateLintPassObjects<'_, $hir> {
expand_late_lint_pass_impl_methods!([$hir], $methods);
}
};
@@ -382,7 +382,7 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>(
late_lint_mod_pass(tcx, module_def_id, builtin_lints);

let mut passes: Vec<_> =
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();

if !passes.is_empty() {
late_lint_mod_pass(tcx, module_def_id, LateLintPassObjects { lints: &mut passes[..] });
@@ -418,7 +418,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T)
}

fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints: T) {
let mut passes = unerased_lint_store(tcx).late_passes.iter().map(|p| (p)()).collect::<Vec<_>>();
let mut passes =
unerased_lint_store(tcx).late_passes.iter().map(|p| (p)(tcx)).collect::<Vec<_>>();

if !tcx.sess.opts.unstable_opts.no_interleave_lints {
if !passes.is_empty() {
@@ -434,7 +435,7 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints
}

let mut passes: Vec<_> =
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)()).collect();
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();

for pass in &mut passes {
tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run(
43 changes: 29 additions & 14 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -260,26 +260,41 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
)
}

macro_rules! register_pass {
macro_rules! register_early_pass {
($method:ident, $ty:ident, $constructor:expr) => {
store.register_lints(&$ty::get_lints());
store.$method(|| Box::new($constructor));
};
}

macro_rules! register_passes {
macro_rules! register_late_pass {
($method:ident, $ty:ident, $constructor:expr) => {
store.register_lints(&$ty::get_lints());
store.$method(|_| Box::new($constructor));
};
}

macro_rules! register_early_passes {
($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
$(
register_early_pass!($method, $passes, $constructor);
)*
)
}

macro_rules! register_late_passes {
($method:ident, [$($passes:ident: $constructor:expr,)*]) => (
$(
register_pass!($method, $passes, $constructor);
register_late_pass!($method, $passes, $constructor);
)*
)
}

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);
pre_expansion_lint_passes!(register_early_passes, register_pre_expansion_pass);
early_lint_passes!(register_early_passes, register_early_pass);
late_lint_passes!(register_late_passes, register_late_pass);
late_lint_mod_passes!(register_late_passes, register_late_mod_pass);
} else {
store.register_lints(&BuiltinCombinedPreExpansionLintPass::get_lints());
store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
@@ -510,19 +525,19 @@ fn register_internals(store: &mut LintStore) {
store.register_lints(&LintPassImpl::get_lints());
store.register_early_pass(|| Box::new(LintPassImpl));
store.register_lints(&DefaultHashTypes::get_lints());
store.register_late_pass(|| Box::new(DefaultHashTypes));
store.register_late_pass(|_| Box::new(DefaultHashTypes));
store.register_lints(&QueryStability::get_lints());
store.register_late_pass(|| Box::new(QueryStability));
store.register_late_pass(|_| Box::new(QueryStability));
store.register_lints(&ExistingDocKeyword::get_lints());
store.register_late_pass(|| Box::new(ExistingDocKeyword));
store.register_late_pass(|_| Box::new(ExistingDocKeyword));
store.register_lints(&TyTyKind::get_lints());
store.register_late_pass(|| Box::new(TyTyKind));
store.register_late_pass(|_| Box::new(TyTyKind));
store.register_lints(&Diagnostics::get_lints());
store.register_late_pass(|| Box::new(Diagnostics));
store.register_late_pass(|_| Box::new(Diagnostics));
store.register_lints(&BadOptAccess::get_lints());
store.register_late_pass(|| Box::new(BadOptAccess));
store.register_late_pass(|_| Box::new(BadOptAccess));
store.register_lints(&PassByValue::get_lints());
store.register_late_pass(|| Box::new(PassByValue));
store.register_late_pass(|_| Box::new(PassByValue));
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
// these lints will trigger all of the time - change this once migration to diagnostic structs
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/passes.rs
Original file line number Diff line number Diff line change
@@ -244,4 +244,4 @@ macro_rules! declare_combined_early_lint_pass {

/// A lint pass boxed up as a trait object.
pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + 'static>;
pub type LateLintPassObject = Box<dyn for<'tcx> LateLintPass<'tcx> + sync::Send + 'static>;
pub type LateLintPassObject<'tcx> = Box<dyn LateLintPass<'tcx> + sync::Send + 'tcx>;
2 changes: 1 addition & 1 deletion src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ use rustc_span::source_map;
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]);
reg.lint_store.register_late_pass(|| Box::new(MissingAllowedAttrPass));
reg.lint_store.register_late_pass(|_| Box::new(MissingAllowedAttrPass));
}

declare_lint! {
6 changes: 3 additions & 3 deletions src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ fn __rustc_plugin_registrar(reg: &mut Registry) {
&CRATE_NOT_GREY,
&CRATE_NOT_GREEN,
]);
reg.lint_store.register_late_pass(|| Box::new(PassOkay));
reg.lint_store.register_late_pass(|| Box::new(PassRedBlue));
reg.lint_store.register_late_pass(|| Box::new(PassGreyGreen));
reg.lint_store.register_late_pass(|_| Box::new(PassOkay));
reg.lint_store.register_late_pass(|_| Box::new(PassRedBlue));
reg.lint_store.register_late_pass(|_| Box::new(PassGreyGreen));
}
2 changes: 1 addition & 1 deletion src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
Original file line number Diff line number Diff line change
@@ -39,5 +39,5 @@ impl<'tcx> LateLintPass<'tcx> for Pass {
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]);
reg.lint_store.register_late_pass(|| Box::new(Pass));
reg.lint_store.register_late_pass(|_| Box::new(Pass));
}
2 changes: 1 addition & 1 deletion src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for Pass {
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]);
reg.lint_store.register_late_pass(|| Box::new(Pass));
reg.lint_store.register_late_pass(|_| Box::new(Pass));
reg.lint_store.register_group(
true,
"lint_me",
6 changes: 4 additions & 2 deletions src/tools/clippy/clippy_dev/src/new_lint.rs
Original file line number Diff line number Diff line change
@@ -120,15 +120,17 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {

let new_lint = if enable_msrv {
format!(
"store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n ",
"store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv)));\n ",
lint_pass = lint.pass,
ctor_arg = if lint.pass == "late" { "_" } else { "" },
module_name = lint.name,
camel_name = to_camel_case(lint.name),
)
} else {
format!(
"store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n ",
"store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n ",
lint_pass = lint.pass,
ctor_arg = if lint.pass == "late" { "_" } else { "" },
module_name = lint.name,
camel_name = to_camel_case(lint.name),
)
Loading