mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-25 13:24:22 +00:00
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.
This commit is contained in:
parent
e09fc03701
commit
450263de4a
44
src/test/compile-fail/method-ambig-one-trait-coerce.rs
Normal file
44
src/test/compile-fail/method-ambig-one-trait-coerce.rs
Normal file
@ -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() { }
|
@ -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() { }
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
}
|
33
src/test/compile-fail/method-commit-to-trait.rs
Normal file
33
src/test/compile-fail/method-commit-to-trait.rs
Normal file
@ -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() { }
|
@ -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);
|
||||
}
|
48
src/test/run-pass/method-two-trait-defer-resolution-2.rs
Normal file
48
src/test/run-pass/method-two-trait-defer-resolution-2.rs
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user