Skip to content

Commit e043917

Browse files
committed
Auto merge of #58176 - Zoxc:lint-levels, r=<try>
[WIP] Only insert nodes which changes lint levels in the LintLevelMap r? @eddyb
2 parents 65e647c + 59c6c5a commit e043917

File tree

11 files changed

+139
-128
lines changed

11 files changed

+139
-128
lines changed

src/librustc/dep_graph/dep_node.rs

+1
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ define_dep_nodes!( <'tcx>
574574
[] HasPanicHandler(CrateNum),
575575
[input] ExternCrate(DefId),
576576
[eval_always] LintLevels,
577+
[eval_always] LintLevelRootForDefId(DefId),
577578
[] Specializes { impl1: DefId, impl2: DefId },
578579
[input] InScopeTraits(DefIndex),
579580
[input] ModuleExports(DefId),

src/librustc/lint/levels.rs

+5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ use syntax::source_map::MultiSpan;
1616
use syntax::symbol::Symbol;
1717
use util::nodemap::FxHashMap;
1818

19+
#[derive(Debug)]
1920
pub struct LintLevelSets {
2021
list: Vec<LintSet>,
2122
lint_cap: Level,
2223
}
2324

25+
#[derive(Debug)]
2426
enum LintSet {
2527
CommandLine {
2628
// -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
@@ -157,6 +159,7 @@ pub struct LintLevelsBuilder<'a> {
157159

158160
pub struct BuilderPush {
159161
prev: u32,
162+
pub(super) changed: bool,
160163
}
161164

162165
impl<'a> LintLevelsBuilder<'a> {
@@ -454,6 +457,7 @@ impl<'a> LintLevelsBuilder<'a> {
454457

455458
BuilderPush {
456459
prev: prev,
460+
changed: prev != self.cur,
457461
}
458462
}
459463

@@ -492,6 +496,7 @@ impl<'a> LintLevelsBuilder<'a> {
492496
}
493497
}
494498

499+
#[derive(Debug)]
495500
pub struct LintLevelMap {
496501
sets: LintLevelSets,
497502
id_to_set: FxHashMap<HirId, u32>,

src/librustc/lint/mod.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ pub use self::LintSource::*;
2424
use rustc_data_structures::sync::{self, Lrc};
2525

2626
use errors::{DiagnosticBuilder, DiagnosticId};
27-
use hir::def_id::{CrateNum, LOCAL_CRATE};
27+
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
2828
use hir::intravisit;
2929
use hir;
30+
use hir::CRATE_HIR_ID;
3031
use lint::builtin::BuiltinLintDiagnostics;
3132
use lint::builtin::parser::{QUESTION_MARK_MACRO_SEP, ILL_FORMED_ATTRIBUTE_INPUT};
3233
use session::{Session, DiagnosticMessageId};
@@ -540,7 +541,7 @@ impl Level {
540541
}
541542

542543
/// How a lint level was set.
543-
#[derive(Clone, Copy, PartialEq, Eq)]
544+
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
544545
pub enum LintSource {
545546
/// Lint is at the default level as declared
546547
/// in rustc or a plugin.
@@ -722,11 +723,32 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
722723
};
723724
let krate = tcx.hir().krate();
724725

725-
builder.with_lint_attrs(ast::CRATE_NODE_ID, &krate.attrs, |builder| {
726-
intravisit::walk_crate(builder, krate);
727-
});
726+
let push = builder.levels.push(&krate.attrs);
727+
builder.levels.register_id(CRATE_HIR_ID);
728+
intravisit::walk_crate(&mut builder, krate);
729+
builder.levels.pop(push);
728730

729-
Lrc::new(builder.levels.build_map())
731+
let r = Lrc::new(builder.levels.build_map());
732+
if tcx.sess.verbose() {
733+
eprintln!("lint level map: {:#?}", r);
734+
}
735+
r
736+
}
737+
738+
fn lint_level_root_for_def_id(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> hir::HirId {
739+
let mut id = tcx.hir().as_local_hir_id(def_id).unwrap();
740+
let sets = tcx.lint_levels(LOCAL_CRATE);
741+
loop {
742+
if sets.lint_level_set(id).is_some() {
743+
return id
744+
}
745+
let node_id = tcx.hir().hir_to_node_id(id);
746+
let next = tcx.hir().node_to_hir_id(tcx.hir().get_parent_node(node_id));
747+
if next == id {
748+
bug!("lint traversal reached the root of the crate");
749+
}
750+
id = next;
751+
}
730752
}
731753

732754
struct LintLevelMapBuilder<'a, 'tcx: 'a> {
@@ -742,7 +764,9 @@ impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> {
742764
where F: FnOnce(&mut Self)
743765
{
744766
let push = self.levels.push(attrs);
745-
self.levels.register_id(self.tcx.hir().definitions().node_to_hir_id(id));
767+
if push.changed {
768+
self.levels.register_id(self.tcx.hir().definitions().node_to_hir_id(id));
769+
}
746770
f(self);
747771
self.levels.pop(push);
748772
}
@@ -807,6 +831,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
807831

808832
pub fn provide(providers: &mut Providers<'_>) {
809833
providers.lint_levels = lint_levels;
834+
providers.lint_level_root_for_def_id = lint_level_root_for_def_id;
810835
}
811836

812837
/// Returns whether `span` originates in a foreign crate's external macro.

src/librustc/ty/context.rs

+31-23
Original file line numberDiff line numberDiff line change
@@ -2857,31 +2857,39 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
28572857
err.emit()
28582858
}
28592859

2860-
pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
2860+
pub fn lint_level_root(self, mut id: ast::NodeId) -> ast::NodeId {
2861+
// If the `id` has a DefId, just use the query to avoid
2862+
// adding dependencies to its parents
2863+
if let Some(def_id) = self.hir().opt_local_def_id(id) {
2864+
return self.hir().hir_to_node_id(self.lint_level_root_for_def_id(def_id));
2865+
}
2866+
2867+
let sets = self.lint_levels(LOCAL_CRATE);
2868+
loop {
2869+
let hir_id = self.hir().definitions().node_to_hir_id(id);
2870+
if sets.lint_level_set(hir_id).is_some() {
2871+
return id
2872+
}
2873+
let next = self.hir().get_parent_node(id);
2874+
if next == id {
2875+
bug!("lint traversal reached the root of the crate");
2876+
}
2877+
// If we find a node with a DefId, stop adding dependencies
2878+
// to the parents of `id` and just use the query
2879+
if let Some(def_id) = self.hir().opt_local_def_id(next) {
2880+
return self.hir().hir_to_node_id(self.lint_level_root_for_def_id(def_id));
2881+
}
2882+
id = next;
2883+
}
2884+
}
2885+
2886+
pub fn lint_level_at_node(self, lint: &'static Lint, id: NodeId)
28612887
-> (lint::Level, lint::LintSource)
28622888
{
2863-
// Right now we insert a `with_ignore` node in the dep graph here to
2864-
// ignore the fact that `lint_levels` below depends on the entire crate.
2865-
// For now this'll prevent false positives of recompiling too much when
2866-
// anything changes.
2867-
//
2868-
// Once red/green incremental compilation lands we should be able to
2869-
// remove this because while the crate changes often the lint level map
2870-
// will change rarely.
2871-
self.dep_graph.with_ignore(|| {
2872-
let sets = self.lint_levels(LOCAL_CRATE);
2873-
loop {
2874-
let hir_id = self.hir().definitions().node_to_hir_id(id);
2875-
if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) {
2876-
return pair
2877-
}
2878-
let next = self.hir().get_parent_node(id);
2879-
if next == id {
2880-
bug!("lint traversal reached the root of the crate");
2881-
}
2882-
id = next;
2883-
}
2884-
})
2889+
let sets = self.lint_levels(LOCAL_CRATE);
2890+
let lint_root = self.lint_level_root(id);
2891+
let hir_id = self.hir().definitions().node_to_hir_id(lint_root);
2892+
sets.level_and_source(lint, hir_id, self.sess).unwrap()
28852893
}
28862894

28872895
pub fn struct_span_lint_hir<S: Into<MultiSpan>>(self,

src/librustc/ty/query/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use dep_graph::{DepConstructor, DepNode};
22
use errors::DiagnosticBuilder;
33
use hir::def_id::{CrateNum, DefId, DefIndex};
44
use hir::def::{Def, Export};
5-
use hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs};
5+
use hir::{self, HirId, TraitCandidate, ItemLocalId, CodegenFnAttrs};
66
use rustc_data_structures::svh::Svh;
77
use infer::canonical::{self, Canonical};
88
use lint;
@@ -443,6 +443,7 @@ define_queries! { <'tcx>
443443
Other {
444444
[] fn module_exports: ModuleExports(DefId) -> Option<Lrc<Vec<Export>>>,
445445
[] fn lint_levels: lint_levels_node(CrateNum) -> Lrc<lint::LintLevelMap>,
446+
[] fn lint_level_root_for_def_id: LintLevelRootForDefId(DefId) -> HirId,
446447
},
447448

448449
TypeChecking {

src/librustc/ty/query/plumbing.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
400400
return Ok(result);
401401
}
402402

403-
if !dep_node.kind.is_input() {
403+
if !dep_node.kind.is_input() && !dep_node.kind.is_eval_always() {
404404
if let Some((prev_dep_node_index,
405405
dep_node_index)) = self.dep_graph.try_mark_green_and_read(self,
406406
&dep_node) {
@@ -1330,6 +1330,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
13301330
DepKind::HasPanicHandler => { force!(has_panic_handler, krate!()); }
13311331
DepKind::ExternCrate => { force!(extern_crate, def_id!()); }
13321332
DepKind::LintLevels => { force!(lint_levels, LOCAL_CRATE); }
1333+
DepKind::LintLevelRootForDefId => { force!(lint_level_root_for_def_id, def_id!()); }
13331334
DepKind::InScopeTraits => { force!(in_scope_traits_map, def_id!().index); }
13341335
DepKind::ModuleExports => { force!(module_exports, def_id!()); }
13351336
DepKind::IsSanitizerRuntime => { force!(is_sanitizer_runtime, krate!()); }

src/librustc_mir/build/scope.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ use hair::LintLevel;
8282
use rustc::middle::region;
8383
use rustc::ty::Ty;
8484
use rustc::hir;
85-
use rustc::hir::def_id::LOCAL_CRATE;
8685
use rustc::mir::*;
8786
use syntax_pos::{Span};
8887
use rustc_data_structures::fx::FxHashMap;
@@ -309,19 +308,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
309308
let source_scope = self.source_scope;
310309
let tcx = self.hir.tcx();
311310
if let LintLevel::Explicit(node_id) = lint_level {
312-
let same_lint_scopes = tcx.dep_graph.with_ignore(|| {
313-
let sets = tcx.lint_levels(LOCAL_CRATE);
314-
let parent_hir_id =
315-
tcx.hir().definitions().node_to_hir_id(
316-
self.source_scope_local_data[source_scope].lint_root
317-
);
318-
let current_hir_id =
319-
tcx.hir().definitions().node_to_hir_id(node_id);
320-
sets.lint_level_set(parent_hir_id) ==
321-
sets.lint_level_set(current_hir_id)
322-
});
323-
324-
if !same_lint_scopes {
311+
let parent_root = tcx.lint_level_root(
312+
self.source_scope_local_data[source_scope].lint_root
313+
);
314+
let current_root = tcx.lint_level_root(node_id);
315+
316+
if parent_root != current_root {
317+
// FIXME: The new source scope should use `current_root`
318+
// but that causes bindings to be created in the wrong
319+
// source scope which might affect debug info
325320
self.source_scope =
326321
self.new_source_scope(region_scope.1.span, lint_level,
327322
None);

src/librustc_mir/hair/cx/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
101101
},
102102
pattern,
103103
initializer: local.init.to_ref(),
104-
lint_level: cx.lint_level_of(local.id),
104+
lint_level: LintLevel::Explicit(local.id),
105105
},
106106
opt_destruction_scope: opt_dxn_ext,
107107
span: stmt_span,

src/librustc_mir/hair/cx/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
4444
kind: ExprKind::Scope {
4545
region_scope: expr_scope,
4646
value: expr.to_ref(),
47-
lint_level: cx.lint_level_of(self.id),
47+
lint_level: LintLevel::Explicit(self.id),
4848
},
4949
};
5050

src/librustc_mir/hair/cx/mod.rs

+2-41
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hair::*;
88
use hair::util::UserAnnotatedTyHelpers;
99

1010
use rustc_data_structures::indexed_vec::Idx;
11-
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
11+
use rustc::hir::def_id::DefId;
1212
use rustc::hir::Node;
1313
use rustc::middle::region;
1414
use rustc::infer::InferCtxt;
@@ -78,11 +78,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
7878
// Constants always need overflow checks.
7979
check_overflow |= constness == hir::Constness::Const;
8080

81-
let lint_level = lint_level_for_hir_id(tcx, src_id);
8281
Cx {
8382
tcx,
8483
infcx,
85-
root_lint_level: lint_level,
84+
root_lint_level: tcx.lint_level_root(src_id),
8685
param_env: tcx.param_env(src_def_id),
8786
identity_substs: Substs::identity_for_item(tcx.global_tcx(), src_def_id),
8887
region_scope_tree: tcx.region_scope_tree(src_def_id),
@@ -199,19 +198,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
199198
ty.needs_drop(self.tcx.global_tcx(), param_env)
200199
}
201200

202-
fn lint_level_of(&self, node_id: ast::NodeId) -> LintLevel {
203-
let hir_id = self.tcx.hir().definitions().node_to_hir_id(node_id);
204-
let has_lint_level = self.tcx.dep_graph.with_ignore(|| {
205-
self.tcx.lint_levels(LOCAL_CRATE).lint_level_set(hir_id).is_some()
206-
});
207-
208-
if has_lint_level {
209-
LintLevel::Explicit(node_id)
210-
} else {
211-
LintLevel::Inherited
212-
}
213-
}
214-
215201
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
216202
self.tcx
217203
}
@@ -239,31 +225,6 @@ impl UserAnnotatedTyHelpers<'gcx, 'tcx> for Cx<'_, 'gcx, 'tcx> {
239225
}
240226
}
241227

242-
fn lint_level_for_hir_id(tcx: TyCtxt, mut id: ast::NodeId) -> ast::NodeId {
243-
// Right now we insert a `with_ignore` node in the dep graph here to
244-
// ignore the fact that `lint_levels` below depends on the entire crate.
245-
// For now this'll prevent false positives of recompiling too much when
246-
// anything changes.
247-
//
248-
// Once red/green incremental compilation lands we should be able to
249-
// remove this because while the crate changes often the lint level map
250-
// will change rarely.
251-
tcx.dep_graph.with_ignore(|| {
252-
let sets = tcx.lint_levels(LOCAL_CRATE);
253-
loop {
254-
let hir_id = tcx.hir().definitions().node_to_hir_id(id);
255-
if sets.lint_level_set(hir_id).is_some() {
256-
return id
257-
}
258-
let next = tcx.hir().get_parent_node(id);
259-
if next == id {
260-
bug!("lint traversal reached the root of the crate");
261-
}
262-
id = next;
263-
}
264-
})
265-
}
266-
267228
mod block;
268229
mod expr;
269230
mod to_ref;

0 commit comments

Comments
 (0)