Skip to content

Commit 796195c

Browse files
committed
default WF: Leverage type substitution, less workarounding
`Predicate` is `TypeFoldable`, use that. Be less clever with the workaround.
1 parent 6c22754 commit 796195c

File tree

1 file changed

+31
-80
lines changed

1 file changed

+31
-80
lines changed

src/librustc_typeck/check/wfcheck.rs

+31-80
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
339339
}
340340

341341
self.for_item(item).with_fcx(|fcx, _| {
342-
self.check_where_clauses(fcx, item.span, trait_def_id);
342+
self.check_trait_where_clauses(fcx, item.span, trait_def_id);
343343
vec![]
344344
});
345345
}
@@ -410,41 +410,46 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
410410
});
411411
}
412412

413-
/// Checks where clauses and inline bounds.
413+
/// Checks where clauses and inline bounds that are declared on def_id.
414414
fn check_where_clauses<'fcx, 'tcx>(&mut self,
415415
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
416416
span: Span,
417-
def_id: DefId)
417+
def_id: DefId) {
418+
self.inner_check_where_clauses(fcx, span, def_id, false)
419+
}
420+
421+
fn check_trait_where_clauses<'fcx, 'tcx>(&mut self,
422+
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
423+
span: Span,
424+
def_id: DefId) {
425+
self.inner_check_where_clauses(fcx, span, def_id, true)
426+
}
427+
428+
/// Checks where clauses and inline bounds that are declared on def_id.
429+
fn inner_check_where_clauses<'fcx, 'tcx>(&mut self,
430+
fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
431+
span: Span,
432+
def_id: DefId,
433+
is_trait: bool)
418434
{
419435
use ty::subst::Subst;
420-
use ty::Predicate;
436+
use rustc::ty::TypeFoldable;
421437

422438
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-
});
439+
let defaulted_params = generics.types.iter()
440+
.filter(|def| def.has_default &&
441+
def.index >= generics.parent_count() as u32);
427442
// Defaults must be well-formed.
428-
for d in defaults {
443+
for d in defaulted_params.map(|p| p.def_id) {
429444
fcx.register_wf_obligation(fcx.tcx.type_of(d), fcx.tcx.def_span(d), self.code.clone());
430445
}
431-
432446
// Check that each default fulfills the bounds on it's parameter.
433447
// We go over each predicate and duplicate it, substituting defaults in the self type.
434448
let mut predicates = fcx.tcx.predicates_of(def_id);
435449
let mut default_predicates = Vec::new();
436-
for pred in &predicates.predicates {
437-
let mut self_ty = match pred {
438-
Predicate::Trait(trait_pred) => trait_pred.skip_binder().self_ty(),
439-
Predicate::TypeOutlives(outlives_pred) => (outlives_pred.0).0,
440-
Predicate::Projection(proj_pred) => {
441-
fcx.tcx.mk_ty(ty::TyProjection(proj_pred.skip_binder().projection_ty))
442-
}
443-
// Lifetime params can't have defaults.
444-
Predicate::RegionOutlives(..) => continue,
445-
_ => bug!("Predicate {:?} not supported in where clauses.", pred)
446-
};
447-
450+
// In `trait Trait : Super` predicates as `Self: Trait` and `Self: Super` are a problem.
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())) {
448453
let mut skip = false;
449454
let mut no_default = true;
450455
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
@@ -458,42 +463,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
458463
no_default = false;
459464
// Has a default, use it in the substitution.
460465
let default_ty = fcx.tcx.type_of(def.def_id);
461-
// Skip `Self : Self` in traits, it's problematic.
462-
// This means we probably check less than we could.
463-
let should_skip = match self_ty.sty {
464-
ty::TyParam(ref p) => {
465-
// lhs is Self && rhs is Self
466-
p.is_self() && match pred {
467-
Predicate::Trait(p) => p.def_id() == def_id,
468-
Predicate::TypeOutlives(_) => false,
469-
_ => bug!("Unexpected predicate {:?}", pred)
470-
}
471-
}
472-
ty::TyProjection(ref proj) => {
473-
let mut projection = proj;
474-
let mut next_typ = &projection.substs[0].as_type().unwrap().sty;
475-
// Dig through projections.
476-
while let ty::TyProjection(ref proj) = next_typ {
477-
projection = proj;
478-
next_typ = &projection.substs[0].as_type().unwrap().sty;
479-
}
480-
let lhs_is_self = match next_typ {
481-
ty::TyParam(ref p) => p.is_self(),
482-
_ => false
483-
};
484-
let rhs = fcx.tcx.associated_item(projection.item_def_id)
485-
.container
486-
.assert_trait();
487-
lhs_is_self && rhs == def_id
488-
}
489-
_ => false
490-
};
491-
skip = skip || should_skip;
492466

493-
match default_ty.sty {
467+
match default_ty.sty {
494468
// Skip `Self: Sized` when `Self` is the default. Needed in traits.
495-
ty::TyParam(ref p) if p.is_self() => {
496-
if let Predicate::Trait(p) = pred {
469+
ty::TyParam(ref p) if is_trait && p.is_self() => {
470+
if let ty::Predicate::Trait(p) = pred {
497471
if Some(p.def_id()) == fcx.tcx.lang_items().sized_trait() {
498472
skip = true;
499473
}
@@ -509,30 +483,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
509483
continue;
510484
}
511485

512-
self_ty = self_ty.subst(fcx.tcx, substs);
513-
default_predicates.push(match pred {
514-
Predicate::Trait(trait_pred) => {
515-
let mut substs = trait_pred.skip_binder().trait_ref.substs.to_vec();
516-
substs[0] = self_ty.into();
517-
let substs = fcx.tcx.intern_substs(&substs);
518-
let trait_ref = ty::Binder(ty::TraitRef::new(trait_pred.def_id(), substs));
519-
Predicate::Trait(trait_ref.to_poly_trait_predicate())
520-
}
521-
Predicate::TypeOutlives(pred) => {
522-
Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(self_ty, (pred.0).1)))
523-
}
524-
Predicate::Projection(proj_pred) => {
525-
let projection_ty = match self_ty.sty {
526-
ty::TyProjection(proj_ty) => proj_ty,
527-
_ => bug!("self_ty not projection for projection predicate.")
528-
};
529-
Predicate::Projection(ty::Binder(ty::ProjectionPredicate {
530-
projection_ty,
531-
ty: proj_pred.ty().skip_binder()
532-
}))
533-
}
534-
_ => bug!("Predicate {:?} not supported for type params.", pred)
535-
});
486+
default_predicates.push(pred.subst(fcx.tcx, substs));
536487
}
537488

538489
predicates.predicates.extend(default_predicates);

0 commit comments

Comments
 (0)