]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/upvar.rs
86165d50b27e4366887070a27efd31ee3c35755a
[rust.git] / src / librustc_typeck / check / upvar.rs
1 //! ### Inferring borrow kinds for upvars
2 //!
3 //! Whenever there is a closure expression, we need to determine how each
4 //! upvar is used. We do this by initially assigning each upvar an
5 //! immutable "borrow kind" (see `ty::BorrowKind` for details) and then
6 //! "escalating" the kind as needed. The borrow kind proceeds according to
7 //! the following lattice:
8 //!
9 //!     ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
10 //!
11 //! So, for example, if we see an assignment `x = 5` to an upvar `x`, we
12 //! will promote its borrow kind to mutable borrow. If we see an `&mut x`
13 //! we'll do the same. Naturally, this applies not just to the upvar, but
14 //! to everything owned by `x`, so the result is the same for something
15 //! like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a
16 //! struct). These adjustments are performed in
17 //! `adjust_upvar_borrow_kind()` (you can trace backwards through the code
18 //! from there).
19 //!
20 //! The fact that we are inferring borrow kinds as we go results in a
21 //! semi-hacky interaction with mem-categorization. In particular,
22 //! mem-categorization will query the current borrow kind as it
23 //! categorizes, and we'll return the *current* value, but this may get
24 //! adjusted later. Therefore, in this module, we generally ignore the
25 //! borrow kind (and derived mutabilities) that are returned from
26 //! mem-categorization, since they may be inaccurate. (Another option
27 //! would be to use a unification scheme, where instead of returning a
28 //! concrete borrow kind like `ty::ImmBorrow`, we return a
29 //! `ty::InferBorrow(upvar_id)` or something like that, but this would
30 //! then mean that all later passes would have to check for these figments
31 //! and report an error, and it just seems like more mess in the end.)
32
33 use super::FnCtxt;
34
35 use middle::expr_use_visitor as euv;
36 use middle::mem_categorization as mc;
37 use middle::mem_categorization::Categorization;
38 use rustc::hir;
39 use rustc::hir::def_id::DefId;
40 use rustc::hir::def_id::LocalDefId;
41 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
42 use rustc::infer::UpvarRegion;
43 use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
44 use syntax::ast;
45 use syntax_pos::Span;
46
47 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
48     pub fn closure_analyze(&self, body: &'gcx hir::Body) {
49         InferBorrowKindVisitor { fcx: self }.visit_body(body);
50
51         // it's our job to process these.
52         assert!(self.deferred_call_resolutions.borrow().is_empty());
53     }
54 }
55
56 struct InferBorrowKindVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
57     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
58 }
59
60 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for InferBorrowKindVisitor<'a, 'gcx, 'tcx> {
61     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
62         NestedVisitorMap::None
63     }
64
65     fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
66         if let hir::ExprKind::Closure(cc, _, body_id, _, _) = expr.node {
67             let body = self.fcx.tcx.hir().body(body_id);
68             self.visit_body(body);
69             self.fcx
70                 .analyze_closure(expr.id, expr.hir_id, expr.span, body, cc);
71         }
72
73         intravisit::walk_expr(self, expr);
74     }
75 }
76
77 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
78     fn analyze_closure(
79         &self,
80         closure_node_id: ast::NodeId,
81         closure_hir_id: hir::HirId,
82         span: Span,
83         body: &hir::Body,
84         capture_clause: hir::CaptureClause,
85     ) {
86         /*!
87          * Analysis starting point.
88          */
89
90         debug!(
91             "analyze_closure(id={:?}, body.id={:?})",
92             closure_node_id,
93             body.id()
94         );
95
96         // Extract the type of the closure.
97         let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty {
98             ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
99             ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
100             ty::Error => {
101                 // #51714: skip analysis when we have already encountered type errors
102                 return;
103             }
104             ref t => {
105                 span_bug!(
106                     span,
107                     "type of closure expr {:?} is not a closure {:?}",
108                     closure_node_id,
109                     t
110                 );
111             }
112         };
113
114         let infer_kind = if let UpvarSubsts::Closure(closure_substs) = substs {
115             if self.closure_kind(closure_def_id, closure_substs).is_none() {
116                 Some(closure_substs)
117             } else {
118                 None
119             }
120         } else {
121             None
122         };
123
124         self.tcx.with_freevars(closure_node_id, |freevars| {
125             for freevar in freevars {
126                 let upvar_id = ty::UpvarId {
127                     var_path: ty::UpvarPath {
128                         hir_id : self.tcx.hir().node_to_hir_id(freevar.var_id()),
129                     },
130                     closure_expr_id: LocalDefId::from_def_id(closure_def_id),
131                 };
132                 debug!("seed upvar_id {:?}", upvar_id);
133
134                 let capture_kind = match capture_clause {
135                     hir::CaptureByValue => ty::UpvarCapture::ByValue,
136                     hir::CaptureByRef => {
137                         let origin = UpvarRegion(upvar_id, span);
138                         let freevar_region = self.next_region_var(origin);
139                         let upvar_borrow = ty::UpvarBorrow {
140                             kind: ty::ImmBorrow,
141                             region: freevar_region,
142                         };
143                         ty::UpvarCapture::ByRef(upvar_borrow)
144                     }
145                 };
146
147                 self.tables
148                     .borrow_mut()
149                     .upvar_capture_map
150                     .insert(upvar_id, capture_kind);
151             }
152         });
153
154         let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id());
155         let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
156         let mut delegate = InferBorrowKind {
157             fcx: self,
158             closure_def_id: closure_def_id,
159             current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM,
160             current_origin: None,
161             adjust_upvar_captures: ty::UpvarCaptureMap::default(),
162         };
163         euv::ExprUseVisitor::with_infer(
164             &mut delegate,
165             &self.infcx,
166             self.param_env,
167             region_scope_tree,
168             &self.tables.borrow(),
169         ).consume_body(body);
170
171         if let Some(closure_substs) = infer_kind {
172             // Unify the (as yet unbound) type variable in the closure
173             // substs with the kind we inferred.
174             let inferred_kind = delegate.current_closure_kind;
175             let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
176             self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
177
178             // If we have an origin, store it.
179             if let Some(origin) = delegate.current_origin {
180                 self.tables
181                     .borrow_mut()
182                     .closure_kind_origins_mut()
183                     .insert(closure_hir_id, origin);
184             }
185         }
186
187         self.tables
188             .borrow_mut()
189             .upvar_capture_map
190             .extend(delegate.adjust_upvar_captures);
191
192         // Now that we've analyzed the closure, we know how each
193         // variable is borrowed, and we know what traits the closure
194         // implements (Fn vs FnMut etc). We now have some updates to do
195         // with that information.
196         //
197         // Note that no closure type C may have an upvar of type C
198         // (though it may reference itself via a trait object). This
199         // results from the desugaring of closures to a struct like
200         // `Foo<..., UV0...UVn>`. If one of those upvars referenced
201         // C, then the type would have infinite size (and the
202         // inference algorithm will reject it).
203
204         // Equate the type variables for the upvars with the actual types.
205         let final_upvar_tys = self.final_upvar_tys(closure_node_id);
206         debug!(
207             "analyze_closure: id={:?} substs={:?} final_upvar_tys={:?}",
208             closure_node_id, substs, final_upvar_tys
209         );
210         for (upvar_ty, final_upvar_ty) in substs
211             .upvar_tys(closure_def_id, self.tcx)
212             .zip(final_upvar_tys)
213         {
214             self.demand_suptype(span, upvar_ty, final_upvar_ty);
215         }
216
217         // If we are also inferred the closure kind here,
218         // process any deferred resolutions.
219         let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
220         for deferred_call_resolution in deferred_call_resolutions {
221             deferred_call_resolution.resolve(self);
222         }
223     }
224
225     // Returns a list of `ClosureUpvar`s for each upvar.
226     fn final_upvar_tys(&self, closure_id: ast::NodeId) -> Vec<Ty<'tcx>> {
227         // Presently an unboxed closure type cannot "escape" out of a
228         // function, so we will only encounter ones that originated in the
229         // local crate or were inlined into it along with some function.
230         // This may change if abstract return types of some sort are
231         // implemented.
232         let tcx = self.tcx;
233         let closure_def_index = tcx.hir().local_def_id(closure_id);
234
235         tcx.with_freevars(closure_id, |freevars| {
236             freevars
237                 .iter()
238                 .map(|freevar| {
239                     let var_node_id = freevar.var_id();
240                     let var_hir_id = tcx.hir().node_to_hir_id(var_node_id);
241                     let freevar_ty = self.node_ty(var_hir_id);
242                     let upvar_id = ty::UpvarId {
243                         var_path: ty::UpvarPath {
244                             hir_id: var_hir_id,
245                         },
246                         closure_expr_id: LocalDefId::from_def_id(closure_def_index),
247                     };
248                     let capture = self.tables.borrow().upvar_capture(upvar_id);
249
250                     debug!(
251                         "var_id={:?} freevar_ty={:?} capture={:?}",
252                         var_node_id, freevar_ty, capture
253                     );
254
255                     match capture {
256                         ty::UpvarCapture::ByValue => freevar_ty,
257                         ty::UpvarCapture::ByRef(borrow) => tcx.mk_ref(
258                             borrow.region,
259                             ty::TypeAndMut {
260                                 ty: freevar_ty,
261                                 mutbl: borrow.kind.to_mutbl_lossy(),
262                             },
263                         ),
264                     }
265                 }).collect()
266         })
267     }
268 }
269
270 struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
271     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
272
273     // The def-id of the closure whose kind and upvar accesses are being inferred.
274     closure_def_id: DefId,
275
276     // The kind that we have inferred that the current closure
277     // requires. Note that we *always* infer a minimal kind, even if
278     // we don't always *use* that in the final result (i.e., sometimes
279     // we've taken the closure kind from the expectations instead, and
280     // for generators we don't even implement the closure traits
281     // really).
282     current_closure_kind: ty::ClosureKind,
283
284     // If we modified `current_closure_kind`, this field contains a `Some()` with the
285     // variable access that caused us to do so.
286     current_origin: Option<(Span, ast::Name)>,
287
288     // For each upvar that we access, we track the minimal kind of
289     // access we need (ref, ref mut, move, etc).
290     adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>,
291 }
292
293 impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
294     fn adjust_upvar_borrow_kind_for_consume(
295         &mut self,
296         cmt: &mc::cmt_<'tcx>,
297         mode: euv::ConsumeMode,
298     ) {
299         debug!(
300             "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})",
301             cmt, mode
302         );
303
304         // we only care about moves
305         match mode {
306             euv::Copy => {
307                 return;
308             }
309             euv::Move(_) => {}
310         }
311
312         let tcx = self.fcx.tcx;
313
314         // watch out for a move of the deref of a borrowed pointer;
315         // for that to be legal, the upvar would have to be borrowed
316         // by value instead
317         let guarantor = cmt.guarantor();
318         debug!(
319             "adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
320             guarantor
321         );
322         debug!(
323             "adjust_upvar_borrow_kind_for_consume: guarantor.cat={:?}",
324             guarantor.cat
325         );
326         if let Categorization::Deref(_, mc::BorrowedPtr(..)) = guarantor.cat {
327             debug!(
328                 "adjust_upvar_borrow_kind_for_consume: found deref with note {:?}",
329                 cmt.note
330             );
331             match guarantor.note {
332                 mc::NoteUpvarRef(upvar_id) => {
333                     debug!(
334                         "adjust_upvar_borrow_kind_for_consume: \
335                          setting upvar_id={:?} to by value",
336                         upvar_id
337                     );
338
339                     // to move out of an upvar, this must be a FnOnce closure
340                     self.adjust_closure_kind(
341                         upvar_id.closure_expr_id,
342                         ty::ClosureKind::FnOnce,
343                         guarantor.span,
344                         var_name(tcx, upvar_id.var_path.hir_id),
345                     );
346
347                     self.adjust_upvar_captures
348                         .insert(upvar_id, ty::UpvarCapture::ByValue);
349                 }
350                 mc::NoteClosureEnv(upvar_id) => {
351                     // we get just a closureenv ref if this is a
352                     // `move` closure, or if the upvar has already
353                     // been inferred to by-value. In any case, we
354                     // must still adjust the kind of the closure
355                     // to be a FnOnce closure to permit moves out
356                     // of the environment.
357                     self.adjust_closure_kind(
358                         upvar_id.closure_expr_id,
359                         ty::ClosureKind::FnOnce,
360                         guarantor.span,
361                         var_name(tcx, upvar_id.var_path.hir_id),
362                     );
363                 }
364                 mc::NoteIndex | mc::NoteNone => {}
365             }
366         }
367     }
368
369     /// Indicates that `cmt` is being directly mutated (e.g., assigned
370     /// to). If cmt contains any by-ref upvars, this implies that
371     /// those upvars must be borrowed using an `&mut` borrow.
372     fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'tcx>) {
373         debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt);
374
375         match cmt.cat.clone() {
376             Categorization::Deref(base, mc::Unique)
377             | Categorization::Interior(base, _)
378             | Categorization::Downcast(base, _) => {
379                 // Interior or owned data is mutable if base is
380                 // mutable, so iterate to the base.
381                 self.adjust_upvar_borrow_kind_for_mut(&base);
382             }
383
384             Categorization::Deref(base, mc::BorrowedPtr(..)) => {
385                 if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) {
386                     // assignment to deref of an `&mut`
387                     // borrowed pointer implies that the
388                     // pointer itself must be unique, but not
389                     // necessarily *mutable*
390                     self.adjust_upvar_borrow_kind_for_unique(&base);
391                 }
392             }
393
394             Categorization::Deref(_, mc::UnsafePtr(..))
395             | Categorization::StaticItem
396             | Categorization::ThreadLocal(..)
397             | Categorization::Rvalue(..)
398             | Categorization::Local(_)
399             | Categorization::Upvar(..) => {
400                 return;
401             }
402         }
403     }
404
405     fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'tcx>) {
406         debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt);
407
408         match cmt.cat.clone() {
409             Categorization::Deref(base, mc::Unique)
410             | Categorization::Interior(base, _)
411             | Categorization::Downcast(base, _) => {
412                 // Interior or owned data is unique if base is
413                 // unique.
414                 self.adjust_upvar_borrow_kind_for_unique(&base);
415             }
416
417             Categorization::Deref(base, mc::BorrowedPtr(..)) => {
418                 if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
419                     // for a borrowed pointer to be unique, its
420                     // base must be unique
421                     self.adjust_upvar_borrow_kind_for_unique(&base);
422                 }
423             }
424
425             Categorization::Deref(_, mc::UnsafePtr(..))
426             | Categorization::StaticItem
427             | Categorization::ThreadLocal(..)
428             | Categorization::Rvalue(..)
429             | Categorization::Local(_)
430             | Categorization::Upvar(..) => {}
431         }
432     }
433
434     fn try_adjust_upvar_deref(
435         &mut self,
436         cmt: &mc::cmt_<'tcx>,
437         borrow_kind: ty::BorrowKind,
438     ) -> bool {
439         assert!(match borrow_kind {
440             ty::MutBorrow => true,
441             ty::UniqueImmBorrow => true,
442
443             // imm borrows never require adjusting any kinds, so we don't wind up here
444             ty::ImmBorrow => false,
445         });
446
447         let tcx = self.fcx.tcx;
448
449         match cmt.note {
450             mc::NoteUpvarRef(upvar_id) => {
451                 // if this is an implicit deref of an
452                 // upvar, then we need to modify the
453                 // borrow_kind of the upvar to make sure it
454                 // is inferred to mutable if necessary
455                 self.adjust_upvar_borrow_kind(upvar_id, borrow_kind);
456
457                 // also need to be in an FnMut closure since this is not an ImmBorrow
458                 self.adjust_closure_kind(
459                     upvar_id.closure_expr_id,
460                     ty::ClosureKind::FnMut,
461                     cmt.span,
462                     var_name(tcx, upvar_id.var_path.hir_id),
463                 );
464
465                 true
466             }
467             mc::NoteClosureEnv(upvar_id) => {
468                 // this kind of deref occurs in a `move` closure, or
469                 // for a by-value upvar; in either case, to mutate an
470                 // upvar, we need to be an FnMut closure
471                 self.adjust_closure_kind(
472                     upvar_id.closure_expr_id,
473                     ty::ClosureKind::FnMut,
474                     cmt.span,
475                     var_name(tcx, upvar_id.var_path.hir_id),
476                 );
477
478                 true
479             }
480             mc::NoteIndex | mc::NoteNone => false,
481         }
482     }
483
484     /// We infer the borrow_kind with which to borrow upvars in a stack closure.
485     /// The borrow_kind basically follows a lattice of `imm < unique-imm < mut`,
486     /// moving from left to right as needed (but never right to left).
487     /// Here the argument `mutbl` is the borrow_kind that is required by
488     /// some particular use.
489     fn adjust_upvar_borrow_kind(&mut self, upvar_id: ty::UpvarId, kind: ty::BorrowKind) {
490         let upvar_capture = self
491             .adjust_upvar_captures
492             .get(&upvar_id)
493             .cloned()
494             .unwrap_or_else(|| self.fcx.tables.borrow().upvar_capture(upvar_id));
495         debug!(
496             "adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})",
497             upvar_id, upvar_capture, kind
498         );
499
500         match upvar_capture {
501             ty::UpvarCapture::ByValue => {
502                 // Upvar is already by-value, the strongest criteria.
503             }
504             ty::UpvarCapture::ByRef(mut upvar_borrow) => {
505                 match (upvar_borrow.kind, kind) {
506                     // Take RHS:
507                     (ty::ImmBorrow, ty::UniqueImmBorrow)
508                     | (ty::ImmBorrow, ty::MutBorrow)
509                     | (ty::UniqueImmBorrow, ty::MutBorrow) => {
510                         upvar_borrow.kind = kind;
511                         self.adjust_upvar_captures
512                             .insert(upvar_id, ty::UpvarCapture::ByRef(upvar_borrow));
513                     }
514                     // Take LHS:
515                     (ty::ImmBorrow, ty::ImmBorrow)
516                     | (ty::UniqueImmBorrow, ty::ImmBorrow)
517                     | (ty::UniqueImmBorrow, ty::UniqueImmBorrow)
518                     | (ty::MutBorrow, _) => {}
519                 }
520             }
521         }
522     }
523
524     fn adjust_closure_kind(
525         &mut self,
526         closure_id: LocalDefId,
527         new_kind: ty::ClosureKind,
528         upvar_span: Span,
529         var_name: ast::Name,
530     ) {
531         debug!(
532             "adjust_closure_kind(closure_id={:?}, new_kind={:?}, upvar_span={:?}, var_name={})",
533             closure_id, new_kind, upvar_span, var_name
534         );
535
536         // Is this the closure whose kind is currently being inferred?
537         if closure_id.to_def_id() != self.closure_def_id {
538             debug!("adjust_closure_kind: not current closure");
539             return;
540         }
541
542         // closures start out as `Fn`.
543         let existing_kind = self.current_closure_kind;
544
545         debug!(
546             "adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
547             closure_id, existing_kind, new_kind
548         );
549
550         match (existing_kind, new_kind) {
551             (ty::ClosureKind::Fn, ty::ClosureKind::Fn)
552             | (ty::ClosureKind::FnMut, ty::ClosureKind::Fn)
553             | (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut)
554             | (ty::ClosureKind::FnOnce, _) => {
555                 // no change needed
556             }
557
558             (ty::ClosureKind::Fn, ty::ClosureKind::FnMut)
559             | (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce)
560             | (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
561                 // new kind is stronger than the old kind
562                 self.current_closure_kind = new_kind;
563                 self.current_origin = Some((upvar_span, var_name));
564             }
565         }
566     }
567 }
568
569 impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> {
570     fn consume(
571         &mut self,
572         _consume_id: ast::NodeId,
573         _consume_span: Span,
574         cmt: &mc::cmt_<'tcx>,
575         mode: euv::ConsumeMode,
576     ) {
577         debug!("consume(cmt={:?},mode={:?})", cmt, mode);
578         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
579     }
580
581     fn matched_pat(
582         &mut self,
583         _matched_pat: &hir::Pat,
584         _cmt: &mc::cmt_<'tcx>,
585         _mode: euv::MatchMode,
586     ) {
587     }
588
589     fn consume_pat(
590         &mut self,
591         _consume_pat: &hir::Pat,
592         cmt: &mc::cmt_<'tcx>,
593         mode: euv::ConsumeMode,
594     ) {
595         debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode);
596         self.adjust_upvar_borrow_kind_for_consume(cmt, mode);
597     }
598
599     fn borrow(
600         &mut self,
601         borrow_id: ast::NodeId,
602         _borrow_span: Span,
603         cmt: &mc::cmt_<'tcx>,
604         _loan_region: ty::Region<'tcx>,
605         bk: ty::BorrowKind,
606         _loan_cause: euv::LoanCause,
607     ) {
608         debug!(
609             "borrow(borrow_id={}, cmt={:?}, bk={:?})",
610             borrow_id, cmt, bk
611         );
612
613         match bk {
614             ty::ImmBorrow => {}
615             ty::UniqueImmBorrow => {
616                 self.adjust_upvar_borrow_kind_for_unique(cmt);
617             }
618             ty::MutBorrow => {
619                 self.adjust_upvar_borrow_kind_for_mut(cmt);
620             }
621         }
622     }
623
624     fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) {}
625
626     fn mutate(
627         &mut self,
628         _assignment_id: ast::NodeId,
629         _assignment_span: Span,
630         assignee_cmt: &mc::cmt_<'tcx>,
631         _mode: euv::MutateMode,
632     ) {
633         debug!("mutate(assignee_cmt={:?})", assignee_cmt);
634
635         self.adjust_upvar_borrow_kind_for_mut(assignee_cmt);
636     }
637 }
638
639 fn var_name(tcx: TyCtxt, var_hir_id: hir::HirId) -> ast::Name {
640     let var_node_id = tcx.hir().hir_to_node_id(var_hir_id);
641     tcx.hir().name(var_node_id)
642 }