]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/check/regionck.rs
auto merge of #14869 : nick29581/rust/tstore, r=nmatsakis
[rust.git] / src / librustc / middle / typeck / check / regionck.rs
1 // Copyright 2012 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 /*!
12
13 The region check is a final pass that runs over the AST after we have
14 inferred the type constraints but before we have actually finalized
15 the types.  Its purpose is to embed a variety of region constraints.
16 Inserting these constraints as a separate pass is good because (1) it
17 localizes the code that has to do with region inference and (2) often
18 we cannot know what constraints are needed until the basic types have
19 been inferred.
20
21 ### Interaction with the borrow checker
22
23 In general, the job of the borrowck module (which runs later) is to
24 check that all soundness criteria are met, given a particular set of
25 regions. The job of *this* module is to anticipate the needs of the
26 borrow checker and infer regions that will satisfy its requirements.
27 It is generally true that the inference doesn't need to be sound,
28 meaning that if there is a bug and we inferred bad regions, the borrow
29 checker should catch it. This is not entirely true though; for
30 example, the borrow checker doesn't check subtyping, and it doesn't
31 check that region pointers are always live when they are used. It
32 might be worthwhile to fix this so that borrowck serves as a kind of
33 verification step -- that would add confidence in the overall
34 correctness of the compiler, at the cost of duplicating some type
35 checks and effort.
36
37 ### Inferring the duration of borrows, automatic and otherwise
38
39 Whenever we introduce a borrowed pointer, for example as the result of
40 a borrow expression `let x = &data`, the lifetime of the pointer `x`
41 is always specified as a region inference variable. `regionck` has the
42 job of adding constraints such that this inference variable is as
43 narrow as possible while still accommodating all uses (that is, every
44 dereference of the resulting pointer must be within the lifetime).
45
46 #### Reborrows
47
48 Generally speaking, `regionck` does NOT try to ensure that the data
49 `data` will outlive the pointer `x`. That is the job of borrowck.  The
50 one exception is when "re-borrowing" the contents of another borrowed
51 pointer. For example, imagine you have a borrowed pointer `b` with
52 lifetime L1 and you have an expression `&*b`. The result of this
53 expression will be another borrowed pointer with lifetime L2 (which is
54 an inference variable). The borrow checker is going to enforce the
55 constraint that L2 < L1, because otherwise you are re-borrowing data
56 for a lifetime larger than the original loan.  However, without the
57 routines in this module, the region inferencer would not know of this
58 dependency and thus it might infer the lifetime of L2 to be greater
59 than L1 (issue #3148).
60
61 There are a number of troublesome scenarios in the tests
62 `region-dependent-*.rs`, but here is one example:
63
64     struct Foo { i: int }
65     struct Bar { foo: Foo  }
66     fn get_i(x: &'a Bar) -> &'a int {
67        let foo = &x.foo; // Lifetime L1
68        &foo.i            // Lifetime L2
69     }
70
71 Note that this comes up either with `&` expressions, `ref`
72 bindings, and `autorefs`, which are the three ways to introduce
73 a borrow.
74
75 The key point here is that when you are borrowing a value that
76 is "guaranteed" by a borrowed pointer, you must link the
77 lifetime of that borrowed pointer (L1, here) to the lifetime of
78 the borrow itself (L2).  What do I mean by "guaranteed" by a
79 borrowed pointer? I mean any data that is reached by first
80 dereferencing a borrowed pointer and then either traversing
81 interior offsets or owned pointers.  We say that the guarantor
82 of such data it the region of the borrowed pointer that was
83 traversed.  This is essentially the same as the ownership
84 relation, except that a borrowed pointer never owns its
85 contents.
86
87 ### Inferring borrow kinds for upvars
88
89 Whenever there is a closure expression, we need to determine how each
90 upvar is used. We do this by initially assigning each upvar an
91 immutable "borrow kind" (see `ty::BorrowKind` for details) and then
92 "escalating" the kind as needed. The borrow kind proceeds according to
93 the following lattice:
94
95     ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
96
97 So, for example, if we see an assignment `x = 5` to an upvar `x`, we
98 will promote its borrow kind to mutable borrow. If we see an `&mut x`
99 we'll do the same. Naturally, this applies not just to the upvar, but
100 to everything owned by `x`, so the result is the same for something
101 like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a
102 struct). These adjustments are performed in
103 `adjust_upvar_borrow_kind()` (you can trace backwards through the code
104 from there).
105
106 The fact that we are inferring borrow kinds as we go results in a
107 semi-hacky interaction with mem-categorization. In particular,
108 mem-categorization will query the current borrow kind as it
109 categorizes, and we'll return the *current* value, but this may get
110 adjusted later. Therefore, in this module, we generally ignore the
111 borrow kind (and derived mutabilities) that are returned from
112 mem-categorization, since they may be inaccurate. (Another option
113 would be to use a unification scheme, where instead of returning a
114 concrete borrow kind like `ty::ImmBorrow`, we return a
115 `ty::InferBorrow(upvar_id)` or something like that, but this would
116 then mean that all later passes would have to check for these figments
117 and report an error, and it just seems like more mess in the end.)
118
119 */
120
121 use middle::def;
122 use middle::def::{DefArg, DefBinding, DefLocal, DefUpvar};
123 use middle::freevars;
124 use mc = middle::mem_categorization;
125 use middle::ty::{ReScope};
126 use middle::ty;
127 use middle::typeck::astconv::AstConv;
128 use middle::typeck::check::FnCtxt;
129 use middle::typeck::check::regionmanip::relate_nested_regions;
130 use middle::typeck::infer::resolve_and_force_all_but_regions;
131 use middle::typeck::infer::resolve_type;
132 use middle::typeck::infer;
133 use middle::typeck::MethodCall;
134 use middle::pat_util;
135 use util::nodemap::NodeMap;
136 use util::ppaux::{ty_to_str, region_to_str, Repr};
137
138 use syntax::ast;
139 use syntax::codemap::Span;
140 use syntax::visit;
141 use syntax::visit::Visitor;
142
143 use std::cell::RefCell;
144 use std::gc::Gc;
145
146 // If mem categorization results in an error, it's because the type
147 // check failed (or will fail, when the error is uncovered and
148 // reported during writeback). In this case, we just ignore this part
149 // of the code and don't try to add any more region constraints.
150 macro_rules! ignore_err(
151     ($inp: expr) => (
152         match $inp {
153             Ok(v) => v,
154             Err(()) => return
155         }
156     )
157 )
158
159 pub struct Rcx<'a> {
160     fcx: &'a FnCtxt<'a>,
161
162     // id of innermost fn or loop
163     repeating_scope: ast::NodeId,
164 }
165
166 fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
167     /*!
168      * Returns the validity region of `def` -- that is, how long
169      * is `def` valid?
170      */
171
172     let tcx = fcx.tcx();
173     match def {
174         DefLocal(node_id, _) | DefArg(node_id, _) |
175         DefBinding(node_id, _) => {
176             tcx.region_maps.var_region(node_id)
177         }
178         DefUpvar(_, subdef, closure_id, body_id) => {
179             match ty::ty_closure_store(fcx.node_ty(closure_id)) {
180                 ty::RegionTraitStore(..) => region_of_def(fcx, *subdef),
181                 ty::UniqTraitStore => ReScope(body_id)
182             }
183         }
184         _ => {
185             tcx.sess.bug(format!("unexpected def in region_of_def: {:?}",
186                                  def).as_slice())
187         }
188     }
189 }
190
191 impl<'a> Rcx<'a> {
192     pub fn tcx(&self) -> &'a ty::ctxt {
193         self.fcx.ccx.tcx
194     }
195
196     pub fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
197         let old_scope = self.repeating_scope;
198         self.repeating_scope = scope;
199         old_scope
200     }
201
202     pub fn resolve_type(&self, unresolved_ty: ty::t) -> ty::t {
203         /*!
204          * Try to resolve the type for the given node, returning
205          * t_err if an error results.  Note that we never care
206          * about the details of the error, the same error will be
207          * detected and reported in the writeback phase.
208          *
209          * Note one important point: we do not attempt to resolve
210          * *region variables* here.  This is because regionck is
211          * essentially adding constraints to those region variables
212          * and so may yet influence how they are resolved.
213          *
214          * Consider this silly example:
215          *
216          *     fn borrow(x: &int) -> &int {x}
217          *     fn foo(x: @int) -> int {  // block: B
218          *         let b = borrow(x);    // region: <R0>
219          *         *b
220          *     }
221          *
222          * Here, the region of `b` will be `<R0>`.  `<R0>` is
223          * constrainted to be some subregion of the block B and some
224          * superregion of the call.  If we forced it now, we'd choose
225          * the smaller region (the call).  But that would make the *b
226          * illegal.  Since we don't resolve, the type of b will be
227          * `&<R0>.int` and then `*b` will require that `<R0>` be
228          * bigger than the let and the `*b` expression, so we will
229          * effectively resolve `<R0>` to be the block B.
230          */
231         match resolve_type(self.fcx.infcx(), unresolved_ty,
232                            resolve_and_force_all_but_regions) {
233             Ok(t) => t,
234             Err(_) => ty::mk_err()
235         }
236     }
237
238     /// Try to resolve the type for the given node.
239     fn resolve_node_type(&self, id: ast::NodeId) -> ty::t {
240         let t = self.fcx.node_ty(id);
241         self.resolve_type(t)
242     }
243
244     fn resolve_method_type(&self, method_call: MethodCall) -> Option<ty::t> {
245         let method_ty = self.fcx.inh.method_map.borrow()
246                             .find(&method_call).map(|method| method.ty);
247         method_ty.map(|method_ty| self.resolve_type(method_ty))
248     }
249
250     /// Try to resolve the type for the given node.
251     pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> ty::t {
252         let ty_unadjusted = self.resolve_node_type(expr.id);
253         if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) {
254             ty_unadjusted
255         } else {
256             let tcx = self.fcx.tcx();
257             ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
258                           self.fcx.inh.adjustments.borrow().find(&expr.id),
259                           |method_call| self.resolve_method_type(method_call))
260         }
261     }
262 }
263
264 impl<'fcx> mc::Typer for Rcx<'fcx> {
265     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
266         self.fcx.tcx()
267     }
268
269     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
270         let t = self.resolve_node_type(id);
271         if ty::type_is_error(t) {Err(())} else {Ok(t)}
272     }
273
274     fn node_method_ty(&self, method_call: MethodCall) -> Option<ty::t> {
275         self.resolve_method_type(method_call)
276     }
277
278     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
279         &self.fcx.inh.adjustments
280     }
281
282     fn is_method_call(&self, id: ast::NodeId) -> bool {
283         self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
284     }
285
286     fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
287         self.tcx().region_maps.temporary_scope(id)
288     }
289
290     fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
291         self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
292     }
293 }
294
295 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
296     let mut rcx = Rcx { fcx: fcx, repeating_scope: e.id };
297     let rcx = &mut rcx;
298     if fcx.err_count_since_creation() == 0 {
299         // regionck assumes typeck succeeded
300         rcx.visit_expr(e, ());
301     }
302     fcx.infcx().resolve_regions_and_report_errors();
303 }
304
305 pub fn regionck_fn(fcx: &FnCtxt, blk: &ast::Block) {
306     let mut rcx = Rcx { fcx: fcx, repeating_scope: blk.id };
307     let rcx = &mut rcx;
308     if fcx.err_count_since_creation() == 0 {
309         // regionck assumes typeck succeeded
310         rcx.visit_block(blk, ());
311     }
312     fcx.infcx().resolve_regions_and_report_errors();
313 }
314
315 impl<'a> Visitor<()> for Rcx<'a> {
316     // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
317     // However, right now we run into an issue whereby some free
318     // regions are not properly related if they appear within the
319     // types of arguments that must be inferred. This could be
320     // addressed by deferring the construction of the region
321     // hierarchy, and in particular the relationships between free
322     // regions, until regionck, as described in #3238.
323
324     fn visit_item(&mut self, i: &ast::Item, _: ()) { visit_item(self, i); }
325
326     fn visit_expr(&mut self, ex: &ast::Expr, _: ()) { visit_expr(self, ex); }
327
328     //visit_pat: visit_pat, // (..) see above
329
330     fn visit_arm(&mut self, a: &ast::Arm, _: ()) { visit_arm(self, a); }
331
332     fn visit_local(&mut self, l: &ast::Local, _: ()) { visit_local(self, l); }
333
334     fn visit_block(&mut self, b: &ast::Block, _: ()) { visit_block(self, b); }
335 }
336
337 fn visit_item(_rcx: &mut Rcx, _item: &ast::Item) {
338     // Ignore items
339 }
340
341 fn visit_block(rcx: &mut Rcx, b: &ast::Block) {
342     visit::walk_block(rcx, b, ());
343 }
344
345 fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
346     // see above
347     for p in arm.pats.iter() {
348         constrain_bindings_in_pat(&**p, rcx);
349     }
350
351     visit::walk_arm(rcx, arm, ());
352 }
353
354 fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
355     // see above
356     constrain_bindings_in_pat(&*l.pat, rcx);
357     link_local(rcx, l);
358     visit::walk_local(rcx, l, ());
359 }
360
361 fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
362     let tcx = rcx.fcx.tcx();
363     debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
364     pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
365         // If we have a variable that contains region'd data, that
366         // data will be accessible from anywhere that the variable is
367         // accessed. We must be wary of loops like this:
368         //
369         //     // from src/test/compile-fail/borrowck-lend-flow.rs
370         //     let mut v = box 3, w = box 4;
371         //     let mut x = &mut w;
372         //     loop {
373         //         **x += 1;   // (2)
374         //         borrow(v);  //~ ERROR cannot borrow
375         //         x = &mut v; // (1)
376         //     }
377         //
378         // Typically, we try to determine the region of a borrow from
379         // those points where it is dereferenced. In this case, one
380         // might imagine that the lifetime of `x` need only be the
381         // body of the loop. But of course this is incorrect because
382         // the pointer that is created at point (1) is consumed at
383         // point (2), meaning that it must be live across the loop
384         // iteration. The easiest way to guarantee this is to require
385         // that the lifetime of any regions that appear in a
386         // variable's type enclose at least the variable's scope.
387
388         let var_region = tcx.region_maps.var_region(id);
389         constrain_regions_in_type_of_node(
390             rcx, id, var_region,
391             infer::BindingTypeIsNotValidAtDecl(span));
392     })
393 }
394
395 fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
396     debug!("regionck::visit_expr(e={}, repeating_scope={:?})",
397            expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
398
399     let method_call = MethodCall::expr(expr.id);
400     let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call);
401
402     // Check any autoderefs or autorefs that appear.
403     for &adjustment in rcx.fcx.inh.adjustments.borrow().find(&expr.id).iter() {
404         debug!("adjustment={:?}", adjustment);
405         match *adjustment {
406             ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: opt_autoref}) => {
407                 let expr_ty = rcx.resolve_node_type(expr.id);
408                 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
409                 for autoref in opt_autoref.iter() {
410                     link_autoref(rcx, expr, autoderefs, autoref);
411
412                     // Require that the resulting region encompasses
413                     // the current node.
414                     //
415                     // FIXME(#6268) remove to support nested method calls
416                     constrain_regions_in_type_of_node(
417                         rcx, expr.id, ty::ReScope(expr.id),
418                         infer::AutoBorrow(expr.span));
419                 }
420             }
421             ty::AutoObject(ty::RegionTraitStore(trait_region, _), _, _, _) => {
422                 // Determine if we are casting `expr` to a trait
423                 // instance.  If so, we have to be sure that the type of
424                 // the source obeys the trait's region bound.
425                 //
426                 // Note: there is a subtle point here concerning type
427                 // parameters.  It is possible that the type of `source`
428                 // contains type parameters, which in turn may contain
429                 // regions that are not visible to us (only the caller
430                 // knows about them).  The kind checker is ultimately
431                 // responsible for guaranteeing region safety in that
432                 // particular case.  There is an extensive comment on the
433                 // function check_cast_for_escaping_regions() in kind.rs
434                 // explaining how it goes about doing that.
435
436                 let source_ty = rcx.resolve_node_type(expr.id);
437                 constrain_regions_in_type(rcx, trait_region,
438                                             infer::RelateObjectBound(expr.span), source_ty);
439             }
440             _ => {}
441         }
442     }
443
444     match expr.node {
445         ast::ExprCall(ref callee, ref args) => {
446             if has_method_map {
447                 constrain_call(rcx, None, expr, Some(*callee),
448                                args.as_slice(), false);
449             } else {
450                 constrain_callee(rcx, callee.id, expr, &**callee);
451                 constrain_call(rcx,
452                                Some(callee.id),
453                                expr,
454                                None,
455                                args.as_slice(),
456                                false);
457             }
458
459             visit::walk_expr(rcx, expr, ());
460         }
461
462         ast::ExprMethodCall(_, _, ref args) => {
463             constrain_call(rcx, None, expr, Some(*args.get(0)),
464                            args.slice_from(1), false);
465
466             visit::walk_expr(rcx, expr, ());
467         }
468
469         ast::ExprAssign(ref lhs, _) => {
470             adjust_borrow_kind_for_assignment_lhs(rcx, &**lhs);
471             visit::walk_expr(rcx, expr, ());
472         }
473
474         ast::ExprAssignOp(_, ref lhs, ref rhs) => {
475             if has_method_map {
476                 constrain_call(rcx, None, expr, Some(lhs.clone()),
477                                [rhs.clone()], true);
478             }
479
480             adjust_borrow_kind_for_assignment_lhs(rcx, &**lhs);
481
482             visit::walk_expr(rcx, expr, ());
483         }
484
485         ast::ExprIndex(ref lhs, ref rhs) |
486         ast::ExprBinary(_, ref lhs, ref rhs) if has_method_map => {
487             // As `expr_method_call`, but the call is via an
488             // overloaded op.  Note that we (sadly) currently use an
489             // implicit "by ref" sort of passing style here.  This
490             // should be converted to an adjustment!
491             constrain_call(rcx, None, expr, Some(lhs.clone()),
492                            [rhs.clone()], true);
493
494             visit::walk_expr(rcx, expr, ());
495         }
496
497         ast::ExprUnary(_, ref lhs) if has_method_map => {
498             // As above.
499             constrain_call(rcx, None, expr, Some(lhs.clone()), [], true);
500
501             visit::walk_expr(rcx, expr, ());
502         }
503
504         ast::ExprUnary(ast::UnDeref, ref base) => {
505             // For *a, the lifetime of a must enclose the deref
506             let method_call = MethodCall::expr(expr.id);
507             let base_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
508                 Some(method) => {
509                     constrain_call(rcx, None, expr, Some(base.clone()), [], true);
510                     ty::ty_fn_ret(method.ty)
511                 }
512                 None => rcx.resolve_node_type(base.id)
513             };
514             match ty::get(base_ty).sty {
515                 ty::ty_rptr(r_ptr, _) => {
516                     mk_subregion_due_to_dereference(rcx, expr.span,
517                                                     ty::ReScope(expr.id), r_ptr);
518                 }
519                 _ => {}
520             }
521
522             visit::walk_expr(rcx, expr, ());
523         }
524
525         ast::ExprIndex(ref vec_expr, _) => {
526             // For a[b], the lifetime of a must enclose the deref
527             let vec_type = rcx.resolve_expr_type_adjusted(&**vec_expr);
528             constrain_index(rcx, expr, vec_type);
529
530             visit::walk_expr(rcx, expr, ());
531         }
532
533         ast::ExprCast(ref source, _) => {
534             // Determine if we are casting `source` to a trait
535             // instance.  If so, we have to be sure that the type of
536             // the source obeys the trait's region bound.
537             //
538             // Note: there is a subtle point here concerning type
539             // parameters.  It is possible that the type of `source`
540             // contains type parameters, which in turn may contain
541             // regions that are not visible to us (only the caller
542             // knows about them).  The kind checker is ultimately
543             // responsible for guaranteeing region safety in that
544             // particular case.  There is an extensive comment on the
545             // function check_cast_for_escaping_regions() in kind.rs
546             // explaining how it goes about doing that.
547             let target_ty = rcx.resolve_node_type(expr.id);
548             match ty::get(target_ty).sty {
549                 ty::ty_rptr(trait_region, ty::mt{ty, ..}) => {
550                     match ty::get(ty).sty {
551                         ty::ty_trait(..) => {
552                             let source_ty = rcx.resolve_expr_type_adjusted(&**source);
553                             constrain_regions_in_type(
554                                 rcx,
555                                 trait_region,
556                                 infer::RelateObjectBound(expr.span),
557                                 source_ty);
558                         }
559                         _ => {}
560                     }
561                 }
562                 _ => ()
563             }
564
565             visit::walk_expr(rcx, expr, ());
566         }
567
568         ast::ExprAddrOf(m, ref base) => {
569             link_addr_of(rcx, expr, m, &**base);
570
571             // Require that when you write a `&expr` expression, the
572             // resulting pointer has a lifetime that encompasses the
573             // `&expr` expression itself. Note that we constraining
574             // the type of the node expr.id here *before applying
575             // adjustments*.
576             //
577             // FIXME(#6268) nested method calls requires that this rule change
578             let ty0 = rcx.resolve_node_type(expr.id);
579             constrain_regions_in_type(rcx, ty::ReScope(expr.id),
580                                       infer::AddrOf(expr.span), ty0);
581             visit::walk_expr(rcx, expr, ());
582         }
583
584         ast::ExprMatch(ref discr, ref arms) => {
585             link_match(rcx, &**discr, arms.as_slice());
586
587             visit::walk_expr(rcx, expr, ());
588         }
589
590         ast::ExprFnBlock(_, ref body) | ast::ExprProc(_, ref body) => {
591             check_expr_fn_block(rcx, expr, &**body);
592         }
593
594         ast::ExprLoop(ref body, _) => {
595             let repeating_scope = rcx.set_repeating_scope(body.id);
596             visit::walk_expr(rcx, expr, ());
597             rcx.set_repeating_scope(repeating_scope);
598         }
599
600         ast::ExprWhile(ref cond, ref body) => {
601             let repeating_scope = rcx.set_repeating_scope(cond.id);
602             rcx.visit_expr(&**cond, ());
603
604             rcx.set_repeating_scope(body.id);
605             rcx.visit_block(&**body, ());
606
607             rcx.set_repeating_scope(repeating_scope);
608         }
609
610         _ => {
611             visit::walk_expr(rcx, expr, ());
612         }
613     }
614 }
615
616 fn check_expr_fn_block(rcx: &mut Rcx,
617                        expr: &ast::Expr,
618                        body: &ast::Block) {
619     let tcx = rcx.fcx.tcx();
620     let function_type = rcx.resolve_node_type(expr.id);
621     match ty::get(function_type).sty {
622         ty::ty_closure(box ty::ClosureTy {
623                 store: ty::RegionTraitStore(region, _), ..}) => {
624             freevars::with_freevars(tcx, expr.id, |freevars| {
625                 if freevars.is_empty() {
626                     // No free variables means that the environment
627                     // will be NULL at runtime and hence the closure
628                     // has static lifetime.
629                 } else {
630                     // Closure must not outlive the variables it closes over.
631                     constrain_free_variables(rcx, region, expr, freevars);
632
633                     // Closure cannot outlive the appropriate temporary scope.
634                     let s = rcx.repeating_scope;
635                     rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span),
636                                     region, ty::ReScope(s));
637                 }
638             });
639         }
640         _ => ()
641     }
642
643     let repeating_scope = rcx.set_repeating_scope(body.id);
644     visit::walk_expr(rcx, expr, ());
645     rcx.set_repeating_scope(repeating_scope);
646
647     match ty::get(function_type).sty {
648         ty::ty_closure(box ty::ClosureTy {
649                 store: ty::RegionTraitStore(..),
650                 ..
651             }) => {
652             freevars::with_freevars(tcx, expr.id, |freevars| {
653                 propagate_upupvar_borrow_kind(rcx, expr, freevars);
654             })
655         }
656         _ => ()
657     }
658
659     fn constrain_free_variables(rcx: &mut Rcx,
660                                 region: ty::Region,
661                                 expr: &ast::Expr,
662                                 freevars: &[freevars::freevar_entry]) {
663         /*!
664          * Make sure that all free variables referenced inside the closure
665          * outlive the closure itself. Also, create an entry in the
666          * upvar_borrows map with a region.
667          */
668
669         let tcx = rcx.fcx.ccx.tcx;
670         let infcx = rcx.fcx.infcx();
671         debug!("constrain_free_variables({}, {})",
672                region.repr(tcx), expr.repr(tcx));
673         for freevar in freevars.iter() {
674             debug!("freevar def is {:?}", freevar.def);
675
676             // Identify the variable being closed over and its node-id.
677             let def = freevar.def;
678             let def_id = def.def_id();
679             assert!(def_id.krate == ast::LOCAL_CRATE);
680             let upvar_id = ty::UpvarId { var_id: def_id.node,
681                                          closure_expr_id: expr.id };
682
683             // Create a region variable to represent this borrow. This borrow
684             // must outlive the region on the closure.
685             let origin = infer::UpvarRegion(upvar_id, expr.span);
686             let freevar_region = infcx.next_region_var(origin);
687             rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node),
688                             region, freevar_region);
689
690             // Create a UpvarBorrow entry. Note that we begin with a
691             // const borrow_kind, but change it to either mut or
692             // immutable as dictated by the uses.
693             let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow,
694                                                  region: freevar_region };
695             rcx.fcx.inh.upvar_borrow_map.borrow_mut().insert(upvar_id,
696                                                              upvar_borrow);
697
698             // Guarantee that the closure does not outlive the variable itself.
699             let en_region = region_of_def(rcx.fcx, def);
700             debug!("en_region = {}", en_region.repr(tcx));
701             rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node),
702                             region, en_region);
703         }
704     }
705
706     fn propagate_upupvar_borrow_kind(rcx: &mut Rcx,
707                                      expr: &ast::Expr,
708                                      freevars: &[freevars::freevar_entry]) {
709         let tcx = rcx.fcx.ccx.tcx;
710         debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
711         for freevar in freevars.iter() {
712             // Because of the semi-hokey way that we are doing
713             // borrow_kind inference, we need to check for
714             // indirect dependencies, like so:
715             //
716             //     let mut x = 0;
717             //     outer_call(|| {
718             //         inner_call(|| {
719             //             x = 1;
720             //         });
721             //     });
722             //
723             // Here, the `inner_call` is basically "reborrowing" the
724             // outer pointer. With no other changes, `inner_call`
725             // would infer that it requires a mutable borrow, but
726             // `outer_call` would infer that a const borrow is
727             // sufficient. This is because we haven't linked the
728             // borrow_kind of the borrow that occurs in the inner
729             // closure to the borrow_kind of the borrow in the outer
730             // closure. Note that regions *are* naturally linked
731             // because we have a proper inference scheme there.
732             //
733             // Anyway, for borrow_kind, we basically go back over now
734             // after checking the inner closure (and hence
735             // determining the final borrow_kind) and propagate that as
736             // a constraint on the outer closure.
737             match freevar.def {
738                 def::DefUpvar(var_id, _, outer_closure_id, _) => {
739                     // thing being captured is itself an upvar:
740                     let outer_upvar_id = ty::UpvarId {
741                         var_id: var_id,
742                         closure_expr_id: outer_closure_id };
743                     let inner_upvar_id = ty::UpvarId {
744                         var_id: var_id,
745                         closure_expr_id: expr.id };
746                     link_upvar_borrow_kind_for_nested_closures(rcx,
747                                                                inner_upvar_id,
748                                                                outer_upvar_id);
749                 }
750                 _ => {}
751             }
752         }
753     }
754 }
755
756 fn constrain_callee(rcx: &mut Rcx,
757                     callee_id: ast::NodeId,
758                     call_expr: &ast::Expr,
759                     callee_expr: &ast::Expr) {
760     let call_region = ty::ReScope(call_expr.id);
761
762     let callee_ty = rcx.resolve_node_type(callee_id);
763     match ty::get(callee_ty).sty {
764         ty::ty_bare_fn(..) => { }
765         ty::ty_closure(ref closure_ty) => {
766             let region = match closure_ty.store {
767                 ty::RegionTraitStore(r, _) => {
768                     // While we're here, link the closure's region with a unique
769                     // immutable borrow (gathered later in borrowck)
770                     let mc = mc::MemCategorizationContext::new(rcx);
771                     let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
772                     link_region(rcx, callee_expr.span, call_region,
773                                 ty::UniqueImmBorrow, expr_cmt);
774                     r
775                 }
776                 ty::UniqTraitStore => ty::ReStatic
777             };
778             rcx.fcx.mk_subr(true, infer::InvokeClosure(callee_expr.span),
779                             call_region, region);
780         }
781         _ => {
782             // this should not happen, but it does if the program is
783             // erroneous
784             //
785             // tcx.sess.span_bug(
786             //     callee_expr.span,
787             //     format!("Calling non-function: {}", callee_ty.repr(tcx)));
788         }
789     }
790 }
791
792 fn constrain_call(rcx: &mut Rcx,
793                   // might be expr_call, expr_method_call, or an overloaded
794                   // operator
795                   fn_expr_id: Option<ast::NodeId>,
796                   call_expr: &ast::Expr,
797                   receiver: Option<Gc<ast::Expr>>,
798                   arg_exprs: &[Gc<ast::Expr>],
799                   implicitly_ref_args: bool) {
800     //! Invoked on every call site (i.e., normal calls, method calls,
801     //! and overloaded operators). Constrains the regions which appear
802     //! in the type of the function. Also constrains the regions that
803     //! appear in the arguments appropriately.
804
805     let tcx = rcx.fcx.tcx();
806     debug!("constrain_call(call_expr={}, \
807             receiver={}, \
808             arg_exprs={}, \
809             implicitly_ref_args={:?})",
810             call_expr.repr(tcx),
811             receiver.repr(tcx),
812             arg_exprs.repr(tcx),
813             implicitly_ref_args);
814     let callee_ty = match fn_expr_id {
815         Some(id) => rcx.resolve_node_type(id),
816         None => rcx.resolve_method_type(MethodCall::expr(call_expr.id))
817                    .expect("call should have been to a method")
818     };
819     if ty::type_is_error(callee_ty) {
820         // Bail, as function type is unknown
821         return;
822     }
823     let fn_sig = ty::ty_fn_sig(callee_ty);
824
825     // `callee_region` is the scope representing the time in which the
826     // call occurs.
827     //
828     // FIXME(#6268) to support nested method calls, should be callee_id
829     let callee_scope = call_expr.id;
830     let callee_region = ty::ReScope(callee_scope);
831
832     for arg_expr in arg_exprs.iter() {
833         debug!("Argument");
834
835         // ensure that any regions appearing in the argument type are
836         // valid for at least the lifetime of the function:
837         constrain_regions_in_type_of_node(
838             rcx, arg_expr.id, callee_region,
839             infer::CallArg(arg_expr.span));
840
841         // unfortunately, there are two means of taking implicit
842         // references, and we need to propagate constraints as a
843         // result. modes are going away and the "DerefArgs" code
844         // should be ported to use adjustments
845         if implicitly_ref_args {
846             link_by_ref(rcx, &**arg_expr, callee_scope);
847         }
848     }
849
850     // as loop above, but for receiver
851     for r in receiver.iter() {
852         debug!("Receiver");
853         constrain_regions_in_type_of_node(
854             rcx, r.id, callee_region, infer::CallRcvr(r.span));
855         if implicitly_ref_args {
856             link_by_ref(rcx, &**r, callee_scope);
857         }
858     }
859
860     // constrain regions that may appear in the return type to be
861     // valid for the function call:
862     constrain_regions_in_type(
863         rcx, callee_region, infer::CallReturn(call_expr.span),
864         fn_sig.output);
865 }
866
867 fn constrain_autoderefs(rcx: &mut Rcx,
868                         deref_expr: &ast::Expr,
869                         derefs: uint,
870                         mut derefd_ty: ty::t) {
871     /*!
872      * Invoked on any auto-dereference that occurs.  Checks that if
873      * this is a region pointer being dereferenced, the lifetime of
874      * the pointer includes the deref expr.
875      */
876     let r_deref_expr = ty::ReScope(deref_expr.id);
877     for i in range(0u, derefs) {
878         debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={:?}/{:?}",
879                rcx.fcx.infcx().ty_to_str(derefd_ty),
880                i, derefs);
881
882         let method_call = MethodCall::autoderef(deref_expr.id, i as u32);
883         derefd_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
884             Some(method) => {
885                 // Treat overloaded autoderefs as if an AutoRef adjustment
886                 // was applied on the base type, as that is always the case.
887                 let fn_sig = ty::ty_fn_sig(method.ty);
888                 let self_ty = *fn_sig.inputs.get(0);
889                 let (m, r) = match ty::get(self_ty).sty {
890                     ty::ty_rptr(r, ref m) => (m.mutbl, r),
891                     _ => rcx.tcx().sess.span_bug(deref_expr.span,
892                             format!("bad overloaded deref type {}",
893                                     method.ty.repr(rcx.tcx())).as_slice())
894                 };
895                 {
896                     let mc = mc::MemCategorizationContext::new(rcx);
897                     let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
898                     link_region(rcx, deref_expr.span, r,
899                                 ty::BorrowKind::from_mutbl(m), self_cmt);
900                 }
901
902                 // Specialized version of constrain_call.
903                 constrain_regions_in_type(rcx, r_deref_expr,
904                                           infer::CallRcvr(deref_expr.span),
905                                           self_ty);
906                 constrain_regions_in_type(rcx, r_deref_expr,
907                                           infer::CallReturn(deref_expr.span),
908                                           fn_sig.output);
909                 fn_sig.output
910             }
911             None => derefd_ty
912         };
913
914         match ty::get(derefd_ty).sty {
915             ty::ty_rptr(r_ptr, _) => {
916                 mk_subregion_due_to_dereference(rcx, deref_expr.span,
917                                                 r_deref_expr, r_ptr);
918             }
919             _ => {}
920         }
921
922         match ty::deref(derefd_ty, true) {
923             Some(mt) => derefd_ty = mt.ty,
924             /* if this type can't be dereferenced, then there's already an error
925                in the session saying so. Just bail out for now */
926             None => break
927         }
928     }
929 }
930
931 pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
932                                        deref_span: Span,
933                                        minimum_lifetime: ty::Region,
934                                        maximum_lifetime: ty::Region) {
935     rcx.fcx.mk_subr(true, infer::DerefPointer(deref_span),
936                     minimum_lifetime, maximum_lifetime)
937 }
938
939
940 fn constrain_index(rcx: &mut Rcx,
941                    index_expr: &ast::Expr,
942                    indexed_ty: ty::t)
943 {
944     /*!
945      * Invoked on any index expression that occurs.  Checks that if
946      * this is a slice being indexed, the lifetime of the pointer
947      * includes the deref expr.
948      */
949
950     debug!("constrain_index(index_expr=?, indexed_ty={}",
951            rcx.fcx.infcx().ty_to_str(indexed_ty));
952
953     let r_index_expr = ty::ReScope(index_expr.id);
954     match ty::get(indexed_ty).sty {
955         ty::ty_rptr(r_ptr, mt) => match ty::get(mt.ty).sty {
956             ty::ty_vec(_, None) | ty::ty_str => {
957                 rcx.fcx.mk_subr(true, infer::IndexSlice(index_expr.span),
958                                 r_index_expr, r_ptr);
959             }
960             _ => {}
961         },
962
963         _ => {}
964     }
965 }
966
967 fn constrain_regions_in_type_of_node(
968     rcx: &mut Rcx,
969     id: ast::NodeId,
970     minimum_lifetime: ty::Region,
971     origin: infer::SubregionOrigin) {
972     //! Guarantees that any lifetimes which appear in the type of
973     //! the node `id` (after applying adjustments) are valid for at
974     //! least `minimum_lifetime`
975
976     let tcx = rcx.fcx.tcx();
977
978     // Try to resolve the type.  If we encounter an error, then typeck
979     // is going to fail anyway, so just stop here and let typeck
980     // report errors later on in the writeback phase.
981     let ty0 = rcx.resolve_node_type(id);
982     let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
983                            rcx.fcx.inh.adjustments.borrow().find(&id),
984                            |method_call| rcx.resolve_method_type(method_call));
985     debug!("constrain_regions_in_type_of_node(\
986             ty={}, ty0={}, id={}, minimum_lifetime={:?})",
987            ty_to_str(tcx, ty), ty_to_str(tcx, ty0),
988            id, minimum_lifetime);
989     constrain_regions_in_type(rcx, minimum_lifetime, origin, ty);
990 }
991
992 fn constrain_regions_in_type(
993     rcx: &mut Rcx,
994     minimum_lifetime: ty::Region,
995     origin: infer::SubregionOrigin,
996     ty: ty::t) {
997     /*!
998      * Requires that any regions which appear in `ty` must be
999      * superregions of `minimum_lifetime`.  Also enforces the constraint
1000      * that given a pointer type `&'r T`, T must not contain regions
1001      * that outlive 'r, as well as analogous constraints for other
1002      * lifetime'd types.
1003      *
1004      * This check prevents regions from being used outside of the block in
1005      * which they are valid.  Recall that regions represent blocks of
1006      * code or expressions: this requirement basically says "any place
1007      * that uses or may use a region R must be within the block of
1008      * code that R corresponds to."
1009      */
1010
1011     let tcx = rcx.fcx.ccx.tcx;
1012
1013     debug!("constrain_regions_in_type(minimum_lifetime={}, ty={})",
1014            region_to_str(tcx, "", false, minimum_lifetime),
1015            ty_to_str(tcx, ty));
1016
1017     relate_nested_regions(tcx, Some(minimum_lifetime), ty, |r_sub, r_sup| {
1018         debug!("relate_nested_regions(r_sub={}, r_sup={})",
1019                 r_sub.repr(tcx),
1020                 r_sup.repr(tcx));
1021
1022         if r_sup.is_bound() || r_sub.is_bound() {
1023             // a bound region is one which appears inside an fn type.
1024             // (e.g., the `&` in `fn(&T)`).  Such regions need not be
1025             // constrained by `minimum_lifetime` as they are placeholders
1026             // for regions that are as-yet-unknown.
1027         } else if r_sub == minimum_lifetime {
1028             rcx.fcx.mk_subr(
1029                 true, origin.clone(),
1030                 r_sub, r_sup);
1031         } else {
1032             rcx.fcx.mk_subr(
1033                 true, infer::ReferenceOutlivesReferent(ty, origin.span()),
1034                 r_sub, r_sup);
1035         }
1036     });
1037 }
1038
1039 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
1040                mutability: ast::Mutability, base: &ast::Expr) {
1041     /*!
1042      * Computes the guarantor for an expression `&base` and then
1043      * ensures that the lifetime of the resulting pointer is linked
1044      * to the lifetime of its guarantor (if any).
1045      */
1046
1047     debug!("link_addr_of(base=?)");
1048
1049     let cmt = {
1050         let mc = mc::MemCategorizationContext::new(rcx);
1051         ignore_err!(mc.cat_expr(base))
1052     };
1053     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
1054 }
1055
1056 fn link_local(rcx: &Rcx, local: &ast::Local) {
1057     /*!
1058      * Computes the guarantors for any ref bindings in a `let` and
1059      * then ensures that the lifetime of the resulting pointer is
1060      * linked to the lifetime of the initialization expression.
1061      */
1062
1063     debug!("regionck::for_local()");
1064     let init_expr = match local.init {
1065         None => { return; }
1066         Some(ref expr) => expr,
1067     };
1068     let mc = mc::MemCategorizationContext::new(rcx);
1069     let discr_cmt = ignore_err!(mc.cat_expr(&**init_expr));
1070     link_pattern(rcx, mc, discr_cmt, &*local.pat);
1071 }
1072
1073 fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
1074     /*!
1075      * Computes the guarantors for any ref bindings in a match and
1076      * then ensures that the lifetime of the resulting pointer is
1077      * linked to the lifetime of its guarantor (if any).
1078      */
1079
1080     debug!("regionck::for_match()");
1081     let mc = mc::MemCategorizationContext::new(rcx);
1082     let discr_cmt = ignore_err!(mc.cat_expr(discr));
1083     debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
1084     for arm in arms.iter() {
1085         for root_pat in arm.pats.iter() {
1086             link_pattern(rcx, mc, discr_cmt.clone(), &**root_pat);
1087         }
1088     }
1089 }
1090
1091 fn link_pattern(rcx: &Rcx,
1092                 mc: mc::MemCategorizationContext<Rcx>,
1093                 discr_cmt: mc::cmt,
1094                 root_pat: &ast::Pat) {
1095     /*!
1096      * Link lifetimes of any ref bindings in `root_pat` to
1097      * the pointers found in the discriminant, if needed.
1098      */
1099
1100     let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
1101             match sub_pat.node {
1102                 // `ref x` pattern
1103                 ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
1104                     link_region_from_node_type(
1105                         rcx, sub_pat.span, sub_pat.id,
1106                         mutbl, sub_cmt);
1107                 }
1108
1109                 // `[_, ..slice, _]` pattern
1110                 ast::PatVec(_, Some(ref slice_pat), _) => {
1111                     match mc.cat_slice_pattern(sub_cmt, &**slice_pat) {
1112                         Ok((slice_cmt, slice_mutbl, slice_r)) => {
1113                             link_region(rcx, sub_pat.span, slice_r,
1114                                         ty::BorrowKind::from_mutbl(slice_mutbl),
1115                                         slice_cmt);
1116                         }
1117                         Err(()) => {}
1118                     }
1119                 }
1120                 _ => {}
1121             }
1122         });
1123 }
1124
1125 fn link_autoref(rcx: &Rcx,
1126                 expr: &ast::Expr,
1127                 autoderefs: uint,
1128                 autoref: &ty::AutoRef) {
1129     /*!
1130      * Link lifetime of borrowed pointer resulting from autoref
1131      * to lifetimes in the value being autoref'd.
1132      */
1133
1134     debug!("link_autoref(autoref={:?})", autoref);
1135     let mc = mc::MemCategorizationContext::new(rcx);
1136     let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
1137     debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
1138
1139     match *autoref {
1140         ty::AutoPtr(r, m) => {
1141             link_region(rcx, expr.span, r,
1142                         ty::BorrowKind::from_mutbl(m), expr_cmt);
1143         }
1144
1145         ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
1146             let cmt_index = mc.cat_index(expr, expr_cmt, autoderefs+1);
1147             link_region(rcx, expr.span, r,
1148                         ty::BorrowKind::from_mutbl(m), cmt_index);
1149         }
1150
1151         ty::AutoBorrowObj(r, m) => {
1152             let cmt_deref = mc.cat_deref_obj(expr, expr_cmt);
1153             link_region(rcx, expr.span, r,
1154                         ty::BorrowKind::from_mutbl(m), cmt_deref);
1155         }
1156
1157         ty::AutoUnsafe(_) => {}
1158     }
1159 }
1160
1161 fn link_by_ref(rcx: &Rcx,
1162                expr: &ast::Expr,
1163                callee_scope: ast::NodeId) {
1164     /*!
1165      * Computes the guarantor for cases where the `expr` is
1166      * being passed by implicit reference and must outlive
1167      * `callee_scope`.
1168      */
1169
1170     let tcx = rcx.tcx();
1171     debug!("link_by_ref(expr={}, callee_scope={})",
1172            expr.repr(tcx), callee_scope);
1173     let mc = mc::MemCategorizationContext::new(rcx);
1174     let expr_cmt = ignore_err!(mc.cat_expr(expr));
1175     let region_min = ty::ReScope(callee_scope);
1176     link_region(rcx, expr.span, region_min, ty::ImmBorrow, expr_cmt);
1177 }
1178
1179 fn link_region_from_node_type(rcx: &Rcx,
1180                               span: Span,
1181                               id: ast::NodeId,
1182                               mutbl: ast::Mutability,
1183                               cmt_borrowed: mc::cmt) {
1184     /*!
1185      * Like `link_region()`, except that the region is
1186      * extracted from the type of `id`, which must be some
1187      * reference (`&T`, `&str`, etc).
1188      */
1189
1190     let rptr_ty = rcx.resolve_node_type(id);
1191     if !ty::type_is_bot(rptr_ty) && !ty::type_is_error(rptr_ty) {
1192         let tcx = rcx.fcx.ccx.tcx;
1193         debug!("rptr_ty={}", ty_to_str(tcx, rptr_ty));
1194         let r = ty::ty_region(tcx, span, rptr_ty);
1195         link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
1196                     cmt_borrowed);
1197     }
1198 }
1199
1200 fn link_region(rcx: &Rcx,
1201                span: Span,
1202                region_min: ty::Region,
1203                kind: ty::BorrowKind,
1204                cmt_borrowed: mc::cmt) {
1205     /*!
1206      * Informs the inference engine that a borrow of `cmt`
1207      * must have the borrow kind `kind` and lifetime `region_min`.
1208      * If `cmt` is a deref of a region pointer with
1209      * lifetime `r_borrowed`, this will add the constraint that
1210      * `region_min <= r_borrowed`.
1211      */
1212
1213     // Iterate through all the things that must be live at least
1214     // for the lifetime `region_min` for the borrow to be valid:
1215     let mut cmt_borrowed = cmt_borrowed;
1216     loop {
1217         debug!("link_region(region_min={}, kind={}, cmt_borrowed={})",
1218                region_min.repr(rcx.tcx()),
1219                kind.repr(rcx.tcx()),
1220                cmt_borrowed.repr(rcx.tcx()));
1221         match cmt_borrowed.cat.clone() {
1222             mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => {
1223                 // References to an upvar `x` are translated to
1224                 // `*x`, since that is what happens in the
1225                 // underlying machine.  We detect such references
1226                 // and treat them slightly differently, both to
1227                 // offer better error messages and because we need
1228                 // to infer the kind of borrow (mut, const, etc)
1229                 // to use for each upvar.
1230                 let cause = match base.cat {
1231                     mc::cat_upvar(ref upvar_id, _) => {
1232                         match rcx.fcx.inh.upvar_borrow_map.borrow_mut()
1233                                  .find_mut(upvar_id) {
1234                             Some(upvar_borrow) => {
1235                                 debug!("link_region: {} <= {}",
1236                                        region_min.repr(rcx.tcx()),
1237                                        upvar_borrow.region.repr(rcx.tcx()));
1238                                 adjust_upvar_borrow_kind_for_loan(
1239                                     *upvar_id,
1240                                     upvar_borrow,
1241                                     kind);
1242                                 infer::ReborrowUpvar(span, *upvar_id)
1243                             }
1244                             None => {
1245                                 rcx.tcx().sess.span_bug(
1246                                     span,
1247                                     format!("Illegal upvar id: {}",
1248                                             upvar_id.repr(
1249                                                 rcx.tcx())).as_slice());
1250                             }
1251                         }
1252                     }
1253
1254                     _ => {
1255                         infer::Reborrow(span)
1256                     }
1257                 };
1258
1259                 debug!("link_region: {} <= {}",
1260                        region_min.repr(rcx.tcx()),
1261                        r_borrowed.repr(rcx.tcx()));
1262                 rcx.fcx.mk_subr(true, cause, region_min, r_borrowed);
1263
1264                 if kind != ty::ImmBorrow {
1265                     // If this is a mutable borrow, then the thing
1266                     // being borrowed will have to be unique.
1267                     // In user code, this means it must be an `&mut`
1268                     // borrow, but for an upvar, we might opt
1269                     // for an immutable-unique borrow.
1270                     adjust_upvar_borrow_kind_for_unique(rcx, base);
1271                 }
1272
1273                 // Borrowing an `&mut` pointee for `region_min` is
1274                 // only valid if the pointer resides in a unique
1275                 // location which is itself valid for
1276                 // `region_min`.  We don't care about the unique
1277                 // part, but we may need to influence the
1278                 // inference to ensure that the location remains
1279                 // valid.
1280                 //
1281                 // FIXME(#8624) fixing borrowck will require this
1282                 // if m == ast::m_mutbl {
1283                 //    cmt_borrowed = cmt_base;
1284                 // } else {
1285                 //    return;
1286                 // }
1287                 return;
1288             }
1289             mc::cat_discr(cmt_base, _) |
1290             mc::cat_downcast(cmt_base) |
1291             mc::cat_deref(cmt_base, _, mc::GcPtr(..)) |
1292             mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
1293             mc::cat_interior(cmt_base, _) => {
1294                 // Interior or owned data requires its base to be valid
1295                 cmt_borrowed = cmt_base;
1296             }
1297             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1298             mc::cat_static_item |
1299             mc::cat_copied_upvar(..) |
1300             mc::cat_local(..) |
1301             mc::cat_arg(..) |
1302             mc::cat_upvar(..) |
1303             mc::cat_rvalue(..) => {
1304                 // These are all "base cases" with independent lifetimes
1305                 // that are not subject to inference
1306                 return;
1307             }
1308         }
1309     }
1310 }
1311
1312 fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
1313                                          lhs: &ast::Expr) {
1314     /*!
1315      * Adjusts the inferred borrow_kind as needed to account
1316      * for upvars that are assigned to in an assignment
1317      * expression.
1318      */
1319
1320     let mc = mc::MemCategorizationContext::new(rcx);
1321     let cmt = ignore_err!(mc.cat_expr(lhs));
1322     adjust_upvar_borrow_kind_for_mut(rcx, cmt);
1323 }
1324
1325 fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
1326                                     cmt: mc::cmt) {
1327     let mut cmt = cmt;
1328     loop {
1329         debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
1330                cmt.repr(rcx.tcx()));
1331
1332         match cmt.cat.clone() {
1333             mc::cat_deref(base, _, mc::OwnedPtr) |
1334             mc::cat_interior(base, _) |
1335             mc::cat_downcast(base) |
1336             mc::cat_discr(base, _) => {
1337                 // Interior or owned data is mutable if base is
1338                 // mutable, so iterate to the base.
1339                 cmt = base;
1340                 continue;
1341             }
1342
1343             mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
1344                 match base.cat {
1345                     mc::cat_upvar(ref upvar_id, _) => {
1346                         // if this is an implicit deref of an
1347                         // upvar, then we need to modify the
1348                         // borrow_kind of the upvar to make sure it
1349                         // is inferred to mutable if necessary
1350                         let mut upvar_borrow_map =
1351                             rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1352                         let ub = upvar_borrow_map.get_mut(upvar_id);
1353                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow);
1354                     }
1355
1356                     _ => {}
1357                 }
1358
1359                 // assignment to deref of an `&mut`
1360                 // borrowed pointer implies that the
1361                 // pointer itself must be unique, but not
1362                 // necessarily *mutable*
1363                 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1364             }
1365
1366             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1367             mc::cat_deref(_, _, mc::GcPtr) |
1368             mc::cat_static_item |
1369             mc::cat_rvalue(_) |
1370             mc::cat_copied_upvar(_) |
1371             mc::cat_local(_) |
1372             mc::cat_arg(_) |
1373             mc::cat_upvar(..) => {
1374                 return;
1375             }
1376         }
1377     }
1378 }
1379
1380 fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
1381     let mut cmt = cmt;
1382     loop {
1383         debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
1384                cmt.repr(rcx.tcx()));
1385
1386         match cmt.cat.clone() {
1387             mc::cat_deref(base, _, mc::OwnedPtr) |
1388             mc::cat_interior(base, _) |
1389             mc::cat_downcast(base) |
1390             mc::cat_discr(base, _) => {
1391                 // Interior or owned data is unique if base is
1392                 // unique.
1393                 cmt = base;
1394                 continue;
1395             }
1396
1397             mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
1398                 match base.cat {
1399                     mc::cat_upvar(ref upvar_id, _) => {
1400                         // if this is an implicit deref of an
1401                         // upvar, then we need to modify the
1402                         // borrow_kind of the upvar to make sure it
1403                         // is inferred to unique if necessary
1404                         let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1405                         let ub = ub.get_mut(upvar_id);
1406                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow);
1407                     }
1408
1409                     _ => {}
1410                 }
1411
1412                 // for a borrowed pointer to be unique, its
1413                 // base must be unique
1414                 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1415             }
1416
1417             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1418             mc::cat_deref(_, _, mc::GcPtr) |
1419             mc::cat_static_item |
1420             mc::cat_rvalue(_) |
1421             mc::cat_copied_upvar(_) |
1422             mc::cat_local(_) |
1423             mc::cat_arg(_) |
1424             mc::cat_upvar(..) => {
1425                 return;
1426             }
1427         }
1428     }
1429 }
1430
1431 fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx,
1432                                               inner_upvar_id: ty::UpvarId,
1433                                               outer_upvar_id: ty::UpvarId) {
1434     /*!
1435      * Indicates that the borrow_kind of `outer_upvar_id` must
1436      * permit a reborrowing with the borrow_kind of `inner_upvar_id`.
1437      * This occurs in nested closures, see comment above at the call to
1438      * this function.
1439      */
1440
1441     debug!("link_upvar_borrow_kind: inner_upvar_id={:?} outer_upvar_id={:?}",
1442            inner_upvar_id, outer_upvar_id);
1443
1444     let mut upvar_borrow_map = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1445     let inner_borrow = upvar_borrow_map.get_copy(&inner_upvar_id);
1446     match upvar_borrow_map.find_mut(&outer_upvar_id) {
1447         Some(outer_borrow) => {
1448             adjust_upvar_borrow_kind(outer_upvar_id, outer_borrow, inner_borrow.kind);
1449         }
1450         None => { /* outer closure is not a stack closure */ }
1451     }
1452 }
1453
1454 fn adjust_upvar_borrow_kind_for_loan(upvar_id: ty::UpvarId,
1455                                      upvar_borrow: &mut ty::UpvarBorrow,
1456                                      kind: ty::BorrowKind) {
1457     debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}",
1458            upvar_id, upvar_borrow.kind, kind);
1459
1460     adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind)
1461 }
1462
1463 fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId,
1464                             upvar_borrow: &mut ty::UpvarBorrow,
1465                             kind: ty::BorrowKind) {
1466     /*!
1467      * We infer the borrow_kind with which to borrow upvars in a stack
1468      * closure. The borrow_kind basically follows a lattice of
1469      * `imm < unique-imm < mut`, moving from left to right as needed (but never
1470      * right to left). Here the argument `mutbl` is the borrow_kind that
1471      * is required by some particular use.
1472      */
1473
1474     debug!("adjust_upvar_borrow_kind: id={:?} kind=({:?} -> {:?})",
1475            upvar_id, upvar_borrow.kind, kind);
1476
1477     match (upvar_borrow.kind, kind) {
1478         // Take RHS:
1479         (ty::ImmBorrow, ty::UniqueImmBorrow) |
1480         (ty::ImmBorrow, ty::MutBorrow) |
1481         (ty::UniqueImmBorrow, ty::MutBorrow) => {
1482             upvar_borrow.kind = kind;
1483         }
1484         // Take LHS:
1485         (ty::ImmBorrow, ty::ImmBorrow) |
1486         (ty::UniqueImmBorrow, ty::ImmBorrow) |
1487         (ty::UniqueImmBorrow, ty::UniqueImmBorrow) |
1488         (ty::MutBorrow, _) => {
1489         }
1490     }
1491 }