Expand comments, address nits.

This commit is contained in:
leonardo.yvens 2018-01-20 13:33:44 -02:00
parent 7c1b6848db
commit 35499aa9fc
3 changed files with 52 additions and 10 deletions

View File

@ -381,12 +381,20 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
let defaulted_params = generics.types.iter()
.filter(|def| def.has_default &&
def.index >= generics.parent_count() as u32);
// WF checks for type parameter defaults. See test `type-check-defaults.rs` for examples.
for param_def in defaulted_params {
// Defaults must be well-formed.
// This parameter has a default value. Check that this default value is well-formed.
// For example this forbids the declaration:
// struct Foo<T = Vec<[u32]>> { .. }
// Here `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
let d = param_def.def_id;
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
// Check the clauses are well-formed when the param is substituted by it's default.
// In trait definitions, the predicate `Self: Trait` is problematic.
// For example this forbids the following declaration because `String` is not `Copy`:
// struct Foo<T: Copy = String> { .. }
//
// In `trait Trait: Super`, checking `Self: Trait` or `Self: Super` is problematic.
// Therefore we skip such predicates. This means we check less than we could.
for pred in predicates.predicates.iter().filter(|p| !(is_trait && p.has_self_ty())) {
let mut skip = true;
@ -394,9 +402,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
// All regions are identity.
fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
}, |def, _| {
let identity_substs = fcx.tcx.mk_param_from_def(def);
let identity_ty = fcx.tcx.mk_param_from_def(def);
if def.index != param_def.index {
identity_substs
identity_ty
} else {
let sized = fcx.tcx.lang_items().sized_trait();
let pred_is_sized = match pred {
@ -410,7 +418,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
};
// In trait defs, skip `Self: Sized` when `Self` is the default.
if is_trait && pred_is_sized && default_is_self {
identity_substs
identity_ty
} else {
skip = false;
default_ty
@ -420,6 +428,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
if skip { continue; }
substituted_predicates.push(match pred {
// In trait predicates, substitute defaults only for the LHS.
// See test `defaults-well-formedness.rs` for why substituting the RHS is bad.
ty::Predicate::Trait(t_pred) => {
let trait_ref = t_pred.map_bound(|t_pred| {
let mut trait_subs = t_pred.trait_ref.substs.to_vec();

View File

@ -44,4 +44,8 @@ struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
//~^ error: the trait bound `TwoParams<i32, U>: Trait` is not satisfied [E0277]
//~^^ error: the trait bound `TwoParams<T, i32>: Trait` is not satisfied [E0277]
trait Super<T: Copy> { }
trait Base<T = String>: Super<T> { }
//~^ error: the trait bound `T: std::marker::Copy` is not satisfied [E0277]
fn main() { }

View File

@ -5,7 +5,11 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfi
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
|
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
= note: required by `Foo`
note: required by `Foo`
--> $DIR/type-check-defaults.rs:15:1
|
15 | struct Foo<T, U: FromIterator<T>>(T, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfied
--> $DIR/type-check-defaults.rs:18:27
@ -14,7 +18,11 @@ error[E0277]: the trait bound `i32: std::iter::FromIterator<i32>` is not satisfi
| ^ a collection of type `i32` cannot be built from an iterator over elements of type `i32`
|
= help: the trait `std::iter::FromIterator<i32>` is not implemented for `i32`
= note: required by `Foo`
note: required by `Foo`
--> $DIR/type-check-defaults.rs:15:1
|
15 | struct Foo<T, U: FromIterator<T>>(T, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0277]: the trait bound `A: std::iter::Iterator` is not satisfied
--> $DIR/type-check-defaults.rs:21:1
@ -74,7 +82,11 @@ error[E0277]: the trait bound `TwoParams<i32, U>: Trait` is not satisfied
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<i32, U>`
|
= help: consider adding a `where TwoParams<i32, U>: Trait` bound
= note: required by `Trait`
note: required by `Trait`
--> $DIR/type-check-defaults.rs:39:1
|
39 | trait Trait {}
| ^^^^^^^^^^^
error[E0277]: the trait bound `TwoParams<T, i32>: Trait` is not satisfied
--> $DIR/type-check-defaults.rs:43:1
@ -83,7 +95,24 @@ error[E0277]: the trait bound `TwoParams<T, i32>: Trait` is not satisfied
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<T, i32>`
|
= help: consider adding a `where TwoParams<T, i32>: Trait` bound
= note: required by `Trait`
note: required by `Trait`
--> $DIR/type-check-defaults.rs:39:1
|
39 | trait Trait {}
| ^^^^^^^^^^^
error: aborting due to 10 previous errors
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/type-check-defaults.rs:48:1
|
48 | trait Base<T = String>: Super<T> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:47:1
|
47 | trait Super<T: Copy> { }
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 11 previous errors