diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index da7f894e84d..f653f056177 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 064c374de2b..129ea9b5b67 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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> { + 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] diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index c3ecc04b12e..96e16efd130 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -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). diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index c74511cf0fd..8c3110792a8 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -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()); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c652c196afd..5c2a86f8f3f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -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. diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 42945c79ddf..33447eba749 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -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) } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index d17dcaafc04..52fd645e38e 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -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) => {