default WF: Substitute defaults individually in the clauses.
This commit is contained in:
parent
87c2ad048a
commit
d9c336afb7
3 changed files with 64 additions and 42 deletions
|
@ -375,58 +375,56 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
|
|||
use ty::subst::Subst;
|
||||
use rustc::ty::TypeFoldable;
|
||||
|
||||
let mut predicates = fcx.tcx.predicates_of(def_id);
|
||||
let mut substituted_predicates = Vec::new();
|
||||
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let defaulted_params = generics.types.iter()
|
||||
.filter(|def| def.has_default &&
|
||||
def.index >= generics.parent_count() as u32);
|
||||
// Defaults must be well-formed.
|
||||
for d in defaulted_params.map(|p| p.def_id) {
|
||||
for param_def in defaulted_params {
|
||||
// Defaults must be well-formed.
|
||||
let d = param_def.def_id;
|
||||
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
|
||||
}
|
||||
// Check that each default fulfills the bounds on it's parameter.
|
||||
// We go over each predicate and duplicate it, substituting defaults in the self type.
|
||||
let mut predicates = fcx.tcx.predicates_of(def_id);
|
||||
let mut default_predicates = Vec::new();
|
||||
// In `trait Trait : Super` predicates as `Self: Trait` and `Self: Super` are a problem.
|
||||
// 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 = false;
|
||||
let mut no_default = true;
|
||||
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
|
||||
// All regions are identity.
|
||||
fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
|
||||
}, |def, _| {
|
||||
// No default or generic comes from parent, identity substitution.
|
||||
if !def.has_default || (def.index as usize) < generics.parent_count() {
|
||||
fcx.tcx.mk_param_from_def(def)
|
||||
} else {
|
||||
no_default = false;
|
||||
// Has a default, use it in the substitution.
|
||||
let default_ty = fcx.tcx.type_of(def.def_id);
|
||||
|
||||
match default_ty.sty {
|
||||
// Skip `Self: Sized` when `Self` is the default. Needed in traits.
|
||||
ty::TyParam(ref p) if is_trait && p.is_self() => {
|
||||
if let ty::Predicate::Trait(p) = pred {
|
||||
if Some(p.def_id()) == fcx.tcx.lang_items().sized_trait() {
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
// Check the clauses are well-formed when the param is substituted by it's default.
|
||||
// In trait definitions, predicates as `Self: Trait` and `Self: Super` are 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;
|
||||
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
|
||||
// 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);
|
||||
if def.index != param_def.index {
|
||||
identity_substs
|
||||
} else {
|
||||
let sized = fcx.tcx.lang_items().sized_trait();
|
||||
let pred_is_sized = match pred {
|
||||
ty::Predicate::Trait(p) => Some(p.def_id()) == sized,
|
||||
_ => false,
|
||||
};
|
||||
let default_ty = fcx.tcx.type_of(def.def_id);
|
||||
let default_is_self = match default_ty.sty {
|
||||
ty::TyParam(ref p) => p.is_self(),
|
||||
_ => false
|
||||
};
|
||||
// In trait defs, skip `Self: Sized` when `Self` is the default.
|
||||
if is_trait && pred_is_sized && default_is_self {
|
||||
identity_substs
|
||||
} else {
|
||||
skip = false;
|
||||
default_ty
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
default_ty
|
||||
});
|
||||
if !skip {
|
||||
substituted_predicates.push(pred.subst(fcx.tcx, substs));
|
||||
}
|
||||
});
|
||||
|
||||
if skip || no_default {
|
||||
continue;
|
||||
}
|
||||
|
||||
default_predicates.push(pred.subst(fcx.tcx, substs));
|
||||
}
|
||||
|
||||
predicates.predicates.extend(default_predicates);
|
||||
predicates.predicates.extend(substituted_predicates);
|
||||
let predicates = predicates.instantiate_identity(fcx.tcx);
|
||||
let predicates = fcx.normalize_associated_types_in(span, &predicates);
|
||||
|
||||
|
|
|
@ -29,4 +29,10 @@ trait SelfBound<T:Copy=Self> {}
|
|||
|
||||
trait FooTrait<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {}
|
||||
|
||||
trait Trait {}
|
||||
struct TwoParams<T, U>(T, U);
|
||||
impl Trait for TwoParams<i32, i32> {}
|
||||
// Check that each default is substituted individually in the clauses.
|
||||
struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
|
||||
fn main() { }
|
||||
|
|
|
@ -67,5 +67,23 @@ error[E0277]: the trait bound `i32: std::ops::Add<u8>` is not satisfied
|
|||
= help: the trait `std::ops::Add<u8>` is not implemented for `i32`
|
||||
= note: required by `std::ops::Add`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error[E0277]: the trait bound `TwoParams<i32, U>: Trait` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:36:1
|
||||
|
|
||||
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<i32, U>`
|
||||
|
|
||||
= help: consider adding a `where TwoParams<i32, U>: Trait` bound
|
||||
= note: required by `Trait`
|
||||
|
||||
error[E0277]: the trait bound `TwoParams<T, i32>: Trait` is not satisfied
|
||||
--> $DIR/type-check-defaults.rs:36:1
|
||||
|
|
||||
36 | struct Bogus<T = i32, U = i32>(TwoParams<T, U>) where TwoParams<T, U>: Trait;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `TwoParams<T, i32>`
|
||||
|
|
||||
= help: consider adding a `where TwoParams<T, i32>: Trait` bound
|
||||
= note: required by `Trait`
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue