Skip to content

Commit 450263d

Browse files
committed
Tests for method resolution in the face of various ambiguities or non-ambiguities. These
are mostly new tests though I also revamped (and renamed) some of the existing tests.
1 parent e09fc03 commit 450263d

8 files changed

+204
-13
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2012 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 when we pick a trait based on coercion, versus subtyping,
12+
// we consider all possible coercions equivalent and don't try to pick
13+
// a best one.
14+
15+
trait Object { }
16+
17+
trait foo {
18+
fn foo(self) -> int;
19+
}
20+
21+
impl foo for Box<Object+'static> {
22+
fn foo(self) -> int {1}
23+
}
24+
25+
impl foo for Box<Object+Send> {
26+
fn foo(self) -> int {2}
27+
}
28+
29+
fn test1(x: Box<Object+Send+Sync>) {
30+
// Ambiguous because we could coerce to either impl:
31+
x.foo(); //~ ERROR E0034
32+
}
33+
34+
fn test2(x: Box<Object+Send>) {
35+
// Not ambiguous because it is a precise match:
36+
x.foo();
37+
}
38+
39+
fn test3(x: Box<Object+'static>) {
40+
// Not ambiguous because it is a precise match:
41+
x.foo();
42+
}
43+
44+
fn main() { }
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2012 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 we invoking `foo()` successfully resolves to the trait `foo`
12+
// (prompting the mismatched types error) but does not influence the choice
13+
// of what kind of `Vec` we have, eventually leading to a type error.
14+
15+
trait foo {
16+
fn foo(&self) -> int;
17+
}
18+
19+
impl foo for Vec<uint> {
20+
fn foo(&self) -> int {1}
21+
}
22+
23+
impl foo for Vec<int> {
24+
fn foo(&self) -> int {2}
25+
}
26+
27+
// This is very hokey: we have heuristics to suppress messages about
28+
// type annotations required. But placing these two bits of code into
29+
// distinct functions, in this order, causes us to print out both
30+
// errors I'd like to see.
31+
32+
fn m1() {
33+
// we couldn't infer the type of the vector just based on calling foo()...
34+
let mut x = Vec::new(); //~ ERROR type annotations required
35+
x.foo();
36+
}
37+
38+
fn m2() {
39+
let mut x = Vec::new();
40+
41+
// ...but we still resolved `foo()` to the trait and hence know the return type.
42+
let y: uint = x.foo(); //~ ERROR mismatched types
43+
}
44+
45+
fn main() { }

src/test/compile-fail/ambig_impl_2_exe.rs renamed to src/test/compile-fail/method-ambig-two-traits-cross-crate.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Test an ambiguity scenario where one copy of the method is available
12+
// from a trait imported from another crate.
13+
1114
// aux-build:ambig_impl_2_lib.rs
1215
extern crate ambig_impl_2_lib;
1316
use ambig_impl_2_lib::me;
1417
trait me2 {
1518
fn me(&self) -> uint;
1619
}
17-
impl me2 for uint { fn me(&self) -> uint { *self } } //~ NOTE is `uint.me2::me`
18-
fn main() { 1u.me(); } //~ ERROR multiple applicable methods in scope
19-
//~^ NOTE is `ambig_impl_2_lib::uint.me::me`
20+
impl me2 for uint { fn me(&self) -> uint { *self } }
21+
fn main() { 1u.me(); } //~ ERROR E0034
22+

src/test/compile-fail/ambig_impl_bounds.rs renamed to src/test/compile-fail/method-ambig-two-traits-from-bounds.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ trait A { fn foo(&self); }
1212
trait B { fn foo(&self); }
1313

1414
fn foo<T:A + B>(t: T) {
15-
t.foo(); //~ ERROR multiple applicable methods in scope
16-
//~^ NOTE candidate #1 derives from the bound `A`
17-
//~^^ NOTE candidate #2 derives from the bound `B`
15+
t.foo(); //~ ERROR E0034
1816
}
1917

2018
fn main() {}

src/test/compile-fail/ambig-default-method.rs renamed to src/test/compile-fail/method-ambig-two-traits-with-default-method.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
trait Foo { fn method(&self) {} } //~ NOTE `Foo::method`
12-
trait Bar { fn method(&self) {} } //~ NOTE `Bar::method`
11+
// Test that we correctly report an ambiguity where two applicable traits
12+
// are in scope and the method being invoked is a default method not
13+
// defined directly in the impl.
14+
15+
trait Foo { fn method(&self) {} }
16+
trait Bar { fn method(&self) {} }
1317

1418
impl Foo for uint {}
1519
impl Bar for uint {}
1620

1721
fn main() {
18-
1u.method(); //~ ERROR multiple applicable methods in scope
22+
1u.method(); //~ ERROR E0034
1923
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2012 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 we pick `Foo`, and also pick the `impl`, even though in
12+
// this case the vector type `T` is not copyable. This is because
13+
// there is no other reasonable choice. The error you see is thus
14+
// about `T` being non-copyable, not about `Foo` being
15+
// unimplemented. This is better for user too, since it suggests minimal
16+
// diff requird to fix program.
17+
18+
trait Object { }
19+
20+
trait Foo {
21+
fn foo(self) -> int;
22+
}
23+
24+
impl<T:Copy> Foo for Vec<T> {
25+
fn foo(self) -> int {1}
26+
}
27+
28+
fn test1<T>(x: Vec<T>) {
29+
x.foo();
30+
//~^ ERROR `core::kinds::Copy` is not implemented for the type `T`
31+
}
32+
33+
fn main() { }

src/test/compile-fail/ambig_impl_unify.rs renamed to src/test/run-pass/method-two-trait-defer-resolution-1.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,36 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Test that we pick which version of `foo` to run based on the
12+
// type that is (ultimately) inferred for `x`.
1113

1214
trait foo {
1315
fn foo(&self) -> int;
1416
}
1517

1618
impl foo for Vec<uint> {
17-
fn foo(&self) -> int {1} //~ NOTE candidate #1 is `Vec<uint>.foo::foo`
19+
fn foo(&self) -> int {1}
1820
}
1921

2022
impl foo for Vec<int> {
21-
fn foo(&self) -> int {2} //~ NOTE candidate #2 is `Vec<int>.foo::foo`
23+
fn foo(&self) -> int {2}
24+
}
25+
26+
fn call_foo_uint() -> int {
27+
let mut x = Vec::new();
28+
let y = x.foo();
29+
x.push(0u);
30+
y
31+
}
32+
33+
fn call_foo_int() -> int {
34+
let mut x = Vec::new();
35+
let y = x.foo();
36+
x.push(0i);
37+
y
2238
}
2339

2440
fn main() {
25-
let x = Vec::new();
26-
x.foo(); //~ ERROR multiple applicable methods in scope
41+
assert_eq!(call_foo_uint(), 1);
42+
assert_eq!(call_foo_int(), 2);
2743
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2012 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 we pick which version of `Foo` to run based on whether
12+
// the type we (ultimately) inferred for `x` is copyable or not.
13+
//
14+
// In this case, the two versions are both impls of same trait, and
15+
// hence we we can resolve method even without knowing yet which
16+
// version will run (note that the `push` occurs after the call to
17+
// `foo()`).
18+
19+
trait Foo {
20+
fn foo(&self) -> int;
21+
}
22+
23+
impl<T:Copy> Foo for Vec<T> {
24+
fn foo(&self) -> int {1}
25+
}
26+
27+
impl<T> Foo for Vec<Box<T>> {
28+
fn foo(&self) -> int {2}
29+
}
30+
31+
fn call_foo_copy() -> int {
32+
let mut x = Vec::new();
33+
let y = x.foo();
34+
x.push(0u);
35+
y
36+
}
37+
38+
fn call_foo_other() -> int {
39+
let mut x = Vec::new();
40+
let y = x.foo();
41+
x.push(box 0i);
42+
y
43+
}
44+
45+
fn main() {
46+
assert_eq!(call_foo_copy(), 1);
47+
assert_eq!(call_foo_other(), 2);
48+
}

0 commit comments

Comments
 (0)