]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/typeck/check/regionck.rs
Doc says to avoid mixing allocator instead of forbiding it
[rust.git] / src / librustc / middle / typeck / check / regionck.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
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 middle::mem_categorization as mc;
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;
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::{DefIdMap, NodeMap};
136 use util::ppaux::{ty_to_string, 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
145 ///////////////////////////////////////////////////////////////////////////
146 // PUBLIC ENTRY POINTS
147
148 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
149     let mut rcx = Rcx::new(fcx, e.id);
150     if fcx.err_count_since_creation() == 0 {
151         // regionck assumes typeck succeeded
152         rcx.visit_expr(e);
153         rcx.visit_region_obligations(e.id);
154     }
155     fcx.infcx().resolve_regions_and_report_errors();
156 }
157
158 pub fn regionck_type_defn(fcx: &FnCtxt,
159                           span: Span,
160                           component_tys: &[ty::t]) {
161     let mut rcx = Rcx::new(fcx, 0);
162     for &component_ty in component_tys.iter() {
163         // Check that each type outlives the empty region. Since the
164         // empty region is a subregion of all others, this can't fail
165         // unless the type does not meet the well-formedness
166         // requirements.
167         type_must_outlive(&mut rcx, infer::RelateRegionParamBound(span),
168                           component_ty, ty::ReEmpty);
169     }
170     fcx.infcx().resolve_regions_and_report_errors();
171 }
172
173 pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, blk: &ast::Block) {
174     let mut rcx = Rcx::new(fcx, blk.id);
175     if fcx.err_count_since_creation() == 0 {
176         // regionck assumes typeck succeeded
177         rcx.visit_fn_body(id, blk);
178     }
179     fcx.infcx().resolve_regions_and_report_errors();
180 }
181
182 ///////////////////////////////////////////////////////////////////////////
183 // INTERNALS
184
185 // If mem categorization results in an error, it's because the type
186 // check failed (or will fail, when the error is uncovered and
187 // reported during writeback). In this case, we just ignore this part
188 // of the code and don't try to add any more region constraints.
189 macro_rules! ignore_err(
190     ($inp: expr) => (
191         match $inp {
192             Ok(v) => v,
193             Err(()) => return
194         }
195     )
196 )
197
198 pub struct Rcx<'a, 'tcx: 'a> {
199     fcx: &'a FnCtxt<'a, 'tcx>,
200
201     region_param_pairs: Vec<(ty::Region, ty::ParamTy)>,
202
203     // id of innermost fn or loop
204     repeating_scope: ast::NodeId,
205 }
206
207 /// When entering a function, we can derive relationships from the
208 /// signature between various regions and type parameters. Consider
209 /// a function like:
210 ///
211 ///     fn foo<'a, A>(x: &'a A) { ... }
212 ///
213 /// Here, we can derive that `A` must outlive `'a`, because otherwise
214 /// the caller would be illegal. We record this by storing a series of
215 /// pairs (in this case, `('a, A)`). These pairs will be consulted
216 /// later during regionck.
217 ///
218 /// In the case of nested fns, additional relationships may be
219 /// derived.  The result is a link list walking up the stack (hence
220 /// the `previous` field).
221 #[deriving(Clone)]
222 pub struct RegionSubParamConstraints<'a> {
223     pairs: Vec<(ty::Region, ty::ParamTy)>,
224     previous: Option<&'a RegionSubParamConstraints<'a>>,
225 }
226
227 fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
228     /*!
229      * Returns the validity region of `def` -- that is, how long
230      * is `def` valid?
231      */
232
233     let tcx = fcx.tcx();
234     match def {
235         DefLocal(node_id, _) | DefArg(node_id, _) |
236         DefBinding(node_id, _) => {
237             tcx.region_maps.var_region(node_id)
238         }
239         DefUpvar(_, subdef, closure_id, body_id) => {
240             match ty::ty_closure_store(fcx.node_ty(closure_id)) {
241                 ty::RegionTraitStore(..) => region_of_def(fcx, *subdef),
242                 ty::UniqTraitStore => ReScope(body_id)
243             }
244         }
245         _ => {
246             tcx.sess.bug(format!("unexpected def in region_of_def: {:?}",
247                                  def).as_slice())
248         }
249     }
250 }
251
252 impl<'a, 'tcx> Rcx<'a, 'tcx> {
253     pub fn new(fcx: &'a FnCtxt<'a, 'tcx>,
254                initial_repeating_scope: ast::NodeId) -> Rcx<'a, 'tcx> {
255         Rcx { fcx: fcx,
256               repeating_scope: initial_repeating_scope,
257               region_param_pairs: Vec::new() }
258     }
259
260     pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
261         self.fcx.ccx.tcx
262     }
263
264     pub fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
265         let old_scope = self.repeating_scope;
266         self.repeating_scope = scope;
267         old_scope
268     }
269
270     pub fn resolve_type(&self, unresolved_ty: ty::t) -> ty::t {
271         /*!
272          * Try to resolve the type for the given node, returning
273          * t_err if an error results.  Note that we never care
274          * about the details of the error, the same error will be
275          * detected and reported in the writeback phase.
276          *
277          * Note one important point: we do not attempt to resolve
278          * *region variables* here.  This is because regionck is
279          * essentially adding constraints to those region variables
280          * and so may yet influence how they are resolved.
281          *
282          * Consider this silly example:
283          *
284          *     fn borrow(x: &int) -> &int {x}
285          *     fn foo(x: @int) -> int {  // block: B
286          *         let b = borrow(x);    // region: <R0>
287          *         *b
288          *     }
289          *
290          * Here, the region of `b` will be `<R0>`.  `<R0>` is
291          * constrainted to be some subregion of the block B and some
292          * superregion of the call.  If we forced it now, we'd choose
293          * the smaller region (the call).  But that would make the *b
294          * illegal.  Since we don't resolve, the type of b will be
295          * `&<R0>.int` and then `*b` will require that `<R0>` be
296          * bigger than the let and the `*b` expression, so we will
297          * effectively resolve `<R0>` to be the block B.
298          */
299         match resolve_type(self.fcx.infcx(), None, unresolved_ty,
300                            resolve_and_force_all_but_regions) {
301             Ok(t) => t,
302             Err(_) => ty::mk_err()
303         }
304     }
305
306     /// Try to resolve the type for the given node.
307     fn resolve_node_type(&self, id: ast::NodeId) -> ty::t {
308         let t = self.fcx.node_ty(id);
309         self.resolve_type(t)
310     }
311
312     fn resolve_method_type(&self, method_call: MethodCall) -> Option<ty::t> {
313         let method_ty = self.fcx.inh.method_map.borrow()
314                             .find(&method_call).map(|method| method.ty);
315         method_ty.map(|method_ty| self.resolve_type(method_ty))
316     }
317
318     /// Try to resolve the type for the given node.
319     pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> ty::t {
320         let ty_unadjusted = self.resolve_node_type(expr.id);
321         if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) {
322             ty_unadjusted
323         } else {
324             let tcx = self.fcx.tcx();
325             ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
326                           self.fcx.inh.adjustments.borrow().find(&expr.id),
327                           |method_call| self.resolve_method_type(method_call))
328         }
329     }
330
331     fn visit_fn_body(&mut self,
332                      id: ast::NodeId,
333                      body: &ast::Block)
334     {
335         // When we enter a function, we can derive
336
337         let fn_sig_map = self.fcx.inh.fn_sig_map.borrow();
338         let fn_sig = match fn_sig_map.find(&id) {
339             Some(f) => f,
340             None => {
341                 self.tcx().sess.bug(
342                     format!("No fn-sig entry for id={}", id).as_slice());
343             }
344         };
345
346         let len = self.region_param_pairs.len();
347         self.relate_free_regions(fn_sig.as_slice(), body.id);
348         self.visit_block(body);
349         self.visit_region_obligations(body.id);
350         self.region_param_pairs.truncate(len);
351     }
352
353     fn visit_region_obligations(&mut self, node_id: ast::NodeId)
354     {
355         debug!("visit_region_obligations: node_id={}", node_id);
356         let region_obligations = self.fcx.inh.region_obligations.borrow();
357         match region_obligations.find(&node_id) {
358             None => { }
359             Some(vec) => {
360                 for r_o in vec.iter() {
361                     debug!("visit_region_obligations: r_o={}",
362                            r_o.repr(self.tcx()));
363                     let sup_type = self.resolve_type(r_o.sup_type);
364                     type_must_outlive(self, r_o.origin.clone(),
365                                       sup_type, r_o.sub_region);
366                 }
367             }
368         }
369     }
370
371     fn relate_free_regions(&mut self,
372                            fn_sig_tys: &[ty::t],
373                            body_id: ast::NodeId) {
374         /*!
375          * This method populates the region map's `free_region_map`.
376          * It walks over the transformed argument and return types for
377          * each function just before we check the body of that
378          * function, looking for types where you have a borrowed
379          * pointer to other borrowed data (e.g., `&'a &'b [uint]`.  We
380          * do not allow references to outlive the things they point
381          * at, so we can assume that `'a <= 'b`. This holds for both
382          * the argument and return types, basically because, on the caller
383          * side, the caller is responsible for checking that the type of
384          * every expression (including the actual values for the arguments,
385          * as well as the return type of the fn call) is well-formed.
386          *
387          * Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
388          */
389
390         debug!("relate_free_regions >>");
391         let tcx = self.tcx();
392
393         for &ty in fn_sig_tys.iter() {
394             let ty = self.resolve_type(ty);
395             debug!("relate_free_regions(t={})", ty.repr(tcx));
396             let body_scope = ty::ReScope(body_id);
397             let constraints =
398                 regionmanip::region_wf_constraints(
399                     tcx,
400                     ty,
401                     body_scope);
402             for constraint in constraints.iter() {
403                 debug!("constraint: {}", constraint.repr(tcx));
404                 match *constraint {
405                     regionmanip::RegionSubRegionConstraint(_,
406                                               ty::ReFree(free_a),
407                                               ty::ReFree(free_b)) => {
408                         tcx.region_maps.relate_free_regions(free_a, free_b);
409                     }
410                     regionmanip::RegionSubRegionConstraint(_,
411                                               ty::ReFree(free_a),
412                                               ty::ReInfer(ty::ReVar(vid_b))) => {
413                         self.fcx.inh.infcx.add_given(free_a, vid_b);
414                     }
415                     regionmanip::RegionSubRegionConstraint(..) => {
416                         // In principle, we could record (and take
417                         // advantage of) every relationship here, but
418                         // we are also free not to -- it simply means
419                         // strictly less that we can successfully type
420                         // check. (It may also be that we should
421                         // revise our inference system to be more
422                         // general and to make use of *every*
423                         // relationship that arises here, but
424                         // presently we do not.)
425                     }
426                     regionmanip::RegionSubParamConstraint(_, r_a, p_b) => {
427                         debug!("RegionSubParamConstraint: {} <= {}",
428                                r_a.repr(tcx), p_b.repr(tcx));
429
430                         self.region_param_pairs.push((r_a, p_b));
431                     }
432                 }
433             }
434         }
435
436         debug!("<< relate_free_regions");
437     }
438 }
439
440 impl<'fcx, 'tcx> mc::Typer<'tcx> for Rcx<'fcx, 'tcx> {
441     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
442         self.fcx.ccx.tcx
443     }
444
445     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
446         let t = self.resolve_node_type(id);
447         if ty::type_is_error(t) {Err(())} else {Ok(t)}
448     }
449
450     fn node_method_ty(&self, method_call: MethodCall) -> Option<ty::t> {
451         self.resolve_method_type(method_call)
452     }
453
454     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
455         &self.fcx.inh.adjustments
456     }
457
458     fn is_method_call(&self, id: ast::NodeId) -> bool {
459         self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
460     }
461
462     fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
463         self.tcx().region_maps.temporary_scope(id)
464     }
465
466     fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
467         self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
468     }
469
470     fn capture_mode(&self, closure_expr_id: ast::NodeId)
471                     -> freevars::CaptureMode {
472         self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
473     }
474
475     fn unboxed_closures<'a>(&'a self)
476                         -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
477         &self.fcx.inh.unboxed_closures
478     }
479 }
480
481 impl<'a, 'tcx, 'v> Visitor<'v> for Rcx<'a, 'tcx> {
482     // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
483     // However, right now we run into an issue whereby some free
484     // regions are not properly related if they appear within the
485     // types of arguments that must be inferred. This could be
486     // addressed by deferring the construction of the region
487     // hierarchy, and in particular the relationships between free
488     // regions, until regionck, as described in #3238.
489
490     fn visit_fn(&mut self, _fk: visit::FnKind<'v>, _fd: &'v ast::FnDecl,
491                 b: &'v ast::Block, _s: Span, id: ast::NodeId) {
492         self.visit_fn_body(id, b)
493     }
494
495     fn visit_item(&mut self, i: &ast::Item) { visit_item(self, i); }
496
497     fn visit_expr(&mut self, ex: &ast::Expr) { visit_expr(self, ex); }
498
499     //visit_pat: visit_pat, // (..) see above
500
501     fn visit_arm(&mut self, a: &ast::Arm) { visit_arm(self, a); }
502
503     fn visit_local(&mut self, l: &ast::Local) { visit_local(self, l); }
504
505     fn visit_block(&mut self, b: &ast::Block) { visit_block(self, b); }
506 }
507
508 fn visit_item(_rcx: &mut Rcx, _item: &ast::Item) {
509     // Ignore items
510 }
511
512 fn visit_block(rcx: &mut Rcx, b: &ast::Block) {
513     visit::walk_block(rcx, b);
514 }
515
516 fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
517     // see above
518     for p in arm.pats.iter() {
519         constrain_bindings_in_pat(&**p, rcx);
520     }
521
522     visit::walk_arm(rcx, arm);
523 }
524
525 fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
526     // see above
527     constrain_bindings_in_pat(&*l.pat, rcx);
528     link_local(rcx, l);
529     visit::walk_local(rcx, l);
530 }
531
532 fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
533     let tcx = rcx.fcx.tcx();
534     debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
535     pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
536         // If we have a variable that contains region'd data, that
537         // data will be accessible from anywhere that the variable is
538         // accessed. We must be wary of loops like this:
539         //
540         //     // from src/test/compile-fail/borrowck-lend-flow.rs
541         //     let mut v = box 3, w = box 4;
542         //     let mut x = &mut w;
543         //     loop {
544         //         **x += 1;   // (2)
545         //         borrow(v);  //~ ERROR cannot borrow
546         //         x = &mut v; // (1)
547         //     }
548         //
549         // Typically, we try to determine the region of a borrow from
550         // those points where it is dereferenced. In this case, one
551         // might imagine that the lifetime of `x` need only be the
552         // body of the loop. But of course this is incorrect because
553         // the pointer that is created at point (1) is consumed at
554         // point (2), meaning that it must be live across the loop
555         // iteration. The easiest way to guarantee this is to require
556         // that the lifetime of any regions that appear in a
557         // variable's type enclose at least the variable's scope.
558
559         let var_region = tcx.region_maps.var_region(id);
560         type_of_node_must_outlive(
561             rcx, infer::BindingTypeIsNotValidAtDecl(span),
562             id, var_region);
563     })
564 }
565
566 fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
567     debug!("regionck::visit_expr(e={}, repeating_scope={:?})",
568            expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
569
570     // No matter what, the type of each expression must outlive the
571     // scope of that expression. This also guarantees basic WF.
572     let expr_ty = rcx.resolve_node_type(expr.id);
573
574     type_must_outlive(rcx, infer::ExprTypeIsNotInScope(expr_ty, expr.span),
575                       expr_ty, ty::ReScope(expr.id));
576
577     let method_call = MethodCall::expr(expr.id);
578     let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call);
579
580     // Check any autoderefs or autorefs that appear.
581     for &adjustment in rcx.fcx.inh.adjustments.borrow().find(&expr.id).iter() {
582         debug!("adjustment={:?}", adjustment);
583         match *adjustment {
584             ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: ref opt_autoref}) => {
585                 let expr_ty = rcx.resolve_node_type(expr.id);
586                 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
587                 for autoref in opt_autoref.iter() {
588                     link_autoref(rcx, expr, autoderefs, autoref);
589
590                     // Require that the resulting region encompasses
591                     // the current node.
592                     //
593                     // FIXME(#6268) remove to support nested method calls
594                     type_of_node_must_outlive(
595                         rcx, infer::AutoBorrow(expr.span),
596                         expr.id, ty::ReScope(expr.id));
597                 }
598             }
599             /*
600             ty::AutoObject(_, ref bounds, _, _) => {
601                 // Determine if we are casting `expr` to a trait
602                 // instance. If so, we have to be sure that the type
603                 // of the source obeys the new region bound.
604                 let source_ty = rcx.resolve_node_type(expr.id);
605                 type_must_outlive(rcx, infer::RelateObjectBound(expr.span),
606                                   source_ty, bounds.region_bound);
607             }
608             */
609             _ => {}
610         }
611     }
612
613     match expr.node {
614         ast::ExprCall(ref callee, ref args) => {
615             if has_method_map {
616                 constrain_call(rcx, expr, Some(&**callee),
617                                args.iter().map(|e| &**e), false);
618             } else {
619                 constrain_callee(rcx, callee.id, expr, &**callee);
620                 constrain_call(rcx, expr, None,
621                                args.iter().map(|e| &**e), false);
622             }
623
624             visit::walk_expr(rcx, expr);
625         }
626
627         ast::ExprMethodCall(_, _, ref args) => {
628             constrain_call(rcx, expr, Some(&**args.get(0)),
629                            args.slice_from(1).iter().map(|e| &**e), false);
630
631             visit::walk_expr(rcx, expr);
632         }
633
634         ast::ExprAssign(ref lhs, _) => {
635             adjust_borrow_kind_for_assignment_lhs(rcx, &**lhs);
636             visit::walk_expr(rcx, expr);
637         }
638
639         ast::ExprAssignOp(_, ref lhs, ref rhs) => {
640             if has_method_map {
641                 constrain_call(rcx, expr, Some(&**lhs),
642                                Some(&**rhs).move_iter(), true);
643             }
644
645             adjust_borrow_kind_for_assignment_lhs(rcx, &**lhs);
646
647             visit::walk_expr(rcx, expr);
648         }
649
650         ast::ExprIndex(ref lhs, ref rhs) |
651         ast::ExprBinary(_, ref lhs, ref rhs) if has_method_map => {
652             // As `expr_method_call`, but the call is via an
653             // overloaded op.  Note that we (sadly) currently use an
654             // implicit "by ref" sort of passing style here.  This
655             // should be converted to an adjustment!
656             constrain_call(rcx, expr, Some(&**lhs),
657                            Some(&**rhs).move_iter(), true);
658
659             visit::walk_expr(rcx, expr);
660         }
661
662         ast::ExprUnary(_, ref lhs) if has_method_map => {
663             // As above.
664             constrain_call(rcx, expr, Some(&**lhs),
665                            None::<ast::Expr>.iter(), true);
666
667             visit::walk_expr(rcx, expr);
668         }
669
670         ast::ExprUnary(ast::UnBox, ref base) => {
671             // Managed data must not have borrowed pointers within it:
672             let base_ty = rcx.resolve_node_type(base.id);
673             type_must_outlive(rcx, infer::Managed(expr.span),
674                               base_ty, ty::ReStatic);
675             visit::walk_expr(rcx, expr);
676         }
677
678         ast::ExprUnary(ast::UnDeref, ref base) => {
679             // For *a, the lifetime of a must enclose the deref
680             let method_call = MethodCall::expr(expr.id);
681             let base_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
682                 Some(method) => {
683                     constrain_call(rcx, expr, Some(&**base),
684                                    None::<ast::Expr>.iter(), true);
685                     ty::ty_fn_ret(method.ty)
686                 }
687                 None => rcx.resolve_node_type(base.id)
688             };
689             match ty::get(base_ty).sty {
690                 ty::ty_rptr(r_ptr, _) => {
691                     mk_subregion_due_to_dereference(rcx, expr.span,
692                                                     ty::ReScope(expr.id), r_ptr);
693                 }
694                 _ => {}
695             }
696
697             visit::walk_expr(rcx, expr);
698         }
699
700         ast::ExprIndex(ref vec_expr, _) => {
701             // For a[b], the lifetime of a must enclose the deref
702             let vec_type = rcx.resolve_expr_type_adjusted(&**vec_expr);
703             constrain_index(rcx, expr, vec_type);
704
705             visit::walk_expr(rcx, expr);
706         }
707
708         ast::ExprCast(ref source, _) => {
709             // Determine if we are casting `source` to a trait
710             // instance.  If so, we have to be sure that the type of
711             // the source obeys the trait's region bound.
712             constrain_cast(rcx, expr, &**source);
713             visit::walk_expr(rcx, expr);
714         }
715
716         ast::ExprAddrOf(m, ref base) => {
717             link_addr_of(rcx, expr, m, &**base);
718
719             // Require that when you write a `&expr` expression, the
720             // resulting pointer has a lifetime that encompasses the
721             // `&expr` expression itself. Note that we constraining
722             // the type of the node expr.id here *before applying
723             // adjustments*.
724             //
725             // FIXME(#6268) nested method calls requires that this rule change
726             let ty0 = rcx.resolve_node_type(expr.id);
727             type_must_outlive(rcx, infer::AddrOf(expr.span),
728                               ty0, ty::ReScope(expr.id));
729             visit::walk_expr(rcx, expr);
730         }
731
732         ast::ExprMatch(ref discr, ref arms) => {
733             link_match(rcx, &**discr, arms.as_slice());
734
735             visit::walk_expr(rcx, expr);
736         }
737
738         ast::ExprFnBlock(_, _, ref body) |
739         ast::ExprProc(_, ref body) |
740         ast::ExprUnboxedFn(_, _, _, ref body) => {
741             check_expr_fn_block(rcx, expr, &**body);
742         }
743
744         ast::ExprLoop(ref body, _) => {
745             let repeating_scope = rcx.set_repeating_scope(body.id);
746             visit::walk_expr(rcx, expr);
747             rcx.set_repeating_scope(repeating_scope);
748         }
749
750         ast::ExprWhile(ref cond, ref body, _) => {
751             let repeating_scope = rcx.set_repeating_scope(cond.id);
752             rcx.visit_expr(&**cond);
753
754             rcx.set_repeating_scope(body.id);
755             rcx.visit_block(&**body);
756
757             rcx.set_repeating_scope(repeating_scope);
758         }
759
760         ast::ExprForLoop(ref pat, ref head, ref body, _) => {
761             constrain_bindings_in_pat(&**pat, rcx);
762
763             {
764                 let mc = mc::MemCategorizationContext::new(rcx);
765                 let head_cmt = ignore_err!(mc.cat_expr(&**head));
766                 link_pattern(rcx, mc, head_cmt, &**pat);
767             }
768
769             rcx.visit_expr(&**head);
770             type_of_node_must_outlive(rcx,
771                                       infer::AddrOf(expr.span),
772                                       head.id,
773                                       ty::ReScope(expr.id));
774
775             let repeating_scope = rcx.set_repeating_scope(body.id);
776             rcx.visit_block(&**body);
777             rcx.set_repeating_scope(repeating_scope);
778         }
779
780         _ => {
781             visit::walk_expr(rcx, expr);
782         }
783     }
784 }
785
786 fn constrain_cast(rcx: &mut Rcx,
787                   cast_expr: &ast::Expr,
788                   source_expr: &ast::Expr)
789 {
790     debug!("constrain_cast(cast_expr={}, source_expr={})",
791            cast_expr.repr(rcx.tcx()),
792            source_expr.repr(rcx.tcx()));
793
794     let source_ty = rcx.resolve_node_type(source_expr.id);
795     let target_ty = rcx.resolve_node_type(cast_expr.id);
796
797     walk_cast(rcx, cast_expr, source_ty, target_ty);
798
799     fn walk_cast(rcx: &mut Rcx,
800                  cast_expr: &ast::Expr,
801                  from_ty: ty::t,
802                  to_ty: ty::t) {
803         debug!("walk_cast(from_ty={}, to_ty={})",
804                from_ty.repr(rcx.tcx()),
805                to_ty.repr(rcx.tcx()));
806         match (&ty::get(from_ty).sty, &ty::get(to_ty).sty) {
807             /*From:*/ (&ty::ty_rptr(from_r, ref from_mt),
808             /*To:  */  &ty::ty_rptr(to_r, ref to_mt)) => {
809                 // Target cannot outlive source, naturally.
810                 rcx.fcx.mk_subr(infer::Reborrow(cast_expr.span), to_r, from_r);
811                 walk_cast(rcx, cast_expr, from_mt.ty, to_mt.ty);
812             }
813
814             /*From:*/ (_,
815             /*To:  */  &ty::ty_trait(box ty::TyTrait { bounds, .. })) => {
816                 // When T is existentially quantified as a trait
817                 // `Foo+'to`, it must outlive the region bound `'to`.
818                 type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
819                                   from_ty, bounds.region_bound);
820             }
821
822             /*From:*/ (&ty::ty_uniq(from_referent_ty),
823             /*To:  */  &ty::ty_uniq(to_referent_ty)) => {
824                 walk_cast(rcx, cast_expr, from_referent_ty, to_referent_ty);
825             }
826
827             _ => { }
828         }
829     }
830 }
831
832 fn check_expr_fn_block(rcx: &mut Rcx,
833                        expr: &ast::Expr,
834                        body: &ast::Block) {
835     let tcx = rcx.fcx.tcx();
836     let function_type = rcx.resolve_node_type(expr.id);
837
838     match ty::get(function_type).sty {
839         ty::ty_closure(box ty::ClosureTy{store: ty::RegionTraitStore(..),
840                                          bounds: ref bounds,
841                                          ..}) => {
842             // For closure, ensure that the variables outlive region
843             // bound, since they are captured by reference.
844             freevars::with_freevars(tcx, expr.id, |freevars| {
845                 if freevars.is_empty() {
846                     // No free variables means that the environment
847                     // will be NULL at runtime and hence the closure
848                     // has static lifetime.
849                 } else {
850                     // Variables being referenced must outlive closure.
851                     constrain_free_variables_in_stack_closure(
852                         rcx, bounds.region_bound, expr, freevars);
853
854                     // Closure is stack allocated and hence cannot
855                     // outlive the appropriate temporary scope.
856                     let s = rcx.repeating_scope;
857                     rcx.fcx.mk_subr(infer::InfStackClosure(expr.span),
858                                     bounds.region_bound, ty::ReScope(s));
859                 }
860             });
861         }
862         ty::ty_closure(box ty::ClosureTy{store: ty::UniqTraitStore,
863                                          bounds: ref bounds,
864                                          ..}) => {
865             // For proc, ensure that the *types* of the variables
866             // outlive region bound, since they are captured by value.
867             freevars::with_freevars(tcx, expr.id, |freevars| {
868                 ensure_free_variable_types_outlive_closure_bound(
869                     rcx, bounds.region_bound, expr, freevars);
870             });
871         }
872         ty::ty_unboxed_closure(_, region) => {
873             freevars::with_freevars(tcx, expr.id, |freevars| {
874                 // No free variables means that there is no environment and
875                 // hence the closure has static lifetime. Otherwise, the
876                 // closure must not outlive the variables it closes over
877                 // by-reference.
878                 //
879                 // NDM -- this seems wrong, discuss with pcwalton, should
880                 // be straightforward enough.
881                 if !freevars.is_empty() {
882                     ensure_free_variable_types_outlive_closure_bound(
883                         rcx, region, expr, freevars);
884                 }
885             })
886         }
887         _ => { }
888     }
889
890     let repeating_scope = rcx.set_repeating_scope(body.id);
891     visit::walk_expr(rcx, expr);
892     rcx.set_repeating_scope(repeating_scope);
893
894     match ty::get(function_type).sty {
895         ty::ty_closure(box ty::ClosureTy {
896                 store: ty::RegionTraitStore(..),
897                 ..
898             }) => {
899             freevars::with_freevars(tcx, expr.id, |freevars| {
900                 propagate_upupvar_borrow_kind(rcx, expr, freevars);
901             })
902         }
903         _ => ()
904     }
905
906     fn ensure_free_variable_types_outlive_closure_bound(
907         rcx: &mut Rcx,
908         region_bound: ty::Region,
909         expr: &ast::Expr,
910         freevars: &[freevars::freevar_entry])
911     {
912         /*!
913          * Make sure that the type of all free variables referenced
914          * inside a closure/proc outlive the closure/proc's lifetime
915          * bound. This is just a special case of the usual rules about
916          * closed over values outliving the object's lifetime bound.
917          */
918
919         let tcx = rcx.fcx.ccx.tcx;
920
921         debug!("ensure_free_variable_types_outlive_closure_bound({}, {})",
922                region_bound.repr(tcx), expr.repr(tcx));
923
924         for freevar in freevars.iter() {
925             let var_node_id = {
926                 let def_id = freevar.def.def_id();
927                 assert!(def_id.krate == ast::LOCAL_CRATE);
928                 def_id.node
929             };
930
931             let var_ty = rcx.resolve_node_type(var_node_id);
932
933             type_must_outlive(
934                 rcx, infer::RelateProcBound(expr.span, var_node_id, var_ty),
935                 var_ty, region_bound);
936         }
937     }
938
939     fn constrain_free_variables_in_stack_closure(
940         rcx: &mut Rcx,
941         region_bound: ty::Region,
942         expr: &ast::Expr,
943         freevars: &[freevars::freevar_entry])
944     {
945         /*!
946          * Make sure that all free variables referenced inside the
947          * closure outlive the closure's lifetime bound. Also, create
948          * an entry in the upvar_borrows map with a region.
949          */
950
951         let tcx = rcx.fcx.ccx.tcx;
952         let infcx = rcx.fcx.infcx();
953         debug!("constrain_free_variables({}, {})",
954                region_bound.repr(tcx), expr.repr(tcx));
955         for freevar in freevars.iter() {
956             debug!("freevar def is {:?}", freevar.def);
957
958             // Identify the variable being closed over and its node-id.
959             let def = freevar.def;
960             let var_node_id = {
961                 let def_id = def.def_id();
962                 assert!(def_id.krate == ast::LOCAL_CRATE);
963                 def_id.node
964             };
965             let upvar_id = ty::UpvarId { var_id: var_node_id,
966                                          closure_expr_id: expr.id };
967
968             // Create a region variable to represent this borrow. This borrow
969             // must outlive the region on the closure.
970             let origin = infer::UpvarRegion(upvar_id, expr.span);
971             let freevar_region = infcx.next_region_var(origin);
972             rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id),
973                             region_bound, freevar_region);
974
975             // Create a UpvarBorrow entry. Note that we begin with a
976             // const borrow_kind, but change it to either mut or
977             // immutable as dictated by the uses.
978             let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow,
979                                                  region: freevar_region };
980             rcx.fcx.inh.upvar_borrow_map.borrow_mut().insert(upvar_id,
981                                                              upvar_borrow);
982
983             // Guarantee that the closure does not outlive the variable itself.
984             let enclosing_region = region_of_def(rcx.fcx, def);
985             debug!("enclosing_region = {}", enclosing_region.repr(tcx));
986             rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id),
987                             region_bound, enclosing_region);
988         }
989     }
990
991     fn propagate_upupvar_borrow_kind(rcx: &mut Rcx,
992                                      expr: &ast::Expr,
993                                      freevars: &[freevars::freevar_entry]) {
994         let tcx = rcx.fcx.ccx.tcx;
995         debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
996         for freevar in freevars.iter() {
997             // Because of the semi-hokey way that we are doing
998             // borrow_kind inference, we need to check for
999             // indirect dependencies, like so:
1000             //
1001             //     let mut x = 0;
1002             //     outer_call(|| {
1003             //         inner_call(|| {
1004             //             x = 1;
1005             //         });
1006             //     });
1007             //
1008             // Here, the `inner_call` is basically "reborrowing" the
1009             // outer pointer. With no other changes, `inner_call`
1010             // would infer that it requires a mutable borrow, but
1011             // `outer_call` would infer that a const borrow is
1012             // sufficient. This is because we haven't linked the
1013             // borrow_kind of the borrow that occurs in the inner
1014             // closure to the borrow_kind of the borrow in the outer
1015             // closure. Note that regions *are* naturally linked
1016             // because we have a proper inference scheme there.
1017             //
1018             // Anyway, for borrow_kind, we basically go back over now
1019             // after checking the inner closure (and hence
1020             // determining the final borrow_kind) and propagate that as
1021             // a constraint on the outer closure.
1022             match freevar.def {
1023                 def::DefUpvar(var_id, _, outer_closure_id, _) => {
1024                     // thing being captured is itself an upvar:
1025                     let outer_upvar_id = ty::UpvarId {
1026                         var_id: var_id,
1027                         closure_expr_id: outer_closure_id };
1028                     let inner_upvar_id = ty::UpvarId {
1029                         var_id: var_id,
1030                         closure_expr_id: expr.id };
1031                     link_upvar_borrow_kind_for_nested_closures(rcx,
1032                                                                inner_upvar_id,
1033                                                                outer_upvar_id);
1034                 }
1035                 _ => {}
1036             }
1037         }
1038     }
1039 }
1040
1041 fn constrain_callee(rcx: &mut Rcx,
1042                     callee_id: ast::NodeId,
1043                     call_expr: &ast::Expr,
1044                     callee_expr: &ast::Expr) {
1045     let call_region = ty::ReScope(call_expr.id);
1046
1047     let callee_ty = rcx.resolve_node_type(callee_id);
1048     match ty::get(callee_ty).sty {
1049         ty::ty_bare_fn(..) => { }
1050         ty::ty_closure(ref closure_ty) => {
1051             let region = match closure_ty.store {
1052                 ty::RegionTraitStore(r, _) => {
1053                     // While we're here, link the closure's region with a unique
1054                     // immutable borrow (gathered later in borrowck)
1055                     let mc = mc::MemCategorizationContext::new(rcx);
1056                     let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
1057                     link_region(rcx, callee_expr.span, call_region,
1058                                 ty::UniqueImmBorrow, expr_cmt);
1059                     r
1060                 }
1061                 ty::UniqTraitStore => ty::ReStatic
1062             };
1063             rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span),
1064                             call_region, region);
1065
1066             let region = closure_ty.bounds.region_bound;
1067             rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span),
1068                             call_region, region);
1069         }
1070         _ => {
1071             // this should not happen, but it does if the program is
1072             // erroneous
1073             //
1074             // tcx.sess.span_bug(
1075             //     callee_expr.span,
1076             //     format!("Calling non-function: {}", callee_ty.repr(tcx)));
1077         }
1078     }
1079 }
1080
1081 fn constrain_call<'a, I: Iterator<&'a ast::Expr>>(rcx: &mut Rcx,
1082                                                   call_expr: &ast::Expr,
1083                                                   receiver: Option<&ast::Expr>,
1084                                                   mut arg_exprs: I,
1085                                                   implicitly_ref_args: bool) {
1086     //! Invoked on every call site (i.e., normal calls, method calls,
1087     //! and overloaded operators). Constrains the regions which appear
1088     //! in the type of the function. Also constrains the regions that
1089     //! appear in the arguments appropriately.
1090
1091     let tcx = rcx.fcx.tcx();
1092     debug!("constrain_call(call_expr={}, \
1093             receiver={}, \
1094             implicitly_ref_args={:?})",
1095             call_expr.repr(tcx),
1096             receiver.repr(tcx),
1097             implicitly_ref_args);
1098
1099     // `callee_region` is the scope representing the time in which the
1100     // call occurs.
1101     //
1102     // FIXME(#6268) to support nested method calls, should be callee_id
1103     let callee_scope = call_expr.id;
1104     let callee_region = ty::ReScope(callee_scope);
1105
1106     debug!("callee_region={}", callee_region.repr(tcx));
1107
1108     for arg_expr in arg_exprs {
1109         debug!("Argument: {}", arg_expr.repr(tcx));
1110
1111         // ensure that any regions appearing in the argument type are
1112         // valid for at least the lifetime of the function:
1113         type_of_node_must_outlive(
1114             rcx, infer::CallArg(arg_expr.span),
1115             arg_expr.id, callee_region);
1116
1117         // unfortunately, there are two means of taking implicit
1118         // references, and we need to propagate constraints as a
1119         // result. modes are going away and the "DerefArgs" code
1120         // should be ported to use adjustments
1121         if implicitly_ref_args {
1122             link_by_ref(rcx, arg_expr, callee_scope);
1123         }
1124     }
1125
1126     // as loop above, but for receiver
1127     for r in receiver.iter() {
1128         debug!("receiver: {}", r.repr(tcx));
1129         type_of_node_must_outlive(
1130             rcx, infer::CallRcvr(r.span),
1131             r.id, callee_region);
1132         if implicitly_ref_args {
1133             link_by_ref(rcx, &**r, callee_scope);
1134         }
1135     }
1136 }
1137
1138 fn constrain_autoderefs(rcx: &mut Rcx,
1139                         deref_expr: &ast::Expr,
1140                         derefs: uint,
1141                         mut derefd_ty: ty::t) {
1142     /*!
1143      * Invoked on any auto-dereference that occurs.  Checks that if
1144      * this is a region pointer being dereferenced, the lifetime of
1145      * the pointer includes the deref expr.
1146      */
1147     let r_deref_expr = ty::ReScope(deref_expr.id);
1148     for i in range(0u, derefs) {
1149         debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={:?}/{:?}",
1150                rcx.fcx.infcx().ty_to_string(derefd_ty),
1151                i, derefs);
1152
1153         let method_call = MethodCall::autoderef(deref_expr.id, i);
1154         derefd_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
1155             Some(method) => {
1156                 // Treat overloaded autoderefs as if an AutoRef adjustment
1157                 // was applied on the base type, as that is always the case.
1158                 let fn_sig = ty::ty_fn_sig(method.ty);
1159                 let self_ty = *fn_sig.inputs.get(0);
1160                 let (m, r) = match ty::get(self_ty).sty {
1161                     ty::ty_rptr(r, ref m) => (m.mutbl, r),
1162                     _ => rcx.tcx().sess.span_bug(deref_expr.span,
1163                             format!("bad overloaded deref type {}",
1164                                     method.ty.repr(rcx.tcx())).as_slice())
1165                 };
1166                 {
1167                     let mc = mc::MemCategorizationContext::new(rcx);
1168                     let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
1169                     link_region(rcx, deref_expr.span, r,
1170                                 ty::BorrowKind::from_mutbl(m), self_cmt);
1171                 }
1172
1173                 // Specialized version of constrain_call.
1174                 type_must_outlive(rcx, infer::CallRcvr(deref_expr.span),
1175                                   self_ty, r_deref_expr);
1176                 type_must_outlive(rcx, infer::CallReturn(deref_expr.span),
1177                                   fn_sig.output, r_deref_expr);
1178                 fn_sig.output
1179             }
1180             None => derefd_ty
1181         };
1182
1183         match ty::get(derefd_ty).sty {
1184             ty::ty_rptr(r_ptr, _) => {
1185                 mk_subregion_due_to_dereference(rcx, deref_expr.span,
1186                                                 r_deref_expr, r_ptr);
1187             }
1188             _ => {}
1189         }
1190
1191         match ty::deref(derefd_ty, true) {
1192             Some(mt) => derefd_ty = mt.ty,
1193             /* if this type can't be dereferenced, then there's already an error
1194                in the session saying so. Just bail out for now */
1195             None => break
1196         }
1197     }
1198 }
1199
1200 pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
1201                                        deref_span: Span,
1202                                        minimum_lifetime: ty::Region,
1203                                        maximum_lifetime: ty::Region) {
1204     rcx.fcx.mk_subr(infer::DerefPointer(deref_span),
1205                     minimum_lifetime, maximum_lifetime)
1206 }
1207
1208
1209 fn constrain_index(rcx: &mut Rcx,
1210                    index_expr: &ast::Expr,
1211                    indexed_ty: ty::t)
1212 {
1213     /*!
1214      * Invoked on any index expression that occurs.  Checks that if
1215      * this is a slice being indexed, the lifetime of the pointer
1216      * includes the deref expr.
1217      */
1218
1219     debug!("constrain_index(index_expr=?, indexed_ty={}",
1220            rcx.fcx.infcx().ty_to_string(indexed_ty));
1221
1222     let r_index_expr = ty::ReScope(index_expr.id);
1223     match ty::get(indexed_ty).sty {
1224         ty::ty_rptr(r_ptr, mt) => match ty::get(mt.ty).sty {
1225             ty::ty_vec(_, None) | ty::ty_str => {
1226                 rcx.fcx.mk_subr(infer::IndexSlice(index_expr.span),
1227                                 r_index_expr, r_ptr);
1228             }
1229             _ => {}
1230         },
1231
1232         _ => {}
1233     }
1234 }
1235
1236 fn type_of_node_must_outlive(
1237     rcx: &mut Rcx,
1238     origin: infer::SubregionOrigin,
1239     id: ast::NodeId,
1240     minimum_lifetime: ty::Region)
1241 {
1242     /*!
1243      * Guarantees that any lifetimes which appear in the type of
1244      * the node `id` (after applying adjustments) are valid for at
1245      * least `minimum_lifetime`
1246      */
1247
1248     let tcx = rcx.fcx.tcx();
1249
1250     // Try to resolve the type.  If we encounter an error, then typeck
1251     // is going to fail anyway, so just stop here and let typeck
1252     // report errors later on in the writeback phase.
1253     let ty0 = rcx.resolve_node_type(id);
1254     let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
1255                            rcx.fcx.inh.adjustments.borrow().find(&id),
1256                            |method_call| rcx.resolve_method_type(method_call));
1257     debug!("constrain_regions_in_type_of_node(\
1258             ty={}, ty0={}, id={}, minimum_lifetime={:?})",
1259            ty_to_string(tcx, ty), ty_to_string(tcx, ty0),
1260            id, minimum_lifetime);
1261     type_must_outlive(rcx, origin, ty, minimum_lifetime);
1262 }
1263
1264 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
1265                mutability: ast::Mutability, base: &ast::Expr) {
1266     /*!
1267      * Computes the guarantor for an expression `&base` and then
1268      * ensures that the lifetime of the resulting pointer is linked
1269      * to the lifetime of its guarantor (if any).
1270      */
1271
1272     debug!("link_addr_of(base=?)");
1273
1274     let cmt = {
1275         let mc = mc::MemCategorizationContext::new(rcx);
1276         ignore_err!(mc.cat_expr(base))
1277     };
1278     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
1279 }
1280
1281 fn link_local(rcx: &Rcx, local: &ast::Local) {
1282     /*!
1283      * Computes the guarantors for any ref bindings in a `let` and
1284      * then ensures that the lifetime of the resulting pointer is
1285      * linked to the lifetime of the initialization expression.
1286      */
1287
1288     debug!("regionck::for_local()");
1289     let init_expr = match local.init {
1290         None => { return; }
1291         Some(ref expr) => &**expr,
1292     };
1293     let mc = mc::MemCategorizationContext::new(rcx);
1294     let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
1295     link_pattern(rcx, mc, discr_cmt, &*local.pat);
1296 }
1297
1298 fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
1299     /*!
1300      * Computes the guarantors for any ref bindings in a match and
1301      * then ensures that the lifetime of the resulting pointer is
1302      * linked to the lifetime of its guarantor (if any).
1303      */
1304
1305     debug!("regionck::for_match()");
1306     let mc = mc::MemCategorizationContext::new(rcx);
1307     let discr_cmt = ignore_err!(mc.cat_expr(discr));
1308     debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
1309     for arm in arms.iter() {
1310         for root_pat in arm.pats.iter() {
1311             link_pattern(rcx, mc, discr_cmt.clone(), &**root_pat);
1312         }
1313     }
1314 }
1315
1316 fn link_pattern(rcx: &Rcx,
1317                 mc: mc::MemCategorizationContext<Rcx>,
1318                 discr_cmt: mc::cmt,
1319                 root_pat: &ast::Pat) {
1320     /*!
1321      * Link lifetimes of any ref bindings in `root_pat` to
1322      * the pointers found in the discriminant, if needed.
1323      */
1324
1325     let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
1326             match sub_pat.node {
1327                 // `ref x` pattern
1328                 ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
1329                     link_region_from_node_type(
1330                         rcx, sub_pat.span, sub_pat.id,
1331                         mutbl, sub_cmt);
1332                 }
1333
1334                 // `[_, ..slice, _]` pattern
1335                 ast::PatVec(_, Some(ref slice_pat), _) => {
1336                     match mc.cat_slice_pattern(sub_cmt, &**slice_pat) {
1337                         Ok((slice_cmt, slice_mutbl, slice_r)) => {
1338                             link_region(rcx, sub_pat.span, slice_r,
1339                                         ty::BorrowKind::from_mutbl(slice_mutbl),
1340                                         slice_cmt);
1341                         }
1342                         Err(()) => {}
1343                     }
1344                 }
1345                 _ => {}
1346             }
1347         });
1348 }
1349
1350 fn link_autoref(rcx: &Rcx,
1351                 expr: &ast::Expr,
1352                 autoderefs: uint,
1353                 autoref: &ty::AutoRef) {
1354     /*!
1355      * Link lifetime of borrowed pointer resulting from autoref
1356      * to lifetimes in the value being autoref'd.
1357      */
1358
1359     debug!("link_autoref(autoref={:?})", autoref);
1360     let mc = mc::MemCategorizationContext::new(rcx);
1361     let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
1362     debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
1363
1364     match *autoref {
1365         ty::AutoPtr(r, m, _) => {
1366             link_region(rcx, expr.span, r,
1367                 ty::BorrowKind::from_mutbl(m), expr_cmt);
1368         }
1369
1370         ty::AutoUnsafe(..) | ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) => {}
1371     }
1372 }
1373
1374 fn link_by_ref(rcx: &Rcx,
1375                expr: &ast::Expr,
1376                callee_scope: ast::NodeId) {
1377     /*!
1378      * Computes the guarantor for cases where the `expr` is
1379      * being passed by implicit reference and must outlive
1380      * `callee_scope`.
1381      */
1382
1383     let tcx = rcx.tcx();
1384     debug!("link_by_ref(expr={}, callee_scope={})",
1385            expr.repr(tcx), callee_scope);
1386     let mc = mc::MemCategorizationContext::new(rcx);
1387     let expr_cmt = ignore_err!(mc.cat_expr(expr));
1388     let borrow_region = ty::ReScope(callee_scope);
1389     link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
1390 }
1391
1392 fn link_region_from_node_type(rcx: &Rcx,
1393                               span: Span,
1394                               id: ast::NodeId,
1395                               mutbl: ast::Mutability,
1396                               cmt_borrowed: mc::cmt) {
1397     /*!
1398      * Like `link_region()`, except that the region is
1399      * extracted from the type of `id`, which must be some
1400      * reference (`&T`, `&str`, etc).
1401      */
1402
1403     let rptr_ty = rcx.resolve_node_type(id);
1404     if !ty::type_is_bot(rptr_ty) && !ty::type_is_error(rptr_ty) {
1405         let tcx = rcx.fcx.ccx.tcx;
1406         debug!("rptr_ty={}", ty_to_string(tcx, rptr_ty));
1407         let r = ty::ty_region(tcx, span, rptr_ty);
1408         link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
1409                     cmt_borrowed);
1410     }
1411 }
1412
1413 fn link_region(rcx: &Rcx,
1414                span: Span,
1415                borrow_region: ty::Region,
1416                borrow_kind: ty::BorrowKind,
1417                borrow_cmt: mc::cmt) {
1418     /*!
1419      * Informs the inference engine that `borrow_cmt` is being
1420      * borrowed with kind `borrow_kind` and lifetime `borrow_region`.
1421      * In order to ensure borrowck is satisfied, this may create
1422      * constraints between regions, as explained in
1423      * `link_reborrowed_region()`.
1424      */
1425
1426     let mut borrow_cmt = borrow_cmt;
1427     let mut borrow_kind = borrow_kind;
1428
1429     loop {
1430         debug!("link_region(borrow_region={}, borrow_kind={}, borrow_cmt={})",
1431                borrow_region.repr(rcx.tcx()),
1432                borrow_kind.repr(rcx.tcx()),
1433                borrow_cmt.repr(rcx.tcx()));
1434         match borrow_cmt.cat.clone() {
1435             mc::cat_deref(ref_cmt, _,
1436                           mc::Implicit(ref_kind, ref_region)) |
1437             mc::cat_deref(ref_cmt, _,
1438                           mc::BorrowedPtr(ref_kind, ref_region)) => {
1439                 match link_reborrowed_region(rcx, span,
1440                                              borrow_region, borrow_kind,
1441                                              ref_cmt, ref_region, ref_kind) {
1442                     Some((c, k)) => {
1443                         borrow_cmt = c;
1444                         borrow_kind = k;
1445                     }
1446                     None => {
1447                         return;
1448                     }
1449                 }
1450             }
1451
1452             mc::cat_discr(cmt_base, _) |
1453             mc::cat_downcast(cmt_base) |
1454             mc::cat_deref(cmt_base, _, mc::GcPtr(..)) |
1455             mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
1456             mc::cat_interior(cmt_base, _) => {
1457                 // Borrowing interior or owned data requires the base
1458                 // to be valid and borrowable in the same fashion.
1459                 borrow_cmt = cmt_base;
1460                 borrow_kind = borrow_kind;
1461             }
1462
1463             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1464             mc::cat_static_item |
1465             mc::cat_copied_upvar(..) |
1466             mc::cat_local(..) |
1467             mc::cat_arg(..) |
1468             mc::cat_upvar(..) |
1469             mc::cat_rvalue(..) => {
1470                 // These are all "base cases" with independent lifetimes
1471                 // that are not subject to inference
1472                 return;
1473             }
1474         }
1475     }
1476 }
1477
1478 fn link_reborrowed_region(rcx: &Rcx,
1479                           span: Span,
1480                           borrow_region: ty::Region,
1481                           borrow_kind: ty::BorrowKind,
1482                           ref_cmt: mc::cmt,
1483                           ref_region: ty::Region,
1484                           ref_kind: ty::BorrowKind)
1485                           -> Option<(mc::cmt, ty::BorrowKind)>
1486 {
1487     /*!
1488      * This is the most complicated case: the path being borrowed is
1489      * itself the referent of a borrowed pointer. Let me give an
1490      * example fragment of code to make clear(er) the situation:
1491      *
1492      *    let r: &'a mut T = ...;  // the original reference "r" has lifetime 'a
1493      *    ...
1494      *    &'z *r                   // the reborrow has lifetime 'z
1495      *
1496      * Now, in this case, our primary job is to add the inference
1497      * constraint that `'z <= 'a`. Given this setup, let's clarify the
1498      * parameters in (roughly) terms of the example:
1499      *
1500      *     A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T`
1501      *     borrow_region   ^~                 ref_region    ^~
1502      *     borrow_kind        ^~               ref_kind        ^~
1503      *     ref_cmt                 ^
1504      *
1505      * Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc).
1506      *
1507      * Unfortunately, there are some complications beyond the simple
1508      * scenario I just painted:
1509      *
1510      * 1. The reference `r` might in fact be a "by-ref" upvar. In that
1511      *    case, we have two jobs. First, we are inferring whether this reference
1512      *    should be an `&T`, `&mut T`, or `&uniq T` reference, and we must
1513      *    adjust that based on this borrow (e.g., if this is an `&mut` borrow,
1514      *    then `r` must be an `&mut` reference). Second, whenever we link
1515      *    two regions (here, `'z <= 'a`), we supply a *cause*, and in this
1516      *    case we adjust the cause to indicate that the reference being
1517      *    "reborrowed" is itself an upvar. This provides a nicer error message
1518      *    should something go wrong.
1519      *
1520      * 2. There may in fact be more levels of reborrowing. In the
1521      *    example, I said the borrow was like `&'z *r`, but it might
1522      *    in fact be a borrow like `&'z **q` where `q` has type `&'a
1523      *    &'b mut T`. In that case, we want to ensure that `'z <= 'a`
1524      *    and `'z <= 'b`. This is explained more below.
1525      *
1526      * The return value of this function indicates whether we need to
1527      * recurse and process `ref_cmt` (see case 2 above).
1528      */
1529
1530     // Detect references to an upvar `x`:
1531     let cause = match ref_cmt.cat {
1532         mc::cat_upvar(ref upvar_id, _) => {
1533             let mut upvar_borrow_map =
1534                 rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1535             match upvar_borrow_map.find_mut(upvar_id) {
1536                 Some(upvar_borrow) => {
1537                     // Adjust mutability that we infer for the upvar
1538                     // so it can accommodate being borrowed with
1539                     // mutability `kind`:
1540                     adjust_upvar_borrow_kind_for_loan(*upvar_id,
1541                                                       upvar_borrow,
1542                                                       borrow_kind);
1543
1544                     infer::ReborrowUpvar(span, *upvar_id)
1545                 }
1546                 None => {
1547                     rcx.tcx().sess.span_bug(
1548                         span,
1549                         format!("Illegal upvar id: {}",
1550                                 upvar_id.repr(
1551                                     rcx.tcx())).as_slice());
1552                 }
1553             }
1554         }
1555
1556         _ => {
1557             infer::Reborrow(span)
1558         }
1559     };
1560
1561     debug!("link_reborrowed_region: {} <= {}",
1562            borrow_region.repr(rcx.tcx()),
1563            ref_region.repr(rcx.tcx()));
1564     rcx.fcx.mk_subr(cause, borrow_region, ref_region);
1565
1566     // Decide whether we need to recurse and link any regions within
1567     // the `ref_cmt`. This is concerned for the case where the value
1568     // being reborrowed is in fact a borrowed pointer found within
1569     // another borrowed pointer. For example:
1570     //
1571     //    let p: &'b &'a mut T = ...;
1572     //    ...
1573     //    &'z **p
1574     //
1575     // What makes this case particularly tricky is that, if the data
1576     // being borrowed is a `&mut` or `&uniq` borrow, borrowck requires
1577     // not only that `'z <= 'a`, (as before) but also `'z <= 'b`
1578     // (otherwise the user might mutate through the `&mut T` reference
1579     // after `'b` expires and invalidate the borrow we are looking at
1580     // now).
1581     //
1582     // So let's re-examine our parameters in light of this more
1583     // complicated (possible) scenario:
1584     //
1585     //     A borrow of: `& 'z bk * * p` where `p` has type `&'b bk & 'a bk T`
1586     //     borrow_region   ^~                 ref_region             ^~
1587     //     borrow_kind        ^~               ref_kind                 ^~
1588     //     ref_cmt                 ^~~
1589     //
1590     // (Note that since we have not examined `ref_cmt.cat`, we don't
1591     // know whether this scenario has occurred; but I wanted to show
1592     // how all the types get adjusted.)
1593     match ref_kind {
1594         ty::ImmBorrow => {
1595             // The reference being reborrowed is a sharable ref of
1596             // type `&'a T`. In this case, it doesn't matter where we
1597             // *found* the `&T` pointer, the memory it references will
1598             // be valid and immutable for `'a`. So we can stop here.
1599             //
1600             // (Note that the `borrow_kind` must also be ImmBorrow or
1601             // else the user is borrowed imm memory as mut memory,
1602             // which means they'll get an error downstream in borrowck
1603             // anyhow.)
1604             return None;
1605         }
1606
1607         ty::MutBorrow | ty::UniqueImmBorrow => {
1608             // The reference being reborrowed is either an `&mut T` or
1609             // `&uniq T`. This is the case where recursion is needed.
1610             //
1611             // One interesting twist is that we can weaken the borrow
1612             // kind when we recurse: to reborrow an `&mut` referent as
1613             // mutable, borrowck requires a unique path to the `&mut`
1614             // reference but not necessarily a *mutable* path.
1615             let new_borrow_kind = match borrow_kind {
1616                 ty::ImmBorrow =>
1617                     ty::ImmBorrow,
1618                 ty::MutBorrow | ty::UniqueImmBorrow =>
1619                     ty::UniqueImmBorrow
1620             };
1621             return Some((ref_cmt, new_borrow_kind));
1622         }
1623     }
1624 }
1625
1626 fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
1627                                          lhs: &ast::Expr) {
1628     /*!
1629      * Adjusts the inferred borrow_kind as needed to account
1630      * for upvars that are assigned to in an assignment
1631      * expression.
1632      */
1633
1634     let mc = mc::MemCategorizationContext::new(rcx);
1635     let cmt = ignore_err!(mc.cat_expr(lhs));
1636     adjust_upvar_borrow_kind_for_mut(rcx, cmt);
1637 }
1638
1639 fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
1640                                     cmt: mc::cmt) {
1641     /*!
1642      * Indicates that `cmt` is being directly mutated (e.g., assigned
1643      * to).  If cmt contains any by-ref upvars, this implies that
1644      * those upvars must be borrowed using an `&mut` borow.
1645      */
1646
1647     let mut cmt = cmt;
1648     loop {
1649         debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
1650                cmt.repr(rcx.tcx()));
1651
1652         match cmt.cat.clone() {
1653             mc::cat_deref(base, _, mc::OwnedPtr) |
1654             mc::cat_interior(base, _) |
1655             mc::cat_downcast(base) |
1656             mc::cat_discr(base, _) => {
1657                 // Interior or owned data is mutable if base is
1658                 // mutable, so iterate to the base.
1659                 cmt = base;
1660                 continue;
1661             }
1662
1663             mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
1664             mc::cat_deref(base, _, mc::Implicit(..)) => {
1665                 match base.cat {
1666                     mc::cat_upvar(ref upvar_id, _) => {
1667                         // if this is an implicit deref of an
1668                         // upvar, then we need to modify the
1669                         // borrow_kind of the upvar to make sure it
1670                         // is inferred to mutable if necessary
1671                         let mut upvar_borrow_map =
1672                             rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1673                         let ub = upvar_borrow_map.get_mut(upvar_id);
1674                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow);
1675                     }
1676
1677                     _ => {}
1678                 }
1679
1680                 // assignment to deref of an `&mut`
1681                 // borrowed pointer implies that the
1682                 // pointer itself must be unique, but not
1683                 // necessarily *mutable*
1684                 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1685             }
1686
1687             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1688             mc::cat_deref(_, _, mc::GcPtr) |
1689             mc::cat_static_item |
1690             mc::cat_rvalue(_) |
1691             mc::cat_copied_upvar(_) |
1692             mc::cat_local(_) |
1693             mc::cat_arg(_) |
1694             mc::cat_upvar(..) => {
1695                 return;
1696             }
1697         }
1698     }
1699 }
1700
1701 fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
1702     let mut cmt = cmt;
1703     loop {
1704         debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
1705                cmt.repr(rcx.tcx()));
1706
1707         match cmt.cat.clone() {
1708             mc::cat_deref(base, _, mc::OwnedPtr) |
1709             mc::cat_interior(base, _) |
1710             mc::cat_downcast(base) |
1711             mc::cat_discr(base, _) => {
1712                 // Interior or owned data is unique if base is
1713                 // unique.
1714                 cmt = base;
1715                 continue;
1716             }
1717
1718             mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
1719             mc::cat_deref(base, _, mc::Implicit(..)) => {
1720                 match base.cat {
1721                     mc::cat_upvar(ref upvar_id, _) => {
1722                         // if this is an implicit deref of an
1723                         // upvar, then we need to modify the
1724                         // borrow_kind of the upvar to make sure it
1725                         // is inferred to unique if necessary
1726                         let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1727                         let ub = ub.get_mut(upvar_id);
1728                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow);
1729                     }
1730
1731                     _ => {}
1732                 }
1733
1734                 // for a borrowed pointer to be unique, its
1735                 // base must be unique
1736                 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1737             }
1738
1739             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1740             mc::cat_deref(_, _, mc::GcPtr) |
1741             mc::cat_static_item |
1742             mc::cat_rvalue(_) |
1743             mc::cat_copied_upvar(_) |
1744             mc::cat_local(_) |
1745             mc::cat_arg(_) |
1746             mc::cat_upvar(..) => {
1747                 return;
1748             }
1749         }
1750     }
1751 }
1752
1753 fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx,
1754                                               inner_upvar_id: ty::UpvarId,
1755                                               outer_upvar_id: ty::UpvarId) {
1756     /*!
1757      * Indicates that the borrow_kind of `outer_upvar_id` must
1758      * permit a reborrowing with the borrow_kind of `inner_upvar_id`.
1759      * This occurs in nested closures, see comment above at the call to
1760      * this function.
1761      */
1762
1763     debug!("link_upvar_borrow_kind: inner_upvar_id={:?} outer_upvar_id={:?}",
1764            inner_upvar_id, outer_upvar_id);
1765
1766     let mut upvar_borrow_map = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1767     let inner_borrow = upvar_borrow_map.get_copy(&inner_upvar_id);
1768     match upvar_borrow_map.find_mut(&outer_upvar_id) {
1769         Some(outer_borrow) => {
1770             adjust_upvar_borrow_kind(outer_upvar_id, outer_borrow, inner_borrow.kind);
1771         }
1772         None => { /* outer closure is not a stack closure */ }
1773     }
1774 }
1775
1776 fn adjust_upvar_borrow_kind_for_loan(upvar_id: ty::UpvarId,
1777                                      upvar_borrow: &mut ty::UpvarBorrow,
1778                                      kind: ty::BorrowKind) {
1779     debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}",
1780            upvar_id, upvar_borrow.kind, kind);
1781
1782     adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind)
1783 }
1784
1785 fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId,
1786                             upvar_borrow: &mut ty::UpvarBorrow,
1787                             kind: ty::BorrowKind) {
1788     /*!
1789      * We infer the borrow_kind with which to borrow upvars in a stack
1790      * closure. The borrow_kind basically follows a lattice of
1791      * `imm < unique-imm < mut`, moving from left to right as needed (but never
1792      * right to left). Here the argument `mutbl` is the borrow_kind that
1793      * is required by some particular use.
1794      */
1795
1796     debug!("adjust_upvar_borrow_kind: id={:?} kind=({:?} -> {:?})",
1797            upvar_id, upvar_borrow.kind, kind);
1798
1799     match (upvar_borrow.kind, kind) {
1800         // Take RHS:
1801         (ty::ImmBorrow, ty::UniqueImmBorrow) |
1802         (ty::ImmBorrow, ty::MutBorrow) |
1803         (ty::UniqueImmBorrow, ty::MutBorrow) => {
1804             upvar_borrow.kind = kind;
1805         }
1806         // Take LHS:
1807         (ty::ImmBorrow, ty::ImmBorrow) |
1808         (ty::UniqueImmBorrow, ty::ImmBorrow) |
1809         (ty::UniqueImmBorrow, ty::UniqueImmBorrow) |
1810         (ty::MutBorrow, _) => {
1811         }
1812     }
1813 }
1814
1815 fn type_must_outlive(rcx: &mut Rcx,
1816                      origin: infer::SubregionOrigin,
1817                      ty: ty::t,
1818                      region: ty::Region)
1819 {
1820     /*!
1821      * Ensures that all borrowed data reachable via `ty` outlives `region`.
1822      */
1823
1824     debug!("type_must_outlive(ty={}, region={})",
1825            ty.repr(rcx.tcx()),
1826            region.repr(rcx.tcx()));
1827
1828     let constraints =
1829         regionmanip::region_wf_constraints(
1830             rcx.tcx(),
1831             ty,
1832             region);
1833     for constraint in constraints.iter() {
1834         debug!("constraint: {}", constraint.repr(rcx.tcx()));
1835         match *constraint {
1836             regionmanip::RegionSubRegionConstraint(None, r_a, r_b) => {
1837                 rcx.fcx.mk_subr(origin.clone(), r_a, r_b);
1838             }
1839             regionmanip::RegionSubRegionConstraint(Some(ty), r_a, r_b) => {
1840                 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
1841                 rcx.fcx.mk_subr(o1, r_a, r_b);
1842             }
1843             regionmanip::RegionSubParamConstraint(None, r_a, param_b) => {
1844                 param_must_outlive(rcx, origin.clone(), r_a, param_b);
1845             }
1846             regionmanip::RegionSubParamConstraint(Some(ty), r_a, param_b) => {
1847                 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
1848                 param_must_outlive(rcx, o1, r_a, param_b);
1849             }
1850         }
1851     }
1852 }
1853
1854 fn param_must_outlive(rcx: &Rcx,
1855                       origin: infer::SubregionOrigin,
1856                       region: ty::Region,
1857                       param_ty: ty::ParamTy) {
1858     let param_env = &rcx.fcx.inh.param_env;
1859
1860     debug!("param_must_outlive(region={}, param_ty={})",
1861            region.repr(rcx.tcx()),
1862            param_ty.repr(rcx.tcx()));
1863
1864     // Collect all regions that `param_ty` is known to outlive into
1865     // this vector:
1866     let mut param_bounds;
1867
1868     // To start, collect bounds from user:
1869     let param_bound = param_env.bounds.get(param_ty.space, param_ty.idx);
1870     param_bounds =
1871         ty::required_region_bounds(rcx.tcx(),
1872                                    param_bound.opt_region_bound.as_slice(),
1873                                    param_bound.builtin_bounds,
1874                                    param_bound.trait_bounds.as_slice());
1875
1876     // Collect default bound of fn body that applies to all in scope
1877     // type parameters:
1878     param_bounds.push(param_env.implicit_region_bound);
1879
1880     // Finally, collect regions we scraped from the well-formedness
1881     // constraints in the fn signature. To do that, we walk the list
1882     // of known relations from the fn ctxt.
1883     //
1884     // This is crucial because otherwise code like this fails:
1885     //
1886     //     fn foo<'a, A>(x: &'a A) { x.bar() }
1887     //
1888     // The problem is that the type of `x` is `&'a A`. To be
1889     // well-formed, then, A must be lower-bounded by `'a`, but we
1890     // don't know that this holds from first principles.
1891     for &(ref r, ref p) in rcx.region_param_pairs.iter() {
1892         debug!("param_ty={}/{} p={}/{}",
1893                param_ty.repr(rcx.tcx()),
1894                param_ty.def_id,
1895                p.repr(rcx.tcx()),
1896                p.def_id);
1897         if param_ty == *p {
1898             param_bounds.push(*r);
1899         }
1900     }
1901
1902     // Inform region inference that this parameter type must be
1903     // properly bounded.
1904     infer::verify_param_bound(rcx.fcx.infcx(),
1905                               origin,
1906                               param_ty,
1907                               region,
1908                               param_bounds);
1909 }