name = "rustc_errors"
version = "0.0.0"
dependencies = [
+ "serialize 0.0.0",
"syntax_pos 0.0.0",
]
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;
/// 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,
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,
// 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);
}
// 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
}
}
}
+
+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),
+ }
+ })
+ }
+}
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,
+// 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>>
}
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.
use dep_graph::{DepGraph, DepTrackingMap};
use session::Session;
+use lint;
use middle;
use hir::TraitMap;
use hir::def::Def;
/// 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> {
liberated_fn_sigs: NodeMap(),
fru_field_types: NodeMap(),
cast_kinds: NodeMap(),
+ lints: lint::LintTable::new(),
}
}
crate-type = ["dylib"]
[dependencies]
+serialize = { path = "../libserialize" }
syntax_pos = { path = "../libsyntax_pos" }
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)>,
}
/// 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)>,
extern crate term;
extern crate libc;
+extern crate serialize as rustc_serialize;
extern crate syntax_pos;
pub use emitter::ColorConfig;
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
Suggestion(CodeSuggestion),
}
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct CodeSuggestion {
pub msp: MultiSpan,
pub substitutes: Vec<String>,
}
-#[derive(Copy, PartialEq, Clone, Debug)]
+#[derive(Copy, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Level {
Bug,
Fatal,
pub style: Style,
}
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Style {
HeaderMsg,
FileNameStyle,
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)));
}
}
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));
}
}
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);
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
/// 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)>,