diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-27 01:33:01 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-27 18:56:16 +0300 |
| commit | 9be35f82c1abf2ecbab489bca9eca138ea648312 (patch) | |
| tree | 69888506e34af447d9748c0d542de3ba1dd76210 /src/test/ui/specialization | |
| parent | ca9faa52f5ada0054b1fa27d97aedf448afb059b (diff) | |
| download | rust-9be35f82c1abf2ecbab489bca9eca138ea648312.tar.gz rust-9be35f82c1abf2ecbab489bca9eca138ea648312.zip | |
tests: Move run-pass tests without naming conflicts to ui
Diffstat (limited to 'src/test/ui/specialization')
26 files changed, 954 insertions, 0 deletions
diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.rs b/src/test/ui/specialization/assoc-ty-graph-cycle.rs new file mode 100644 index 00000000000..54d51492ab3 --- /dev/null +++ b/src/test/ui/specialization/assoc-ty-graph-cycle.rs @@ -0,0 +1,25 @@ +// run-pass + +// Make sure we don't crash with a cycle error during coherence. + +#![feature(specialization)] + +trait Trait<T> { + type Assoc; +} + +impl<T> Trait<T> for Vec<T> { + default type Assoc = (); +} + +impl Trait<u8> for Vec<u8> { + type Assoc = u8; +} + +impl<T> Trait<T> for String { + type Assoc = (); +} + +impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {} + +fn main() {} diff --git a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs new file mode 100644 index 00000000000..5cf975b5752 --- /dev/null +++ b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs @@ -0,0 +1,38 @@ +#![feature(specialization)] + +// First, test only use of explicit `default` items: + +pub trait Foo { + fn foo(&self) -> bool; +} + +impl<T> Foo for T { + default fn foo(&self) -> bool { false } +} + +impl Foo for i32 {} + +impl Foo for i64 { + fn foo(&self) -> bool { true } +} + +// Next, test mixture of explicit `default` and provided methods: + +pub trait Bar { + fn bar(&self) -> i32 { 0 } +} + +impl<T> Bar for T {} // use the provided method + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl<T> Bar for Vec<T> { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec<i32> {} +impl Bar for Vec<i64> { + fn bar(&self) -> i32 { 3 } +} diff --git a/src/test/ui/specialization/auxiliary/go_trait.rs b/src/test/ui/specialization/auxiliary/go_trait.rs new file mode 100644 index 00000000000..aa0ec22896d --- /dev/null +++ b/src/test/ui/specialization/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go<G:Go>(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once<G:GoOnce>(this: G, arg: isize) { + this.go_once(arg) +} + +impl<G> GoMut for G + where G : Go +{ + default fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +impl<G> GoOnce for G + where G : GoMut +{ + default fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/src/test/ui/specialization/auxiliary/specialization_cross_crate.rs b/src/test/ui/specialization/auxiliary/specialization_cross_crate.rs new file mode 100644 index 00000000000..8caa8524fb9 --- /dev/null +++ b/src/test/ui/specialization/auxiliary/specialization_cross_crate.rs @@ -0,0 +1,72 @@ +#![feature(specialization)] + +pub trait Foo { + fn foo(&self) -> &'static str; +} + +impl<T> Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl<T: Clone> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl<T, U> Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl<T: Clone> Foo for (T, T) { + default fn foo(&self) -> &'static str { + "generic uniform pair" + } +} + +impl Foo for (u8, u32) { + default fn foo(&self) -> &'static str { + "(u8, u32)" + } +} + +impl Foo for (u8, u8) { + default fn foo(&self) -> &'static str { + "(u8, u8)" + } +} + +impl<T: Clone> Foo for Vec<T> { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec<i32> { + fn foo(&self) -> &'static str { + "Vec<i32>" + } +} + +impl Foo for String { + fn foo(&self) -> &'static str { + "String" + } +} + +impl Foo for i32 { + fn foo(&self) -> &'static str { + "i32" + } +} + +pub trait MyMarker {} +impl<T: Clone + MyMarker> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone + MyMarker" + } +} diff --git a/src/test/ui/specialization/cross-crate-defaults.rs b/src/test/ui/specialization/cross-crate-defaults.rs new file mode 100644 index 00000000000..79cb6594397 --- /dev/null +++ b/src/test/ui/specialization/cross-crate-defaults.rs @@ -0,0 +1,41 @@ +// run-pass + +// aux-build:cross_crates_defaults.rs + +#![feature(specialization)] + +extern crate cross_crates_defaults; + +use cross_crates_defaults::*; + +struct LocalDefault; +struct LocalOverride; + +impl Foo for LocalDefault {} + +impl Foo for LocalOverride { + fn foo(&self) -> bool { true } +} + +fn test_foo() { + assert!(!0i8.foo()); + assert!(!0i32.foo()); + assert!(0i64.foo()); + + assert!(!LocalDefault.foo()); + assert!(LocalOverride.foo()); +} + +fn test_bar() { + assert!(0u8.bar() == 0); + assert!(0i32.bar() == 1); + assert!("hello".bar() == 0); + assert!(vec![()].bar() == 2); + assert!(vec![0i32].bar() == 2); + assert!(vec![0i64].bar() == 3); +} + +fn main() { + test_foo(); + test_bar(); +} diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs new file mode 100644 index 00000000000..15550bcce2a --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] + +// aux-build:go_trait.rs + +#![feature(specialization)] + +extern crate go_trait; + +use go_trait::{Go,GoMut}; +use std::fmt::Debug; +use std::default::Default; + +struct MyThingy; + +impl Go for MyThingy { + fn go(&self, arg: isize) { } +} + +impl GoMut for MyThingy { + fn go_mut(&mut self, arg: isize) { } +} + +fn main() { } diff --git a/src/test/ui/specialization/defaultimpl/auxiliary/go_trait.rs b/src/test/ui/specialization/defaultimpl/auxiliary/go_trait.rs new file mode 100644 index 00000000000..c065593b432 --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/auxiliary/go_trait.rs @@ -0,0 +1,43 @@ +#![feature(specialization)] + +// Common code used for tests that model the Fn/FnMut/FnOnce hierarchy. + +pub trait Go { + fn go(&self, arg: isize); +} + +pub fn go<G:Go>(this: &G, arg: isize) { + this.go(arg) +} + +pub trait GoMut { + fn go_mut(&mut self, arg: isize); +} + +pub fn go_mut<G:GoMut>(this: &mut G, arg: isize) { + this.go_mut(arg) +} + +pub trait GoOnce { + fn go_once(self, arg: isize); +} + +pub fn go_once<G:GoOnce>(this: G, arg: isize) { + this.go_once(arg) +} + +default impl<G> GoMut for G + where G : Go +{ + fn go_mut(&mut self, arg: isize) { + go(&*self, arg) + } +} + +default impl<G> GoOnce for G + where G : GoMut +{ + fn go_once(mut self, arg: isize) { + go_mut(&mut self, arg) + } +} diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.rs b/src/test/ui/specialization/defaultimpl/out-of-order.rs new file mode 100644 index 00000000000..f9c73a19cfa --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/out-of-order.rs @@ -0,0 +1,19 @@ +// run-pass + +// Test that you can list the more specific impl before the more general one. + +#![feature(specialization)] + +trait Foo { + type Out; +} + +impl Foo for bool { + type Out = (); +} + +default impl<T> Foo for T { + type Out = bool; +} + +fn main() {} diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.rs b/src/test/ui/specialization/defaultimpl/overlap-projection.rs new file mode 100644 index 00000000000..ed38bb3fc3a --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/overlap-projection.rs @@ -0,0 +1,25 @@ +// run-pass + +// Test that impls on projected self types can resolve overlap, even when the +// projections involve specialization, so long as the associated type is +// provided by the most specialized impl. + +#![feature(specialization)] + +trait Assoc { + type Output; +} + +default impl<T> Assoc for T { + type Output = bool; +} + +impl Assoc for u8 { type Output = u8; } +impl Assoc for u16 { type Output = u16; } + +trait Foo {} +impl Foo for u32 {} +impl Foo for <u8 as Assoc>::Output {} +impl Foo for <u16 as Assoc>::Output {} + +fn main() {} diff --git a/src/test/ui/specialization/defaultimpl/projection.rs b/src/test/ui/specialization/defaultimpl/projection.rs new file mode 100644 index 00000000000..897a7aade2f --- /dev/null +++ b/src/test/ui/specialization/defaultimpl/projection.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] + +// Make sure we *can* project non-defaulted associated types +// cf compile-fail/specialization-default-projection.rs + +// First, do so without any use of specialization + +trait Foo { + type Assoc; +} + +impl<T> Foo for T { + type Assoc = (); +} + +fn generic_foo<T>() -> <T as Foo>::Assoc { + () +} + +// Next, allow for one layer of specialization + +trait Bar { + type Assoc; +} + +default impl<T> Bar for T { + type Assoc = (); +} + +impl<T: Clone> Bar for T { + type Assoc = u8; +} + +fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc { + 0u8 +} + +fn main() { +} diff --git a/src/test/ui/specialization/issue-50452.rs b/src/test/ui/specialization/issue-50452.rs new file mode 100644 index 00000000000..93f081d9558 --- /dev/null +++ b/src/test/ui/specialization/issue-50452.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(specialization)] + +pub trait Foo { + fn foo(); +} + +impl Foo for i32 {} +impl Foo for i64 {} +impl<T> Foo for T { + fn foo() {} +} + +fn main() { + i32::foo(); + i64::foo(); + u8::foo(); +} diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.rs b/src/test/ui/specialization/specialization-allowed-cross-crate.rs new file mode 100644 index 00000000000..15550bcce2a --- /dev/null +++ b/src/test/ui/specialization/specialization-allowed-cross-crate.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(unused_imports)] + +// aux-build:go_trait.rs + +#![feature(specialization)] + +extern crate go_trait; + +use go_trait::{Go,GoMut}; +use std::fmt::Debug; +use std::default::Default; + +struct MyThingy; + +impl Go for MyThingy { + fn go(&self, arg: isize) { } +} + +impl GoMut for MyThingy { + fn go_mut(&mut self, arg: isize) { } +} + +fn main() { } diff --git a/src/test/ui/specialization/specialization-assoc-fns.rs b/src/test/ui/specialization/specialization-assoc-fns.rs new file mode 100644 index 00000000000..b6a7a48972a --- /dev/null +++ b/src/test/ui/specialization/specialization-assoc-fns.rs @@ -0,0 +1,29 @@ +// run-pass + +// Test that non-method associated functions can be specialized + +#![feature(specialization)] + +trait Foo { + fn mk() -> Self; +} + +impl<T: Default> Foo for T { + default fn mk() -> T { + T::default() + } +} + +impl Foo for Vec<u8> { + fn mk() -> Vec<u8> { + vec![0] + } +} + +fn main() { + let v1: Vec<i32> = Foo::mk(); + let v2: Vec<u8> = Foo::mk(); + + assert!(v1.len() == 0); + assert!(v2.len() == 1); +} diff --git a/src/test/ui/specialization/specialization-basics.rs b/src/test/ui/specialization/specialization-basics.rs new file mode 100644 index 00000000000..6c359e51bc2 --- /dev/null +++ b/src/test/ui/specialization/specialization-basics.rs @@ -0,0 +1,98 @@ +// run-pass + +#![feature(specialization)] + +// Tests a variety of basic specialization scenarios and method +// dispatch for them. + +trait Foo { + fn foo(&self) -> &'static str; +} + +impl<T> Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl<T: Clone> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl<T, U> Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl<T: Clone> Foo for (T, T) { + default fn foo(&self) -> &'static str { + "generic uniform pair" + } +} + +impl Foo for (u8, u32) { + default fn foo(&self) -> &'static str { + "(u8, u32)" + } +} + +impl Foo for (u8, u8) { + default fn foo(&self) -> &'static str { + "(u8, u8)" + } +} + +impl<T: Clone> Foo for Vec<T> { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec<i32> { + fn foo(&self) -> &'static str { + "Vec<i32>" + } +} + +impl Foo for String { + fn foo(&self) -> &'static str { + "String" + } +} + +impl Foo for i32 { + fn foo(&self) -> &'static str { + "i32" + } +} + +struct NotClone; + +trait MyMarker {} +impl<T: Clone + MyMarker> Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone + MyMarker" + } +} + +#[derive(Clone)] +struct MarkedAndClone; +impl MyMarker for MarkedAndClone {} + +fn main() { + assert!(NotClone.foo() == "generic"); + assert!(0u8.foo() == "generic Clone"); + assert!(vec![NotClone].foo() == "generic"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec<i32>"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); + assert!(MarkedAndClone.foo() == "generic Clone + MyMarker"); +} diff --git a/src/test/ui/specialization/specialization-cross-crate-no-gate.rs b/src/test/ui/specialization/specialization-cross-crate-no-gate.rs new file mode 100644 index 00000000000..f744b16de7a --- /dev/null +++ b/src/test/ui/specialization/specialization-cross-crate-no-gate.rs @@ -0,0 +1,21 @@ +// run-pass + +// Test that specialization works even if only the upstream crate enables it + +// aux-build:specialization_cross_crate.rs + +extern crate specialization_cross_crate; + +use specialization_cross_crate::*; + +fn main() { + assert!(0u8.foo() == "generic Clone"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec<i32>"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); +} diff --git a/src/test/ui/specialization/specialization-cross-crate.rs b/src/test/ui/specialization/specialization-cross-crate.rs new file mode 100644 index 00000000000..fa63c866329 --- /dev/null +++ b/src/test/ui/specialization/specialization-cross-crate.rs @@ -0,0 +1,50 @@ +// run-pass + +// aux-build:specialization_cross_crate.rs + +#![feature(specialization)] + +extern crate specialization_cross_crate; + +use specialization_cross_crate::*; + +struct NotClone; + +#[derive(Clone)] +struct MarkedAndClone; +impl MyMarker for MarkedAndClone {} + +struct MyType<T>(T); +impl<T> Foo for MyType<T> { + default fn foo(&self) -> &'static str { + "generic MyType" + } +} + +impl Foo for MyType<u8> { + fn foo(&self) -> &'static str { + "MyType<u8>" + } +} + +struct MyOtherType; +impl Foo for MyOtherType {} + +fn main() { + assert!(NotClone.foo() == "generic"); + assert!(0u8.foo() == "generic Clone"); + assert!(vec![NotClone].foo() == "generic"); + assert!(vec![0u8].foo() == "generic Vec"); + assert!(vec![0i32].foo() == "Vec<i32>"); + assert!(0i32.foo() == "i32"); + assert!(String::new().foo() == "String"); + assert!(((), 0).foo() == "generic pair"); + assert!(((), ()).foo() == "generic uniform pair"); + assert!((0u8, 0u32).foo() == "(u8, u32)"); + assert!((0u8, 0u8).foo() == "(u8, u8)"); + assert!(MarkedAndClone.foo() == "generic Clone + MyMarker"); + + assert!(MyType(()).foo() == "generic MyType"); + assert!(MyType(0u8).foo() == "MyType<u8>"); + assert!(MyOtherType.foo() == "generic"); +} diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs new file mode 100644 index 00000000000..5d65a0457e7 --- /dev/null +++ b/src/test/ui/specialization/specialization-default-methods.rs @@ -0,0 +1,86 @@ +// run-pass + +#![feature(specialization)] + +// Test that default methods are cascaded correctly + +// First, test only use of explicit `default` items: + +trait Foo { + fn foo(&self) -> bool; +} + +// Specialization tree for Foo: +// +// T +// / \ +// i32 i64 + +impl<T> Foo for T { + default fn foo(&self) -> bool { false } +} + +impl Foo for i32 {} + +impl Foo for i64 { + fn foo(&self) -> bool { true } +} + +fn test_foo() { + assert!(!0i8.foo()); + assert!(!0i32.foo()); + assert!(0i64.foo()); +} + +// Next, test mixture of explicit `default` and provided methods: + +trait Bar { + fn bar(&self) -> i32 { 0 } +} + +// Specialization tree for Bar. +// Uses of $ designate that method is provided +// +// $Bar (the trait) +// | +// T +// /|\ +// / | \ +// / | \ +// / | \ +// / | \ +// / | \ +// $i32 &str $Vec<T> +// /\ +// / \ +// Vec<i32> $Vec<i64> + +// use the provided method +impl<T> Bar for T {} + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl<T> Bar for Vec<T> { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec<i32> {} +impl Bar for Vec<i64> { + fn bar(&self) -> i32 { 3 } +} + +fn test_bar() { + assert!(0u8.bar() == 0); + assert!(0i32.bar() == 1); + assert!("hello".bar() == 0); + assert!(vec![()].bar() == 2); + assert!(vec![0i32].bar() == 2); + assert!(vec![0i64].bar() == 3); +} + +fn main() { + test_foo(); + test_bar(); +} diff --git a/src/test/ui/specialization/specialization-on-projection.rs b/src/test/ui/specialization/specialization-on-projection.rs new file mode 100644 index 00000000000..5606eaea307 --- /dev/null +++ b/src/test/ui/specialization/specialization-on-projection.rs @@ -0,0 +1,24 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] + +// Ensure that specialization works for impls defined directly on a projection + +trait Foo<T> {} + +trait Assoc { + type Item; +} + +impl<T: Assoc> Foo<T::Item> for T {} + +struct Struct; + +impl Assoc for Struct { + type Item = u8; +} + +impl Foo<u8> for Struct {} + +fn main() {} diff --git a/src/test/ui/specialization/specialization-out-of-order.rs b/src/test/ui/specialization/specialization-out-of-order.rs new file mode 100644 index 00000000000..94e764f7636 --- /dev/null +++ b/src/test/ui/specialization/specialization-out-of-order.rs @@ -0,0 +1,19 @@ +// run-pass + +// Test that you can list the more specific impl before the more general one. + +#![feature(specialization)] + +trait Foo { + type Out; +} + +impl Foo for bool { + type Out = (); +} + +impl<T> Foo for T { + default type Out = bool; +} + +fn main() {} diff --git a/src/test/ui/specialization/specialization-overlap-projection.rs b/src/test/ui/specialization/specialization-overlap-projection.rs new file mode 100644 index 00000000000..00b83c7e7a1 --- /dev/null +++ b/src/test/ui/specialization/specialization-overlap-projection.rs @@ -0,0 +1,25 @@ +// run-pass + +// Test that impls on projected self types can resolve overlap, even when the +// projections involve specialization, so long as the associated type is +// provided by the most specialized impl. + +#![feature(specialization)] + +trait Assoc { + type Output; +} + +impl<T> Assoc for T { + default type Output = bool; +} + +impl Assoc for u8 { type Output = u8; } +impl Assoc for u16 { type Output = u16; } + +trait Foo {} +impl Foo for u32 {} +impl Foo for <u8 as Assoc>::Output {} +impl Foo for <u16 as Assoc>::Output {} + +fn main() {} diff --git a/src/test/ui/specialization/specialization-projection-alias.rs b/src/test/ui/specialization/specialization-projection-alias.rs new file mode 100644 index 00000000000..0081ed455c9 --- /dev/null +++ b/src/test/ui/specialization/specialization-projection-alias.rs @@ -0,0 +1,26 @@ +// run-pass +#![allow(dead_code)] +#![allow(unused_variables)] + +#![feature(specialization)] + +// Regression test for ICE when combining specialized associated types and type +// aliases + +trait Id_ { + type Out; +} + +type Id<T> = <T as Id_>::Out; + +impl<T> Id_ for T { + default type Out = T; +} + +fn test_proection() { + let x: Id<bool> = panic!(); +} + +fn main() { + +} diff --git a/src/test/ui/specialization/specialization-projection.rs b/src/test/ui/specialization/specialization-projection.rs new file mode 100644 index 00000000000..86cdccf131e --- /dev/null +++ b/src/test/ui/specialization/specialization-projection.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(dead_code)] + +#![feature(specialization)] + +// Make sure we *can* project non-defaulted associated types +// cf compile-fail/specialization-default-projection.rs + +// First, do so without any use of specialization + +trait Foo { + type Assoc; +} + +impl<T> Foo for T { + type Assoc = (); +} + +fn generic_foo<T>() -> <T as Foo>::Assoc { + () +} + +// Next, allow for one layer of specialization + +trait Bar { + type Assoc; +} + +impl<T> Bar for T { + default type Assoc = (); +} + +impl<T: Clone> Bar for T { + type Assoc = u8; +} + +fn generic_bar_clone<T: Clone>() -> <T as Bar>::Assoc { + 0u8 +} + +fn main() { +} diff --git a/src/test/ui/specialization/specialization-super-traits.rs b/src/test/ui/specialization/specialization-super-traits.rs new file mode 100644 index 00000000000..a0f71d87693 --- /dev/null +++ b/src/test/ui/specialization/specialization-super-traits.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(specialization)] + +// Test that you can specialize via an explicit trait hierarchy + +// FIXME: this doesn't work yet... + +trait Parent {} +trait Child: Parent {} + +trait Foo {} + +impl<T: Parent> Foo for T {} +impl<T: Child> Foo for T {} + +fn main() {} diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs new file mode 100644 index 00000000000..2e32e3ff02d --- /dev/null +++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs @@ -0,0 +1,33 @@ +// run-pass + +#![feature(specialization)] + +trait Iterator { + fn next(&self); +} + +trait WithAssoc { + type Item; +} + +impl<'a> WithAssoc for &'a () { + type Item = &'a u32; +} + +struct Cloned<I>(I); + +impl<'a, I, T: 'a> Iterator for Cloned<I> + where I: WithAssoc<Item=&'a T>, T: Clone +{ + fn next(&self) {} +} + +impl<'a, I, T: 'a> Iterator for Cloned<I> + where I: WithAssoc<Item=&'a T>, T: Copy +{ + +} + +fn main() { + Cloned(&()).next(); +} diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.rs b/src/test/ui/specialization/specialization-translate-projections-with-params.rs new file mode 100644 index 00000000000..bdc6501df44 --- /dev/null +++ b/src/test/ui/specialization/specialization-translate-projections-with-params.rs @@ -0,0 +1,32 @@ +// run-pass + +// Ensure that provided items are inherited properly even when impls vary in +// type parameters *and* rely on projections, and the type parameters are input +// types on the trait. + +#![feature(specialization)] + +trait Trait<T> { + fn convert(&self) -> T; +} +trait WithAssoc { + type Item; + fn as_item(&self) -> &Self::Item; +} + +impl<T, U> Trait<U> for T where T: WithAssoc<Item=U>, U: Clone { + fn convert(&self) -> U { + self.as_item().clone() + } +} + +impl WithAssoc for u8 { + type Item = u8; + fn as_item(&self) -> &u8 { self } +} + +impl Trait<u8> for u8 {} + +fn main() { + assert!(3u8.convert() == 3u8); +} diff --git a/src/test/ui/specialization/specialization-translate-projections.rs b/src/test/ui/specialization/specialization-translate-projections.rs new file mode 100644 index 00000000000..fcccb67902e --- /dev/null +++ b/src/test/ui/specialization/specialization-translate-projections.rs @@ -0,0 +1,33 @@ +// run-pass + +// Ensure that provided items are inherited properly even when impls vary in +// type parameters *and* rely on projections. + +#![feature(specialization)] + +use std::convert::Into; + +trait Trait { + fn to_u8(&self) -> u8; +} +trait WithAssoc { + type Item; + fn to_item(&self) -> Self::Item; +} + +impl<T, U> Trait for T where T: WithAssoc<Item=U>, U: Into<u8> { + fn to_u8(&self) -> u8 { + self.to_item().into() + } +} + +impl WithAssoc for u8 { + type Item = u8; + fn to_item(&self) -> u8 { *self } +} + +impl Trait for u8 {} + +fn main() { + assert!(3u8.to_u8() == 3u8); +} |
