Skip to content

Commit

Permalink
Tests for method resolution in the face of various ambiguities or non…
Browse files Browse the repository at this point in the history
…-ambiguities. These

are mostly new tests though I also revamped (and renamed) some of the existing tests.
  • Loading branch information
nikomatsakis committed Oct 21, 2014
1 parent e09fc03 commit 450263d
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 13 deletions.
44 changes: 44 additions & 0 deletions 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() { }
45 changes: 45 additions & 0 deletions 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() { }
Expand Up @@ -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

Expand Up @@ -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() {}
Expand Up @@ -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 changes: 33 additions & 0 deletions 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() { }
Expand Up @@ -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 changes: 48 additions & 0 deletions 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);
}

0 comments on commit 450263d

Please sign in to comment.