diff options
Diffstat (limited to 'tests/ui/traits/inheritance')
37 files changed, 1080 insertions, 0 deletions
diff --git a/tests/ui/traits/inheritance/auto-xc-2.rs b/tests/ui/traits/inheritance/auto-xc-2.rs new file mode 100644 index 000000000..f2130228d --- /dev/null +++ b/tests/ui/traits/inheritance/auto-xc-2.rs @@ -0,0 +1,23 @@ +// run-pass +// aux-build:auto_xc_2.rs + + +extern crate auto_xc_2 as 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> Quux for T { } + +fn f<T:Quux>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auto-xc.rs b/tests/ui/traits/inheritance/auto-xc.rs new file mode 100644 index 000000000..3d5ae182a --- /dev/null +++ b/tests/ui/traits/inheritance/auto-xc.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(dead_code)] +// aux-build:auto_xc.rs + + +extern crate auto_xc as aux; + +use aux::{Foo, Bar, Baz, Quux}; + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +fn f<T:Quux>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auto.rs b/tests/ui/traits/inheritance/auto.rs new file mode 100644 index 000000000..0be67a55e --- /dev/null +++ b/tests/ui/traits/inheritance/auto.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(dead_code)] +// Testing that this impl turns A into a Quux, because +// A is already a Foo Bar Baz + +impl<T:Foo + Bar + Baz> Quux for T { } + +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } + +trait Quux: Foo + Bar + Baz { } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +fn f<T:Quux>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs new file mode 100644 index 000000000..9af26cb2e --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/auto_xc.rs @@ -0,0 +1,7 @@ +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } + +pub trait Quux: Foo + Bar + Baz { } + +impl<T:Foo + Bar + Baz> Quux for T { } diff --git a/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs new file mode 100644 index 000000000..e9327676d --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/auto_xc_2.rs @@ -0,0 +1,9 @@ +pub trait Foo { fn f(&self) -> isize; } +pub trait Bar { fn g(&self) -> isize; } +pub trait Baz { fn h(&self) -> isize; } + +pub struct A { pub x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } diff --git a/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs new file mode 100644 index 000000000..a25704412 --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/overloading_xc.rs @@ -0,0 +1,38 @@ +use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; + +pub trait MyNum : Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + PartialEq + Clone { +} + +#[derive(Clone, Debug)] +pub struct MyInt { + pub val: isize +} + +impl Add for MyInt { + type Output = MyInt; + + fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl Sub for MyInt { + type Output = MyInt; + + fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) } +} + +impl Mul for MyInt { + type Output = MyInt; + + fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) } +} + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } diff --git a/tests/ui/traits/inheritance/auxiliary/xc_call.rs b/tests/ui/traits/inheritance/auxiliary/xc_call.rs new file mode 100644 index 000000000..b76c52e62 --- /dev/null +++ b/tests/ui/traits/inheritance/auxiliary/xc_call.rs @@ -0,0 +1,11 @@ +pub trait Foo { + fn f(&self) -> isize; +} + +pub struct A { + pub x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} diff --git a/tests/ui/traits/inheritance/basic.rs b/tests/ui/traits/inheritance/basic.rs new file mode 100644 index 000000000..5bfa60b1a --- /dev/null +++ b/tests/ui/traits/inheritance/basic.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar { fn g(&self) -> isize; } +trait Baz { fn h(&self) -> isize; } + +trait Quux: Foo + Bar + Baz { } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } +impl Quux for A {} + +fn f<T:Quux + Foo + Bar + Baz>(a: &T) { + assert_eq!(a.f(), 10); + assert_eq!(a.g(), 20); + assert_eq!(a.h(), 30); +} + +pub fn main() { + let a = &A { x: 3 }; + f(a); +} diff --git a/tests/ui/traits/inheritance/call-bound-inherited.rs b/tests/ui/traits/inheritance/call-bound-inherited.rs new file mode 100644 index 000000000..37c2ff63c --- /dev/null +++ b/tests/ui/traits/inheritance/call-bound-inherited.rs @@ -0,0 +1,20 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } + +// Call a function on Foo, given a T: Bar +fn gg<T:Bar>(a: &T) -> isize { + a.f() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(gg(a), 10); +} diff --git a/tests/ui/traits/inheritance/call-bound-inherited2.rs b/tests/ui/traits/inheritance/call-bound-inherited2.rs new file mode 100644 index 000000000..8576d29f2 --- /dev/null +++ b/tests/ui/traits/inheritance/call-bound-inherited2.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } +trait Baz : Bar { fn h(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } +impl Baz for A { fn h(&self) -> isize { 30 } } + +// Call a function on Foo, given a T: Baz, +// which is inherited via Bar +fn gg<T:Baz>(a: &T) -> isize { + a.f() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(gg(a), 10); +} diff --git a/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs new file mode 100644 index 000000000..25159c1ad --- /dev/null +++ b/tests/ui/traits/inheritance/cast-without-call-to-supertrait.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] +// Testing that we can cast to a subtrait and call subtrait +// methods. Not testing supertrait methods + + +trait Foo { + fn f(&self) -> isize; +} + +trait Bar : Foo { + fn g(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} + +impl Bar for A { + fn g(&self) -> isize { 20 } +} + +pub fn main() { + let a = &A { x: 3 }; + let afoo = a as &dyn Foo; + let abar = a as &dyn Bar; + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); +} diff --git a/tests/ui/traits/inheritance/cast.rs b/tests/ui/traits/inheritance/cast.rs new file mode 100644 index 000000000..9070b9d1f --- /dev/null +++ b/tests/ui/traits/inheritance/cast.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(dead_code)] +// Testing that supertrait methods can be called on subtrait object types + + +trait Foo { + fn f(&self) -> isize; +} + +trait Bar : Foo { + fn g(&self) -> isize; +} + +struct A { + x: isize +} + +impl Foo for A { + fn f(&self) -> isize { 10 } +} + +impl Bar for A { + fn g(&self) -> isize { 20 } +} + +pub fn main() { + let a = &A { x: 3 }; + let afoo = a as &dyn Foo; + let abar = a as &dyn Bar; + assert_eq!(afoo.f(), 10); + assert_eq!(abar.g(), 20); + assert_eq!(abar.f(), 10); +} diff --git a/tests/ui/traits/inheritance/cross-trait-call-xc.rs b/tests/ui/traits/inheritance/cross-trait-call-xc.rs new file mode 100644 index 000000000..99fbb5c61 --- /dev/null +++ b/tests/ui/traits/inheritance/cross-trait-call-xc.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:xc_call.rs + + +extern crate xc_call as aux; + +use aux::Foo; + +trait Bar : Foo { + fn g(&self) -> isize; +} + +impl Bar for aux::A { + fn g(&self) -> isize { self.f() } +} + +pub fn main() { + let a = &aux::A { x: 3 }; + assert_eq!(a.g(), 10); +} diff --git a/tests/ui/traits/inheritance/cross-trait-call.rs b/tests/ui/traits/inheritance/cross-trait-call.rs new file mode 100644 index 000000000..512c928ca --- /dev/null +++ b/tests/ui/traits/inheritance/cross-trait-call.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } + +impl Bar for A { + // Testing that this impl can call the impl of Foo + fn g(&self) -> isize { self.f() } +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(a.g(), 10); +} diff --git a/tests/ui/traits/inheritance/diamond.rs b/tests/ui/traits/inheritance/diamond.rs new file mode 100644 index 000000000..32ad0fb4d --- /dev/null +++ b/tests/ui/traits/inheritance/diamond.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(dead_code)] +// B and C both require A, so D does as well, twice, but that's just fine + + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } +trait D: B + C { fn d(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } +impl D for S { fn d(&self) -> isize { 40 } } + +fn f<T:D>(x: &T) { + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); + assert_eq!(x.d(), 40); +} + +pub fn main() { + let value = &S { bogus: () }; + f(value); +} diff --git a/tests/ui/traits/inheritance/multiple-inheritors.rs b/tests/ui/traits/inheritance/multiple-inheritors.rs new file mode 100644 index 000000000..77ecbd8eb --- /dev/null +++ b/tests/ui/traits/inheritance/multiple-inheritors.rs @@ -0,0 +1,23 @@ +// run-pass +#![allow(dead_code)] + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } + +// Both B and C inherit from A +fn f<T:B + C>(x: &T) { + assert_eq!(x.a(), 10); + assert_eq!(x.b(), 20); + assert_eq!(x.c(), 30); +} + +pub fn main() { + f(&S { bogus: () }) +} diff --git a/tests/ui/traits/inheritance/multiple-params.rs b/tests/ui/traits/inheritance/multiple-params.rs new file mode 100644 index 000000000..8ff5ba541 --- /dev/null +++ b/tests/ui/traits/inheritance/multiple-params.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] + +trait A { fn a(&self) -> isize; } +trait B: A { fn b(&self) -> isize; } +trait C: A { fn c(&self) -> isize; } + +struct S { bogus: () } + +impl A for S { fn a(&self) -> isize { 10 } } +impl B for S { fn b(&self) -> isize { 20 } } +impl C for S { fn c(&self) -> isize { 30 } } + +// Multiple type params, multiple levels of inheritance +fn f<X:A,Y:B,Z:C>(x: &X, y: &Y, z: &Z) { + assert_eq!(x.a(), 10); + assert_eq!(y.a(), 10); + assert_eq!(y.b(), 20); + assert_eq!(z.a(), 10); + assert_eq!(z.c(), 30); +} + +pub fn main() { + let s = &S { bogus: () }; + f(s, s, s); +} diff --git a/tests/ui/traits/inheritance/num.rs b/tests/ui/traits/inheritance/num.rs new file mode 100644 index 000000000..3d63d78ca --- /dev/null +++ b/tests/ui/traits/inheritance/num.rs @@ -0,0 +1,13 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +// pretty-expanded FIXME #23616 + +pub trait NumExt: PartialEq + PartialOrd {} + +pub trait FloatExt: NumExt {} + +fn greater_than_one<T: NumExt>(n: &T) -> bool { loop {} } +fn greater_than_one_float<T: FloatExt>(n: &T) -> bool { loop {} } + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num0.rs b/tests/ui/traits/inheritance/num0.rs new file mode 100644 index 000000000..cee52542d --- /dev/null +++ b/tests/ui/traits/inheritance/num0.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] +// Extending Num and using inherited static methods + +// pretty-expanded FIXME #23616 + +use std::cmp::PartialOrd; + +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait Num { + fn from_int(i: isize) -> Self; + fn gt(&self, other: &Self) -> bool; +} + +pub trait NumExt: NumCast + PartialOrd { } + +fn greater_than_one<T:NumExt>(n: &T) -> bool { + n.gt(&NumCast::from(1).unwrap()) +} + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num1.rs b/tests/ui/traits/inheritance/num1.rs new file mode 100644 index 000000000..663dd3a5e --- /dev/null +++ b/tests/ui/traits/inheritance/num1.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(dead_code)] +// pretty-expanded FIXME #23616 + +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait NumExt: NumCast + PartialOrd { } + +fn greater_than_one<T:NumExt>(n: &T) -> bool { + *n > NumCast::from(1).unwrap() +} + +pub fn main() {} diff --git a/tests/ui/traits/inheritance/num2.rs b/tests/ui/traits/inheritance/num2.rs new file mode 100644 index 000000000..b713c66a3 --- /dev/null +++ b/tests/ui/traits/inheritance/num2.rs @@ -0,0 +1,86 @@ +// run-pass +// A more complex example of numeric extensions + +pub trait TypeExt {} + +impl TypeExt for u8 {} +impl TypeExt for u16 {} +impl TypeExt for u32 {} +impl TypeExt for u64 {} +impl TypeExt for usize {} + +impl TypeExt for i8 {} +impl TypeExt for i16 {} +impl TypeExt for i32 {} +impl TypeExt for i64 {} +impl TypeExt for isize {} + +impl TypeExt for f32 {} +impl TypeExt for f64 {} + + +pub trait NumExt: TypeExt + PartialEq + PartialOrd {} + +impl NumExt for u8 {} +impl NumExt for u16 {} +impl NumExt for u32 {} +impl NumExt for u64 {} +impl NumExt for usize {} + +impl NumExt for i8 {} +impl NumExt for i16 {} +impl NumExt for i32 {} +impl NumExt for i64 {} +impl NumExt for isize {} + +impl NumExt for f32 {} +impl NumExt for f64 {} + + +pub trait UnSignedExt: NumExt {} + +impl UnSignedExt for u8 {} +impl UnSignedExt for u16 {} +impl UnSignedExt for u32 {} +impl UnSignedExt for u64 {} +impl UnSignedExt for usize {} + + +pub trait SignedExt: NumExt {} + +impl SignedExt for i8 {} +impl SignedExt for i16 {} +impl SignedExt for i32 {} +impl SignedExt for i64 {} +impl SignedExt for isize {} + +impl SignedExt for f32 {} +impl SignedExt for f64 {} + + +pub trait IntegerExt: NumExt {} + +impl IntegerExt for u8 {} +impl IntegerExt for u16 {} +impl IntegerExt for u32 {} +impl IntegerExt for u64 {} +impl IntegerExt for usize {} + +impl IntegerExt for i8 {} +impl IntegerExt for i16 {} +impl IntegerExt for i32 {} +impl IntegerExt for i64 {} +impl IntegerExt for isize {} + + +pub trait FloatExt: NumExt {} + +impl FloatExt for f32 {} +impl FloatExt for f64 {} + + +fn test_float_ext<T:FloatExt>(n: T) { println!("{}", n < n) } + +pub fn main() { + test_float_ext(1f32); +} diff --git a/tests/ui/traits/inheritance/num3.rs b/tests/ui/traits/inheritance/num3.rs new file mode 100644 index 000000000..c40be6f83 --- /dev/null +++ b/tests/ui/traits/inheritance/num3.rs @@ -0,0 +1,19 @@ +// run-pass +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait NumExt: PartialEq + PartialOrd + NumCast {} + +impl NumExt for f32 {} +impl NumCast for f32 { + fn from(i: i32) -> Option<f32> { Some(i as f32) } +} + +fn num_eq_one<T: NumExt>(n: T) { + println!("{}", n == NumCast::from(1).unwrap()) +} + +pub fn main() { + num_eq_one(1f32); // you need to actually use the function to trigger the ICE +} diff --git a/tests/ui/traits/inheritance/num5.rs b/tests/ui/traits/inheritance/num5.rs new file mode 100644 index 000000000..f478618f7 --- /dev/null +++ b/tests/ui/traits/inheritance/num5.rs @@ -0,0 +1,26 @@ +// run-pass +// pretty-expanded FIXME #23616 + +pub trait NumCast: Sized { + fn from(i: i32) -> Option<Self>; +} + +pub trait NumExt: PartialEq + NumCast {} + +impl NumExt for f32 {} +impl NumExt for isize {} + +impl NumCast for f32 { + fn from(i: i32) -> Option<f32> { Some(i as f32) } +} +impl NumCast for isize { + fn from(i: i32) -> Option<isize> { Some(i as isize) } +} + +fn num_eq_one<T:NumExt>() -> T { + NumCast::from(1).unwrap() +} + +pub fn main() { + num_eq_one::<isize>(); // you need to actually use the function to trigger the ICE +} diff --git a/tests/ui/traits/inheritance/overloading-simple.rs b/tests/ui/traits/inheritance/overloading-simple.rs new file mode 100644 index 000000000..c306aa2cd --- /dev/null +++ b/tests/ui/traits/inheritance/overloading-simple.rs @@ -0,0 +1,27 @@ +// run-pass +#![allow(dead_code)] +use std::cmp::PartialEq; + +trait MyNum : PartialEq { } + +#[derive(Debug)] +struct MyInt { val: isize } + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> bool { + return x == y; +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y, z) = (mi(3), mi(5), mi(3)); + assert!(x != y); + assert_eq!(x, z); +} diff --git a/tests/ui/traits/inheritance/overloading-xc-exe.rs b/tests/ui/traits/inheritance/overloading-xc-exe.rs new file mode 100644 index 000000000..08778061b --- /dev/null +++ b/tests/ui/traits/inheritance/overloading-xc-exe.rs @@ -0,0 +1,20 @@ +// run-pass +// aux-build:overloading_xc.rs + + +extern crate overloading_xc; +use overloading_xc::{MyNum, MyInt}; + +fn f<T:MyNum>(x: T, y: T) -> (T, T, T) { + return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let (a, b, c) = f(x, y); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); +} diff --git a/tests/ui/traits/inheritance/overloading.rs b/tests/ui/traits/inheritance/overloading.rs new file mode 100644 index 000000000..083643e82 --- /dev/null +++ b/tests/ui/traits/inheritance/overloading.rs @@ -0,0 +1,47 @@ +// run-pass +use std::cmp::PartialEq; +use std::ops::{Add, Sub, Mul}; + +trait MyNum : Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + PartialEq + Clone { } + +#[derive(Clone, Debug)] +struct MyInt { val: isize } + +impl Add for MyInt { + type Output = MyInt; + + fn add(self, other: MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl Sub for MyInt { + type Output = MyInt; + + fn sub(self, other: MyInt) -> MyInt { mi(self.val - other.val) } +} + +impl Mul for MyInt { + type Output = MyInt; + + fn mul(self, other: MyInt) -> MyInt { mi(self.val * other.val) } +} + +impl PartialEq for MyInt { + fn eq(&self, other: &MyInt) -> bool { self.val == other.val } + fn ne(&self, other: &MyInt) -> bool { !self.eq(other) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> (T, T, T) { + return (x.clone() + y.clone(), x.clone() - y.clone(), x * y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let (a, b, c) = f(x, y); + assert_eq!(a, mi(8)); + assert_eq!(b, mi(-2)); + assert_eq!(c, mi(15)); +} diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs new file mode 100644 index 000000000..727897d20 --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.rs @@ -0,0 +1,43 @@ +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test then that when we don't give +// enough information to pick between these, no selection is made. In +// this particular case, the two choices are i64/u64 -- so when we use +// an integer literal, we wind up falling this literal back to i32. +// See also `run-pass/trait-repeated-supertrait.rs`. + +trait CompareTo<T> { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo<i64> + CompareTo<u64> { +} + +impl CompareTo<i64> for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo<u64> for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &dyn CompareToInts) -> bool { + c.same_as(22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfied +} + +fn with_trait<C:CompareToInts>(c: &C) -> bool { + c.same_as(22) //~ ERROR `C: CompareTo<i32>` is not satisfied +} + +fn with_ufcs1<C:CompareToInts>(c: &C) -> bool { + <dyn CompareToInts>::same_as(c, 22) //~ ERROR `dyn CompareToInts: CompareTo<i32>` is not satisfi +} + +fn with_ufcs2<C:CompareToInts>(c: &C) -> bool { + CompareTo::same_as(c, 22) //~ ERROR `C: CompareTo<i32>` is not satisfied +} + +fn main() { + assert_eq!(22_i64.same_as(22), true); //~ ERROR `i64: CompareTo<i32>` is not satisfied +} diff --git a/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr new file mode 100644 index 000000000..656e0d0bf --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait-ambig.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:26:15 + | +LL | c.same_as(22) + | ------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> + +error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:30:15 + | +LL | c.same_as(22) + | ------- ^^ the trait `CompareTo<i32>` is not implemented for `C` + | | + | required by a bound introduced by this call + | +help: consider further restricting this bound + | +LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool { + | ++++++++++++++++ + +error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:34:37 + | +LL | <dyn CompareToInts>::same_as(c, 22) + | ---------------------------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> + +error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:38:27 + | +LL | CompareTo::same_as(c, 22) + | ------------------ ^^ the trait `CompareTo<i32>` is not implemented for `C` + | | + | required by a bound introduced by this call + | +help: consider further restricting this bound + | +LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool { + | ++++++++++++++++ + +error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied + --> $DIR/repeated-supertrait-ambig.rs:42:31 + | +LL | assert_eq!(22_i64.same_as(22), true); + | ------- ^^ the trait `CompareTo<i32>` is not implemented for `i64` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `CompareTo<T>`: + <i64 as CompareTo<i64>> + <i64 as CompareTo<u64>> + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/inheritance/repeated-supertrait.rs b/tests/ui/traits/inheritance/repeated-supertrait.rs new file mode 100644 index 000000000..cb2581ffa --- /dev/null +++ b/tests/ui/traits/inheritance/repeated-supertrait.rs @@ -0,0 +1,48 @@ +// run-pass +// Test a case of a trait which extends the same supertrait twice, but +// with difference type parameters. Test that we can invoke the +// various methods in various ways successfully. +// See also `ui/traits/trait-repeated-supertrait-ambig.rs`. + + +trait CompareTo<T> { + fn same_as(&self, t: T) -> bool; +} + +trait CompareToInts : CompareTo<i64> + CompareTo<u64> { +} + +impl CompareTo<i64> for i64 { + fn same_as(&self, t: i64) -> bool { *self == t } +} + +impl CompareTo<u64> for i64 { + fn same_as(&self, t: u64) -> bool { *self == (t as i64) } +} + +impl CompareToInts for i64 { } + +fn with_obj(c: &dyn CompareToInts) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_trait<C:CompareToInts>(c: &C) -> bool { + c.same_as(22_i64) && c.same_as(22_u64) +} + +fn with_ufcs1<C:CompareToInts>(c: &C) -> bool { + <dyn CompareToInts>::same_as(c, 22_i64) && <dyn CompareToInts>::same_as(c, 22_u64) +} + +fn with_ufcs2<C:CompareToInts>(c: &C) -> bool { + CompareTo::same_as(c, 22_i64) && CompareTo::same_as(c, 22_u64) +} + +fn main() { + assert_eq!(22_i64.same_as(22_i64), true); + assert_eq!(22_i64.same_as(22_u64), true); + assert_eq!(with_trait(&22), true); + assert_eq!(with_obj(&22), true); + assert_eq!(with_ufcs1(&22), true); + assert_eq!(with_ufcs2(&22), true); +} diff --git a/tests/ui/traits/inheritance/self-in-supertype.rs b/tests/ui/traits/inheritance/self-in-supertype.rs new file mode 100644 index 000000000..e8a2bd791 --- /dev/null +++ b/tests/ui/traits/inheritance/self-in-supertype.rs @@ -0,0 +1,62 @@ +// run-pass +// Test for issue #4183: use of Self in supertraits. + +pub static FUZZY_EPSILON: f64 = 0.1; + +pub trait FuzzyEq<Eps> { + fn fuzzy_eq(&self, other: &Self) -> bool; + fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool; +} + +trait Float: Sized+FuzzyEq<Self> { + fn two_pi() -> Self; +} + +impl FuzzyEq<f32> for f32 { + fn fuzzy_eq(&self, other: &f32) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f32)) + } + + fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool { + (*self - *other).abs() < *epsilon + } +} + +impl Float for f32 { + fn two_pi() -> f32 { 6.28318530717958647692528676655900576_f32 } +} + +impl FuzzyEq<f64> for f64 { + fn fuzzy_eq(&self, other: &f64) -> bool { + self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f64)) + } + + fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool { + (*self - *other).abs() < *epsilon + } +} + +impl Float for f64 { + fn two_pi() -> f64 { 6.28318530717958647692528676655900576_f64 } +} + +fn compare<F:Float>(f1: F) -> bool { + let f2 = Float::two_pi(); + f1.fuzzy_eq(&f2) +} + +pub fn main() { + assert!(compare::<f32>(6.28318530717958647692528676655900576)); + assert!(compare::<f32>(6.29)); + assert!(compare::<f32>(6.3)); + assert!(compare::<f32>(6.19)); + assert!(!compare::<f32>(7.28318530717958647692528676655900576)); + assert!(!compare::<f32>(6.18)); + + assert!(compare::<f64>(6.28318530717958647692528676655900576)); + assert!(compare::<f64>(6.29)); + assert!(compare::<f64>(6.3)); + assert!(compare::<f64>(6.19)); + assert!(!compare::<f64>(7.28318530717958647692528676655900576)); + assert!(!compare::<f64>(6.18)); +} diff --git a/tests/ui/traits/inheritance/self.rs b/tests/ui/traits/inheritance/self.rs new file mode 100644 index 000000000..5f2559f48 --- /dev/null +++ b/tests/ui/traits/inheritance/self.rs @@ -0,0 +1,29 @@ +// run-pass +trait Foo<T> { + fn f(&self, x: &T); +} + +trait Bar : Sized + Foo<Self> { + fn g(&self); +} + +struct S { + x: isize +} + +impl Foo<S> for S { + fn f(&self, x: &S) { + println!("{}", x.x); + } +} + +impl Bar for S { + fn g(&self) { + self.f(self); + } +} + +pub fn main() { + let s = S { x: 1 }; + s.g(); +} diff --git a/tests/ui/traits/inheritance/simple.rs b/tests/ui/traits/inheritance/simple.rs new file mode 100644 index 000000000..ca3a284e5 --- /dev/null +++ b/tests/ui/traits/inheritance/simple.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +trait Foo { fn f(&self) -> isize; } +trait Bar : Foo { fn g(&self) -> isize; } + +struct A { x: isize } + +impl Foo for A { fn f(&self) -> isize { 10 } } +impl Bar for A { fn g(&self) -> isize { 20 } } + +fn ff<T:Foo>(a: &T) -> isize { + a.f() +} + +fn gg<T:Bar>(a: &T) -> isize { + a.g() +} + +pub fn main() { + let a = &A { x: 3 }; + assert_eq!(ff(a), 10); + assert_eq!(gg(a), 20); +} diff --git a/tests/ui/traits/inheritance/static.rs b/tests/ui/traits/inheritance/static.rs new file mode 100644 index 000000000..16218fbd2 --- /dev/null +++ b/tests/ui/traits/inheritance/static.rs @@ -0,0 +1,26 @@ +// run-pass + +pub trait MyNum { + fn from_int(_: isize) -> Self; +} + +pub trait NumExt: MyNum { } + +struct S { v: isize } + +impl MyNum for S { + fn from_int(i: isize) -> S { + S { + v: i + } + } +} + +impl NumExt for S { } + +fn greater_than_one<T:NumExt>() -> T { MyNum::from_int(1) } + +pub fn main() { + let v: S = greater_than_one(); + assert_eq!(v.v, 1); +} diff --git a/tests/ui/traits/inheritance/static2.rs b/tests/ui/traits/inheritance/static2.rs new file mode 100644 index 000000000..bc78e1e23 --- /dev/null +++ b/tests/ui/traits/inheritance/static2.rs @@ -0,0 +1,29 @@ +// run-pass +pub trait MyEq {} + +pub trait MyNum { + fn from_int(_: isize) -> Self; +} + +pub trait NumExt: MyEq + MyNum { } + +struct S { v: isize } + +impl MyEq for S { } + +impl MyNum for S { + fn from_int(i: isize) -> S { + S { + v: i + } + } +} + +impl NumExt for S { } + +fn greater_than_one<T:NumExt>() -> T { MyNum::from_int(1) } + +pub fn main() { + let v: S = greater_than_one(); + assert_eq!(v.v, 1); +} diff --git a/tests/ui/traits/inheritance/subst.rs b/tests/ui/traits/inheritance/subst.rs new file mode 100644 index 000000000..b2b650366 --- /dev/null +++ b/tests/ui/traits/inheritance/subst.rs @@ -0,0 +1,27 @@ +// run-pass + +pub trait Add<RHS,Result> { + fn add(&self, rhs: &RHS) -> Result; +} + +trait MyNum : Sized + Add<Self,Self> { } + +struct MyInt { val: isize } + +impl Add<MyInt, MyInt> for MyInt { + fn add(&self, other: &MyInt) -> MyInt { mi(self.val + other.val) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> T { + return x.add(&y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let z = f(x, y); + assert_eq!(z.val, 8) +} diff --git a/tests/ui/traits/inheritance/subst2.rs b/tests/ui/traits/inheritance/subst2.rs new file mode 100644 index 000000000..ccc9628c7 --- /dev/null +++ b/tests/ui/traits/inheritance/subst2.rs @@ -0,0 +1,37 @@ +// run-pass + +trait Panda<T> { + fn chomp(&self, bamboo: &T) -> T; +} + +trait Add<RHS,Result>: Panda<RHS> { + fn add(&self, rhs: &RHS) -> Result; +} + +trait MyNum : Sized + Add<Self,Self> { } + +struct MyInt { val: isize } + +impl Panda<MyInt> for MyInt { + fn chomp(&self, bamboo: &MyInt) -> MyInt { + mi(self.val + bamboo.val) + } +} + +impl Add<MyInt, MyInt> for MyInt { + fn add(&self, other: &MyInt) -> MyInt { self.chomp(other) } +} + +impl MyNum for MyInt {} + +fn f<T:MyNum>(x: T, y: T) -> T { + return x.add(&y).chomp(&y); +} + +fn mi(v: isize) -> MyInt { MyInt { val: v } } + +pub fn main() { + let (x, y) = (mi(3), mi(5)); + let z = f(x, y); + assert_eq!(z.val, 13); +} diff --git a/tests/ui/traits/inheritance/visibility.rs b/tests/ui/traits/inheritance/visibility.rs new file mode 100644 index 000000000..6ad864926 --- /dev/null +++ b/tests/ui/traits/inheritance/visibility.rs @@ -0,0 +1,20 @@ +// run-pass + +mod traits { + pub trait Foo { fn f(&self) -> isize; } + + impl Foo for isize { fn f(&self) -> isize { 10 } } +} + +trait Quux: traits::Foo { } +impl<T:traits::Foo> Quux for T { } + +// 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_eq!(x.f(), 10); +} + +pub fn main() { + f(&0) +} |