Skip to content

Commit 5a28d17

Browse files
committed
Allow impl's to have late-bound regions. Introduces another level of
region binding at the impl site, so for method types that come from impls, it is necessary to liberate/instantiate late-bound regions at multiple depths.
1 parent 6fb68f1 commit 5a28d17

File tree

19 files changed

+729
-261
lines changed

19 files changed

+729
-261
lines changed

src/librustc/middle/resolve_lifetime.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,21 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
105105
ast::ItemTy(_, ref generics) |
106106
ast::ItemEnum(_, ref generics) |
107107
ast::ItemStruct(_, ref generics) |
108-
ast::ItemTrait(ref generics, _, _, _) |
109-
ast::ItemImpl(ref generics, _, _, _) => {
108+
ast::ItemTrait(ref generics, _, _, _) => {
110109
// These kinds of items have only early bound lifetime parameters.
111110
let lifetimes = &generics.lifetimes;
112111
self.with(EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE), |this| {
113112
this.check_lifetime_defs(lifetimes);
114113
visit::walk_item(this, item);
115114
});
116115
}
116+
ast::ItemImpl(ref generics, _, _, _) => {
117+
// Impls have both early- and late-bound lifetimes.
118+
self.visit_early_late(subst::TypeSpace, generics, |this| {
119+
this.check_lifetime_defs(&generics.lifetimes);
120+
visit::walk_item(this, item);
121+
})
122+
}
117123
}
118124
}
119125

@@ -493,10 +499,10 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
493499
FreeLifetimeCollector { early_bound: &mut early_bound,
494500
late_bound: &mut late_bound };
495501
for ty_param in generics.ty_params.iter() {
496-
visit::walk_ty_param_bounds(&mut collector, &ty_param.bounds);
502+
visit::walk_ty_param_bounds_helper(&mut collector, &ty_param.bounds);
497503
}
498504
for predicate in generics.where_clause.predicates.iter() {
499-
visit::walk_ty_param_bounds(&mut collector, &predicate.bounds);
505+
visit::walk_ty_param_bounds_helper(&mut collector, &predicate.bounds);
500506
}
501507
}
502508

src/librustc/middle/subst.rs

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ impl Substs {
100100
regions_is_noop && self.types.is_empty()
101101
}
102102

103+
pub fn has_regions_escaping_depth(&self, depth: uint) -> bool {
104+
self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
105+
match self.regions {
106+
ErasedRegions =>
107+
false,
108+
NonerasedRegions(ref regions) =>
109+
regions.iter().any(|r| r.escapes_depth(depth)),
110+
}
111+
}
112+
}
113+
103114
pub fn self_ty(&self) -> Option<ty::t> {
104115
self.types.get_self().map(|&t| t)
105116
}
@@ -165,6 +176,13 @@ impl RegionSubsts {
165176
NonerasedRegions(r) => NonerasedRegions(op(r, a))
166177
}
167178
}
179+
180+
pub fn is_erased(&self) -> bool {
181+
match *self {
182+
ErasedRegions => true,
183+
NonerasedRegions(_) => false,
184+
}
185+
}
168186
}
169187

170188
///////////////////////////////////////////////////////////////////////////
@@ -391,6 +409,10 @@ impl<T> VecPerParamSpace<T> {
391409
self.content.iter()
392410
}
393411

412+
pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> {
413+
EnumeratedItems::new(self)
414+
}
415+
394416
pub fn as_slice(&self) -> &[T] {
395417
self.content.as_slice()
396418
}
@@ -420,6 +442,14 @@ impl<T> VecPerParamSpace<T> {
420442
self.assoc_limit)
421443
}
422444

445+
pub fn map_enumerated<U>(&self, pred: |(ParamSpace, uint, &T)| -> U) -> VecPerParamSpace<U> {
446+
let result = self.iter_enumerated().map(pred).collect();
447+
VecPerParamSpace::new_internal(result,
448+
self.type_limit,
449+
self.self_limit,
450+
self.assoc_limit)
451+
}
452+
423453
pub fn map_move<U>(self, pred: |T| -> U) -> VecPerParamSpace<U> {
424454
let SeparateVecsPerParamSpace {
425455
types: t,
@@ -456,6 +486,49 @@ impl<T> VecPerParamSpace<T> {
456486
}
457487
}
458488

489+
pub struct EnumeratedItems<'a,T:'a> {
490+
vec: &'a VecPerParamSpace<T>,
491+
space_index: uint,
492+
elem_index: uint
493+
}
494+
495+
impl<'a,T> EnumeratedItems<'a,T> {
496+
fn new(v: &'a VecPerParamSpace<T>) -> EnumeratedItems<'a,T> {
497+
let mut result = EnumeratedItems { vec: v, space_index: 0, elem_index: 0 };
498+
result.adjust_space();
499+
result
500+
}
501+
502+
fn adjust_space(&mut self) {
503+
let spaces = ParamSpace::all();
504+
while
505+
self.space_index < spaces.len() &&
506+
self.elem_index >= self.vec.len(spaces[self.space_index])
507+
{
508+
self.space_index += 1;
509+
self.elem_index = 0;
510+
}
511+
}
512+
}
513+
514+
impl<'a,T> Iterator<(ParamSpace, uint, &'a T)> for EnumeratedItems<'a,T> {
515+
fn next(&mut self) -> Option<(ParamSpace, uint, &'a T)> {
516+
let spaces = ParamSpace::all();
517+
if self.space_index < spaces.len() {
518+
let space = spaces[self.space_index];
519+
let index = self.elem_index;
520+
let item = self.vec.get(space, index);
521+
522+
self.elem_index += 1;
523+
self.adjust_space();
524+
525+
Some((space, index, item))
526+
} else {
527+
None
528+
}
529+
}
530+
}
531+
459532
///////////////////////////////////////////////////////////////////////////
460533
// Public trait `Subst`
461534
//
@@ -485,7 +558,8 @@ impl<T:TypeFoldable> Subst for T {
485558
substs: substs,
486559
span: span,
487560
root_ty: None,
488-
ty_stack_depth: 0 };
561+
ty_stack_depth: 0,
562+
region_binders_passed: 0 };
489563
(*self).fold_with(&mut folder)
490564
}
491565
}

src/librustc/middle/traits/coherence.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use super::util;
1717
use middle::subst;
1818
use middle::subst::Subst;
1919
use middle::ty;
20-
use middle::typeck::infer::InferCtxt;
20+
use middle::typeck::infer::{mod, InferCtxt};
2121
use syntax::ast;
2222
use syntax::codemap::DUMMY_SP;
2323
use util::ppaux::Repr;
@@ -38,14 +38,18 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
3838
util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
3939
let impl1_trait_ref =
4040
ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()
41-
.subst(infcx.tcx, &impl1_substs);
41+
.subst(infcx.tcx, &impl1_substs);
42+
let impl1_trait_ref =
43+
infcx.replace_late_bound_regions_with_fresh_var(DUMMY_SP,
44+
infer::FnCall,
45+
&impl1_trait_ref).0;
4246

4347
// Determine whether `impl2` can provide an implementation for those
4448
// same types.
4549
let param_env = ty::empty_parameter_environment();
4650
let mut selcx = SelectionContext::intercrate(infcx, &param_env, infcx.tcx);
4751
let obligation = Obligation::misc(DUMMY_SP, impl1_trait_ref);
48-
debug!("impl_can_satisfy obligation={}", obligation.repr(infcx.tcx));
52+
debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx));
4953
selcx.evaluate_impl(impl2_def_id, &obligation)
5054
}
5155

src/librustc/middle/traits/mod.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -281,33 +281,28 @@ pub fn overlapping_impls(infcx: &InferCtxt,
281281
coherence::impl_can_satisfy(infcx, impl2_def_id, impl1_def_id)
282282
}
283283

284-
pub fn impl_obligations(tcx: &ty::ctxt,
285-
cause: ObligationCause,
286-
impl_def_id: ast::DefId,
287-
impl_substs: &subst::Substs)
288-
-> subst::VecPerParamSpace<Obligation>
289-
{
290-
let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
291-
obligations_for_generics(tcx, cause, &impl_generics, impl_substs)
292-
}
293-
294284
pub fn obligations_for_generics(tcx: &ty::ctxt,
295285
cause: ObligationCause,
296-
generics: &ty::Generics,
297-
substs: &subst::Substs)
286+
generic_bounds: &ty::GenericBounds,
287+
type_substs: &subst::VecPerParamSpace<ty::t>)
298288
-> subst::VecPerParamSpace<Obligation>
299289
{
300290
/*!
301-
* Given generics for an impl like:
291+
* Given generic bounds from an impl like:
302292
*
303293
* impl<A:Foo, B:Bar+Qux> ...
304294
*
305-
* and a substs vector like `<A=A0, B=B0>`, yields a result like
295+
* along with the bindings for the types `A` and `B` (e.g.,
296+
* `<A=A0, B=B0>`), yields a result like
306297
*
307298
* [[Foo for A0, Bar for B0, Qux for B0], [], []]
299+
*
300+
* Expects that `generic_bounds` have already been fully
301+
* substituted, late-bound regions liberated and so forth,
302+
* so that they are in the same namespace as `type_substs`.
308303
*/
309304

310-
util::obligations_for_generics(tcx, cause, 0, generics, substs)
305+
util::obligations_for_generics(tcx, cause, 0, generic_bounds, type_substs)
311306
}
312307

313308
pub fn obligation_for_builtin_bound(tcx: &ty::ctxt,

src/librustc/middle/traits/select.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2017,10 +2017,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20172017
impl_substs: &Substs)
20182018
-> VecPerParamSpace<Obligation>
20192019
{
2020-
let impl_generics = ty::lookup_item_type(self.tcx(),
2021-
impl_def_id).generics;
2020+
let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
2021+
let bounds = impl_generics.to_bounds(self.tcx(), impl_substs);
20222022
util::obligations_for_generics(self.tcx(), cause, recursion_depth,
2023-
&impl_generics, impl_substs)
2023+
&bounds, &impl_substs.types)
20242024
}
20252025
}
20262026

src/librustc/middle/traits/util.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// except according to those terms.
1111

1212
use middle::subst;
13-
use middle::subst::{ParamSpace, Subst, Substs, VecPerParamSpace};
13+
use middle::subst::{ParamSpace, Substs, VecPerParamSpace};
1414
use middle::typeck::infer::InferCtxt;
1515
use middle::ty;
1616
use std::collections::HashSet;
@@ -173,25 +173,25 @@ impl fmt::Show for VtableParamData {
173173
pub fn obligations_for_generics(tcx: &ty::ctxt,
174174
cause: ObligationCause,
175175
recursion_depth: uint,
176-
generics: &ty::Generics,
177-
substs: &Substs)
176+
generic_bounds: &ty::GenericBounds,
177+
type_substs: &VecPerParamSpace<ty::t>)
178178
-> VecPerParamSpace<Obligation>
179179
{
180180
/*! See `super::obligations_for_generics` */
181181

182-
debug!("obligations_for_generics(generics={}, substs={})",
183-
generics.repr(tcx), substs.repr(tcx));
182+
debug!("obligations_for_generics(generic_bounds={}, type_substs={})",
183+
generic_bounds.repr(tcx), type_substs.repr(tcx));
184184

185185
let mut obligations = VecPerParamSpace::empty();
186186

187-
for def in generics.types.iter() {
187+
for (space, index, bounds) in generic_bounds.types.iter_enumerated() {
188188
push_obligations_for_param_bounds(tcx,
189189
cause,
190190
recursion_depth,
191-
def.space,
192-
def.index,
193-
&def.bounds,
194-
substs,
191+
space,
192+
index,
193+
bounds,
194+
type_substs,
195195
&mut obligations);
196196
}
197197

@@ -207,11 +207,10 @@ fn push_obligations_for_param_bounds(
207207
space: subst::ParamSpace,
208208
index: uint,
209209
param_bounds: &ty::ParamBounds,
210-
param_substs: &Substs,
210+
param_type_substs: &VecPerParamSpace<ty::t>,
211211
obligations: &mut VecPerParamSpace<Obligation>)
212212
{
213-
let param_ty = *param_substs.types.get(space, index);
214-
213+
let param_ty = *param_type_substs.get(space, index);
215214
for builtin_bound in param_bounds.builtin_bounds.iter() {
216215
let obligation = obligation_for_builtin_bound(tcx,
217216
cause,
@@ -225,12 +224,11 @@ fn push_obligations_for_param_bounds(
225224
}
226225

227226
for bound_trait_ref in param_bounds.trait_bounds.iter() {
228-
let bound_trait_ref = bound_trait_ref.subst(tcx, param_substs);
229227
obligations.push(
230228
space,
231229
Obligation { cause: cause,
232230
recursion_depth: recursion_depth,
233-
trait_ref: bound_trait_ref });
231+
trait_ref: (*bound_trait_ref).clone() });
234232
}
235233
}
236234

0 commit comments

Comments
 (0)