Rollup merge of #134339 - Urgau:tcx-in-early-diag, r=jieyouxu
Pass `TyCtxt` to early diagostics decoration This PR pass a `TyCtxt` to the early diagnostics decoration code so that diagnostics code that take advantage of (a very limited but still useful) `TyCtxt` in their note, help, suggestions, ... This is particulary useful for #133221 which wants to get the crate name of a `DefId`, which is possible with `tcx.crate_name(...)`. I highly recommend reviewing this PR commit by commit. r? `@jieyouxu`
This commit is contained in:
commit
56545cae69
8 changed files with 84 additions and 112 deletions
|
@ -76,6 +76,7 @@ fn pre_expansion_lint<'a>(
|
|||
|| {
|
||||
rustc_lint::check_ast_node(
|
||||
sess,
|
||||
None,
|
||||
features,
|
||||
true,
|
||||
lint_store,
|
||||
|
@ -310,6 +311,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
|
|||
let lint_store = unerased_lint_store(tcx.sess);
|
||||
rustc_lint::check_ast_node(
|
||||
sess,
|
||||
Some(tcx),
|
||||
tcx.features(),
|
||||
false,
|
||||
lint_store,
|
||||
|
|
|
@ -806,7 +806,7 @@ lint_unexpected_cfg_add_build_rs_println = or consider adding `{$build_rs_printl
|
|||
lint_unexpected_cfg_add_cargo_feature = consider using a Cargo feature instead
|
||||
lint_unexpected_cfg_add_cargo_toml_lint_cfg = or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:{$cargo_toml_lint_cfg}
|
||||
lint_unexpected_cfg_add_cmdline_arg = to expect this configuration use `{$cmdline_arg}`
|
||||
lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
|
||||
lint_unexpected_cfg_cargo_update = the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`
|
||||
|
||||
lint_unexpected_cfg_define_features = consider defining some features in `Cargo.toml`
|
||||
lint_unexpected_cfg_doc_cargo = see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
|
|
|
@ -20,7 +20,7 @@ use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
|
|||
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
|
||||
use rustc_session::lint::{
|
||||
BuiltinLintDiag, FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
|
||||
FutureIncompatibleInfo, Level, Lint, LintBuffer, LintExpectationId, LintId,
|
||||
};
|
||||
use rustc_session::{LintStoreMarker, Session};
|
||||
use rustc_span::Span;
|
||||
|
@ -33,8 +33,6 @@ use self::TargetLint::*;
|
|||
use crate::levels::LintLevelsBuilder;
|
||||
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
|
||||
|
||||
mod diagnostics;
|
||||
|
||||
type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync;
|
||||
type LateLintPassFactory =
|
||||
dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync;
|
||||
|
@ -511,38 +509,6 @@ pub struct EarlyContext<'a> {
|
|||
pub buffered: LintBuffer,
|
||||
}
|
||||
|
||||
impl EarlyContext<'_> {
|
||||
/// Emit a lint at the appropriate level, with an associated span and an existing
|
||||
/// diagnostic.
|
||||
///
|
||||
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_lint_with_diagnostics(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
span: MultiSpan,
|
||||
diagnostic: BuiltinLintDiag,
|
||||
) {
|
||||
self.opt_span_lint_with_diagnostics(lint, Some(span), diagnostic);
|
||||
}
|
||||
|
||||
/// Emit a lint at the appropriate level, with an optional associated span and an existing
|
||||
/// diagnostic.
|
||||
///
|
||||
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn opt_span_lint_with_diagnostics(
|
||||
&self,
|
||||
lint: &'static Lint,
|
||||
span: Option<MultiSpan>,
|
||||
diagnostic: BuiltinLintDiag,
|
||||
) {
|
||||
self.opt_span_lint(lint, span, |diag| {
|
||||
diagnostics::decorate_lint(self.sess(), diagnostic, diag);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LintContext {
|
||||
fn sess(&self) -> &Session;
|
||||
|
||||
|
|
|
@ -9,35 +9,40 @@ use rustc_ast::visit::{self as ast_visit, Visitor, walk_list};
|
|||
use rustc_ast::{self as ast, HasAttrs};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_feature::Features;
|
||||
use rustc_middle::ty::RegisteredTools;
|
||||
use rustc_middle::ty::{RegisteredTools, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Ident;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::context::{EarlyContext, LintStore};
|
||||
use crate::context::{EarlyContext, LintContext, LintStore};
|
||||
use crate::passes::{EarlyLintPass, EarlyLintPassObject};
|
||||
|
||||
mod diagnostics;
|
||||
|
||||
macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({
|
||||
$cx.pass.$f(&$cx.context, $($args),*);
|
||||
}) }
|
||||
|
||||
/// Implements the AST traversal for early lint passes. `T` provides the
|
||||
/// `check_*` methods.
|
||||
pub struct EarlyContextAndPass<'a, T: EarlyLintPass> {
|
||||
context: EarlyContext<'a>,
|
||||
pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> {
|
||||
context: EarlyContext<'ecx>,
|
||||
tcx: Option<TyCtxt<'tcx>>,
|
||||
pass: T,
|
||||
}
|
||||
|
||||
impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
||||
impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> {
|
||||
// This always-inlined function is for the hot call site.
|
||||
#[inline(always)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
fn inlined_check_id(&mut self, id: ast::NodeId) {
|
||||
for early_lint in self.context.buffered.take(id) {
|
||||
let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint;
|
||||
self.context.opt_span_lint_with_diagnostics(lint_id.lint, span, diagnostic);
|
||||
self.context.opt_span_lint(lint_id.lint, span, |diag| {
|
||||
diagnostics::decorate_lint(self.context.sess(), self.tcx, diagnostic, diag);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +54,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
|||
/// Merge the lints specified by any lint attributes into the
|
||||
/// current lint context, call the provided function, then reset the
|
||||
/// lints in effect to their previous state.
|
||||
fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'a [ast::Attribute], f: F)
|
||||
fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'_ [ast::Attribute], f: F)
|
||||
where
|
||||
F: FnOnce(&mut Self),
|
||||
{
|
||||
|
@ -67,19 +72,21 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> {
|
||||
fn visit_coroutine_kind(&mut self, coroutine_kind: &'a ast::CoroutineKind) -> Self::Result {
|
||||
impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
|
||||
for EarlyContextAndPass<'ecx, 'tcx, T>
|
||||
{
|
||||
fn visit_coroutine_kind(&mut self, coroutine_kind: &'ast ast::CoroutineKind) -> Self::Result {
|
||||
self.check_id(coroutine_kind.closure_id());
|
||||
}
|
||||
|
||||
fn visit_param(&mut self, param: &'a ast::Param) {
|
||||
fn visit_param(&mut self, param: &'ast ast::Param) {
|
||||
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
||||
lint_callback!(cx, check_param, param);
|
||||
ast_visit::walk_param(cx, param);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, it: &'a ast::Item) {
|
||||
fn visit_item(&mut self, it: &'ast ast::Item) {
|
||||
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
||||
lint_callback!(cx, check_item, it);
|
||||
ast_visit::walk_item(cx, it);
|
||||
|
@ -87,31 +94,31 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
})
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, it: &'a ast::ForeignItem) {
|
||||
fn visit_foreign_item(&mut self, it: &'ast ast::ForeignItem) {
|
||||
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
||||
ast_visit::walk_item(cx, it);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, p: &'a ast::Pat) {
|
||||
fn visit_pat(&mut self, p: &'ast ast::Pat) {
|
||||
lint_callback!(self, check_pat, p);
|
||||
self.check_id(p.id);
|
||||
ast_visit::walk_pat(self, p);
|
||||
lint_callback!(self, check_pat_post, p);
|
||||
}
|
||||
|
||||
fn visit_pat_field(&mut self, field: &'a ast::PatField) {
|
||||
fn visit_pat_field(&mut self, field: &'ast ast::PatField) {
|
||||
self.with_lint_attrs(field.id, &field.attrs, |cx| {
|
||||
ast_visit::walk_pat_field(cx, field);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_anon_const(&mut self, c: &'a ast::AnonConst) {
|
||||
fn visit_anon_const(&mut self, c: &'ast ast::AnonConst) {
|
||||
self.check_id(c.id);
|
||||
ast_visit::walk_anon_const(self, c);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
fn visit_expr(&mut self, e: &'ast ast::Expr) {
|
||||
self.with_lint_attrs(e.id, &e.attrs, |cx| {
|
||||
lint_callback!(cx, check_expr, e);
|
||||
ast_visit::walk_expr(cx, e);
|
||||
|
@ -119,13 +126,13 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
})
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, f: &'a ast::ExprField) {
|
||||
fn visit_expr_field(&mut self, f: &'ast ast::ExprField) {
|
||||
self.with_lint_attrs(f.id, &f.attrs, |cx| {
|
||||
ast_visit::walk_expr_field(cx, f);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, s: &'a ast::Stmt) {
|
||||
fn visit_stmt(&mut self, s: &'ast ast::Stmt) {
|
||||
// Add the statement's lint attributes to our
|
||||
// current state when checking the statement itself.
|
||||
// This allows us to handle attributes like
|
||||
|
@ -145,33 +152,33 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
ast_visit::walk_stmt(self, s);
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: ast_visit::FnKind<'a>, span: Span, id: ast::NodeId) {
|
||||
fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, span: Span, id: ast::NodeId) {
|
||||
lint_callback!(self, check_fn, fk, span, id);
|
||||
self.check_id(id);
|
||||
ast_visit::walk_fn(self, fk);
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self, s: &'a ast::VariantData) {
|
||||
fn visit_variant_data(&mut self, s: &'ast ast::VariantData) {
|
||||
if let Some(ctor_node_id) = s.ctor_node_id() {
|
||||
self.check_id(ctor_node_id);
|
||||
}
|
||||
ast_visit::walk_struct_def(self, s);
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'a ast::FieldDef) {
|
||||
fn visit_field_def(&mut self, s: &'ast ast::FieldDef) {
|
||||
self.with_lint_attrs(s.id, &s.attrs, |cx| {
|
||||
ast_visit::walk_field_def(cx, s);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_variant(&mut self, v: &'a ast::Variant) {
|
||||
fn visit_variant(&mut self, v: &'ast ast::Variant) {
|
||||
self.with_lint_attrs(v.id, &v.attrs, |cx| {
|
||||
lint_callback!(cx, check_variant, v);
|
||||
ast_visit::walk_variant(cx, v);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'a ast::Ty) {
|
||||
fn visit_ty(&mut self, t: &'ast ast::Ty) {
|
||||
lint_callback!(self, check_ty, t);
|
||||
self.check_id(t.id);
|
||||
ast_visit::walk_ty(self, t);
|
||||
|
@ -181,55 +188,55 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
lint_callback!(self, check_ident, ident);
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, l: &'a ast::Local) {
|
||||
fn visit_local(&mut self, l: &'ast ast::Local) {
|
||||
self.with_lint_attrs(l.id, &l.attrs, |cx| {
|
||||
lint_callback!(cx, check_local, l);
|
||||
ast_visit::walk_local(cx, l);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, b: &'a ast::Block) {
|
||||
fn visit_block(&mut self, b: &'ast ast::Block) {
|
||||
lint_callback!(self, check_block, b);
|
||||
self.check_id(b.id);
|
||||
ast_visit::walk_block(self, b);
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, a: &'a ast::Arm) {
|
||||
fn visit_arm(&mut self, a: &'ast ast::Arm) {
|
||||
self.with_lint_attrs(a.id, &a.attrs, |cx| {
|
||||
lint_callback!(cx, check_arm, a);
|
||||
ast_visit::walk_arm(cx, a);
|
||||
})
|
||||
}
|
||||
|
||||
fn visit_generic_arg(&mut self, arg: &'a ast::GenericArg) {
|
||||
fn visit_generic_arg(&mut self, arg: &'ast ast::GenericArg) {
|
||||
lint_callback!(self, check_generic_arg, arg);
|
||||
ast_visit::walk_generic_arg(self, arg);
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
|
||||
fn visit_generic_param(&mut self, param: &'ast ast::GenericParam) {
|
||||
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
||||
lint_callback!(cx, check_generic_param, param);
|
||||
ast_visit::walk_generic_param(cx, param);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, g: &'a ast::Generics) {
|
||||
fn visit_generics(&mut self, g: &'ast ast::Generics) {
|
||||
lint_callback!(self, check_generics, g);
|
||||
ast_visit::walk_generics(self, g);
|
||||
}
|
||||
|
||||
fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
|
||||
fn visit_where_predicate(&mut self, p: &'ast ast::WherePredicate) {
|
||||
lint_callback!(self, enter_where_predicate, p);
|
||||
ast_visit::walk_where_predicate(self, p);
|
||||
lint_callback!(self, exit_where_predicate, p);
|
||||
}
|
||||
|
||||
fn visit_poly_trait_ref(&mut self, t: &'a ast::PolyTraitRef) {
|
||||
fn visit_poly_trait_ref(&mut self, t: &'ast ast::PolyTraitRef) {
|
||||
lint_callback!(self, check_poly_trait_ref, t);
|
||||
ast_visit::walk_poly_trait_ref(self, t);
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
fn visit_assoc_item(&mut self, item: &'ast ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
self.with_lint_attrs(item.id, &item.attrs, |cx| {
|
||||
match ctxt {
|
||||
ast_visit::AssocCtxt::Trait => {
|
||||
|
@ -243,32 +250,32 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime, _: ast_visit::LifetimeCtxt) {
|
||||
fn visit_lifetime(&mut self, lt: &'ast ast::Lifetime, _: ast_visit::LifetimeCtxt) {
|
||||
self.check_id(lt.id);
|
||||
ast_visit::walk_lifetime(self, lt);
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) {
|
||||
fn visit_path(&mut self, p: &'ast ast::Path, id: ast::NodeId) {
|
||||
self.check_id(id);
|
||||
ast_visit::walk_path(self, p);
|
||||
}
|
||||
|
||||
fn visit_path_segment(&mut self, s: &'a ast::PathSegment) {
|
||||
fn visit_path_segment(&mut self, s: &'ast ast::PathSegment) {
|
||||
self.check_id(s.id);
|
||||
ast_visit::walk_path_segment(self, s);
|
||||
}
|
||||
|
||||
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
|
||||
fn visit_attribute(&mut self, attr: &'ast ast::Attribute) {
|
||||
lint_callback!(self, check_attribute, attr);
|
||||
ast_visit::walk_attribute(self, attr);
|
||||
}
|
||||
|
||||
fn visit_mac_def(&mut self, mac: &'a ast::MacroDef, id: ast::NodeId) {
|
||||
fn visit_mac_def(&mut self, mac: &'ast ast::MacroDef, id: ast::NodeId) {
|
||||
lint_callback!(self, check_mac_def, mac);
|
||||
self.check_id(id);
|
||||
}
|
||||
|
||||
fn visit_mac_call(&mut self, mac: &'a ast::MacCall) {
|
||||
fn visit_mac_call(&mut self, mac: &'ast ast::MacCall) {
|
||||
lint_callback!(self, check_mac, mac);
|
||||
ast_visit::walk_mac(self, mac);
|
||||
}
|
||||
|
@ -310,28 +317,18 @@ crate::early_lint_methods!(impl_early_lint_pass, []);
|
|||
/// This trait generalizes over those nodes.
|
||||
pub trait EarlyCheckNode<'a>: Copy {
|
||||
fn id(self) -> ast::NodeId;
|
||||
fn attrs<'b>(self) -> &'b [ast::Attribute]
|
||||
where
|
||||
'a: 'b;
|
||||
fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
|
||||
where
|
||||
'a: 'b;
|
||||
fn attrs(self) -> &'a [ast::Attribute];
|
||||
fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>);
|
||||
}
|
||||
|
||||
impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) {
|
||||
fn id(self) -> ast::NodeId {
|
||||
ast::CRATE_NODE_ID
|
||||
}
|
||||
fn attrs<'b>(self) -> &'b [ast::Attribute]
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
fn attrs(self) -> &'a [ast::Attribute] {
|
||||
self.1
|
||||
}
|
||||
fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) {
|
||||
lint_callback!(cx, check_crate, self.0);
|
||||
ast_visit::walk_crate(cx, self.0);
|
||||
lint_callback!(cx, check_crate_post, self.0);
|
||||
|
@ -342,16 +339,10 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
|
|||
fn id(self) -> ast::NodeId {
|
||||
self.0
|
||||
}
|
||||
fn attrs<'b>(self) -> &'b [ast::Attribute]
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
fn attrs(self) -> &'a [ast::Attribute] {
|
||||
self.1
|
||||
}
|
||||
fn check<'b, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'b, T>)
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) {
|
||||
walk_list!(cx, visit_attribute, self.1);
|
||||
walk_list!(cx, visit_item, self.2);
|
||||
}
|
||||
|
@ -359,6 +350,7 @@ impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::
|
|||
|
||||
pub fn check_ast_node<'a>(
|
||||
sess: &Session,
|
||||
tcx: Option<TyCtxt<'_>>,
|
||||
features: &Features,
|
||||
pre_expansion: bool,
|
||||
lint_store: &LintStore,
|
||||
|
@ -382,22 +374,23 @@ pub fn check_ast_node<'a>(
|
|||
let passes =
|
||||
if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes };
|
||||
if passes.is_empty() {
|
||||
check_ast_node_inner(sess, check_node, context, builtin_lints);
|
||||
check_ast_node_inner(sess, tcx, check_node, context, builtin_lints);
|
||||
} else {
|
||||
let mut passes: Vec<_> = passes.iter().map(|mk_pass| (mk_pass)()).collect();
|
||||
passes.push(Box::new(builtin_lints));
|
||||
let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] };
|
||||
check_ast_node_inner(sess, check_node, context, pass);
|
||||
check_ast_node_inner(sess, tcx, check_node, context, pass);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_ast_node_inner<'a, T: EarlyLintPass>(
|
||||
sess: &Session,
|
||||
tcx: Option<TyCtxt<'_>>,
|
||||
check_node: impl EarlyCheckNode<'a>,
|
||||
context: EarlyContext<'_>,
|
||||
pass: T,
|
||||
) {
|
||||
let mut cx = EarlyContextAndPass { context, pass };
|
||||
let mut cx = EarlyContextAndPass { context, tcx, pass };
|
||||
|
||||
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use rustc_errors::{
|
|||
Applicability, Diag, DiagArgValue, LintDiagnostic, elided_lifetime_in_path_suggestion,
|
||||
};
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{BuiltinLintDiag, ElidedLifetimeResolution};
|
||||
use rustc_span::BytePos;
|
||||
|
@ -18,7 +19,12 @@ use crate::lints::{self, ElidedNamedLifetime};
|
|||
|
||||
mod check_cfg;
|
||||
|
||||
pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Diag<'_, ()>) {
|
||||
pub(super) fn decorate_lint(
|
||||
sess: &Session,
|
||||
tcx: Option<TyCtxt<'_>>,
|
||||
diagnostic: BuiltinLintDiag,
|
||||
diag: &mut Diag<'_, ()>,
|
||||
) {
|
||||
match diagnostic {
|
||||
BuiltinLintDiag::UnicodeTextFlow(comment_span, content) => {
|
||||
let spans: Vec<_> = content
|
||||
|
@ -199,10 +205,10 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
|
|||
.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgName(name, value) => {
|
||||
check_cfg::unexpected_cfg_name(sess, name, value).decorate_lint(diag);
|
||||
check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::UnexpectedCfgValue(name, value) => {
|
||||
check_cfg::unexpected_cfg_value(sess, name, value).decorate_lint(diag);
|
||||
check_cfg::unexpected_cfg_value(sess, tcx, name, value).decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::DeprecatedWhereclauseLocation(left_sp, sugg) => {
|
||||
let suggestion = match sugg {
|
|
@ -1,5 +1,6 @@
|
|||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
|
@ -73,17 +74,20 @@ fn rustc_macro_help(span: Span) -> Option<lints::UnexpectedCfgRustcMacroHelp> {
|
|||
}
|
||||
}
|
||||
|
||||
fn cargo_macro_help(span: Span) -> Option<lints::UnexpectedCfgCargoMacroHelp> {
|
||||
fn cargo_macro_help(
|
||||
tcx: Option<TyCtxt<'_>>,
|
||||
span: Span,
|
||||
) -> Option<lints::UnexpectedCfgCargoMacroHelp> {
|
||||
let oexpn = span.ctxt().outer_expn_data();
|
||||
if let Some(def_id) = oexpn.macro_def_id
|
||||
&& let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind
|
||||
&& def_id.krate != LOCAL_CRATE
|
||||
&& let Some(tcx) = tcx
|
||||
{
|
||||
Some(lints::UnexpectedCfgCargoMacroHelp {
|
||||
macro_kind: macro_kind.descr(),
|
||||
macro_name,
|
||||
// FIXME: Get access to a `TyCtxt` from an `EarlyContext`
|
||||
// crate_name: cx.tcx.crate_name(def_id.krate),
|
||||
crate_name: tcx.crate_name(def_id.krate),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
@ -92,6 +96,7 @@ fn cargo_macro_help(span: Span) -> Option<lints::UnexpectedCfgCargoMacroHelp> {
|
|||
|
||||
pub(super) fn unexpected_cfg_name(
|
||||
sess: &Session,
|
||||
tcx: Option<TyCtxt<'_>>,
|
||||
(name, name_span): (Symbol, Span),
|
||||
value: Option<(Symbol, Span)>,
|
||||
) -> lints::UnexpectedCfgName {
|
||||
|
@ -223,7 +228,7 @@ pub(super) fn unexpected_cfg_name(
|
|||
};
|
||||
lints::unexpected_cfg_name::InvocationHelp::Cargo {
|
||||
help,
|
||||
macro_help: cargo_macro_help(name_span),
|
||||
macro_help: cargo_macro_help(tcx, name_span),
|
||||
}
|
||||
} else {
|
||||
let help = lints::UnexpectedCfgRustcHelp::new(&inst(EscapeQuotes::No));
|
||||
|
@ -238,6 +243,7 @@ pub(super) fn unexpected_cfg_name(
|
|||
|
||||
pub(super) fn unexpected_cfg_value(
|
||||
sess: &Session,
|
||||
tcx: Option<TyCtxt<'_>>,
|
||||
(name, name_span): (Symbol, Span),
|
||||
value: Option<(Symbol, Span)>,
|
||||
) -> lints::UnexpectedCfgValue {
|
||||
|
@ -339,7 +345,7 @@ pub(super) fn unexpected_cfg_value(
|
|||
};
|
||||
lints::unexpected_cfg_value::InvocationHelp::Cargo {
|
||||
help,
|
||||
macro_help: cargo_macro_help(name_span),
|
||||
macro_help: cargo_macro_help(tcx, name_span),
|
||||
}
|
||||
} else {
|
||||
let help = if can_suggest_adding_value {
|
|
@ -2187,8 +2187,7 @@ pub(crate) struct UnexpectedCfgRustcMacroHelp {
|
|||
pub(crate) struct UnexpectedCfgCargoMacroHelp {
|
||||
pub macro_kind: &'static str,
|
||||
pub macro_name: Symbol,
|
||||
// FIXME: Figure out a way to get the crate name
|
||||
// crate_name: String,
|
||||
pub crate_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
|
|
|
@ -7,7 +7,7 @@ LL | cfg_macro::my_lib_macro!();
|
|||
= help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
|
||||
= note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
|
||||
= help: try refering to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg
|
||||
= help: the macro `cfg_macro::my_lib_macro` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
|
||||
= help: the macro `cfg_macro::my_lib_macro` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
= note: this warning originates in the macro `cfg_macro::my_lib_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
@ -21,7 +21,7 @@ LL | cfg_macro::my_lib_macro_value!();
|
|||
= note: expected values for `panic` are: `abort` and `unwind`
|
||||
= note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
|
||||
= help: try refering to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg
|
||||
= help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
|
||||
= help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
= note: this warning originates in the macro `cfg_macro::my_lib_macro_value` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
|
@ -34,7 +34,7 @@ LL | cfg_macro::my_lib_macro_feature!();
|
|||
= note: no expected values for `feature`
|
||||
= note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
|
||||
= help: try refering to `cfg_macro::my_lib_macro_feature` crate for guidance on how handle this unexpected cfg
|
||||
= help: the macro `cfg_macro::my_lib_macro_feature` may come from an old version of it's defining crate, try updating your dependencies with `cargo update`
|
||||
= help: the macro `cfg_macro::my_lib_macro_feature` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
|
||||
= note: this warning originates in the macro `cfg_macro::my_lib_macro_feature` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue