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
This commit is contained in:
commit
e4eea73306
26 changed files with 290 additions and 131 deletions
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
|
@ -363,6 +363,7 @@ dependencies = [
|
|||
name = "rustc_errors"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"serialize 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ pub enum DepNode<D: Clone + Debug> {
|
|||
AssociatedItemDefIds(D),
|
||||
InherentImpls(D),
|
||||
TypeckTables(D),
|
||||
UsedTraitImports(D),
|
||||
|
||||
// The set of impls for a given trait. Ultimately, it would be
|
||||
// nice to get more fine-grained here (e.g., to include a
|
||||
|
@ -162,6 +163,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
|||
AssociatedItemDefIds,
|
||||
InherentImpls,
|
||||
TypeckTables,
|
||||
UsedTraitImports,
|
||||
TraitImpls,
|
||||
ReprHints,
|
||||
}
|
||||
|
@ -230,6 +232,7 @@ impl<D: Clone + Debug> DepNode<D> {
|
|||
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
|
||||
InherentImpls(ref d) => op(d).map(InherentImpls),
|
||||
TypeckTables(ref d) => op(d).map(TypeckTables),
|
||||
UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
|
||||
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||
TraitItems(ref d) => op(d).map(TraitItems),
|
||||
ReprHints(ref d) => op(d).map(ReprHints),
|
||||
|
|
|
@ -61,15 +61,10 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
|
|||
self.map.get(k)
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, k: &M::Key) -> Option<&mut M::Value> {
|
||||
self.read(k);
|
||||
self.write(k);
|
||||
self.map.get_mut(k)
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, k: M::Key, v: M::Value) -> Option<M::Value> {
|
||||
pub fn insert(&mut self, k: M::Key, v: M::Value) {
|
||||
self.write(&k);
|
||||
self.map.insert(k, v)
|
||||
let old_value = self.map.insert(k, v);
|
||||
assert!(old_value.is_none());
|
||||
}
|
||||
|
||||
pub fn contains_key(&self, k: &M::Key) -> bool {
|
||||
|
@ -83,6 +78,10 @@ impl<M: DepTrackingMapConfig> DepTrackingMap<M> {
|
|||
|
||||
/// Append `elem` to the vector stored for `k`, creating a new vector if needed.
|
||||
/// This is considered a write to `k`.
|
||||
///
|
||||
/// NOTE: Caution is required when using this method. You should
|
||||
/// be sure that nobody is **reading from the vector** while you
|
||||
/// are writing to it. Eventually, it'd be nice to remove this.
|
||||
pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
|
||||
where M: DepTrackingMapConfig<Value=Vec<E>>
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
@ -773,11 +774,10 @@ 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) {
|
||||
if let Some(lints) = self.sess().lints.borrow_mut().remove(&id) {
|
||||
debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints);
|
||||
for early_lint in lints {
|
||||
self.early_lint(early_lint);
|
||||
}
|
||||
let lints = self.sess().lints.borrow_mut().take(id);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1232,7 +1232,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
// If we missed any lints added to the session, then there's a bug somewhere
|
||||
// in the iteration code.
|
||||
for (id, v) in tcx.sess.lints.borrow().iter() {
|
||||
if let Some((id, v)) = tcx.sess.lints.borrow().get_any() {
|
||||
for early_lint in v {
|
||||
span_bug!(early_lint.diagnostic.span.clone(),
|
||||
"unprocessed lint {:?} at {}",
|
||||
|
@ -1250,10 +1250,9 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
|
|||
// Visit the whole crate.
|
||||
cx.with_lint_attrs(&krate.attrs, |cx| {
|
||||
// Lints may be assigned to the whole crate.
|
||||
if let Some(lints) = cx.sess.lints.borrow_mut().remove(&ast::CRATE_NODE_ID) {
|
||||
for early_lint in lints {
|
||||
cx.early_lint(early_lint);
|
||||
}
|
||||
let lints = cx.sess.lints.borrow_mut().take(ast::CRATE_NODE_ID);
|
||||
for early_lint in lints {
|
||||
cx.early_lint(&early_lint);
|
||||
}
|
||||
|
||||
// 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) {
|
|||
|
||||
// If we missed any lints added to the session, then there's a bug somewhere
|
||||
// in the iteration code.
|
||||
for (_, v) in sess.lints.borrow().iter() {
|
||||
for (_, v) in sess.lints.borrow().get_any() {
|
||||
for early_lint in v {
|
||||
span_bug!(early_lint.diagnostic.span.clone(), "unprocessed lint {:?}", early_lint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,18 +31,20 @@
|
|||
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,
|
||||
raw_struct_lint, FutureIncompatibleInfo, EarlyLint, IntoEarlyLint};
|
||||
|
||||
pub use lint::table::LintTable;
|
||||
|
||||
/// Specification of a single lint.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Lint {
|
||||
|
@ -346,3 +348,4 @@ pub type LevelSource = (Level, LintSource);
|
|||
|
||||
pub mod builtin;
|
||||
mod context;
|
||||
mod table;
|
||||
|
|
71
src/librustc/lint/table.rs
Normal file
71
src/librustc/lint/table.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
// 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>>
|
||||
}
|
||||
|
||||
impl LintTable {
|
||||
pub fn new() -> Self {
|
||||
LintTable { map: NodeMap() }
|
||||
}
|
||||
|
||||
pub fn add_lint<S: Into<MultiSpan>>(&mut self,
|
||||
lint: &'static Lint,
|
||||
id: ast::NodeId,
|
||||
sp: S,
|
||||
msg: String)
|
||||
{
|
||||
self.add_lint_diagnostic(lint, id, (sp, &msg[..]))
|
||||
}
|
||||
|
||||
pub fn add_lint_diagnostic<M>(&mut self,
|
||||
lint: &'static Lint,
|
||||
id: ast::NodeId,
|
||||
msg: M)
|
||||
where M: IntoEarlyLint,
|
||||
{
|
||||
let lint_id = LintId::of(lint);
|
||||
let early_lint = msg.into_early_lint(lint_id);
|
||||
let arr = self.map.entry(id).or_insert(vec![]);
|
||||
if !arr.contains(&early_lint) {
|
||||
arr.push(early_lint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, id: ast::NodeId) -> &[EarlyLint] {
|
||||
self.map.get(&id).map(|v| &v[..]).unwrap_or(&[])
|
||||
}
|
||||
|
||||
pub fn take(&mut self, id: ast::NodeId) -> 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.
|
||||
pub fn get_any(&self) -> Option<(&ast::NodeId, &Vec<EarlyLint>)> {
|
||||
self.map.iter()
|
||||
.filter(|&(_, v)| !v.is_empty())
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@ use middle::dependency_format;
|
|||
use session::search_paths::PathKind;
|
||||
use session::config::DebugInfoLevel;
|
||||
use ty::tls;
|
||||
use util::nodemap::{NodeMap, FxHashMap, FxHashSet};
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
use util::common::duration_to_secs_str;
|
||||
use mir::transform as mir_pass;
|
||||
|
||||
|
@ -78,7 +78,7 @@ pub struct Session {
|
|||
pub local_crate_source_file: Option<PathBuf>,
|
||||
pub working_dir: PathBuf,
|
||||
pub lint_store: RefCell<lint::LintStore>,
|
||||
pub lints: RefCell<NodeMap<Vec<lint::EarlyLint>>>,
|
||||
pub lints: RefCell<lint::LintTable>,
|
||||
/// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics
|
||||
/// that have been set once, but should not be set again, in order to avoid
|
||||
/// redundantly verbose output (Issue #24690).
|
||||
|
@ -270,13 +270,14 @@ impl Session {
|
|||
pub fn unimpl(&self, msg: &str) -> ! {
|
||||
self.diagnostic().unimpl(msg)
|
||||
}
|
||||
|
||||
pub fn add_lint<S: Into<MultiSpan>>(&self,
|
||||
lint: &'static lint::Lint,
|
||||
id: ast::NodeId,
|
||||
sp: S,
|
||||
msg: String)
|
||||
{
|
||||
self.add_lint_diagnostic(lint, id, (sp, &msg[..]))
|
||||
self.lints.borrow_mut().add_lint(lint, id, sp, msg);
|
||||
}
|
||||
|
||||
pub fn add_lint_diagnostic<M>(&self,
|
||||
|
@ -285,17 +286,9 @@ impl Session {
|
|||
msg: M)
|
||||
where M: lint::IntoEarlyLint,
|
||||
{
|
||||
let lint_id = lint::LintId::of(lint);
|
||||
let mut lints = self.lints.borrow_mut();
|
||||
let early_lint = msg.into_early_lint(lint_id);
|
||||
if let Some(arr) = lints.get_mut(&id) {
|
||||
if !arr.contains(&early_lint) {
|
||||
arr.push(early_lint);
|
||||
}
|
||||
return;
|
||||
}
|
||||
lints.insert(id, vec![early_lint]);
|
||||
self.lints.borrow_mut().add_lint_diagnostic(lint, id, msg);
|
||||
}
|
||||
|
||||
pub fn reserve_node_ids(&self, count: usize) -> ast::NodeId {
|
||||
let id = self.next_node_id.get();
|
||||
|
||||
|
@ -617,7 +610,7 @@ pub fn build_session_(sopts: config::Options,
|
|||
local_crate_source_file: local_crate_source_file,
|
||||
working_dir: env::current_dir().unwrap(),
|
||||
lint_store: RefCell::new(lint::LintStore::new()),
|
||||
lints: RefCell::new(NodeMap()),
|
||||
lints: RefCell::new(lint::LintTable::new()),
|
||||
one_time_diagnostics: RefCell::new(FxHashSet()),
|
||||
plugin_llvm_passes: RefCell::new(Vec::new()),
|
||||
mir_passes: RefCell::new(mir_pass::Passes::new()),
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,7 +499,7 @@ pub struct GlobalCtxt<'tcx> {
|
|||
|
||||
/// Set of trait imports actually used in the method resolution.
|
||||
/// This is used for warning unused imports.
|
||||
pub used_trait_imports: RefCell<NodeSet>,
|
||||
pub used_trait_imports: RefCell<DepTrackingMap<maps::UsedTraitImports<'tcx>>>,
|
||||
|
||||
/// The set of external nominal types whose implementations have been read.
|
||||
/// This is used for lazy resolution of methods.
|
||||
|
@ -783,7 +788,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
inherent_impls: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
used_unsafe: RefCell::new(NodeSet()),
|
||||
used_mut_nodes: RefCell::new(NodeSet()),
|
||||
used_trait_imports: RefCell::new(NodeSet()),
|
||||
used_trait_imports: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
populated_external_types: RefCell::new(DefIdSet()),
|
||||
populated_external_primitive_impls: RefCell::new(DefIdSet()),
|
||||
stability: RefCell::new(stability),
|
||||
|
|
|
@ -12,6 +12,7 @@ use dep_graph::{DepNode, DepTrackingMapConfig};
|
|||
use hir::def_id::DefId;
|
||||
use mir;
|
||||
use ty::{self, Ty};
|
||||
use util::nodemap::DefIdSet;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -49,3 +50,4 @@ dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
|
|||
dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind }
|
||||
dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> }
|
||||
dep_map_ty! { TypeckTables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx> }
|
||||
dep_map_ty! { UsedTraitImports: UsedTraitImports(DefId) -> DefIdSet }
|
||||
|
|
|
@ -9,4 +9,5 @@ path = "lib.rs"
|
|||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
|
|
@ -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)>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -139,7 +139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
|
|||
|
||||
let mir = tcx.alloc_mir(mir);
|
||||
let def_id = tcx.hir.local_def_id(src.item_id());
|
||||
assert!(tcx.mir_map.borrow_mut().insert(def_id, mir).is_none());
|
||||
tcx.mir_map.borrow_mut().insert(def_id, mir);
|
||||
});
|
||||
|
||||
let body = self.tcx.hir.body(body_id);
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -137,7 +137,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
self_ty, call_expr.id)?;
|
||||
|
||||
if let Some(import_id) = pick.import_id {
|
||||
self.tcx.used_trait_imports.borrow_mut().insert(import_id);
|
||||
let import_def_id = self.tcx.hir.local_def_id(import_id);
|
||||
debug!("used_trait_import: {:?}", import_def_id);
|
||||
self.used_trait_imports.borrow_mut().insert(import_def_id);
|
||||
}
|
||||
|
||||
self.tcx.check_stability(pick.item.def_id, call_expr.id, span);
|
||||
|
@ -336,7 +338,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
self_ty, expr_id)?;
|
||||
|
||||
if let Some(import_id) = pick.import_id {
|
||||
self.tcx.used_trait_imports.borrow_mut().insert(import_id);
|
||||
let import_def_id = self.tcx.hir.local_def_id(import_id);
|
||||
debug!("used_trait_import: {:?}", import_def_id);
|
||||
self.used_trait_imports.borrow_mut().insert(import_def_id);
|
||||
}
|
||||
|
||||
let def = pick.item.def();
|
||||
|
|
|
@ -55,7 +55,6 @@ struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
|||
inherent_candidates: Vec<Candidate<'tcx>>,
|
||||
extension_candidates: Vec<Candidate<'tcx>>,
|
||||
impl_dups: FxHashSet<DefId>,
|
||||
import_id: Option<ast::NodeId>,
|
||||
|
||||
/// Collects near misses when the candidate functions are missing a `self` keyword and is only
|
||||
/// used for error reporting
|
||||
|
@ -351,7 +350,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
inherent_candidates: Vec::new(),
|
||||
extension_candidates: Vec::new(),
|
||||
impl_dups: FxHashSet(),
|
||||
import_id: None,
|
||||
steps: Rc::new(steps),
|
||||
opt_simplified_steps: opt_simplified_steps,
|
||||
static_candidates: Vec::new(),
|
||||
|
@ -530,7 +528,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
xform_self_ty: xform_self_ty,
|
||||
item: item,
|
||||
kind: InherentImplCandidate(impl_substs, obligations),
|
||||
import_id: self.import_id,
|
||||
import_id: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +557,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
xform_self_ty: xform_self_ty,
|
||||
item: item,
|
||||
kind: ObjectCandidate,
|
||||
import_id: this.import_id,
|
||||
import_id: None,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -609,7 +607,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
xform_self_ty: xform_self_ty,
|
||||
item: item,
|
||||
kind: WhereClauseCandidate(poly_trait_ref),
|
||||
import_id: this.import_id,
|
||||
import_id: None,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -644,9 +642,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
for trait_candidate in applicable_traits {
|
||||
let trait_did = trait_candidate.def_id;
|
||||
if duplicates.insert(trait_did) {
|
||||
self.import_id = trait_candidate.import_id;
|
||||
let result = self.assemble_extension_candidates_for_trait(trait_did);
|
||||
self.import_id = None;
|
||||
let import_id = trait_candidate.import_id;
|
||||
let result = self.assemble_extension_candidates_for_trait(import_id, trait_did);
|
||||
result?;
|
||||
}
|
||||
}
|
||||
|
@ -658,7 +655,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
let mut duplicates = FxHashSet();
|
||||
for trait_info in suggest::all_traits(self.ccx) {
|
||||
if duplicates.insert(trait_info.def_id) {
|
||||
self.assemble_extension_candidates_for_trait(trait_info.def_id)?;
|
||||
self.assemble_extension_candidates_for_trait(None, trait_info.def_id)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -682,6 +679,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn assemble_extension_candidates_for_trait(&mut self,
|
||||
import_id: Option<ast::NodeId>,
|
||||
trait_def_id: DefId)
|
||||
-> Result<(), MethodError<'tcx>> {
|
||||
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
|
||||
|
@ -695,19 +693,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
self.assemble_extension_candidates_for_trait_impls(trait_def_id, item.clone());
|
||||
self.assemble_extension_candidates_for_trait_impls(import_id, trait_def_id,
|
||||
item.clone());
|
||||
|
||||
self.assemble_closure_candidates(trait_def_id, item.clone())?;
|
||||
self.assemble_closure_candidates(import_id, trait_def_id, item.clone())?;
|
||||
|
||||
self.assemble_projection_candidates(trait_def_id, item.clone());
|
||||
self.assemble_projection_candidates(import_id, trait_def_id, item.clone());
|
||||
|
||||
self.assemble_where_clause_candidates(trait_def_id, item.clone());
|
||||
self.assemble_where_clause_candidates(import_id, trait_def_id, item.clone());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn assemble_extension_candidates_for_trait_impls(&mut self,
|
||||
import_id: Option<ast::NodeId>,
|
||||
trait_def_id: DefId,
|
||||
item: ty::AssociatedItem) {
|
||||
let trait_def = self.tcx.lookup_trait_def(trait_def_id);
|
||||
|
@ -751,7 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
xform_self_ty: xform_self_ty,
|
||||
item: item.clone(),
|
||||
kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations),
|
||||
import_id: self.import_id,
|
||||
import_id: import_id,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -777,6 +777,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn assemble_closure_candidates(&mut self,
|
||||
import_id: Option<ast::NodeId>,
|
||||
trait_def_id: DefId,
|
||||
item: ty::AssociatedItem)
|
||||
-> Result<(), MethodError<'tcx>> {
|
||||
|
@ -840,7 +841,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
xform_self_ty: xform_self_ty,
|
||||
item: item.clone(),
|
||||
kind: TraitCandidate,
|
||||
import_id: self.import_id,
|
||||
import_id: import_id,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -848,6 +849,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn assemble_projection_candidates(&mut self,
|
||||
import_id: Option<ast::NodeId>,
|
||||
trait_def_id: DefId,
|
||||
item: ty::AssociatedItem) {
|
||||
debug!("assemble_projection_candidates(\
|
||||
|
@ -895,7 +897,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
xform_self_ty: xform_self_ty,
|
||||
item: item.clone(),
|
||||
kind: TraitCandidate,
|
||||
import_id: self.import_id,
|
||||
import_id: import_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -903,6 +905,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn assemble_where_clause_candidates(&mut self,
|
||||
import_id: Option<ast::NodeId>,
|
||||
trait_def_id: DefId,
|
||||
item: ty::AssociatedItem) {
|
||||
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
|
||||
|
@ -923,7 +926,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
xform_self_ty: xform_self_ty,
|
||||
item: item.clone(),
|
||||
kind: WhereClauseCandidate(poly_bound),
|
||||
import_id: self.import_id,
|
||||
import_id: import_id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ use CrateCtxt;
|
|||
use TypeAndSubsts;
|
||||
use lint;
|
||||
use util::common::{ErrorReported, indenter};
|
||||
use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap};
|
||||
use util::nodemap::{DefIdMap, DefIdSet, FxHashMap, FxHashSet, NodeMap};
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cmp;
|
||||
|
@ -179,6 +179,11 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
// Obligations which will have to be checked at the end of
|
||||
// type-checking, after all functions have been inferred.
|
||||
deferred_obligations: RefCell<Vec<traits::DeferredObligation<'tcx>>>,
|
||||
|
||||
// a set of trait import def-ids that we use during method
|
||||
// resolution; during writeback, this is written into
|
||||
// `tcx.used_trait_imports` for this item def-id
|
||||
used_trait_imports: RefCell<FxHashSet<DefId>>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
|
||||
|
@ -513,6 +518,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
|
|||
deferred_cast_checks: RefCell::new(Vec::new()),
|
||||
anon_types: RefCell::new(DefIdMap()),
|
||||
deferred_obligations: RefCell::new(Vec::new()),
|
||||
used_trait_imports: RefCell::new(DefIdSet()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1521,9 +1527,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,9 +19,10 @@ use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
|
|||
use rustc::ty::adjustment;
|
||||
use rustc::ty::fold::{TypeFolder,TypeFoldable};
|
||||
use rustc::infer::{InferCtxt, FixupError};
|
||||
use rustc::util::nodemap::DefIdMap;
|
||||
use rustc::util::nodemap::{DefIdMap, DefIdSet};
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::mem;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
@ -52,9 +53,15 @@ 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);
|
||||
|
||||
let used_trait_imports = mem::replace(&mut *self.used_trait_imports.borrow_mut(),
|
||||
DefIdSet());
|
||||
debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
|
||||
self.tcx.used_trait_imports.borrow_mut().insert(item_def_id, used_trait_imports);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,6 +308,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
|
||||
|
|
|
@ -17,17 +17,21 @@ use syntax_pos::{Span, DUMMY_SP};
|
|||
|
||||
use rustc::hir;
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
|
||||
struct UnusedTraitImportVisitor<'a, 'tcx: 'a> {
|
||||
struct CheckVisitor<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
used_trait_imports: DefIdSet,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> {
|
||||
impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
|
||||
fn check_import(&self, id: ast::NodeId, span: Span) {
|
||||
if !self.tcx.maybe_unused_trait_imports.contains(&id) {
|
||||
return;
|
||||
}
|
||||
if self.tcx.used_trait_imports.borrow().contains(&id) {
|
||||
|
||||
let import_def_id = self.tcx.hir.local_def_id(id);
|
||||
if self.used_trait_imports.contains(&import_def_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -40,7 +44,7 @@ impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> {
|
||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CheckVisitor<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
if item.vis == hir::Public || item.span == DUMMY_SP {
|
||||
return;
|
||||
|
@ -59,6 +63,21 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> {
|
|||
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let _task = tcx.dep_graph.in_task(DepNode::UnusedTraitCheck);
|
||||
let mut visitor = UnusedTraitImportVisitor { tcx: tcx };
|
||||
|
||||
let mut used_trait_imports = DefIdSet();
|
||||
for &body_id in tcx.hir.krate().bodies.keys() {
|
||||
let item_id = tcx.hir.body_owner(body_id);
|
||||
let item_def_id = tcx.hir.local_def_id(item_id);
|
||||
|
||||
// this will have been written by the main typeck pass
|
||||
if let Some(imports) = tcx.used_trait_imports.borrow().get(&item_def_id) {
|
||||
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
|
||||
used_trait_imports.extend(imports);
|
||||
} else {
|
||||
debug!("GatherVisitor: item_def_id={:?} with no imports", item_def_id);
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = CheckVisitor { tcx, used_trait_imports };
|
||||
tcx.hir.krate().visit_all_item_likes(&mut visitor);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
// done by the orphan and overlap modules. Then we build up various
|
||||
// mappings. That mapping code resides here.
|
||||
|
||||
use dep_graph::DepTrackingMap;
|
||||
use hir::def_id::DefId;
|
||||
use rustc::ty::{self, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::{self, maps, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::{Ty, TyBool, TyChar, TyError};
|
||||
use rustc::ty::{TyParam, TyRawPtr};
|
||||
use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple};
|
||||
|
@ -29,17 +30,19 @@ use rustc::dep_graph::DepNode;
|
|||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir::{Item, ItemImpl};
|
||||
use rustc::hir;
|
||||
use std::cell::RefMut;
|
||||
|
||||
mod builtin;
|
||||
mod orphan;
|
||||
mod overlap;
|
||||
mod unsafety;
|
||||
|
||||
struct CoherenceChecker<'a, 'tcx: 'a> {
|
||||
struct CoherenceCollect<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
inherent_impls: RefMut<'a, DepTrackingMap<maps::InherentImpls<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceChecker<'a, 'tcx> {
|
||||
impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceCollect<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &Item) {
|
||||
if let ItemImpl(..) = item.node {
|
||||
self.check_implementation(item)
|
||||
|
@ -53,7 +56,17 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for CoherenceChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
||||
impl<'a, 'tcx> CoherenceCollect<'a, 'tcx> {
|
||||
fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let inherent_impls = tcx.inherent_impls.borrow_mut();
|
||||
let mut this = &mut CoherenceCollect { tcx, inherent_impls };
|
||||
|
||||
// Check implementations and traits. This populates the tables
|
||||
// containing the inherent methods and extension methods. It also
|
||||
// builds up the trait inheritance table.
|
||||
tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, this);
|
||||
}
|
||||
|
||||
// Returns the def ID of the base type, if there is one.
|
||||
fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
|
||||
match ty.sty {
|
||||
|
@ -75,14 +88,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check(&mut self) {
|
||||
// Check implementations and traits. This populates the tables
|
||||
// containing the inherent methods and extension methods. It also
|
||||
// builds up the trait inheritance table.
|
||||
self.tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl, self);
|
||||
}
|
||||
|
||||
fn check_implementation(&self, item: &Item) {
|
||||
fn check_implementation(&mut self, item: &Item) {
|
||||
let tcx = self.tcx;
|
||||
let impl_did = tcx.hir.local_def_id(item.id);
|
||||
let self_type = tcx.item_type(impl_did);
|
||||
|
@ -119,8 +125,19 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
|
||||
self.tcx.inherent_impls.borrow_mut().push(base_def_id, impl_def_id);
|
||||
fn add_inherent_impl(&mut self, base_def_id: DefId, impl_def_id: DefId) {
|
||||
// Subtle: it'd be better to collect these into a local map
|
||||
// and then write the vector only once all items are known,
|
||||
// but that leads to degenerate dep-graphs. The problem is
|
||||
// that the write of that big vector winds up having reads
|
||||
// from *all* impls in the krate, since we've lost the
|
||||
// precision basically. This would be ok in the firewall
|
||||
// model so once we've made progess towards that we can modify
|
||||
// the strategy here. In the meantime, using `push` is ok
|
||||
// because we are doing this as a pre-pass before anyone
|
||||
// actually reads from `inherent_impls` -- and we know this is
|
||||
// true beacuse we hold the refcell lock.
|
||||
self.inherent_impls.push(base_def_id, impl_def_id);
|
||||
}
|
||||
|
||||
fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) {
|
||||
|
@ -160,8 +177,9 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, sp: Span, trait_def_id: Def
|
|||
}
|
||||
|
||||
pub fn check_coherence(ccx: &CrateCtxt) {
|
||||
CoherenceCollect::check(ccx.tcx);
|
||||
|
||||
let _task = ccx.tcx.dep_graph.in_task(DepNode::Coherence);
|
||||
CoherenceChecker { tcx: ccx.tcx }.check();
|
||||
unsafety::check(ccx.tcx);
|
||||
orphan::check(ccx.tcx);
|
||||
overlap::check(ccx.tcx);
|
||||
|
|
|
@ -634,7 +634,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
ccx.tcx.item_types.borrow_mut().insert(ty_f.did, tt);
|
||||
|
||||
let def_id = ccx.tcx.hir.local_def_id(field.id);
|
||||
ccx.tcx.item_types.borrow_mut().insert(def_id, tt);
|
||||
assert_eq!(def_id, ty_f.did);
|
||||
ccx.tcx.generics.borrow_mut().insert(def_id, struct_generics);
|
||||
ccx.tcx.predicates.borrow_mut().insert(def_id, struct_predicates.clone());
|
||||
}
|
||||
|
@ -848,9 +848,10 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
|
|||
let const_def_id = ccx.tcx.hir.local_def_id(trait_item.id);
|
||||
generics_of_def_id(ccx, const_def_id);
|
||||
let ty = ccx.icx(&trait_predicates).to_ty(&ty);
|
||||
tcx.item_types.borrow_mut().insert(const_def_id, ty);
|
||||
convert_associated_const(ccx, TraitContainer(trait_def_id),
|
||||
trait_item.id, ty);
|
||||
convert_associated_const(ccx,
|
||||
TraitContainer(trait_def_id),
|
||||
trait_item.id,
|
||||
ty);
|
||||
}
|
||||
|
||||
hir::TraitItemKind::Type(_, ref opt_ty) => {
|
||||
|
@ -884,9 +885,10 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
|
|||
let const_def_id = ccx.tcx.hir.local_def_id(impl_item.id);
|
||||
generics_of_def_id(ccx, const_def_id);
|
||||
let ty = ccx.icx(&impl_predicates).to_ty(&ty);
|
||||
tcx.item_types.borrow_mut().insert(const_def_id, ty);
|
||||
convert_associated_const(ccx, ImplContainer(impl_def_id),
|
||||
impl_item.id, ty);
|
||||
convert_associated_const(ccx,
|
||||
ImplContainer(impl_def_id),
|
||||
impl_item.id,
|
||||
ty);
|
||||
}
|
||||
|
||||
hir::ImplItemKind::Type(ref ty) => {
|
||||
|
@ -1283,9 +1285,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
|
|||
items);
|
||||
trait_predicates.predicates.extend(assoc_predicates);
|
||||
|
||||
let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
|
||||
assert!(prev_predicates.is_none());
|
||||
|
||||
tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
|
||||
return;
|
||||
|
||||
fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
|
@ -1592,9 +1592,7 @@ fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
};
|
||||
|
||||
let predicates = ty_generic_predicates(ccx, generics, None, vec![], false);
|
||||
let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id,
|
||||
predicates.clone());
|
||||
assert!(prev_predicates.is_none());
|
||||
ccx.tcx.predicates.borrow_mut().insert(def_id, predicates.clone());
|
||||
|
||||
predicates
|
||||
}
|
||||
|
@ -1617,8 +1615,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
};
|
||||
|
||||
let predicates = ty_generic_predicates(ccx, generics, None, vec![], false);
|
||||
let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
|
||||
assert!(prev_predicates.is_none());
|
||||
ccx.tcx.predicates.borrow_mut().insert(def_id, predicates);
|
||||
}
|
||||
|
||||
// Is it marked with ?Sized
|
||||
|
|
|
@ -77,6 +77,7 @@ This API is completely unstable and subject to change.
|
|||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(field_init_shorthand)]
|
||||
#![feature(loop_break_value)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
|
|
|
@ -137,11 +137,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
|
|||
item_variances);
|
||||
}
|
||||
|
||||
let newly_added = tcx.item_variance_map
|
||||
.borrow_mut()
|
||||
.insert(item_def_id, Rc::new(item_variances))
|
||||
.is_none();
|
||||
assert!(newly_added);
|
||||
tcx.item_variance_map
|
||||
.borrow_mut()
|
||||
.insert(item_def_id, Rc::new(item_variances));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,12 +178,10 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
|
|||
// parameters".
|
||||
if self.num_inferred() == inferreds_on_entry {
|
||||
let item_def_id = self.tcx.hir.local_def_id(item_id);
|
||||
let newly_added = self.tcx
|
||||
self.tcx
|
||||
.item_variance_map
|
||||
.borrow_mut()
|
||||
.insert(item_def_id, self.empty_variances.clone())
|
||||
.is_none();
|
||||
assert!(newly_added);
|
||||
.insert(item_def_id, self.empty_variances.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue