From 1077ff2deca4c80f27596905119a84564fe9813f Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Mon, 28 Dec 2015 15:40:11 -0800 Subject: [PATCH] Add basic specialization tests, including for default item inheritance. Updates some of the coherence tests as well. --- src/test/auxiliary/go_trait.rs | 4 +- .../auxiliary/specialization_cross_crate.rs | 80 ++++++++++++++ .../specialization_cross_crate_defaults.rs | 49 +++++++++ .../coherence-no-direct-lifetime-dispatch.rs | 18 +++ .../coherence-overlap-messages.rs | 24 ++-- .../specialization-negative-impl.rs | 23 ++++ .../specialization-overlap-negative.rs | 20 ++++ .../compile-fail/specialization-overlap.rs | 23 ++++ .../specialization-allowed-cross-crate.rs | 29 +++++ src/test/run-pass/specialization-assoc-fns.rs | 33 ++++++ src/test/run-pass/specialization-basics.rs | 104 ++++++++++++++++++ .../specialization-cross-crate-defaults.rs | 37 +++++++ .../run-pass/specialization-cross-crate.rs | 56 ++++++++++ .../specialization-default-methods.rs | 66 +++++++++++ .../run-pass/specialization-super-traits.rs | 23 ++++ 15 files changed, 570 insertions(+), 19 deletions(-) create mode 100644 src/test/auxiliary/specialization_cross_crate.rs create mode 100755 src/test/auxiliary/specialization_cross_crate_defaults.rs create mode 100644 src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs create mode 100644 src/test/compile-fail/specialization-negative-impl.rs create mode 100644 src/test/compile-fail/specialization-overlap-negative.rs create mode 100644 src/test/compile-fail/specialization-overlap.rs create mode 100644 src/test/run-pass/specialization-allowed-cross-crate.rs create mode 100644 src/test/run-pass/specialization-assoc-fns.rs create mode 100644 src/test/run-pass/specialization-basics.rs create mode 100644 src/test/run-pass/specialization-cross-crate-defaults.rs create mode 100644 src/test/run-pass/specialization-cross-crate.rs create mode 100644 src/test/run-pass/specialization-default-methods.rs create mode 100644 src/test/run-pass/specialization-super-traits.rs diff --git a/src/test/auxiliary/go_trait.rs b/src/test/auxiliary/go_trait.rs index 0a921c8f5b3a..ab1051c56501 100644 --- a/src/test/auxiliary/go_trait.rs +++ b/src/test/auxiliary/go_trait.rs @@ -37,7 +37,7 @@ pub fn go_once(this: G, arg: isize) { impl GoMut for G where G : Go { - fn go_mut(&mut self, arg: isize) { + default fn go_mut(&mut self, arg: isize) { go(&*self, arg) } } @@ -45,7 +45,7 @@ impl GoMut for G impl GoOnce for G where G : GoMut { - fn go_once(mut self, arg: isize) { + default fn go_once(mut self, arg: isize) { go_mut(&mut self, arg) } } diff --git a/src/test/auxiliary/specialization_cross_crate.rs b/src/test/auxiliary/specialization_cross_crate.rs new file mode 100644 index 000000000000..92c985a3e1dd --- /dev/null +++ b/src/test/auxiliary/specialization_cross_crate.rs @@ -0,0 +1,80 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Foo { + fn foo(&self) -> &'static str; +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl 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 Foo for Vec { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec { + fn foo(&self) -> &'static str { + "Vec" + } +} + +impl Foo for String { + fn foo(&self) -> &'static str { + "String" + } +} + +impl Foo for i32 { + fn foo(&self) -> &'static str { + "i32" + } +} + +pub trait MyMarker {} +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone + MyMarker" + } +} diff --git a/src/test/auxiliary/specialization_cross_crate_defaults.rs b/src/test/auxiliary/specialization_cross_crate_defaults.rs new file mode 100755 index 000000000000..b62d80b589fd --- /dev/null +++ b/src/test/auxiliary/specialization_cross_crate_defaults.rs @@ -0,0 +1,49 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +#![feature(specialization)] + +// First, test only use of explicit `default` items: + +pub trait Foo { + fn foo(&self) -> bool; +} + +impl 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 Bar for T {} // use the provided method + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl Bar for Vec { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec {} +impl Bar for Vec { + fn bar(&self) -> i32 { 3 } +} diff --git a/src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs b/src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs new file mode 100644 index 000000000000..6de338f1db0f --- /dev/null +++ b/src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that you cannot *directly* dispatch on lifetime requirements + +trait MyTrait {} + +impl MyTrait for T {} +impl MyTrait for T {} //~ ERROR E0119 + +fn main() {} diff --git a/src/test/compile-fail/coherence-overlap-messages.rs b/src/test/compile-fail/coherence-overlap-messages.rs index 4f1092f960e0..2a54ad88055e 100644 --- a/src/test/compile-fail/coherence-overlap-messages.rs +++ b/src/test/compile-fail/coherence-overlap-messages.rs @@ -15,28 +15,18 @@ impl Foo for U {} trait Bar {} -impl Bar for T {} //~ ERROR conflicting implementations of trait `Bar` for type `u8`: -impl Bar for u8 {} +impl Bar for (T, u8) {} //~ ERROR conflicting implementations of trait `Bar` for type `(u8, u8)`: +impl Bar for (u8, T) {} trait Baz {} -impl Baz for T {} //~ ERROR conflicting implementations of trait `Baz<_>` for type `u8`: +impl Baz for T {} //~ ERROR conflicting implementations of trait `Baz` for type `u8`: impl Baz for u8 {} -trait Quux {} +trait Quux {} -impl Quux for T {} //~ ERROR conflicting implementations of trait `Quux<_>`: -impl Quux for T {} - -trait Qaar {} - -impl Qaar for T {} //~ ERROR conflicting implementations of trait `Qaar`: -impl Qaar for T {} - -trait Qaax {} - -impl Qaax for T {} -//~^ ERROR conflicting implementations of trait `Qaax` for type `u32`: -impl Qaax for u32 {} +impl Quux for T {} //~ ERROR conflicting implementations of trait `Quux<_, _>`: +impl Quux for T {} +impl Quux for T {} fn main() {} diff --git a/src/test/compile-fail/specialization-negative-impl.rs b/src/test/compile-fail/specialization-negative-impl.rs new file mode 100644 index 000000000000..d0d698d12e09 --- /dev/null +++ b/src/test/compile-fail/specialization-negative-impl.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +struct TestType(T); + +unsafe impl Send for TestType {} +impl !Send for TestType {} + +fn assert_send() {} + +fn main() { + assert_send::>(); + assert_send::>(); //~ ERROR +} diff --git a/src/test/compile-fail/specialization-overlap-negative.rs b/src/test/compile-fail/specialization-overlap-negative.rs new file mode 100644 index 000000000000..cc427b4fed21 --- /dev/null +++ b/src/test/compile-fail/specialization-overlap-negative.rs @@ -0,0 +1,20 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(optin_builtin_traits)] + +trait MyTrait {} + +struct TestType(::std::marker::PhantomData); + +unsafe impl Send for TestType {} +impl !Send for TestType {} //~ ERROR E0119 + +fn main() {} diff --git a/src/test/compile-fail/specialization-overlap.rs b/src/test/compile-fail/specialization-overlap.rs new file mode 100644 index 000000000000..7d14e85fba83 --- /dev/null +++ b/src/test/compile-fail/specialization-overlap.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo {} +impl Foo for T {} +impl Foo for Vec {} //~ ERROR E0119 + +trait Bar {} +impl Bar for (T, u8) {} +impl Bar for (u8, T) {} //~ ERROR E0119 + +trait Baz {} +impl Baz for u8 {} +impl Baz for T {} //~ ERROR E0119 + +fn main() {} diff --git a/src/test/run-pass/specialization-allowed-cross-crate.rs b/src/test/run-pass/specialization-allowed-cross-crate.rs new file mode 100644 index 000000000000..139c63d3cdb4 --- /dev/null +++ b/src/test/run-pass/specialization-allowed-cross-crate.rs @@ -0,0 +1,29 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:go_trait.rs + +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/run-pass/specialization-assoc-fns.rs b/src/test/run-pass/specialization-assoc-fns.rs new file mode 100644 index 000000000000..750581ffe923 --- /dev/null +++ b/src/test/run-pass/specialization-assoc-fns.rs @@ -0,0 +1,33 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + fn mk() -> Self; +} + +impl Foo for T { + default fn mk() -> T { + T::default() + } +} + +impl Foo for Vec { + fn mk() -> Vec { + vec![0] + } +} + +fn main() { + let v1: Vec = Foo::mk(); + let v2: Vec = Foo::mk(); + + assert!(v1.len() == 0); + assert!(v2.len() == 1); +} diff --git a/src/test/run-pass/specialization-basics.rs b/src/test/run-pass/specialization-basics.rs new file mode 100644 index 000000000000..e585c8e23535 --- /dev/null +++ b/src/test/run-pass/specialization-basics.rs @@ -0,0 +1,104 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests a variety of basic specialization scenarios and method +// dispatch for them. + +trait Foo { + fn foo(&self) -> &'static str; +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic" + } +} + +impl Foo for T { + default fn foo(&self) -> &'static str { + "generic Clone" + } +} + +impl Foo for (T, U) where T: Clone, U: Clone { + default fn foo(&self) -> &'static str { + "generic pair" + } +} + +impl 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 Foo for Vec { + default fn foo(&self) -> &'static str { + "generic Vec" + } +} + +impl Foo for Vec { + fn foo(&self) -> &'static str { + "Vec" + } +} + +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 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"); + 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/run-pass/specialization-cross-crate-defaults.rs b/src/test/run-pass/specialization-cross-crate-defaults.rs new file mode 100644 index 000000000000..750c3cf8b3ec --- /dev/null +++ b/src/test/run-pass/specialization-cross-crate-defaults.rs @@ -0,0 +1,37 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:specialization_cross_crate_defaults.rs + +#![feature(specialization)] + +extern crate specialization_cross_crate_defaults; + +use specialization_cross_crate_defaults::*; + +fn test_foo() { + assert!(0i8.foo() == false); + assert!(0i32.foo() == false); + assert!(0i64.foo() == true); +} + +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/run-pass/specialization-cross-crate.rs b/src/test/run-pass/specialization-cross-crate.rs new file mode 100644 index 000000000000..c74b1f2e49e4 --- /dev/null +++ b/src/test/run-pass/specialization-cross-crate.rs @@ -0,0 +1,56 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:specialization_cross_crate.rs + +extern crate specialization_cross_crate; + +use specialization_cross_crate::*; + +struct NotClone; + +#[derive(Clone)] +struct MarkedAndClone; +impl MyMarker for MarkedAndClone {} + +struct MyType(T); +impl Foo for MyType { + default fn foo(&self) -> &'static str { + "generic MyType" + } +} + +impl Foo for MyType { + fn foo(&self) -> &'static str { + "MyType" + } +} + +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"); + 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"); + assert!(MyOtherType.foo() == "generic"); +} diff --git a/src/test/run-pass/specialization-default-methods.rs b/src/test/run-pass/specialization-default-methods.rs new file mode 100644 index 000000000000..7482d3acbc1a --- /dev/null +++ b/src/test/run-pass/specialization-default-methods.rs @@ -0,0 +1,66 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// First, test only use of explicit `default` items: + +trait Foo { + fn foo(&self) -> bool; +} + +impl 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() == false); + assert!(0i32.foo() == false); + assert!(0i64.foo() == true); +} + +// Next, test mixture of explicit `default` and provided methods: + +trait Bar { + fn bar(&self) -> i32 { 0 } +} + +impl Bar for T {} // use the provided method + +impl Bar for i32 { + fn bar(&self) -> i32 { 1 } +} +impl<'a> Bar for &'a str {} + +impl Bar for Vec { + default fn bar(&self) -> i32 { 2 } +} +impl Bar for Vec {} +impl Bar for Vec { + 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/run-pass/specialization-super-traits.rs b/src/test/run-pass/specialization-super-traits.rs new file mode 100644 index 000000000000..4a30e6bcd25f --- /dev/null +++ b/src/test/run-pass/specialization-super-traits.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that you can specialize via an explicit trait hierarchy + +// FIXME: this doesn't work yet... + +trait Parent {} +trait Child: Parent {} + +trait Foo {} + +impl Foo for T {} +impl Foo for T {} + +fn main() {}