@@ -5,6 +5,7 @@ use crate::infer::canonical::Canonical;
5
5
use crate :: ty:: { self , Lift , List , Ty , TyCtxt , InferConst , ParamConst } ;
6
6
use crate :: ty:: fold:: { TypeFoldable , TypeFolder , TypeVisitor } ;
7
7
use crate :: mir:: interpret:: ConstValue ;
8
+ use crate :: ty:: sty:: SplitClosureSubsts ;
8
9
9
10
use rustc_serialize:: { self , Encodable , Encoder , Decodable , Decoder } ;
10
11
use syntax_pos:: { Span , DUMMY_SP } ;
@@ -379,6 +380,72 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
379
380
pub fn truncate_to ( & self , tcx : TyCtxt < ' tcx > , generics : & ty:: Generics ) -> SubstsRef < ' tcx > {
380
381
tcx. mk_substs ( self . iter ( ) . take ( generics. count ( ) ) . cloned ( ) )
381
382
}
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
+ }
382
449
}
383
450
384
451
impl < ' tcx > TypeFoldable < ' tcx > for SubstsRef < ' tcx > {
0 commit comments