clean-up adt_sized_constraint now that it uses on-demand
This commit is contained in:
parent
23de823e93
commit
5412587910
3 changed files with 21 additions and 49 deletions
|
|
@ -1790,11 +1790,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
ty::TyAdt(def, substs) => {
|
||||
let sized_crit = def.sized_constraint(self.tcx());
|
||||
// (*) binder moved here
|
||||
Where(ty::Binder(match sized_crit.sty {
|
||||
ty::TyTuple(tys, _) => tys.to_vec().subst(self.tcx(), substs),
|
||||
ty::TyBool => vec![],
|
||||
_ => vec![sized_crit.subst(self.tcx(), substs)]
|
||||
}))
|
||||
Where(ty::Binder(
|
||||
sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect()
|
||||
))
|
||||
}
|
||||
|
||||
ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None,
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ define_maps! { <'tcx>
|
|||
pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,
|
||||
pub adt_def: ItemSignature(DefId) -> &'tcx ty::AdtDef,
|
||||
pub adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
|
||||
pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>,
|
||||
pub adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>],
|
||||
|
||||
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
|
||||
pub is_foreign_item: IsForeignItem(DefId) -> bool,
|
||||
|
|
|
|||
|
|
@ -1780,16 +1780,9 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
queries::adt_destructor::get(tcx, DUMMY_SP, self.did)
|
||||
}
|
||||
|
||||
/// Returns a simpler type such that `Self: Sized` if and only
|
||||
/// Returns a list of types such that `Self: Sized` if and only
|
||||
/// if that type is Sized, or `TyErr` if this type is recursive.
|
||||
///
|
||||
/// HACK: instead of returning a list of types, this function can
|
||||
/// return a tuple. In that case, the result is Sized only if
|
||||
/// all elements of the tuple are Sized.
|
||||
///
|
||||
/// This is generally the `struct_tail` if this is a struct, or a
|
||||
/// tuple of them if this is an enum.
|
||||
///
|
||||
/// Oddly enough, checking that the sized-constraint is Sized is
|
||||
/// actually more expressive than checking all members:
|
||||
/// the Sized trait is inductive, so an associated type that references
|
||||
|
|
@ -1797,16 +1790,16 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
///
|
||||
/// Due to normalization being eager, this applies even if
|
||||
/// the associated type is behind a pointer, e.g. issue #31299.
|
||||
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
|
||||
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
|
||||
match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
|
||||
Ok(ty) => ty,
|
||||
Ok(tys) => tys,
|
||||
Err(_) => {
|
||||
debug!("adt_sized_constraint: {:?} is recursive", self);
|
||||
// This should be reported as an error by `check_representable`.
|
||||
//
|
||||
// Consider the type as Sized in the meanwhile to avoid
|
||||
// further errors.
|
||||
tcx.types.err
|
||||
tcx.intern_type_list(&[tcx.types.err])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1836,18 +1829,13 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
|||
|
||||
TyAdt(adt, substs) => {
|
||||
// recursive case
|
||||
let adt_ty =
|
||||
adt.sized_constraint(tcx)
|
||||
.subst(tcx, substs);
|
||||
let adt_tys = adt.sized_constraint(tcx);
|
||||
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
|
||||
ty, adt_ty);
|
||||
if let ty::TyTuple(ref tys, _) = adt_ty.sty {
|
||||
tys.iter().flat_map(|ty| {
|
||||
self.sized_constraint_for_ty(tcx, ty)
|
||||
}).collect()
|
||||
} else {
|
||||
self.sized_constraint_for_ty(tcx, adt_ty)
|
||||
}
|
||||
ty, adt_tys);
|
||||
adt_tys.iter()
|
||||
.map(|ty| ty.subst(tcx, substs))
|
||||
.flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
|
||||
.collect()
|
||||
}
|
||||
|
||||
TyProjection(..) | TyAnon(..) => {
|
||||
|
|
@ -2697,13 +2685,7 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
|||
|
||||
/// Calculates the Sized-constraint.
|
||||
///
|
||||
/// As the Sized-constraint of enums can be a *set* of types,
|
||||
/// the Sized-constraint may need to be a set also. Because introducing
|
||||
/// a new type of IVar is currently a complex affair, the Sized-constraint
|
||||
/// may be a tuple.
|
||||
///
|
||||
/// In fact, there are only a few options for the constraint:
|
||||
/// - `bool`, if the type is always Sized
|
||||
/// In fact, there are only a few options for the types in the constraint:
|
||||
/// - an obviously-unsized type
|
||||
/// - a type parameter or projection whose Sizedness can't be known
|
||||
/// - a tuple of type parameters or projections, if there are multiple
|
||||
|
|
@ -2712,26 +2694,18 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
|||
/// check should catch this case.
|
||||
fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> Ty<'tcx> {
|
||||
-> &'tcx [Ty<'tcx>] {
|
||||
let def = tcx.lookup_adt_def(def_id);
|
||||
|
||||
let tys: Vec<_> = def.variants.iter().flat_map(|v| {
|
||||
let result = tcx.intern_type_list(&def.variants.iter().flat_map(|v| {
|
||||
v.fields.last()
|
||||
}).flat_map(|f| {
|
||||
let ty = tcx.item_type(f.did);
|
||||
def.sized_constraint_for_ty(tcx, ty)
|
||||
}).collect();
|
||||
def.sized_constraint_for_ty(tcx, tcx.item_type(f.did))
|
||||
}).collect::<Vec<_>>());
|
||||
|
||||
let ty = match tys.len() {
|
||||
_ if tys.references_error() => tcx.types.err,
|
||||
0 => tcx.types.bool,
|
||||
1 => tys[0],
|
||||
_ => tcx.intern_tup(&tys[..], false)
|
||||
};
|
||||
debug!("adt_sized_constraint: {:?} => {:?}", def, result);
|
||||
|
||||
debug!("adt_sized_constraint: {:?} => {:?}", def, ty);
|
||||
|
||||
ty
|
||||
result
|
||||
}
|
||||
|
||||
fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue