Implement trait inheritance for bounded type parameters
This commit is contained in:
parent
daa89e0861
commit
78ee821154
38 changed files with 1004 additions and 176 deletions
11
src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs
Normal file
11
src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
pub trait Foo { fn f() -> int; }
|
||||
pub trait Bar { fn g() -> int; }
|
||||
pub trait Baz { fn h() -> int; }
|
||||
|
||||
pub struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
impl A : Bar { fn g() -> int { 20 } }
|
||||
impl A : Baz { fn h() -> int { 30 } }
|
||||
|
||||
|
||||
7
src/test/auxiliary/trait_inheritance_auto_xc_aux.rs
Normal file
7
src/test/auxiliary/trait_inheritance_auto_xc_aux.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
trait Foo { fn f() -> int; }
|
||||
trait Bar { fn g() -> int; }
|
||||
trait Baz { fn h() -> int; }
|
||||
|
||||
trait Quux: Foo, Bar, Baz { }
|
||||
|
||||
impl<T: Foo Bar Baz> T: Quux { }
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
pub trait Foo {
|
||||
fn f() -> int;
|
||||
}
|
||||
|
||||
pub struct A {
|
||||
x: int
|
||||
}
|
||||
|
||||
impl A : Foo {
|
||||
fn f() -> int { 10 }
|
||||
}
|
||||
|
|
@ -1,9 +1,31 @@
|
|||
pub trait MyNum : Add<self,self>, Sub<self,self>, Mul<self,self> {
|
||||
use cmp::Eq;
|
||||
|
||||
pub trait MyNum : Add<self,self>, Sub<self,self>, Mul<self,self>, Eq {
|
||||
}
|
||||
|
||||
pub impl int : MyNum {
|
||||
pure fn add(other: &int) -> int { self + *other }
|
||||
pure fn sub(&self, other: &int) -> int { *self - *other }
|
||||
pure fn mul(&self, other: &int) -> int { *self * *other }
|
||||
pub struct MyInt {
|
||||
val: int
|
||||
}
|
||||
|
||||
pub impl MyInt : Add<MyInt, MyInt> {
|
||||
pure fn add(other: &MyInt) -> MyInt { mi(self.val + other.val) }
|
||||
}
|
||||
|
||||
pub impl MyInt : Sub<MyInt, MyInt> {
|
||||
pure fn sub(&self, other: &MyInt) -> MyInt { mi(self.val - other.val) }
|
||||
}
|
||||
|
||||
pub impl MyInt : Mul<MyInt, MyInt> {
|
||||
pure fn mul(&self, other: &MyInt) -> MyInt { mi(self.val * other.val) }
|
||||
}
|
||||
|
||||
pub impl MyInt : Eq {
|
||||
pure fn eq(&self, other: &MyInt) -> bool { self.val == other.val }
|
||||
|
||||
pure fn ne(&self, other: &MyInt) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
pub impl MyInt : MyNum;
|
||||
|
||||
pure fn mi(v: int) -> MyInt { MyInt { val: v } }
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
// xfail-test
|
||||
// error-pattern: what
|
||||
|
||||
trait Foo {
|
||||
fn f();
|
||||
}
|
||||
|
||||
trait Bar : Foo {
|
||||
fn g();
|
||||
}
|
||||
|
||||
struct A {
|
||||
x: int
|
||||
}
|
||||
|
||||
// Can't implement Bar without an impl of Foo
|
||||
impl A : Bar {
|
||||
fn g() { }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
23
src/test/run-pass/trait-inheritance-auto-xc-2.rs
Normal file
23
src/test/run-pass/trait-inheritance-auto-xc-2.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// xfail-fast
|
||||
// aux-build:trait_inheritance_auto_xc_2_aux.rs
|
||||
|
||||
extern mod aux(name = "trait_inheritance_auto_xc_2_aux");
|
||||
|
||||
// aux defines impls of Foo, Bar and Baz for A
|
||||
use aux::{Foo, Bar, Baz, A};
|
||||
|
||||
// We want to extend all Foo, Bar, Bazes to Quuxes
|
||||
pub trait Quux: Foo, Bar, Baz { }
|
||||
impl<T: Foo Bar Baz> T: Quux { }
|
||||
|
||||
fn f<T: Quux>(a: &T) {
|
||||
assert a.f() == 10;
|
||||
assert a.g() == 20;
|
||||
assert a.h() == 30;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
f(a);
|
||||
}
|
||||
|
||||
24
src/test/run-pass/trait-inheritance-auto-xc.rs
Normal file
24
src/test/run-pass/trait-inheritance-auto-xc.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// xfail-fast
|
||||
// aux-build:trait_inheritance_auto_xc_aux.rs
|
||||
|
||||
extern mod aux(name = "trait_inheritance_auto_xc_aux");
|
||||
|
||||
use aux::{Foo, Bar, Baz, Quux};
|
||||
|
||||
struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
impl A : Bar { fn g() -> int { 20 } }
|
||||
impl A : Baz { fn h() -> int { 30 } }
|
||||
|
||||
fn f<T: Quux>(a: &T) {
|
||||
assert a.f() == 10;
|
||||
assert a.g() == 20;
|
||||
assert a.h() == 30;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
f(a);
|
||||
}
|
||||
|
||||
27
src/test/run-pass/trait-inheritance-auto.rs
Normal file
27
src/test/run-pass/trait-inheritance-auto.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Testing that this impl turns A into a Quux, because
|
||||
// A is already a Foo Bar Baz
|
||||
impl<T: Foo Bar Baz> T: Quux { }
|
||||
|
||||
trait Foo { fn f() -> int; }
|
||||
trait Bar { fn g() -> int; }
|
||||
trait Baz { fn h() -> int; }
|
||||
|
||||
trait Quux: Foo, Bar, Baz { }
|
||||
|
||||
struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
impl A : Bar { fn g() -> int { 20 } }
|
||||
impl A : Baz { fn h() -> int { 30 } }
|
||||
|
||||
fn f<T: Quux>(a: &T) {
|
||||
assert a.f() == 10;
|
||||
assert a.g() == 20;
|
||||
assert a.h() == 30;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
f(a);
|
||||
}
|
||||
|
||||
18
src/test/run-pass/trait-inheritance-call-bound-inherited.rs
Normal file
18
src/test/run-pass/trait-inheritance-call-bound-inherited.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
trait Foo { fn f() -> int; }
|
||||
trait Bar : Foo { fn g() -> int; }
|
||||
|
||||
struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
impl A : Bar { fn g() -> int { 20 } }
|
||||
|
||||
// Call a function on Foo, given a T: Bar
|
||||
fn gg<T:Bar>(a: &T) -> int {
|
||||
a.f()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
assert gg(a) == 10;
|
||||
}
|
||||
|
||||
21
src/test/run-pass/trait-inheritance-call-bound-inherited2.rs
Normal file
21
src/test/run-pass/trait-inheritance-call-bound-inherited2.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
trait Foo { fn f() -> int; }
|
||||
trait Bar : Foo { fn g() -> int; }
|
||||
trait Baz : Bar { fn h() -> int; }
|
||||
|
||||
struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
impl A : Bar { fn g() -> int { 20 } }
|
||||
impl A : Baz { fn h() -> int { 30 } }
|
||||
|
||||
// Call a function on Foo, given a T: Baz,
|
||||
// which is inherited via Bar
|
||||
fn gg<T: Baz>(a: &T) -> int {
|
||||
a.f()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
assert gg(a) == 10;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Testing that we can cast to a subtrait and call subtrait
|
||||
// methods. Not testing supertrait methods
|
||||
|
||||
trait Foo {
|
||||
fn f() -> int;
|
||||
}
|
||||
|
||||
trait Bar : Foo {
|
||||
fn g() -> int;
|
||||
}
|
||||
|
||||
struct A {
|
||||
x: int
|
||||
}
|
||||
|
||||
impl A : Foo {
|
||||
fn f() -> int { 10 }
|
||||
}
|
||||
|
||||
impl A : Bar {
|
||||
fn g() -> int { 20 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
let afoo = a as &Foo;
|
||||
let abar = a as &Bar;
|
||||
assert afoo.f() == 10;
|
||||
assert abar.g() == 20;
|
||||
}
|
||||
|
||||
33
src/test/run-pass/trait-inheritance-cast.rs
Normal file
33
src/test/run-pass/trait-inheritance-cast.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// xfail-test
|
||||
// Testing that supertrait methods can be called on subtrait object types
|
||||
// It's not clear yet that we want this
|
||||
|
||||
trait Foo {
|
||||
fn f() -> int;
|
||||
}
|
||||
|
||||
trait Bar : Foo {
|
||||
fn g() -> int;
|
||||
}
|
||||
|
||||
struct A {
|
||||
x: int
|
||||
}
|
||||
|
||||
impl A : Foo {
|
||||
fn f() -> int { 10 }
|
||||
}
|
||||
|
||||
impl A : Bar {
|
||||
fn g() -> int { 20 }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
let afoo = a as &Foo;
|
||||
let abar = a as &Bar;
|
||||
assert afoo.f() == 10;
|
||||
assert abar.g() == 20;
|
||||
assert abar.f() == 10;
|
||||
}
|
||||
|
||||
18
src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs
Normal file
18
src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// xfail-fast
|
||||
// aux-build:trait_inheritance_cross_trait_call_xc_aux.rs
|
||||
|
||||
extern mod aux(name = "trait_inheritance_cross_trait_call_xc_aux");
|
||||
|
||||
trait Bar : aux::Foo {
|
||||
fn g() -> int;
|
||||
}
|
||||
|
||||
impl aux::A : Bar {
|
||||
fn g() -> int { self.f() }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &aux::A { x: 3 };
|
||||
assert a.g() == 10;
|
||||
}
|
||||
|
||||
17
src/test/run-pass/trait-inheritance-cross-trait-call.rs
Normal file
17
src/test/run-pass/trait-inheritance-cross-trait-call.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
trait Foo { fn f() -> int; }
|
||||
trait Bar : Foo { fn g() -> int; }
|
||||
|
||||
struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
|
||||
impl A : Bar {
|
||||
// Testing that this impl can call the impl of Foo
|
||||
fn g() -> int { self.f() }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
assert a.g() == 10;
|
||||
}
|
||||
|
||||
25
src/test/run-pass/trait-inheritance-diamond.rs
Normal file
25
src/test/run-pass/trait-inheritance-diamond.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// B and C both require A, so D does as well, twice, but that's just fine
|
||||
|
||||
trait A { fn a(&self) -> int; }
|
||||
trait B: A { fn b(&self) -> int; }
|
||||
trait C: A { fn c(&self) -> int; }
|
||||
trait D: B, C { fn d(&self) -> int; }
|
||||
|
||||
struct S { bogus: () }
|
||||
|
||||
impl S: A { fn a(&self) -> int { 10 } }
|
||||
impl S: B { fn b(&self) -> int { 20 } }
|
||||
impl S: C { fn c(&self) -> int { 30 } }
|
||||
impl S: D { fn d(&self) -> int { 40 } }
|
||||
|
||||
fn f<T: D>(x: &T) {
|
||||
assert x.a() == 10;
|
||||
assert x.b() == 20;
|
||||
assert x.c() == 30;
|
||||
assert x.d() == 40;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let value = &S { bogus: () };
|
||||
f(value);
|
||||
}
|
||||
20
src/test/run-pass/trait-inheritance-multiple-inheritors.rs
Normal file
20
src/test/run-pass/trait-inheritance-multiple-inheritors.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
trait A { fn a(&self) -> int; }
|
||||
trait B: A { fn b(&self) -> int; }
|
||||
trait C: A { fn c(&self) -> int; }
|
||||
|
||||
struct S { bogus: () }
|
||||
|
||||
impl S: A { fn a(&self) -> int { 10 } }
|
||||
impl S: B { fn b(&self) -> int { 20 } }
|
||||
impl S: C { fn c(&self) -> int { 30 } }
|
||||
|
||||
// Both B and C inherit from A
|
||||
fn f<T: B C>(x: &T) {
|
||||
assert x.a() == 10;
|
||||
assert x.b() == 20;
|
||||
assert x.c() == 30;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
f(&S { bogus: () })
|
||||
}
|
||||
23
src/test/run-pass/trait-inheritance-multiple-params.rs
Normal file
23
src/test/run-pass/trait-inheritance-multiple-params.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
trait A { fn a(&self) -> int; }
|
||||
trait B: A { fn b(&self) -> int; }
|
||||
trait C: A { fn c(&self) -> int; }
|
||||
|
||||
struct S { bogus: () }
|
||||
|
||||
impl S: A { fn a(&self) -> int { 10 } }
|
||||
impl S: B { fn b(&self) -> int { 20 } }
|
||||
impl S: C { fn c(&self) -> int { 30 } }
|
||||
|
||||
// Multiple type params, multiple levels of inheritance
|
||||
fn f<X: A, Y: B, Z: C>(x: &X, y: &Y, z: &Z) {
|
||||
assert x.a() == 10;
|
||||
assert y.a() == 10;
|
||||
assert y.b() == 20;
|
||||
assert z.a() == 10;
|
||||
assert z.c() == 30;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = &S { bogus: () };
|
||||
f(s, s, s);
|
||||
}
|
||||
14
src/test/run-pass/trait-inheritance-num.rs
Normal file
14
src/test/run-pass/trait-inheritance-num.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
use cmp::{Eq, Ord};
|
||||
use num::from_int;
|
||||
|
||||
extern mod std;
|
||||
use std::cmp::FuzzyEq;
|
||||
|
||||
pub trait NumExt: Num, Eq, Ord {}
|
||||
|
||||
pub trait FloatExt: NumExt, FuzzyEq {}
|
||||
|
||||
fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > from_int(1) }
|
||||
fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > from_int(1) }
|
||||
|
||||
fn main() {}
|
||||
16
src/test/run-pass/trait-inheritance-num0.rs
Normal file
16
src/test/run-pass/trait-inheritance-num0.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Extending Num and using inherited static methods
|
||||
|
||||
use num::from_int;
|
||||
|
||||
trait Num {
|
||||
static fn from_int(i: int) -> self;
|
||||
fn gt(&self, other: &self) -> bool;
|
||||
}
|
||||
|
||||
pub trait NumExt: Num { }
|
||||
|
||||
fn greater_than_one<T:NumExt>(n: &T) -> bool {
|
||||
n.gt(&from_int(1))
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
12
src/test/run-pass/trait-inheritance-num1.rs
Normal file
12
src/test/run-pass/trait-inheritance-num1.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Using the real Num from core
|
||||
|
||||
use cmp::Ord;
|
||||
use num::from_int;
|
||||
|
||||
pub trait NumExt: Num, Ord { }
|
||||
|
||||
fn greater_than_one<T:NumExt>(n: &T) -> bool {
|
||||
*n > from_int(1)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
96
src/test/run-pass/trait-inheritance-num2.rs
Normal file
96
src/test/run-pass/trait-inheritance-num2.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// A more complex example of numeric extensions
|
||||
|
||||
use cmp::{Eq, Ord};
|
||||
use num::from_int;
|
||||
|
||||
extern mod std;
|
||||
use std::cmp::FuzzyEq;
|
||||
|
||||
pub trait TypeExt {}
|
||||
|
||||
|
||||
pub impl u8: TypeExt {}
|
||||
pub impl u16: TypeExt {}
|
||||
pub impl u32: TypeExt {}
|
||||
pub impl u64: TypeExt {}
|
||||
pub impl uint: TypeExt {}
|
||||
|
||||
pub impl i8: TypeExt {}
|
||||
pub impl i16: TypeExt {}
|
||||
pub impl i32: TypeExt {}
|
||||
pub impl i64: TypeExt {}
|
||||
pub impl int: TypeExt {}
|
||||
|
||||
pub impl f32: TypeExt {}
|
||||
pub impl f64: TypeExt {}
|
||||
pub impl float: TypeExt {}
|
||||
|
||||
|
||||
pub trait NumExt: TypeExt, Eq, Ord, Num {}
|
||||
|
||||
pub impl u8: NumExt {}
|
||||
pub impl u16: NumExt {}
|
||||
pub impl u32: NumExt {}
|
||||
pub impl u64: NumExt {}
|
||||
pub impl uint: NumExt {}
|
||||
|
||||
pub impl i8: NumExt {}
|
||||
pub impl i16: NumExt {}
|
||||
pub impl i32: NumExt {}
|
||||
pub impl i64: NumExt {}
|
||||
pub impl int: NumExt {}
|
||||
|
||||
pub impl f32: NumExt {}
|
||||
pub impl f64: NumExt {}
|
||||
pub impl float: NumExt {}
|
||||
|
||||
|
||||
pub trait UnSignedExt: NumExt {}
|
||||
|
||||
pub impl u8: UnSignedExt {}
|
||||
pub impl u16: UnSignedExt {}
|
||||
pub impl u32: UnSignedExt {}
|
||||
pub impl u64: UnSignedExt {}
|
||||
pub impl uint: UnSignedExt {}
|
||||
|
||||
|
||||
pub trait SignedExt: NumExt {}
|
||||
|
||||
pub impl i8: SignedExt {}
|
||||
pub impl i16: SignedExt {}
|
||||
pub impl i32: SignedExt {}
|
||||
pub impl i64: SignedExt {}
|
||||
pub impl int: SignedExt {}
|
||||
|
||||
pub impl f32: SignedExt {}
|
||||
pub impl f64: SignedExt {}
|
||||
pub impl float: SignedExt {}
|
||||
|
||||
|
||||
pub trait IntegerExt: NumExt {}
|
||||
|
||||
pub impl u8: IntegerExt {}
|
||||
pub impl u16: IntegerExt {}
|
||||
pub impl u32: IntegerExt {}
|
||||
pub impl u64: IntegerExt {}
|
||||
pub impl uint: IntegerExt {}
|
||||
|
||||
pub impl i8: IntegerExt {}
|
||||
pub impl i16: IntegerExt {}
|
||||
pub impl i32: IntegerExt {}
|
||||
pub impl i64: IntegerExt {}
|
||||
pub impl int: IntegerExt {}
|
||||
|
||||
|
||||
pub trait FloatExt: NumExt , FuzzyEq {}
|
||||
|
||||
pub impl f32: FloatExt {}
|
||||
pub impl f64: FloatExt {}
|
||||
pub impl float: FloatExt {}
|
||||
|
||||
|
||||
fn test_float_ext<T:FloatExt>(n: T) { io::println(fmt!("%?", n < n)) }
|
||||
|
||||
fn main() {
|
||||
test_float_ext(1f32);
|
||||
}
|
||||
12
src/test/run-pass/trait-inheritance-num3.rs
Normal file
12
src/test/run-pass/trait-inheritance-num3.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
use cmp::{Eq, Ord};
|
||||
use num::from_int;
|
||||
|
||||
pub trait NumExt: Eq, Ord, Num {}
|
||||
|
||||
pub impl f32: NumExt {}
|
||||
|
||||
fn num_eq_one<T:NumExt>(n: T) { io::println(fmt!("%?", n == from_int(1))) }
|
||||
|
||||
fn main() {
|
||||
num_eq_one(1f32); // you need to actually use the function to trigger the ICE
|
||||
}
|
||||
15
src/test/run-pass/trait-inheritance-num5.rs
Normal file
15
src/test/run-pass/trait-inheritance-num5.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use cmp::{Eq, Ord};
|
||||
use num::from_int;
|
||||
|
||||
pub trait NumExt: Eq, Num {}
|
||||
|
||||
pub impl f32: NumExt {}
|
||||
pub impl int: NumExt {}
|
||||
|
||||
fn num_eq_one<T:NumExt>() -> T {
|
||||
from_int(1)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
num_eq_one::<int>(); // you need to actually use the function to trigger the ICE
|
||||
}
|
||||
25
src/test/run-pass/trait-inheritance-overloading-simple.rs
Normal file
25
src/test/run-pass/trait-inheritance-overloading-simple.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use cmp::Eq;
|
||||
|
||||
trait MyNum : Eq { }
|
||||
|
||||
struct MyInt { val: int }
|
||||
|
||||
impl MyInt : Eq {
|
||||
pure fn eq(&self, other: &MyInt) -> bool { self.val == other.val }
|
||||
pure fn ne(&self, other: &MyInt) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
impl MyInt : MyNum;
|
||||
|
||||
fn f<T:MyNum>(x: T, y: T) -> bool {
|
||||
return x == y;
|
||||
}
|
||||
|
||||
pure fn mi(v: int) -> MyInt { MyInt { val: v } }
|
||||
|
||||
fn main() {
|
||||
let (x, y, z) = (mi(3), mi(5), mi(3));
|
||||
assert x != y;
|
||||
assert x == z;
|
||||
}
|
||||
|
||||
|
|
@ -2,18 +2,19 @@
|
|||
// aux-build:trait_inheritance_overloading_xc.rs
|
||||
|
||||
extern mod trait_inheritance_overloading_xc;
|
||||
use trait_inheritance_overloading_xc::MyNum;
|
||||
use trait_inheritance_overloading_xc::{MyNum, MyInt};
|
||||
|
||||
fn f<T:Copy MyNum>(x: T, y: T) -> (T, T, T) {
|
||||
return (x + y, x - y, x * y);
|
||||
}
|
||||
|
||||
pure fn mi(v: int) -> MyInt { MyInt { val: v } }
|
||||
|
||||
fn main() {
|
||||
let (x, y) = (3, 5);
|
||||
let (x, y) = (mi(3), mi(5));
|
||||
let (a, b, c) = f(x, y);
|
||||
assert a == 8;
|
||||
assert b == -2;
|
||||
assert c == 15;
|
||||
assert a == mi(8);
|
||||
assert b == mi(-2);
|
||||
assert c == mi(15);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,39 @@
|
|||
trait MyNum : Add<self,self>, Sub<self,self>, Mul<self,self> {
|
||||
use cmp::Eq;
|
||||
|
||||
trait MyNum : Add<self,self>, Sub<self,self>, Mul<self,self>, Eq { }
|
||||
|
||||
struct MyInt { val: int }
|
||||
|
||||
impl MyInt : Add<MyInt, MyInt> {
|
||||
pure fn add(other: &MyInt) -> MyInt { mi(self.val + other.val) }
|
||||
}
|
||||
|
||||
impl int : MyNum {
|
||||
pure fn add(other: &int) -> int { self + *other }
|
||||
pure fn sub(&self, other: &int) -> int { *self - *other }
|
||||
pure fn mul(&self, other: &int) -> int { *self * *other }
|
||||
impl MyInt : Sub<MyInt, MyInt> {
|
||||
pure fn sub(&self, other: &MyInt) -> MyInt { mi(self.val - other.val) }
|
||||
}
|
||||
|
||||
impl MyInt : Mul<MyInt, MyInt> {
|
||||
pure fn mul(&self, other: &MyInt) -> MyInt { mi(self.val * other.val) }
|
||||
}
|
||||
|
||||
impl MyInt : Eq {
|
||||
pure fn eq(&self, other: &MyInt) -> bool { self.val == other.val }
|
||||
pure fn ne(&self, other: &MyInt) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
impl MyInt : MyNum;
|
||||
|
||||
fn f<T:Copy MyNum>(x: T, y: T) -> (T, T, T) {
|
||||
return (x + y, x - y, x * y);
|
||||
}
|
||||
|
||||
pure fn mi(v: int) -> MyInt { MyInt { val: v } }
|
||||
|
||||
fn main() {
|
||||
let (x, y) = (3, 5);
|
||||
let (x, y) = (mi(3), mi(5));
|
||||
let (a, b, c) = f(x, y);
|
||||
assert a == 8;
|
||||
assert b == -2;
|
||||
assert c == 15;
|
||||
assert a == mi(8);
|
||||
assert b == mi(-2);
|
||||
assert c == mi(15);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +1,22 @@
|
|||
trait Foo {
|
||||
fn f();
|
||||
trait Foo { fn f() -> int; }
|
||||
trait Bar : Foo { fn g() -> int; }
|
||||
|
||||
struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
impl A : Bar { fn g() -> int { 20 } }
|
||||
|
||||
fn ff<T:Foo>(a: &T) -> int {
|
||||
a.f()
|
||||
}
|
||||
|
||||
trait Bar : Foo {
|
||||
fn g();
|
||||
}
|
||||
|
||||
struct A {
|
||||
x: int
|
||||
}
|
||||
|
||||
impl A : Bar {
|
||||
fn g() { io::println("in g"); }
|
||||
fn f() { io::println("in f"); }
|
||||
}
|
||||
|
||||
fn h<T:Foo>(a: &T) {
|
||||
a.f();
|
||||
fn gg<T:Bar>(a: &T) -> int {
|
||||
a.g()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = A { x: 3 };
|
||||
h(&a);
|
||||
let a = &A { x: 3 };
|
||||
assert ff(a) == 10;
|
||||
assert gg(a) == 20;
|
||||
}
|
||||
|
||||
|
|
|
|||
24
src/test/run-pass/trait-inheritance-static.rs
Normal file
24
src/test/run-pass/trait-inheritance-static.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
trait MyNum {
|
||||
static fn from_int(int) -> self;
|
||||
}
|
||||
|
||||
pub trait NumExt: MyNum { }
|
||||
|
||||
struct S { v: int }
|
||||
|
||||
impl S: MyNum {
|
||||
static fn from_int(i: int) -> S {
|
||||
S {
|
||||
v: i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl S: NumExt { }
|
||||
|
||||
fn greater_than_one<T:NumExt>() -> T { from_int(1) }
|
||||
|
||||
fn main() {
|
||||
let v: S = greater_than_one();
|
||||
assert v.v == 1;
|
||||
}
|
||||
28
src/test/run-pass/trait-inheritance-static2.rs
Normal file
28
src/test/run-pass/trait-inheritance-static2.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
trait MyEq { }
|
||||
|
||||
trait MyNum {
|
||||
static fn from_int(int) -> self;
|
||||
}
|
||||
|
||||
pub trait NumExt: MyEq, MyNum { }
|
||||
|
||||
struct S { v: int }
|
||||
|
||||
impl S: MyEq { }
|
||||
|
||||
impl S: MyNum {
|
||||
static fn from_int(i: int) -> S {
|
||||
S {
|
||||
v: i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl S: NumExt { }
|
||||
|
||||
fn greater_than_one<T:NumExt>() -> T { from_int(1) }
|
||||
|
||||
fn main() {
|
||||
let v: S = greater_than_one();
|
||||
assert v.v == 1;
|
||||
}
|
||||
26
src/test/run-pass/trait-inheritance-subst.rs
Normal file
26
src/test/run-pass/trait-inheritance-subst.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
pub trait Add<RHS,Result> {
|
||||
pure fn add(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
trait MyNum : Add<self,self> { }
|
||||
|
||||
struct MyInt { val: int }
|
||||
|
||||
impl MyInt : Add<MyInt, MyInt> {
|
||||
pure fn add(other: &MyInt) -> MyInt { mi(self.val + other.val) }
|
||||
}
|
||||
|
||||
impl MyInt : MyNum;
|
||||
|
||||
fn f<T:MyNum>(x: T, y: T) -> T {
|
||||
return x.add(&y);
|
||||
}
|
||||
|
||||
pure fn mi(v: int) -> MyInt { MyInt { val: v } }
|
||||
|
||||
fn main() {
|
||||
let (x, y) = (mi(3), mi(5));
|
||||
let z = f(x, y);
|
||||
assert z.val == 8
|
||||
}
|
||||
|
||||
36
src/test/run-pass/trait-inheritance-subst2.rs
Normal file
36
src/test/run-pass/trait-inheritance-subst2.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
trait Panda<T> {
|
||||
fn chomp(bamboo: &T) -> T;
|
||||
}
|
||||
|
||||
trait Add<RHS,Result>: Panda<RHS> {
|
||||
fn add(rhs: &RHS) -> Result;
|
||||
}
|
||||
|
||||
trait MyNum : Add<self,self> { }
|
||||
|
||||
struct MyInt { val: int }
|
||||
|
||||
impl MyInt : Panda<MyInt> {
|
||||
fn chomp(bamboo: &MyInt) -> MyInt {
|
||||
mi(self.val + bamboo.val)
|
||||
}
|
||||
}
|
||||
|
||||
impl MyInt : Add<MyInt, MyInt> {
|
||||
fn add(other: &MyInt) -> MyInt { self.chomp(other) }
|
||||
}
|
||||
|
||||
impl MyInt : MyNum;
|
||||
|
||||
fn f<T:MyNum>(x: T, y: T) -> T {
|
||||
return x.add(&y).chomp(&y);
|
||||
}
|
||||
|
||||
fn mi(v: int) -> MyInt { MyInt { val: v } }
|
||||
|
||||
fn main() {
|
||||
let (x, y) = (mi(3), mi(5));
|
||||
let z = f(x, y);
|
||||
assert z.val == 13;
|
||||
}
|
||||
|
||||
18
src/test/run-pass/trait-inheritance-visibility.rs
Normal file
18
src/test/run-pass/trait-inheritance-visibility.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
mod traits {
|
||||
pub trait Foo { fn f() -> int; }
|
||||
|
||||
impl int: Foo { fn f() -> int { 10 } }
|
||||
}
|
||||
|
||||
trait Quux: traits::Foo { }
|
||||
impl<T: traits::Foo> T: Quux { }
|
||||
|
||||
// Foo is not in scope but because Quux is we can still access
|
||||
// Foo's methods on a Quux bound typaram
|
||||
fn f<T: Quux>(x: &T) {
|
||||
assert x.f() == 10;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
f(&0)
|
||||
}
|
||||
24
src/test/run-pass/trait-inheritance2.rs
Normal file
24
src/test/run-pass/trait-inheritance2.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
trait Foo { fn f() -> int; }
|
||||
trait Bar { fn g() -> int; }
|
||||
trait Baz { fn h() -> int; }
|
||||
|
||||
trait Quux: Foo, Bar, Baz { }
|
||||
|
||||
struct A { x: int }
|
||||
|
||||
impl A : Foo { fn f() -> int { 10 } }
|
||||
impl A : Bar { fn g() -> int { 20 } }
|
||||
impl A : Baz { fn h() -> int { 30 } }
|
||||
impl A : Quux;
|
||||
|
||||
fn f<T: Quux Foo Bar Baz>(a: &T) {
|
||||
assert a.f() == 10;
|
||||
assert a.g() == 20;
|
||||
assert a.h() == 30;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = &A { x: 3 };
|
||||
f(a);
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue