Skip to content

Commit e4eea73

Browse files
committed
Auto merge of #39434 - nikomatsakis:incr-comp-skip-typeck-2, r=eddyb
Miscellaneous refactors around how lints and typeck interact This is preparation for making incr. comp. skip typeck. The main gist of is trying to rationalize the outputs from typeck that are not part of tables: - one bit of output is the `used_trait_imports` set, which becomes something we track for dependencies - the other big of output are various lints; we used to store these into a table on sess, but this work stores them into the`TypeckTables`, and then makes the lint pass consult that - I think it probably makes sense to handle errors similarly, eventually, but that's not necessary now r? @eddyb Fixes #39495
2 parents 8568fdc + 2fc1586 commit e4eea73

File tree

26 files changed

+290
-131
lines changed

26 files changed

+290
-131
lines changed

src/Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/librustc/dep_graph/dep_node.rs

+3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ pub enum DepNode<D: Clone + Debug> {
113113
AssociatedItemDefIds(D),
114114
InherentImpls(D),
115115
TypeckTables(D),
116+
UsedTraitImports(D),
116117

117118
// The set of impls for a given trait. Ultimately, it would be
118119
// nice to get more fine-grained here (e.g., to include a
@@ -162,6 +163,7 @@ impl<D: Clone + Debug> DepNode<D> {
162163
AssociatedItemDefIds,
163164
InherentImpls,
164165
TypeckTables,
166+
UsedTraitImports,
165167
TraitImpls,
166168
ReprHints,
167169
}
@@ -230,6 +232,7 @@ impl<D: Clone + Debug> DepNode<D> {
230232
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
231233
InherentImpls(ref d) => op(d).map(InherentImpls),
232234
TypeckTables(ref d) => op(d).map(TypeckTables),
235+
UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
233236
TraitImpls(ref d) => op(d).map(TraitImpls),
234237
TraitItems(ref d) => op(d).map(TraitItems),
235238
ReprHints(ref d) => op(d).map(ReprHints),

src/librustc/dep_graph/dep_tracking_map.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,10 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
6161
self.map.get(k)
6262
}
6363

64-
pub fn get_mut(&mut self, k: &M::Key) -> Option<&mut M::Value> {
65-
self.read(k);
66-
self.write(k);
67-
self.map.get_mut(k)
68-
}
69-
70-
pub fn insert(&mut self, k: M::Key, v: M::Value) -> Option<M::Value> {
64+
pub fn insert(&mut self, k: M::Key, v: M::Value) {
7165
self.write(&k);
72-
self.map.insert(k, v)
66+
let old_value = self.map.insert(k, v);
67+
assert!(old_value.is_none());
7368
}
7469

7570
pub fn contains_key(&self, k: &M::Key) -> bool {
@@ -83,6 +78,10 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
8378

8479
/// Append `elem` to the vector stored for `k`, creating a new vector if needed.
8580
/// This is considered a write to `k`.
81+
///
82+
/// NOTE: Caution is required when using this method. You should
83+
/// be sure that nobody is **reading from the vector** while you
84+
/// are writing to it. Eventually, it'd be nice to remove this.
8685
pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
8786
where M: DepTrackingMapConfig<Value=Vec<E>>
8887
{

src/librustc/lint/context.rs

+31-13
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource};
3333
use lint::{EarlyLintPassObject, LateLintPassObject};
3434
use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
3535
use lint::builtin;
36+
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
3637
use util::nodemap::FxHashMap;
3738

3839
use std::cmp;
@@ -82,7 +83,7 @@ pub struct LintStore {
8283

8384
/// When you call `add_lint` on the session, you wind up storing one
8485
/// of these, which records a "potential lint" at a particular point.
85-
#[derive(PartialEq)]
86+
#[derive(PartialEq, RustcEncodable, RustcDecodable)]
8687
pub struct EarlyLint {
8788
/// what lint is this? (e.g., `dead_code`)
8889
pub id: LintId,
@@ -558,7 +559,7 @@ pub trait LintContext<'tcx>: Sized {
558559
self.lookup_and_emit(lint, Some(span), msg);
559560
}
560561

561-
fn early_lint(&self, early_lint: EarlyLint) {
562+
fn early_lint(&self, early_lint: &EarlyLint) {
562563
let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span");
563564
let mut err = self.struct_span_lint(early_lint.id.lint,
564565
span,
@@ -773,11 +774,10 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
773774

774775
// Output any lints that were previously added to the session.
775776
fn visit_id(&mut self, id: ast::NodeId) {
776-
if let Some(lints) = self.sess().lints.borrow_mut().remove(&id) {
777-
debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints);
778-
for early_lint in lints {
779-
self.early_lint(early_lint);
780-
}
777+
let lints = self.sess().lints.borrow_mut().take(id);
778+
for early_lint in lints.iter().chain(self.tables.lints.get(id)) {
779+
debug!("LateContext::visit_id: id={:?} early_lint={:?}", id, early_lint);
780+
self.early_lint(early_lint);
781781
}
782782
}
783783

@@ -1232,7 +1232,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12321232

12331233
// If we missed any lints added to the session, then there's a bug somewhere
12341234
// in the iteration code.
1235-
for (id, v) in tcx.sess.lints.borrow().iter() {
1235+
if let Some((id, v)) = tcx.sess.lints.borrow().get_any() {
12361236
for early_lint in v {
12371237
span_bug!(early_lint.diagnostic.span.clone(),
12381238
"unprocessed lint {:?} at {}",
@@ -1250,10 +1250,9 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
12501250
// Visit the whole crate.
12511251
cx.with_lint_attrs(&krate.attrs, |cx| {
12521252
// Lints may be assigned to the whole crate.
1253-
if let Some(lints) = cx.sess.lints.borrow_mut().remove(&ast::CRATE_NODE_ID) {
1254-
for early_lint in lints {
1255-
cx.early_lint(early_lint);
1256-
}
1253+
let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID);
1254+
for early_lint in lints {
1255+
cx.early_lint(&early_lint);
12571256
}
12581257

12591258
// since the root module isn't visited as an item (because it isn't an
@@ -1270,9 +1269,28 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
12701269

12711270
// If we missed any lints added to the session, then there's a bug somewhere
12721271
// in the iteration code.
1273-
for (_, v) in sess.lints.borrow().iter() {
1272+
for (_, v) in sess.lints.borrow().get_any() {
12741273
for early_lint in v {
12751274
span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?}", early_lint);
12761275
}
12771276
}
12781277
}
1278+
1279+
impl Encodable for LintId {
1280+
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1281+
s.emit_str(&self.lint.name.to_lowercase())
1282+
}
1283+
}
1284+
1285+
impl Decodable for LintId {
1286+
#[inline]
1287+
fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
1288+
let s = d.read_str()?;
1289+
ty::tls::with(|tcx| {
1290+
match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) {
1291+
Ok(id) => Ok(id),
1292+
Err(_) => panic!("invalid lint-id `{}`", s),
1293+
}
1294+
})
1295+
}
1296+
}

src/librustc/lint/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,20 @@
3131
pub use self::Level::*;
3232
pub use self::LintSource::*;
3333

34+
use hir;
35+
use hir::intravisit::FnKind;
3436
use std::hash;
3537
use std::ascii::AsciiExt;
3638
use syntax_pos::Span;
37-
use hir::intravisit::FnKind;
3839
use syntax::visit as ast_visit;
3940
use syntax::ast;
40-
use hir;
4141

4242
pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
4343
raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
4444
raw_struct_lint, FutureIncompatibleInfo, EarlyLint, IntoEarlyLint};
4545

46+
pub use lint::table::LintTable;
47+
4648
/// Specification of a single lint.
4749
#[derive(Copy, Clone, Debug)]
4850
pub struct Lint {
@@ -346,3 +348,4 @@ pub type LevelSource = (Level, LintSource);
346348

347349
pub mod builtin;
348350
mod context;
351+
mod table;

src/librustc/lint/table.rs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use syntax::ast;
12+
use syntax_pos::MultiSpan;
13+
use util::nodemap::NodeMap;
14+
15+
use super::{Lint, LintId, EarlyLint, IntoEarlyLint};
16+
17+
#[derive(RustcEncodable, RustcDecodable)]
18+
pub struct LintTable {
19+
map: NodeMap<Vec<EarlyLint>>
20+
}
21+
22+
impl LintTable {
23+
pub fn new() -> Self {
24+
LintTable { map: NodeMap() }
25+
}
26+
27+
pub fn add_lint<S: Into<MultiSpan>>(&mut self,
28+
lint: &'static Lint,
29+
id: ast::NodeId,
30+
sp: S,
31+
msg: String)
32+
{
33+
self.add_lint_diagnostic(lint, id, (sp, &msg[..]))
34+
}
35+
36+
pub fn add_lint_diagnostic<M>(&mut self,
37+
lint: &'static Lint,
38+
id: ast::NodeId,
39+
msg: M)
40+
where M: IntoEarlyLint,
41+
{
42+
let lint_id = LintId::of(lint);
43+
let early_lint = msg.into_early_lint(lint_id);
44+
let arr = self.map.entry(id).or_insert(vec![]);
45+
if !arr.contains(&early_lint) {
46+
arr.push(early_lint);
47+
}
48+
}
49+
50+
pub fn get(&self, id: ast::NodeId) -> &[EarlyLint] {
51+
self.map.get(&id).map(|v| &v[..]).unwrap_or(&[])
52+
}
53+
54+
pub fn take(&mut self, id: ast::NodeId) -> Vec<EarlyLint> {
55+
self.map.remove(&id).unwrap_or(vec![])
56+
}
57+
58+
pub fn transfer(&mut self, into: &mut LintTable) {
59+
into.map.extend(self.map.drain());
60+
}
61+
62+
/// Returns the first (id, lint) pair that is non-empty. Used to
63+
/// implement a sanity check in lints that all node-ids are
64+
/// visited.
65+
pub fn get_any(&self) -> Option<(&ast::NodeId, &Vec<EarlyLint>)> {
66+
self.map.iter()
67+
.filter(|&(_, v)| !v.is_empty())
68+
.next()
69+
}
70+
}
71+

src/librustc/session/mod.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use middle::dependency_format;
2020
use session::search_paths::PathKind;
2121
use session::config::DebugInfoLevel;
2222
use ty::tls;
23-
use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
23+
use util::nodemap::{FxHashMap, FxHashSet};
2424
use util::common::duration_to_secs_str;
2525
use mir::transform as mir_pass;
2626

@@ -78,7 +78,7 @@ pub struct Session {
7878
pub local_crate_source_file: Option<PathBuf>,
7979
pub working_dir: PathBuf,
8080
pub lint_store: RefCell<lint::LintStore>,
81-
pub lints: RefCell<NodeMap<Vec<lint::EarlyLint>>>,
81+
pub lints: RefCell<lint::LintTable>,
8282
/// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics
8383
/// that have been set once, but should not be set again, in order to avoid
8484
/// redundantly verbose output (Issue #24690).
@@ -270,13 +270,14 @@ impl Session {
270270
pub fn unimpl(&self, msg: &str) -> ! {
271271
self.diagnostic().unimpl(msg)
272272
}
273+
273274
pub fn add_lint<S: Into<MultiSpan>>(&self,
274275
lint: &'static lint::Lint,
275276
id: ast::NodeId,
276277
sp: S,
277278
msg: String)
278279
{
279-
self.add_lint_diagnostic(lint, id, (sp, &msg[..]))
280+
self.lints.borrow_mut().add_lint(lint, id, sp, msg);
280281
}
281282

282283
pub fn add_lint_diagnostic<M>(&self,
@@ -285,17 +286,9 @@ impl Session {
285286
msg: M)
286287
where M: lint::IntoEarlyLint,
287288
{
288-
let lint_id = lint::LintId::of(lint);
289-
let mut lints = self.lints.borrow_mut();
290-
let early_lint = msg.into_early_lint(lint_id);
291-
if let Some(arr) = lints.get_mut(&id) {
292-
if !arr.contains(&early_lint) {
293-
arr.push(early_lint);
294-
}
295-
return;
296-
}
297-
lints.insert(id, vec![early_lint]);
289+
self.lints.borrow_mut().add_lint_diagnostic(lint, id, msg);
298290
}
291+
299292
pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId {
300293
let id = self.next_node_id.get();
301294

@@ -617,7 +610,7 @@ pub fn build_session_(sopts: config::Options,
617610
local_crate_source_file: local_crate_source_file,
618611
working_dir: env::current_dir().unwrap(),
619612
lint_store: RefCell::new(lint::LintStore::new()),
620-
lints: RefCell::new(NodeMap()),
613+
lints: RefCell::new(lint::LintTable::new()),
621614
one_time_diagnostics: RefCell::new(FxHashSet()),
622615
plugin_llvm_passes: RefCell::new(Vec::new()),
623616
mir_passes: RefCell::new(mir_pass::Passes::new()),

src/librustc/ty/context.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use dep_graph::{DepGraph, DepTrackingMap};
1414
use session::Session;
15+
use lint;
1516
use middle;
1617
use hir::TraitMap;
1718
use hir::def::Def;
@@ -237,6 +238,9 @@ pub struct TypeckTables<'tcx> {
237238
/// Maps a cast expression to its kind. This is keyed on the
238239
/// *from* expression of the cast, not the cast itself.
239240
pub cast_kinds: NodeMap<ty::cast::CastKind>,
241+
242+
/// Lints for the body of this fn generated by typeck.
243+
pub lints: lint::LintTable,
240244
}
241245

242246
impl<'tcx> TypeckTables<'tcx> {
@@ -253,6 +257,7 @@ impl<'tcx> TypeckTables<'tcx> {
253257
liberated_fn_sigs: NodeMap(),
254258
fru_field_types: NodeMap(),
255259
cast_kinds: NodeMap(),
260+
lints: lint::LintTable::new(),
256261
}
257262
}
258263

@@ -494,7 +499,7 @@ pub struct GlobalCtxt<'tcx> {
494499

495500
/// Set of trait imports actually used in the method resolution.
496501
/// This is used for warning unused imports.
497-
pub used_trait_imports: RefCell<NodeSet>,
502+
pub used_trait_imports: RefCell<DepTrackingMap<maps::UsedTraitImports<'tcx>>>,
498503

499504
/// The set of external nominal types whose implementations have been read.
500505
/// This is used for lazy resolution of methods.
@@ -783,7 +788,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
783788
inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
784789
used_unsafe: RefCell::new(NodeSet()),
785790
used_mut_nodes: RefCell::new(NodeSet()),
786-
used_trait_imports: RefCell::new(NodeSet()),
791+
used_trait_imports: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
787792
populated_external_types: RefCell::new(DefIdSet()),
788793
populated_external_primitive_impls: RefCell::new(DefIdSet()),
789794
stability: RefCell::new(stability),

src/librustc/ty/maps.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use dep_graph::{DepNode, DepTrackingMapConfig};
1212
use hir::def_id::DefId;
1313
use mir;
1414
use ty::{self, Ty};
15+
use util::nodemap::DefIdSet;
1516

1617
use std::cell::RefCell;
1718
use std::marker::PhantomData;
@@ -49,3 +50,4 @@ dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
4950
dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind }
5051
dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> }
5152
dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> }
53+
dep_map_ty! { UsedTraitImports: UsedTraitImports(DefId) -> DefIdSet }

src/librustc_errors/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ path = "lib.rs"
99
crate-type = ["dylib"]
1010

1111
[dependencies]
12+
serialize = { path = "../libserialize" }
1213
syntax_pos = { path = "../libsyntax_pos" }

0 commit comments

Comments
 (0)