Be less eager about implicit borrowing when doing method resolution. Closes #2796.
This commit is contained in:
parent
ceac155211
commit
038f925586
@ -77,16 +77,20 @@ class lookup {
|
||||
// loop for impls in scope. Note: I don't love these
|
||||
// semantics, but that's what we had so I am preserving
|
||||
// it.
|
||||
if self.candidates.len() > 0u {
|
||||
break;
|
||||
}
|
||||
if self.candidates.len() > 0u { break; }
|
||||
|
||||
self.add_candidates_from_scope();
|
||||
// now look for impls in scope, but don't look for impls that
|
||||
// would require doing an implicit borrow of the lhs.
|
||||
self.add_candidates_from_scope(false);
|
||||
|
||||
// if we found anything, stop before trying borrows
|
||||
if self.candidates.len() > 0u { break; }
|
||||
|
||||
// now look for impls in scope that might require a borrow
|
||||
self.add_candidates_from_scope(true);
|
||||
|
||||
// if we found anything, stop before attempting auto-deref.
|
||||
if self.candidates.len() > 0u {
|
||||
break;
|
||||
}
|
||||
if self.candidates.len() > 0u { break; }
|
||||
|
||||
// check whether we can autoderef and if so loop around again.
|
||||
alt ty::deref(self.tcx(), self.self_ty, false) {
|
||||
@ -290,7 +294,7 @@ class lookup {
|
||||
*/
|
||||
}
|
||||
|
||||
fn add_candidates_from_scope() {
|
||||
fn add_candidates_from_scope(use_assignability: bool) {
|
||||
let impls_vecs = self.fcx.ccx.impl_map.get(self.expr.id);
|
||||
let mut added_any = false;
|
||||
|
||||
@ -306,13 +310,18 @@ class lookup {
|
||||
let {substs: impl_substs, ty: impl_ty} =
|
||||
impl_self_ty(self.fcx, im.did);
|
||||
|
||||
// if we can assign the caller to the callee, that's a
|
||||
// potential match. Collect those in the vector.
|
||||
let can_assign = self.fcx.can_mk_assignty(
|
||||
self.self_expr, self.borrow_scope,
|
||||
self.self_ty, impl_ty);
|
||||
#debug["can_assign = %?", can_assign];
|
||||
alt can_assign {
|
||||
// Depending on our argument, we find potential
|
||||
// matches either by checking subtypability or
|
||||
// type assignability. Collect the matches.
|
||||
let matches = if use_assignability {
|
||||
self.fcx.can_mk_assignty(
|
||||
self.self_expr, self.borrow_scope,
|
||||
self.self_ty, impl_ty)
|
||||
} else {
|
||||
self.fcx.can_mk_subty(self.self_ty, impl_ty)
|
||||
};
|
||||
#debug["matches = %?", matches];
|
||||
alt matches {
|
||||
result::err(_) { /* keep looking */ }
|
||||
result::ok(_) {
|
||||
if !self.candidate_impls.contains_key(im.did) {
|
||||
|
43
src/test/run-pass/assignability-iface.rs
Normal file
43
src/test/run-pass/assignability-iface.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Tests that type assignability is used to search for instances when
|
||||
// making method calls, but only if there aren't any matches without
|
||||
// it.
|
||||
|
||||
iface iterable<A> {
|
||||
fn iterate(blk: fn(A) -> bool);
|
||||
}
|
||||
|
||||
impl vec/&<A> of iterable<A> for &[const A] {
|
||||
fn iterate(f: fn(A) -> bool) {
|
||||
vec::each(self, f);
|
||||
}
|
||||
}
|
||||
|
||||
impl vec<A> of iterable<A> for ~[const A] {
|
||||
fn iterate(f: fn(A) -> bool) {
|
||||
vec::each(self, f);
|
||||
}
|
||||
}
|
||||
|
||||
fn length<A, T: iterable<A>>(x: T) -> uint {
|
||||
let mut len = 0;
|
||||
for x.iterate() |_y| { len += 1 }
|
||||
ret len;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = ~[0,1,2,3];
|
||||
// Call a method
|
||||
for x.iterate() |y| { assert x[y] == y; }
|
||||
// Call a parameterized function
|
||||
assert length(x) == vec::len(x);
|
||||
// Call a parameterized function, with type arguments that require
|
||||
// a borrow
|
||||
assert length::<int, &[int]>(x) == vec::len(x);
|
||||
|
||||
// Now try it with a type that *needs* to be borrowed
|
||||
let z = [0,1,2,3]/_;
|
||||
// Call a method
|
||||
for z.iterate() |y| { assert z[y] == y; }
|
||||
// Call a parameterized function
|
||||
assert length::<int, &[int]>(z) == vec::len(z);
|
||||
}
|
Loading…
Reference in New Issue
Block a user