Skip to content

Commit 73e9938

Browse files
committed
Try just testing substituted types for well-formedness.
1 parent e09082c commit 73e9938

File tree

3 files changed

+47
-77
lines changed

3 files changed

+47
-77
lines changed

src/librustc_typeck/check/wfcheck.rs

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -433,10 +433,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
433433
is_trait: bool)
434434
{
435435
use ty::subst::Subst;
436-
use rustc::ty::TypeFoldable;
437-
438-
let mut predicates = fcx.tcx.predicates_of(def_id);
439-
let mut substituted_predicates = Vec::new();
440436

441437
let generics = self.tcx.generics_of(def_id);
442438
let defaulted_params = generics.types.iter()
@@ -446,46 +442,29 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
446442
// Defaults must be well-formed.
447443
let d = param_def.def_id;
448444
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
449-
// Check the clauses are well-formed when the param is substituted by it's default.
450-
// In trait definitions, predicates as `Self: Trait` and `Self: Super` are problematic.
451-
// Therefore we skip such predicates. This means we check less than we could.
452-
for pred in predicates.predicates.iter().filter(|p| !(is_trait && p.has_self_ty())) {
453-
let mut skip = true;
454-
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
445+
// Trait declarations are hard to support here for many reasons.
446+
// They don't support `type_of`. We'd have to ignore `Self: Sized` bounds.
447+
// So for now we just don't do the next check on traits.
448+
if is_trait {
449+
continue;
450+
}
451+
// Check the type is still well-formed when the param is substituted by it's default.
452+
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
455453
// All regions are identity.
456454
fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
457455
}, |def, _| {
458-
let identity_substs = fcx.tcx.mk_param_from_def(def);
459456
if def.index != param_def.index {
460-
identity_substs
457+
// Other params are identity.
458+
fcx.tcx.mk_param_from_def(def)
461459
} else {
462-
let sized = fcx.tcx.lang_items().sized_trait();
463-
let pred_is_sized = match pred {
464-
ty::Predicate::Trait(p) => Some(p.def_id()) == sized,
465-
_ => false,
466-
};
467-
let default_ty = fcx.tcx.type_of(def.def_id);
468-
let default_is_self = match default_ty.sty {
469-
ty::TyParam(ref p) => p.is_self(),
470-
_ => false
471-
};
472-
// In trait defs, skip `Self: Sized` when `Self` is the default.
473-
if is_trait && pred_is_sized && default_is_self {
474-
identity_substs
475-
} else {
476-
skip = false;
477-
default_ty
478-
}
460+
fcx.tcx.type_of(def.def_id)
479461
}
480462
});
481-
if !skip {
482-
substituted_predicates.push(pred.subst(fcx.tcx, substs));
483-
}
484-
}
463+
let defaulted_type = fcx.tcx.type_of(def_id).subst(fcx.tcx, substs);
464+
fcx.register_wf_obligation(defaulted_type, span, self.code.clone());
485465
}
486466

487-
predicates.predicates.extend(substituted_predicates);
488-
let predicates = predicates.instantiate_identity(fcx.tcx);
467+
let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
489468
let predicates = fcx.normalize_associated_types_in(span, &predicates);
490469

491470
let obligations =

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@ struct Foo<T, U: FromIterator<T>>(T, U);
1717
struct WellFormed<Z = Foo<i32, i32>>(Z);
1818
struct WellFormedNoBounds<Z:?Sized = Foo<i32, i32>>(Z);
1919

20+
trait WellFormedTrait<Z = Foo<i32, i32>> {}
21+
2022
struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
2123

2224
struct Bounds<T:Copy=String>(T);
2325

2426
struct WhereClause<T=String>(T) where T: Copy;
2527

26-
trait TraitBound<T:Copy=String> {}
27-
28-
trait SelfBound<T:Copy=Self> {}
29-
30-
trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
28+
struct Projection<T:Iterator = IntoIter<i32>>(T) where T::Item : Add<u8>;
3129

3230
trait Trait {}
3331
struct TwoParams<T, U>(T, U);

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

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,74 +16,67 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfi
1616
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
1717
= note: required by `Foo`
1818

19-
error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
20-
--> $DIR/type-check-defaults.rs:20:1
19+
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
20+
--> $DIR/type-check-defaults.rs:20:23
2121
|
22-
20 | struct WellFormedProjection<A, T=<A as Iterator>::Item>(A, T);
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `A` is not an iterator; maybe try calling `.iter()` or a similar method
22+
20 | trait WellFormedTrait<Z = Foo<i32, i32>> {}
23+
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
2424
|
25-
= help: the trait `std::iter::Iterator` is not implemented for `A`
26-
= help: consider adding a `where A: std::iter::Iterator` bound
25+
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
26+
= note: required by `Foo`
2727

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

3638
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
3739
--> $DIR/type-check-defaults.rs:24:1
3840
|
39-
24 | struct WhereClause<T=String>(T) where T: Copy;
40-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
41+
24 | struct Bounds<T:Copy=String>(T);
42+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
4143
|
42-
= note: required by `std::marker::Copy`
44+
= note: required by `Bounds`
4345

4446
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
4547
--> $DIR/type-check-defaults.rs:26:1
4648
|
47-
26 | trait TraitBound<T:Copy=String> {}
48-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
49-
|
50-
= note: required by `std::marker::Copy`
51-
52-
error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
53-
--> $DIR/type-check-defaults.rs:28:1
54-
|
55-
28 | trait SelfBound<T:Copy=Self> {}
56-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `Self`
49+
26 | struct WhereClause<T=String>(T) where T: Copy;
50+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
5751
|
58-
= help: consider adding a `where Self: std::marker::Copy` bound
59-
= note: required by `std::marker::Copy`
52+
= note: required by `WhereClause`
6053

6154
error[E0277]: the trait bound `i32: std::ops::Add<u8>` is not satisfied
62-
--> $DIR/type-check-defaults.rs:30:1
55+
--> $DIR/type-check-defaults.rs:28:1
6356
|
64-
30 | trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
65-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
57+
28 | struct Projection<T:Iterator = IntoIter<i32>>(T) where T::Item : Add<u8>;
58+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8`
6659
|
6760
= help: the trait `std::ops::Add<u8>` is not implemented for `i32`
68-
= note: required by `std::ops::Add`
61+
= note: required by `Projection`
6962

7063
error[E0277]: the trait bound `TwoParams<i32, U>: Trait` is not satisfied
71-
--> $DIR/type-check-defaults.rs:36:1
64+
--> $DIR/type-check-defaults.rs:34:1
7265
|
73-
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
66+
34 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
7467
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<i32, U>`
7568
|
7669
= help: consider adding a `where TwoParams<i32, U>: Trait` bound
77-
= note: required by `Trait`
70+
= note: required by `Bogus`
7871

7972
error[E0277]: the trait bound `TwoParams<T, i32>: Trait` is not satisfied
80-
--> $DIR/type-check-defaults.rs:36:1
73+
--> $DIR/type-check-defaults.rs:34:1
8174
|
82-
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
75+
34 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
8376
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<T, i32>`
8477
|
8578
= help: consider adding a `where TwoParams<T, i32>: Trait` bound
86-
= note: required by `Trait`
79+
= note: required by `Bogus`
8780

88-
error: aborting due to 10 previous errors
81+
error: aborting due to 9 previous errors
8982

0 commit comments

Comments
 (0)