]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_typeck/check/generator_interior.rs
record upvar into GeneratorInteriorTypeCause
[rust.git] / src / librustc_typeck / check / generator_interior.rs
index db9c8c35c2cee742d77d82899b1f4c8c094e8cfc..aa4abcd7224268fcca52d7432d75e6d46d97fd5c 100644 (file)
@@ -16,6 +16,7 @@
 
 struct InteriorVisitor<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
+    closure_def_id: DefId,
     types: FxHashMap<ty::GeneratorInteriorTypeCause<'tcx>, usize>,
     region_scope_tree: &'tcx region::ScopeTree,
     expr_count: usize,
@@ -30,6 +31,7 @@ fn record(
         scope: Option<region::Scope>,
         expr: Option<&'tcx Expr<'tcx>>,
         source_span: Span,
+        is_upvar: bool,
     ) {
         use rustc_span::DUMMY_SP;
 
@@ -96,6 +98,7 @@ fn record(
                         span: source_span,
                         ty: &ty,
                         scope_span,
+                        yield_span: Some(yield_data.span),
                         expr: expr.map(|e| e.hir_id),
                     })
                     .or_insert(entries);
@@ -116,6 +119,20 @@ fn record(
                     unresolved_type, unresolved_type_span
                 );
                 self.prev_unresolved_span = unresolved_type_span;
+            } else {
+                if is_upvar {
+                    let entries = self.types.len();
+                    let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree));
+                    self.types
+                        .entry(ty::GeneratorInteriorTypeCause {
+                            span: source_span,
+                            ty: &ty,
+                            scope_span,
+                            yield_span: None,
+                            expr: expr.map(|e| e.hir_id),
+                        })
+                        .or_insert(entries);
+                }
             }
         }
     }
@@ -129,8 +146,12 @@ pub fn resolve_interior<'a, 'tcx>(
     kind: hir::GeneratorKind,
 ) {
     let body = fcx.tcx.hir().body(body_id);
+
+    let closure_def_id = fcx.tcx.hir().body_owner_def_id(body_id).to_def_id();
+
     let mut visitor = InteriorVisitor {
         fcx,
+        closure_def_id,
         types: FxHashMap::default(),
         region_scope_tree: fcx.tcx.region_scope_tree(def_id),
         expr_count: 0,
@@ -222,7 +243,7 @@ fn visit_pat(&mut self, pat: &'tcx Pat<'tcx>) {
         if let PatKind::Binding(..) = pat.kind {
             let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id);
             let ty = self.fcx.tables.borrow().pat_ty(pat);
-            self.record(ty, Some(scope), None, pat.span);
+            self.record(ty, Some(scope), None, pat.span, false);
         }
     }
 
@@ -235,9 +256,10 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
                         // Direct calls never need to keep the callee `ty::FnDef`
                         // ZST in a temporary, so skip its type, just in case it
                         // can significantly complicate the generator type.
-                        Res::Def(DefKind::Fn, _)
-                        | Res::Def(DefKind::AssocFn, _)
-                        | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => {
+                        Res::Def(
+                            DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn),
+                            _,
+                        ) => {
                             // NOTE(eddyb) this assumes a path expression has
                             // no nested expressions to keep track of.
                             self.expr_count += 1;
@@ -262,7 +284,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         // If there are adjustments, then record the final type --
         // this is the actual value that is being produced.
         if let Some(adjusted_ty) = self.fcx.tables.borrow().expr_ty_adjusted_opt(expr) {
-            self.record(adjusted_ty, scope, Some(expr), expr.span);
+            self.record(adjusted_ty, scope, Some(expr), expr.span, false);
         }
 
         // Also record the unadjusted type (which is the only type if
@@ -290,9 +312,17 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
         // The type table might not have information for this expression
         // if it is in a malformed scope. (#66387)
         if let Some(ty) = self.fcx.tables.borrow().expr_ty_opt(expr) {
-            self.record(ty, scope, Some(expr), expr.span);
+            self.record(ty, scope, Some(expr), expr.span, false);
         } else {
             self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node");
         }
+
+        if let Some(upvars) = self.fcx.tcx.upvars(self.closure_def_id) {
+            for (upvar_id, upvar) in upvars.iter() {
+                let upvar_ty = self.fcx.tables.borrow().node_type(*upvar_id);
+                debug!("type of upvar: {:?}", upvar_ty);
+                self.record(upvar_ty, scope, Some(expr), upvar.span, true);
+            }
+        }
     }
 }