Skip to content

Commit 6f5e455

Browse files
committed
rustc: split GenericPredicates of a method from its parent predicates.
1 parent 3e74e5b commit 6f5e455

File tree

14 files changed

+136
-150
lines changed

14 files changed

+136
-150
lines changed

src/librustc/traits/select.rs

+12-14
Original file line numberDiff line numberDiff line change
@@ -2897,20 +2897,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
28972897
// obligation will normalize to `<$0 as Iterator>::Item = $1` and
28982898
// `$1: Copy`, so we must ensure the obligations are emitted in
28992899
// that order.
2900-
let predicates = tcx
2901-
.lookup_predicates(def_id)
2902-
.predicates.iter()
2903-
.flat_map(|predicate| {
2904-
let predicate =
2905-
normalize_with_depth(self, cause.clone(), recursion_depth,
2906-
&predicate.subst(tcx, substs));
2907-
predicate.obligations.into_iter().chain(
2908-
Some(Obligation {
2909-
cause: cause.clone(),
2910-
recursion_depth: recursion_depth,
2911-
predicate: predicate.value
2912-
}))
2913-
}).collect();
2900+
let predicates = tcx.lookup_predicates(def_id);
2901+
assert_eq!(predicates.parent, None);
2902+
let predicates = predicates.predicates.iter().flat_map(|predicate| {
2903+
let predicate = normalize_with_depth(self, cause.clone(), recursion_depth,
2904+
&predicate.subst(tcx, substs));
2905+
predicate.obligations.into_iter().chain(
2906+
Some(Obligation {
2907+
cause: cause.clone(),
2908+
recursion_depth: recursion_depth,
2909+
predicate: predicate.value
2910+
}))
2911+
}).collect();
29142912
self.infcx().plug_leaks(skol_map, snapshot, &predicates)
29152913
}
29162914
}

src/librustc/ty/mod.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -768,27 +768,38 @@ pub struct Generics<'tcx> {
768768
/// Bounds on generics.
769769
#[derive(Clone)]
770770
pub struct GenericPredicates<'tcx> {
771+
pub parent: Option<DefId>,
771772
pub predicates: Vec<Predicate<'tcx>>,
772773
}
773774

774775
impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
775-
pub fn empty() -> GenericPredicates<'tcx> {
776-
GenericPredicates {
777-
predicates: vec![]
778-
}
779-
}
780-
781776
pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
782777
-> InstantiatedPredicates<'tcx> {
778+
let mut instantiated = InstantiatedPredicates::empty();
779+
self.instantiate_into(tcx, &mut instantiated, substs);
780+
instantiated
781+
}
782+
pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
783+
-> InstantiatedPredicates<'tcx> {
783784
InstantiatedPredicates {
784-
predicates: self.predicates.subst(tcx, substs),
785+
predicates: self.predicates.subst(tcx, substs)
786+
}
787+
}
788+
789+
fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
790+
instantiated: &mut InstantiatedPredicates<'tcx>,
791+
substs: &Substs<'tcx>) {
792+
if let Some(def_id) = self.parent {
793+
tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs);
785794
}
795+
instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
786796
}
787797

788798
pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
789799
poly_trait_ref: &ty::PolyTraitRef<'tcx>)
790800
-> InstantiatedPredicates<'tcx>
791801
{
802+
assert_eq!(self.parent, None);
792803
InstantiatedPredicates {
793804
predicates: self.predicates.iter().map(|pred| {
794805
pred.subst_supertrait(tcx, poly_trait_ref)

src/librustc/ty/structural_impls.rs

-12
Original file line numberDiff line numberDiff line change
@@ -832,18 +832,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
832832
}
833833
}
834834

835-
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
836-
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
837-
ty::GenericPredicates {
838-
predicates: self.predicates.fold_with(folder),
839-
}
840-
}
841-
842-
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
843-
self.predicates.visit_with(visitor)
844-
}
845-
}
846-
847835
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
848836
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
849837
match *self {

src/librustc_metadata/decoder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,7 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
15911591
let doc = reader::get_doc(base_doc, tag);
15921592

15931593
ty::GenericPredicates {
1594+
parent: item_parent_item(cdata, doc),
15941595
predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| {
15951596
doc_predicate(cdata, predicate_doc, tcx)
15961597
}).collect()

src/librustc_metadata/encoder.rs

+3
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,9 @@ fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
525525
tag: usize)
526526
{
527527
rbml_w.start_tag(tag);
528+
if let Some(def_id) = predicates.parent {
529+
rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id));
530+
}
528531
for predicate in &predicates.predicates {
529532
rbml_w.wr_tagged_u32(tag_predicate,
530533
index.add_xref(XRef::Predicate(predicate.clone())));

src/librustc_typeck/astconv.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1726,6 +1726,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
17261726
let predicates = bounds.predicates(tcx, ty);
17271727
let predicates = tcx.lift_to_global(&predicates).unwrap();
17281728
tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates {
1729+
parent: None,
17291730
predicates: predicates
17301731
});
17311732

src/librustc_typeck/check/compare_method.rs

+10-20
Original file line numberDiff line numberDiff line change
@@ -211,29 +211,18 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
211211
return;
212212
}
213213

214-
// Depend on trait/impl predicates always being before method's own predicates,
215-
// to be able to split method predicates into "inherited" and method-specific.
216-
let trait_predicates = tcx.lookup_predicates(trait_m.container_id()).predicates;
217-
let impl_predicates = tcx.lookup_predicates(impl_m.container_id()).predicates;
218-
let trait_method_start = trait_predicates.len();
219-
let impl_method_start = impl_predicates.len();
220-
assert_eq!(&trait_predicates[..], &trait_m.predicates.predicates[..trait_method_start]);
221-
assert_eq!(&impl_predicates[..], &impl_m.predicates.predicates[..impl_method_start]);
222-
223214
tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| {
224215
let mut fulfillment_cx = traits::FulfillmentContext::new();
225216

226-
// Normalize the associated types in the trait_bounds.
227-
let trait_bounds = trait_m.predicates.instantiate(tcx, trait_to_skol_substs);
228-
229217
// Create obligations for each predicate declared by the impl
230218
// definition in the context of the trait's parameter
231219
// environment. We can't just use `impl_env.caller_bounds`,
232220
// however, because we want to replace all late-bound regions with
233221
// region variables.
234-
let impl_bounds = impl_m.predicates.instantiate(tcx, impl_to_skol_substs);
222+
let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap());
223+
let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs);
235224

236-
debug!("compare_impl_method: impl_bounds={:?}", impl_bounds);
225+
debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds);
237226

238227
// This is the only tricky bit of the new way we check implementation methods
239228
// We need to build a set of predicates where only the FnSpace bounds
@@ -242,14 +231,14 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
242231
//
243232
// We then register the obligations from the impl_m and check to see
244233
// if all constraints hold.
245-
let hybrid_preds = impl_bounds.predicates[..impl_method_start].iter()
246-
.chain(trait_bounds.predicates[trait_method_start..].iter());
234+
hybrid_preds.predicates.extend(
235+
trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
247236

248237
// Construct trait parameter environment and then shift it into the skolemized viewpoint.
249238
// The key step here is to update the caller_bounds's predicates to be
250239
// the new hybrid bounds we computed.
251240
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
252-
let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.cloned().collect());
241+
let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
253242
let trait_param_env = traits::normalize_param_env_or_error(tcx,
254243
trait_param_env,
255244
normalize_cause.clone());
@@ -261,12 +250,13 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
261250

262251
let mut selcx = traits::SelectionContext::new(&infcx);
263252

264-
let (impl_pred_fns, _) =
253+
let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs);
254+
let (impl_m_own_bounds, _) =
265255
infcx.replace_late_bound_regions_with_fresh_var(
266256
impl_m_span,
267257
infer::HigherRankedType,
268-
&ty::Binder(impl_bounds.predicates[impl_method_start..].to_vec()));
269-
for predicate in impl_pred_fns {
258+
&ty::Binder(impl_m_own_bounds.predicates));
259+
for predicate in impl_m_own_bounds {
270260
let traits::Normalized { value: predicate, .. } =
271261
traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
272262

src/librustc_typeck/check/dropck.rs

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
184184
// 'a:'b and T:'b into region inference constraints. It is simpler
185185
// just to look for all the predicates directly.
186186

187+
assert_eq!(dtor_predicates.parent, None);
187188
for predicate in &dtor_predicates.predicates {
188189
// (We do not need to worry about deep analysis of type
189190
// expressions etc because the Drop impls are already forced

src/librustc_typeck/check/mod.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1612,8 +1612,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
16121612
bounds: &ty::GenericPredicates<'tcx>)
16131613
-> ty::InstantiatedPredicates<'tcx>
16141614
{
1615+
let result = bounds.instantiate(self.tcx, substs);
1616+
let result = self.normalize_associated_types_in(span, &result.predicates);
1617+
debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
1618+
bounds,
1619+
substs,
1620+
result);
16151621
ty::InstantiatedPredicates {
1616-
predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates)
1622+
predicates: result
16171623
}
16181624
}
16191625

@@ -4210,8 +4216,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42104216
}
42114217
_ => {}
42124218
}
4213-
let scheme = self.tcx.lookup_item_type(def.def_id());
4214-
let type_predicates = self.tcx.lookup_predicates(def.def_id());
42154219

42164220
// Now we have to compare the types that the user *actually*
42174221
// provided against the types that were *expected*. If the user
@@ -4296,6 +4300,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
42964300

42974301
// The things we are substituting into the type should not contain
42984302
// escaping late-bound regions, and nor should the base type scheme.
4303+
let scheme = self.tcx.lookup_item_type(def.def_id());
4304+
let type_predicates = self.tcx.lookup_predicates(def.def_id());
42994305
assert!(!substs.has_escaping_regions());
43004306
assert!(!scheme.ty.has_escaping_regions());
43014307

src/librustc_typeck/check/regionck.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1754,6 +1754,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
17541754
//
17551755
// we can thus deduce that `<T as SomeTrait<'a>>::SomeType : 'a`.
17561756
let trait_predicates = self.tcx.lookup_predicates(projection_ty.trait_ref.def_id);
1757+
assert_eq!(trait_predicates.parent, None);
17571758
let predicates = trait_predicates.predicates.as_slice().to_vec();
17581759
traits::elaborate_predicates(self.tcx, predicates)
17591760
.filter_map(|predicate| {

src/librustc_typeck/check/wfcheck.rs

+1
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
454454

455455
let item_def_id = self.tcx().map.local_def_id(item.id);
456456
let ty_predicates = self.tcx().lookup_predicates(item_def_id);
457+
assert_eq!(ty_predicates.parent, None);
457458
let variances = self.tcx().item_variances(item_def_id);
458459

459460
let mut constrained_parameters: HashSet<_> =

0 commit comments

Comments
 (0)