Skip to content
Draft
Show file tree
Hide file tree
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
18 changes: 14 additions & 4 deletions compiler/rustc_errors/src/decorate_diag.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::any::Any;

/// This module provides types and traits for buffering lints until later in compilation.
use rustc_ast::AttrId;
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_error_messages::MultiSpan;
use rustc_lint_defs::{Lint, LintId};

use crate::{Diag, DiagCtxtHandle, Diagnostic, Level};
use crate::{Diag, DiagCtxtHandle, DiagInner, Diagnostic, Level};

pub struct DecorateDiagCompat(
/// The third argument of the closure is a `Session`. However, due to the dependency tree,
Expand Down Expand Up @@ -51,19 +52,28 @@ pub struct BufferedEarlyLint {
pub diagnostic: DecorateDiagCompat,
}

#[derive(Debug)]
pub struct PreExpansionLint {
pub lint: &'static Lint,
pub span: Option<MultiSpan>,
pub diag: DiagInner,
pub attrs: Vec<AttrId>,
}

#[derive(Default, Debug)]
pub struct LintBuffer {
pub map: FxIndexMap<NodeId, Vec<BufferedEarlyLint>>,
pub early: FxIndexMap<NodeId, Vec<BufferedEarlyLint>>,
pub pre_expansion: Vec<PreExpansionLint>,
}

impl LintBuffer {
pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) {
self.map.entry(early_lint.node_id).or_default().push(early_lint);
self.early.entry(early_lint.node_id).or_default().push(early_lint);
}

pub fn take(&mut self, id: NodeId) -> Vec<BufferedEarlyLint> {
// FIXME(#120456) - is `swap_remove` correct?
self.map.swap_remove(&id).unwrap_or_default()
self.early.swap_remove(&id).unwrap_or_default()
}

pub fn buffer_lint(
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,19 @@ impl<'a> Diag<'a> {
Self { dcx, diag: Some(Box::new(diag)) }
}

pub fn from_inner_with_level(
dcx: DiagCtxtHandle<'a>,
mut diag: DiagInner,
level: Level,
) -> Self {
diag.level = level;
Self::new_diagnostic(dcx, diag)
}

pub fn into_inner(mut self) -> DiagInner {
self.take_diag()
}

/// Delay emission of this diagnostic as a bug.
///
/// This can be useful in contexts where an error indicates a bug but
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use anstyle::{
Ansi256Color, AnsiColor, Color, EffectIter, Effects, Reset, RgbColor, Style as Anstyle,
};
pub use codes::*;
pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer};
pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer, PreExpansionLint};
pub use diagnostic::{
Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic, StringPart,
Subdiag, Subdiagnostic,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind
use rustc_attr_ir::{self as attrs, CfgEntry, Deprecation, Stability, find_attr};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::sync;
use rustc_errors::{BufferedEarlyLint, DiagCtxtHandle, ErrorGuaranteed};
use rustc_errors::{BufferedEarlyLint, DiagCtxtHandle, ErrorGuaranteed, PreExpansionLint};
use rustc_feature::Features;
use rustc_hir::def::MacroKinds;
use rustc_lint_defs::RegisteredTools;
Expand Down Expand Up @@ -1132,6 +1132,8 @@ pub trait ResolverExpand {
/// Mark the scope as having a compile error so that error for lookup in this scope
/// should be suppressed
fn mark_scope_with_compile_error(&mut self, parent_node: NodeId);

fn buffer_pre_expansion_lints(&mut self, lints: Vec<PreExpansionLint>);
}

pub trait LintStoreExpand {
Expand All @@ -1144,7 +1146,7 @@ pub trait LintStoreExpand {
attrs: &[Attribute],
items: &[Box<Item>],
name: Symbol,
);
) -> Vec<PreExpansionLint>;
}

type LintStoreExpandDyn<'a> = Option<&'a (dyn LintStoreExpand + 'a)>;
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,7 @@ impl InvocationCollectorNode for Box<ast::Item> {
);

if let Some(lint_store) = ecx.lint_store {
lint_store.pre_expansion_lint(
let lints = lint_store.pre_expansion_lint(
ecx.sess,
ecx.ecfg.features,
ecx.resolver.registered_lint_tools(),
Expand All @@ -1419,6 +1419,7 @@ impl InvocationCollectorNode for Box<ast::Item> {
&items,
ident.name,
);
ecx.resolver.buffer_pre_expansion_lints(lints);
}

*mod_kind = ModKind::Loaded(items, Inline::No { had_parse_error }, spans);
Expand Down
22 changes: 10 additions & 12 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use rustc_data_structures::sync::{
};
use rustc_data_structures::thousands;
use rustc_errors::timings::TimingSection;
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level};
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, PreExpansionLint};
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
use rustc_feature::Features;
use rustc_fs_util::try_canonicalize;
Expand Down Expand Up @@ -93,20 +93,18 @@ fn pre_expansion_lint<'a>(
registered_lint_tools: &RegisteredTools,
check_node: EarlyCheckNode<'a>,
node_name: Symbol,
) {
) -> Vec<PreExpansionLint> {
sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
|| {
rustc_lint::check_ast_node(
rustc_lint::check_ast_node_pre_expansion(
sess,
features,
true,
lint_store,
registered_lint_tools,
None,
check_node,
);
)
},
);
)
}

// Cannot implement directly for `LintStore` due to trait coherence.
Expand All @@ -122,9 +120,9 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
attrs: &[ast::Attribute],
items: &[Box<ast::Item>],
name: Symbol,
) {
) -> Vec<PreExpansionLint> {
let check_node = EarlyCheckNode::LoadedMod(node_id, attrs, items);
pre_expansion_lint(sess, features, self.0, registered_lint_tools, check_node, name);
pre_expansion_lint(sess, features, self.0, registered_lint_tools, check_node, name)
}
}

Expand All @@ -143,14 +141,15 @@ fn configure_and_expand(
let features = tcx.features();
let lint_store = unerased_lint_store(sess);
let crate_name = tcx.crate_name(LOCAL_CRATE);
pre_expansion_lint(
let lints = pre_expansion_lint(
sess,
features,
lint_store,
tcx.registered_lint_tools(()),
EarlyCheckNode::CrateRoot(&krate, pre_configured_attrs),
crate_name,
);
resolver.lint_buffer().pre_expansion.extend(lints);
rustc_builtin_macros::register_builtin_macros(resolver);

let num_standard_library_imports = sess.time("crate_injection", || {
Expand Down Expand Up @@ -490,10 +489,9 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
rustc_lint::check_ast_node(
sess,
tcx.features(),
false,
lint_store,
tcx.registered_lint_tools(()),
Some(lint_buffer),
lint_buffer,
EarlyCheckNode::CrateRoot(&*krate, &*krate.attrs),
)
}
Expand Down
14 changes: 7 additions & 7 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ use crate::diagnostics::{
BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue,
EqInternalMethodImplemented, InvalidAsmLabel,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, PreExpansion};

declare_lint! {
/// The `while_true` lint detects `while true { }`.
Expand Down Expand Up @@ -1744,7 +1744,7 @@ declare_lint_pass!(
struct UnderMacro(bool);

impl KeywordIdents {
fn check_tokens(&mut self, cx: &EarlyContext<'_>, tokens: &TokenStream) {
fn check_tokens(&mut self, cx: &EarlyContext<'_, PreExpansion>, tokens: &TokenStream) {
// Check if the preceding token is `$`, because we want to allow `$async`, etc.
let mut prev_dollar = false;
for tt in tokens.iter() {
Expand Down Expand Up @@ -1775,7 +1775,7 @@ impl KeywordIdents {

fn check_ident_token(
&mut self,
cx: &EarlyContext<'_>,
cx: &EarlyContext<'_, PreExpansion>,
UnderMacro(under_macro): UnderMacro,
ident: Ident,
prefix: &'static str,
Expand Down Expand Up @@ -1817,14 +1817,14 @@ impl KeywordIdents {
}
}

impl EarlyLintPass for KeywordIdents {
fn check_mac_def(&mut self, cx: &EarlyContext<'_>, mac_def: &ast::MacroDef) {
impl EarlyLintPass<PreExpansion> for KeywordIdents {
fn check_mac_def(&mut self, cx: &EarlyContext<'_, PreExpansion>, mac_def: &ast::MacroDef) {
self.check_tokens(cx, &mac_def.body.tokens);
}
fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &ast::MacCall) {
fn check_mac(&mut self, cx: &EarlyContext<'_, PreExpansion>, mac: &ast::MacCall) {
self.check_tokens(cx, &mac.args.tokens);
}
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: &Ident) {
fn check_ident(&mut self, cx: &EarlyContext<'_, PreExpansion>, ident: &Ident) {
if ident.name.as_str().starts_with('\'') {
self.check_ident_token(cx, UnderMacro(false), ident.without_first_quote(), "'");
} else {
Expand Down
22 changes: 13 additions & 9 deletions compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ use rustc_span::{Ident, Span, Symbol, bug, sym};
use tracing::debug;

use self::TargetLint::*;
use crate::early::{EarlyLintMode, PostExpansion, PreExpansion};
use crate::levels::LintLevelsBuilder;
use crate::passes::{EarlyLintPassObject, LateLintPassObject};

pub(crate) type EarlyLintPassFactory =
Box<dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync>;
pub(crate) type EarlyLintPassFactory<M = PostExpansion> =
Box<dyn Fn() -> EarlyLintPassObject<M> + sync::DynSend + sync::DynSync>;
type LateLintPassFactory =
Box<dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync>;

Expand All @@ -59,7 +60,7 @@ pub struct LintStore {
///
/// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838)
/// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518)
pub(crate) pre_expansion_lint_passes: Vec<EarlyLintPassFactory>,
pub(crate) pre_expansion_lint_passes: Vec<EarlyLintPassFactory<PreExpansion>>,

/// These lint passes run on AST nodes.
pub(crate) early_lint_passes: Vec<EarlyLintPassFactory>,
Expand Down Expand Up @@ -183,7 +184,7 @@ impl LintStore {
}

/// See the comment on `LintStore::pre_expansion_lint_passes`.
pub fn register_pre_expansion_lint_pass(&mut self, pass: EarlyLintPassFactory) {
pub fn register_pre_expansion_lint_pass(&mut self, pass: EarlyLintPassFactory<PreExpansion>) {
self.pre_expansion_lint_passes.push(pass);
}

Expand Down Expand Up @@ -501,9 +502,10 @@ pub struct LateContext<'tcx> {
}

/// Context for lint checking of the AST, after expansion, before lowering to HIR.
pub struct EarlyContext<'a> {
pub struct EarlyContext<'a, M = PostExpansion> {
pub builder: LintLevelsBuilder<'a, crate::levels::TopDown>,
pub buffered: LintBuffer,
pub(crate) mode: M,
}

pub trait LintContext {
Expand Down Expand Up @@ -551,15 +553,16 @@ pub trait LintContext {
}
}

impl<'a> EarlyContext<'a> {
impl<'a, M: EarlyLintMode> EarlyContext<'a, M> {
pub(crate) fn new(
sess: &'a Session,
features: &'a Features,
lint_added_lints: bool,
lint_store: &'a LintStore,
registered_lint_tools: &'a RegisteredTools,
buffered: LintBuffer,
) -> EarlyContext<'a> {
mode: M,
) -> EarlyContext<'a, M> {
EarlyContext {
builder: LintLevelsBuilder::new(
sess,
Expand All @@ -569,6 +572,7 @@ impl<'a> EarlyContext<'a> {
registered_lint_tools,
),
buffered,
mode,
}
}
}
Expand Down Expand Up @@ -600,7 +604,7 @@ impl<'tcx> LintContext for LateContext<'tcx> {
}
}

impl LintContext for EarlyContext<'_> {
impl<M: EarlyLintMode> LintContext for EarlyContext<'_, M> {
type LintExpectationId = UnstableLintExpectationId;

/// Gets the overall compiler `Session` object.
Expand All @@ -614,7 +618,7 @@ impl LintContext for EarlyContext<'_> {
span: Option<S>,
decorator: impl for<'a> Diagnostic<'a>,
) {
self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorator)
M::opt_span_lint(self, lint, span.map(|s| s.into()), decorator)
}

fn get_lint_level_spec(&self, lint: &'static Lint) -> UnstableLevelSpec {
Expand Down
Loading
Loading