about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/check/wfcheck.rs11
-rw-r--r--src/test/run-pass/defaults-well-formedness.rs2
-rw-r--r--src/test/ui/type-check-defaults.rs3
-rw-r--r--src/test/ui/type-check-defaults.stderr36
4 files changed, 22 insertions, 30 deletions
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 258860d3d5e..4eb3e29ec69 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -363,13 +363,16 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
         let generics = self.tcx.generics_of(def_id);
         let is_our_default = |def: &ty::TypeParameterDef|
                                 def.has_default && def.index >= generics.parent_count() as u32;
-        let defaulted_params = generics.types.iter().cloned().filter(&is_our_default);
-        // Check that defaults are well-formed. See test `type-check-defaults.rs`.
+
+        // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
         // For example this forbids the declaration:
         // struct Foo<T = Vec<[u32]>> { .. }
         // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
-        for d in defaulted_params.map(|p| p.def_id) {
-            fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
+        for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
+            let ty = fcx.tcx.type_of(d);
+            if !ty.needs_subst() {
+                fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone());
+            }
         }
 
         // Check that trait predicates are WF when params are substituted by their defaults.
diff --git a/src/test/run-pass/defaults-well-formedness.rs b/src/test/run-pass/defaults-well-formedness.rs
index 552665bac4e..f3594679095 100644
--- a/src/test/run-pass/defaults-well-formedness.rs
+++ b/src/test/run-pass/defaults-well-formedness.rs
@@ -24,5 +24,7 @@ struct DefaultedLhs<U, V=i32>(U, V) where V: Trait<U>;
 // Dependent defaults are not checked.
 struct Dependent<T, U = T>(T, U) where U: Copy;
 trait SelfBound<T: Copy=Self> {}
+// Not even for well-formedness.
+struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
 
 fn main() {}
diff --git a/src/test/ui/type-check-defaults.rs b/src/test/ui/type-check-defaults.rs
index 65560df9f21..f916df5d32d 100644
--- a/src/test/ui/type-check-defaults.rs
+++ b/src/test/ui/type-check-defaults.rs
@@ -18,9 +18,6 @@ struct WellFormed<Z = Foo<i32, i32>>(Z);
 struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
 //~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
 
-struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
-//~^ error: the trait bound `A: std::iter::Iterator` is not satisfied [E0277]
-
 struct Bounds<T:Copy=String>(T);
 //~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
 
diff --git a/src/test/ui/type-check-defaults.stderr b/src/test/ui/type-check-defaults.stderr
index c73c0792f8e..4af8f5da0dd 100644
--- a/src/test/ui/type-check-defaults.stderr
+++ b/src/test/ui/type-check-defaults.stderr
@@ -24,61 +24,51 @@ note: required by `Foo`
 15 | struct Foo<T, U: FromIterator<T>>(T, U);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
-  --> $DIR/type-check-defaults.rs:21:32
-   |
-21 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
-   |                                ^ `A` is not an iterator; maybe try calling `.iter()` or a similar method
-   |
-   = help: the trait `std::iter::Iterator` is not implemented for `A`
-   = help: consider adding a `where A: std::iter::Iterator` bound
-   = note: required by `std::iter::Iterator`
-
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
-  --> $DIR/type-check-defaults.rs:24:1
+  --> $DIR/type-check-defaults.rs:21:1
    |
-24 | struct Bounds<T:Copy=String>(T);
+21 | struct Bounds<T:Copy=String>(T);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
    |
    = note: required by `std::marker::Copy`
 
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
-  --> $DIR/type-check-defaults.rs:27:1
+  --> $DIR/type-check-defaults.rs:24:1
    |
-27 | struct WhereClause<T=String>(T) where T: Copy;
+24 | struct WhereClause<T=String>(T) where T: Copy;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
    |
    = note: required by `std::marker::Copy`
 
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
-  --> $DIR/type-check-defaults.rs:30:1
+  --> $DIR/type-check-defaults.rs:27:1
    |
-30 | trait TraitBound<T:Copy=String> {}
+27 | trait TraitBound<T:Copy=String> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
    |
    = note: required by `std::marker::Copy`
 
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
-  --> $DIR/type-check-defaults.rs:34:1
+  --> $DIR/type-check-defaults.rs:31:1
    |
-34 | trait Base<T = String>: Super<T> { }
+31 | trait Base<T = String>: Super<T> { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = help: consider adding a `where T: std::marker::Copy` bound
 note: required by `Super`
-  --> $DIR/type-check-defaults.rs:33:1
+  --> $DIR/type-check-defaults.rs:30:1
    |
-33 | trait Super<T: Copy> { }
+30 | trait Super<T: Copy> { }
    | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: cannot add `u8` to `i32`
-  --> $DIR/type-check-defaults.rs:37:1
+  --> $DIR/type-check-defaults.rs:34:1
    |
-37 | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+34 | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
    |
    = help: the trait `std::ops::Add<u8>` is not implemented for `i32`
    = note: required by `std::ops::Add`
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors