]> git.lizzy.rs Git - rust.git/commitdiff
Check WF of defaults even when there are no bounds.
authorleonardo.yvens <leoyvens@gmail.com>
Mon, 18 Dec 2017 14:40:15 +0000 (12:40 -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/ui/type-check-defaults.rs
src/test/ui/type-check-defaults.stderr

index c3aaeae69633faebd537a52f13f8b6b4cac759e1..bf004df824b1154bc567ccf314e513b4af81c9b1 100644 (file)
@@ -359,6 +359,16 @@ fn check_where_clauses<'fcx, 'tcx>(&mut self,
         use ty::subst::Subst;
         use ty::Predicate;
 
+        let generics = self.tcx.generics_of(def_id);
+        let defaults = generics.types.iter().filter_map(|p| match p.has_default {
+                                                                true => Some(p.def_id),
+                                                                false => None,
+                                                        });
+        // Defaults must be well-formed.
+        for d in defaults {
+            fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
+        }
+
         // Check that each default fulfills the bounds on it's parameter.
         // We go over each predicate and duplicate it, substituting defaults in the self type.
         let mut predicates = fcx.tcx.predicates_of(def_id);
@@ -377,7 +387,6 @@ fn check_where_clauses<'fcx, 'tcx>(&mut self,
 
             let mut skip = false;
             let mut no_default = true;
-            let generics = self.tcx.generics_of(def_id);
             let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
                 // All regions are identity.
                 fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
index 6e50dd46afc716148567d463164b707e57a0eeb6..2264fb860f1552ed26fe96a123885f09e9acd052 100644 (file)
@@ -15,6 +15,7 @@
 
 struct Foo<T, U: FromIterator<T>>(T, U);
 struct WellFormed<Z = Foo<i32, i32>>(Z);
+struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
 
 struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
 
index 6f9fee62e50769ac7ce137a0a6c007f9f05480d2..2a9f4eb693caaf6ad77b640c2dc9a416e185ec3f 100644 (file)
@@ -1,62 +1,71 @@
 error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
-  --> $DIR/type-check-defaults.rs:17:1
+  --> $DIR/type-check-defaults.rs:17:19
    |
 17 | struct WellFormed<Z = Foo<i32, i32>>(Z);
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
+   |                   ^ 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`
+   = note: required by `Foo`
+
+error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
+  --> $DIR/type-check-defaults.rs:18:27
+   |
+18 | struct WellFormedNoBounds<Z:?Sized = 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`
    = note: required by `Foo`
 
 error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
-  --> $DIR/type-check-defaults.rs:19:1
+  --> $DIR/type-check-defaults.rs:20:1
    |
-19 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
+20 | 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:21:1
+  --> $DIR/type-check-defaults.rs:22:1
    |
-21 | struct Bounds<T:Copy=String>(T);
+22 | 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:23:1
+  --> $DIR/type-check-defaults.rs:24:1
    |
-23 | 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:25:1
+  --> $DIR/type-check-defaults.rs:26:1
    |
-25 | trait TraitBound<T:Copy=String> {}
+26 | 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:27:1
+  --> $DIR/type-check-defaults.rs:28:1
    |
-27 | trait SelfBound<T:Copy=Self> {}
+28 | 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:29:1
+  --> $DIR/type-check-defaults.rs:30:1
    |
-29 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
+30 | 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: aborting due to 7 previous errors
+error: aborting due to 8 previous errors