about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/check/wfcheck.rs19
-rw-r--r--src/test/run-pass/defaults-well-formedness.rs14
-rw-r--r--src/test/ui/type-check-defaults.rs11
-rw-r--r--src/test/ui/type-check-defaults.stderr36
4 files changed, 57 insertions, 23 deletions
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 0a919eb3b8c..a16b806b6f1 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -387,7 +387,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
             let d = param_def.def_id;
             fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
             // Check the clauses are well-formed when the param is substituted by it's default.
-            // In trait definitions, predicates as `Self: Trait` and `Self: Super` are problematic.
+            // In trait definitions, the predicate `Self: Trait` is problematic.
             // Therefore we skip such predicates. This means we check less than we could.
             for pred in predicates.predicates.iter().filter(|p| !(is_trait && p.has_self_ty())) {
                 let mut skip = true;
@@ -418,9 +418,20 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
                         }
                     }
                 });
-                if !skip {
-                    substituted_predicates.push(pred.subst(fcx.tcx, substs));
-                }
+                if skip { continue; }
+                substituted_predicates.push(match pred {
+                    // In trait predicates, substitute defaults only for the LHS.
+                    ty::Predicate::Trait(trait_pred) => {
+                        let t_pred = trait_pred.skip_binder();
+                        let self_ty = t_pred.self_ty().subst(fcx.tcx, substs);
+                        let mut trait_substs = t_pred.trait_ref.substs.to_vec();
+                        trait_substs[0] = self_ty.into();
+                        let trait_ref = ty::TraitRef::new(t_pred.def_id(),
+                                                          fcx.tcx.intern_substs(&trait_substs));
+                        ty::Predicate::Trait(ty::Binder(trait_ref).to_poly_trait_predicate())
+                    }
+                    _ => pred.subst(fcx.tcx, substs)
+                });
             }
         }
 
diff --git a/src/test/run-pass/defaults-well-formedness.rs b/src/test/run-pass/defaults-well-formedness.rs
new file mode 100644
index 00000000000..92c7f8731ba
--- /dev/null
+++ b/src/test/run-pass/defaults-well-formedness.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 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.
+
+trait Trait<T> {}
+struct Foo<U, V=i32>(U, V) where U: Trait<V>;
+
+fn main() {}
diff --git a/src/test/ui/type-check-defaults.rs b/src/test/ui/type-check-defaults.rs
index a6e475eb1a3..7c379a1f1bc 100644
--- a/src/test/ui/type-check-defaults.rs
+++ b/src/test/ui/type-check-defaults.rs
@@ -7,7 +7,6 @@
 // <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.
-// compile-flags: --error-format=human
 
 use std::iter::FromIterator;
 use std::vec::IntoIter;
@@ -15,24 +14,34 @@ use std::ops::Add;
 
 struct Foo<T, U: FromIterator<T>>(T, U);
 struct WellFormed<Z = Foo<i32, i32>>(Z);
+//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
 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]
 
 struct WhereClause<T=String>(T) where T: Copy;
+//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
 
 trait TraitBound<T:Copy=String> {}
+//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
 
 trait SelfBound<T:Copy=Self> {}
+//~^ error: the trait bound `Self: std::marker::Copy` is not satisfied [E0277]
 
 trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+//~^ error: the trait bound `i32: std::ops::Add<u8>` is not satisfied [E0277]
 
 trait Trait {}
 struct TwoParams<T, U>(T, U);
 impl Trait for TwoParams<i32, i32> {}
 // Check that each default is substituted individually in the clauses.
 struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
+//~^ error: the trait bound `TwoParams<i32, U>: Trait` is not satisfied [E0277]
+//~^^ error: the trait bound `TwoParams<T, i32>: Trait` is not satisfied [E0277]
 
 fn main() { }
diff --git a/src/test/ui/type-check-defaults.stderr b/src/test/ui/type-check-defaults.stderr
index cf11282f7d2..3ac6e4c26b4 100644
--- a/src/test/ui/type-check-defaults.stderr
+++ b/src/test/ui/type-check-defaults.stderr
@@ -1,7 +1,7 @@
 error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
-  --> $DIR/type-check-defaults.rs:17:19
+  --> $DIR/type-check-defaults.rs:16:19
    |
-17 | struct WellFormed<Z = Foo<i32, i32>>(Z);
+16 | struct WellFormed<Z = Foo<i32, i32>>(Z);
    |                   ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
    |
    = help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
@@ -17,69 +17,69 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfi
    = note: required by `Foo`
 
 error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
-  --> $DIR/type-check-defaults.rs:20:1
+  --> $DIR/type-check-defaults.rs:21:1
    |
-20 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
+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
 
 error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
-  --> $DIR/type-check-defaults.rs:22:1
+  --> $DIR/type-check-defaults.rs:24:1
    |
-22 | struct Bounds<T:Copy=String>(T);
+24 | 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:24:1
+  --> $DIR/type-check-defaults.rs:27:1
    |
-24 | struct WhereClause<T=String>(T) where T: Copy;
+27 | 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:26:1
+  --> $DIR/type-check-defaults.rs:30:1
    |
-26 | trait TraitBound<T:Copy=String> {}
+30 | 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 `Self: std::marker::Copy` is not satisfied
-  --> $DIR/type-check-defaults.rs:28:1
+  --> $DIR/type-check-defaults.rs:33:1
    |
-28 | trait SelfBound<T:Copy=Self> {}
+33 | trait SelfBound<T:Copy=Self> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `Self`
    |
    = help: consider adding a `where Self: std::marker::Copy` bound
    = note: required by `std::marker::Copy`
 
 error[E0277]: the trait bound `i32: std::ops::Add<u8>` is not satisfied
-  --> $DIR/type-check-defaults.rs:30:1
+  --> $DIR/type-check-defaults.rs:36:1
    |
-30 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+36 | trait FooTrait<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[E0277]: the trait bound `TwoParams<i32, U>: Trait` is not satisfied
-  --> $DIR/type-check-defaults.rs:36:1
+  --> $DIR/type-check-defaults.rs:43:1
    |
-36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
+43 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<i32, U>`
    |
    = help: consider adding a `where TwoParams<i32, U>: Trait` bound
    = note: required by `Trait`
 
 error[E0277]: the trait bound `TwoParams<T, i32>: Trait` is not satisfied
-  --> $DIR/type-check-defaults.rs:36:1
+  --> $DIR/type-check-defaults.rs:43:1
    |
-36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
+43 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<T, i32>`
    |
    = help: consider adding a `where TwoParams<T, i32>: Trait` bound