Implement multidispatch and conditional dispatch. Because we do not
attempt to preserve crate concatenation, this is a backwards compatible change. Conflicts: src/librustc/middle/traits/select.rs
This commit is contained in:
parent
79d056f94b
commit
389ef6601d
31 changed files with 1425 additions and 755 deletions
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
use std::fmt::Show;
|
||||
use std::default::Default;
|
||||
|
||||
// Test that a blank impl for all T conflicts with an impl for some
|
||||
// specific T, even when there are multiple type parameters involved.
|
||||
|
||||
trait MyTrait<T> {
|
||||
fn get(&self) -> T;
|
||||
}
|
||||
|
||||
impl<T> MyTrait<T> for T { //~ ERROR E0119
|
||||
fn get(&self) -> T {
|
||||
fail!()
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
struct MyType {
|
||||
dummy: uint
|
||||
}
|
||||
|
||||
impl MyTrait<MyType> for MyType {
|
||||
fn get(&self) -> uint { (*self).clone() }
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2014 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 a blank impl for all T:PartialEq conflicts with an impl for some
|
||||
// specific T when T:PartialEq.
|
||||
|
||||
trait OtherTrait {
|
||||
fn noop(&self);
|
||||
}
|
||||
|
||||
trait MyTrait {
|
||||
fn get(&self) -> uint;
|
||||
}
|
||||
|
||||
impl<T:OtherTrait> MyTrait for T { //~ ERROR E0119
|
||||
fn get(&self) -> uint { 0 }
|
||||
}
|
||||
|
||||
struct MyType {
|
||||
dummy: uint
|
||||
}
|
||||
|
||||
impl MyTrait for MyType {
|
||||
fn get(&self) -> uint { self.dummy }
|
||||
}
|
||||
|
||||
impl OtherTrait for MyType {
|
||||
fn noop(&self) { }
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
use std::fmt::Show;
|
||||
use std::default::Default;
|
||||
|
||||
// Test that a blank impl for all T conflicts with an impl for some
|
||||
// specific T.
|
||||
|
||||
trait MyTrait {
|
||||
fn get(&self) -> uint;
|
||||
}
|
||||
|
||||
impl<T> MyTrait for T { //~ ERROR E0119
|
||||
fn get(&self) -> uint { 0 }
|
||||
}
|
||||
|
||||
struct MyType {
|
||||
dummy: uint
|
||||
}
|
||||
|
||||
impl MyTrait for MyType {
|
||||
fn get(&self) -> uint { self.dummy }
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
BIN
src/test/compile-fail/coherence-multidispatch-tuple
Executable file
BIN
src/test/compile-fail/coherence-multidispatch-tuple
Executable file
Binary file not shown.
29
src/test/compile-fail/coherence-tuple-conflict.rs
Normal file
29
src/test/compile-fail/coherence-tuple-conflict.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
use std::fmt::Show;
|
||||
use std::default::Default;
|
||||
|
||||
// Test that a blank impl for all T conflicts with an impl for some
|
||||
// specific T.
|
||||
|
||||
trait MyTrait {
|
||||
fn get(&self) -> uint;
|
||||
}
|
||||
|
||||
impl<T> MyTrait for (T,T) { //~ ERROR E0119
|
||||
fn get(&self) -> uint { 0 }
|
||||
}
|
||||
|
||||
impl<A,B> MyTrait for (A,B) {
|
||||
fn get(&self) -> uint { self.dummy }
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -20,9 +20,8 @@ impl<T:Dot> Dot for Cons<T> {
|
|||
}
|
||||
}
|
||||
fn test<T:Dot> (n:int, i:int, first:T, second:T) ->int {
|
||||
//~^ ERROR: reached the recursion limit during monomorphization
|
||||
match n {
|
||||
0 => {first.dot(second)}
|
||||
match n { 0 => {first.dot(second)}
|
||||
//~^ ERROR: reached the recursion limit during monomorphization
|
||||
// Error message should be here. It should be a type error
|
||||
// to instantiate `test` at a type other than T. (See #4287)
|
||||
_ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,6 @@ impl Trait<&'static str> for Struct {
|
|||
|
||||
fn main() {
|
||||
let s: Box<Trait<int>> = box Struct { person: "Fred" };
|
||||
//~^ ERROR type mismatch
|
||||
//~^ ERROR the trait `Trait<int>` is not implemented for the type `Struct`
|
||||
s.f(1);
|
||||
}
|
||||
|
|
|
|||
32
src/test/compile-fail/traits-multidispatch-bad.rs
Normal file
32
src/test/compile-fail/traits-multidispatch-bad.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2014 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 detect an illegal combination of types.
|
||||
|
||||
trait Convert<Target> {
|
||||
fn convert(&self) -> Target;
|
||||
}
|
||||
|
||||
impl Convert<uint> for int {
|
||||
fn convert(&self) -> uint {
|
||||
*self as uint
|
||||
}
|
||||
}
|
||||
|
||||
fn test<T,U>(_: T, _: U)
|
||||
where T : Convert<U>
|
||||
{
|
||||
}
|
||||
|
||||
fn a() {
|
||||
test(22i, 44i); //~ ERROR not implemented
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
// Check that we get an error in a multidisptach scenario where the
|
||||
// set of impls is ambiguous.
|
||||
|
||||
trait Convert<Target> {
|
||||
fn convert(&self) -> Target;
|
||||
}
|
||||
|
||||
impl Convert<i8> for i32 {
|
||||
fn convert(&self) -> i8 {
|
||||
*self as i8
|
||||
}
|
||||
}
|
||||
|
||||
impl Convert<i16> for i32 {
|
||||
fn convert(&self) -> i16 {
|
||||
*self as i16
|
||||
}
|
||||
}
|
||||
|
||||
fn test<T,U>(_: T, _: U)
|
||||
where T : Convert<U>
|
||||
{
|
||||
}
|
||||
|
||||
fn a() {
|
||||
test(22_i32, 44); //~ ERROR unable to infer
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -15,12 +15,12 @@ trait Tr<T> {
|
|||
// these compile as if Self: Tr<U>, even tho only Self: Tr<Self or T>
|
||||
trait A: Tr<Self> {
|
||||
fn test<U>(u: U) -> Self {
|
||||
Tr::op(u) //~ ERROR type mismatch
|
||||
Tr::op(u) //~ ERROR not implemented
|
||||
}
|
||||
}
|
||||
trait B<T>: Tr<T> {
|
||||
fn test<U>(u: U) -> Self {
|
||||
Tr::op(u) //~ ERROR type mismatch
|
||||
Tr::op(u) //~ ERROR not implemented
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
|
|
@ -8,15 +8,22 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Foo {
|
||||
use std::fmt::Show;
|
||||
use std::default::Default;
|
||||
|
||||
// Test that an impl for homogeneous pairs does not conflict with a
|
||||
// heterogeneous pair.
|
||||
|
||||
trait MyTrait {
|
||||
fn get(&self) -> uint;
|
||||
}
|
||||
|
||||
impl Foo for int { //~ ERROR conflicting implementations
|
||||
|
||||
impl<T> MyTrait for (T,T) {
|
||||
fn get(&self) -> uint { 0 }
|
||||
}
|
||||
|
||||
impl<A> Foo for A { //~ NOTE conflicting implementation here
|
||||
|
||||
impl MyTrait for (uint,int) {
|
||||
fn get(&self) -> uint { 0 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
46
src/test/run-pass/coherence-where-clause.rs
Normal file
46
src/test/run-pass/coherence-where-clause.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
use std::fmt::Show;
|
||||
use std::default::Default;
|
||||
|
||||
trait MyTrait {
|
||||
fn get(&self) -> Self;
|
||||
}
|
||||
|
||||
impl<T> MyTrait for T
|
||||
where T : Default
|
||||
{
|
||||
fn get(&self) -> T {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone,Show,PartialEq)]
|
||||
struct MyType {
|
||||
dummy: uint
|
||||
}
|
||||
|
||||
impl MyTrait for MyType {
|
||||
fn get(&self) -> MyType { (*self).clone() }
|
||||
}
|
||||
|
||||
fn test_eq<M>(m: M, n: M)
|
||||
where M : MyTrait + Show + PartialEq
|
||||
{
|
||||
assert_eq!(m.get(), n);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
test_eq(0u, 0u);
|
||||
|
||||
let value = MyType { dummy: 256 + 22 };
|
||||
test_eq(value, value);
|
||||
}
|
||||
40
src/test/run-pass/multidispatch1.rs
Normal file
40
src/test/run-pass/multidispatch1.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
use std::fmt::Show;
|
||||
|
||||
trait MyTrait<T> {
|
||||
fn get(&self) -> T;
|
||||
}
|
||||
|
||||
struct MyType {
|
||||
dummy: uint
|
||||
}
|
||||
|
||||
impl MyTrait<uint> for MyType {
|
||||
fn get(&self) -> uint { self.dummy }
|
||||
}
|
||||
|
||||
impl MyTrait<u8> for MyType {
|
||||
fn get(&self) -> u8 { self.dummy as u8 }
|
||||
}
|
||||
|
||||
fn test_eq<T,M>(m: M, v: T)
|
||||
where T : Eq + Show,
|
||||
M : MyTrait<T>
|
||||
{
|
||||
assert_eq!(m.get(), v);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let value = MyType { dummy: 256 + 22 };
|
||||
test_eq::<uint, _>(value, value.dummy);
|
||||
test_eq::<u8, _>(value, value.dummy as u8);
|
||||
}
|
||||
46
src/test/run-pass/multidispatch2.rs
Normal file
46
src/test/run-pass/multidispatch2.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
use std::fmt::Show;
|
||||
use std::default::Default;
|
||||
|
||||
trait MyTrait<T> {
|
||||
fn get(&self) -> T;
|
||||
}
|
||||
|
||||
impl<T> MyTrait<T> for T
|
||||
where T : Default
|
||||
{
|
||||
fn get(&self) -> T {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
struct MyType {
|
||||
dummy: uint
|
||||
}
|
||||
|
||||
impl MyTrait<uint> for MyType {
|
||||
fn get(&self) -> uint { self.dummy }
|
||||
}
|
||||
|
||||
fn test_eq<T,M>(m: M, v: T)
|
||||
where T : Eq + Show,
|
||||
M : MyTrait<T>
|
||||
{
|
||||
assert_eq!(m.get(), v);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
test_eq(22u, 0u);
|
||||
|
||||
let value = MyType { dummy: 256 + 22 };
|
||||
test_eq(value, value.dummy);
|
||||
}
|
||||
36
src/test/run-pass/traits-conditional-dispatch.rs
Normal file
36
src/test/run-pass/traits-conditional-dispatch.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2014 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 are able to resolve conditional dispatch. Here, the
|
||||
// blanket impl for T:Copy coexists with an impl for Box<T>, because
|
||||
// Box does not impl Copy.
|
||||
|
||||
trait Get {
|
||||
fn get(&self) -> Self;
|
||||
}
|
||||
|
||||
impl<T:Copy> Get for T {
|
||||
fn get(&self) -> T { *self }
|
||||
}
|
||||
|
||||
impl<T:Get> Get for Box<T> {
|
||||
fn get(&self) -> Box<T> { box get_it(&**self) }
|
||||
}
|
||||
|
||||
fn get_it<T:Get>(t: &T) -> T {
|
||||
(*t).get()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(get_it(&1_u32), 1_u32);
|
||||
assert_eq!(get_it(&1_u16), 1_u16);
|
||||
assert_eq!(get_it(&Some(1_u16)), Some(1_u16));
|
||||
assert_eq!(get_it(&box 1i), box 1i);
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2014 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 if there is one impl we can infer everything.
|
||||
|
||||
use std::mem;
|
||||
|
||||
trait Convert<Target> {
|
||||
fn convert(&self) -> Target;
|
||||
}
|
||||
|
||||
impl Convert<u32> for i16 {
|
||||
fn convert(&self) -> u32 {
|
||||
*self as u32
|
||||
}
|
||||
}
|
||||
|
||||
fn test<T,U>(_: T, _: U, t_size: uint, u_size: uint)
|
||||
where T : Convert<U>
|
||||
{
|
||||
assert_eq!(mem::size_of::<T>(), t_size);
|
||||
assert_eq!(mem::size_of::<U>(), u_size);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// T = i16, U = u32
|
||||
test(22, 44, 2, 4);
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// Copyright 2014 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 can infer the Target based on the Self or vice versa.
|
||||
|
||||
use std::mem;
|
||||
|
||||
trait Convert<Target> {
|
||||
fn convert(&self) -> Target;
|
||||
}
|
||||
|
||||
impl Convert<u32> for i16 {
|
||||
fn convert(&self) -> u32 {
|
||||
*self as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl Convert<i16> for u32 {
|
||||
fn convert(&self) -> i16 {
|
||||
*self as i16
|
||||
}
|
||||
}
|
||||
|
||||
fn test<T,U>(_: T, _: U, t_size: uint, u_size: uint)
|
||||
where T : Convert<U>
|
||||
{
|
||||
assert_eq!(mem::size_of::<T>(), t_size);
|
||||
assert_eq!(mem::size_of::<U>(), u_size);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// T = i16, U = u32
|
||||
test(22_i16, 44, 2, 4);
|
||||
test(22, 44_u32, 2, 4);
|
||||
|
||||
// T = u32, U = i16
|
||||
test(22_u32, 44, 4, 2);
|
||||
test(22, 44_i16, 4, 2);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue