diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index c3aaeae69633f..bf004df824b11 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -359,6 +359,16 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { 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 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { 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())) diff --git a/src/test/ui/type-check-defaults.rs b/src/test/ui/type-check-defaults.rs index 6e50dd46afc71..2264fb860f155 100644 --- a/src/test/ui/type-check-defaults.rs +++ b/src/test/ui/type-check-defaults.rs @@ -15,6 +15,7 @@ use std::ops::Add; struct Foo>(T, U); struct WellFormed>(Z); +struct WellFormedNoBounds>(Z); struct WellFormedProjection::Item>(A, T); diff --git a/src/test/ui/type-check-defaults.stderr b/src/test/ui/type-check-defaults.stderr index 6f9fee62e5076..2a9f4eb693caa 100644 --- a/src/test/ui/type-check-defaults.stderr +++ b/src/test/ui/type-check-defaults.stderr @@ -1,62 +1,71 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator` is not satisfied - --> $DIR/type-check-defaults.rs:17:1 + --> $DIR/type-check-defaults.rs:17:19 | 17 | struct WellFormed>(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` is not implemented for `i32` + = note: required by `Foo` + +error[E0277]: the trait bound `i32: std::iter::FromIterator` is not satisfied + --> $DIR/type-check-defaults.rs:18:27 + | +18 | struct WellFormedNoBounds>(Z); + | ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32` | = help: the trait `std::iter::FromIterator` 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::Item>(A, T); +20 | struct WellFormedProjection::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); +22 | struct Bounds(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) where T: Copy; +24 | struct WhereClause(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 {} +26 | trait TraitBound {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 {} +28 | trait SelfBound {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` is not satisfied - --> $DIR/type-check-defaults.rs:29:1 + --> $DIR/type-check-defaults.rs:30:1 | -29 | trait FooTrait> where T::Item : Add {} +30 | trait FooTrait> where T::Item : Add {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8` | = help: the trait `std::ops::Add` 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