add tuple_fields convenience method and use it in a few places

This commit is contained in:
Ralf Jung 2019-08-07 09:01:53 +02:00
parent fbd56131a9
commit 8e6fbbec83
7 changed files with 25 additions and 18 deletions

View File

@ -2565,6 +2565,8 @@ impl<'tcx> AdtDef {
}
impl<'tcx> FieldDef {
/// Returns the type of this field. The `subst` is typically obtained
/// via the second field of `TyKind::AdtDef`.
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).subst(tcx, subst)
}

View File

@ -171,6 +171,7 @@ pub enum TyKind<'tcx> {
Never,
/// A tuple type. For example, `(i32, bool)`.
/// Use `TyS::tuple_fields` to iterate over the field types.
Tuple(SubstsRef<'tcx>),
/// The projection of an associated type. For example,
@ -1723,8 +1724,8 @@ impl<'tcx> TyS<'tcx> {
})
})
}
ty::Tuple(tys) => tys.iter().any(|ty| {
ty.expect_ty().conservative_is_privately_uninhabited(tcx)
ty::Tuple(..) => self.tuple_fields().any(|ty| {
ty.conservative_is_privately_uninhabited(tcx)
}),
ty::Array(ty, len) => {
match len.try_eval_usize(tcx, ParamEnv::empty()) {
@ -2103,6 +2104,15 @@ impl<'tcx> TyS<'tcx> {
}
}
/// Iterates over tuple fields.
/// Panics when called on anything but a tuple.
pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
match self.sty {
Tuple(substs) => substs.iter().map(|field| field.expect_ty()),
_ => bug!("tuple_fields called on non-tuple"),
}
}
/// If the type contains variants, returns the valid range of variant indices.
/// FIXME This requires the optimized MIR in the case of generators.
#[inline]

View File

@ -845,15 +845,15 @@ impl<'tcx> ty::TyS<'tcx> {
ty: Ty<'tcx>,
) -> Representability {
match ty.sty {
Tuple(ref ts) => {
Tuple(..) => {
// Find non representable
fold_repr(ts.iter().map(|ty| {
fold_repr(ty.tuple_fields().map(|ty| {
is_type_structurally_recursive(
tcx,
sp,
seen,
representable_cache,
ty.expect_ty(),
ty,
)
}))
}
@ -1095,7 +1095,7 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>
// state transformation pass
ty::Generator(..) => true,
ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).any(needs_drop),
ty::Tuple(..) => ty.tuple_fields().any(needs_drop),
// unions don't have destructors because of the child types,
// only if they manually implement `Drop` (handled above).

View File

@ -119,8 +119,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
ty::GeneratorWitness(ts) => {
stack.extend(ts.skip_binder().iter().cloned().rev());
}
ty::Tuple(ts) => {
stack.extend(ts.iter().map(|k| k.expect_ty()).rev());
ty::Tuple(..) => {
stack.extend(parent_ty.tuple_fields().rev());
}
ty::FnDef(_, substs) => {
stack.extend(substs.types().rev());

View File

@ -1903,14 +1903,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
_ => true, // Conservative fallback for multi-variant enum.
}
}
Tuple(substs) => {
Tuple(..) => {
// Proceed recursively, check all fields.
substs.iter().all(|field| {
ty_maybe_allows_zero_init(
tcx,
field.expect_ty(),
)
})
ty.tuple_fields().all(|field| ty_maybe_allows_zero_init(tcx, field))
}
// FIXME: Would be nice to also warn for `NonNull`/`NonZero*`.
// Conservative fallback.

View File

@ -324,7 +324,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
substs.upvar_tys(def_id, tcx)
)
}
ty::Tuple(tys) => builder.tuple_like_shim(dest, src, tys.iter().map(|k| k.expect_ty())),
ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
_ => {
bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty)
}

View File

@ -804,8 +804,8 @@ where
let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
self.open_drop_for_tuple(&tys)
}
ty::Tuple(tys) => {
let tys: Vec<_> = tys.iter().map(|k| k.expect_ty()).collect();
ty::Tuple(..) => {
let tys: Vec<_> = ty.tuple_fields().collect();
self.open_drop_for_tuple(&tys)
}
ty::Adt(def, substs) => {