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
This commit is contained in:
commit
efda9bae87
@ -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)]
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
|
||||
default impl<T> Foo for T {
|
||||
fn foo_one(&self) -> &'static str {
|
||||
"generic"
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo for Vec<u8> {
|
||||
fn mk() -> Vec<u8> {
|
||||
vec![0]
|
||||
}
|
||||
}
|
||||
impl Foo for MyStruct {}
|
||||
//~^ ERROR not all trait items implemented, missing: `foo_two` [E0046]
|
||||
|
||||
fn main() {
|
||||
let v1: Vec<i32> = Foo::mk();
|
||||
let v2: Vec<u8> = Foo::mk();
|
||||
|
||||
assert!(v1.len() == 0);
|
||||
assert!(v2.len() == 1);
|
||||
println!("{}", MyStruct.foo_one());
|
||||
}
|
@ -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
|
||||
}
|
@ -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.
|
||||
|
||||
// Tests that a default impl still has to have a WF trait ref.
|
||||
|
||||
#![feature(specialization)]
|
||||
|
||||
// Regression test for ICE when combining specialized associated types and type
|
||||
// aliases
|
||||
trait Foo<'a, T: Eq + 'a> { }
|
||||
|
||||
trait Id_ {
|
||||
type Out;
|
||||
}
|
||||
default impl<U> Foo<'static, U> for () {}
|
||||
//~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied
|
||||
|
||||
type Id<T> = <T as Id_>::Out;
|
||||
|
||||
default impl<T> Id_ for T {
|
||||
type Out = T;
|
||||
}
|
||||
|
||||
fn test_proection() {
|
||||
let x: Id<bool> = panic!();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
fn main(){}
|
@ -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"
|
||||
}
|
||||
}
|
@ -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 }
|
||||
}
|
@ -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");
|
||||
}
|
@ -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");
|
||||
}
|
@ -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();
|
||||
}
|
@ -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)");
|
||||
}
|
@ -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");
|
||||
}
|
@ -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();
|
||||
}
|
@ -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");
|
||||
}
|
Loading…
Reference in New Issue
Block a user