about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-10-17 09:13:12 -0400
committerNiko Matsakis <niko@alum.mit.edu>2014-10-21 12:32:36 -0400
commit450263de4a93e7dd4eb863c8f4b98fc780b9c385 (patch)
treed745e5466c3a1cf890a8213ff5160e14abcc591f
parente09fc0370188eff0bd3e6f27f72ba4de0d1a6c24 (diff)
downloadrust-450263de4a93e7dd4eb863c8f4b98fc780b9c385.tar.gz
rust-450263de4a93e7dd4eb863c8f4b98fc780b9c385.zip
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.
-rw-r--r--src/test/compile-fail/method-ambig-one-trait-coerce.rs44
-rw-r--r--src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs45
-rw-r--r--src/test/compile-fail/method-ambig-two-traits-cross-crate.rs (renamed from src/test/compile-fail/ambig_impl_2_exe.rs)9
-rw-r--r--src/test/compile-fail/method-ambig-two-traits-from-bounds.rs (renamed from src/test/compile-fail/ambig_impl_bounds.rs)4
-rw-r--r--src/test/compile-fail/method-ambig-two-traits-with-default-method.rs (renamed from src/test/compile-fail/ambig-default-method.rs)10
-rw-r--r--src/test/compile-fail/method-commit-to-trait.rs33
-rw-r--r--src/test/run-pass/method-two-trait-defer-resolution-1.rs (renamed from src/test/compile-fail/ambig_impl_unify.rs)24
-rw-r--r--src/test/run-pass/method-two-trait-defer-resolution-2.rs48
8 files changed, 204 insertions, 13 deletions
diff --git a/src/test/compile-fail/method-ambig-one-trait-coerce.rs b/src/test/compile-fail/method-ambig-one-trait-coerce.rs
new file mode 100644
index 00000000000..e5c3da10df8
--- /dev/null
+++ b/src/test/compile-fail/method-ambig-one-trait-coerce.rs
@@ -0,0 +1,44 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that when we pick a trait based on coercion, versus subtyping,
+// we consider all possible coercions equivalent and don't try to pick
+// a best one.
+
+trait Object { }
+
+trait foo {
+    fn foo(self) -> int;
+}
+
+impl foo for Box<Object+'static> {
+    fn foo(self) -> int {1}
+}
+
+impl foo for Box<Object+Send> {
+    fn foo(self) -> int {2}
+}
+
+fn test1(x: Box<Object+Send+Sync>) {
+    // Ambiguous because we could coerce to either impl:
+    x.foo(); //~ ERROR E0034
+}
+
+fn test2(x: Box<Object+Send>) {
+    // Not ambiguous because it is a precise match:
+    x.foo();
+}
+
+fn test3(x: Box<Object+'static>) {
+    // Not ambiguous because it is a precise match:
+    x.foo();
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs b/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs
new file mode 100644
index 00000000000..e211db2dcd2
--- /dev/null
+++ b/src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs
@@ -0,0 +1,45 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we invoking `foo()` successfully resolves to the trait `foo`
+// (prompting the mismatched types error) but does not influence the choice
+// of what kind of `Vec` we have, eventually leading to a type error.
+
+trait foo {
+    fn foo(&self) -> int;
+}
+
+impl foo for Vec<uint> {
+    fn foo(&self) -> int {1}
+}
+
+impl foo for Vec<int> {
+    fn foo(&self) -> int {2}
+}
+
+// This is very hokey: we have heuristics to suppress messages about
+// type annotations required. But placing these two bits of code into
+// distinct functions, in this order, causes us to print out both
+// errors I'd like to see.
+
+fn m1() {
+    // we couldn't infer the type of the vector just based on calling foo()...
+    let mut x = Vec::new(); //~ ERROR type annotations required
+    x.foo();
+}
+
+fn m2() {
+    let mut x = Vec::new();
+
+    // ...but we still resolved `foo()` to the trait and hence know the return type.
+    let y: uint = x.foo(); //~ ERROR mismatched types
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/ambig_impl_2_exe.rs b/src/test/compile-fail/method-ambig-two-traits-cross-crate.rs
index 13cceaa71ae..30e635149c4 100644
--- a/src/test/compile-fail/ambig_impl_2_exe.rs
+++ b/src/test/compile-fail/method-ambig-two-traits-cross-crate.rs
@@ -8,12 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Test an ambiguity scenario where one copy of the method is available
+// from a trait imported from another crate.
+
 // aux-build:ambig_impl_2_lib.rs
 extern crate ambig_impl_2_lib;
 use ambig_impl_2_lib::me;
 trait me2 {
     fn me(&self) -> uint;
 }
-impl me2 for uint { fn me(&self) -> uint { *self } } //~ NOTE is `uint.me2::me`
-fn main() { 1u.me(); } //~ ERROR multiple applicable methods in scope
-//~^ NOTE is `ambig_impl_2_lib::uint.me::me`
+impl me2 for uint { fn me(&self) -> uint { *self } }
+fn main() { 1u.me(); } //~ ERROR E0034
+
diff --git a/src/test/compile-fail/ambig_impl_bounds.rs b/src/test/compile-fail/method-ambig-two-traits-from-bounds.rs
index 9f26e5ae9b3..184927c0135 100644
--- a/src/test/compile-fail/ambig_impl_bounds.rs
+++ b/src/test/compile-fail/method-ambig-two-traits-from-bounds.rs
@@ -12,9 +12,7 @@ trait A { fn foo(&self); }
 trait B { fn foo(&self); }
 
 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`
+    t.foo(); //~ ERROR E0034
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/ambig-default-method.rs b/src/test/compile-fail/method-ambig-two-traits-with-default-method.rs
index 56ab6d7da3f..87efaed4e3d 100644
--- a/src/test/compile-fail/ambig-default-method.rs
+++ b/src/test/compile-fail/method-ambig-two-traits-with-default-method.rs
@@ -8,12 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait Foo { fn method(&self) {} } //~ NOTE `Foo::method`
-trait Bar { fn method(&self) {} } //~ NOTE `Bar::method`
+// Test that we correctly report an ambiguity where two applicable traits
+// are in scope and the method being invoked is a default method not
+// defined directly in the impl.
+
+trait Foo { fn method(&self) {} }
+trait Bar { fn method(&self) {} }
 
 impl Foo for uint {}
 impl Bar for uint {}
 
 fn main() {
-    1u.method(); //~ ERROR multiple applicable methods in scope
+    1u.method(); //~ ERROR E0034
 }
diff --git a/src/test/compile-fail/method-commit-to-trait.rs b/src/test/compile-fail/method-commit-to-trait.rs
new file mode 100644
index 00000000000..6e4b5e088c9
--- /dev/null
+++ b/src/test/compile-fail/method-commit-to-trait.rs
@@ -0,0 +1,33 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we pick `Foo`, and also pick the `impl`, even though in
+// this case the vector type `T` is not copyable. This is because
+// there is no other reasonable choice. The error you see is thus
+// about `T` being non-copyable, not about `Foo` being
+// unimplemented. This is better for user too, since it suggests minimal
+// diff requird to fix program.
+
+trait Object { }
+
+trait Foo {
+    fn foo(self) -> int;
+}
+
+impl<T:Copy> Foo for Vec<T> {
+    fn foo(self) -> int {1}
+}
+
+fn test1<T>(x: Vec<T>) {
+    x.foo();
+    //~^ ERROR `core::kinds::Copy` is not implemented for the type `T`
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/ambig_impl_unify.rs b/src/test/run-pass/method-two-trait-defer-resolution-1.rs
index 67b7a5a7f37..e4ae33c1c50 100644
--- a/src/test/compile-fail/ambig_impl_unify.rs
+++ b/src/test/run-pass/method-two-trait-defer-resolution-1.rs
@@ -8,20 +8,36 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Test that we pick which version of `foo` to run based on the
+// type that is (ultimately) inferred for `x`.
 
 trait foo {
     fn foo(&self) -> int;
 }
 
 impl foo for Vec<uint> {
-    fn foo(&self) -> int {1} //~ NOTE candidate #1 is `Vec<uint>.foo::foo`
+    fn foo(&self) -> int {1}
 }
 
 impl foo for Vec<int> {
-    fn foo(&self) -> int {2} //~ NOTE candidate #2 is `Vec<int>.foo::foo`
+    fn foo(&self) -> int {2}
+}
+
+fn call_foo_uint() -> int {
+    let mut x = Vec::new();
+    let y = x.foo();
+    x.push(0u);
+    y
+}
+
+fn call_foo_int() -> int {
+    let mut x = Vec::new();
+    let y = x.foo();
+    x.push(0i);
+    y
 }
 
 fn main() {
-    let x = Vec::new();
-    x.foo(); //~ ERROR multiple applicable methods in scope
+    assert_eq!(call_foo_uint(), 1);
+    assert_eq!(call_foo_int(), 2);
 }
diff --git a/src/test/run-pass/method-two-trait-defer-resolution-2.rs b/src/test/run-pass/method-two-trait-defer-resolution-2.rs
new file mode 100644
index 00000000000..cae783e7ea8
--- /dev/null
+++ b/src/test/run-pass/method-two-trait-defer-resolution-2.rs
@@ -0,0 +1,48 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we pick which version of `Foo` to run based on whether
+// the type we (ultimately) inferred for `x` is copyable or not.
+//
+// In this case, the two versions are both impls of same trait, and
+// hence we we can resolve method even without knowing yet which
+// version will run (note that the `push` occurs after the call to
+// `foo()`).
+
+trait Foo {
+    fn foo(&self) -> int;
+}
+
+impl<T:Copy> Foo for Vec<T> {
+    fn foo(&self) -> int {1}
+}
+
+impl<T> Foo for Vec<Box<T>> {
+    fn foo(&self) -> int {2}
+}
+
+fn call_foo_copy() -> int {
+    let mut x = Vec::new();
+    let y = x.foo();
+    x.push(0u);
+    y
+}
+
+fn call_foo_other() -> int {
+    let mut x = Vec::new();
+    let y = x.foo();
+    x.push(box 0i);
+    y
+}
+
+fn main() {
+    assert_eq!(call_foo_copy(), 1);
+    assert_eq!(call_foo_other(), 2);
+}