]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/check/regionck.rs
Honor hidden doc attribute of derivable trait methods
[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
122 use middle::freevars;
123 use mc = middle::mem_categorization;
124 use middle::ty::{ReScope};
125 use middle::ty;
126 use middle::typeck::astconv::AstConv;
127 use middle::typeck::check::FnCtxt;
128 use middle::typeck::check::regionmanip::relate_nested_regions;
129 use middle::typeck::infer::resolve_and_force_all_but_regions;
130 use middle::typeck::infer::resolve_type;
131 use middle::typeck::infer;
132 use middle::typeck::MethodCall;
133 use middle::pat_util;
134 use util::nodemap::NodeMap;
135 use util::ppaux::{ty_to_str, region_to_str, Repr};
136
137 use syntax::ast::{DefArg, DefBinding, DefLocal, DefUpvar};
138 use syntax::ast;
139 use syntax::ast_util;
140 use syntax::codemap::Span;
141 use syntax::visit;
142 use syntax::visit::Visitor;
143
144 use std::cell::RefCell;
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: ast::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))
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<'a, 'b> mc::Typer for &'a Rcx<'b> {
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();
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();
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 = ~3, w = ~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 an 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.fcx.expr_ty(expr);
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(callee, ref args) => {
446             constrain_callee(rcx, callee.id, expr, callee);
447             constrain_call(rcx,
448                            Some(callee.id),
449                            expr,
450                            None,
451                            args.as_slice(),
452                            false);
453
454             visit::walk_expr(rcx, expr, ());
455         }
456
457         ast::ExprMethodCall(_, _, ref args) => {
458             constrain_call(rcx, None, expr, Some(*args.get(0)),
459                            args.slice_from(1), false);
460
461             visit::walk_expr(rcx, expr, ());
462         }
463
464         ast::ExprAssign(lhs, _) => {
465             adjust_borrow_kind_for_assignment_lhs(rcx, lhs);
466             visit::walk_expr(rcx, expr, ());
467         }
468
469         ast::ExprAssignOp(_, lhs, rhs) => {
470             if has_method_map {
471                 constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
472             }
473
474             adjust_borrow_kind_for_assignment_lhs(rcx, lhs);
475
476             visit::walk_expr(rcx, expr, ());
477         }
478
479         ast::ExprIndex(lhs, rhs) |
480         ast::ExprBinary(_, lhs, rhs) if has_method_map => {
481             // As `expr_method_call`, but the call is via an
482             // overloaded op.  Note that we (sadly) currently use an
483             // implicit "by ref" sort of passing style here.  This
484             // should be converted to an adjustment!
485             constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
486
487             visit::walk_expr(rcx, expr, ());
488         }
489
490         ast::ExprUnary(_, lhs) if has_method_map => {
491             // As above.
492             constrain_call(rcx, None, expr, Some(lhs), [], true);
493
494             visit::walk_expr(rcx, expr, ());
495         }
496
497         ast::ExprUnary(ast::UnDeref, base) => {
498             // For *a, the lifetime of a must enclose the deref
499             let method_call = MethodCall::expr(expr.id);
500             let base_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
501                 Some(method) => {
502                     constrain_call(rcx, None, expr, Some(base), [], true);
503                     ty::ty_fn_ret(method.ty)
504                 }
505                 None => rcx.resolve_node_type(base.id)
506             };
507             match ty::get(base_ty).sty {
508                 ty::ty_rptr(r_ptr, _) => {
509                     mk_subregion_due_to_dereference(rcx, expr.span,
510                                                     ty::ReScope(expr.id), r_ptr);
511                 }
512                 _ => {}
513             }
514
515             visit::walk_expr(rcx, expr, ());
516         }
517
518         ast::ExprIndex(vec_expr, _) => {
519             // For a[b], the lifetime of a must enclose the deref
520             let vec_type = rcx.resolve_expr_type_adjusted(vec_expr);
521             constrain_index(rcx, expr, vec_type);
522
523             visit::walk_expr(rcx, expr, ());
524         }
525
526         ast::ExprCast(source, _) => {
527             // Determine if we are casting `source` to an trait
528             // instance.  If so, we have to be sure that the type of
529             // the source obeys the trait's region bound.
530             //
531             // Note: there is a subtle point here concerning type
532             // parameters.  It is possible that the type of `source`
533             // contains type parameters, which in turn may contain
534             // regions that are not visible to us (only the caller
535             // knows about them).  The kind checker is ultimately
536             // responsible for guaranteeing region safety in that
537             // particular case.  There is an extensive comment on the
538             // function check_cast_for_escaping_regions() in kind.rs
539             // explaining how it goes about doing that.
540             let target_ty = rcx.resolve_node_type(expr.id);
541             match ty::get(target_ty).sty {
542                 ty::ty_trait(~ty::TyTrait {
543                     store: ty::RegionTraitStore(trait_region, _), ..
544                 }) => {
545                     let source_ty = rcx.resolve_expr_type_adjusted(source);
546                     constrain_regions_in_type(
547                         rcx,
548                         trait_region,
549                         infer::RelateObjectBound(expr.span),
550                         source_ty);
551                 }
552                 _ => ()
553             }
554
555             visit::walk_expr(rcx, expr, ());
556         }
557
558         ast::ExprAddrOf(m, base) => {
559             link_addr_of(rcx, expr, m, base);
560
561             // Require that when you write a `&expr` expression, the
562             // resulting pointer has a lifetime that encompasses the
563             // `&expr` expression itself. Note that we constraining
564             // the type of the node expr.id here *before applying
565             // adjustments*.
566             //
567             // FIXME(#6268) nested method calls requires that this rule change
568             let ty0 = rcx.resolve_node_type(expr.id);
569             constrain_regions_in_type(rcx, ty::ReScope(expr.id),
570                                       infer::AddrOf(expr.span), ty0);
571             visit::walk_expr(rcx, expr, ());
572         }
573
574         ast::ExprMatch(discr, ref arms) => {
575             link_match(rcx, discr, arms.as_slice());
576
577             visit::walk_expr(rcx, expr, ());
578         }
579
580         ast::ExprFnBlock(_, ref body) | ast::ExprProc(_, ref body) => {
581             check_expr_fn_block(rcx, expr, &**body);
582         }
583
584         ast::ExprLoop(body, _) => {
585             let repeating_scope = rcx.set_repeating_scope(body.id);
586             visit::walk_expr(rcx, expr, ());
587             rcx.set_repeating_scope(repeating_scope);
588         }
589
590         ast::ExprWhile(cond, body) => {
591             let repeating_scope = rcx.set_repeating_scope(cond.id);
592             rcx.visit_expr(cond, ());
593
594             rcx.set_repeating_scope(body.id);
595             rcx.visit_block(body, ());
596
597             rcx.set_repeating_scope(repeating_scope);
598         }
599
600         _ => {
601             visit::walk_expr(rcx, expr, ());
602         }
603     }
604 }
605
606 fn check_expr_fn_block(rcx: &mut Rcx,
607                        expr: &ast::Expr,
608                        body: &ast::Block) {
609     let tcx = rcx.fcx.tcx();
610     let function_type = rcx.resolve_node_type(expr.id);
611     match ty::get(function_type).sty {
612         ty::ty_closure(~ty::ClosureTy {
613                 store: ty::RegionTraitStore(region, _), ..}) => {
614             freevars::with_freevars(tcx, expr.id, |freevars| {
615                 if freevars.is_empty() {
616                     // No free variables means that the environment
617                     // will be NULL at runtime and hence the closure
618                     // has static lifetime.
619                 } else {
620                     // Closure must not outlive the variables it closes over.
621                     constrain_free_variables(rcx, region, expr, freevars);
622
623                     // Closure cannot outlive the appropriate temporary scope.
624                     let s = rcx.repeating_scope;
625                     rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span),
626                                     region, ty::ReScope(s));
627                 }
628             });
629         }
630         _ => ()
631     }
632
633     let repeating_scope = rcx.set_repeating_scope(body.id);
634     visit::walk_expr(rcx, expr, ());
635     rcx.set_repeating_scope(repeating_scope);
636
637     match ty::get(function_type).sty {
638         ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
639             freevars::with_freevars(tcx, expr.id, |freevars| {
640                 propagate_upupvar_borrow_kind(rcx, expr, freevars);
641             });
642         }
643         _ => ()
644     }
645
646     fn constrain_free_variables(rcx: &mut Rcx,
647                                 region: ty::Region,
648                                 expr: &ast::Expr,
649                                 freevars: &[freevars::freevar_entry]) {
650         /*!
651          * Make sure that all free variables referenced inside the closure
652          * outlive the closure itself. Also, create an entry in the
653          * upvar_borrows map with a region.
654          */
655
656         let tcx = rcx.fcx.ccx.tcx;
657         let infcx = rcx.fcx.infcx();
658         debug!("constrain_free_variables({}, {})",
659                region.repr(tcx), expr.repr(tcx));
660         for freevar in freevars.iter() {
661             debug!("freevar def is {:?}", freevar.def);
662
663             // Identify the variable being closed over and its node-id.
664             let def = freevar.def;
665             let def_id = ast_util::def_id_of_def(def);
666             assert!(def_id.krate == ast::LOCAL_CRATE);
667             let upvar_id = ty::UpvarId { var_id: def_id.node,
668                                          closure_expr_id: expr.id };
669
670             // Create a region variable to represent this borrow. This borrow
671             // must outlive the region on the closure.
672             let origin = infer::UpvarRegion(upvar_id, expr.span);
673             let freevar_region = infcx.next_region_var(origin);
674             rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node),
675                             region, freevar_region);
676
677             // Create a UpvarBorrow entry. Note that we begin with a
678             // const borrow_kind, but change it to either mut or
679             // immutable as dictated by the uses.
680             let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow,
681                                                  region: freevar_region };
682             rcx.fcx.inh.upvar_borrow_map.borrow_mut().insert(upvar_id,
683                                                              upvar_borrow);
684
685             // Guarantee that the closure does not outlive the variable itself.
686             let en_region = region_of_def(rcx.fcx, def);
687             debug!("en_region = {}", en_region.repr(tcx));
688             rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node),
689                             region, en_region);
690         }
691     }
692
693     fn propagate_upupvar_borrow_kind(rcx: &mut Rcx,
694                                      expr: &ast::Expr,
695                                      freevars: &[freevars::freevar_entry]) {
696         let tcx = rcx.fcx.ccx.tcx;
697         debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
698         for freevar in freevars.iter() {
699             // Because of the semi-hokey way that we are doing
700             // borrow_kind inference, we need to check for
701             // indirect dependencies, like so:
702             //
703             //     let mut x = 0;
704             //     outer_call(|| {
705             //         inner_call(|| {
706             //             x = 1;
707             //         });
708             //     });
709             //
710             // Here, the `inner_call` is basically "reborrowing" the
711             // outer pointer. With no other changes, `inner_call`
712             // would infer that it requires a mutable borrow, but
713             // `outer_call` would infer that a const borrow is
714             // sufficient. This is because we haven't linked the
715             // borrow_kind of the borrow that occurs in the inner
716             // closure to the borrow_kind of the borrow in the outer
717             // closure. Note that regions *are* naturally linked
718             // because we have a proper inference scheme there.
719             //
720             // Anyway, for borrow_kind, we basically go back over now
721             // after checking the inner closure (and hence
722             // determining the final borrow_kind) and propagate that as
723             // a constraint on the outer closure.
724             match freevar.def {
725                 ast::DefUpvar(var_id, _, outer_closure_id, _) => {
726                     // thing being captured is itself an upvar:
727                     let outer_upvar_id = ty::UpvarId {
728                         var_id: var_id,
729                         closure_expr_id: outer_closure_id };
730                     let inner_upvar_id = ty::UpvarId {
731                         var_id: var_id,
732                         closure_expr_id: expr.id };
733                     link_upvar_borrow_kind_for_nested_closures(rcx,
734                                                                inner_upvar_id,
735                                                                outer_upvar_id);
736                 }
737                 _ => {}
738             }
739         }
740     }
741 }
742
743 fn constrain_callee(rcx: &mut Rcx,
744                     callee_id: ast::NodeId,
745                     call_expr: &ast::Expr,
746                     callee_expr: &ast::Expr) {
747     let call_region = ty::ReScope(call_expr.id);
748
749     let callee_ty = rcx.resolve_node_type(callee_id);
750     match ty::get(callee_ty).sty {
751         ty::ty_bare_fn(..) => { }
752         ty::ty_closure(ref closure_ty) => {
753             let region = match closure_ty.store {
754                 ty::RegionTraitStore(r, _) => r,
755                 ty::UniqTraitStore => ty::ReStatic
756             };
757             rcx.fcx.mk_subr(true, infer::InvokeClosure(callee_expr.span),
758                             call_region, region);
759         }
760         _ => {
761             // this should not happen, but it does if the program is
762             // erroneous
763             //
764             // tcx.sess.span_bug(
765             //     callee_expr.span,
766             //     format!("Calling non-function: {}", callee_ty.repr(tcx)));
767         }
768     }
769 }
770
771 fn constrain_call(rcx: &mut Rcx,
772                   // might be expr_call, expr_method_call, or an overloaded
773                   // operator
774                   fn_expr_id: Option<ast::NodeId>,
775                   call_expr: &ast::Expr,
776                   receiver: Option<@ast::Expr>,
777                   arg_exprs: &[@ast::Expr],
778                   implicitly_ref_args: bool) {
779     //! Invoked on every call site (i.e., normal calls, method calls,
780     //! and overloaded operators). Constrains the regions which appear
781     //! in the type of the function. Also constrains the regions that
782     //! appear in the arguments appropriately.
783
784     let tcx = rcx.fcx.tcx();
785     debug!("constrain_call(call_expr={}, \
786             receiver={}, \
787             arg_exprs={}, \
788             implicitly_ref_args={:?})",
789             call_expr.repr(tcx),
790             receiver.repr(tcx),
791             arg_exprs.repr(tcx),
792             implicitly_ref_args);
793     let callee_ty = match fn_expr_id {
794         Some(id) => rcx.resolve_node_type(id),
795         None => rcx.resolve_method_type(MethodCall::expr(call_expr.id))
796                    .expect("call should have been to a method")
797     };
798     if ty::type_is_error(callee_ty) {
799         // Bail, as function type is unknown
800         return;
801     }
802     let fn_sig = ty::ty_fn_sig(callee_ty);
803
804     // `callee_region` is the scope representing the time in which the
805     // call occurs.
806     //
807     // FIXME(#6268) to support nested method calls, should be callee_id
808     let callee_scope = call_expr.id;
809     let callee_region = ty::ReScope(callee_scope);
810
811     for &arg_expr in arg_exprs.iter() {
812         debug!("Argument");
813
814         // ensure that any regions appearing in the argument type are
815         // valid for at least the lifetime of the function:
816         constrain_regions_in_type_of_node(
817             rcx, arg_expr.id, callee_region,
818             infer::CallArg(arg_expr.span));
819
820         // unfortunately, there are two means of taking implicit
821         // references, and we need to propagate constraints as a
822         // result. modes are going away and the "DerefArgs" code
823         // should be ported to use adjustments
824         if implicitly_ref_args {
825             link_by_ref(rcx, arg_expr, callee_scope);
826         }
827     }
828
829     // as loop above, but for receiver
830     for &r in receiver.iter() {
831         debug!("Receiver");
832         constrain_regions_in_type_of_node(
833             rcx, r.id, callee_region, infer::CallRcvr(r.span));
834         if implicitly_ref_args {
835             link_by_ref(rcx, r, callee_scope);
836         }
837     }
838
839     // constrain regions that may appear in the return type to be
840     // valid for the function call:
841     constrain_regions_in_type(
842         rcx, callee_region, infer::CallReturn(call_expr.span),
843         fn_sig.output);
844 }
845
846 fn constrain_autoderefs(rcx: &mut Rcx,
847                         deref_expr: &ast::Expr,
848                         derefs: uint,
849                         mut derefd_ty: ty::t) {
850     /*!
851      * Invoked on any auto-dereference that occurs.  Checks that if
852      * this is a region pointer being dereferenced, the lifetime of
853      * the pointer includes the deref expr.
854      */
855     let r_deref_expr = ty::ReScope(deref_expr.id);
856     for i in range(0u, derefs) {
857         debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={:?}/{:?}",
858                rcx.fcx.infcx().ty_to_str(derefd_ty),
859                i, derefs);
860
861         let method_call = MethodCall::autoderef(deref_expr.id, i as u32);
862         derefd_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
863             Some(method) => {
864                 // Treat overloaded autoderefs as if an AutoRef adjustment
865                 // was applied on the base type, as that is always the case.
866                 let fn_sig = ty::ty_fn_sig(method.ty);
867                 let self_ty = *fn_sig.inputs.get(0);
868                 let (m, r) = match ty::get(self_ty).sty {
869                     ty::ty_rptr(r, ref m) => (m.mutbl, r),
870                     _ => rcx.tcx().sess.span_bug(deref_expr.span,
871                             format!("bad overloaded deref type {}",
872                                 method.ty.repr(rcx.tcx())))
873                 };
874                 {
875                     let mc = mc::MemCategorizationContext { typer: &*rcx };
876                     let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
877                     link_region(mc.typer, deref_expr.span, r, m, self_cmt);
878                 }
879
880                 // Specialized version of constrain_call.
881                 constrain_regions_in_type(rcx, r_deref_expr,
882                                           infer::CallRcvr(deref_expr.span),
883                                           self_ty);
884                 constrain_regions_in_type(rcx, r_deref_expr,
885                                           infer::CallReturn(deref_expr.span),
886                                           fn_sig.output);
887                 fn_sig.output
888             }
889             None => derefd_ty
890         };
891
892         match ty::get(derefd_ty).sty {
893             ty::ty_rptr(r_ptr, _) => {
894                 mk_subregion_due_to_dereference(rcx, deref_expr.span,
895                                                 r_deref_expr, r_ptr);
896             }
897             _ => {}
898         }
899
900         match ty::deref(derefd_ty, true) {
901             Some(mt) => derefd_ty = mt.ty,
902             /* if this type can't be dereferenced, then there's already an error
903                in the session saying so. Just bail out for now */
904             None => break
905         }
906     }
907 }
908
909 pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
910                                        deref_span: Span,
911                                        minimum_lifetime: ty::Region,
912                                        maximum_lifetime: ty::Region) {
913     rcx.fcx.mk_subr(true, infer::DerefPointer(deref_span),
914                     minimum_lifetime, maximum_lifetime)
915 }
916
917
918 fn constrain_index(rcx: &mut Rcx,
919                    index_expr: &ast::Expr,
920                    indexed_ty: ty::t)
921 {
922     /*!
923      * Invoked on any index expression that occurs.  Checks that if
924      * this is a slice being indexed, the lifetime of the pointer
925      * includes the deref expr.
926      */
927
928     debug!("constrain_index(index_expr=?, indexed_ty={}",
929            rcx.fcx.infcx().ty_to_str(indexed_ty));
930
931     let r_index_expr = ty::ReScope(index_expr.id);
932     match ty::get(indexed_ty).sty {
933         ty::ty_str(ty::VstoreSlice(r_ptr)) => {
934             rcx.fcx.mk_subr(true, infer::IndexSlice(index_expr.span),
935                             r_index_expr, r_ptr);
936         }
937         ty::ty_rptr(r_ptr, mt) => match ty::get(mt.ty).sty {
938             ty::ty_vec(_, None) => {
939                 rcx.fcx.mk_subr(true, infer::IndexSlice(index_expr.span),
940                                 r_index_expr, r_ptr);
941             }
942             _ => {}
943         },
944
945         _ => {}
946     }
947 }
948
949 fn constrain_regions_in_type_of_node(
950     rcx: &mut Rcx,
951     id: ast::NodeId,
952     minimum_lifetime: ty::Region,
953     origin: infer::SubregionOrigin) {
954     //! Guarantees that any lifetimes which appear in the type of
955     //! the node `id` (after applying adjustments) are valid for at
956     //! least `minimum_lifetime`
957
958     let tcx = rcx.fcx.tcx();
959
960     // Try to resolve the type.  If we encounter an error, then typeck
961     // is going to fail anyway, so just stop here and let typeck
962     // report errors later on in the writeback phase.
963     let ty0 = rcx.resolve_node_type(id);
964     let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
965                            rcx.fcx.inh.adjustments.borrow().find(&id),
966                            |method_call| rcx.resolve_method_type(method_call));
967     debug!("constrain_regions_in_type_of_node(\
968             ty={}, ty0={}, id={}, minimum_lifetime={:?})",
969            ty_to_str(tcx, ty), ty_to_str(tcx, ty0),
970            id, minimum_lifetime);
971     constrain_regions_in_type(rcx, minimum_lifetime, origin, ty);
972 }
973
974 fn constrain_regions_in_type(
975     rcx: &mut Rcx,
976     minimum_lifetime: ty::Region,
977     origin: infer::SubregionOrigin,
978     ty: ty::t) {
979     /*!
980      * Requires that any regions which appear in `ty` must be
981      * superregions of `minimum_lifetime`.  Also enforces the constraint
982      * that given a pointer type `&'r T`, T must not contain regions
983      * that outlive 'r, as well as analogous constraints for other
984      * lifetime'd types.
985      *
986      * This check prevents regions from being used outside of the block in
987      * which they are valid.  Recall that regions represent blocks of
988      * code or expressions: this requirement basically says "any place
989      * that uses or may use a region R must be within the block of
990      * code that R corresponds to."
991      */
992
993     let tcx = rcx.fcx.ccx.tcx;
994
995     debug!("constrain_regions_in_type(minimum_lifetime={}, ty={})",
996            region_to_str(tcx, "", false, minimum_lifetime),
997            ty_to_str(tcx, ty));
998
999     relate_nested_regions(tcx, Some(minimum_lifetime), ty, |r_sub, r_sup| {
1000         debug!("relate_nested_regions(r_sub={}, r_sup={})",
1001                 r_sub.repr(tcx),
1002                 r_sup.repr(tcx));
1003
1004         if r_sup.is_bound() || r_sub.is_bound() {
1005             // a bound region is one which appears inside an fn type.
1006             // (e.g., the `&` in `fn(&T)`).  Such regions need not be
1007             // constrained by `minimum_lifetime` as they are placeholders
1008             // for regions that are as-yet-unknown.
1009         } else if r_sub == minimum_lifetime {
1010             rcx.fcx.mk_subr(
1011                 true, origin.clone(),
1012                 r_sub, r_sup);
1013         } else {
1014             rcx.fcx.mk_subr(
1015                 true, infer::ReferenceOutlivesReferent(ty, origin.span()),
1016                 r_sub, r_sup);
1017         }
1018     });
1019 }
1020
1021 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
1022                mutability: ast::Mutability, base: &ast::Expr) {
1023     /*!
1024      * Computes the guarantor for an expression `&base` and then
1025      * ensures that the lifetime of the resulting pointer is linked
1026      * to the lifetime of its guarantor (if any).
1027      */
1028
1029     debug!("link_addr_of(base=?)");
1030
1031     let cmt = {
1032         let mc = mc::MemCategorizationContext { typer: &*rcx };
1033         ignore_err!(mc.cat_expr(base))
1034     };
1035     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
1036 }
1037
1038 fn link_local(rcx: &Rcx, local: &ast::Local) {
1039     /*!
1040      * Computes the guarantors for any ref bindings in a `let` and
1041      * then ensures that the lifetime of the resulting pointer is
1042      * linked to the lifetime of the initialization expression.
1043      */
1044
1045     debug!("regionck::for_local()");
1046     let init_expr = match local.init {
1047         None => { return; }
1048         Some(expr) => expr,
1049     };
1050     let mc = mc::MemCategorizationContext { typer: rcx };
1051     let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
1052     link_pattern(mc, discr_cmt, local.pat);
1053 }
1054
1055 fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
1056     /*!
1057      * Computes the guarantors for any ref bindings in a match and
1058      * then ensures that the lifetime of the resulting pointer is
1059      * linked to the lifetime of its guarantor (if any).
1060      */
1061
1062     debug!("regionck::for_match()");
1063     let mc = mc::MemCategorizationContext { typer: rcx };
1064     let discr_cmt = ignore_err!(mc.cat_expr(discr));
1065     debug!("discr_cmt={}", discr_cmt.repr(mc.typer.tcx()));
1066     for arm in arms.iter() {
1067         for &root_pat in arm.pats.iter() {
1068             link_pattern(mc, discr_cmt.clone(), root_pat);
1069         }
1070     }
1071 }
1072
1073 fn link_pattern(mc: mc::MemCategorizationContext<&Rcx>,
1074                 discr_cmt: mc::cmt,
1075                 root_pat: &ast::Pat) {
1076     /*!
1077      * Link lifetimes of any ref bindings in `root_pat` to
1078      * the pointers found in the discriminant, if needed.
1079      */
1080
1081     let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
1082             match sub_pat.node {
1083                 // `ref x` pattern
1084                 ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
1085                     link_region_from_node_type(
1086                         mc.typer, sub_pat.span, sub_pat.id,
1087                         mutbl, sub_cmt);
1088                 }
1089
1090                 // `[_, ..slice, _]` pattern
1091                 ast::PatVec(_, Some(slice_pat), _) => {
1092                     match mc.cat_slice_pattern(sub_cmt, slice_pat) {
1093                         Ok((slice_cmt, slice_mutbl, slice_r)) => {
1094                             link_region(mc.typer, sub_pat.span, slice_r,
1095                                         slice_mutbl, slice_cmt);
1096                         }
1097                         Err(()) => {}
1098                     }
1099                 }
1100                 _ => {}
1101             }
1102         });
1103 }
1104
1105 fn link_autoref(rcx: &Rcx,
1106                 expr: &ast::Expr,
1107                 autoderefs: uint,
1108                 autoref: &ty::AutoRef) {
1109     /*!
1110      * Link lifetime of borrowed pointer resulting from autoref
1111      * to lifetimes in the value being autoref'd.
1112      */
1113
1114     debug!("link_autoref(autoref={:?})", autoref);
1115     let mc = mc::MemCategorizationContext { typer: rcx };
1116     let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
1117     debug!("expr_cmt={}", expr_cmt.repr(mc.typer.tcx()));
1118
1119     match *autoref {
1120         ty::AutoPtr(r, m) => {
1121             link_region(mc.typer, expr.span, r, m, expr_cmt);
1122         }
1123
1124         ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
1125             let cmt_index = mc.cat_index(expr, expr_cmt, autoderefs+1);
1126             link_region(mc.typer, expr.span, r, m, cmt_index);
1127         }
1128
1129         ty::AutoBorrowObj(r, m) => {
1130             let cmt_deref = mc.cat_deref_obj(expr, expr_cmt);
1131             link_region(mc.typer, expr.span, r, m, cmt_deref);
1132         }
1133
1134         ty::AutoUnsafe(_) => {}
1135     }
1136 }
1137
1138 fn link_by_ref(rcx: &Rcx,
1139                expr: &ast::Expr,
1140                callee_scope: ast::NodeId) {
1141     /*!
1142      * Computes the guarantor for cases where the `expr` is
1143      * being passed by implicit reference and must outlive
1144      * `callee_scope`.
1145      */
1146
1147     let tcx = rcx.tcx();
1148     debug!("link_by_ref(expr={}, callee_scope={})",
1149            expr.repr(tcx), callee_scope);
1150     let mc = mc::MemCategorizationContext { typer: rcx };
1151     let expr_cmt = ignore_err!(mc.cat_expr(expr));
1152     let region_min = ty::ReScope(callee_scope);
1153     link_region(mc.typer, expr.span, region_min, ast::MutImmutable, expr_cmt);
1154 }
1155
1156 fn link_region_from_node_type(rcx: &Rcx,
1157                               span: Span,
1158                               id: ast::NodeId,
1159                               mutbl: ast::Mutability,
1160                               cmt_borrowed: mc::cmt) {
1161     /*!
1162      * Like `link_region()`, except that the region is
1163      * extracted from the type of `id`, which must be some
1164      * reference (`&T`, `&str`, etc).
1165      */
1166
1167     let rptr_ty = rcx.resolve_node_type(id);
1168     if !ty::type_is_bot(rptr_ty) && !ty::type_is_error(rptr_ty) {
1169         let tcx = rcx.fcx.ccx.tcx;
1170         debug!("rptr_ty={}", ty_to_str(tcx, rptr_ty));
1171         let r = ty::ty_region(tcx, span, rptr_ty);
1172         link_region(rcx, span, r, mutbl, cmt_borrowed);
1173     }
1174 }
1175
1176 fn link_region(rcx: &Rcx,
1177                span: Span,
1178                region_min: ty::Region,
1179                mutbl: ast::Mutability,
1180                cmt_borrowed: mc::cmt) {
1181     /*!
1182      * Informs the inference engine that a borrow of `cmt`
1183      * must have mutability `mutbl` and lifetime `region_min`.
1184      * If `cmt` is a deref of a region pointer with
1185      * lifetime `r_borrowed`, this will add the constraint that
1186      * `region_min <= r_borrowed`.
1187      */
1188
1189     // Iterate through all the things that must be live at least
1190     // for the lifetime `region_min` for the borrow to be valid:
1191     let mut cmt_borrowed = cmt_borrowed;
1192     loop {
1193         debug!("link_region(region_min={}, mutbl={}, cmt_borrowed={})",
1194                region_min.repr(rcx.tcx()),
1195                mutbl.repr(rcx.tcx()),
1196                cmt_borrowed.repr(rcx.tcx()));
1197         match cmt_borrowed.cat.clone() {
1198             mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => {
1199                 // References to an upvar `x` are translated to
1200                 // `*x`, since that is what happens in the
1201                 // underlying machine.  We detect such references
1202                 // and treat them slightly differently, both to
1203                 // offer better error messages and because we need
1204                 // to infer the kind of borrow (mut, const, etc)
1205                 // to use for each upvar.
1206                 let cause = match base.cat {
1207                     mc::cat_upvar(ref upvar_id, _) => {
1208                         match rcx.fcx.inh.upvar_borrow_map.borrow_mut()
1209                                  .find_mut(upvar_id) {
1210                             Some(upvar_borrow) => {
1211                                 debug!("link_region: {} <= {}",
1212                                        region_min.repr(rcx.tcx()),
1213                                        upvar_borrow.region.repr(rcx.tcx()));
1214                                 adjust_upvar_borrow_kind_for_loan(
1215                                     *upvar_id,
1216                                     upvar_borrow,
1217                                     mutbl);
1218                                 infer::ReborrowUpvar(span, *upvar_id)
1219                             }
1220                             None => {
1221                                 rcx.tcx().sess.span_bug(
1222                                     span,
1223                                     format!("Illegal upvar id: {}",
1224                                             upvar_id.repr(rcx.tcx())));
1225                             }
1226                         }
1227                     }
1228
1229                     _ => {
1230                         infer::Reborrow(span)
1231                     }
1232                 };
1233
1234                 debug!("link_region: {} <= {}",
1235                        region_min.repr(rcx.tcx()),
1236                        r_borrowed.repr(rcx.tcx()));
1237                 rcx.fcx.mk_subr(true, cause, region_min, r_borrowed);
1238
1239                 if mutbl == ast::MutMutable {
1240                     // If this is a mutable borrow, then the thing
1241                     // being borrowed will have to be unique.
1242                     // In user code, this means it must be an `&mut`
1243                     // borrow, but for an upvar, we might opt
1244                     // for an immutable-unique borrow.
1245                     adjust_upvar_borrow_kind_for_unique(rcx, base);
1246                 }
1247
1248                 // Borrowing an `&mut` pointee for `region_min` is
1249                 // only valid if the pointer resides in a unique
1250                 // location which is itself valid for
1251                 // `region_min`.  We don't care about the unique
1252                 // part, but we may need to influence the
1253                 // inference to ensure that the location remains
1254                 // valid.
1255                 //
1256                 // FIXME(#8624) fixing borrowck will require this
1257                 // if m == ast::m_mutbl {
1258                 //    cmt_borrowed = cmt_base;
1259                 // } else {
1260                 //    return;
1261                 // }
1262                 return;
1263             }
1264             mc::cat_discr(cmt_base, _) |
1265             mc::cat_downcast(cmt_base) |
1266             mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
1267             mc::cat_interior(cmt_base, _) => {
1268                 // Interior or owned data requires its base to be valid
1269                 cmt_borrowed = cmt_base;
1270             }
1271             mc::cat_deref(_, _, mc::GcPtr(..)) |
1272             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1273             mc::cat_static_item |
1274             mc::cat_copied_upvar(..) |
1275             mc::cat_local(..) |
1276             mc::cat_arg(..) |
1277             mc::cat_upvar(..) |
1278             mc::cat_rvalue(..) => {
1279                 // These are all "base cases" with independent lifetimes
1280                 // that are not subject to inference
1281                 return;
1282             }
1283         }
1284     }
1285 }
1286
1287 fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
1288                                          lhs: &ast::Expr) {
1289     /*!
1290      * Adjusts the inferred borrow_kind as needed to account
1291      * for upvars that are assigned to in an assignment
1292      * expression.
1293      */
1294
1295     let mc = mc::MemCategorizationContext { typer: rcx };
1296     let cmt = ignore_err!(mc.cat_expr(lhs));
1297     adjust_upvar_borrow_kind_for_mut(mc.typer, cmt);
1298 }
1299
1300 fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
1301                                     cmt: mc::cmt) {
1302     let mut cmt = cmt;
1303     loop {
1304         debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
1305                cmt.repr(rcx.tcx()));
1306
1307         match cmt.cat.clone() {
1308             mc::cat_deref(base, _, mc::OwnedPtr) |
1309             mc::cat_interior(base, _) |
1310             mc::cat_downcast(base) |
1311             mc::cat_discr(base, _) => {
1312                 // Interior or owned data is mutable if base is
1313                 // mutable, so iterate to the base.
1314                 cmt = base;
1315                 continue;
1316             }
1317
1318             mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
1319                 match base.cat {
1320                     mc::cat_upvar(ref upvar_id, _) => {
1321                         // if this is an implicit deref of an
1322                         // upvar, then we need to modify the
1323                         // borrow_kind of the upvar to make sure it
1324                         // is inferred to mutable if necessary
1325                         let mut upvar_borrow_map =
1326                             rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1327                         let ub = upvar_borrow_map.get_mut(upvar_id);
1328                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow);
1329                     }
1330
1331                     _ => {}
1332                 }
1333
1334                 // assignment to deref of an `&mut`
1335                 // borrowed pointer implies that the
1336                 // pointer itself must be unique, but not
1337                 // necessarily *mutable*
1338                 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1339             }
1340
1341             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1342             mc::cat_deref(_, _, mc::GcPtr) |
1343             mc::cat_static_item |
1344             mc::cat_rvalue(_) |
1345             mc::cat_copied_upvar(_) |
1346             mc::cat_local(_) |
1347             mc::cat_arg(_) |
1348             mc::cat_upvar(..) => {
1349                 return;
1350             }
1351         }
1352     }
1353 }
1354
1355 fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
1356     let mut cmt = cmt;
1357     loop {
1358         debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
1359                cmt.repr(rcx.tcx()));
1360
1361         match cmt.cat.clone() {
1362             mc::cat_deref(base, _, mc::OwnedPtr) |
1363             mc::cat_interior(base, _) |
1364             mc::cat_downcast(base) |
1365             mc::cat_discr(base, _) => {
1366                 // Interior or owned data is unique if base is
1367                 // unique.
1368                 cmt = base;
1369                 continue;
1370             }
1371
1372             mc::cat_deref(base, _, mc::BorrowedPtr(..)) => {
1373                 match base.cat {
1374                     mc::cat_upvar(ref upvar_id, _) => {
1375                         // if this is an implicit deref of an
1376                         // upvar, then we need to modify the
1377                         // borrow_kind of the upvar to make sure it
1378                         // is inferred to unique if necessary
1379                         let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1380                         let ub = ub.get_mut(upvar_id);
1381                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow);
1382                     }
1383
1384                     _ => {}
1385                 }
1386
1387                 // for a borrowed pointer to be unique, its
1388                 // base must be unique
1389                 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1390             }
1391
1392             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1393             mc::cat_deref(_, _, mc::GcPtr) |
1394             mc::cat_static_item |
1395             mc::cat_rvalue(_) |
1396             mc::cat_copied_upvar(_) |
1397             mc::cat_local(_) |
1398             mc::cat_arg(_) |
1399             mc::cat_upvar(..) => {
1400                 return;
1401             }
1402         }
1403     }
1404 }
1405
1406 fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx,
1407                                               inner_upvar_id: ty::UpvarId,
1408                                               outer_upvar_id: ty::UpvarId) {
1409     /*!
1410      * Indicates that the borrow_kind of `outer_upvar_id` must
1411      * permit a reborrowing with the borrow_kind of `inner_upvar_id`.
1412      * This occurs in nested closures, see comment above at the call to
1413      * this function.
1414      */
1415
1416     debug!("link_upvar_borrow_kind: inner_upvar_id={:?} outer_upvar_id={:?}",
1417            inner_upvar_id, outer_upvar_id);
1418
1419     let mut upvar_borrow_map = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1420     let inner_borrow = upvar_borrow_map.get_copy(&inner_upvar_id);
1421     match upvar_borrow_map.find_mut(&outer_upvar_id) {
1422         Some(outer_borrow) => {
1423             adjust_upvar_borrow_kind(outer_upvar_id, outer_borrow, inner_borrow.kind);
1424         }
1425         None => { /* outer closure is not a stack closure */ }
1426     }
1427 }
1428
1429 fn adjust_upvar_borrow_kind_for_loan(upvar_id: ty::UpvarId,
1430                                      upvar_borrow: &mut ty::UpvarBorrow,
1431                                      mutbl: ast::Mutability) {
1432     debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}",
1433            upvar_id, upvar_borrow.kind, mutbl);
1434
1435     adjust_upvar_borrow_kind(upvar_id, upvar_borrow,
1436                              ty::BorrowKind::from_mutbl(mutbl))
1437 }
1438
1439 fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId,
1440                             upvar_borrow: &mut ty::UpvarBorrow,
1441                             kind: ty::BorrowKind) {
1442     /*!
1443      * We infer the borrow_kind with which to borrow upvars in a stack
1444      * closure. The borrow_kind basically follows a lattice of
1445      * `imm < unique-imm < mut`, moving from left to right as needed (but never
1446      * right to left). Here the argument `mutbl` is the borrow_kind that
1447      * is required by some particular use.
1448      */
1449
1450     debug!("adjust_upvar_borrow_kind: id={:?} kind=({:?} -> {:?})",
1451            upvar_id, upvar_borrow.kind, kind);
1452
1453     match (upvar_borrow.kind, kind) {
1454         // Take RHS:
1455         (ty::ImmBorrow, ty::UniqueImmBorrow) |
1456         (ty::ImmBorrow, ty::MutBorrow) |
1457         (ty::UniqueImmBorrow, ty::MutBorrow) => {
1458             upvar_borrow.kind = kind;
1459         }
1460         // Take LHS:
1461         (ty::ImmBorrow, ty::ImmBorrow) |
1462         (ty::UniqueImmBorrow, ty::ImmBorrow) |
1463         (ty::UniqueImmBorrow, ty::UniqueImmBorrow) |
1464         (ty::MutBorrow, _) => {
1465         }
1466     }
1467 }