@@ -656,51 +656,54 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
656
656
// FnOnce | copied | upvar -> &'up bk
657
657
// old stack | N/A | upvar -> &'env mut -> &'up bk
658
658
// old proc/once | copied | N/A
659
+ let var_ty = if_ok ! ( self . node_ty( var_id) ) ;
660
+
659
661
let upvar_id = ty:: UpvarId { var_id : var_id,
660
662
closure_expr_id : fn_node_id } ;
661
663
662
- // Do we need to deref through an env reference?
663
- let has_env_deref = kind != ty:: FnOnceUnboxedClosureKind ;
664
-
665
664
// Mutability of original variable itself
666
665
let var_mutbl = MutabilityCategory :: from_local ( self . tcx ( ) , var_id) ;
667
666
668
- // Mutability of environment dereference
669
- let env_mutbl = match kind {
670
- ty:: FnOnceUnboxedClosureKind => var_mutbl,
671
- ty:: FnMutUnboxedClosureKind => McInherited ,
672
- ty:: FnUnboxedClosureKind => McImmutable
667
+ // Construct information about env pointer dereference, if any
668
+ let mutbl = match kind {
669
+ ty:: FnOnceUnboxedClosureKind => None , // None, env is by-value
670
+ ty:: FnMutUnboxedClosureKind => match mode { // Depends on capture type
671
+ ast:: CaptureByValue => Some ( var_mutbl) , // Mutable if the original var is
672
+ ast:: CaptureByRef => Some ( McDeclared ) // Mutable regardless
673
+ } ,
674
+ ty:: FnUnboxedClosureKind => Some ( McImmutable ) // Never mutable
673
675
} ;
676
+ let env_info = mutbl. map ( |env_mutbl| {
677
+ // Look up the node ID of the closure body so we can construct
678
+ // a free region within it
679
+ let fn_body_id = {
680
+ let fn_expr = match self . tcx ( ) . map . find ( fn_node_id) {
681
+ Some ( ast_map:: NodeExpr ( e) ) => e,
682
+ _ => unreachable ! ( )
683
+ } ;
674
684
675
- // Look up the node ID of the closure body so we can construct
676
- // a free region within it
677
- let fn_body_id = {
678
- let fn_expr = match self . tcx ( ) . map . find ( fn_node_id ) {
679
- Some ( ast_map :: NodeExpr ( e ) ) => e ,
680
- _ => unreachable ! ( )
685
+ match fn_expr . node {
686
+ ast :: ExprFnBlock ( _ , _ , ref body ) |
687
+ ast :: ExprProc ( _ , ref body ) |
688
+ ast :: ExprUnboxedFn ( _ , _ , _ , ref body ) => body . id ,
689
+ _ => unreachable ! ( )
690
+ }
681
691
} ;
682
692
683
- match fn_expr. node {
684
- ast:: ExprFnBlock ( _, _, ref body) |
685
- ast:: ExprProc ( _, ref body) |
686
- ast:: ExprUnboxedFn ( _, _, _, ref body) => body. id ,
687
- _ => unreachable ! ( )
688
- }
689
- } ;
693
+ // Region of environment pointer
694
+ let env_region = ty:: ReFree ( ty:: FreeRegion {
695
+ scope_id : fn_body_id,
696
+ bound_region : ty:: BrEnv
697
+ } ) ;
690
698
691
- // Region of environment pointer
692
- let env_region = ty:: ReFree ( ty:: FreeRegion {
693
- scope_id : fn_body_id,
694
- bound_region : ty:: BrEnv
695
- } ) ;
696
-
697
- let env_ptr = BorrowedPtr ( if env_mutbl. is_mutable ( ) {
698
- ty:: MutBorrow
699
- } else {
700
- ty:: ImmBorrow
701
- } , env_region) ;
699
+ let env_ptr = BorrowedPtr ( if env_mutbl. is_mutable ( ) {
700
+ ty:: MutBorrow
701
+ } else {
702
+ ty:: ImmBorrow
703
+ } , env_region) ;
702
704
703
- let var_ty = if_ok ! ( self . node_ty( var_id) ) ;
705
+ ( env_mutbl, env_ptr)
706
+ } ) ;
704
707
705
708
// First, switch by capture mode
706
709
Ok ( match mode {
@@ -718,25 +721,27 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
718
721
note : NoteNone
719
722
} ;
720
723
721
- if has_env_deref {
722
- // We need to add the env deref. This means that
723
- // the above is actually immutable and has a ref
724
- // type. However, nothing should actually look at
725
- // the type, so we can get away with stuffing a
726
- // `ty_err` in there instead of bothering to
727
- // construct a proper one.
728
- base. mutbl = McImmutable ;
729
- base. ty = ty:: mk_err ( ) ;
730
- Rc :: new ( cmt_ {
731
- id : id,
732
- span : span,
733
- cat : cat_deref ( Rc :: new ( base) , 0 , env_ptr) ,
734
- mutbl : env_mutbl,
735
- ty : var_ty,
736
- note : NoteClosureEnv ( upvar_id)
737
- } )
738
- } else {
739
- Rc :: new ( base)
724
+ match env_info {
725
+ Some ( ( env_mutbl, env_ptr) ) => {
726
+ // We need to add the env deref. This means
727
+ // that the above is actually immutable and
728
+ // has a ref type. However, nothing should
729
+ // actually look at the type, so we can get
730
+ // away with stuffing a `ty_err` in there
731
+ // instead of bothering to construct a proper
732
+ // one.
733
+ base. mutbl = McImmutable ;
734
+ base. ty = ty:: mk_err ( ) ;
735
+ Rc :: new ( cmt_ {
736
+ id : id,
737
+ span : span,
738
+ cat : cat_deref ( Rc :: new ( base) , 0 , env_ptr) ,
739
+ mutbl : env_mutbl,
740
+ ty : var_ty,
741
+ note : NoteClosureEnv ( upvar_id)
742
+ } )
743
+ }
744
+ None => Rc :: new ( base)
740
745
}
741
746
} ,
742
747
ast:: CaptureByRef => {
@@ -756,16 +761,18 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
756
761
note : NoteNone
757
762
} ;
758
763
759
- // As in the by-value case, add env deref if needed
760
- if has_env_deref {
761
- base = cmt_ {
762
- id : id,
763
- span : span,
764
- cat : cat_deref ( Rc :: new ( base) , 0 , env_ptr) ,
765
- mutbl : env_mutbl,
766
- ty : ty:: mk_err ( ) ,
767
- note : NoteClosureEnv ( upvar_id)
768
- } ;
764
+ match env_info {
765
+ Some ( ( env_mutbl, env_ptr) ) => {
766
+ base = cmt_ {
767
+ id : id,
768
+ span : span,
769
+ cat : cat_deref ( Rc :: new ( base) , 0 , env_ptr) ,
770
+ mutbl : env_mutbl,
771
+ ty : ty:: mk_err ( ) ,
772
+ note : NoteClosureEnv ( upvar_id)
773
+ } ;
774
+ }
775
+ None => { }
769
776
}
770
777
771
778
// Look up upvar borrow so we can get its region
0 commit comments