diff options
| author | Brian Anderson <banderson@mozilla.com> | 2012-11-28 12:34:30 -0800 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2012-11-29 18:10:11 -0800 |
| commit | 78ee821154ba6034a86397d8540fec00c94e9282 (patch) | |
| tree | 7e029752af04975fd78b6218c8a0d44010b51a42 /src/test | |
| parent | daa89e086156099e3aa95577ec97f761e056e65e (diff) | |
| download | rust-78ee821154ba6034a86397d8540fec00c94e9282.tar.gz rust-78ee821154ba6034a86397d8540fec00c94e9282.zip | |
Implement trait inheritance for bounded type parameters
Diffstat (limited to 'src/test')
33 files changed, 752 insertions, 36 deletions
diff --git a/src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs b/src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs new file mode 100644 index 00000000000..99f4119b1cc --- /dev/null +++ b/src/test/auxiliary/trait_inheritance_auto_xc_2_aux.rs @@ -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 } } + + diff --git a/src/test/auxiliary/trait_inheritance_auto_xc_aux.rs b/src/test/auxiliary/trait_inheritance_auto_xc_aux.rs new file mode 100644 index 00000000000..8fe7b72f8e7 --- /dev/null +++ b/src/test/auxiliary/trait_inheritance_auto_xc_aux.rs @@ -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 { } diff --git a/src/test/auxiliary/trait_inheritance_cross_trait_call_xc_aux.rs b/src/test/auxiliary/trait_inheritance_cross_trait_call_xc_aux.rs new file mode 100644 index 00000000000..00029d11bf4 --- /dev/null +++ b/src/test/auxiliary/trait_inheritance_cross_trait_call_xc_aux.rs @@ -0,0 +1,12 @@ + +pub trait Foo { + fn f() -> int; +} + +pub struct A { + x: int +} + +impl A : Foo { + fn f() -> int { 10 } +} diff --git a/src/test/auxiliary/trait_inheritance_overloading_xc.rs b/src/test/auxiliary/trait_inheritance_overloading_xc.rs index 235a174c838..ceeee89de6a 100644 --- a/src/test/auxiliary/trait_inheritance_overloading_xc.rs +++ b/src/test/auxiliary/trait_inheritance_overloading_xc.rs @@ -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 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 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 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 } } + diff --git a/src/test/compile-fail/trait-inheritance-missing-requirement.rs b/src/test/compile-fail/trait-inheritance-missing-requirement.rs new file mode 100644 index 00000000000..3105f72415a --- /dev/null +++ b/src/test/compile-fail/trait-inheritance-missing-requirement.rs @@ -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() { +} + diff --git a/src/test/run-pass/trait-inheritance-auto-xc-2.rs b/src/test/run-pass/trait-inheritance-auto-xc-2.rs new file mode 100644 index 00000000000..4eac9710250 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-auto-xc-2.rs @@ -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); +} + diff --git a/src/test/run-pass/trait-inheritance-auto-xc.rs b/src/test/run-pass/trait-inheritance-auto-xc.rs new file mode 100644 index 00000000000..4bc62fab51b --- /dev/null +++ b/src/test/run-pass/trait-inheritance-auto-xc.rs @@ -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); +} + diff --git a/src/test/run-pass/trait-inheritance-auto.rs b/src/test/run-pass/trait-inheritance-auto.rs new file mode 100644 index 00000000000..29de9f111dc --- /dev/null +++ b/src/test/run-pass/trait-inheritance-auto.rs @@ -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); +} + diff --git a/src/test/run-pass/trait-inheritance-call-bound-inherited.rs b/src/test/run-pass/trait-inheritance-call-bound-inherited.rs new file mode 100644 index 00000000000..dd3f53cfbdd --- /dev/null +++ b/src/test/run-pass/trait-inheritance-call-bound-inherited.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs b/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs new file mode 100644 index 00000000000..222d8e7291d --- /dev/null +++ b/src/test/run-pass/trait-inheritance-call-bound-inherited2.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs new file mode 100644 index 00000000000..6cb05516520 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-cast-without-call-to-supertrait.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-cast.rs b/src/test/run-pass/trait-inheritance-cast.rs new file mode 100644 index 00000000000..1cd23f49733 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-cast.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs b/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs new file mode 100644 index 00000000000..9f588ddb907 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-cross-trait-call-xc.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-cross-trait-call.rs b/src/test/run-pass/trait-inheritance-cross-trait-call.rs new file mode 100644 index 00000000000..a96bfb41f44 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-cross-trait-call.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-diamond.rs b/src/test/run-pass/trait-inheritance-diamond.rs new file mode 100644 index 00000000000..4c18d92a8c0 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-diamond.rs @@ -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); +} \ No newline at end of file diff --git a/src/test/run-pass/trait-inheritance-multiple-inheritors.rs b/src/test/run-pass/trait-inheritance-multiple-inheritors.rs new file mode 100644 index 00000000000..fdc68a31997 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-multiple-inheritors.rs @@ -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: () }) +} \ No newline at end of file diff --git a/src/test/run-pass/trait-inheritance-multiple-params.rs b/src/test/run-pass/trait-inheritance-multiple-params.rs new file mode 100644 index 00000000000..0a5330b68f8 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-multiple-params.rs @@ -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); +} \ No newline at end of file diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs new file mode 100644 index 00000000000..2266b67c234 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-num.rs @@ -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() {} diff --git a/src/test/run-pass/trait-inheritance-num0.rs b/src/test/run-pass/trait-inheritance-num0.rs new file mode 100644 index 00000000000..6c3b22894f5 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-num0.rs @@ -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() {} diff --git a/src/test/run-pass/trait-inheritance-num1.rs b/src/test/run-pass/trait-inheritance-num1.rs new file mode 100644 index 00000000000..57487f072f3 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-num1.rs @@ -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() {} diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs new file mode 100644 index 00000000000..5f51f943817 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -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); +} \ No newline at end of file diff --git a/src/test/run-pass/trait-inheritance-num3.rs b/src/test/run-pass/trait-inheritance-num3.rs new file mode 100644 index 00000000000..656e6390662 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-num3.rs @@ -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 +} \ No newline at end of file diff --git a/src/test/run-pass/trait-inheritance-num5.rs b/src/test/run-pass/trait-inheritance-num5.rs new file mode 100644 index 00000000000..fa30ceff8ad --- /dev/null +++ b/src/test/run-pass/trait-inheritance-num5.rs @@ -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 +} diff --git a/src/test/run-pass/trait-inheritance-overloading-simple.rs b/src/test/run-pass/trait-inheritance-overloading-simple.rs new file mode 100644 index 00000000000..13867eed52f --- /dev/null +++ b/src/test/run-pass/trait-inheritance-overloading-simple.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs index a38a834fb72..585ce63b389 100644 --- a/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs +++ b/src/test/run-pass/trait-inheritance-overloading-xc-exe.rs @@ -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); } - diff --git a/src/test/run-pass/trait-inheritance-overloading.rs b/src/test/run-pass/trait-inheritance-overloading.rs index f8bf9faa186..def37d1f950 100644 --- a/src/test/run-pass/trait-inheritance-overloading.rs +++ b/src/test/run-pass/trait-inheritance-overloading.rs @@ -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 MyInt : Sub<MyInt, MyInt> { + pure fn sub(&self, 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 : 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); } diff --git a/src/test/run-pass/trait-inheritance-simple.rs b/src/test/run-pass/trait-inheritance-simple.rs index fcd4cf1de6b..9725b18ca0f 100644 --- a/src/test/run-pass/trait-inheritance-simple.rs +++ b/src/test/run-pass/trait-inheritance-simple.rs @@ -1,26 +1,22 @@ -trait Foo { - fn f(); -} +trait Foo { fn f() -> int; } +trait Bar : Foo { fn g() -> int; } -trait Bar : Foo { - fn g(); -} +struct A { x: int } -struct A { - x: int -} +impl A : Foo { fn f() -> int { 10 } } +impl A : Bar { fn g() -> int { 20 } } -impl A : Bar { - fn g() { io::println("in g"); } - fn f() { io::println("in f"); } +fn ff<T:Foo>(a: &T) -> int { + a.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; } diff --git a/src/test/run-pass/trait-inheritance-static.rs b/src/test/run-pass/trait-inheritance-static.rs new file mode 100644 index 00000000000..a3788d8647b --- /dev/null +++ b/src/test/run-pass/trait-inheritance-static.rs @@ -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; +} diff --git a/src/test/run-pass/trait-inheritance-static2.rs b/src/test/run-pass/trait-inheritance-static2.rs new file mode 100644 index 00000000000..e6f3f1fb991 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-static2.rs @@ -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; +} diff --git a/src/test/run-pass/trait-inheritance-subst.rs b/src/test/run-pass/trait-inheritance-subst.rs new file mode 100644 index 00000000000..3fdf96b404e --- /dev/null +++ b/src/test/run-pass/trait-inheritance-subst.rs @@ -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 +} + diff --git a/src/test/run-pass/trait-inheritance-subst2.rs b/src/test/run-pass/trait-inheritance-subst2.rs new file mode 100644 index 00000000000..343c567ab97 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-subst2.rs @@ -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; +} + diff --git a/src/test/run-pass/trait-inheritance-visibility.rs b/src/test/run-pass/trait-inheritance-visibility.rs new file mode 100644 index 00000000000..1fbe35328b6 --- /dev/null +++ b/src/test/run-pass/trait-inheritance-visibility.rs @@ -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) +} \ No newline at end of file diff --git a/src/test/run-pass/trait-inheritance2.rs b/src/test/run-pass/trait-inheritance2.rs new file mode 100644 index 00000000000..7d4c2cacfea --- /dev/null +++ b/src/test/run-pass/trait-inheritance2.rs @@ -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); +} + |
