Skip to content

Commit 843c304

Browse files
committed
Auto merge of #48939 - wesleywiser:incr_query_wf_checking, r=<try>
Querify WF-checking so it can be cached r? @michaelwoerister
2 parents 222b0eb + 2b3d2a5 commit 843c304

File tree

5 files changed

+89
-33
lines changed

5 files changed

+89
-33
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,9 @@ define_dep_nodes!( <'tcx>
575575
[] GetPanicStrategy(CrateNum),
576576
[] IsNoBuiltins(CrateNum),
577577
[] ImplDefaultness(DefId),
578+
[] CheckItemWellFormed(DefId),
579+
[] CheckTraitItemWellFormed(DefId),
580+
[] CheckImplItemWellFormed(DefId),
578581
[] ReachableNonGenerics(CrateNum),
579582
[] NativeLibraries(CrateNum),
580583
[] PluginRegistrarFn(CrateNum),

src/librustc/ty/maps/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ define_maps! { <'tcx>
292292

293293
[] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
294294

295+
[] fn check_item_well_formed: CheckItemWellFormed(DefId) -> (),
296+
[] fn check_trait_item_well_formed: CheckTraitItemWellFormed(DefId) -> (),
297+
[] fn check_impl_item_well_formed: CheckImplItemWellFormed(DefId) -> (),
298+
295299
// The DefIds of all non-generic functions and statics in the given crate
296300
// that can be reached from outside the crate.
297301
//

src/librustc/ty/maps/plumbing.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
869869
DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
870870
DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
871871
DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
872+
DepKind::CheckItemWellFormed => { force!(check_item_well_formed, def_id!()); }
873+
DepKind::CheckTraitItemWellFormed => { force!(check_trait_item_well_formed, def_id!()); }
874+
DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
872875
DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
873876
DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
874877
DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }

src/librustc_typeck/check/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,13 +718,28 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum
718718
})?)
719719
}
720720

721+
fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
722+
wfcheck::CheckTypeWellFormed::new(tcx).check_item_well_formed(def_id);
723+
}
724+
725+
fn check_trait_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
726+
wfcheck::CheckTypeWellFormed::new(tcx).check_trait_item(def_id);
727+
}
728+
729+
fn check_impl_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
730+
wfcheck::CheckTypeWellFormed::new(tcx).check_impl_item(def_id);
731+
}
732+
721733
pub fn provide(providers: &mut Providers) {
722734
*providers = Providers {
723735
typeck_item_bodies,
724736
typeck_tables_of,
725737
has_typeck_tables,
726738
adt_destructor,
727739
used_trait_imports,
740+
check_item_well_formed,
741+
check_trait_item_well_formed,
742+
check_impl_item_well_formed,
728743
..*providers
729744
};
730745
}

src/librustc_typeck/check/wfcheck.rs

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,15 @@ use errors::{DiagnosticBuilder, DiagnosticId};
2626
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
2727
use rustc::hir;
2828

29-
pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> {
29+
pub struct CheckTypeWellFormed<'a, 'tcx:'a> {
3030
tcx: TyCtxt<'a, 'tcx, 'tcx>,
31-
code: ObligationCauseCode<'tcx>,
3231
}
3332

3433
/// Helper type of a temporary returned by .for_item(...).
3534
/// Necessary because we can't write the following bound:
3635
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
3736
struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
3837
inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
39-
code: ObligationCauseCode<'gcx>,
4038
id: ast::NodeId,
4139
span: Span,
4240
param_env: ty::ParamEnv<'tcx>,
@@ -45,30 +43,27 @@ struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
4543
impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
4644
fn with_fcx<F>(&'tcx mut self, f: F) where
4745
F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>,
48-
&mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec<Ty<'tcx>>
46+
&mut CheckTypeWellFormed<'b, 'gcx>) -> Vec<Ty<'tcx>>
4947
{
50-
let code = self.code.clone();
5148
let id = self.id;
5249
let span = self.span;
5350
let param_env = self.param_env;
5451
self.inherited.enter(|inh| {
5552
let fcx = FnCtxt::new(&inh, param_env, id);
56-
let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
53+
let wf_tys = f(&fcx, &mut CheckTypeWellFormed {
5754
tcx: fcx.tcx.global_tcx(),
58-
code,
5955
});
6056
fcx.select_all_obligations_or_error();
6157
fcx.regionck_item(id, span, &wf_tys);
6258
});
6359
}
6460
}
6561

66-
impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
62+
impl<'a, 'gcx> CheckTypeWellFormed<'a, 'gcx> {
6763
pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
68-
-> CheckTypeWellFormedVisitor<'a, 'gcx> {
69-
CheckTypeWellFormedVisitor {
64+
-> CheckTypeWellFormed<'a, 'gcx> {
65+
CheckTypeWellFormed {
7066
tcx,
71-
code: ObligationCauseCode::MiscObligation
7267
}
7368
}
7469

@@ -83,11 +78,14 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
8378
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
8479
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
8580
/// the types first.
86-
fn check_item_well_formed(&mut self, item: &hir::Item) {
81+
pub fn check_item_well_formed(&mut self, def_id: DefId) {
8782
let tcx = self.tcx;
83+
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
84+
let item = tcx.hir.expect_item(node_id);
85+
8886
debug!("check_item_well_formed(it.id={}, it.name={})",
8987
item.id,
90-
tcx.item_path_str(tcx.hir.local_def_id(item.id)));
88+
tcx.item_path_str(def_id));
9189

9290
match item.node {
9391
// Right now we check that every default trait implementation
@@ -161,11 +159,34 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
161159
}
162160
}
163161

162+
pub fn check_trait_item(&mut self, def_id: DefId) {
163+
let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
164+
let trait_item = self.tcx.hir.expect_trait_item(node_id);
165+
166+
let method_sig = match trait_item.node {
167+
hir::TraitItemKind::Method(ref sig, _) => Some(sig),
168+
_ => None
169+
};
170+
CheckTypeWellFormed::new(self.tcx)
171+
.check_associated_item(trait_item.id, trait_item.span, method_sig);
172+
}
173+
174+
pub fn check_impl_item(&mut self, def_id: DefId) {
175+
let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
176+
let impl_item = self.tcx.hir.expect_impl_item(node_id);
177+
178+
let method_sig = match impl_item.node {
179+
hir::ImplItemKind::Method(ref sig, _) => Some(sig),
180+
_ => None
181+
};
182+
self.check_associated_item(impl_item.id, impl_item.span, method_sig);
183+
}
184+
164185
fn check_associated_item(&mut self,
165186
item_id: ast::NodeId,
166187
span: Span,
167188
sig_if_method: Option<&hir::MethodSig>) {
168-
let code = self.code.clone();
189+
let code = ObligationCauseCode::MiscObligation;
169190
self.for_id(item_id, span).with_fcx(|fcx, this| {
170191
let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
171192

@@ -213,7 +234,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
213234
let def_id = self.tcx.hir.local_def_id(id);
214235
CheckWfFcxBuilder {
215236
inherited: Inherited::build(self.tcx, def_id),
216-
code: self.code.clone(),
217237
id,
218238
span,
219239
param_env: self.tcx.param_env(def_id),
@@ -265,7 +285,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
265285

266286
// All field types must be well-formed.
267287
for field in &variant.fields {
268-
fcx.register_wf_obligation(field.ty, field.span, this.code.clone())
288+
fcx.register_wf_obligation(field.ty, field.span,
289+
ObligationCauseCode::MiscObligation)
269290
}
270291
}
271292

@@ -300,11 +321,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
300321
{
301322
debug!("check_item_type: {:?}", item);
302323

303-
self.for_item(item).with_fcx(|fcx, this| {
324+
self.for_item(item).with_fcx(|fcx, _this| {
304325
let ty = fcx.tcx.type_of(fcx.tcx.hir.local_def_id(item.id));
305326
let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
306327

307-
fcx.register_wf_obligation(item_ty, item.span, this.code.clone());
328+
fcx.register_wf_obligation(item_ty, item.span, ObligationCauseCode::MiscObligation);
308329

309330
vec![] // no implied bounds in a const etc
310331
});
@@ -339,7 +360,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
339360
None => {
340361
let self_ty = fcx.tcx.type_of(item_def_id);
341362
let self_ty = fcx.normalize_associated_types_in(item.span, &self_ty);
342-
fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
363+
fcx.register_wf_obligation(self_ty, ast_self_ty.span,
364+
ObligationCauseCode::MiscObligation);
343365
}
344366
}
345367

@@ -374,7 +396,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
374396
// parameter includes another (e.g., <T, U = T>). In those cases, we can't
375397
// be sure if it will error or not as user might always specify the other.
376398
if !ty.needs_subst() {
377-
fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone());
399+
fcx.register_wf_obligation(ty, fcx.tcx.def_span(d),
400+
ObligationCauseCode::MiscObligation);
378401
}
379402
}
380403

@@ -458,11 +481,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
458481
let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig);
459482

460483
for input_ty in sig.inputs() {
461-
fcx.register_wf_obligation(&input_ty, span, self.code.clone());
484+
fcx.register_wf_obligation(&input_ty, span, ObligationCauseCode::MiscObligation);
462485
}
463486
implied_bounds.extend(sig.inputs());
464487

465-
fcx.register_wf_obligation(sig.output(), span, self.code.clone());
488+
fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation);
466489

467490
// FIXME(#25759) return types should not be implied bounds
468491
implied_bounds.push(sig.output());
@@ -648,34 +671,42 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
648671
}
649672
}
650673

674+
pub struct CheckTypeWellFormedVisitor<'a, 'tcx: 'a> {
675+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
676+
}
677+
678+
impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
679+
pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>)
680+
-> CheckTypeWellFormedVisitor<'a, 'gcx> {
681+
CheckTypeWellFormedVisitor {
682+
tcx,
683+
}
684+
}
685+
}
686+
651687
impl<'a, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'a, 'tcx> {
652688
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
653689
NestedVisitorMap::None
654690
}
655691

656692
fn visit_item(&mut self, i: &hir::Item) {
657693
debug!("visit_item: {:?}", i);
658-
self.check_item_well_formed(i);
694+
let def_id = self.tcx.hir.local_def_id(i.id);
695+
ty::maps::queries::check_item_well_formed::ensure(self.tcx, def_id);
659696
intravisit::walk_item(self, i);
660697
}
661698

662699
fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
663700
debug!("visit_trait_item: {:?}", trait_item);
664-
let method_sig = match trait_item.node {
665-
hir::TraitItemKind::Method(ref sig, _) => Some(sig),
666-
_ => None
667-
};
668-
self.check_associated_item(trait_item.id, trait_item.span, method_sig);
701+
let def_id = self.tcx.hir.local_def_id(trait_item.id);
702+
ty::maps::queries::check_trait_item_well_formed::ensure(self.tcx, def_id);
669703
intravisit::walk_trait_item(self, trait_item)
670704
}
671705

672706
fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
673707
debug!("visit_impl_item: {:?}", impl_item);
674-
let method_sig = match impl_item.node {
675-
hir::ImplItemKind::Method(ref sig, _) => Some(sig),
676-
_ => None
677-
};
678-
self.check_associated_item(impl_item.id, impl_item.span, method_sig);
708+
let def_id = self.tcx.hir.local_def_id(impl_item.id);
709+
ty::maps::queries::check_impl_item_well_formed::ensure(self.tcx, def_id);
679710
intravisit::walk_impl_item(self, impl_item)
680711
}
681712
}

0 commit comments

Comments
 (0)