Skip to content

Commit a7c7c8a

Browse files
committed
Check only concrete defaults for well formedness
1 parent c74f85f commit a7c7c8a

File tree

4 files changed

+22
-30
lines changed

4 files changed

+22
-30
lines changed

src/librustc_typeck/check/wfcheck.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,16 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
363363
let generics = self.tcx.generics_of(def_id);
364364
let is_our_default = |def: &ty::TypeParameterDef|
365365
def.has_default && def.index >= generics.parent_count() as u32;
366-
let defaulted_params = generics.types.iter().cloned().filter(&is_our_default);
367-
// Check that defaults are well-formed. See test `type-check-defaults.rs`.
366+
367+
// Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
368368
// For example this forbids the declaration:
369369
// struct Foo<T = Vec<[u32]>> { .. }
370370
// Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
371-
for d in defaulted_params.map(|p| p.def_id) {
372-
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
371+
for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
372+
let ty = fcx.tcx.type_of(d);
373+
if !ty.needs_subst() {
374+
fcx.register_wf_obligation(ty, fcx.tcx.def_span(d), self.code.clone());
375+
}
373376
}
374377

375378
// Check that trait predicates are WF when params are substituted by their defaults.

src/test/run-pass/defaults-well-formedness.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@ struct DefaultedLhs<U, V=i32>(U, V) where V: Trait<U>;
2424
// Dependent defaults are not checked.
2525
struct Dependent<T, U = T>(T, U) where U: Copy;
2626
trait SelfBound<T: Copy=Self> {}
27+
// Not even for well-formedness.
28+
struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
2729

2830
fn main() {}

src/test/ui/type-check-defaults.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ struct WellFormed<Z = Foo<i32, i32>>(Z);
1818
struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
1919
//~^ error: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied [E0277]
2020

21-
struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
22-
//~^ error: the trait bound `A: std::iter::Iterator` is not satisfied [E0277]
23-
2421
struct Bounds<T:Copy=String>(T);
2522
//~^ error: the trait bound `std::string::String: std::marker::Copy` is not satisfied [E0277]
2623

src/test/ui/type-check-defaults.stderr

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,61 +24,51 @@ note: required by `Foo`
2424
15 | struct Foo<T, U: FromIterator<T>>(T, U);
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2626

27-
error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
28-
--> $DIR/type-check-defaults.rs:21:32
29-
|
30-
21 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
31-
| ^ `A` is not an iterator; maybe try calling `.iter()` or a similar method
32-
|
33-
= help: the trait `std::iter::Iterator` is not implemented for `A`
34-
= help: consider adding a `where A: std::iter::Iterator` bound
35-
= note: required by `std::iter::Iterator`
36-
3727
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
38-
--> $DIR/type-check-defaults.rs:24:1
28+
--> $DIR/type-check-defaults.rs:21:1
3929
|
40-
24 | struct Bounds<T:Copy=String>(T);
30+
21 | struct Bounds<T:Copy=String>(T);
4131
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
4232
|
4333
= note: required by `std::marker::Copy`
4434

4535
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
46-
--> $DIR/type-check-defaults.rs:27:1
36+
--> $DIR/type-check-defaults.rs:24:1
4737
|
48-
27 | struct WhereClause<T=String>(T) where T: Copy;
38+
24 | struct WhereClause<T=String>(T) where T: Copy;
4939
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
5040
|
5141
= note: required by `std::marker::Copy`
5242

5343
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
54-
--> $DIR/type-check-defaults.rs:30:1
44+
--> $DIR/type-check-defaults.rs:27:1
5545
|
56-
30 | trait TraitBound<T:Copy=String> {}
46+
27 | trait TraitBound<T:Copy=String> {}
5747
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
5848
|
5949
= note: required by `std::marker::Copy`
6050

6151
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
62-
--> $DIR/type-check-defaults.rs:34:1
52+
--> $DIR/type-check-defaults.rs:31:1
6353
|
64-
34 | trait Base<T = String>: Super<T> { }
54+
31 | trait Base<T = String>: Super<T> { }
6555
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
6656
|
6757
= help: consider adding a `where T: std::marker::Copy` bound
6858
note: required by `Super`
69-
--> $DIR/type-check-defaults.rs:33:1
59+
--> $DIR/type-check-defaults.rs:30:1
7060
|
71-
33 | trait Super<T: Copy> { }
61+
30 | trait Super<T: Copy> { }
7262
| ^^^^^^^^^^^^^^^^^^^^
7363

7464
error[E0277]: cannot add `u8` to `i32`
75-
--> $DIR/type-check-defaults.rs:37:1
65+
--> $DIR/type-check-defaults.rs:34:1
7666
|
77-
37 | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
67+
34 | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
7868
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
7969
|
8070
= help: the trait `std::ops::Add<u8>` is not implemented for `i32`
8171
= note: required by `std::ops::Add`
8272

83-
error: aborting due to 8 previous errors
73+
error: aborting due to 7 previous errors
8474

0 commit comments

Comments
 (0)