diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 3156f17e0c4c5..427fe51e6ff9c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -472,6 +472,12 @@ define_dep_nodes!( <'tcx> [] UnsafetyCheckResult(DefId), [] UnsafeDeriveOnReprPacked(DefId), + [] CheckModAttrs(DefId), + [] CheckModLoops(DefId), + [] CheckModUnstableApiUsage(DefId), + [] CheckModItemTypes(DefId), + [] CollectModItemTypes(DefId), + [] Reachability, [] MirKeys, [eval_always] CrateVariances, diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 2e0e9672758fd..a214ec88c6654 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -4,9 +4,14 @@ //! conflicts between multiple such attributes attached to the same //! item. + +use ty::TyCtxt; +use ty::query::Providers; +use ty::query::queries; + use hir; +use hir::def_id::DefId; use hir::intravisit::{self, Visitor, NestedVisitorMap}; -use ty::TyCtxt; use std::fmt::{self, Display}; use syntax_pos::Span; @@ -364,8 +369,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> { } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut checker = CheckAttrVisitor { tcx }; - tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor()); + for &module in tcx.hir().krate().modules.keys() { + queries::check_mod_attrs::ensure(tcx, tcx.hir().local_def_id(module)); + } } fn is_c_like_enum(item: &hir::Item) -> bool { @@ -381,3 +387,17 @@ fn is_c_like_enum(item: &hir::Item) -> bool { false } } + +fn check_mod_attrs<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { + tcx.hir().visit_item_likes_in_module( + module_def_id, + &mut CheckAttrVisitor { tcx }.as_deep_visitor() + ); +} + +pub(crate) fn provide(providers: &mut Providers<'_>) { + *providers = Providers { + check_mod_attrs, + ..*providers + }; +} diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index fb2c873d740ca..868072b2fa7bf 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -1,4 +1,5 @@ use ty; +use ty::TyCtxt; use hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX; use rustc_data_structures::indexed_vec::Idx; use serialize; @@ -247,6 +248,14 @@ impl DefId { pub fn to_local(self) -> LocalDefId { LocalDefId::from_def_id(self) } + + pub fn describe_as_module(&self, tcx: TyCtxt<'_, '_, '_>) -> String { + if self.is_local() && self.index == CRATE_DEF_INDEX { + format!("top-level module") + } else { + format!("module `{}`", tcx.item_path_str(*self)) + } + } } impl serialize::UseSpecializedEncodable for DefId {} diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 359bd37488241..8badcbfc1b301 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -48,7 +48,7 @@ use session::config::nightly_options; use util::common::FN_OUTPUT_NAME; use util::nodemap::{DefIdMap, NodeMap}; -use std::collections::BTreeMap; +use std::collections::{BTreeSet, BTreeMap}; use std::fmt::Debug; use std::mem; use smallvec::SmallVec; @@ -90,6 +90,8 @@ pub struct LoweringContext<'a> { trait_impls: BTreeMap>, trait_auto_impl: BTreeMap, + modules: BTreeMap, + is_generator: bool, catch_scopes: Vec, @@ -124,6 +126,8 @@ pub struct LoweringContext<'a> { // needs to be created for it. in_scope_lifetimes: Vec, + current_module: NodeId, + type_def_lifetime_params: DefIdMap, current_hir_id_owner: Vec<(DefIndex, u32)>, @@ -228,12 +232,14 @@ pub fn lower_crate( bodies: BTreeMap::new(), trait_impls: BTreeMap::new(), trait_auto_impl: BTreeMap::new(), + modules: BTreeMap::new(), exported_macros: Vec::new(), catch_scopes: Vec::new(), loop_scopes: Vec::new(), is_in_loop_condition: false, anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, type_def_lifetime_params: Default::default(), + current_module: CRATE_NODE_ID, current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)], item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), @@ -414,11 +420,24 @@ impl<'a> LoweringContext<'a> { } impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> { + fn visit_mod(&mut self, m: &'lcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) { + self.lctx.modules.insert(n, hir::ModuleItems { + items: BTreeSet::new(), + trait_items: BTreeSet::new(), + impl_items: BTreeSet::new(), + }); + + let old = self.lctx.current_module; + self.lctx.current_module = n; + visit::walk_mod(self, m); + self.lctx.current_module = old; + } + fn visit_item(&mut self, item: &'lcx Item) { let mut item_lowered = true; self.lctx.with_hir_id_owner(item.id, |lctx| { if let Some(hir_item) = lctx.lower_item(item) { - lctx.items.insert(item.id, hir_item); + lctx.insert_item(item.id, hir_item); } else { item_lowered = false; } @@ -451,6 +470,7 @@ impl<'a> LoweringContext<'a> { let id = hir::TraitItemId { node_id: item.id }; let hir_item = lctx.lower_trait_item(item); lctx.trait_items.insert(id, hir_item); + lctx.modules.get_mut(&lctx.current_module).unwrap().trait_items.insert(id); }); visit::walk_trait_item(self, item); @@ -461,6 +481,7 @@ impl<'a> LoweringContext<'a> { let id = hir::ImplItemId { node_id: item.id }; let hir_item = lctx.lower_impl_item(item); lctx.impl_items.insert(id, hir_item); + lctx.modules.get_mut(&lctx.current_module).unwrap().impl_items.insert(id); }); visit::walk_impl_item(self, item); } @@ -492,9 +513,15 @@ impl<'a> LoweringContext<'a> { body_ids, trait_impls: self.trait_impls, trait_auto_impl: self.trait_auto_impl, + modules: self.modules, } } + fn insert_item(&mut self, id: NodeId, item: hir::Item) { + self.items.insert(id, item); + self.modules.get_mut(&self.current_module).unwrap().items.insert(id); + } + fn allocate_hir_id_counter(&mut self, owner: NodeId, debug: &T) -> LoweredNodeId { if self.item_local_id_counters.insert(owner, 0).is_some() { bug!( @@ -1370,7 +1397,7 @@ impl<'a> LoweringContext<'a> { // Insert the item into the global list. This usually happens // automatically for all AST items. But this existential type item // does not actually exist in the AST. - lctx.items.insert(exist_ty_id.node_id, exist_ty_item); + lctx.insert_item(exist_ty_id.node_id, exist_ty_item); // `impl Trait` now just becomes `Foo<'a, 'b, ..>`. hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes) @@ -3026,7 +3053,7 @@ impl<'a> LoweringContext<'a> { }; let vis = respan(vis.span, vis_kind); - this.items.insert( + this.insert_item( new_id.node_id, hir::Item { id: new_id.node_id, @@ -3133,7 +3160,7 @@ impl<'a> LoweringContext<'a> { }; let vis = respan(vis.span, vis_kind); - this.items.insert( + this.insert_item( new_id, hir::Item { id: new_id, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 78acea9f58814..925a5fb85b81b 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -119,6 +119,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { trait_impls: _, trait_auto_impl: _, body_ids: _, + modules: _, } = *krate; alloc_hir_dep_nodes( diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 5bcbeeefa5030..513e18b137371 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -17,6 +17,7 @@ use syntax::ext::base::MacroKind; use syntax_pos::{Span, DUMMY_SP}; use hir::*; +use hir::itemlikevisit::ItemLikeVisitor; use hir::print::Nested; use util::nodemap::FxHashMap; @@ -506,6 +507,32 @@ impl<'hir> Map<'hir> { &self.forest.krate.attrs } + pub fn visit_item_likes_in_module(&self, module: DefId, visitor: &mut V) + where V: ItemLikeVisitor<'hir> + { + let node_id = self.as_local_node_id(module).unwrap(); + + // Read the module so we'll be re-executed if new items + // appear immediately under in the module. If some new item appears + // in some nested item in the module, we'll be re-executed due to reads + // in the expect_* calls the loops below + self.read(node_id); + + let module = &self.forest.krate.modules[&node_id]; + + for id in &module.items { + visitor.visit_item(self.expect_item(*id)); + } + + for id in &module.trait_items { + visitor.visit_trait_item(self.expect_trait_item(id.node_id)); + } + + for id in &module.impl_items { + visitor.visit_impl_item(self.expect_impl_item(id.node_id)); + } + } + /// Retrieve the Node corresponding to `id`, panicking if it cannot /// be found. pub fn get(&self, id: NodeId) -> Node<'hir> { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 7e87171a5edf7..fc4bd05476f6c 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -33,7 +33,7 @@ use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope} use rustc_data_structures::thin_vec::ThinVec; use serialize::{self, Encoder, Encodable, Decoder, Decodable}; -use std::collections::BTreeMap; +use std::collections::{BTreeSet, BTreeMap}; use std::fmt; /// HIR doesn't commit to a concrete storage type and has its own alias for a vector. @@ -676,6 +676,15 @@ pub struct WhereEqPredicate { pub rhs_ty: P, } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub struct ModuleItems { + // Use BTreeSets here so items are in the same order as in the + // list of all items in Crate + pub items: BTreeSet, + pub trait_items: BTreeSet, + pub impl_items: BTreeSet, +} + /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -708,6 +717,10 @@ pub struct Crate { /// in the crate, you should iterate over this list rather than the keys /// of bodies. pub body_ids: Vec, + + /// A list of modules written out in the order in which they + /// appear in the crate. This includes the main crate module. + pub modules: BTreeMap, } impl Crate { @@ -2408,6 +2421,7 @@ pub type GlobMap = NodeMap>; pub fn provide(providers: &mut Providers<'_>) { + check_attr::provide(providers); providers.describe_def = map::describe_def; } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 43cb89ccf6c0f..918e286c435bc 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -8,6 +8,8 @@ use hir::{self, Item, Generics, StructField, Variant, HirId}; use hir::def::Def; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; +use ty::query::Providers; +use ty::query::queries; use middle::privacy::AccessLevels; use session::{DiagnosticMessageId, Session}; use syntax::symbol::Symbol; @@ -454,11 +456,23 @@ impl<'a, 'tcx> Index<'tcx> { } } +pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + for &module in tcx.hir().krate().modules.keys() { + queries::check_mod_unstable_api_usage::ensure(tcx, tcx.hir().local_def_id(module)); + } +} + /// Cross-references the feature names of unstable APIs with enabled /// features and possibly prints errors. -pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut checker = Checker { tcx }; - tcx.hir().krate().visit_all_item_likes(&mut checker.as_deep_visitor()); +fn check_mod_unstable_api_usage<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { + tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }.as_deep_visitor()); +} + +pub fn provide(providers: &mut Providers<'_>) { + *providers = Providers { + check_mod_unstable_api_usage, + ..*providers + }; } /// Check whether an item marked with `deprecated(since="X")` is currently diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 3464464aa229c..ca5d1f6bd3203 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -68,11 +68,56 @@ impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M { format!("processing `{}`", tcx.item_path_str(def_id)).into() } else { let name = unsafe { ::std::intrinsics::type_name::() }; - format!("processing `{}` applied to `{:?}`", name, def_id).into() + format!("processing {:?} with query `{}`", def_id, name).into() } } } +impl<'tcx> QueryDescription<'tcx> for queries::check_mod_attrs<'tcx> { + fn describe( + tcx: TyCtxt<'_, '_, '_>, + key: DefId, + ) -> Cow<'static, str> { + format!("checking attributes in {}", key.describe_as_module(tcx)).into() + } +} + +impl<'tcx> QueryDescription<'tcx> for queries::check_mod_unstable_api_usage<'tcx> { + fn describe( + tcx: TyCtxt<'_, '_, '_>, + key: DefId, + ) -> Cow<'static, str> { + format!("checking for unstable API usage in {}", key.describe_as_module(tcx)).into() + } +} + +impl<'tcx> QueryDescription<'tcx> for queries::check_mod_loops<'tcx> { + fn describe( + tcx: TyCtxt<'_, '_, '_>, + key: DefId, + ) -> Cow<'static, str> { + format!("checking loops in {}", key.describe_as_module(tcx)).into() + } +} + +impl<'tcx> QueryDescription<'tcx> for queries::check_mod_item_types<'tcx> { + fn describe( + tcx: TyCtxt<'_, '_, '_>, + key: DefId, + ) -> Cow<'static, str> { + format!("checking item types in {}", key.describe_as_module(tcx)).into() + } +} + +impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> { + fn describe( + tcx: TyCtxt<'_, '_, '_>, + key: DefId, + ) -> Cow<'static, str> { + format!("collecting item types in {}", key.describe_as_module(tcx)).into() + } +} + impl<'tcx> QueryDescription<'tcx> for queries::normalize_projection_ty<'tcx> { fn describe( _tcx: TyCtxt<'_, '_, '_>, diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index d9cabb395740e..39d76ceed9507 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -254,6 +254,18 @@ define_queries! { <'tcx> }, Other { + /// Checks the attributes in the module + [] fn check_mod_attrs: CheckModAttrs(DefId) -> (), + + [] fn check_mod_unstable_api_usage: CheckModUnstableApiUsage(DefId) -> (), + + /// Checks the loops in the module + [] fn check_mod_loops: CheckModLoops(DefId) -> (), + + [] fn check_mod_item_types: CheckModItemTypes(DefId) -> (), + + [] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (), + /// Caches CoerceUnsized kinds for impls on custom types. [] fn coerce_unsized_info: CoerceUnsizedInfo(DefId) -> ty::adjustment::CoerceUnsizedInfo, diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 2d619d19b4243..af23bf3c5901f 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1262,6 +1262,11 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); } DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); } DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); } + DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); } + DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); } + DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); } + DepKind::CheckModItemTypes => { force!(check_mod_item_types, def_id!()); } + DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); } DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); } DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); } DepKind::CrateVariances => { force!(crate_variances, LOCAL_CRATE); } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index bfff592a5dd49..380f9afd68de6 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1167,6 +1167,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) { typeck::provide(providers); ty::provide(providers); traits::provide(providers); + stability::provide(providers); reachable::provide(providers); rustc_passes::provide(providers); rustc_traits::provide(providers); @@ -1218,8 +1219,6 @@ where sess.proc_macro_decls_static .set(proc_macro_decls::find(&hir_map)); - time(sess, "loop checking", || loops::check_crate(sess, &hir_map)); - let mut local_providers = ty::query::Providers::default(); default_provide(&mut local_providers); codegen_backend.provide(&mut local_providers); @@ -1247,7 +1246,9 @@ where |tcx| { // Do some initialization of the DepGraph that can only be done with the // tcx available. - rustc_incremental::dep_graph_tcx_init(tcx); + time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx)); + + time(sess, "loop checking", || loops::check_crate(tcx)); time(sess, "attribute checking", || { hir::check_attr::check_crate(tcx) diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 0b394d800ea89..829d4b34cf779 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -38,4 +38,5 @@ __build_diagnostic_array! { librustc_passes, DIAGNOSTICS } pub fn provide(providers: &mut Providers) { rvalue_promotion::provide(providers); + loops::provide(providers); } diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 7a37a35abbce7..7d9165a82bc8f 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -2,6 +2,10 @@ use self::Context::*; use rustc::session::Session; +use rustc::ty::query::Providers; +use rustc::ty::query::queries; +use rustc::ty::TyCtxt; +use rustc::hir::def_id::DefId; use rustc::hir::map::Map; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::{self, Node, Destination}; @@ -42,28 +46,32 @@ struct CheckLoopVisitor<'a, 'hir: 'a> { cx: Context, } -pub fn check_crate(sess: &Session, map: &Map) { - let krate = map.krate(); - krate.visit_all_item_likes(&mut CheckLoopVisitor { - sess, - hir_map: map, +pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + for &module in tcx.hir().krate().modules.keys() { + queries::check_mod_loops::ensure(tcx, tcx.hir().local_def_id(module)); + } +} + +fn check_mod_loops<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { + tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckLoopVisitor { + sess: &tcx.sess, + hir_map: &tcx.hir(), cx: Normal, }.as_deep_visitor()); } +pub(crate) fn provide(providers: &mut Providers) { + *providers = Providers { + check_mod_loops, + ..*providers + }; +} + impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> { NestedVisitorMap::OnlyBodies(&self.hir_map) } - fn visit_item(&mut self, i: &'hir hir::Item) { - self.with_context(Normal, |v| intravisit::walk_item(v, i)); - } - - fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) { - self.with_context(Normal, |v| intravisit::walk_impl_item(v, i)); - } - fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) { self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c)); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1a5d164873d32..111055e61234c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -109,6 +109,7 @@ use rustc::ty::{ use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; +use rustc::ty::query::queries; use rustc::ty::subst::{UnpackedKind, Subst, Substs, UserSelfTy, UserSubsts}; use rustc::ty::util::{Representability, IntTypeExt, Discr}; use rustc::ty::layout::VariantIdx; @@ -700,10 +701,16 @@ pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorRe pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { - tcx.hir().krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx }); + for &module in tcx.hir().krate().modules.keys() { + queries::check_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module)); + } }) } +fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { + tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); +} + pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> { tcx.typeck_item_bodies(LOCAL_CRATE) } @@ -742,6 +749,7 @@ pub fn provide(providers: &mut Providers) { check_item_well_formed, check_trait_item_well_formed, check_impl_item_well_formed, + check_mod_item_types, ..*providers }; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index e0e173901ef38..52fa9e5f9918e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -22,6 +22,7 @@ use middle::resolve_lifetime as rl; use middle::weak_lang_items; use rustc::mir::mono::Linkage; use rustc::ty::query::Providers; +use rustc::ty::query::queries; use rustc::ty::subst::Substs; use rustc::ty::util::Discr; use rustc::ty::util::IntTypeExt; @@ -55,10 +56,16 @@ struct OnlySelfBounds(bool); // Main entry point pub fn collect_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let mut visitor = CollectItemTypesVisitor { tcx }; - tcx.hir() - .krate() - .visit_all_item_likes(&mut visitor.as_deep_visitor()); + for &module in tcx.hir().krate().modules.keys() { + queries::collect_mod_item_types::ensure(tcx, tcx.hir().local_def_id(module)); + } +} + +fn collect_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) { + tcx.hir().visit_item_likes_in_module( + module_def_id, + &mut CollectItemTypesVisitor { tcx }.as_deep_visitor() + ); } pub fn provide(providers: &mut Providers) { @@ -77,6 +84,7 @@ pub fn provide(providers: &mut Providers) { impl_polarity, is_foreign_item, codegen_fn_attrs, + collect_mod_item_types, ..*providers }; } diff --git a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr index 1a75eb5e31450..aa45462a52e41 100644 --- a/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr +++ b/src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr @@ -5,6 +5,11 @@ LL | trait Foo> { | ^^^ | = note: ...which again requires processing `Foo::X`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cycle-trait-default-type-trait.rs:4:1 + | +LL | trait Foo> { + | ^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr index 22efa8ee0a58d..8aa3ac8abf52c 100644 --- a/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr +++ b/src/test/ui/cycle-trait/cycle-trait-supertrait-direct.stderr @@ -5,6 +5,11 @@ LL | trait Chromosome: Chromosome { | ^^^^^^^^^^ | = note: ...which again requires computing the supertraits of `Chromosome`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cycle-trait-supertrait-direct.rs:3:1 + | +LL | trait Chromosome: Chromosome { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/existential_types/no_inferrable_concrete_type.stderr b/src/test/ui/existential_types/no_inferrable_concrete_type.stderr index 9d2609e546db5..fab61bd9ed065 100644 --- a/src/test/ui/existential_types/no_inferrable_concrete_type.stderr +++ b/src/test/ui/existential_types/no_inferrable_concrete_type.stderr @@ -10,6 +10,17 @@ note: ...which requires processing `bar`... LL | fn bar(x: Foo) -> Foo { x } | ^^^^^ = note: ...which again requires processing `Foo`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/no_inferrable_concrete_type.rs:4:1 + | +LL | / #![feature(existential_type)] +LL | | +LL | | existential type Foo: Copy; //~ cycle detected +LL | | +... | +LL | | let _: Foo = std::mem::transmute(0u8); +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index d6928584b9e43..4acc400f8e799 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -22,6 +22,17 @@ LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:3:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}` --> $DIR/auto-trait-leak.rs:14:16 @@ -46,6 +57,17 @@ note: ...which requires processing `cycle2`... LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle +note: cycle used when checking item types in top-level module + --> $DIR/auto-trait-leak.rs:3:1 + | +LL | / use std::cell::Cell; +LL | | use std::rc::Rc; +LL | | +LL | | fn send(_: T) {} +... | +LL | | Rc::new(String::from("foo")) +LL | | } + | |_^ error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/auto-trait-leak.rs:17:5 diff --git a/src/test/ui/infinite/infinite-vec-type-recursion.stderr b/src/test/ui/infinite/infinite-vec-type-recursion.stderr index eb1461a7b29e1..daa18a7e9b1ce 100644 --- a/src/test/ui/infinite/infinite-vec-type-recursion.stderr +++ b/src/test/ui/infinite/infinite-vec-type-recursion.stderr @@ -5,6 +5,14 @@ LL | type X = Vec; | ^ | = note: ...which again requires processing `X`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/infinite-vec-type-recursion.rs:1:1 + | +LL | / type X = Vec; +LL | | //~^ ERROR cycle detected +LL | | +LL | | fn main() { let b: X = Vec::new(); } + | |____________________________________^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-12511.stderr b/src/test/ui/issues/issue-12511.stderr index 945cdc745efb0..37e38ff60ae4b 100644 --- a/src/test/ui/issues/issue-12511.stderr +++ b/src/test/ui/issues/issue-12511.stderr @@ -10,6 +10,11 @@ note: ...which requires computing the supertraits of `T2`... LL | trait T2 : T1 { | ^^ = note: ...which again requires computing the supertraits of `T1`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-12511.rs:1:1 + | +LL | trait T1 : T2 { + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20772.stderr b/src/test/ui/issues/issue-20772.stderr index 15a5fc40926fe..7dc4e43fd573d 100644 --- a/src/test/ui/issues/issue-20772.stderr +++ b/src/test/ui/issues/issue-20772.stderr @@ -8,6 +8,14 @@ LL | | {} | |__^ | = note: ...which again requires computing the supertraits of `T`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-20772.rs:1:1 + | +LL | / trait T : Iterator +LL | | //~^ ERROR cycle detected +LL | | //~| ERROR associated type `Item` not found for `Self` +LL | | {} + | |__^ error[E0220]: associated type `Item` not found for `Self` --> $DIR/issue-20772.rs:1:25 diff --git a/src/test/ui/issues/issue-20825.stderr b/src/test/ui/issues/issue-20825.stderr index 1df51dc2d41ac..5f9709d1c649b 100644 --- a/src/test/ui/issues/issue-20825.stderr +++ b/src/test/ui/issues/issue-20825.stderr @@ -5,6 +5,11 @@ LL | pub trait Processor: Subscriber { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...which again requires computing the supertraits of `Processor`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-20825.rs:5:1 + | +LL | pub trait Processor: Subscriber { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22673.stderr b/src/test/ui/issues/issue-22673.stderr index 4b5730c91eb55..9e7e4b218b1c6 100644 --- a/src/test/ui/issues/issue-22673.stderr +++ b/src/test/ui/issues/issue-22673.stderr @@ -5,6 +5,11 @@ LL | trait Expr : PartialEq { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...which again requires computing the supertraits of `Expr`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-22673.rs:1:1 + | +LL | trait Expr : PartialEq { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-34373.stderr b/src/test/ui/issues/issue-34373.stderr index 45e8d1bf3e399..07ac421455cf6 100644 --- a/src/test/ui/issues/issue-34373.stderr +++ b/src/test/ui/issues/issue-34373.stderr @@ -10,6 +10,17 @@ note: ...which requires processing `DefaultFoo`... LL | type DefaultFoo = Foo; | ^^^ = note: ...which again requires processing `Foo::T`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-34373.rs:1:1 + | +LL | / #![allow(warnings)] +LL | | +LL | | trait Trait { +LL | | fn foo(_: T) {} +... | +LL | | fn main() { +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr index 17b2f9fa4fbbc..1da56ad05d28c 100644 --- a/src/test/ui/resolve/issue-23305.stderr +++ b/src/test/ui/resolve/issue-23305.stderr @@ -5,6 +5,11 @@ LL | impl ToNbt {} | ^^^^ | = note: ...which again requires processing ``, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/issue-23305.rs:1:1 + | +LL | pub trait ToNbt { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/resolve/resolve-self-in-impl.stderr b/src/test/ui/resolve/resolve-self-in-impl.stderr index 47704f114d16c..1940c0cd2a4b7 100644 --- a/src/test/ui/resolve/resolve-self-in-impl.stderr +++ b/src/test/ui/resolve/resolve-self-in-impl.stderr @@ -5,6 +5,17 @@ LL | impl Tr for Self {} //~ ERROR cycle detected | ^^^^ | = note: ...which again requires processing ``, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/resolve-self-in-impl.rs:1:1 + | +LL | / #![feature(associated_type_defaults)] +LL | | +LL | | struct S(T); +LL | | trait Tr { +... | +LL | | +LL | | fn main() {} + | |____________^ error[E0391]: cycle detected when processing `` --> $DIR/resolve-self-in-impl.rs:15:15 @@ -13,6 +24,17 @@ LL | impl Tr for S {} //~ ERROR cycle detected | ^^^^ | = note: ...which again requires processing ``, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/resolve-self-in-impl.rs:1:1 + | +LL | / #![feature(associated_type_defaults)] +LL | | +LL | | struct S(T); +LL | | trait Tr { +... | +LL | | +LL | | fn main() {} + | |____________^ error[E0391]: cycle detected when processing `` --> $DIR/resolve-self-in-impl.rs:16:6 @@ -21,6 +43,17 @@ LL | impl Self {} //~ ERROR cycle detected | ^^^^ | = note: ...which again requires processing ``, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/resolve-self-in-impl.rs:1:1 + | +LL | / #![feature(associated_type_defaults)] +LL | | +LL | | struct S(T); +LL | | trait Tr { +... | +LL | | +LL | | fn main() {} + | |____________^ error[E0391]: cycle detected when processing `` --> $DIR/resolve-self-in-impl.rs:17:8 @@ -29,6 +62,17 @@ LL | impl S {} //~ ERROR cycle detected | ^^^^ | = note: ...which again requires processing ``, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/resolve-self-in-impl.rs:1:1 + | +LL | / #![feature(associated_type_defaults)] +LL | | +LL | | struct S(T); +LL | | trait Tr { +... | +LL | | +LL | | fn main() {} + | |____________^ error[E0391]: cycle detected when processing `` --> $DIR/resolve-self-in-impl.rs:18:1 @@ -37,6 +81,17 @@ LL | impl Tr for S {} //~ ERROR cycle detected | ^^^^^^^^^^^^^^^^^^^^^^ | = note: ...which again requires processing ``, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/resolve-self-in-impl.rs:1:1 + | +LL | / #![feature(associated_type_defaults)] +LL | | +LL | | struct S(T); +LL | | trait Tr { +... | +LL | | +LL | | fn main() {} + | |____________^ error: aborting due to 5 previous errors diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-declaration-type.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-declaration-type.stderr index 4c1985b9f3af1..22df5e42d2607 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-declaration-type.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-declaration-type.stderr @@ -1,39 +1,3 @@ -error[E0442]: intrinsic argument 1 has wrong type: found `u16`, expected `i16` - --> $DIR/simd-intrinsic-declaration-type.rs:33:9 - | -LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0442]: intrinsic argument 2 has wrong type: found `u16`, expected `i16` - --> $DIR/simd-intrinsic-declaration-type.rs:33:9 - | -LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0442]: intrinsic return value has wrong type: found `u16`, expected `i16` - --> $DIR/simd-intrinsic-declaration-type.rs:33:9 - | -LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0442]: intrinsic argument 1 has wrong type: found `i16`, expected `u16` - --> $DIR/simd-intrinsic-declaration-type.rs:37:9 - | -LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0442]: intrinsic argument 2 has wrong type: found `i16`, expected `u16` - --> $DIR/simd-intrinsic-declaration-type.rs:37:9 - | -LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0442]: intrinsic return value has wrong type: found `i16`, expected `u16` - --> $DIR/simd-intrinsic-declaration-type.rs:37:9 - | -LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0442]: intrinsic argument 1 has wrong type: found vector with length 16, expected length 8 --> $DIR/simd-intrinsic-declaration-type.rs:45:5 | @@ -70,6 +34,42 @@ error[E0442]: intrinsic return value has wrong type: found `i32`, expected `f32` LL | fn x86_mm_max_ps(x: i32x4, y: i32x4) -> i32x4; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0442]: intrinsic argument 1 has wrong type: found `u16`, expected `i16` + --> $DIR/simd-intrinsic-declaration-type.rs:33:9 + | +LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0442]: intrinsic argument 2 has wrong type: found `u16`, expected `i16` + --> $DIR/simd-intrinsic-declaration-type.rs:33:9 + | +LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0442]: intrinsic return value has wrong type: found `u16`, expected `i16` + --> $DIR/simd-intrinsic-declaration-type.rs:33:9 + | +LL | fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0442]: intrinsic argument 1 has wrong type: found `i16`, expected `u16` + --> $DIR/simd-intrinsic-declaration-type.rs:37:9 + | +LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0442]: intrinsic argument 2 has wrong type: found `i16`, expected `u16` + --> $DIR/simd-intrinsic-declaration-type.rs:37:9 + | +LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0442]: intrinsic return value has wrong type: found `i16`, expected `u16` + --> $DIR/simd-intrinsic-declaration-type.rs:37:9 + | +LL | fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0442`.