From 5dfb4bb72dfbebd6258889ecf74483ec617deb92 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 9 Mar 2018 22:35:15 -0500 Subject: [PATCH] Queryify check_item_well_formed Fixes #46753 --- src/librustc/dep_graph/dep_node.rs | 1 + src/librustc/ty/maps/mod.rs | 2 ++ src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_typeck/check/mod.rs | 5 +++ src/librustc_typeck/check/wfcheck.rs | 50 ++++++++++++++++++++-------- 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 7d8709a82f4d3..04e597cf567ce 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -575,6 +575,7 @@ define_dep_nodes!( <'tcx> [] GetPanicStrategy(CrateNum), [] IsNoBuiltins(CrateNum), [] ImplDefaultness(DefId), + [] CheckItemWellFormed(DefId), [] ReachableNonGenerics(CrateNum), [] NativeLibraries(CrateNum), [] PluginRegistrarFn(CrateNum), diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 0ded759fec730..021ad8f3b63e5 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -292,6 +292,8 @@ define_maps! { <'tcx> [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness, + [] fn check_item_well_formed: CheckItemWellFormed(DefId) -> (), + // The DefIds of all non-generic functions and statics in the given crate // that can be reached from outside the crate. // diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 68d1088890205..91ccccf14986d 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -869,6 +869,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); } DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); } DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); } + DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); } DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); } DepKind::NativeLibraries => { force!(native_libraries, krate!()); } DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 19085ff039ec5..3d7d42daf814d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -718,6 +718,10 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum })?) } +fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + wfcheck::CheckTypeWellFormed::new(tcx).check_item_well_formed(def_id); +} + pub fn provide(providers: &mut Providers) { *providers = Providers { typeck_item_bodies, @@ -725,6 +729,7 @@ pub fn provide(providers: &mut Providers) { has_typeck_tables, adt_destructor, used_trait_imports, + check_item_well_formed, ..*providers }; } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 7b9f23b5f9e8f..05e0270e658cc 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -26,7 +26,7 @@ use errors::{DiagnosticBuilder, DiagnosticId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir; -pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> { +pub struct CheckTypeWellFormed<'a, 'tcx:'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, } @@ -43,14 +43,14 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { fn with_fcx(&'tcx mut self, f: F) where F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>, - &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec> + &mut CheckTypeWellFormed<'b, 'gcx>) -> Vec> { let id = self.id; let span = self.span; let param_env = self.param_env; self.inherited.enter(|inh| { let fcx = FnCtxt::new(&inh, param_env, id); - let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { + let wf_tys = f(&fcx, &mut CheckTypeWellFormed { tcx: fcx.tcx.global_tcx(), }); fcx.select_all_obligations_or_error(); @@ -59,10 +59,10 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { +impl<'a, 'gcx> CheckTypeWellFormed<'a, 'gcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) - -> CheckTypeWellFormedVisitor<'a, 'gcx> { - CheckTypeWellFormedVisitor { + -> CheckTypeWellFormed<'a, 'gcx> { + CheckTypeWellFormed { tcx, } } @@ -78,11 +78,14 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { /// We do this check as a pre-pass before checking fn bodies because if these constraints are /// not included it frequently leads to confusing errors in fn bodies. So it's better to check /// the types first. - fn check_item_well_formed(&mut self, item: &hir::Item) { + pub fn check_item_well_formed(&mut self, def_id: DefId) { let tcx = self.tcx; + let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); + let item = tcx.hir.expect_item(node_id); + debug!("check_item_well_formed(it.id={}, it.name={})", item.id, - tcx.item_path_str(tcx.hir.local_def_id(item.id))); + tcx.item_path_str(def_id)); match item.node { // Right now we check that every default trait implementation @@ -259,7 +262,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { // All field types must be well-formed. for field in &variant.fields { - fcx.register_wf_obligation(field.ty, field.span, ObligationCauseCode::MiscObligation) + fcx.register_wf_obligation(field.ty, field.span, + ObligationCauseCode::MiscObligation) } } @@ -333,7 +337,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { None => { let self_ty = fcx.tcx.type_of(item_def_id); let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty); - fcx.register_wf_obligation(self_ty, ast_self_ty.span, ObligationCauseCode::MiscObligation); + fcx.register_wf_obligation(self_ty, ast_self_ty.span, + ObligationCauseCode::MiscObligation); } } @@ -368,7 +373,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { // parameter includes another (e.g., ). In those cases, we can't // be sure if it will error or not as user might always specify the other. if !ty.needs_subst() { - fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), ObligationCauseCode::MiscObligation); + fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), + ObligationCauseCode::MiscObligation); } } @@ -642,6 +648,19 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) { } } +pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, +} + +impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) + -> CheckTypeWellFormedVisitor<'a, 'gcx> { + CheckTypeWellFormedVisitor { + tcx, + } + } +} + impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> { NestedVisitorMap::None @@ -649,7 +668,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { fn visit_item(&mut self, i: &hir::Item) { debug!("visit_item: {:?}", i); - self.check_item_well_formed(i); + let def_id = self.tcx.hir.local_def_id(i.id); + ty::maps::queries::check_item_well_formed::ensure(self.tcx, def_id); intravisit::walk_item(self, i); } @@ -659,7 +679,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { hir::TraitItemKind::Method(ref sig, _) => Some(sig), _ => None }; - self.check_associated_item(trait_item.id, trait_item.span, method_sig); + CheckTypeWellFormed::new(self.tcx) + .check_associated_item(trait_item.id, trait_item.span, method_sig); intravisit::walk_trait_item(self, trait_item) } @@ -669,7 +690,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> { hir::ImplItemKind::Method(ref sig, _) => Some(sig), _ => None }; - self.check_associated_item(impl_item.id, impl_item.span, method_sig); + CheckTypeWellFormed::new(self.tcx) + .check_associated_item(impl_item.id, impl_item.span, method_sig); intravisit::walk_impl_item(self, impl_item) } }