Skip to content

Commit cab7a45

Browse files
committed
1 parent c6515ee commit cab7a45

File tree

3 files changed

+82
-23
lines changed

3 files changed

+82
-23
lines changed

src/librustc/middle/typeck/check/method.rs

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl<'self> LookupContext<'self> {
192192

193193
// Prepare the list of candidates
194194
self.push_inherent_candidates(self_ty);
195-
self.push_extension_candidates();
195+
self.push_extension_candidates(self_ty);
196196

197197
let mut enum_dids = ~[];
198198
let mut self_ty = self_ty;
@@ -295,7 +295,7 @@ impl<'self> LookupContext<'self> {
295295
ty_trait(did, ref substs, store, _, _) => {
296296
self.push_inherent_candidates_from_trait(
297297
self_ty, did, substs, store);
298-
self.push_inherent_impl_candidates_for_type(did);
298+
self.push_inherent_impl_candidates_for_type(self_ty, did);
299299
}
300300
ty_self(self_did) => {
301301
// Call is of the form "self.foo()" and appears in one
@@ -310,7 +310,8 @@ impl<'self> LookupContext<'self> {
310310
}
311311
ty_enum(did, _) | ty_struct(did, _) => {
312312
if self.check_traits == CheckTraitsAndInherentMethods {
313-
self.push_inherent_impl_candidates_for_type(did);
313+
self.push_inherent_impl_candidates_for_type(self_ty,
314+
did);
314315
}
315316
}
316317
_ => { /* No inherent methods in these types */ }
@@ -326,7 +327,7 @@ impl<'self> LookupContext<'self> {
326327
}
327328
}
328329

329-
pub fn push_extension_candidates(&self) {
330+
pub fn push_extension_candidates(&self, self_ty: ty::t) {
330331
// If the method being called is associated with a trait, then
331332
// find all the impls of that trait. Each of those are
332333
// candidates.
@@ -342,7 +343,7 @@ impl<'self> LookupContext<'self> {
342343
for opt_impl_infos.iter().advance |impl_infos| {
343344
for impl_infos.iter().advance |impl_info| {
344345
self.push_candidates_from_impl(
345-
self.extension_candidates, *impl_info);
346+
self_ty, self.extension_candidates, *impl_info);
346347

347348
}
348349
}
@@ -523,18 +524,21 @@ impl<'self> LookupContext<'self> {
523524
}
524525
}
525526

526-
pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
527+
pub fn push_inherent_impl_candidates_for_type(&self,
528+
self_ty: ty::t,
529+
did: def_id) {
527530
let opt_impl_infos =
528531
self.fcx.ccx.coherence_info.inherent_methods.find(&did);
529532
for opt_impl_infos.iter().advance |impl_infos| {
530533
for impl_infos.iter().advance |impl_info| {
531534
self.push_candidates_from_impl(
532-
self.inherent_candidates, *impl_info);
535+
self_ty, self.inherent_candidates, *impl_info);
533536
}
534537
}
535538
}
536539

537540
pub fn push_candidates_from_impl(&self,
541+
self_ty: ty::t,
538542
candidates: &mut ~[Candidate],
539543
impl_info: &resolve::Impl) {
540544
if !self.impl_dups.insert(impl_info.did) {
@@ -561,17 +565,25 @@ impl<'self> LookupContext<'self> {
561565
ccx: self.fcx.ccx,
562566
infcx: self.fcx.infcx()
563567
};
564-
let ty::ty_param_substs_and_ty {
565-
substs: impl_substs,
566-
ty: impl_ty
567-
} = impl_self_ty(&vcx, location_info, impl_info.did);
568-
569-
candidates.push(Candidate {
570-
rcvr_ty: impl_ty,
571-
rcvr_substs: impl_substs,
572-
method_ty: method,
573-
origin: method_static(method.def_id)
574-
});
568+
match impl_self_ty(&vcx, location_info, impl_info.did, Some(self_ty)) {
569+
Some(ty::ty_param_substs_and_ty {
570+
substs: impl_substs,
571+
ty: impl_ty
572+
}) => {
573+
candidates.push(Candidate {
574+
rcvr_ty: impl_ty,
575+
rcvr_substs: impl_substs,
576+
method_ty: method,
577+
origin: method_static(method.def_id)
578+
});
579+
},
580+
None => {
581+
debug!("push_candidates_from_impl match failed: %s %s %s",
582+
self.m_name.repr(self.tcx()),
583+
impl_info.ident.repr(self.tcx()),
584+
impl_info.methods.map(|m| m.ident).repr(self.tcx()));
585+
}
586+
}
575587
}
576588

577589
// ______________________________________________________________________

src/librustc/middle/typeck/check/mod.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,12 +1077,13 @@ pub fn check_expr(fcx: @mut FnCtxt, expr: @ast::expr) {
10771077
pub fn impl_self_ty(vcx: &VtableContext,
10781078
location_info: &LocationInfo, // (potential) receiver for
10791079
// this impl
1080-
did: ast::def_id)
1081-
-> ty_param_substs_and_ty {
1080+
did: ast::def_id,
1081+
self_ty: Option<ty::t>)
1082+
-> Option<ty_param_substs_and_ty> {
10821083
let tcx = vcx.tcx();
1084+
let ity = ty::lookup_item_type(tcx, did);
10831085

10841086
let (n_tps, region_param, raw_ty) = {
1085-
let ity = ty::lookup_item_type(tcx, did);
10861087
(ity.generics.type_param_defs.len(), ity.generics.region_param, ity.ty)
10871088
};
10881089

@@ -1096,7 +1097,52 @@ pub fn impl_self_ty(vcx: &VtableContext,
10961097
let substs = substs { self_r: self_r, self_ty: None, tps: tps };
10971098
let substd_ty = ty::subst(tcx, &substs, raw_ty);
10981099

1099-
ty_param_substs_and_ty { substs: substs, ty: substd_ty }
1100+
match substs.tps.iter().position_(|&ty| ty == substd_ty) {
1101+
// Check trait bounds on self
1102+
Some(i) => match self_ty {
1103+
Some(self_ty) => {
1104+
for ity.generics.type_param_defs[i].bounds
1105+
.trait_bounds.iter().advance |&trait_ref| {
1106+
// Search for traits implementations in scope
1107+
match vcx.ccx.coherence_info.extension_methods
1108+
.find(&trait_ref.def_id) {
1109+
Some(implementations) => {
1110+
let mut found = false;
1111+
for implementations.iter().advance |im| {
1112+
let ty::ty_param_substs_and_ty {
1113+
substs: substs,
1114+
ty: for_ty
1115+
} = impl_self_ty(vcx,
1116+
location_info,
1117+
im.did,
1118+
None)
1119+
.expect("Implementation");
1120+
match infer::mk_subty(vcx.infcx,
1121+
false,
1122+
location_info.span,
1123+
self_ty,
1124+
for_ty) {
1125+
result::Ok(()) => { found = true; break; },
1126+
result::Err(_) => ()
1127+
}
1128+
}
1129+
if !found { return None; }
1130+
},
1131+
1132+
// No implementations - no chance this impl could be
1133+
// applied.
1134+
None => { return None; }
1135+
}
1136+
}
1137+
},
1138+
None => ()
1139+
},
1140+
1141+
// No trait bounds on self
1142+
None => ()
1143+
}
1144+
1145+
Some(ty_param_substs_and_ty { substs: substs, ty: substd_ty })
11001146
}
11011147

11021148
// Only for fields! Returns <none> for methods>

src/librustc/middle/typeck/check/vtable.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,8 @@ fn lookup_vtable(vcx: &VtableContext,
289289
let ty::ty_param_substs_and_ty {
290290
substs: substs,
291291
ty: for_ty
292-
} = impl_self_ty(vcx, location_info, im.did);
292+
} = impl_self_ty(vcx, location_info, im.did, None)
293+
.expect("Implementation");
293294
match infer::mk_subty(vcx.infcx,
294295
false,
295296
location_info.span,

0 commit comments

Comments
 (0)