Skip to content

Commit 6c22754

Browse files
committed
Check WF of defaults even when there are no bounds.
1 parent cb9da17 commit 6c22754

File tree

3 files changed

+35
-16
lines changed

3 files changed

+35
-16
lines changed

src/librustc_typeck/check/wfcheck.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,16 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
419419
use ty::subst::Subst;
420420
use ty::Predicate;
421421

422+
let generics = self.tcx.generics_of(def_id);
423+
let defaults = generics.types.iter().filter_map(|p| match p.has_default {
424+
true => Some(p.def_id),
425+
false => None,
426+
});
427+
// Defaults must be well-formed.
428+
for d in defaults {
429+
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
430+
}
431+
422432
// Check that each default fulfills the bounds on it's parameter.
423433
// We go over each predicate and duplicate it, substituting defaults in the self type.
424434
let mut predicates = fcx.tcx.predicates_of(def_id);
@@ -437,7 +447,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
437447

438448
let mut skip = false;
439449
let mut no_default = true;
440-
let generics = self.tcx.generics_of(def_id);
441450
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
442451
// All regions are identity.
443452
fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))

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

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::ops::Add;
1515

1616
struct Foo<T, U: FromIterator<T>>(T, U);
1717
struct WellFormed<Z = Foo<i32, i32>>(Z);
18+
struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
1819

1920
struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
2021

+24-15
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,71 @@
11
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
2-
--> $DIR/type-check-defaults.rs:17:1
2+
--> $DIR/type-check-defaults.rs:17:19
33
|
44
17 | struct WellFormed<Z = Foo<i32, i32>>(Z);
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
5+
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
6+
|
7+
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
8+
= note: required by `Foo`
9+
10+
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
11+
--> $DIR/type-check-defaults.rs:18:27
12+
|
13+
18 | struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
14+
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
615
|
716
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
817
= note: required by `Foo`
918

1019
error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
11-
--> $DIR/type-check-defaults.rs:19:1
20+
--> $DIR/type-check-defaults.rs:20:1
1221
|
13-
19 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
22+
20 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
1423
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `A` is not an iterator; maybe try calling `.iter()` or a similar method
1524
|
1625
= help: the trait `std::iter::Iterator` is not implemented for `A`
1726
= help: consider adding a `where A: std::iter::Iterator` bound
1827

1928
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
20-
--> $DIR/type-check-defaults.rs:21:1
29+
--> $DIR/type-check-defaults.rs:22:1
2130
|
22-
21 | struct Bounds<T:Copy=String>(T);
31+
22 | struct Bounds<T:Copy=String>(T);
2332
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
2433
|
2534
= note: required by `std::marker::Copy`
2635

2736
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
28-
--> $DIR/type-check-defaults.rs:23:1
37+
--> $DIR/type-check-defaults.rs:24:1
2938
|
30-
23 | struct WhereClause<T=String>(T) where T: Copy;
39+
24 | struct WhereClause<T=String>(T) where T: Copy;
3140
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
3241
|
3342
= note: required by `std::marker::Copy`
3443

3544
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
36-
--> $DIR/type-check-defaults.rs:25:1
45+
--> $DIR/type-check-defaults.rs:26:1
3746
|
38-
25 | trait TraitBound<T:Copy=String> {}
47+
26 | trait TraitBound<T:Copy=String> {}
3948
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
4049
|
4150
= note: required by `std::marker::Copy`
4251

4352
error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
44-
--> $DIR/type-check-defaults.rs:27:1
53+
--> $DIR/type-check-defaults.rs:28:1
4554
|
46-
27 | trait SelfBound<T:Copy=Self> {}
55+
28 | trait SelfBound<T:Copy=Self> {}
4756
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `Self`
4857
|
4958
= help: consider adding a `where Self: std::marker::Copy` bound
5059
= note: required by `std::marker::Copy`
5160

5261
error[E0277]: the trait bound `i32: std::ops::Add<u8>` is not satisfied
53-
--> $DIR/type-check-defaults.rs:29:1
62+
--> $DIR/type-check-defaults.rs:30:1
5463
|
55-
29 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
64+
30 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
5665
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
5766
|
5867
= help: the trait `std::ops::Add<u8>` is not implemented for `i32`
5968
= note: required by `std::ops::Add`
6069

61-
error: aborting due to 7 previous errors
70+
error: aborting due to 8 previous errors
6271

0 commit comments

Comments
 (0)