From 3fd397b096b360fb46076b757e82e79d6db328de Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 18 Mar 2020 02:48:55 +0200 Subject: [PATCH] rustc: make {Closure,Generator}Substs::split as cheap as possible. --- src/librustc/ty/sty.rs | 98 +++++++++++++----------------------------- 1 file changed, 31 insertions(+), 67 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 5bdab69e2ca9..096f63fdf2e6 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -11,7 +11,7 @@ use crate::mir::interpret::ConstValue; use crate::mir::interpret::Scalar; use crate::mir::Promoted; use crate::ty::layout::VariantIdx; -use crate::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef}; +use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::{ self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, }; @@ -364,11 +364,9 @@ pub struct ClosureSubsts<'tcx> { /// Struct returned by `split()`. Note that these are subslices of the /// parent slice and not canonical substs themselves. struct SplitClosureSubsts<'tcx> { - // FIXME(eddyb) maybe replace these with `GenericArg` to avoid having - // `GenericArg::expect_ty` called on all of them when only one is used. - closure_kind_ty: Ty<'tcx>, - closure_sig_as_fn_ptr_ty: Ty<'tcx>, - tupled_upvars_ty: Ty<'tcx>, + closure_kind_ty: GenericArg<'tcx>, + closure_sig_as_fn_ptr_ty: GenericArg<'tcx>, + tupled_upvars_ty: GenericArg<'tcx>, } impl<'tcx> ClosureSubsts<'tcx> { @@ -376,11 +374,11 @@ impl<'tcx> ClosureSubsts<'tcx> { /// components. Single source of truth with respect to the /// ordering. fn split(self) -> SplitClosureSubsts<'tcx> { - let parent_len = self.substs.len() - 3; - SplitClosureSubsts { - closure_kind_ty: self.substs.type_at(parent_len), - closure_sig_as_fn_ptr_ty: self.substs.type_at(parent_len + 1), - tupled_upvars_ty: self.substs.type_at(parent_len + 2), + match self.substs[..] { + [.., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { + SplitClosureSubsts { closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty } + } + _ => bug!("closure substs missing synthetics"), } } @@ -390,29 +388,19 @@ impl<'tcx> ClosureSubsts<'tcx> { /// Used primarily by `ty::print::pretty` to be able to handle closure /// types that haven't had their synthetic types substituted in. pub fn is_valid(self) -> bool { - self.substs.len() >= 3 && matches!(self.split().tupled_upvars_ty.kind, Tuple(_)) + self.substs.len() >= 3 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_)) } #[inline] pub fn upvar_tys(self) -> impl Iterator> + 'tcx { - let upvars = match self.split().tupled_upvars_ty.kind { - Tuple(upvars) => upvars, - _ => bug!("upvars should be tupled"), - }; - upvars.iter().map(|t| { - if let GenericArgKind::Type(ty) = t.unpack() { - ty - } else { - bug!("upvar should be type") - } - }) + self.split().tupled_upvars_ty.expect_ty().tuple_fields() } /// Returns the closure kind for this closure; may return a type /// variable during inference. To get the closure kind during /// inference, use `infcx.closure_kind(substs)`. pub fn kind_ty(self) -> Ty<'tcx> { - self.split().closure_kind_ty + self.split().closure_kind_ty.expect_ty() } /// Returns the `fn` pointer type representing the closure signature for this @@ -421,7 +409,7 @@ impl<'tcx> ClosureSubsts<'tcx> { // type is known at the time of the creation of `ClosureSubsts`, // see `rustc_typeck::check::closure`. pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> { - self.split().closure_sig_as_fn_ptr_ty + self.split().closure_sig_as_fn_ptr_ty.expect_ty() } /// Returns the closure kind for this closure; only usable outside @@ -430,7 +418,7 @@ impl<'tcx> ClosureSubsts<'tcx> { /// /// If you have an inference context, use `infcx.closure_kind()`. pub fn kind(self) -> ty::ClosureKind { - self.split().closure_kind_ty.to_opt_closure_kind().unwrap() + self.kind_ty().to_opt_closure_kind().unwrap() } /// Extracts the signature from the closure. @@ -450,24 +438,20 @@ pub struct GeneratorSubsts<'tcx> { } struct SplitGeneratorSubsts<'tcx> { - // FIXME(eddyb) maybe replace these with `GenericArg` to avoid having - // `GenericArg::expect_ty` called on all of them when only one is used. - resume_ty: Ty<'tcx>, - yield_ty: Ty<'tcx>, - return_ty: Ty<'tcx>, - witness: Ty<'tcx>, - tupled_upvars_ty: Ty<'tcx>, + resume_ty: GenericArg<'tcx>, + yield_ty: GenericArg<'tcx>, + return_ty: GenericArg<'tcx>, + witness: GenericArg<'tcx>, + tupled_upvars_ty: GenericArg<'tcx>, } impl<'tcx> GeneratorSubsts<'tcx> { fn split(self) -> SplitGeneratorSubsts<'tcx> { - let parent_len = self.substs.len() - 5; - SplitGeneratorSubsts { - resume_ty: self.substs.type_at(parent_len), - yield_ty: self.substs.type_at(parent_len + 1), - return_ty: self.substs.type_at(parent_len + 2), - witness: self.substs.type_at(parent_len + 3), - tupled_upvars_ty: self.substs.type_at(parent_len + 4), + match self.substs[..] { + [.., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { + SplitGeneratorSubsts { resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty } + } + _ => bug!("generator substs missing synthetics"), } } @@ -477,7 +461,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Used primarily by `ty::print::pretty` to be able to handle generator /// types that haven't had their synthetic types substituted in. pub fn is_valid(self) -> bool { - self.substs.len() >= 5 && matches!(self.split().tupled_upvars_ty.kind, Tuple(_)) + self.substs.len() >= 5 && matches!(self.split().tupled_upvars_ty.expect_ty().kind, Tuple(_)) } /// This describes the types that can be contained in a generator. @@ -486,37 +470,27 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// The state transformation MIR pass may only produce layouts which mention types /// in this tuple. Upvars are not counted here. pub fn witness(self) -> Ty<'tcx> { - self.split().witness + self.split().witness.expect_ty() } #[inline] pub fn upvar_tys(self) -> impl Iterator> + 'tcx { - let upvars = match self.split().tupled_upvars_ty.kind { - Tuple(upvars) => upvars, - _ => bug!("upvars should be tupled"), - }; - upvars.iter().map(|t| { - if let GenericArgKind::Type(ty) = t.unpack() { - ty - } else { - bug!("upvar should be type") - } - }) + self.split().tupled_upvars_ty.expect_ty().tuple_fields() } /// Returns the type representing the resume type of the generator. pub fn resume_ty(self) -> Ty<'tcx> { - self.split().resume_ty + self.split().resume_ty.expect_ty() } /// Returns the type representing the yield type of the generator. pub fn yield_ty(self) -> Ty<'tcx> { - self.split().yield_ty + self.split().yield_ty.expect_ty() } /// Returns the type representing the return type of the generator. pub fn return_ty(self) -> Ty<'tcx> { - self.split().return_ty + self.split().return_ty.expect_ty() } /// Returns the "generator signature", which consists of its yield @@ -645,17 +619,7 @@ impl<'tcx> UpvarSubsts<'tcx> { UpvarSubsts::Closure(substs) => substs.as_closure().split().tupled_upvars_ty, UpvarSubsts::Generator(substs) => substs.as_generator().split().tupled_upvars_ty, }; - let upvars = match tupled_upvars_ty.kind { - Tuple(upvars) => upvars, - _ => bug!("upvars should be tupled"), - }; - upvars.iter().map(|t| { - if let GenericArgKind::Type(ty) = t.unpack() { - ty - } else { - bug!("upvar should be type") - } - }) + tupled_upvars_ty.expect_ty().tuple_fields() } }