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:
Niko Matsakis 2014-10-17 09:13:12 -04:00
parent e09fc03701
commit 450263de4a
8 changed files with 204 additions and 13 deletions

View 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() { }

View File

@ -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() { }

View File

@ -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

View File

@ -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() {}

View File

@ -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
}

View 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() { }

View File

@ -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);
}

View 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);
}