From a7c7c8a4d7439e69f22386af1bb44f7686252f12 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Wed, 14 Feb 2018 20:55:37 -0200 Subject: [PATCH] Check only concrete defaults for well formedness --- src/librustc_typeck/check/wfcheck.rs | 11 +++-- src/test/run-pass/defaults-well-formedness.rs | 2 + src/test/ui/type-check-defaults.rs | 3 -- src/test/ui/type-check-defaults.stderr | 40 +++++++------------ 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 258860d3d5e4..4eb3e29ec694 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> { .. } // 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 552665bac4e6..f35946790955 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) where V: Trait; // Dependent defaults are not checked. struct Dependent(T, U) where U: Copy; trait SelfBound {} +// Not even for well-formedness. +struct WellFormedProjection::Item>(A, T); fn main() {} diff --git a/src/test/ui/type-check-defaults.rs b/src/test/ui/type-check-defaults.rs index 65560df9f21f..f916df5d32d0 100644 --- a/src/test/ui/type-check-defaults.rs +++ b/src/test/ui/type-check-defaults.rs @@ -18,9 +18,6 @@ struct WellFormed>(Z); struct WellFormedNoBounds>(Z); //~^ error: the trait bound `i32: std::iter::FromIterator` is not satisfied [E0277] -struct WellFormedProjection::Item>(A, T); -//~^ error: the trait bound `A: std::iter::Iterator` is not satisfied [E0277] - struct Bounds(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 c73c0792f8e7..4af8f5da0dd0 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); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied - --> $DIR/type-check-defaults.rs:21:32 +error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied + --> $DIR/type-check-defaults.rs:21:1 | -21 | struct WellFormedProjection::Item>(A, T); - | ^ `A` is not an iterator; maybe try calling `.iter()` or a similar method +21 | struct Bounds(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` | - = 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` + = 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 | -24 | struct Bounds(T); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` +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:27:1 | -27 | 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:30:1 - | -30 | trait TraitBound {} +27 | 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 `T: std::marker::Copy` is not satisfied - --> $DIR/type-check-defaults.rs:34:1 + --> $DIR/type-check-defaults.rs:31:1 | -34 | trait Base: Super { } +31 | trait Base: Super { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 { } +30 | trait Super { } | ^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add `u8` to `i32` - --> $DIR/type-check-defaults.rs:37:1 + --> $DIR/type-check-defaults.rs:34:1 | -37 | trait ProjectionPred> where T::Item : Add {} +34 | trait ProjectionPred> 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 8 previous errors +error: aborting due to 7 previous errors