diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 1df60dfc63e..3e4dfccf34d 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -220,7 +220,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty_msg = match local_visitor.found_ty { Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { - let fn_sig = substs.closure_sig(*def_id, self.tcx); + let fn_sig = ty::ClosureSubsts::from_ref(substs).closure_sig(*def_id, self.tcx); let args = closure_args(&fn_sig); let ret = fn_sig.output().skip_binder().to_string(); format!(" for the closure `fn({}) -> {}`", args, ret) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 2e19c9c24e9..ff7cd59720f 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -722,7 +722,7 @@ where ty::Closure(def_id, ref substs) => { // Skip lifetime parameters of the enclosing item(s) - for upvar_ty in substs.upvar_tys(def_id, self.tcx) { + for upvar_ty in ty::ClosureSubsts::from_ref(substs).upvar_tys(def_id, self.tcx) { upvar_ty.visit_with(self); } @@ -886,7 +886,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { let generics = self.tcx.generics_of(def_id); let substs = - self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| { + self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { if index < generics.parent_count { // Accommodate missing regions in the parent kinds... self.fold_kind_mapping_missing_regions_to_empty(kind) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 3f5f54c9463..5595047831c 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -745,7 +745,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // During upvar inference we may not know the // closure kind, just use the LATTICE_BOTTOM value. Some(infcx) => - infcx.closure_kind(closure_def_id, closure_substs) + infcx.closure_kind(closure_def_id, ty::ClosureSubsts::from_ref(closure_substs)) .unwrap_or(ty::ClosureKind::LATTICE_BOTTOM), None => diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index e1ca9a16d96..4d025fe7318 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3370,17 +3370,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )?); // FIXME: chalk + if !self.tcx().sess.opts.debugging_opts.chalk { obligations.push(Obligation::new( obligation.cause.clone(), obligation.param_env, - ty::Predicate::ClosureKind(closure_def_id, substs, kind), + ty::Predicate::ClosureKind(closure_def_id, ty::ClosureSubsts::from_ref(substs.clone()), kind), )); } Ok(VtableClosureData { closure_def_id, - substs: substs.clone(), + substs: ty::ClosureSubsts::from_ref(substs), nested: obligations, }) } @@ -3869,7 +3870,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, closure_def_id: DefId, - substs: ty::ClosureSubsts<'tcx>, + substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { debug!( "closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})", diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 91479751ef4..05c6ec6f97a 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -158,7 +158,7 @@ pub enum TyKind<'tcx> { /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. - Closure(DefId, ClosureSubsts<'tcx>), + Closure(DefId, SubstsRef<'tcx>), /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. @@ -317,13 +317,18 @@ 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> { - closure_kind_ty: Ty<'tcx>, - closure_sig_ty: Ty<'tcx>, - upvar_kinds: &'tcx [GenericArg<'tcx>], +pub(crate) struct SplitClosureSubsts<'tcx> { + pub(crate) closure_kind_ty: Ty<'tcx>, + pub(crate) closure_sig_ty: Ty<'tcx>, + pub(crate) upvar_kinds: &'tcx [GenericArg<'tcx>], } impl<'tcx> ClosureSubsts<'tcx> { + // FIXME(csmoe): remove this method once the migration is done. + pub fn from_ref(substs: SubstsRef<'tcx>) -> Self { + Self { substs } + } + /// Divides the closure substs into their respective /// components. Single source of truth with respect to the /// ordering. @@ -2147,7 +2152,7 @@ impl<'tcx> TyS<'tcx> { Adt(_, substs) | Opaque(_, substs) => { out.extend(substs.regions()) } - Closure(_, ClosureSubsts { ref substs }) | + Closure(_, ref substs ) | Generator(_, GeneratorSubsts { ref substs }, _) => { out.extend(substs.regions()) } diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index e5bee3cfbd0..e17a715e957 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -5,6 +5,7 @@ use crate::infer::canonical::Canonical; use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::mir::interpret::ConstValue; +use crate::ty::sty::SplitClosureSubsts; use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; @@ -379,6 +380,72 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> { tcx.mk_substs(self.iter().take(generics.count()).cloned()) } + + /// Divides the closure substs into their respective + /// components. Single source of truth with respect to the + /// ordering. + fn split(self, def_id: DefId, tcx: TyCtxt<'_>) -> SplitClosureSubsts<'tcx> { + let generics = tcx.generics_of(def_id); + let parent_len = generics.parent_count; + SplitClosureSubsts { + closure_kind_ty: self.substs.type_at(parent_len), + closure_sig_ty: self.substs.type_at(parent_len + 1), + upvar_kinds: &self.substs[parent_len + 2..], + } + } + + #[inline] + pub fn upvar_tys( + &self, + def_id: DefId, + tcx: TyCtxt<'_>, + ) -> impl Iterator> + 'tcx { + let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx); + upvar_kinds.iter().map(|t| { + if let UnpackedKind::Type(ty) = t.unpack() { + ty + } else { + bug!("upvar should be type") + } + }) + } + + /// 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(def_id, substs)`. + pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { + self.split(def_id, tcx).closure_kind_ty + } + + /// Returns the type representing the closure signature for this + /// closure; may contain type variables during inference. To get + /// the closure signature during inference, use + /// `infcx.fn_sig(def_id)`. + pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> { + self.split(def_id, tcx).closure_sig_ty + } + + /// Returns the closure kind for this closure; only usable outside + /// of an inference context, because in that context we know that + /// there are no type variables. + /// + /// If you have an inference context, use `infcx.closure_kind()`. + pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind { + self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap() + } + + /// Extracts the signature from the closure; only usable outside + /// of an inference context, because in that context we know that + /// there are no type variables. + /// + /// If you have an inference context, use `infcx.closure_sig()`. + pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + let ty = self.closure_sig_ty(def_id, tcx); + match ty.kind { + ty::FnPtr(sig) => sig, + _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind), + } + } } impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {