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:
Niko Matsakis 2014-10-09 17:19:50 -04:00
parent 79d056f94b
commit 389ef6601d
31 changed files with 1425 additions and 755 deletions

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

View file

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

View file

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

Binary file not shown.

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

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

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

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

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

View file

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

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