about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-02-16 00:03:10 +0000
committerbors <bors@rust-lang.org>2018-02-16 00:03:10 +0000
commitefda9bae8788fdc68ea1d05be3c5b66d3e291961 (patch)
tree424f318bc35d961925a61831e2a30eba54fc2163
parent1670a532dd769763f1d6ad9e5d624ec31361a098 (diff)
parent220bb22e1b621ad5a10a44080e3e1872d99f3e9f (diff)
downloadrust-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
-rw-r--r--src/libcore/iter/mod.rs6
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/collect.rs20
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-default-projection.rs46
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-default-types.rs45
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs (renamed from src/test/run-pass/specialization/defaultimpl/assoc-fns.rs)26
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs34
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs (renamed from src/test/run-pass/specialization/defaultimpl/projection-alias.rs)26
-rw-r--r--src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate.rs82
-rw-r--r--src/test/run-pass/specialization/defaultimpl/auxiliary/cross_crate_defaults.rs49
-rw-r--r--src/test/run-pass/specialization/defaultimpl/basics-unsafe.rs106
-rw-r--r--src/test/run-pass/specialization/defaultimpl/basics.rs106
-rw-r--r--src/test/run-pass/specialization/defaultimpl/cross-crate-defaults.rs49
-rw-r--r--src/test/run-pass/specialization/defaultimpl/cross-crate-no-gate.rs29
-rw-r--r--src/test/run-pass/specialization/defaultimpl/cross-crate.rs58
-rw-r--r--src/test/run-pass/specialization/defaultimpl/default-methods.rs94
-rw-r--r--src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs42
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");
+}