@@ -5,6 +5,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
55use rustc_hir as hir;
66use rustc_hir:: def:: { CtorKind , CtorOf , DefKind , Res } ;
77use rustc_index:: vec:: Idx ;
8+ use rustc_middle:: hir:: place:: Place as HirPlace ;
89use rustc_middle:: hir:: place:: PlaceBase as HirPlaceBase ;
910use rustc_middle:: hir:: place:: ProjectionKind as HirProjectionKind ;
1011use rustc_middle:: mir:: interpret:: Scalar ;
@@ -452,7 +453,39 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
452453 . zip ( substs. upvar_tys ( ) )
453454 . map ( |( captured_place, ty) | self . capture_upvar ( expr, captured_place, ty) ) ,
454455 ) ;
455- ExprKind :: Closure { closure_id : def_id, substs, upvars, movability }
456+
457+ let fake_reads = match self . typeck_results ( ) . closure_fake_reads . get ( & def_id) {
458+ Some ( vals) => Some ( self . arena . alloc_from_iter ( vals
459+ . iter ( )
460+ . filter ( |val| match val. base {
461+ HirPlaceBase :: Upvar ( _) => true ,
462+ _ => false ,
463+ } )
464+ . map ( |val| {
465+ let var_hir_id = match val. base {
466+ HirPlaceBase :: Upvar ( upvar_id) => {
467+ debug ! ( "upvar" ) ;
468+ upvar_id. var_path . hir_id
469+ }
470+ _ => {
471+ bug ! (
472+ "Do not know how to get HirId out of Rvalue and StaticItem"
473+ ) ;
474+ }
475+ } ;
476+ self . fake_read_capture_upvar ( expr, val. clone ( ) , var_hir_id)
477+ } )
478+ ) ) ,
479+ None => None ,
480+ } ;
481+
482+ ExprKind :: Closure {
483+ closure_id : def_id,
484+ substs,
485+ upvars,
486+ movability,
487+ fake_reads : fake_reads,
488+ }
456489 }
457490
458491 hir:: ExprKind :: Path ( ref qpath) => {
@@ -1012,6 +1045,49 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
10121045 ExprKind :: Deref { arg : ref_expr }
10131046 }
10141047
1048+ fn fake_read_capture_upvar (
1049+ & mut self ,
1050+ closure_expr : & ' tcx hir:: Expr < ' tcx > ,
1051+ place : HirPlace < ' tcx > ,
1052+ hir_id : hir:: HirId ,
1053+ ) -> Expr < ' thir , ' tcx > {
1054+ let temp_lifetime = self . region_scope_tree . temporary_scope ( closure_expr. hir_id . local_id ) ;
1055+ let var_ty = place. base_ty ;
1056+
1057+ let mut captured_place_expr = Expr {
1058+ temp_lifetime,
1059+ ty : var_ty,
1060+ span : closure_expr. span ,
1061+ kind : self . convert_var ( hir_id) ,
1062+ } ;
1063+ // [FIXME] RFC2229 Maybe we should introduce an immutable borrow of the fake capture so that we don't
1064+ // end up moving this place
1065+ for proj in place. projections . iter ( ) {
1066+ let kind = match proj. kind {
1067+ HirProjectionKind :: Deref => {
1068+ ExprKind :: Deref { arg : self . arena . alloc ( captured_place_expr) }
1069+ }
1070+ HirProjectionKind :: Field ( field, ..) => {
1071+ // Variant index will always be 0, because for multi-variant
1072+ // enums, we capture the enum entirely.
1073+ ExprKind :: Field {
1074+ lhs : self . arena . alloc ( captured_place_expr) ,
1075+ name : Field :: new ( field as usize ) ,
1076+ }
1077+ }
1078+ HirProjectionKind :: Index | HirProjectionKind :: Subslice => {
1079+ // We don't capture these projections, so we can ignore them here
1080+ continue ;
1081+ }
1082+ } ;
1083+
1084+ captured_place_expr =
1085+ Expr { temp_lifetime, ty : proj. ty , span : closure_expr. span , kind } ;
1086+ }
1087+
1088+ captured_place_expr
1089+ }
1090+
10151091 fn capture_upvar (
10161092 & mut self ,
10171093 closure_expr : & ' tcx hir:: Expr < ' tcx > ,
0 commit comments