diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2014-10-17 09:13:12 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2014-10-21 12:32:36 -0400 |
| commit | 450263de4a93e7dd4eb863c8f4b98fc780b9c385 (patch) | |
| tree | d745e5466c3a1cf890a8213ff5160e14abcc591f | |
| parent | e09fc0370188eff0bd3e6f27f72ba4de0d1a6c24 (diff) | |
| download | rust-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.rs | 44 | ||||
| -rw-r--r-- | src/test/compile-fail/method-ambig-one-trait-unknown-int-type.rs | 45 | ||||
| -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.rs | 33 | ||||
| -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.rs | 48 |
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); +} |
