From d9aaca71cc61a7c0792da2789b5e278cc294733f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 28 Jan 2017 18:13:21 -0500 Subject: [PATCH] store typeck lints in the `TypeckTables` Otherwise they are a "hidden output" --- src/Cargo.lock | 1 + src/librustc/lint/context.rs | 28 ++++++++++++++++++--- src/librustc/lint/mod.rs | 4 +-- src/librustc/lint/table.rs | 15 ++++++++++++ src/librustc/ty/context.rs | 5 ++++ src/librustc_errors/Cargo.toml | 1 + src/librustc_errors/diagnostic.rs | 4 +-- src/librustc_errors/lib.rs | 7 +++--- src/librustc_errors/snippet.rs | 2 +- src/librustc_typeck/check/cast.rs | 34 ++++++++++++++------------ src/librustc_typeck/check/mod.rs | 7 +++--- src/librustc_typeck/check/writeback.rs | 9 +++++++ src/libsyntax_pos/lib.rs | 2 +- 13 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 93bbf0f227b..f40d50dd59d 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -364,6 +364,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ + "serialize 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index edf5666a3a5..362117d860a 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -33,6 +33,7 @@ use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; use lint::{EarlyLintPassObject, LateLintPassObject}; use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid}; use lint::builtin; +use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use util::nodemap::FxHashMap; use std::cmp; @@ -82,7 +83,7 @@ pub struct LintStore { /// When you call `add_lint` on the session, you wind up storing one /// of these, which records a "potential lint" at a particular point. -#[derive(PartialEq)] +#[derive(PartialEq, RustcEncodable, RustcDecodable)] pub struct EarlyLint { /// what lint is this? (e.g., `dead_code`) pub id: LintId, @@ -558,7 +559,7 @@ pub trait LintContext<'tcx>: Sized { self.lookup_and_emit(lint, Some(span), msg); } - fn early_lint(&self, early_lint: EarlyLint) { + fn early_lint(&self, early_lint: &EarlyLint) { let span = early_lint.diagnostic.span.primary_span().expect("early lint w/o primary span"); let mut err = self.struct_span_lint(early_lint.id.lint, span, @@ -774,7 +775,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { // Output any lints that were previously added to the session. fn visit_id(&mut self, id: ast::NodeId) { let lints = self.sess().lints.borrow_mut().take(id); - for early_lint in lints { + for early_lint in lints.iter().chain(self.tables.lints.get(id)) { debug!("LateContext::visit_id: id={:?} early_lint={:?}", id, early_lint); self.early_lint(early_lint); } @@ -1251,7 +1252,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // Lints may be assigned to the whole crate. let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID); for early_lint in lints { - cx.early_lint(early_lint); + cx.early_lint(&early_lint); } // since the root module isn't visited as an item (because it isn't an @@ -1274,3 +1275,22 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { } } } + +impl Encodable for LintId { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_str(&self.lint.name.to_lowercase()) + } +} + +impl Decodable for LintId { + #[inline] + fn decode(d: &mut D) -> Result { + let s = d.read_str()?; + ty::tls::with(|tcx| { + match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) { + Ok(id) => Ok(id), + Err(_) => panic!("invalid lint-id `{}`", s), + } + }) + } +} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 704e32e2d0c..d12065ca86e 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -31,13 +31,13 @@ pub use self::Level::*; pub use self::LintSource::*; +use hir; +use hir::intravisit::FnKind; use std::hash; use std::ascii::AsciiExt; use syntax_pos::Span; -use hir::intravisit::FnKind; use syntax::visit as ast_visit; use syntax::ast; -use hir; pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, raw_emit_lint, check_crate, check_ast_crate, gather_attrs, diff --git a/src/librustc/lint/table.rs b/src/librustc/lint/table.rs index 3b6d268b08f..f2dab25229a 100644 --- a/src/librustc/lint/table.rs +++ b/src/librustc/lint/table.rs @@ -1,9 +1,20 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + use syntax::ast; use syntax_pos::MultiSpan; use util::nodemap::NodeMap; use super::{Lint, LintId, EarlyLint, IntoEarlyLint}; +#[derive(RustcEncodable, RustcDecodable)] pub struct LintTable { map: NodeMap> } @@ -44,6 +55,10 @@ impl LintTable { self.map.remove(&id).unwrap_or(vec![]) } + pub fn transfer(&mut self, into: &mut LintTable) { + into.map.extend(self.map.drain()); + } + /// Returns the first (id, lint) pair that is non-empty. Used to /// implement a sanity check in lints that all node-ids are /// visited. diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5913ed48528..a3b81586738 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -12,6 +12,7 @@ use dep_graph::{DepGraph, DepTrackingMap}; use session::Session; +use lint; use middle; use hir::TraitMap; use hir::def::Def; @@ -237,6 +238,9 @@ pub struct TypeckTables<'tcx> { /// Maps a cast expression to its kind. This is keyed on the /// *from* expression of the cast, not the cast itself. pub cast_kinds: NodeMap, + + /// Lints for the body of this fn generated by typeck. + pub lints: lint::LintTable, } impl<'tcx> TypeckTables<'tcx> { @@ -253,6 +257,7 @@ impl<'tcx> TypeckTables<'tcx> { liberated_fn_sigs: NodeMap(), fru_field_types: NodeMap(), cast_kinds: NodeMap(), + lints: lint::LintTable::new(), } } diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 2ba1f501a63..78ff52b4b23 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -9,4 +9,5 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] +serialize = { path = "../libserialize" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index ac39af20189..1b77ead92de 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -17,7 +17,7 @@ use syntax_pos::{MultiSpan, Span}; use snippet::Style; #[must_use] -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct Diagnostic { pub level: Level, pub message: Vec<(String, Style)>, @@ -27,7 +27,7 @@ pub struct Diagnostic { } /// For example a note attached to an error. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct SubDiagnostic { pub level: Level, pub message: Vec<(String, Style)>, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index bf5f7cde7eb..d7bd5ed23c2 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -26,6 +26,7 @@ extern crate term; extern crate libc; +extern crate serialize as rustc_serialize; extern crate syntax_pos; pub use emitter::ColorConfig; @@ -49,7 +50,7 @@ mod lock; use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; use syntax_pos::MacroBacktrace; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum RenderSpan { /// A FullSpan renders with both with an initial line for the /// message, prefixed by file:linenum, followed by a summary of @@ -63,7 +64,7 @@ pub enum RenderSpan { Suggestion(CodeSuggestion), } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub struct CodeSuggestion { pub msp: MultiSpan, pub substitutes: Vec, @@ -477,7 +478,7 @@ impl Handler { } -#[derive(Copy, PartialEq, Clone, Debug)] +#[derive(Copy, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)] pub enum Level { Bug, Fatal, diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs index 95b03677b72..5debbf4d37c 100644 --- a/src/librustc_errors/snippet.rs +++ b/src/librustc_errors/snippet.rs @@ -204,7 +204,7 @@ pub struct StyledString { pub style: Style, } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Style { HeaderMsg, FileNameStyle, diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 6215b4498dc..441d427fe49 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -311,23 +311,25 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { let t_cast = self.cast_ty; let t_expr = self.expr_ty; if t_cast.is_numeric() && t_expr.is_numeric() { - fcx.tcx.sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS, - self.expr.id, - self.span, - format!("trivial numeric cast: `{}` as `{}`. Cast can be \ - replaced by coercion, this might require type \ - ascription or a temporary variable", - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast))); + fcx.tables.borrow_mut().lints.add_lint( + lint::builtin::TRIVIAL_NUMERIC_CASTS, + self.expr.id, + self.span, + format!("trivial numeric cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast))); } else { - fcx.tcx.sess.add_lint(lint::builtin::TRIVIAL_CASTS, - self.expr.id, - self.span, - format!("trivial cast: `{}` as `{}`. Cast can be \ - replaced by coercion, this might require type \ - ascription or a temporary variable", - fcx.ty_to_string(t_expr), - fcx.ty_to_string(t_cast))); + fcx.tables.borrow_mut().lints.add_lint( + lint::builtin::TRIVIAL_CASTS, + self.expr.id, + self.span, + format!("trivial cast: `{}` as `{}`. Cast can be \ + replaced by coercion, this might require type \ + ascription or a temporary variable", + fcx.ty_to_string(t_expr), + fcx.ty_to_string(t_cast))); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c435f934125..573cbfcc3b0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1521,9 +1521,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if self.diverges.get() == Diverges::Always { self.diverges.set(Diverges::WarnedAlways); - self.tcx.sess.add_lint(lint::builtin::UNREACHABLE_CODE, - id, span, - format!("unreachable {}", kind)); + self.tables.borrow_mut().lints.add_lint( + lint::builtin::UNREACHABLE_CODE, + id, span, + format!("unreachable {}", kind)); } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 7f82d7829ce..3a467c0296a 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -52,6 +52,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { wbcx.visit_deferred_obligations(item_id); wbcx.visit_type_nodes(); wbcx.visit_cast_types(); + wbcx.visit_lints(); let tables = self.tcx.alloc_tables(wbcx.tables); self.tcx.tables.borrow_mut().insert(item_def_id, tables); @@ -301,6 +302,14 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { self.fcx.tables.borrow().cast_kinds.iter().map(|(&key, &value)| (key, value))); } + fn visit_lints(&mut self) { + if self.fcx.writeback_errors.get() { + return + } + + self.fcx.tables.borrow_mut().lints.transfer(&mut self.tables.lints); + } + fn visit_anon_types(&self) { if self.fcx.writeback_errors.get() { return diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 92fdb45caaa..3808923e772 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -66,7 +66,7 @@ pub struct Span { /// the error, and would be rendered with `^^^`. /// - they can have a *label*. In this case, the label is written next /// to the mark in the snippet when we render. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub struct MultiSpan { primary_spans: Vec, span_labels: Vec<(Span, String)>,