Skip to content

Commit 6cdccc5

Browse files
arielb1Ariel Ben-Yehuda
authored and
Ariel Ben-Yehuda
committed
Make impl-trait-ref associated types work in methods
1 parent 1af7266 commit 6cdccc5

File tree

4 files changed

+85
-28
lines changed

4 files changed

+85
-28
lines changed

src/librustc/middle/traits/project.rs

+4
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,19 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
389389
}
390390
}
391391
Ok(ProjectedTy::NoProgress(projected_ty)) => {
392+
debug!("normalize_projection_type: projected_ty={} no progress",
393+
projected_ty.repr(selcx.tcx()));
392394
Some(Normalized {
393395
value: projected_ty,
394396
obligations: vec!()
395397
})
396398
}
397399
Err(ProjectionTyError::TooManyCandidates) => {
400+
debug!("normalize_projection_type: too many candidates");
398401
None
399402
}
400403
Err(ProjectionTyError::TraitSelectionError(_)) => {
404+
debug!("normalize_projection_type: ERROR");
401405
// if we got an error processing the `T as Trait` part,
402406
// just return `ty::err` but add the obligation `T :
403407
// Trait`, which when processed will cause the error to be

src/librustc_typeck/check/method/probe.rs

+44-27
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@ struct Candidate<'tcx> {
5959
}
6060

6161
enum CandidateKind<'tcx> {
62-
InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
62+
InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>,
63+
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
6364
ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ usize, /* vtable index */ usize),
6465
ExtensionImplCandidate(/* Impl */ ast::DefId, ty::TraitRef<'tcx>,
65-
subst::Substs<'tcx>, ItemIndex),
66+
subst::Substs<'tcx>, ItemIndex,
67+
/* Normalize obligations */ Vec<traits::PredicateObligation<'tcx>>),
6668
ClosureCandidate(/* Trait */ ast::DefId, ItemIndex),
6769
WhereClauseCandidate(ty::PolyTraitRef<'tcx>, ItemIndex),
6870
ProjectionCandidate(ast::DefId, ItemIndex),
@@ -398,24 +400,24 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
398400
}
399401

400402
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
403+
let impl_ty = impl_ty.subst(self.tcx(), &impl_substs);
401404

402-
// We can't use instantiate_type_scheme here as it will pollute
403-
// the fcx's fulfillment context if this probe is rolled back.
405+
// Determine the receiver type that the method itself expects.
406+
let xform_self_ty = self.xform_self_ty(&item, impl_ty, &impl_substs);
407+
408+
// We can't use normalize_associated_types_in as it will pollute the
409+
// fcx's fulfillment context after this probe is over.
404410
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
405411
let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx);
406-
let traits::Normalized { value: impl_ty, .. } =
407-
traits::normalize(selcx, cause, &impl_ty.subst(self.tcx(), &impl_substs));
408-
409-
// Determine the receiver type that the method itself expects.
410-
let xform_self_ty =
411-
self.xform_self_ty(&item, impl_ty, &impl_substs);
412-
debug!("assemble_inherent_impl_probe: self ty = {:?}",
412+
let traits::Normalized { value: xform_self_ty, obligations } =
413+
traits::normalize(selcx, cause, &xform_self_ty);
414+
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
413415
xform_self_ty.repr(self.tcx()));
414416

415417
self.inherent_candidates.push(Candidate {
416418
xform_self_ty: xform_self_ty,
417419
item: item,
418-
kind: InherentImplCandidate(impl_def_id, impl_substs)
420+
kind: InherentImplCandidate(impl_def_id, impl_substs, obligations)
419421
});
420422
}
421423

@@ -661,12 +663,24 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
661663
impl_trait_ref.self_ty(),
662664
impl_trait_ref.substs);
663665

666+
// Normalize the receiver. We can't use normalize_associated_types_in
667+
// as it will pollute the fcx's fulfillment context after this probe
668+
// is over.
669+
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
670+
let mut selcx = &mut traits::SelectionContext::new(self.fcx.infcx(), self.fcx);
671+
let traits::Normalized { value: xform_self_ty, obligations } =
672+
traits::normalize(selcx, cause, &xform_self_ty);
673+
664674
debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
665675

666676
self.extension_candidates.push(Candidate {
667677
xform_self_ty: xform_self_ty,
668678
item: item.clone(),
669-
kind: ExtensionImplCandidate(impl_def_id, impl_trait_ref, impl_substs, item_index)
679+
kind: ExtensionImplCandidate(impl_def_id,
680+
impl_trait_ref,
681+
impl_substs,
682+
item_index,
683+
obligations)
670684
});
671685
});
672686
}
@@ -1034,8 +1048,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
10341048
// match as well (or at least may match, sometimes we
10351049
// don't have enough information to fully evaluate).
10361050
match probe.kind {
1037-
InherentImplCandidate(impl_def_id, ref substs) |
1038-
ExtensionImplCandidate(impl_def_id, _, ref substs, _) => {
1051+
InherentImplCandidate(impl_def_id, ref substs, ref ref_obligations) |
1052+
ExtensionImplCandidate(impl_def_id, _, ref substs, _, ref ref_obligations) => {
10391053
let selcx = &mut traits::SelectionContext::new(self.infcx(), self.fcx);
10401054
let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
10411055

@@ -1054,8 +1068,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
10541068
debug!("impl_obligations={}", obligations.repr(self.tcx()));
10551069

10561070
// Evaluate those obligations to see if they might possibly hold.
1057-
obligations.iter().all(|o| selcx.evaluate_obligation(o)) &&
1058-
norm_obligations.iter().all(|o| selcx.evaluate_obligation(o))
1071+
obligations.iter()
1072+
.chain(norm_obligations.iter()).chain(ref_obligations.iter())
1073+
.all(|o| selcx.evaluate_obligation(o))
1074+
10591075
}
10601076

10611077
ProjectionCandidate(..) |
@@ -1289,13 +1305,13 @@ impl<'tcx> Candidate<'tcx> {
12891305
Pick {
12901306
item: self.item.clone(),
12911307
kind: match self.kind {
1292-
InherentImplCandidate(def_id, _) => {
1308+
InherentImplCandidate(def_id, _, _) => {
12931309
InherentImplPick(def_id)
12941310
}
12951311
ObjectCandidate(def_id, item_num, real_index) => {
12961312
ObjectPick(def_id, item_num, real_index)
12971313
}
1298-
ExtensionImplCandidate(def_id, _, _, index) => {
1314+
ExtensionImplCandidate(def_id, _, _, index, _) => {
12991315
ExtensionImplPick(def_id, index)
13001316
}
13011317
ClosureCandidate(trait_def_id, index) => {
@@ -1323,9 +1339,9 @@ impl<'tcx> Candidate<'tcx> {
13231339

13241340
fn to_source(&self) -> CandidateSource {
13251341
match self.kind {
1326-
InherentImplCandidate(def_id, _) => ImplSource(def_id),
1342+
InherentImplCandidate(def_id, _, _) => ImplSource(def_id),
13271343
ObjectCandidate(def_id, _, _) => TraitSource(def_id),
1328-
ExtensionImplCandidate(def_id, _, _, _) => ImplSource(def_id),
1344+
ExtensionImplCandidate(def_id, _, _, _, _) => ImplSource(def_id),
13291345
ClosureCandidate(trait_def_id, _) => TraitSource(trait_def_id),
13301346
WhereClauseCandidate(ref trait_ref, _) => TraitSource(trait_ref.def_id()),
13311347
ProjectionCandidate(trait_def_id, _) => TraitSource(trait_def_id),
@@ -1343,7 +1359,7 @@ impl<'tcx> Candidate<'tcx> {
13431359
ClosureCandidate(trait_def_id, item_num) => {
13441360
Some((trait_def_id, item_num))
13451361
}
1346-
ExtensionImplCandidate(_, ref trait_ref, _, item_num) => {
1362+
ExtensionImplCandidate(_, ref trait_ref, _, item_num, _) => {
13471363
Some((trait_ref.def_id, item_num))
13481364
}
13491365
WhereClauseCandidate(ref trait_ref, item_num) => {
@@ -1367,13 +1383,14 @@ impl<'tcx> Repr<'tcx> for Candidate<'tcx> {
13671383
impl<'tcx> Repr<'tcx> for CandidateKind<'tcx> {
13681384
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
13691385
match *self {
1370-
InherentImplCandidate(ref a, ref b) =>
1371-
format!("InherentImplCandidate({},{})", a.repr(tcx), b.repr(tcx)),
1386+
InherentImplCandidate(ref a, ref b, ref c) =>
1387+
format!("InherentImplCandidate({},{},{})", a.repr(tcx), b.repr(tcx),
1388+
c.repr(tcx)),
13721389
ObjectCandidate(a, b, c) =>
13731390
format!("ObjectCandidate({},{},{})", a.repr(tcx), b, c),
1374-
ExtensionImplCandidate(ref a, ref b, ref c, ref d) =>
1375-
format!("ExtensionImplCandidate({},{},{},{})", a.repr(tcx), b.repr(tcx),
1376-
c.repr(tcx), d),
1391+
ExtensionImplCandidate(ref a, ref b, ref c, ref d, ref e) =>
1392+
format!("ExtensionImplCandidate({},{},{},{},{})", a.repr(tcx), b.repr(tcx),
1393+
c.repr(tcx), d, e.repr(tcx)),
13771394
ClosureCandidate(ref a, ref b) =>
13781395
format!("ClosureCandidate({},{})", a.repr(tcx), b),
13791396
WhereClauseCandidate(ref a, ref b) =>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that methods whose impl-trait-ref contains associated types
12+
// are supported.
13+
14+
trait Device {
15+
type Resources;
16+
}
17+
struct Foo<D, R>(D, R);
18+
19+
trait Tr {
20+
fn present(&self) {}
21+
}
22+
23+
impl<D: Device> Tr for Foo<D, D::Resources> {
24+
fn present(&self) {}
25+
}
26+
27+
struct Res;
28+
struct Dev;
29+
impl Device for Dev {
30+
type Resources = Res;
31+
}
32+
33+
fn main() {
34+
let foo = Foo(Dev, Res);
35+
foo.present();
36+
}

src/test/run-pass/issue-25679.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ trait Device {
1313
}
1414
struct Foo<D, R>(D, R);
1515

16-
impl<D: Device, S> Foo<D, S> {
16+
impl<D: Device> Foo<D, D::Resources> {
1717
fn present(&self) {}
1818
}
1919

0 commit comments

Comments
 (0)