@@ -5,6 +5,7 @@ use crate::infer::canonical::Canonical;
55use crate :: ty:: { self , Lift , List , Ty , TyCtxt , InferConst , ParamConst } ;
66use crate :: ty:: fold:: { TypeFoldable , TypeFolder , TypeVisitor } ;
77use crate :: mir:: interpret:: ConstValue ;
8+ use crate :: ty:: sty:: SplitClosureSubsts ;
89
910use rustc_serialize:: { self , Encodable , Encoder , Decodable , Decoder } ;
1011use syntax_pos:: { Span , DUMMY_SP } ;
@@ -379,6 +380,72 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
379380 pub fn truncate_to ( & self , tcx : TyCtxt < ' tcx > , generics : & ty:: Generics ) -> SubstsRef < ' tcx > {
380381 tcx. mk_substs ( self . iter ( ) . take ( generics. count ( ) ) . cloned ( ) )
381382 }
383+
384+ /// Divides the closure substs into their respective
385+ /// components. Single source of truth with respect to the
386+ /// ordering.
387+ fn split ( self , def_id : DefId , tcx : TyCtxt < ' _ > ) -> SplitClosureSubsts < ' tcx > {
388+ let generics = tcx. generics_of ( def_id) ;
389+ let parent_len = generics. parent_count ;
390+ SplitClosureSubsts {
391+ closure_kind_ty : self . substs . type_at ( parent_len) ,
392+ closure_sig_ty : self . substs . type_at ( parent_len + 1 ) ,
393+ upvar_kinds : & self . substs [ parent_len + 2 ..] ,
394+ }
395+ }
396+
397+ #[ inline]
398+ pub fn upvar_tys (
399+ & self ,
400+ def_id : DefId ,
401+ tcx : TyCtxt < ' _ > ,
402+ ) -> impl Iterator < Item = Ty < ' tcx > > + ' tcx {
403+ let SplitClosureSubsts { upvar_kinds, .. } = self . split ( def_id, tcx) ;
404+ upvar_kinds. iter ( ) . map ( |t| {
405+ if let UnpackedKind :: Type ( ty) = t. unpack ( ) {
406+ ty
407+ } else {
408+ bug ! ( "upvar should be type" )
409+ }
410+ } )
411+ }
412+
413+ /// Returns the closure kind for this closure; may return a type
414+ /// variable during inference. To get the closure kind during
415+ /// inference, use `infcx.closure_kind(def_id, substs)`.
416+ pub fn closure_kind_ty ( self , def_id : DefId , tcx : TyCtxt < ' _ > ) -> Ty < ' tcx > {
417+ self . split ( def_id, tcx) . closure_kind_ty
418+ }
419+
420+ /// Returns the type representing the closure signature for this
421+ /// closure; may contain type variables during inference. To get
422+ /// the closure signature during inference, use
423+ /// `infcx.fn_sig(def_id)`.
424+ pub fn closure_sig_ty ( self , def_id : DefId , tcx : TyCtxt < ' _ > ) -> Ty < ' tcx > {
425+ self . split ( def_id, tcx) . closure_sig_ty
426+ }
427+
428+ /// Returns the closure kind for this closure; only usable outside
429+ /// of an inference context, because in that context we know that
430+ /// there are no type variables.
431+ ///
432+ /// If you have an inference context, use `infcx.closure_kind()`.
433+ pub fn closure_kind ( self , def_id : DefId , tcx : TyCtxt < ' tcx > ) -> ty:: ClosureKind {
434+ self . split ( def_id, tcx) . closure_kind_ty . to_opt_closure_kind ( ) . unwrap ( )
435+ }
436+
437+ /// Extracts the signature from the closure; only usable outside
438+ /// of an inference context, because in that context we know that
439+ /// there are no type variables.
440+ ///
441+ /// If you have an inference context, use `infcx.closure_sig()`.
442+ pub fn closure_sig ( self , def_id : DefId , tcx : TyCtxt < ' tcx > ) -> ty:: PolyFnSig < ' tcx > {
443+ let ty = self . closure_sig_ty ( def_id, tcx) ;
444+ match ty. kind {
445+ ty:: FnPtr ( sig) => sig,
446+ _ => bug ! ( "closure_sig_ty is not a fn-ptr: {:?}" , ty. kind) ,
447+ }
448+ }
382449}
383450
384451impl < ' tcx > TypeFoldable < ' tcx > for SubstsRef < ' tcx > {
0 commit comments