]> git.lizzy.rs Git - rust.git/commitdiff
Go back to checking only the LHS of trait predicates.
authorleonardo.yvens <leoyvens@gmail.com>
Sat, 23 Dec 2017 13:29:01 +0000 (11:29 -0200)
committerleonardo.yvens <leoyvens@gmail.com>
Wed, 28 Feb 2018 15:33:14 +0000 (12:33 -0300)
src/librustc_typeck/check/wfcheck.rs
src/test/run-pass/defaults-well-formedness.rs [new file with mode: 0644]
src/test/ui/type-check-defaults.rs
src/test/ui/type-check-defaults.stderr

index 0a919eb3b8c15ccb92cf64591e51eae1a63a1b8b..a16b806b6f125c353b1c147d7369fe29c1e83183 100644 (file)
@@ -387,7 +387,7 @@ fn inner_check_where_clauses<'fcx, 'tcx>(&mut self,
             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 @@ fn inner_check_where_clauses<'fcx, 'tcx>(&mut self,
                         }
                     }
                 });
-                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 (file)
index 0000000..92c7f87
--- /dev/null
@@ -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() {}
index a6e475eb1a3b5594f09cdee03300d1baf41a8288..7c379a1f1bc99ad96418c9a570dc8dd26f7779ef 100644 (file)
@@ -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;
 
 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() { }
index cf11282f7d20c3d20943a484bee33070427665d1..3ac6e4c26b4f0ccacb8ffe5c3579492de2373605 100644 (file)
@@ -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