]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! ### Inferring borrow kinds for upvars | |
12 | //! | |
13 | //! Whenever there is a closure expression, we need to determine how each | |
14 | //! upvar is used. We do this by initially assigning each upvar an | |
15 | //! immutable "borrow kind" (see `ty::BorrowKind` for details) and then | |
16 | //! "escalating" the kind as needed. The borrow kind proceeds according to | |
17 | //! the following lattice: | |
18 | //! | |
19 | //! ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow | |
20 | //! | |
21 | //! So, for example, if we see an assignment `x = 5` to an upvar `x`, we | |
22 | //! will promote its borrow kind to mutable borrow. If we see an `&mut x` | |
23 | //! we'll do the same. Naturally, this applies not just to the upvar, but | |
24 | //! to everything owned by `x`, so the result is the same for something | |
25 | //! like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a | |
26 | //! struct). These adjustments are performed in | |
27 | //! `adjust_upvar_borrow_kind()` (you can trace backwards through the code | |
28 | //! from there). | |
29 | //! | |
30 | //! The fact that we are inferring borrow kinds as we go results in a | |
31 | //! semi-hacky interaction with mem-categorization. In particular, | |
32 | //! mem-categorization will query the current borrow kind as it | |
33 | //! categorizes, and we'll return the *current* value, but this may get | |
34 | //! adjusted later. Therefore, in this module, we generally ignore the | |
35 | //! borrow kind (and derived mutabilities) that are returned from | |
36 | //! mem-categorization, since they may be inaccurate. (Another option | |
37 | //! would be to use a unification scheme, where instead of returning a | |
38 | //! concrete borrow kind like `ty::ImmBorrow`, we return a | |
39 | //! `ty::InferBorrow(upvar_id)` or something like that, but this would | |
40 | //! then mean that all later passes would have to check for these figments | |
41 | //! and report an error, and it just seems like more mess in the end.) | |
42 | ||
43 | use super::FnCtxt; | |
44 | ||
45 | use middle::expr_use_visitor as euv; | |
46 | use middle::mem_categorization as mc; | |
47 | use middle::ty::{self}; | |
48 | use middle::infer::{InferCtxt, UpvarRegion}; | |
85aaf69f | 49 | use std::collections::HashSet; |
1a4d82fc | 50 | use syntax::ast; |
85aaf69f | 51 | use syntax::ast_util; |
1a4d82fc JJ |
52 | use syntax::codemap::Span; |
53 | use syntax::visit::{self, Visitor}; | |
54 | use util::ppaux::Repr; | |
55 | ||
56 | /////////////////////////////////////////////////////////////////////////// | |
57 | // PUBLIC ENTRY POINTS | |
58 | ||
59 | pub fn closure_analyze_fn(fcx: &FnCtxt, | |
60 | _id: ast::NodeId, | |
85aaf69f SL |
61 | _decl: &ast::FnDecl, |
62 | body: &ast::Block) | |
63 | { | |
1a4d82fc JJ |
64 | let mut seed = SeedBorrowKind::new(fcx); |
65 | seed.visit_block(body); | |
85aaf69f | 66 | let closures_with_inferred_kinds = seed.closures_with_inferred_kinds; |
1a4d82fc | 67 | |
85aaf69f SL |
68 | let mut adjust = AdjustBorrowKind::new(fcx, &closures_with_inferred_kinds); |
69 | adjust.visit_block(body); | |
70 | ||
71 | // it's our job to process these. | |
72 | assert!(fcx.inh.deferred_call_resolutions.borrow().is_empty()); | |
1a4d82fc JJ |
73 | } |
74 | ||
75 | /////////////////////////////////////////////////////////////////////////// | |
76 | // SEED BORROW KIND | |
77 | ||
78 | struct SeedBorrowKind<'a,'tcx:'a> { | |
79 | fcx: &'a FnCtxt<'a,'tcx>, | |
85aaf69f | 80 | closures_with_inferred_kinds: HashSet<ast::NodeId>, |
1a4d82fc JJ |
81 | } |
82 | ||
83 | impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> { | |
84 | fn visit_expr(&mut self, expr: &ast::Expr) { | |
85 | match expr.node { | |
85aaf69f | 86 | ast::ExprClosure(cc, _, ref body) => { |
1a4d82fc JJ |
87 | self.check_closure(expr, cc, &**body); |
88 | } | |
89 | ||
90 | _ => { } | |
91 | } | |
92 | ||
93 | visit::walk_expr(self, expr); | |
94 | } | |
95 | ||
96 | fn visit_fn(&mut self, | |
97 | fn_kind: visit::FnKind<'v>, | |
98 | decl: &'v ast::FnDecl, | |
99 | block: &'v ast::Block, | |
100 | span: Span, | |
101 | _id: ast::NodeId) | |
102 | { | |
103 | match fn_kind { | |
104 | visit::FkItemFn(..) | visit::FkMethod(..) => { | |
105 | // ignore nested fn items | |
106 | } | |
107 | visit::FkFnBlock => { | |
108 | visit::walk_fn(self, fn_kind, decl, block, span); | |
109 | } | |
110 | } | |
111 | } | |
112 | } | |
113 | ||
114 | impl<'a,'tcx> SeedBorrowKind<'a,'tcx> { | |
115 | fn new(fcx: &'a FnCtxt<'a,'tcx>) -> SeedBorrowKind<'a,'tcx> { | |
85aaf69f | 116 | SeedBorrowKind { fcx: fcx, closures_with_inferred_kinds: HashSet::new() } |
1a4d82fc JJ |
117 | } |
118 | ||
119 | fn tcx(&self) -> &'a ty::ctxt<'tcx> { | |
120 | self.fcx.tcx() | |
121 | } | |
122 | ||
123 | fn infcx(&self) -> &'a InferCtxt<'a,'tcx> { | |
124 | self.fcx.infcx() | |
125 | } | |
126 | ||
127 | fn check_closure(&mut self, | |
128 | expr: &ast::Expr, | |
129 | capture_clause: ast::CaptureClause, | |
130 | _body: &ast::Block) | |
131 | { | |
85aaf69f SL |
132 | let closure_def_id = ast_util::local_def(expr.id); |
133 | if !self.fcx.inh.closure_kinds.borrow().contains_key(&closure_def_id) { | |
134 | self.closures_with_inferred_kinds.insert(expr.id); | |
135 | self.fcx.inh.closure_kinds.borrow_mut().insert(closure_def_id, ty::FnClosureKind); | |
136 | debug!("check_closure: adding closure_id={} to closures_with_inferred_kinds", | |
137 | closure_def_id.repr(self.tcx())); | |
138 | } | |
1a4d82fc | 139 | |
85aaf69f SL |
140 | ty::with_freevars(self.tcx(), expr.id, |freevars| { |
141 | for freevar in freevars { | |
142 | let var_node_id = freevar.def.local_node_id(); | |
143 | let upvar_id = ty::UpvarId { var_id: var_node_id, | |
144 | closure_expr_id: expr.id }; | |
145 | debug!("seed upvar_id {:?}", upvar_id); | |
146 | ||
147 | let capture_kind = match capture_clause { | |
148 | ast::CaptureByValue => { | |
149 | ty::UpvarCapture::ByValue | |
150 | } | |
151 | ast::CaptureByRef => { | |
1a4d82fc JJ |
152 | let origin = UpvarRegion(upvar_id, expr.span); |
153 | let freevar_region = self.infcx().next_region_var(origin); | |
154 | let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, | |
155 | region: freevar_region }; | |
85aaf69f | 156 | ty::UpvarCapture::ByRef(upvar_borrow) |
1a4d82fc | 157 | } |
85aaf69f SL |
158 | }; |
159 | ||
160 | self.fcx.inh.upvar_capture_map.borrow_mut().insert(upvar_id, capture_kind); | |
1a4d82fc | 161 | } |
85aaf69f | 162 | }); |
1a4d82fc JJ |
163 | } |
164 | } | |
165 | ||
166 | /////////////////////////////////////////////////////////////////////////// | |
167 | // ADJUST BORROW KIND | |
168 | ||
169 | struct AdjustBorrowKind<'a,'tcx:'a> { | |
85aaf69f SL |
170 | fcx: &'a FnCtxt<'a,'tcx>, |
171 | closures_with_inferred_kinds: &'a HashSet<ast::NodeId>, | |
1a4d82fc JJ |
172 | } |
173 | ||
85aaf69f SL |
174 | impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> { |
175 | fn new(fcx: &'a FnCtxt<'a,'tcx>, | |
176 | closures_with_inferred_kinds: &'a HashSet<ast::NodeId>) | |
177 | -> AdjustBorrowKind<'a,'tcx> { | |
178 | AdjustBorrowKind { fcx: fcx, closures_with_inferred_kinds: closures_with_inferred_kinds } | |
1a4d82fc JJ |
179 | } |
180 | ||
181 | fn tcx(&self) -> &'a ty::ctxt<'tcx> { | |
182 | self.fcx.tcx() | |
183 | } | |
184 | ||
85aaf69f | 185 | fn analyze_closure(&mut self, id: ast::NodeId, decl: &ast::FnDecl, body: &ast::Block) { |
1a4d82fc JJ |
186 | /*! |
187 | * Analysis starting point. | |
188 | */ | |
189 | ||
190 | self.visit_block(body); | |
191 | ||
85aaf69f | 192 | debug!("analyzing closure `{}` with fn body id `{}`", id, body.id); |
1a4d82fc JJ |
193 | |
194 | let mut euv = euv::ExprUseVisitor::new(self, self.fcx); | |
195 | euv.walk_fn(decl, body); | |
85aaf69f SL |
196 | |
197 | // If we had not yet settled on a closure kind for this closure, | |
198 | // then we should have by now. Process and remove any deferred resolutions. | |
199 | // | |
200 | // Interesting fact: all calls to this closure must come | |
201 | // *after* its definition. Initially, I thought that some | |
202 | // kind of fixed-point iteration would be required, due to the | |
203 | // possibility of twisted examples like this one: | |
204 | // | |
205 | // ```rust | |
206 | // let mut closure0 = None; | |
207 | // let vec = vec!(1, 2, 3); | |
208 | // | |
209 | // loop { | |
210 | // { | |
211 | // let closure1 = || { | |
212 | // match closure0.take() { | |
213 | // Some(c) => { | |
214 | // return c(); // (*) call to `closure0` before it is defined | |
215 | // } | |
216 | // None => { } | |
217 | // } | |
218 | // }; | |
219 | // closure1(); | |
220 | // } | |
221 | // | |
222 | // closure0 = || vec; | |
223 | // } | |
224 | // ``` | |
225 | // | |
226 | // However, this turns out to be wrong. Examples like this | |
227 | // fail to compile because the type of the variable `c` above | |
228 | // is an inference variable. And in fact since closure types | |
229 | // cannot be written, there is no way to make this example | |
230 | // work without a boxed closure. This implies that we can't | |
231 | // have two closures that recursively call one another without | |
232 | // some form of boxing (and hence explicit writing of a | |
233 | // closure kind) involved. Huzzah. -nmatsakis | |
234 | let closure_def_id = ast_util::local_def(id); | |
235 | if self.closures_with_inferred_kinds.contains(&id) { | |
236 | let mut deferred_call_resolutions = | |
237 | self.fcx.remove_deferred_call_resolutions(closure_def_id); | |
238 | for deferred_call_resolution in deferred_call_resolutions.iter_mut() { | |
239 | deferred_call_resolution.resolve(self.fcx); | |
240 | } | |
241 | } | |
242 | } | |
243 | ||
244 | fn adjust_upvar_borrow_kind_for_consume(&self, | |
245 | cmt: mc::cmt<'tcx>, | |
246 | mode: euv::ConsumeMode) | |
247 | { | |
248 | debug!("adjust_upvar_borrow_kind_for_consume(cmt={}, mode={:?})", | |
249 | cmt.repr(self.tcx()), mode); | |
250 | ||
251 | // we only care about moves | |
252 | match mode { | |
253 | euv::Copy => { return; } | |
254 | euv::Move(_) => { } | |
255 | } | |
256 | ||
257 | // watch out for a move of the deref of a borrowed pointer; | |
258 | // for that to be legal, the upvar would have to be borrowed | |
259 | // by value instead | |
260 | let guarantor = cmt.guarantor(); | |
261 | debug!("adjust_upvar_borrow_kind_for_consume: guarantor={}", | |
262 | guarantor.repr(self.tcx())); | |
263 | match guarantor.cat { | |
264 | mc::cat_deref(_, _, mc::BorrowedPtr(..)) | | |
265 | mc::cat_deref(_, _, mc::Implicit(..)) => { | |
266 | match cmt.note { | |
267 | mc::NoteUpvarRef(upvar_id) => { | |
268 | debug!("adjust_upvar_borrow_kind_for_consume: \ | |
269 | setting upvar_id={:?} to by value", | |
270 | upvar_id); | |
271 | ||
272 | // to move out of an upvar, this must be a FnOnce closure | |
273 | self.adjust_closure_kind(upvar_id.closure_expr_id, ty::FnOnceClosureKind); | |
274 | ||
275 | let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut(); | |
276 | upvar_capture_map.insert(upvar_id, ty::UpvarCapture::ByValue); | |
277 | } | |
278 | mc::NoteClosureEnv(upvar_id) => { | |
279 | // we get just a closureenv ref if this is a | |
280 | // `move` closure, or if the upvar has already | |
281 | // been inferred to by-value. In any case, we | |
282 | // must still adjust the kind of the closure | |
283 | // to be a FnOnce closure to permit moves out | |
284 | // of the environment. | |
285 | self.adjust_closure_kind(upvar_id.closure_expr_id, ty::FnOnceClosureKind); | |
286 | } | |
287 | mc::NoteNone => { | |
288 | } | |
289 | } | |
290 | } | |
291 | _ => { } | |
292 | } | |
1a4d82fc JJ |
293 | } |
294 | ||
295 | /// Indicates that `cmt` is being directly mutated (e.g., assigned | |
296 | /// to). If cmt contains any by-ref upvars, this implies that | |
c34b1796 | 297 | /// those upvars must be borrowed using an `&mut` borrow. |
1a4d82fc JJ |
298 | fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) { |
299 | debug!("adjust_upvar_borrow_kind_for_mut(cmt={})", | |
300 | cmt.repr(self.tcx())); | |
301 | ||
302 | match cmt.cat.clone() { | |
303 | mc::cat_deref(base, _, mc::Unique) | | |
304 | mc::cat_interior(base, _) | | |
305 | mc::cat_downcast(base, _) => { | |
306 | // Interior or owned data is mutable if base is | |
307 | // mutable, so iterate to the base. | |
308 | self.adjust_upvar_borrow_kind_for_mut(base); | |
309 | } | |
310 | ||
311 | mc::cat_deref(base, _, mc::BorrowedPtr(..)) | | |
312 | mc::cat_deref(base, _, mc::Implicit(..)) => { | |
85aaf69f | 313 | if !self.try_adjust_upvar_deref(&cmt.note, ty::MutBorrow) { |
1a4d82fc JJ |
314 | // assignment to deref of an `&mut` |
315 | // borrowed pointer implies that the | |
316 | // pointer itself must be unique, but not | |
317 | // necessarily *mutable* | |
318 | self.adjust_upvar_borrow_kind_for_unique(base); | |
319 | } | |
320 | } | |
321 | ||
322 | mc::cat_deref(_, _, mc::UnsafePtr(..)) | | |
323 | mc::cat_static_item | | |
324 | mc::cat_rvalue(_) | | |
325 | mc::cat_local(_) | | |
326 | mc::cat_upvar(..) => { | |
327 | return; | |
328 | } | |
329 | } | |
330 | } | |
331 | ||
332 | fn adjust_upvar_borrow_kind_for_unique(&self, cmt: mc::cmt<'tcx>) { | |
333 | debug!("adjust_upvar_borrow_kind_for_unique(cmt={})", | |
334 | cmt.repr(self.tcx())); | |
335 | ||
336 | match cmt.cat.clone() { | |
337 | mc::cat_deref(base, _, mc::Unique) | | |
338 | mc::cat_interior(base, _) | | |
339 | mc::cat_downcast(base, _) => { | |
340 | // Interior or owned data is unique if base is | |
341 | // unique. | |
342 | self.adjust_upvar_borrow_kind_for_unique(base); | |
343 | } | |
344 | ||
345 | mc::cat_deref(base, _, mc::BorrowedPtr(..)) | | |
346 | mc::cat_deref(base, _, mc::Implicit(..)) => { | |
85aaf69f | 347 | if !self.try_adjust_upvar_deref(&cmt.note, ty::UniqueImmBorrow) { |
1a4d82fc JJ |
348 | // for a borrowed pointer to be unique, its |
349 | // base must be unique | |
350 | self.adjust_upvar_borrow_kind_for_unique(base); | |
351 | } | |
352 | } | |
353 | ||
354 | mc::cat_deref(_, _, mc::UnsafePtr(..)) | | |
355 | mc::cat_static_item | | |
356 | mc::cat_rvalue(_) | | |
357 | mc::cat_local(_) | | |
358 | mc::cat_upvar(..) => { | |
359 | } | |
360 | } | |
361 | } | |
362 | ||
85aaf69f SL |
363 | fn try_adjust_upvar_deref(&self, |
364 | note: &mc::Note, | |
365 | borrow_kind: ty::BorrowKind) | |
366 | -> bool | |
367 | { | |
368 | assert!(match borrow_kind { | |
369 | ty::MutBorrow => true, | |
370 | ty::UniqueImmBorrow => true, | |
371 | ||
372 | // imm borrows never require adjusting any kinds, so we don't wind up here | |
373 | ty::ImmBorrow => false, | |
374 | }); | |
375 | ||
376 | match *note { | |
377 | mc::NoteUpvarRef(upvar_id) => { | |
378 | // if this is an implicit deref of an | |
379 | // upvar, then we need to modify the | |
380 | // borrow_kind of the upvar to make sure it | |
381 | // is inferred to mutable if necessary | |
382 | let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut(); | |
c34b1796 | 383 | let ub = upvar_capture_map.get_mut(&upvar_id).unwrap(); |
85aaf69f SL |
384 | self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind); |
385 | ||
386 | // also need to be in an FnMut closure since this is not an ImmBorrow | |
387 | self.adjust_closure_kind(upvar_id.closure_expr_id, ty::FnMutClosureKind); | |
388 | ||
389 | true | |
390 | } | |
391 | mc::NoteClosureEnv(upvar_id) => { | |
392 | // this kind of deref occurs in a `move` closure, or | |
393 | // for a by-value upvar; in either case, to mutate an | |
394 | // upvar, we need to be an FnMut closure | |
395 | self.adjust_closure_kind(upvar_id.closure_expr_id, ty::FnMutClosureKind); | |
396 | ||
397 | true | |
398 | } | |
399 | mc::NoteNone => { | |
400 | false | |
401 | } | |
402 | } | |
403 | } | |
404 | ||
1a4d82fc JJ |
405 | /// We infer the borrow_kind with which to borrow upvars in a stack closure. The borrow_kind |
406 | /// basically follows a lattice of `imm < unique-imm < mut`, moving from left to right as needed | |
407 | /// (but never right to left). Here the argument `mutbl` is the borrow_kind that is required by | |
408 | /// some particular use. | |
409 | fn adjust_upvar_borrow_kind(&self, | |
410 | upvar_id: ty::UpvarId, | |
85aaf69f | 411 | upvar_capture: &mut ty::UpvarCapture, |
1a4d82fc | 412 | kind: ty::BorrowKind) { |
85aaf69f SL |
413 | debug!("adjust_upvar_borrow_kind(upvar_id={:?}, upvar_capture={:?}, kind={:?})", |
414 | upvar_id, upvar_capture, kind); | |
415 | ||
416 | match *upvar_capture { | |
417 | ty::UpvarCapture::ByValue => { | |
418 | // Upvar is already by-value, the strongest criteria. | |
1a4d82fc | 419 | } |
85aaf69f SL |
420 | ty::UpvarCapture::ByRef(ref mut upvar_borrow) => { |
421 | match (upvar_borrow.kind, kind) { | |
422 | // Take RHS: | |
423 | (ty::ImmBorrow, ty::UniqueImmBorrow) | | |
424 | (ty::ImmBorrow, ty::MutBorrow) | | |
425 | (ty::UniqueImmBorrow, ty::MutBorrow) => { | |
426 | upvar_borrow.kind = kind; | |
427 | } | |
428 | // Take LHS: | |
429 | (ty::ImmBorrow, ty::ImmBorrow) | | |
430 | (ty::UniqueImmBorrow, ty::ImmBorrow) | | |
431 | (ty::UniqueImmBorrow, ty::UniqueImmBorrow) | | |
432 | (ty::MutBorrow, _) => { | |
433 | } | |
434 | } | |
435 | } | |
436 | } | |
437 | } | |
438 | ||
439 | fn adjust_closure_kind(&self, | |
440 | closure_id: ast::NodeId, | |
441 | new_kind: ty::ClosureKind) { | |
442 | debug!("adjust_closure_kind(closure_id={}, new_kind={:?})", | |
443 | closure_id, new_kind); | |
444 | ||
445 | if !self.closures_with_inferred_kinds.contains(&closure_id) { | |
446 | return; | |
447 | } | |
448 | ||
449 | let closure_def_id = ast_util::local_def(closure_id); | |
450 | let mut closure_kinds = self.fcx.inh.closure_kinds.borrow_mut(); | |
c34b1796 | 451 | let existing_kind = *closure_kinds.get(&closure_def_id).unwrap(); |
85aaf69f SL |
452 | |
453 | debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}", | |
454 | closure_id, existing_kind, new_kind); | |
455 | ||
456 | match (existing_kind, new_kind) { | |
457 | (ty::FnClosureKind, ty::FnClosureKind) | | |
458 | (ty::FnMutClosureKind, ty::FnClosureKind) | | |
459 | (ty::FnMutClosureKind, ty::FnMutClosureKind) | | |
460 | (ty::FnOnceClosureKind, _) => { | |
461 | // no change needed | |
462 | } | |
463 | ||
464 | (ty::FnClosureKind, ty::FnMutClosureKind) | | |
465 | (ty::FnClosureKind, ty::FnOnceClosureKind) | | |
466 | (ty::FnMutClosureKind, ty::FnOnceClosureKind) => { | |
467 | // new kind is stronger than the old kind | |
468 | closure_kinds.insert(closure_def_id, new_kind); | |
1a4d82fc JJ |
469 | } |
470 | } | |
471 | } | |
472 | } | |
473 | ||
474 | impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx> { | |
475 | fn visit_fn(&mut self, | |
476 | fn_kind: visit::FnKind<'v>, | |
477 | decl: &'v ast::FnDecl, | |
478 | body: &'v ast::Block, | |
479 | span: Span, | |
85aaf69f | 480 | id: ast::NodeId) |
1a4d82fc JJ |
481 | { |
482 | match fn_kind { | |
483 | visit::FkItemFn(..) | visit::FkMethod(..) => { | |
484 | // ignore nested fn items | |
485 | } | |
486 | visit::FkFnBlock => { | |
85aaf69f | 487 | self.analyze_closure(id, decl, body); |
1a4d82fc JJ |
488 | visit::walk_fn(self, fn_kind, decl, body, span); |
489 | } | |
490 | } | |
491 | } | |
492 | } | |
493 | ||
494 | impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> { | |
495 | fn consume(&mut self, | |
496 | _consume_id: ast::NodeId, | |
497 | _consume_span: Span, | |
85aaf69f SL |
498 | cmt: mc::cmt<'tcx>, |
499 | mode: euv::ConsumeMode) | |
500 | { | |
501 | debug!("consume(cmt={},mode={:?})", cmt.repr(self.tcx()), mode); | |
502 | self.adjust_upvar_borrow_kind_for_consume(cmt, mode); | |
503 | } | |
1a4d82fc JJ |
504 | |
505 | fn matched_pat(&mut self, | |
506 | _matched_pat: &ast::Pat, | |
507 | _cmt: mc::cmt<'tcx>, | |
508 | _mode: euv::MatchMode) | |
509 | {} | |
510 | ||
511 | fn consume_pat(&mut self, | |
512 | _consume_pat: &ast::Pat, | |
85aaf69f SL |
513 | cmt: mc::cmt<'tcx>, |
514 | mode: euv::ConsumeMode) | |
515 | { | |
516 | debug!("consume_pat(cmt={},mode={:?})", cmt.repr(self.tcx()), mode); | |
517 | self.adjust_upvar_borrow_kind_for_consume(cmt, mode); | |
518 | } | |
1a4d82fc JJ |
519 | |
520 | fn borrow(&mut self, | |
521 | borrow_id: ast::NodeId, | |
522 | _borrow_span: Span, | |
523 | cmt: mc::cmt<'tcx>, | |
524 | _loan_region: ty::Region, | |
525 | bk: ty::BorrowKind, | |
526 | _loan_cause: euv::LoanCause) | |
527 | { | |
528 | debug!("borrow(borrow_id={}, cmt={}, bk={:?})", | |
529 | borrow_id, cmt.repr(self.tcx()), bk); | |
530 | ||
531 | match bk { | |
532 | ty::ImmBorrow => { } | |
533 | ty::UniqueImmBorrow => { | |
534 | self.adjust_upvar_borrow_kind_for_unique(cmt); | |
535 | } | |
536 | ty::MutBorrow => { | |
537 | self.adjust_upvar_borrow_kind_for_mut(cmt); | |
538 | } | |
539 | } | |
540 | } | |
541 | ||
542 | fn decl_without_init(&mut self, | |
543 | _id: ast::NodeId, | |
544 | _span: Span) | |
545 | {} | |
546 | ||
547 | fn mutate(&mut self, | |
548 | _assignment_id: ast::NodeId, | |
549 | _assignment_span: Span, | |
550 | assignee_cmt: mc::cmt<'tcx>, | |
551 | _mode: euv::MutateMode) | |
552 | { | |
553 | debug!("mutate(assignee_cmt={})", | |
554 | assignee_cmt.repr(self.tcx())); | |
555 | ||
556 | self.adjust_upvar_borrow_kind_for_mut(assignee_cmt); | |
557 | } | |
558 | } |