store typeck lints in the TypeckTables

Otherwise they are a "hidden output"
This commit is contained in:
Niko Matsakis 2017-01-28 18:13:21 -05:00
parent 65b93ebcb8
commit d9aaca71cc
13 changed files with 87 additions and 32 deletions

1
src/Cargo.lock generated
View File

@ -364,6 +364,7 @@ dependencies = [
name = "rustc_errors"
version = "0.0.0"
dependencies = [
"serialize 0.0.0",
"syntax_pos 0.0.0",
]

View File

@ -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<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_str(&self.lint.name.to_lowercase())
}
}
impl Decodable for LintId {
#[inline]
fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
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),
}
})
}
}

View File

@ -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,

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Vec<EarlyLint>>
}
@ -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.

View File

@ -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<ty::cast::CastKind>,
/// 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(),
}
}

View File

@ -9,4 +9,5 @@ path = "lib.rs"
crate-type = ["dylib"]
[dependencies]
serialize = { path = "../libserialize" }
syntax_pos = { path = "../libsyntax_pos" }

View File

@ -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)>,

View File

@ -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<String>,
@ -477,7 +478,7 @@ impl Handler {
}
#[derive(Copy, PartialEq, Clone, Debug)]
#[derive(Copy, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Level {
Bug,
Fatal,

View File

@ -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,

View File

@ -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)));
}
}

View File

@ -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));
}
}

View File

@ -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

View File

@ -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>,
span_labels: Vec<(Span, String)>,