Skip to content

Commit 51357e0

Browse files
committed
rollup merge of #20665: nikomatsakis/assoc-types-method-dispatch-projection
Conflicts: src/librustc/middle/ty.rs
2 parents 6afda64 + ab02f9e commit 51357e0

File tree

8 files changed

+226
-41
lines changed

8 files changed

+226
-41
lines changed

src/librustc/middle/infer/combine.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,16 @@ impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
427427
}
428428
}
429429

430+
impl<'tcx> Combineable<'tcx> for Ty<'tcx> {
431+
fn combine<C:Combine<'tcx>>(combiner: &C,
432+
a: &Ty<'tcx>,
433+
b: &Ty<'tcx>)
434+
-> cres<'tcx, Ty<'tcx>>
435+
{
436+
combiner.tys(*a, *b)
437+
}
438+
}
439+
430440
impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> {
431441
fn combine<C:Combine<'tcx>>(combiner: &C,
432442
a: &ty::ProjectionPredicate<'tcx>,

src/librustc/middle/infer/mod.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use util::ppaux::{ty_to_string};
3939
use util::ppaux::{Repr, UserString};
4040

4141
use self::coercion::Coerce;
42-
use self::combine::{Combine, CombineFields};
42+
use self::combine::{Combine, Combineable, CombineFields};
4343
use self::region_inference::{RegionVarBindings, RegionSnapshot};
4444
use self::equate::Equate;
4545
use self::sub::Sub;
@@ -360,17 +360,9 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
360360
})
361361
}
362362

363-
pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
364-
a: Ty<'tcx>, b: Ty<'tcx>)
365-
-> ures<'tcx> {
366-
debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
367-
cx.probe(|_| {
368-
let trace = TypeTrace {
369-
origin: Misc(codemap::DUMMY_SP),
370-
values: Types(expected_found(true, a, b))
371-
};
372-
cx.equate(true, trace).tys(a, b)
373-
}).to_ures()
363+
pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> ures<'tcx>
364+
{
365+
cx.can_equate(&a, &b)
374366
}
375367

376368
pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
@@ -1072,6 +1064,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10721064

10731065
self.region_vars.verify_generic_bound(origin, kind, a, bs);
10741066
}
1067+
1068+
pub fn can_equate<T>(&self, a: &T, b: &T) -> ures<'tcx>
1069+
where T : Combineable<'tcx> + Repr<'tcx>
1070+
{
1071+
debug!("can_equate({}, {})", a.repr(self.tcx), b.repr(self.tcx));
1072+
self.probe(|_| {
1073+
// Gin up a dummy trace, since this won't be committed
1074+
// anyhow. We should make this typetrace stuff more
1075+
// generic so we don't have to do anything quite this
1076+
// terrible.
1077+
let e = self.tcx.types.err;
1078+
let trace = TypeTrace { origin: Misc(codemap::DUMMY_SP),
1079+
values: Types(expected_found(true, e, e)) };
1080+
let eq = self.equate(true, trace);
1081+
Combineable::combine(&eq, a, b)
1082+
}).to_ures()
1083+
}
10751084
}
10761085

10771086
impl<'tcx> TypeTrace<'tcx> {

src/librustc/middle/subst.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ impl<T> VecPerParamSpace<T> {
394394
self.content.as_slice()
395395
}
396396

397-
pub fn to_vec(self) -> Vec<T> {
397+
pub fn into_vec(self) -> Vec<T> {
398398
self.content
399399
}
400400

src/librustc/middle/traits/project.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ fn confirm_candidate<'cx,'tcx>(
649649
}
650650

651651
match impl_ty {
652-
Some(ty) => (ty, impl_vtable.nested.to_vec()),
652+
Some(ty) => (ty, impl_vtable.nested.into_vec()),
653653
None => {
654654
// This means that the impl is missing a
655655
// definition for the associated type. This error

src/librustc/middle/traits/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
835835
bounds.repr(self.tcx()));
836836

837837
let matching_bound =
838-
util::elaborate_predicates(self.tcx(), bounds.predicates.to_vec())
838+
util::elaborate_predicates(self.tcx(), bounds.predicates.into_vec())
839839
.filter_to_traits()
840840
.find(
841841
|bound| self.infcx.probe(

src/librustc/middle/ty.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,10 +1498,12 @@ impl<'tcx> PolyTraitRef<'tcx> {
14981498
}
14991499

15001500
pub fn substs(&self) -> &'tcx Substs<'tcx> {
1501+
// FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
15011502
self.0.substs
15021503
}
15031504

15041505
pub fn input_types(&self) -> &[Ty<'tcx>] {
1506+
// FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
15051507
self.0.input_types()
15061508
}
15071509

@@ -6977,6 +6979,13 @@ impl<'tcx> RegionEscape for Ty<'tcx> {
69776979
}
69786980
}
69796981

6982+
impl<'tcx> RegionEscape for Substs<'tcx> {
6983+
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
6984+
self.types.has_regions_escaping_depth(depth) ||
6985+
self.regions.has_regions_escaping_depth(depth)
6986+
}
6987+
}
6988+
69806989
impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> {
69816990
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
69826991
self.iter_enumerated().any(|(space, _, t)| {

src/librustc_typeck/check/method/probe.rs

Lines changed: 105 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use middle::fast_reject;
1818
use middle::subst;
1919
use middle::subst::Subst;
2020
use middle::traits;
21-
use middle::ty::{self, Ty, ToPolyTraitRef};
21+
use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef};
2222
use middle::ty_fold::TypeFoldable;
2323
use middle::infer;
2424
use middle::infer::InferCtxt;
@@ -62,6 +62,7 @@ enum CandidateKind<'tcx> {
6262
subst::Substs<'tcx>, MethodIndex),
6363
UnboxedClosureCandidate(/* Trait */ ast::DefId, MethodIndex),
6464
WhereClauseCandidate(ty::PolyTraitRef<'tcx>, MethodIndex),
65+
ProjectionCandidate(ast::DefId, MethodIndex),
6566
}
6667

6768
pub struct Pick<'tcx> {
@@ -309,18 +310,20 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
309310
// argument type like `&Trait`.
310311
let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
311312
self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
313+
let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
314+
312315
let vtable_index =
313316
traits::get_vtable_index_of_object_method(tcx,
314317
trait_ref.clone(),
315-
new_trait_ref.def_id(),
318+
new_trait_ref.def_id,
316319
method_num);
317320

318-
let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs());
321+
let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs);
319322

320323
this.inherent_candidates.push(Candidate {
321324
xform_self_ty: xform_self_ty,
322325
method_ty: m,
323-
kind: ObjectCandidate(new_trait_ref.def_id(), method_num, vtable_index)
326+
kind: ObjectCandidate(new_trait_ref.def_id, method_num, vtable_index)
324327
});
325328
});
326329
}
@@ -353,34 +356,37 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
353356
})
354357
.collect();
355358

356-
self.elaborate_bounds(bounds.as_slice(), true, |this, trait_ref, m, method_num| {
359+
self.elaborate_bounds(bounds.as_slice(), true, |this, poly_trait_ref, m, method_num| {
360+
let trait_ref =
361+
this.erase_late_bound_regions(&poly_trait_ref);
362+
357363
let xform_self_ty =
358-
this.xform_self_ty(&m, trait_ref.substs());
364+
this.xform_self_ty(&m, trait_ref.substs);
359365

360366
debug!("found match: trait_ref={} substs={} m={}",
361367
trait_ref.repr(this.tcx()),
362-
trait_ref.substs().repr(this.tcx()),
368+
trait_ref.substs.repr(this.tcx()),
363369
m.repr(this.tcx()));
364370
assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
365-
trait_ref.substs().types.get_slice(subst::TypeSpace).len());
371+
trait_ref.substs.types.get_slice(subst::TypeSpace).len());
366372
assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
367-
trait_ref.substs().regions().get_slice(subst::TypeSpace).len());
373+
trait_ref.substs.regions().get_slice(subst::TypeSpace).len());
368374
assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(),
369-
trait_ref.substs().types.get_slice(subst::SelfSpace).len());
375+
trait_ref.substs.types.get_slice(subst::SelfSpace).len());
370376
assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
371-
trait_ref.substs().regions().get_slice(subst::SelfSpace).len());
377+
trait_ref.substs.regions().get_slice(subst::SelfSpace).len());
372378

373379
// Because this trait derives from a where-clause, it
374380
// should not contain any inference variables or other
375381
// artifacts. This means it is safe to put into the
376382
// `WhereClauseCandidate` and (eventually) into the
377383
// `WhereClausePick`.
378-
assert!(trait_ref.substs().types.iter().all(|&t| !ty::type_needs_infer(t)));
384+
assert!(trait_ref.substs.types.iter().all(|&t| !ty::type_needs_infer(t)));
379385

380386
this.inherent_candidates.push(Candidate {
381387
xform_self_ty: xform_self_ty,
382388
method_ty: m,
383-
kind: WhereClauseCandidate(trait_ref, method_num)
389+
kind: WhereClauseCandidate(poly_trait_ref, method_num)
384390
});
385391
});
386392
}
@@ -474,6 +480,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
474480
method.clone(),
475481
matching_index);
476482

483+
self.assemble_projection_candidates(trait_def_id,
484+
method.clone(),
485+
matching_index);
486+
477487
self.assemble_where_clause_candidates(trait_def_id,
478488
method,
479489
matching_index);
@@ -603,6 +613,64 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
603613
}
604614
}
605615

616+
fn assemble_projection_candidates(&mut self,
617+
trait_def_id: ast::DefId,
618+
method: Rc<ty::Method<'tcx>>,
619+
method_index: uint)
620+
{
621+
debug!("assemble_projection_candidates(\
622+
trait_def_id={}, \
623+
method={}, \
624+
method_index={})",
625+
trait_def_id.repr(self.tcx()),
626+
method.repr(self.tcx()),
627+
method_index);
628+
629+
for step in self.steps.iter() {
630+
debug!("assemble_projection_candidates: step={}",
631+
step.repr(self.tcx()));
632+
633+
let projection_trait_ref = match step.self_ty.sty {
634+
ty::ty_projection(ref data) => &data.trait_ref,
635+
_ => continue,
636+
};
637+
638+
debug!("assemble_projection_candidates: projection_trait_ref={}",
639+
projection_trait_ref.repr(self.tcx()));
640+
641+
let trait_def = ty::lookup_trait_def(self.tcx(), projection_trait_ref.def_id);
642+
let bounds = trait_def.generics.to_bounds(self.tcx(), projection_trait_ref.substs);
643+
let predicates = bounds.predicates.into_vec();
644+
debug!("assemble_projection_candidates: predicates={}",
645+
predicates.repr(self.tcx()));
646+
for poly_bound in
647+
traits::elaborate_predicates(self.tcx(), predicates)
648+
.filter_map(|p| p.to_opt_poly_trait_ref())
649+
.filter(|b| b.def_id() == trait_def_id)
650+
{
651+
let bound = self.erase_late_bound_regions(&poly_bound);
652+
653+
debug!("assemble_projection_candidates: projection_trait_ref={} bound={}",
654+
projection_trait_ref.repr(self.tcx()),
655+
bound.repr(self.tcx()));
656+
657+
if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
658+
let xform_self_ty = self.xform_self_ty(&method, bound.substs);
659+
660+
debug!("assemble_projection_candidates: bound={} xform_self_ty={}",
661+
bound.repr(self.tcx()),
662+
xform_self_ty.repr(self.tcx()));
663+
664+
self.extension_candidates.push(Candidate {
665+
xform_self_ty: xform_self_ty,
666+
method_ty: method.clone(),
667+
kind: ProjectionCandidate(trait_def_id, method_index)
668+
});
669+
}
670+
}
671+
}
672+
}
673+
606674
fn assemble_where_clause_candidates(&mut self,
607675
trait_def_id: ast::DefId,
608676
method_ty: Rc<ty::Method<'tcx>>,
@@ -611,14 +679,14 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
611679
debug!("assemble_where_clause_candidates(trait_def_id={})",
612680
trait_def_id.repr(self.tcx()));
613681

614-
// Check whether there are any where-clauses pertaining to this trait.
615682
let caller_predicates =
616683
self.fcx.inh.param_env.caller_bounds.predicates.as_slice().to_vec();
617-
for bound in traits::elaborate_predicates(self.tcx(), caller_predicates)
618-
.filter_map(|p| p.to_opt_poly_trait_ref())
619-
.filter(|b| b.def_id() == trait_def_id)
684+
for poly_bound in traits::elaborate_predicates(self.tcx(), caller_predicates)
685+
.filter_map(|p| p.to_opt_poly_trait_ref())
686+
.filter(|b| b.def_id() == trait_def_id)
620687
{
621-
let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs());
688+
let bound = self.erase_late_bound_regions(&poly_bound);
689+
let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs);
622690

623691
debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}",
624692
bound.repr(self.tcx()),
@@ -627,7 +695,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
627695
self.extension_candidates.push(Candidate {
628696
xform_self_ty: xform_self_ty,
629697
method_ty: method_ty.clone(),
630-
kind: WhereClauseCandidate(bound, method_index)
698+
kind: WhereClauseCandidate(poly_bound, method_index)
631699
});
632700
}
633701
}
@@ -829,6 +897,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
829897
norm_obligations.iter().all(|o| selcx.evaluate_obligation(o))
830898
}
831899

900+
ProjectionCandidate(..) |
832901
ObjectCandidate(..) |
833902
UnboxedClosureCandidate(..) |
834903
WhereClauseCandidate(..) => {
@@ -920,6 +989,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
920989
method.fty.sig.0.inputs[0].repr(self.tcx()),
921990
substs.repr(self.tcx()));
922991

992+
assert!(!substs.has_escaping_regions());
993+
923994
// It is possible for type parameters or early-bound lifetimes
924995
// to appear in the signature of `self`. The substitutions we
925996
// are given do not include type/lifetime parameters for the
@@ -949,14 +1020,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
9491020
substs = &placeholder;
9501021
}
9511022

952-
// Replace early-bound regions and types.
953-
let xform_self_ty = method.fty.sig.0.inputs[0].subst(self.tcx(), substs);
1023+
// Erase any late-bound regions from the method and substitute
1024+
// in the values from the substitution.
1025+
let xform_self_ty = method.fty.sig.input(0);
1026+
let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty);
1027+
let xform_self_ty = xform_self_ty.subst(self.tcx(), substs);
9541028

955-
// Replace late-bound regions bound in the impl or
956-
// where-clause (2 levels of binding) and method (1 level of binding).
957-
self.erase_late_bound_regions(
958-
&self.erase_late_bound_regions(
959-
&ty::Binder(ty::Binder(xform_self_ty))))
1029+
xform_self_ty
9601030
}
9611031

9621032
fn impl_substs(&self,
@@ -1065,6 +1135,9 @@ impl<'tcx> Candidate<'tcx> {
10651135

10661136
WhereClausePick((*trait_ref).clone(), index)
10671137
}
1138+
ProjectionCandidate(def_id, index) => {
1139+
TraitPick(def_id, index)
1140+
}
10681141
}
10691142
}
10701143
}
@@ -1076,6 +1149,7 @@ impl<'tcx> Candidate<'tcx> {
10761149
ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id),
10771150
UnboxedClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
10781151
WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
1152+
ProjectionCandidate(trait_def_id, _) => TraitSource(trait_def_id),
10791153
}
10801154
}
10811155

@@ -1094,6 +1168,9 @@ impl<'tcx> Candidate<'tcx> {
10941168
WhereClauseCandidate(ref trait_ref, method_num) => {
10951169
Some((trait_ref.def_id(), method_num))
10961170
}
1171+
ProjectionCandidate(trait_def_id, method_num) => {
1172+
Some((trait_def_id, method_num))
1173+
}
10971174
}
10981175
}
10991176
}
@@ -1120,6 +1197,8 @@ impl<'tcx> Repr<'tcx> for CandidateKind<'tcx> {
11201197
format!("UnboxedClosureCandidate({},{})", a.repr(tcx), b),
11211198
WhereClauseCandidate(ref a, ref b) =>
11221199
format!("WhereClauseCandidate({},{})", a.repr(tcx), b),
1200+
ProjectionCandidate(ref a, ref b) =>
1201+
format!("ProjectionCandidate({},{})", a.repr(tcx), b),
11231202
}
11241203
}
11251204
}

0 commit comments

Comments
 (0)