parent
93633ea734
commit
98740a59da
@ -527,6 +527,10 @@ impl methods for @fn_ctxt {
|
||||
infer::mk_subty(self.infcx, sub, sup)
|
||||
}
|
||||
|
||||
fn can_mk_subty(sub: ty::t, sup: ty::t) -> result<(), ty::type_err> {
|
||||
infer::can_mk_subty(self.infcx, sub, sup)
|
||||
}
|
||||
|
||||
fn mk_eqty(sub: ty::t, sup: ty::t) -> result<(), ty::type_err> {
|
||||
infer::mk_eqty(self.infcx, sub, sup)
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ impl methods for lookup {
|
||||
let tcx = self.tcx();
|
||||
let mut iface_bnd_idx = 0u; // count only iface bounds
|
||||
let bounds = tcx.ty_param_bounds.get(did.node);
|
||||
let mut candidates = [];
|
||||
for vec::each(*bounds) {|bound|
|
||||
let (iid, bound_substs) = alt bound {
|
||||
ty::bound_copy | ty::bound_send | ty::bound_const {
|
||||
@ -74,14 +75,33 @@ impl methods for lookup {
|
||||
// permitted).
|
||||
let substs = {self_ty: some(self.self_ty)
|
||||
with bound_substs};
|
||||
|
||||
ret some(self.write_mty_from_m(
|
||||
substs, ifce_methods[pos],
|
||||
method_param(iid, pos, n, iface_bnd_idx)));
|
||||
candidates += [(substs, ifce_methods[pos],
|
||||
iid, pos, n, iface_bnd_idx)];
|
||||
}
|
||||
}
|
||||
}
|
||||
ret none;
|
||||
|
||||
if candidates.len() == 0u {
|
||||
ret none;
|
||||
}
|
||||
|
||||
if candidates.len() > 1u {
|
||||
self.tcx().sess.span_err(
|
||||
self.expr.span,
|
||||
"multiple applicable methods in scope");
|
||||
|
||||
for candidates.eachi { |i, candidate|
|
||||
let (_, _, iid, _, _, _) = candidate;
|
||||
self.tcx().sess.span_note(
|
||||
self.expr.span,
|
||||
#fmt["candidate #%u derives from the bound `%s`",
|
||||
(i+1u), ty::item_path_str(self.tcx(), iid)]);
|
||||
}
|
||||
}
|
||||
|
||||
let (substs, mty, iid, pos, n, iface_bnd_idx) = candidates[0u];
|
||||
ret some(self.write_mty_from_m(
|
||||
substs, mty, method_param(iid, pos, n, iface_bnd_idx)));
|
||||
}
|
||||
|
||||
fn method_from_iface(
|
||||
@ -197,10 +217,11 @@ impl methods for lookup {
|
||||
|
||||
// if we can assign the caller to the callee, that's a
|
||||
// potential match. Collect those in the vector.
|
||||
alt self.fcx.mk_subty(ty, self_ty) {
|
||||
alt self.fcx.can_mk_subty(ty, self_ty) {
|
||||
result::err(_) { /* keep looking */ }
|
||||
result::ok(_) {
|
||||
results += [(self_substs, m.n_tps, m.did)];
|
||||
results += [(ty, self_ty, self_substs,
|
||||
m.n_tps, m.did)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,7 +237,7 @@ impl methods for lookup {
|
||||
// but I cannot for the life of me figure out how to
|
||||
// annotate resolve to preserve this information.
|
||||
for results.eachi { |i, result|
|
||||
let (_, _, did) = result;
|
||||
let (_, _, _, _, did) = result;
|
||||
let span = if did.crate == ast::local_crate {
|
||||
alt check self.tcx().items.get(did.node) {
|
||||
ast_map::node_method(m, _, _) { m.span }
|
||||
@ -226,13 +247,21 @@ impl methods for lookup {
|
||||
};
|
||||
self.tcx().sess.span_note(
|
||||
span,
|
||||
#fmt["candidate #%u is %s",
|
||||
#fmt["candidate #%u is `%s`",
|
||||
(i+1u),
|
||||
ty::item_path_str(self.tcx(), did)]);
|
||||
}
|
||||
}
|
||||
|
||||
let (self_substs, n_tps, did) = results[0];
|
||||
let (ty, self_ty, self_substs, n_tps, did) = results[0];
|
||||
alt self.fcx.mk_subty(ty, self_ty) {
|
||||
result::ok(_) {}
|
||||
result::err(_) {
|
||||
self.tcx().sess.span_bug(
|
||||
self.expr.span,
|
||||
"what was a subtype now is not?");
|
||||
}
|
||||
}
|
||||
let fty = self.ty_from_did(did);
|
||||
ret some(self.write_mty_from_fty(
|
||||
self_substs, n_tps, fty,
|
||||
|
@ -160,7 +160,7 @@ import util::common::{indent, indenter};
|
||||
|
||||
export infer_ctxt;
|
||||
export new_infer_ctxt;
|
||||
export mk_subty;
|
||||
export mk_subty, can_mk_subty;
|
||||
export mk_subr;
|
||||
export mk_eqty;
|
||||
export mk_assignty;
|
||||
@ -235,6 +235,11 @@ fn mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
|
||||
indent {|| cx.commit {|| sub(cx).tys(a, b) } }.to_ures()
|
||||
}
|
||||
|
||||
fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
|
||||
#debug["can_mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)];
|
||||
indent {|| cx.probe {|| sub(cx).tys(a, b) } }.to_ures()
|
||||
}
|
||||
|
||||
fn mk_subr(cx: infer_ctxt, a: ty::region, b: ty::region) -> ures {
|
||||
#debug["mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx)];
|
||||
indent {|| cx.commit {|| sub(cx).regions(a, b) } }.to_ures()
|
||||
@ -388,7 +393,17 @@ fn uok() -> ures {
|
||||
ok(())
|
||||
}
|
||||
|
||||
fn rollback_to<V:copy vid, T:copy>(
|
||||
vb: vals_and_bindings<V, T>, len: uint) {
|
||||
|
||||
while vb.bindings.len() != len {
|
||||
let (vid, old_v) = vec::pop(vb.bindings);
|
||||
vb.vals.insert(vid.to_uint(), old_v);
|
||||
}
|
||||
}
|
||||
|
||||
impl transaction_methods for infer_ctxt {
|
||||
#[doc = "Execute `f` and commit the bindings if successful"]
|
||||
fn commit<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
|
||||
|
||||
assert self.vb.bindings.len() == 0u;
|
||||
@ -404,17 +419,9 @@ impl transaction_methods for infer_ctxt {
|
||||
ret r;
|
||||
}
|
||||
|
||||
#[doc = "Execute `f`, unroll bindings on failure"]
|
||||
fn try<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
|
||||
|
||||
fn rollback_to<V:copy vid, T:copy>(
|
||||
vb: vals_and_bindings<V, T>, len: uint) {
|
||||
|
||||
while vb.bindings.len() != len {
|
||||
let (vid, old_v) = vec::pop(vb.bindings);
|
||||
vb.vals.insert(vid.to_uint(), old_v);
|
||||
}
|
||||
}
|
||||
|
||||
let vbl = self.vb.bindings.len();
|
||||
let rbl = self.rb.bindings.len();
|
||||
#debug["try(vbl=%u, rbl=%u)", vbl, rbl];
|
||||
@ -429,6 +436,16 @@ impl transaction_methods for infer_ctxt {
|
||||
}
|
||||
ret r;
|
||||
}
|
||||
|
||||
#[doc = "Execute `f` then unroll any bindings it creates"]
|
||||
fn probe<T,E>(f: fn() -> result<T,E>) -> result<T,E> {
|
||||
assert self.vb.bindings.len() == 0u;
|
||||
assert self.rb.bindings.len() == 0u;
|
||||
let r <- f();
|
||||
rollback_to(self.vb, 0u);
|
||||
rollback_to(self.rb, 0u);
|
||||
ret r;
|
||||
}
|
||||
}
|
||||
|
||||
impl methods for infer_ctxt {
|
||||
|
@ -1,3 +1,3 @@
|
||||
impl methods1 for uint { fn me() -> uint { self } } //! NOTE candidate #1 is methods1::me
|
||||
impl methods2 for uint { fn me() -> uint { self } } //! NOTE candidate #2 is methods2::me
|
||||
impl methods1 for uint { fn me() -> uint { self } } //! NOTE candidate #1 is `methods1::me`
|
||||
impl methods2 for uint { fn me() -> uint { self } } //! NOTE candidate #2 is `methods2::me`
|
||||
fn main() { 1u.me(); } //! ERROR multiple applicable methods in scope
|
||||
|
@ -2,6 +2,6 @@
|
||||
// aux-build:ambig_impl_2_lib.rs
|
||||
use ambig_impl_2_lib;
|
||||
import ambig_impl_2_lib::methods1;
|
||||
impl methods2 for uint { fn me() -> uint { self } } //! NOTE candidate #2 is methods2::me
|
||||
impl methods2 for uint { fn me() -> uint { self } } //! NOTE candidate #2 is `methods2::me`
|
||||
fn main() { 1u.me(); } //! ERROR multiple applicable methods in scope
|
||||
//!^ NOTE candidate #1 is ambig_impl_2_lib::methods1::me
|
||||
//!^ NOTE candidate #1 is `ambig_impl_2_lib::methods1::me`
|
||||
|
10
src/test/compile-fail/ambig_impl_bounds.rs
Normal file
10
src/test/compile-fail/ambig_impl_bounds.rs
Normal file
@ -0,0 +1,10 @@
|
||||
iface A { fn foo(); }
|
||||
iface B { fn foo(); }
|
||||
|
||||
fn foo<T: A B>(t: T) {
|
||||
t.foo(); //! ERROR multiple applicable methods in scope
|
||||
//!^ NOTE candidate #1 derives from the bound `A`
|
||||
//!^^ NOTE candidate #2 derives from the bound `B`
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/compile-fail/ambig_impl_unify.rs
Normal file
12
src/test/compile-fail/ambig_impl_unify.rs
Normal file
@ -0,0 +1,12 @@
|
||||
impl methods for [uint] {
|
||||
fn foo() -> int {1} //! NOTE candidate #1 is `methods::foo`
|
||||
}
|
||||
|
||||
impl methods for [int] {
|
||||
fn foo() -> int {2} //! NOTE candidate #2 is `methods::foo`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = [];
|
||||
x.foo(); //! ERROR multiple applicable methods in scope
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user