diff options
| author | bors <bors@rust-lang.org> | 2018-02-16 00:03:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-02-16 00:03:10 +0000 |
| commit | efda9bae8788fdc68ea1d05be3c5b66d3e291961 (patch) | |
| tree | 424f318bc35d961925a61831e2a30eba54fc2163 | |
| parent | 1670a532dd769763f1d6ad9e5d624ec31361a098 (diff) | |
| parent | 220bb22e1b621ad5a10a44080e3e1872d99f3e9f (diff) | |
| download | rust-efda9bae8788fdc68ea1d05be3c5b66d3e291961.tar.gz rust-efda9bae8788fdc68ea1d05be3c5b66d3e291961.zip | |
Auto merge of #45404 - giannicic:defaultimpl2, r=nikomatsakis
#37653 support `default impl` for specialization
this commit implements the second part of the `default impl` feature:
> - a `default impl` need not include all items from the trait
> - a `default impl` alone does not mean that a type implements the trait
The first point allows rustc to compile and run something like this:
```
trait Foo {
fn foo_one(&self) -> &'static str;
fn foo_two(&self) -> &'static str;
}
default impl<T> Foo for T {
fn foo_one(&self) -> &'static str {
"generic"
}
}
struct MyStruct;
fn main() {
assert!(MyStruct.foo_one() == "generic");
}
```
but it shows a proper error if trying to call `MyStruct.foo_two()`
The second point allows a `default impl` to be considered as not implementing the `Trait` if it doesn't implement all the trait items.
The tests provided (in the compile-fail section) should cover all the possible trait resolutions.
Let me know if some tests is missed.
See [referenced ](https://github.com/rust-lang/rust/issues/37653) issue for further info
r? @nikomatsakis
17 files changed, 117 insertions, 703 deletions
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index d929d1d65a9..1a2da83429a 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -595,15 +595,15 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I> {} #[doc(hidden)] -default unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> +unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess<Item=&'a T>, T: Clone { - unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { + default unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item { self.it.get_unchecked(i).clone() } #[inline] - fn may_have_side_effect() -> bool { true } + default fn may_have_side_effect() -> bool { true } } #[doc(hidden)] diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 165b499cc62..9622e7b98f1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1395,7 +1395,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .map(|node_item| !node_item.node.is_from_trait()) .unwrap_or(false); - if !is_implemented { + if !is_implemented && !tcx.impl_is_default(impl_id) { if !trait_item.defaultness.has_value() { missing_items.push(trait_item); } else if associated_type_overridden { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d5328a18c22..1c8d22e4666 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1364,6 +1364,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let node = tcx.hir.get(node_id); let mut is_trait = None; + let mut is_default_impl_trait = None; let icx = ItemCtxt::new(tcx, def_id); let no_generics = hir::Generics::empty(); @@ -1373,8 +1374,13 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, NodeItem(item) => { match item.node { + ItemImpl(_, _, defaultness, ref generics, ..) => { + if defaultness.is_default() { + is_default_impl_trait = tcx.impl_trait_ref(def_id); + } + generics + } ItemFn(.., ref generics, _) | - ItemImpl(_, _, _, ref generics, ..) | ItemTy(_, ref generics) | ItemEnum(_, ref generics) | ItemStruct(_, ref generics) | @@ -1446,6 +1452,18 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, predicates.push(trait_ref.to_poly_trait_ref().to_predicate()); } + // In default impls, we can assume that the self type implements + // the trait. So in: + // + // default impl Foo for Bar { .. } + // + // we add a default where clause `Foo: Bar`. We do a similar thing for traits + // (see below). Recall that a default impl is not itself an impl, but rather a + // set of defaults that can be incorporated into another impl. + if let Some(trait_ref) = is_default_impl_trait { + predicates.push(trait_ref.to_poly_trait_ref().to_predicate()); + } + // Collect the region predicates that were declared inline as // well. In the case of parameters declared on a fn or method, we // have to be careful to only iterate over early-bound regions. diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-default-projection.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-default-projection.rs deleted file mode 100644 index ad55f44255b..00000000000 --- a/src/test/compile-fail/specialization/defaultimpl/specialization-default-projection.rs +++ /dev/null @@ -1,46 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(specialization)] - -// Make sure we can't project defaulted associated types - -trait Foo { - type Assoc; -} - -default impl<T> Foo for T { - type Assoc = (); -} - -impl Foo for u8 { - type Assoc = String; -} - -fn generic<T>() -> <T as Foo>::Assoc { - // `T` could be some downstream crate type that specializes (or, - // for that matter, `u8`). - - () //~ ERROR mismatched types -} - -fn monomorphic() -> () { - // Even though we know that `()` is not specialized in a - // downstream crate, typeck refuses to project here. - - generic::<()>() //~ ERROR mismatched types -} - -fn main() { - // No error here, we CAN project from `u8`, as there is no `default` - // in that impl. - let s: String = generic::<u8>(); - println!("{}", s); // bad news if this all compiles -} diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-default-types.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-default-types.rs deleted file mode 100644 index 7353f7ac8c5..00000000000 --- a/src/test/compile-fail/specialization/defaultimpl/specialization-default-types.rs +++ /dev/null @@ -1,45 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// It should not be possible to use the concrete value of a defaulted -// associated type in the impl defining it -- otherwise, what happens -// if it's overridden? - -#![feature(specialization)] - -trait Example { - type Output; - fn generate(self) -> Self::Output; -} - -default impl<T> Example for T { - type Output = Box<T>; - fn generate(self) -> Self::Output { - Box::new(self) //~ ERROR mismatched types - } -} - -impl Example for bool { - type Output = bool; - fn generate(self) -> bool { self } -} - -fn trouble<T>(t: T) -> Box<T> { - Example::generate(t) //~ ERROR mismatched types -} - -fn weaponize() -> bool { - let b: Box<bool> = trouble(true); - *b -} - -fn main() { - weaponize(); -} diff --git a/src/test/run-pass/specialization/defaultimpl/assoc-fns.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs index b99ba3d0f1c..eacec2e40f0 100644 --- a/src/test/run-pass/specialization/defaultimpl/assoc-fns.rs +++ b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs @@ -8,30 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that non-method associated functions can be specialized +// Tests that default impls do not have to supply all items but regular impls do. #![feature(specialization)] trait Foo { - fn mk() -> Self; + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; } -default impl<T: Default> Foo for T { - fn mk() -> T { - T::default() - } -} +struct MyStruct; -impl Foo for Vec<u8> { - fn mk() -> Vec<u8> { - vec![0] +default impl<T> Foo for T { + fn foo_one(&self) -> &'static str { + "generic" } } -fn main() { - let v1: Vec<i32> = Foo::mk(); - let v2: Vec<u8> = Foo::mk(); +impl Foo for MyStruct {} +//~^ ERROR not all trait items implemented, missing: `foo_two` [E0046] - assert!(v1.len() == 0); - assert!(v2.len() == 1); +fn main() { + println!("{}", MyStruct.foo_one()); } diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs new file mode 100644 index 00000000000..04ddf9ebb17 --- /dev/null +++ b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs @@ -0,0 +1,34 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that: +// - default impls do not have to supply all items and +// - a default impl does not count as an impl (in this case, an incomplete default impl). + +#![feature(specialization)] + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; +} + +struct MyStruct; + +default impl<T> Foo for T { + fn foo_one(&self) -> &'static str { + "generic" + } +} + + +fn main() { + println!("{}", MyStruct.foo_one()); + //~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope +} diff --git a/src/test/run-pass/specialization/defaultimpl/projection-alias.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs index 2397c3e2bff..445a59a373e 100644 --- a/src/test/run-pass/specialization/defaultimpl/projection-alias.rs +++ b/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,25 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(specialization)] - -// Regression test for ICE when combining specialized associated types and type -// aliases - -trait Id_ { - type Out; -} +// Tests that a default impl still has to have a WF trait ref. -type Id<T> = <T as Id_>::Out; - -default impl<T> Id_ for T { - type Out = T; -} +#![feature(specialization)] -fn test_proection() { - let x: Id<bool> = panic!(); -} +trait Foo<'a, T: Eq + 'a> { } -fn main() { +default impl<U> Foo<'static, U> for () {} +//~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied -} +fn main(){} diff --git a/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate.rs b/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate.rs deleted file mode 100644 index 71dd7c99009..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate.rs +++ /dev/null @@ -1,82 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(specialization)] - -pub trait Foo { - fn foo(&self) -> &'static str; -} - -default impl<T> Foo for T { - fn foo(&self) -> &'static str { - "generic" - } -} - -default impl<T: Clone> Foo for T { - fn foo(&self) -> &'static str { - "generic Clone" - } -} - -default impl<T, U> Foo for (T, U) where T: Clone, U: Clone { - fn foo(&self) -> &'static str { - "generic pair" - } -} - -default impl<T: Clone> Foo for (T, T) { - fn foo(&self) -> &'static str { - "generic uniform pair" - } -} - -default impl Foo for (u8, u32) { - fn foo(&self) -> &'static str { - "(u8, u32)" - } -} - -default impl Foo for (u8, u8) { - fn foo(&self) -> &'static str { - "(u8, u8)" - } -} - -default impl<T: Clone> Foo for Vec<T> { - 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 {} -default impl<T: Clone + MyMarker> Foo for T { - fn foo(&self) -> &'static str { - "generic Clone + MyMarker" - } -} diff --git a/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate_defaults.rs b/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate_defaults.rs deleted file mode 100644 index 9d0ea64fed4..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate_defaults.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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; -} - -default impl<T> Foo for T { - 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 {} - -default impl<T> Bar for Vec<T> { - 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/run-pass/specialization/defaultimpl/basics-unsafe.rs b/src/test/run-pass/specialization/defaultimpl/basics-unsafe.rs deleted file mode 100644 index 7daecc842f3..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/basics-unsafe.rs +++ /dev/null @@ -1,106 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(specialization)] - -// Tests a variety of basic specialization scenarios and method -// dispatch for them. - -unsafe trait Foo { - fn foo(&self) -> &'static str; -} - -default unsafe impl<T> Foo for T { - fn foo(&self) -> &'static str { - "generic" - } -} - -default unsafe impl<T: Clone> Foo for T { - fn foo(&self) -> &'static str { - "generic Clone" - } -} - -default unsafe impl<T, U> Foo for (T, U) where T: Clone, U: Clone { - fn foo(&self) -> &'static str { - "generic pair" - } -} - -default unsafe impl<T: Clone> Foo for (T, T) { - fn foo(&self) -> &'static str { - "generic uniform pair" - } -} - -default unsafe impl Foo for (u8, u32) { - fn foo(&self) -> &'static str { - "(u8, u32)" - } -} - -default unsafe impl Foo for (u8, u8) { - fn foo(&self) -> &'static str { - "(u8, u8)" - } -} - -default unsafe impl<T: Clone> Foo for Vec<T> { - fn foo(&self) -> &'static str { - "generic Vec" - } -} - -default unsafe impl Foo for Vec<i32> { - fn foo(&self) -> &'static str { - "Vec<i32>" - } -} - -default unsafe impl Foo for String { - fn foo(&self) -> &'static str { - "String" - } -} - -default unsafe impl Foo for i32 { - fn foo(&self) -> &'static str { - "i32" - } -} - -struct NotClone; - -unsafe trait MyMarker {} -default unsafe impl<T: Clone + MyMarker> Foo for T { - fn foo(&self) -> &'static str { - "generic Clone + MyMarker" - } -} - -#[derive(Clone)] -struct MarkedAndClone; -unsafe 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/run-pass/specialization/defaultimpl/basics.rs b/src/test/run-pass/specialization/defaultimpl/basics.rs deleted file mode 100644 index 594f1e4fcdf..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/basics.rs +++ /dev/null @@ -1,106 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(specialization)] - -// Tests a variety of basic specialization scenarios and method -// dispatch for them. - -trait Foo { - fn foo(&self) -> &'static str; -} - -default impl<T> Foo for T { - fn foo(&self) -> &'static str { - "generic" - } -} - -default impl<T: Clone> Foo for T { - fn foo(&self) -> &'static str { - "generic Clone" - } -} - -default impl<T, U> Foo for (T, U) where T: Clone, U: Clone { - fn foo(&self) -> &'static str { - "generic pair" - } -} - -default impl<T: Clone> Foo for (T, T) { - fn foo(&self) -> &'static str { - "generic uniform pair" - } -} - -default impl Foo for (u8, u32) { - fn foo(&self) -> &'static str { - "(u8, u32)" - } -} - -default impl Foo for (u8, u8) { - fn foo(&self) -> &'static str { - "(u8, u8)" - } -} - -default impl<T: Clone> Foo for Vec<T> { - 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 {} -default impl<T: Clone + MyMarker> Foo for T { - 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/run-pass/specialization/defaultimpl/cross-crate-defaults.rs b/src/test/run-pass/specialization/defaultimpl/cross-crate-defaults.rs deleted file mode 100644 index 19e1af15bdd..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/cross-crate-defaults.rs +++ /dev/null @@ -1,49 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:cross_crate_defaults.rs - -#![feature(specialization)] - -extern crate cross_crate_defaults; - -use cross_crate_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/run-pass/specialization/defaultimpl/cross-crate-no-gate.rs b/src/test/run-pass/specialization/defaultimpl/cross-crate-no-gate.rs deleted file mode 100644 index 67cc694ae12..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/cross-crate-no-gate.rs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that specialization works even if only the upstream crate enables it - -// aux-build:cross_crate.rs - -extern crate cross_crate; - -use 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/run-pass/specialization/defaultimpl/cross-crate.rs b/src/test/run-pass/specialization/defaultimpl/cross-crate.rs deleted file mode 100644 index f1ad105db8f..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/cross-crate.rs +++ /dev/null @@ -1,58 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:cross_crate.rs - -#![feature(specialization)] - -extern crate cross_crate; - -use cross_crate::*; - -struct NotClone; - -#[derive(Clone)] -struct MarkedAndClone; -impl MyMarker for MarkedAndClone {} - -struct MyType<T>(T); -default impl<T> Foo for MyType<T> { - 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/run-pass/specialization/defaultimpl/default-methods.rs b/src/test/run-pass/specialization/defaultimpl/default-methods.rs deleted file mode 100644 index 4ac9afc1c89..00000000000 --- a/src/test/run-pass/specialization/defaultimpl/default-methods.rs +++ /dev/null @@ -1,94 +0,0 @@ -// 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![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 - -default impl<T> Foo for T { - 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 {} - -default impl<T> Bar for Vec<T> { - 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/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs new file mode 100644 index 00000000000..fc731202005 --- /dev/null +++ b/src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs @@ -0,0 +1,42 @@ +// 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that we can combine a default impl that supplies one method with a +// full impl that supplies the other, and they can invoke one another. + +#![feature(specialization)] + +trait Foo { + fn foo_one(&self) -> &'static str; + fn foo_two(&self) -> &'static str; + fn foo_three(&self) -> &'static str; +} + +struct MyStruct; + +default impl<T> Foo for T { + fn foo_one(&self) -> &'static str { + self.foo_three() + } +} + +impl Foo for MyStruct { + fn foo_two(&self) -> &'static str { + self.foo_one() + } + + fn foo_three(&self) -> &'static str { + "generic" + } +} + +fn main() { + assert!(MyStruct.foo_two() == "generic"); +} |
