]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/regionck.rs
Auto merge of #22517 - brson:relnotes, r=Gankro
[rust.git] / src / librustc_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 //! The region check is a final pass that runs over the AST after we have
12 //! inferred the type constraints but before we have actually finalized
13 //! the types.  Its purpose is to embed a variety of region constraints.
14 //! Inserting these constraints as a separate pass is good because (1) it
15 //! localizes the code that has to do with region inference and (2) often
16 //! we cannot know what constraints are needed until the basic types have
17 //! been inferred.
18 //!
19 //! ### Interaction with the borrow checker
20 //!
21 //! In general, the job of the borrowck module (which runs later) is to
22 //! check that all soundness criteria are met, given a particular set of
23 //! regions. The job of *this* module is to anticipate the needs of the
24 //! borrow checker and infer regions that will satisfy its requirements.
25 //! It is generally true that the inference doesn't need to be sound,
26 //! meaning that if there is a bug and we inferred bad regions, the borrow
27 //! checker should catch it. This is not entirely true though; for
28 //! example, the borrow checker doesn't check subtyping, and it doesn't
29 //! check that region pointers are always live when they are used. It
30 //! might be worthwhile to fix this so that borrowck serves as a kind of
31 //! verification step -- that would add confidence in the overall
32 //! correctness of the compiler, at the cost of duplicating some type
33 //! checks and effort.
34 //!
35 //! ### Inferring the duration of borrows, automatic and otherwise
36 //!
37 //! Whenever we introduce a borrowed pointer, for example as the result of
38 //! a borrow expression `let x = &data`, the lifetime of the pointer `x`
39 //! is always specified as a region inference variable. `regionck` has the
40 //! job of adding constraints such that this inference variable is as
41 //! narrow as possible while still accommodating all uses (that is, every
42 //! dereference of the resulting pointer must be within the lifetime).
43 //!
44 //! #### Reborrows
45 //!
46 //! Generally speaking, `regionck` does NOT try to ensure that the data
47 //! `data` will outlive the pointer `x`. That is the job of borrowck.  The
48 //! one exception is when "re-borrowing" the contents of another borrowed
49 //! pointer. For example, imagine you have a borrowed pointer `b` with
50 //! lifetime L1 and you have an expression `&*b`. The result of this
51 //! expression will be another borrowed pointer with lifetime L2 (which is
52 //! an inference variable). The borrow checker is going to enforce the
53 //! constraint that L2 < L1, because otherwise you are re-borrowing data
54 //! for a lifetime larger than the original loan.  However, without the
55 //! routines in this module, the region inferencer would not know of this
56 //! dependency and thus it might infer the lifetime of L2 to be greater
57 //! than L1 (issue #3148).
58 //!
59 //! There are a number of troublesome scenarios in the tests
60 //! `region-dependent-*.rs`, but here is one example:
61 //!
62 //!     struct Foo { i: int }
63 //!     struct Bar { foo: Foo  }
64 //!     fn get_i(x: &'a Bar) -> &'a int {
65 //!        let foo = &x.foo; // Lifetime L1
66 //!        &foo.i            // Lifetime L2
67 //!     }
68 //!
69 //! Note that this comes up either with `&` expressions, `ref`
70 //! bindings, and `autorefs`, which are the three ways to introduce
71 //! a borrow.
72 //!
73 //! The key point here is that when you are borrowing a value that
74 //! is "guaranteed" by a borrowed pointer, you must link the
75 //! lifetime of that borrowed pointer (L1, here) to the lifetime of
76 //! the borrow itself (L2).  What do I mean by "guaranteed" by a
77 //! borrowed pointer? I mean any data that is reached by first
78 //! dereferencing a borrowed pointer and then either traversing
79 //! interior offsets or owned pointers.  We say that the guarantor
80 //! of such data it the region of the borrowed pointer that was
81 //! traversed.  This is essentially the same as the ownership
82 //! relation, except that a borrowed pointer never owns its
83 //! contents.
84
85 use astconv::AstConv;
86 use check::dropck;
87 use check::FnCtxt;
88 use check::implicator;
89 use check::vtable;
90 use middle::def;
91 use middle::mem_categorization as mc;
92 use middle::region::CodeExtent;
93 use middle::traits;
94 use middle::ty::{ReScope};
95 use middle::ty::{self, Ty, MethodCall};
96 use middle::infer::{self, GenericKind};
97 use middle::pat_util;
98 use util::ppaux::{ty_to_string, Repr};
99
100 use std::mem;
101 use syntax::{ast, ast_util};
102 use syntax::codemap::Span;
103 use syntax::visit;
104 use syntax::visit::Visitor;
105
106 use self::SubjectNode::Subject;
107
108 // a variation on try that just returns unit
109 macro_rules! ignore_err {
110     ($e:expr) => (match $e { Ok(e) => e, Err(_) => return () })
111 }
112
113 ///////////////////////////////////////////////////////////////////////////
114 // PUBLIC ENTRY POINTS
115
116 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
117     let mut rcx = Rcx::new(fcx, RepeatingScope(e.id), e.id, Subject(e.id));
118     if fcx.err_count_since_creation() == 0 {
119         // regionck assumes typeck succeeded
120         rcx.visit_expr(e);
121         rcx.visit_region_obligations(e.id);
122     }
123     rcx.resolve_regions_and_report_errors();
124 }
125
126 pub fn regionck_item(fcx: &FnCtxt, item: &ast::Item) {
127     let mut rcx = Rcx::new(fcx, RepeatingScope(item.id), item.id, Subject(item.id));
128     rcx.visit_region_obligations(item.id);
129     rcx.resolve_regions_and_report_errors();
130 }
131
132 pub fn regionck_fn(fcx: &FnCtxt,
133                    fn_id: ast::NodeId,
134                    fn_span: Span,
135                    decl: &ast::FnDecl,
136                    blk: &ast::Block) {
137     debug!("regionck_fn(id={})", fn_id);
138     let mut rcx = Rcx::new(fcx, RepeatingScope(blk.id), blk.id, Subject(fn_id));
139     if fcx.err_count_since_creation() == 0 {
140         // regionck assumes typeck succeeded
141         rcx.visit_fn_body(fn_id, decl, blk, fn_span);
142     }
143
144     rcx.resolve_regions_and_report_errors();
145 }
146
147 /// Checks that the types in `component_tys` are well-formed. This will add constraints into the
148 /// region graph. Does *not* run `resolve_regions_and_report_errors` and so forth.
149 pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
150                                                   span: Span,
151                                                   component_tys: &[Ty<'tcx>]) {
152     let mut rcx = Rcx::new(fcx, RepeatingScope(0), 0, SubjectNode::None);
153     for &component_ty in component_tys {
154         // Check that each type outlives the empty region. Since the
155         // empty region is a subregion of all others, this can't fail
156         // unless the type does not meet the well-formedness
157         // requirements.
158         type_must_outlive(&mut rcx, infer::RelateParamBound(span, component_ty),
159                           component_ty, ty::ReEmpty);
160     }
161 }
162
163 ///////////////////////////////////////////////////////////////////////////
164 // INTERNALS
165
166 pub struct Rcx<'a, 'tcx: 'a> {
167     fcx: &'a FnCtxt<'a, 'tcx>,
168
169     region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>,
170
171     // id of innermost fn body id
172     body_id: ast::NodeId,
173
174     // id of innermost fn or loop
175     repeating_scope: ast::NodeId,
176
177     // id of AST node being analyzed (the subject of the analysis).
178     subject: SubjectNode,
179
180 }
181
182 /// Returns the validity region of `def` -- that is, how long is `def` valid?
183 fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
184     let tcx = fcx.tcx();
185     match def {
186         def::DefLocal(node_id) | def::DefUpvar(node_id, _) => {
187             tcx.region_maps.var_region(node_id)
188         }
189         _ => {
190             tcx.sess.bug(&format!("unexpected def in region_of_def: {:?}",
191                                  def)[])
192         }
193     }
194 }
195
196 struct RepeatingScope(ast::NodeId);
197 pub enum SubjectNode { Subject(ast::NodeId), None }
198
199 impl<'a, 'tcx> Rcx<'a, 'tcx> {
200     pub fn new(fcx: &'a FnCtxt<'a, 'tcx>,
201                initial_repeating_scope: RepeatingScope,
202                initial_body_id: ast::NodeId,
203                subject: SubjectNode) -> Rcx<'a, 'tcx> {
204         let RepeatingScope(initial_repeating_scope) = initial_repeating_scope;
205         Rcx { fcx: fcx,
206               repeating_scope: initial_repeating_scope,
207               body_id: initial_body_id,
208               subject: subject,
209               region_bound_pairs: Vec::new()
210         }
211     }
212
213     pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
214         self.fcx.ccx.tcx
215     }
216
217     fn set_body_id(&mut self, body_id: ast::NodeId) -> ast::NodeId {
218         mem::replace(&mut self.body_id, body_id)
219     }
220
221     fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
222         mem::replace(&mut self.repeating_scope, scope)
223     }
224
225     /// Try to resolve the type for the given node, returning t_err if an error results.  Note that
226     /// we never care about the details of the error, the same error will be detected and reported
227     /// in the writeback phase.
228     ///
229     /// Note one important point: we do not attempt to resolve *region variables* here.  This is
230     /// because regionck is essentially adding constraints to those region variables and so may yet
231     /// influence how they are resolved.
232     ///
233     /// Consider this silly example:
234     ///
235     /// ```
236     /// fn borrow(x: &int) -> &int {x}
237     /// fn foo(x: @int) -> int {  // block: B
238     ///     let b = borrow(x);    // region: <R0>
239     ///     *b
240     /// }
241     /// ```
242     ///
243     /// Here, the region of `b` will be `<R0>`.  `<R0>` is constrainted to be some subregion of the
244     /// block B and some superregion of the call.  If we forced it now, we'd choose the smaller
245     /// region (the call).  But that would make the *b illegal.  Since we don't resolve, the type
246     /// of b will be `&<R0>.int` and then `*b` will require that `<R0>` be bigger than the let and
247     /// the `*b` expression, so we will effectively resolve `<R0>` to be the block B.
248     pub fn resolve_type(&self, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> {
249         self.fcx.infcx().resolve_type_vars_if_possible(&unresolved_ty)
250     }
251
252     /// Try to resolve the type for the given node.
253     fn resolve_node_type(&self, id: ast::NodeId) -> Ty<'tcx> {
254         let t = self.fcx.node_ty(id);
255         self.resolve_type(t)
256     }
257
258     fn resolve_method_type(&self, method_call: MethodCall) -> Option<Ty<'tcx>> {
259         let method_ty = self.fcx.inh.method_map.borrow()
260                             .get(&method_call).map(|method| method.ty);
261         method_ty.map(|method_ty| self.resolve_type(method_ty))
262     }
263
264     /// Try to resolve the type for the given node.
265     pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> Ty<'tcx> {
266         let ty_unadjusted = self.resolve_node_type(expr.id);
267         if ty::type_is_error(ty_unadjusted) {
268             ty_unadjusted
269         } else {
270             let tcx = self.fcx.tcx();
271             ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
272                           self.fcx.inh.adjustments.borrow().get(&expr.id),
273                           |method_call| self.resolve_method_type(method_call))
274         }
275     }
276
277     fn visit_fn_body(&mut self,
278                      id: ast::NodeId,
279                      fn_decl: &ast::FnDecl,
280                      body: &ast::Block,
281                      span: Span)
282     {
283         // When we enter a function, we can derive
284         debug!("visit_fn_body(id={})", id);
285
286         let fn_sig_map = self.fcx.inh.fn_sig_map.borrow();
287         let fn_sig = match fn_sig_map.get(&id) {
288             Some(f) => f,
289             None => {
290                 self.tcx().sess.bug(
291                     &format!("No fn-sig entry for id={}", id)[]);
292             }
293         };
294
295         let len = self.region_bound_pairs.len();
296         let old_body_id = self.set_body_id(body.id);
297         self.relate_free_regions(&fn_sig[], body.id, span);
298         link_fn_args(self, CodeExtent::from_node_id(body.id), &fn_decl.inputs[]);
299         self.visit_block(body);
300         self.visit_region_obligations(body.id);
301         self.region_bound_pairs.truncate(len);
302         self.set_body_id(old_body_id);
303     }
304
305     fn visit_region_obligations(&mut self, node_id: ast::NodeId)
306     {
307         debug!("visit_region_obligations: node_id={}", node_id);
308
309         // region checking can introduce new pending obligations
310         // which, when processed, might generate new region
311         // obligations. So make sure we process those.
312         vtable::select_all_fcx_obligations_or_error(self.fcx);
313
314         // Make a copy of the region obligations vec because we'll need
315         // to be able to borrow the fulfillment-cx below when projecting.
316         let region_obligations =
317             self.fcx.inh.fulfillment_cx.borrow()
318                                        .region_obligations(node_id)
319                                        .to_vec();
320
321         for r_o in &region_obligations {
322             debug!("visit_region_obligations: r_o={}",
323                    r_o.repr(self.tcx()));
324             let sup_type = self.resolve_type(r_o.sup_type);
325             let origin = infer::RelateParamBound(r_o.cause.span, sup_type);
326             type_must_outlive(self, origin, sup_type, r_o.sub_region);
327         }
328
329         // Processing the region obligations should not cause the list to grow further:
330         assert_eq!(region_obligations.len(),
331                    self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len());
332     }
333
334     /// This method populates the region map's `free_region_map`. It walks over the transformed
335     /// argument and return types for each function just before we check the body of that function,
336     /// looking for types where you have a borrowed pointer to other borrowed data (e.g., `&'a &'b
337     /// [uint]`.  We do not allow references to outlive the things they point at, so we can assume
338     /// that `'a <= 'b`. This holds for both the argument and return types, basically because, on
339     /// the caller side, the caller is responsible for checking that the type of every expression
340     /// (including the actual values for the arguments, as well as the return type of the fn call)
341     /// is well-formed.
342     ///
343     /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
344     fn relate_free_regions(&mut self,
345                            fn_sig_tys: &[Ty<'tcx>],
346                            body_id: ast::NodeId,
347                            span: Span) {
348         debug!("relate_free_regions >>");
349         let tcx = self.tcx();
350
351         for &ty in fn_sig_tys {
352             let ty = self.resolve_type(ty);
353             debug!("relate_free_regions(t={})", ty.repr(tcx));
354             let body_scope = CodeExtent::from_node_id(body_id);
355             let body_scope = ty::ReScope(body_scope);
356             let implications = implicator::implications(self.fcx.infcx(), self.fcx, body_id,
357                                                         ty, body_scope, span);
358             for implication in implications {
359                 debug!("implication: {}", implication.repr(tcx));
360                 match implication {
361                     implicator::Implication::RegionSubRegion(_,
362                                                              ty::ReFree(free_a),
363                                                              ty::ReFree(free_b)) => {
364                         tcx.region_maps.relate_free_regions(free_a, free_b);
365                     }
366                     implicator::Implication::RegionSubRegion(_,
367                                                              ty::ReFree(free_a),
368                                                              ty::ReInfer(ty::ReVar(vid_b))) => {
369                         self.fcx.inh.infcx.add_given(free_a, vid_b);
370                     }
371                     implicator::Implication::RegionSubRegion(..) => {
372                         // In principle, we could record (and take
373                         // advantage of) every relationship here, but
374                         // we are also free not to -- it simply means
375                         // strictly less that we can successfully type
376                         // check. (It may also be that we should
377                         // revise our inference system to be more
378                         // general and to make use of *every*
379                         // relationship that arises here, but
380                         // presently we do not.)
381                     }
382                     implicator::Implication::RegionSubGeneric(_, r_a, ref generic_b) => {
383                         debug!("RegionSubGeneric: {} <= {}",
384                                r_a.repr(tcx), generic_b.repr(tcx));
385
386                         self.region_bound_pairs.push((r_a, generic_b.clone()));
387                     }
388                     implicator::Implication::Predicate(..) => { }
389                 }
390             }
391         }
392
393         debug!("<< relate_free_regions");
394     }
395
396     fn resolve_regions_and_report_errors(&self) {
397         let subject_node_id = match self.subject {
398             Subject(s) => s,
399             SubjectNode::None => {
400                 self.tcx().sess.bug("cannot resolve_regions_and_report_errors \
401                                      without subject node");
402             }
403         };
404
405         self.fcx.infcx().resolve_regions_and_report_errors(subject_node_id);
406     }
407 }
408
409 impl<'a, 'tcx, 'v> Visitor<'v> for Rcx<'a, 'tcx> {
410     // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
411     // However, right now we run into an issue whereby some free
412     // regions are not properly related if they appear within the
413     // types of arguments that must be inferred. This could be
414     // addressed by deferring the construction of the region
415     // hierarchy, and in particular the relationships between free
416     // regions, until regionck, as described in #3238.
417
418     fn visit_fn(&mut self, _fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
419                 b: &'v ast::Block, span: Span, id: ast::NodeId) {
420         self.visit_fn_body(id, fd, b, span)
421     }
422
423     fn visit_item(&mut self, i: &ast::Item) { visit_item(self, i); }
424
425     fn visit_expr(&mut self, ex: &ast::Expr) { visit_expr(self, ex); }
426
427     //visit_pat: visit_pat, // (..) see above
428
429     fn visit_arm(&mut self, a: &ast::Arm) { visit_arm(self, a); }
430
431     fn visit_local(&mut self, l: &ast::Local) { visit_local(self, l); }
432
433     fn visit_block(&mut self, b: &ast::Block) { visit_block(self, b); }
434 }
435
436 fn visit_item(_rcx: &mut Rcx, _item: &ast::Item) {
437     // Ignore items
438 }
439
440 fn visit_block(rcx: &mut Rcx, b: &ast::Block) {
441     visit::walk_block(rcx, b);
442 }
443
444 fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
445     // see above
446     for p in &arm.pats {
447         constrain_bindings_in_pat(&**p, rcx);
448     }
449
450     visit::walk_arm(rcx, arm);
451 }
452
453 fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
454     // see above
455     constrain_bindings_in_pat(&*l.pat, rcx);
456     link_local(rcx, l);
457     visit::walk_local(rcx, l);
458 }
459
460 fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
461     let tcx = rcx.fcx.tcx();
462     debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
463     pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
464         // If we have a variable that contains region'd data, that
465         // data will be accessible from anywhere that the variable is
466         // accessed. We must be wary of loops like this:
467         //
468         //     // from src/test/compile-fail/borrowck-lend-flow.rs
469         //     let mut v = box 3, w = box 4;
470         //     let mut x = &mut w;
471         //     loop {
472         //         **x += 1;   // (2)
473         //         borrow(v);  //~ ERROR cannot borrow
474         //         x = &mut v; // (1)
475         //     }
476         //
477         // Typically, we try to determine the region of a borrow from
478         // those points where it is dereferenced. In this case, one
479         // might imagine that the lifetime of `x` need only be the
480         // body of the loop. But of course this is incorrect because
481         // the pointer that is created at point (1) is consumed at
482         // point (2), meaning that it must be live across the loop
483         // iteration. The easiest way to guarantee this is to require
484         // that the lifetime of any regions that appear in a
485         // variable's type enclose at least the variable's scope.
486
487         let var_region = tcx.region_maps.var_region(id);
488         type_of_node_must_outlive(
489             rcx, infer::BindingTypeIsNotValidAtDecl(span),
490             id, var_region);
491
492         let var_scope = tcx.region_maps.var_scope(id);
493         let typ = rcx.resolve_node_type(id);
494         dropck::check_safety_of_destructor_if_necessary(rcx, typ, span, var_scope);
495     })
496 }
497
498 fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
499     debug!("regionck::visit_expr(e={}, repeating_scope={})",
500            expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
501
502     // No matter what, the type of each expression must outlive the
503     // scope of that expression. This also guarantees basic WF.
504     let expr_ty = rcx.resolve_node_type(expr.id);
505
506     type_must_outlive(rcx, infer::ExprTypeIsNotInScope(expr_ty, expr.span),
507                       expr_ty, ty::ReScope(CodeExtent::from_node_id(expr.id)));
508
509     let method_call = MethodCall::expr(expr.id);
510     let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call);
511
512     // Check any autoderefs or autorefs that appear.
513     if let Some(adjustment) = rcx.fcx.inh.adjustments.borrow().get(&expr.id) {
514         debug!("adjustment={:?}", adjustment);
515         match *adjustment {
516             ty::AdjustDerefRef(ty::AutoDerefRef {autoderefs, autoref: ref opt_autoref}) => {
517                 let expr_ty = rcx.resolve_node_type(expr.id);
518                 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
519                 if let Some(ref autoref) = *opt_autoref {
520                     link_autoref(rcx, expr, autoderefs, autoref);
521
522                     // Require that the resulting region encompasses
523                     // the current node.
524                     //
525                     // FIXME(#6268) remove to support nested method calls
526                     type_of_node_must_outlive(
527                         rcx, infer::AutoBorrow(expr.span),
528                         expr.id, ty::ReScope(CodeExtent::from_node_id(expr.id)));
529                 }
530             }
531             /*
532             ty::AutoObject(_, ref bounds, _, _) => {
533                 // Determine if we are casting `expr` to a trait
534                 // instance. If so, we have to be sure that the type
535                 // of the source obeys the new region bound.
536                 let source_ty = rcx.resolve_node_type(expr.id);
537                 type_must_outlive(rcx, infer::RelateObjectBound(expr.span),
538                                   source_ty, bounds.region_bound);
539             }
540             */
541             _ => {}
542         }
543
544         // If necessary, constrain destructors in the unadjusted form of this
545         // expression.
546         let cmt_result = {
547             let mc = mc::MemCategorizationContext::new(rcx.fcx);
548             mc.cat_expr_unadjusted(expr)
549         };
550         match cmt_result {
551             Ok(head_cmt) => {
552                 check_safety_of_rvalue_destructor_if_necessary(rcx,
553                                                                head_cmt,
554                                                                expr.span);
555             }
556             Err(..) => {
557                 rcx.fcx.tcx().sess.span_note(expr.span,
558                                              "cat_expr_unadjusted Errd during dtor check");
559             }
560         }
561     }
562
563     // If necessary, constrain destructors in this expression. This will be
564     // the adjusted form if there is an adjustment.
565     let cmt_result = {
566         let mc = mc::MemCategorizationContext::new(rcx.fcx);
567         mc.cat_expr(expr)
568     };
569     match cmt_result {
570         Ok(head_cmt) => {
571             check_safety_of_rvalue_destructor_if_necessary(rcx, head_cmt, expr.span);
572         }
573         Err(..) => {
574             rcx.fcx.tcx().sess.span_note(expr.span,
575                                          "cat_expr Errd during dtor check");
576         }
577     }
578
579     match expr.node {
580         ast::ExprCall(ref callee, ref args) => {
581             if has_method_map {
582                 constrain_call(rcx, expr, Some(&**callee),
583                                args.iter().map(|e| &**e), false);
584             } else {
585                 constrain_callee(rcx, callee.id, expr, &**callee);
586                 constrain_call(rcx, expr, None,
587                                args.iter().map(|e| &**e), false);
588             }
589
590             visit::walk_expr(rcx, expr);
591         }
592
593         ast::ExprMethodCall(_, _, ref args) => {
594             constrain_call(rcx, expr, Some(&*args[0]),
595                            args[1..].iter().map(|e| &**e), false);
596
597             visit::walk_expr(rcx, expr);
598         }
599
600         ast::ExprAssignOp(_, ref lhs, ref rhs) => {
601             if has_method_map {
602                 constrain_call(rcx, expr, Some(&**lhs),
603                                Some(&**rhs).into_iter(), true);
604             }
605
606             visit::walk_expr(rcx, expr);
607         }
608
609         ast::ExprIndex(ref lhs, ref rhs) if has_method_map => {
610             constrain_call(rcx, expr, Some(&**lhs),
611                            Some(&**rhs).into_iter(), true);
612
613             visit::walk_expr(rcx, expr);
614         },
615
616         ast::ExprBinary(op, ref lhs, ref rhs) if has_method_map => {
617             let implicitly_ref_args = !ast_util::is_by_value_binop(op.node);
618
619             // As `expr_method_call`, but the call is via an
620             // overloaded op.  Note that we (sadly) currently use an
621             // implicit "by ref" sort of passing style here.  This
622             // should be converted to an adjustment!
623             constrain_call(rcx, expr, Some(&**lhs),
624                            Some(&**rhs).into_iter(), implicitly_ref_args);
625
626             visit::walk_expr(rcx, expr);
627         }
628
629         ast::ExprUnary(op, ref lhs) if has_method_map => {
630             let implicitly_ref_args = !ast_util::is_by_value_unop(op);
631
632             // As above.
633             constrain_call(rcx, expr, Some(&**lhs),
634                            None::<ast::Expr>.iter(), implicitly_ref_args);
635
636             visit::walk_expr(rcx, expr);
637         }
638
639         ast::ExprUnary(ast::UnDeref, ref base) => {
640             // For *a, the lifetime of a must enclose the deref
641             let method_call = MethodCall::expr(expr.id);
642             let base_ty = match rcx.fcx.inh.method_map.borrow().get(&method_call) {
643                 Some(method) => {
644                     constrain_call(rcx, expr, Some(&**base),
645                                    None::<ast::Expr>.iter(), true);
646                     let fn_ret = // late-bound regions in overloaded method calls are instantiated
647                         ty::no_late_bound_regions(rcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap();
648                     fn_ret.unwrap()
649                 }
650                 None => rcx.resolve_node_type(base.id)
651             };
652             if let ty::ty_rptr(r_ptr, _) = base_ty.sty {
653                 mk_subregion_due_to_dereference(
654                     rcx, expr.span, ty::ReScope(CodeExtent::from_node_id(expr.id)), *r_ptr);
655             }
656
657             visit::walk_expr(rcx, expr);
658         }
659
660         ast::ExprIndex(ref vec_expr, _) => {
661             // For a[b], the lifetime of a must enclose the deref
662             let vec_type = rcx.resolve_expr_type_adjusted(&**vec_expr);
663             constrain_index(rcx, expr, vec_type);
664
665             visit::walk_expr(rcx, expr);
666         }
667
668         ast::ExprCast(ref source, _) => {
669             // Determine if we are casting `source` to a trait
670             // instance.  If so, we have to be sure that the type of
671             // the source obeys the trait's region bound.
672             constrain_cast(rcx, expr, &**source);
673             visit::walk_expr(rcx, expr);
674         }
675
676         ast::ExprAddrOf(m, ref base) => {
677             link_addr_of(rcx, expr, m, &**base);
678
679             // Require that when you write a `&expr` expression, the
680             // resulting pointer has a lifetime that encompasses the
681             // `&expr` expression itself. Note that we constraining
682             // the type of the node expr.id here *before applying
683             // adjustments*.
684             //
685             // FIXME(#6268) nested method calls requires that this rule change
686             let ty0 = rcx.resolve_node_type(expr.id);
687             type_must_outlive(rcx, infer::AddrOf(expr.span),
688                               ty0, ty::ReScope(CodeExtent::from_node_id(expr.id)));
689             visit::walk_expr(rcx, expr);
690         }
691
692         ast::ExprMatch(ref discr, ref arms, _) => {
693             link_match(rcx, &**discr, &arms[]);
694
695             visit::walk_expr(rcx, expr);
696         }
697
698         ast::ExprClosure(_, _, ref body) => {
699             check_expr_fn_block(rcx, expr, &**body);
700         }
701
702         ast::ExprLoop(ref body, _) => {
703             let repeating_scope = rcx.set_repeating_scope(body.id);
704             visit::walk_expr(rcx, expr);
705             rcx.set_repeating_scope(repeating_scope);
706         }
707
708         ast::ExprWhile(ref cond, ref body, _) => {
709             let repeating_scope = rcx.set_repeating_scope(cond.id);
710             rcx.visit_expr(&**cond);
711
712             rcx.set_repeating_scope(body.id);
713             rcx.visit_block(&**body);
714
715             rcx.set_repeating_scope(repeating_scope);
716         }
717
718         _ => {
719             visit::walk_expr(rcx, expr);
720         }
721     }
722 }
723
724 fn constrain_cast(rcx: &mut Rcx,
725                   cast_expr: &ast::Expr,
726                   source_expr: &ast::Expr)
727 {
728     debug!("constrain_cast(cast_expr={}, source_expr={})",
729            cast_expr.repr(rcx.tcx()),
730            source_expr.repr(rcx.tcx()));
731
732     let source_ty = rcx.resolve_node_type(source_expr.id);
733     let target_ty = rcx.resolve_node_type(cast_expr.id);
734
735     walk_cast(rcx, cast_expr, source_ty, target_ty);
736
737     fn walk_cast<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
738                            cast_expr: &ast::Expr,
739                            from_ty: Ty<'tcx>,
740                            to_ty: Ty<'tcx>) {
741         debug!("walk_cast(from_ty={}, to_ty={})",
742                from_ty.repr(rcx.tcx()),
743                to_ty.repr(rcx.tcx()));
744         match (&from_ty.sty, &to_ty.sty) {
745             /*From:*/ (&ty::ty_rptr(from_r, ref from_mt),
746             /*To:  */  &ty::ty_rptr(to_r, ref to_mt)) => {
747                 // Target cannot outlive source, naturally.
748                 rcx.fcx.mk_subr(infer::Reborrow(cast_expr.span), *to_r, *from_r);
749                 walk_cast(rcx, cast_expr, from_mt.ty, to_mt.ty);
750             }
751
752             /*From:*/ (_,
753             /*To:  */  &ty::ty_trait(box ty::TyTrait { ref bounds, .. })) => {
754                 // When T is existentially quantified as a trait
755                 // `Foo+'to`, it must outlive the region bound `'to`.
756                 type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
757                                   from_ty, bounds.region_bound);
758             }
759
760             /*From:*/ (&ty::ty_uniq(from_referent_ty),
761             /*To:  */  &ty::ty_uniq(to_referent_ty)) => {
762                 walk_cast(rcx, cast_expr, from_referent_ty, to_referent_ty);
763             }
764
765             _ => { }
766         }
767     }
768 }
769
770 fn check_expr_fn_block(rcx: &mut Rcx,
771                        expr: &ast::Expr,
772                        body: &ast::Block) {
773     let tcx = rcx.fcx.tcx();
774     let function_type = rcx.resolve_node_type(expr.id);
775
776     match function_type.sty {
777         ty::ty_closure(_, region, _) => {
778             ty::with_freevars(tcx, expr.id, |freevars| {
779                 constrain_captured_variables(rcx, *region, expr, freevars);
780             })
781         }
782         _ => { }
783     }
784
785     let repeating_scope = rcx.set_repeating_scope(body.id);
786     visit::walk_expr(rcx, expr);
787     rcx.set_repeating_scope(repeating_scope);
788
789     match function_type.sty {
790         ty::ty_closure(_, region, _) => {
791             ty::with_freevars(tcx, expr.id, |freevars| {
792                 let bounds = ty::region_existential_bound(*region);
793                 ensure_free_variable_types_outlive_closure_bound(rcx, &bounds, expr, freevars);
794             })
795         }
796         _ => {}
797     }
798
799     /// Make sure that the type of all free variables referenced inside a closure/proc outlive the
800     /// closure/proc's lifetime bound. This is just a special case of the usual rules about closed
801     /// over values outliving the object's lifetime bound.
802     fn ensure_free_variable_types_outlive_closure_bound(
803         rcx: &mut Rcx,
804         bounds: &ty::ExistentialBounds,
805         expr: &ast::Expr,
806         freevars: &[ty::Freevar])
807     {
808         let tcx = rcx.fcx.ccx.tcx;
809
810         debug!("ensure_free_variable_types_outlive_closure_bound({}, {})",
811                bounds.region_bound.repr(tcx), expr.repr(tcx));
812
813         for freevar in freevars {
814             let var_node_id = {
815                 let def_id = freevar.def.def_id();
816                 assert!(def_id.krate == ast::LOCAL_CRATE);
817                 def_id.node
818             };
819
820             // Compute the type of the field in the environment that
821             // represents `var_node_id`.  For a by-value closure, this
822             // will be the same as the type of the variable.  For a
823             // by-reference closure, this will be `&T` where `T` is
824             // the type of the variable.
825             let raw_var_ty = rcx.resolve_node_type(var_node_id);
826             let upvar_id = ty::UpvarId { var_id: var_node_id,
827                                          closure_expr_id: expr.id };
828             let var_ty = match rcx.fcx.inh.upvar_capture_map.borrow()[upvar_id] {
829                 ty::UpvarCapture::ByRef(ref upvar_borrow) => {
830                     ty::mk_rptr(rcx.tcx(),
831                                 rcx.tcx().mk_region(upvar_borrow.region),
832                                 ty::mt { mutbl: upvar_borrow.kind.to_mutbl_lossy(),
833                                          ty: raw_var_ty })
834                 }
835                 ty::UpvarCapture::ByValue => raw_var_ty,
836             };
837
838             // Check that the type meets the criteria of the existential bounds:
839             for builtin_bound in &bounds.builtin_bounds {
840                 let code = traits::ClosureCapture(var_node_id, expr.span, builtin_bound);
841                 let cause = traits::ObligationCause::new(freevar.span, rcx.fcx.body_id, code);
842                 rcx.fcx.register_builtin_bound(var_ty, builtin_bound, cause);
843             }
844
845             type_must_outlive(
846                 rcx, infer::FreeVariable(expr.span, var_node_id),
847                 var_ty, bounds.region_bound);
848         }
849     }
850
851     /// Make sure that all free variables referenced inside the closure outlive the closure's
852     /// lifetime bound. Also, create an entry in the upvar_borrows map with a region.
853     fn constrain_captured_variables(
854         rcx: &mut Rcx,
855         region_bound: ty::Region,
856         expr: &ast::Expr,
857         freevars: &[ty::Freevar])
858     {
859         let tcx = rcx.fcx.ccx.tcx;
860         debug!("constrain_captured_variables({}, {})",
861                region_bound.repr(tcx), expr.repr(tcx));
862         for freevar in freevars {
863             debug!("constrain_captured_variables: freevar.def={:?}", freevar.def);
864
865             // Identify the variable being closed over and its node-id.
866             let def = freevar.def;
867             let var_node_id = {
868                 let def_id = def.def_id();
869                 assert!(def_id.krate == ast::LOCAL_CRATE);
870                 def_id.node
871             };
872             let upvar_id = ty::UpvarId { var_id: var_node_id,
873                                          closure_expr_id: expr.id };
874
875             match rcx.fcx.inh.upvar_capture_map.borrow()[upvar_id] {
876                 ty::UpvarCapture::ByValue => { }
877                 ty::UpvarCapture::ByRef(upvar_borrow) => {
878                     rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id),
879                                     region_bound, upvar_borrow.region);
880
881                     // Guarantee that the closure does not outlive the variable itself.
882                     let enclosing_region = region_of_def(rcx.fcx, def);
883                     debug!("constrain_captured_variables: enclosing_region = {}",
884                            enclosing_region.repr(tcx));
885                     rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id),
886                                     region_bound, enclosing_region);
887                 }
888             }
889         }
890     }
891 }
892
893 fn constrain_callee(rcx: &mut Rcx,
894                     callee_id: ast::NodeId,
895                     _call_expr: &ast::Expr,
896                     _callee_expr: &ast::Expr) {
897     let callee_ty = rcx.resolve_node_type(callee_id);
898     match callee_ty.sty {
899         ty::ty_bare_fn(..) => { }
900         _ => {
901             // this should not happen, but it does if the program is
902             // erroneous
903             //
904             // tcx.sess.span_bug(
905             //     callee_expr.span,
906             //     format!("Calling non-function: {}", callee_ty.repr(tcx)));
907         }
908     }
909 }
910
911 fn constrain_call<'a, I: Iterator<Item=&'a ast::Expr>>(rcx: &mut Rcx,
912                                                        call_expr: &ast::Expr,
913                                                        receiver: Option<&ast::Expr>,
914                                                        arg_exprs: I,
915                                                        implicitly_ref_args: bool) {
916     //! Invoked on every call site (i.e., normal calls, method calls,
917     //! and overloaded operators). Constrains the regions which appear
918     //! in the type of the function. Also constrains the regions that
919     //! appear in the arguments appropriately.
920
921     let tcx = rcx.fcx.tcx();
922     debug!("constrain_call(call_expr={}, \
923             receiver={}, \
924             implicitly_ref_args={})",
925             call_expr.repr(tcx),
926             receiver.repr(tcx),
927             implicitly_ref_args);
928
929     // `callee_region` is the scope representing the time in which the
930     // call occurs.
931     //
932     // FIXME(#6268) to support nested method calls, should be callee_id
933     let callee_scope = CodeExtent::from_node_id(call_expr.id);
934     let callee_region = ty::ReScope(callee_scope);
935
936     debug!("callee_region={}", callee_region.repr(tcx));
937
938     for arg_expr in arg_exprs {
939         debug!("Argument: {}", arg_expr.repr(tcx));
940
941         // ensure that any regions appearing in the argument type are
942         // valid for at least the lifetime of the function:
943         type_of_node_must_outlive(
944             rcx, infer::CallArg(arg_expr.span),
945             arg_expr.id, callee_region);
946
947         // unfortunately, there are two means of taking implicit
948         // references, and we need to propagate constraints as a
949         // result. modes are going away and the "DerefArgs" code
950         // should be ported to use adjustments
951         if implicitly_ref_args {
952             link_by_ref(rcx, arg_expr, callee_scope);
953         }
954     }
955
956     // as loop above, but for receiver
957     if let Some(r) = receiver {
958         debug!("receiver: {}", r.repr(tcx));
959         type_of_node_must_outlive(
960             rcx, infer::CallRcvr(r.span),
961             r.id, callee_region);
962         if implicitly_ref_args {
963             link_by_ref(rcx, &*r, callee_scope);
964         }
965     }
966 }
967
968 /// Invoked on any auto-dereference that occurs. Checks that if this is a region pointer being
969 /// dereferenced, the lifetime of the pointer includes the deref expr.
970 fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
971                                   deref_expr: &ast::Expr,
972                                   derefs: uint,
973                                   mut derefd_ty: Ty<'tcx>)
974 {
975     debug!("constrain_autoderefs(deref_expr={}, derefs={}, derefd_ty={})",
976            deref_expr.repr(rcx.tcx()),
977            derefs,
978            derefd_ty.repr(rcx.tcx()));
979
980     let r_deref_expr = ty::ReScope(CodeExtent::from_node_id(deref_expr.id));
981     for i in 0..derefs {
982         let method_call = MethodCall::autoderef(deref_expr.id, i);
983         debug!("constrain_autoderefs: method_call={:?} (of {:?} total)", method_call, derefs);
984
985         derefd_ty = match rcx.fcx.inh.method_map.borrow().get(&method_call) {
986             Some(method) => {
987                 debug!("constrain_autoderefs: #{} is overloaded, method={}",
988                        i, method.repr(rcx.tcx()));
989
990                 // Treat overloaded autoderefs as if an AutoRef adjustment
991                 // was applied on the base type, as that is always the case.
992                 let fn_sig = ty::ty_fn_sig(method.ty);
993                 let fn_sig = // late-bound regions should have been instantiated
994                     ty::no_late_bound_regions(rcx.tcx(), fn_sig).unwrap();
995                 let self_ty = fn_sig.inputs[0];
996                 let (m, r) = match self_ty.sty {
997                     ty::ty_rptr(r, ref m) => (m.mutbl, r),
998                     _ => {
999                         rcx.tcx().sess.span_bug(
1000                             deref_expr.span,
1001                             &format!("bad overloaded deref type {}",
1002                                      method.ty.repr(rcx.tcx()))[])
1003                     }
1004                 };
1005
1006                 debug!("constrain_autoderefs: receiver r={:?} m={:?}",
1007                        r.repr(rcx.tcx()), m);
1008
1009                 {
1010                     let mc = mc::MemCategorizationContext::new(rcx.fcx);
1011                     let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
1012                     debug!("constrain_autoderefs: self_cmt={:?}",
1013                            self_cmt.repr(rcx.tcx()));
1014                     link_region(rcx, deref_expr.span, *r,
1015                                 ty::BorrowKind::from_mutbl(m), self_cmt);
1016                 }
1017
1018                 // Specialized version of constrain_call.
1019                 type_must_outlive(rcx, infer::CallRcvr(deref_expr.span),
1020                                   self_ty, r_deref_expr);
1021                 match fn_sig.output {
1022                     ty::FnConverging(return_type) => {
1023                         type_must_outlive(rcx, infer::CallReturn(deref_expr.span),
1024                                           return_type, r_deref_expr);
1025                         return_type
1026                     }
1027                     ty::FnDiverging => unreachable!()
1028                 }
1029             }
1030             None => derefd_ty
1031         };
1032
1033         if let ty::ty_rptr(r_ptr, _) =  derefd_ty.sty {
1034             mk_subregion_due_to_dereference(rcx, deref_expr.span,
1035                                             r_deref_expr, *r_ptr);
1036         }
1037
1038         match ty::deref(derefd_ty, true) {
1039             Some(mt) => derefd_ty = mt.ty,
1040             /* if this type can't be dereferenced, then there's already an error
1041                in the session saying so. Just bail out for now */
1042             None => break
1043         }
1044     }
1045 }
1046
1047 pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
1048                                        deref_span: Span,
1049                                        minimum_lifetime: ty::Region,
1050                                        maximum_lifetime: ty::Region) {
1051     rcx.fcx.mk_subr(infer::DerefPointer(deref_span),
1052                     minimum_lifetime, maximum_lifetime)
1053 }
1054
1055 fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
1056                                                             cmt: mc::cmt<'tcx>,
1057                                                             span: Span) {
1058     match cmt.cat {
1059         mc::cat_rvalue(region) => {
1060             match region {
1061                 ty::ReScope(rvalue_scope) => {
1062                     let typ = rcx.resolve_type(cmt.ty);
1063                     dropck::check_safety_of_destructor_if_necessary(rcx,
1064                                                                     typ,
1065                                                                     span,
1066                                                                     rvalue_scope);
1067                 }
1068                 ty::ReStatic => {}
1069                 region => {
1070                     rcx.tcx()
1071                        .sess
1072                        .span_bug(span,
1073                                  format!("unexpected rvalue region in rvalue \
1074                                           destructor safety checking: `{}`",
1075                                          region.repr(rcx.tcx())).as_slice());
1076                 }
1077             }
1078         }
1079         _ => {}
1080     }
1081 }
1082
1083 /// Invoked on any index expression that occurs. Checks that if this is a slice being indexed, the
1084 /// lifetime of the pointer includes the deref expr.
1085 fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
1086                              index_expr: &ast::Expr,
1087                              indexed_ty: Ty<'tcx>)
1088 {
1089     debug!("constrain_index(index_expr=?, indexed_ty={}",
1090            rcx.fcx.infcx().ty_to_string(indexed_ty));
1091
1092     let r_index_expr = ty::ReScope(CodeExtent::from_node_id(index_expr.id));
1093     if let ty::ty_rptr(r_ptr, mt) = indexed_ty.sty {
1094         match mt.ty.sty {
1095             ty::ty_vec(_, None) | ty::ty_str => {
1096                 rcx.fcx.mk_subr(infer::IndexSlice(index_expr.span),
1097                                 r_index_expr, *r_ptr);
1098             }
1099             _ => {}
1100         }
1101     }
1102 }
1103
1104 /// Guarantees that any lifetimes which appear in the type of the node `id` (after applying
1105 /// adjustments) are valid for at least `minimum_lifetime`
1106 fn type_of_node_must_outlive<'a, 'tcx>(
1107     rcx: &mut Rcx<'a, 'tcx>,
1108     origin: infer::SubregionOrigin<'tcx>,
1109     id: ast::NodeId,
1110     minimum_lifetime: ty::Region)
1111 {
1112     let tcx = rcx.fcx.tcx();
1113
1114     // Try to resolve the type.  If we encounter an error, then typeck
1115     // is going to fail anyway, so just stop here and let typeck
1116     // report errors later on in the writeback phase.
1117     let ty0 = rcx.resolve_node_type(id);
1118     let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
1119                            rcx.fcx.inh.adjustments.borrow().get(&id),
1120                            |method_call| rcx.resolve_method_type(method_call));
1121     debug!("constrain_regions_in_type_of_node(\
1122             ty={}, ty0={}, id={}, minimum_lifetime={:?})",
1123            ty_to_string(tcx, ty), ty_to_string(tcx, ty0),
1124            id, minimum_lifetime);
1125     type_must_outlive(rcx, origin, ty, minimum_lifetime);
1126 }
1127
1128 /// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the
1129 /// resulting pointer is linked to the lifetime of its guarantor (if any).
1130 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
1131                 mutability: ast::Mutability, base: &ast::Expr) {
1132     debug!("link_addr_of(expr={}, base={})", expr.repr(rcx.tcx()), base.repr(rcx.tcx()));
1133
1134     let cmt = {
1135         let mc = mc::MemCategorizationContext::new(rcx.fcx);
1136         ignore_err!(mc.cat_expr(base))
1137     };
1138
1139     debug!("link_addr_of: cmt={}", cmt.repr(rcx.tcx()));
1140
1141     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
1142 }
1143
1144 /// Computes the guarantors for any ref bindings in a `let` and
1145 /// then ensures that the lifetime of the resulting pointer is
1146 /// linked to the lifetime of the initialization expression.
1147 fn link_local(rcx: &Rcx, local: &ast::Local) {
1148     debug!("regionck::for_local()");
1149     let init_expr = match local.init {
1150         None => { return; }
1151         Some(ref expr) => &**expr,
1152     };
1153     let mc = mc::MemCategorizationContext::new(rcx.fcx);
1154     let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
1155     link_pattern(rcx, mc, discr_cmt, &*local.pat);
1156 }
1157
1158 /// Computes the guarantors for any ref bindings in a match and
1159 /// then ensures that the lifetime of the resulting pointer is
1160 /// linked to the lifetime of its guarantor (if any).
1161 fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
1162     debug!("regionck::for_match()");
1163     let mc = mc::MemCategorizationContext::new(rcx.fcx);
1164     let discr_cmt = ignore_err!(mc.cat_expr(discr));
1165     debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
1166     for arm in arms {
1167         for root_pat in &arm.pats {
1168             link_pattern(rcx, mc, discr_cmt.clone(), &**root_pat);
1169         }
1170     }
1171 }
1172
1173 /// Computes the guarantors for any ref bindings in a match and
1174 /// then ensures that the lifetime of the resulting pointer is
1175 /// linked to the lifetime of its guarantor (if any).
1176 fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) {
1177     debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
1178     let mc = mc::MemCategorizationContext::new(rcx.fcx);
1179     for arg in args {
1180         let arg_ty = rcx.fcx.node_ty(arg.id);
1181         let re_scope = ty::ReScope(body_scope);
1182         let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty);
1183         debug!("arg_ty={} arg_cmt={}",
1184                arg_ty.repr(rcx.tcx()),
1185                arg_cmt.repr(rcx.tcx()));
1186         link_pattern(rcx, mc, arg_cmt, &*arg.pat);
1187     }
1188 }
1189
1190 /// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if
1191 /// needed.
1192 fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
1193                           mc: mc::MemCategorizationContext<FnCtxt<'a, 'tcx>>,
1194                           discr_cmt: mc::cmt<'tcx>,
1195                           root_pat: &ast::Pat) {
1196     debug!("link_pattern(discr_cmt={}, root_pat={})",
1197            discr_cmt.repr(rcx.tcx()),
1198            root_pat.repr(rcx.tcx()));
1199     let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
1200             match sub_pat.node {
1201                 // `ref x` pattern
1202                 ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
1203                     link_region_from_node_type(
1204                         rcx, sub_pat.span, sub_pat.id,
1205                         mutbl, sub_cmt);
1206                 }
1207
1208                 // `[_, ..slice, _]` pattern
1209                 ast::PatVec(_, Some(ref slice_pat), _) => {
1210                     match mc.cat_slice_pattern(sub_cmt, &**slice_pat) {
1211                         Ok((slice_cmt, slice_mutbl, slice_r)) => {
1212                             link_region(rcx, sub_pat.span, slice_r,
1213                                         ty::BorrowKind::from_mutbl(slice_mutbl),
1214                                         slice_cmt);
1215                         }
1216                         Err(()) => {}
1217                     }
1218                 }
1219                 _ => {}
1220             }
1221         });
1222 }
1223
1224 /// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being
1225 /// autoref'd.
1226 fn link_autoref(rcx: &Rcx,
1227                 expr: &ast::Expr,
1228                 autoderefs: uint,
1229                 autoref: &ty::AutoRef) {
1230
1231     debug!("link_autoref(autoref={:?})", autoref);
1232     let mc = mc::MemCategorizationContext::new(rcx.fcx);
1233     let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
1234     debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
1235
1236     match *autoref {
1237         ty::AutoPtr(r, m, _) => {
1238             link_region(rcx, expr.span, r,
1239                 ty::BorrowKind::from_mutbl(m), expr_cmt);
1240         }
1241
1242         ty::AutoUnsafe(..) | ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) => {}
1243     }
1244 }
1245
1246 /// Computes the guarantor for cases where the `expr` is being passed by implicit reference and
1247 /// must outlive `callee_scope`.
1248 fn link_by_ref(rcx: &Rcx,
1249                expr: &ast::Expr,
1250                callee_scope: CodeExtent) {
1251     let tcx = rcx.tcx();
1252     debug!("link_by_ref(expr={}, callee_scope={:?})",
1253            expr.repr(tcx), callee_scope);
1254     let mc = mc::MemCategorizationContext::new(rcx.fcx);
1255     let expr_cmt = ignore_err!(mc.cat_expr(expr));
1256     let borrow_region = ty::ReScope(callee_scope);
1257     link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
1258 }
1259
1260 /// Like `link_region()`, except that the region is extracted from the type of `id`, which must be
1261 /// some reference (`&T`, `&str`, etc).
1262 fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
1263                                         span: Span,
1264                                         id: ast::NodeId,
1265                                         mutbl: ast::Mutability,
1266                                         cmt_borrowed: mc::cmt<'tcx>) {
1267     debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={})",
1268            id, mutbl, cmt_borrowed.repr(rcx.tcx()));
1269
1270     let rptr_ty = rcx.resolve_node_type(id);
1271     if !ty::type_is_error(rptr_ty) {
1272         let tcx = rcx.fcx.ccx.tcx;
1273         debug!("rptr_ty={}", ty_to_string(tcx, rptr_ty));
1274         let r = ty::ty_region(tcx, span, rptr_ty);
1275         link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
1276                     cmt_borrowed);
1277     }
1278 }
1279
1280 /// Informs the inference engine that `borrow_cmt` is being borrowed with kind `borrow_kind` and
1281 /// lifetime `borrow_region`. In order to ensure borrowck is satisfied, this may create constraints
1282 /// between regions, as explained in `link_reborrowed_region()`.
1283 fn link_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
1284                          span: Span,
1285                          borrow_region: ty::Region,
1286                          borrow_kind: ty::BorrowKind,
1287                          borrow_cmt: mc::cmt<'tcx>) {
1288     let mut borrow_cmt = borrow_cmt;
1289     let mut borrow_kind = borrow_kind;
1290
1291     loop {
1292         debug!("link_region(borrow_region={}, borrow_kind={}, borrow_cmt={})",
1293                borrow_region.repr(rcx.tcx()),
1294                borrow_kind.repr(rcx.tcx()),
1295                borrow_cmt.repr(rcx.tcx()));
1296         match borrow_cmt.cat.clone() {
1297             mc::cat_deref(ref_cmt, _,
1298                           mc::Implicit(ref_kind, ref_region)) |
1299             mc::cat_deref(ref_cmt, _,
1300                           mc::BorrowedPtr(ref_kind, ref_region)) => {
1301                 match link_reborrowed_region(rcx, span,
1302                                              borrow_region, borrow_kind,
1303                                              ref_cmt, ref_region, ref_kind,
1304                                              borrow_cmt.note) {
1305                     Some((c, k)) => {
1306                         borrow_cmt = c;
1307                         borrow_kind = k;
1308                     }
1309                     None => {
1310                         return;
1311                     }
1312                 }
1313             }
1314
1315             mc::cat_downcast(cmt_base, _) |
1316             mc::cat_deref(cmt_base, _, mc::Unique) |
1317             mc::cat_interior(cmt_base, _) => {
1318                 // Borrowing interior or owned data requires the base
1319                 // to be valid and borrowable in the same fashion.
1320                 borrow_cmt = cmt_base;
1321                 borrow_kind = borrow_kind;
1322             }
1323
1324             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1325             mc::cat_static_item |
1326             mc::cat_upvar(..) |
1327             mc::cat_local(..) |
1328             mc::cat_rvalue(..) => {
1329                 // These are all "base cases" with independent lifetimes
1330                 // that are not subject to inference
1331                 return;
1332             }
1333         }
1334     }
1335 }
1336
1337 /// This is the most complicated case: the path being borrowed is
1338 /// itself the referent of a borrowed pointer. Let me give an
1339 /// example fragment of code to make clear(er) the situation:
1340 ///
1341 ///    let r: &'a mut T = ...;  // the original reference "r" has lifetime 'a
1342 ///    ...
1343 ///    &'z *r                   // the reborrow has lifetime 'z
1344 ///
1345 /// Now, in this case, our primary job is to add the inference
1346 /// constraint that `'z <= 'a`. Given this setup, let's clarify the
1347 /// parameters in (roughly) terms of the example:
1348 ///
1349 ///     A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T`
1350 ///     borrow_region   ^~                 ref_region    ^~
1351 ///     borrow_kind        ^~               ref_kind        ^~
1352 ///     ref_cmt                 ^
1353 ///
1354 /// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc).
1355 ///
1356 /// Unfortunately, there are some complications beyond the simple
1357 /// scenario I just painted:
1358 ///
1359 /// 1. The reference `r` might in fact be a "by-ref" upvar. In that
1360 ///    case, we have two jobs. First, we are inferring whether this reference
1361 ///    should be an `&T`, `&mut T`, or `&uniq T` reference, and we must
1362 ///    adjust that based on this borrow (e.g., if this is an `&mut` borrow,
1363 ///    then `r` must be an `&mut` reference). Second, whenever we link
1364 ///    two regions (here, `'z <= 'a`), we supply a *cause*, and in this
1365 ///    case we adjust the cause to indicate that the reference being
1366 ///    "reborrowed" is itself an upvar. This provides a nicer error message
1367 ///    should something go wrong.
1368 ///
1369 /// 2. There may in fact be more levels of reborrowing. In the
1370 ///    example, I said the borrow was like `&'z *r`, but it might
1371 ///    in fact be a borrow like `&'z **q` where `q` has type `&'a
1372 ///    &'b mut T`. In that case, we want to ensure that `'z <= 'a`
1373 ///    and `'z <= 'b`. This is explained more below.
1374 ///
1375 /// The return value of this function indicates whether we need to
1376 /// recurse and process `ref_cmt` (see case 2 above).
1377 fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
1378                                     span: Span,
1379                                     borrow_region: ty::Region,
1380                                     borrow_kind: ty::BorrowKind,
1381                                     ref_cmt: mc::cmt<'tcx>,
1382                                     ref_region: ty::Region,
1383                                     mut ref_kind: ty::BorrowKind,
1384                                     note: mc::Note)
1385                                     -> Option<(mc::cmt<'tcx>, ty::BorrowKind)>
1386 {
1387     // Possible upvar ID we may need later to create an entry in the
1388     // maybe link map.
1389
1390     // Detect by-ref upvar `x`:
1391     let cause = match note {
1392         mc::NoteUpvarRef(ref upvar_id) => {
1393             let upvar_capture_map = rcx.fcx.inh.upvar_capture_map.borrow_mut();
1394             match upvar_capture_map.get(upvar_id) {
1395                 Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => {
1396                     // The mutability of the upvar may have been modified
1397                     // by the above adjustment, so update our local variable.
1398                     ref_kind = upvar_borrow.kind;
1399
1400                     infer::ReborrowUpvar(span, *upvar_id)
1401                 }
1402                 _ => {
1403                     rcx.tcx().sess.span_bug(
1404                         span,
1405                         &format!("Illegal upvar id: {}",
1406                                 upvar_id.repr(rcx.tcx()))[]);
1407                 }
1408             }
1409         }
1410         mc::NoteClosureEnv(ref upvar_id) => {
1411             // We don't have any mutability changes to propagate, but
1412             // we do want to note that an upvar reborrow caused this
1413             // link
1414             infer::ReborrowUpvar(span, *upvar_id)
1415         }
1416         _ => {
1417             infer::Reborrow(span)
1418         }
1419     };
1420
1421     debug!("link_reborrowed_region: {} <= {}",
1422            borrow_region.repr(rcx.tcx()),
1423            ref_region.repr(rcx.tcx()));
1424     rcx.fcx.mk_subr(cause, borrow_region, ref_region);
1425
1426     // If we end up needing to recurse and establish a region link
1427     // with `ref_cmt`, calculate what borrow kind we will end up
1428     // needing. This will be used below.
1429     //
1430     // One interesting twist is that we can weaken the borrow kind
1431     // when we recurse: to reborrow an `&mut` referent as mutable,
1432     // borrowck requires a unique path to the `&mut` reference but not
1433     // necessarily a *mutable* path.
1434     let new_borrow_kind = match borrow_kind {
1435         ty::ImmBorrow =>
1436             ty::ImmBorrow,
1437         ty::MutBorrow | ty::UniqueImmBorrow =>
1438             ty::UniqueImmBorrow
1439     };
1440
1441     // Decide whether we need to recurse and link any regions within
1442     // the `ref_cmt`. This is concerned for the case where the value
1443     // being reborrowed is in fact a borrowed pointer found within
1444     // another borrowed pointer. For example:
1445     //
1446     //    let p: &'b &'a mut T = ...;
1447     //    ...
1448     //    &'z **p
1449     //
1450     // What makes this case particularly tricky is that, if the data
1451     // being borrowed is a `&mut` or `&uniq` borrow, borrowck requires
1452     // not only that `'z <= 'a`, (as before) but also `'z <= 'b`
1453     // (otherwise the user might mutate through the `&mut T` reference
1454     // after `'b` expires and invalidate the borrow we are looking at
1455     // now).
1456     //
1457     // So let's re-examine our parameters in light of this more
1458     // complicated (possible) scenario:
1459     //
1460     //     A borrow of: `& 'z bk * * p` where `p` has type `&'b bk & 'a bk T`
1461     //     borrow_region   ^~                 ref_region             ^~
1462     //     borrow_kind        ^~               ref_kind                 ^~
1463     //     ref_cmt                 ^~~
1464     //
1465     // (Note that since we have not examined `ref_cmt.cat`, we don't
1466     // know whether this scenario has occurred; but I wanted to show
1467     // how all the types get adjusted.)
1468     match ref_kind {
1469         ty::ImmBorrow => {
1470             // The reference being reborrowed is a sharable ref of
1471             // type `&'a T`. In this case, it doesn't matter where we
1472             // *found* the `&T` pointer, the memory it references will
1473             // be valid and immutable for `'a`. So we can stop here.
1474             //
1475             // (Note that the `borrow_kind` must also be ImmBorrow or
1476             // else the user is borrowed imm memory as mut memory,
1477             // which means they'll get an error downstream in borrowck
1478             // anyhow.)
1479             return None;
1480         }
1481
1482         ty::MutBorrow | ty::UniqueImmBorrow => {
1483             // The reference being reborrowed is either an `&mut T` or
1484             // `&uniq T`. This is the case where recursion is needed.
1485             return Some((ref_cmt, new_borrow_kind));
1486         }
1487     }
1488 }
1489
1490 /// Ensures that all borrowed data reachable via `ty` outlives `region`.
1491 pub fn type_must_outlive<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
1492                                origin: infer::SubregionOrigin<'tcx>,
1493                                ty: Ty<'tcx>,
1494                                region: ty::Region)
1495 {
1496     debug!("type_must_outlive(ty={}, region={})",
1497            ty.repr(rcx.tcx()),
1498            region.repr(rcx.tcx()));
1499
1500     let implications = implicator::implications(rcx.fcx.infcx(), rcx.fcx, rcx.body_id,
1501                                                 ty, region, origin.span());
1502     for implication in implications {
1503         debug!("implication: {}", implication.repr(rcx.tcx()));
1504         match implication {
1505             implicator::Implication::RegionSubRegion(None, r_a, r_b) => {
1506                 rcx.fcx.mk_subr(origin.clone(), r_a, r_b);
1507             }
1508             implicator::Implication::RegionSubRegion(Some(ty), r_a, r_b) => {
1509                 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
1510                 rcx.fcx.mk_subr(o1, r_a, r_b);
1511             }
1512             implicator::Implication::RegionSubGeneric(None, r_a, ref generic_b) => {
1513                 generic_must_outlive(rcx, origin.clone(), r_a, generic_b);
1514             }
1515             implicator::Implication::RegionSubGeneric(Some(ty), r_a, ref generic_b) => {
1516                 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
1517                 generic_must_outlive(rcx, o1, r_a, generic_b);
1518             }
1519             implicator::Implication::Predicate(def_id, predicate) => {
1520                 let cause = traits::ObligationCause::new(origin.span(),
1521                                                          rcx.body_id,
1522                                                          traits::ItemObligation(def_id));
1523                 let obligation = traits::Obligation::new(cause, predicate);
1524                 rcx.fcx.register_predicate(obligation);
1525             }
1526         }
1527     }
1528 }
1529
1530 fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
1531                                   origin: infer::SubregionOrigin<'tcx>,
1532                                   region: ty::Region,
1533                                   generic: &GenericKind<'tcx>) {
1534     let param_env = &rcx.fcx.inh.param_env;
1535
1536     debug!("param_must_outlive(region={}, generic={})",
1537            region.repr(rcx.tcx()),
1538            generic.repr(rcx.tcx()));
1539
1540     // To start, collect bounds from user:
1541     let mut param_bounds =
1542         ty::required_region_bounds(rcx.tcx(),
1543                                    generic.to_ty(rcx.tcx()),
1544                                    param_env.caller_bounds.clone());
1545
1546     // In the case of a projection T::Foo, we may be able to extract bounds from the trait def:
1547     match *generic {
1548         GenericKind::Param(..) => { }
1549         GenericKind::Projection(ref projection_ty) => {
1550             param_bounds.push_all(
1551                 &projection_bounds(rcx, origin.span(), projection_ty)[]);
1552         }
1553     }
1554
1555     // Add in the default bound of fn body that applies to all in
1556     // scope type parameters:
1557     param_bounds.push(param_env.implicit_region_bound);
1558
1559     // Finally, collect regions we scraped from the well-formedness
1560     // constraints in the fn signature. To do that, we walk the list
1561     // of known relations from the fn ctxt.
1562     //
1563     // This is crucial because otherwise code like this fails:
1564     //
1565     //     fn foo<'a, A>(x: &'a A) { x.bar() }
1566     //
1567     // The problem is that the type of `x` is `&'a A`. To be
1568     // well-formed, then, A must be lower-generic by `'a`, but we
1569     // don't know that this holds from first principles.
1570     for &(ref r, ref p) in &rcx.region_bound_pairs {
1571         debug!("generic={} p={}",
1572                generic.repr(rcx.tcx()),
1573                p.repr(rcx.tcx()));
1574         if generic == p {
1575             param_bounds.push(*r);
1576         }
1577     }
1578
1579     // Inform region inference that this generic must be properly
1580     // bounded.
1581     rcx.fcx.infcx().verify_generic_bound(origin,
1582                                          generic.clone(),
1583                                          region,
1584                                          param_bounds);
1585 }
1586
1587 fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
1588                               span: Span,
1589                               projection_ty: &ty::ProjectionTy<'tcx>)
1590                               -> Vec<ty::Region>
1591 {
1592     let fcx = rcx.fcx;
1593     let tcx = fcx.tcx();
1594     let infcx = fcx.infcx();
1595
1596     debug!("projection_bounds(projection_ty={})",
1597            projection_ty.repr(tcx));
1598
1599     let ty = ty::mk_projection(tcx, projection_ty.trait_ref.clone(), projection_ty.item_name);
1600
1601     // Say we have a projection `<T as SomeTrait<'a>>::SomeType`. We are interested
1602     // in looking for a trait definition like:
1603     //
1604     // ```
1605     // trait SomeTrait<'a> {
1606     //     type SomeType : 'a;
1607     // }
1608     // ```
1609     //
1610     // we can thus deduce that `<T as SomeTrait<'a>>::SomeType : 'a`.
1611     let trait_predicates = ty::lookup_predicates(tcx, projection_ty.trait_ref.def_id);
1612     let predicates = trait_predicates.predicates.as_slice().to_vec();
1613     traits::elaborate_predicates(tcx, predicates)
1614         .filter_map(|predicate| {
1615             // we're only interesting in `T : 'a` style predicates:
1616             let outlives = match predicate {
1617                 ty::Predicate::TypeOutlives(data) => data,
1618                 _ => { return None; }
1619             };
1620
1621             debug!("projection_bounds: outlives={} (1)",
1622                    outlives.repr(tcx));
1623
1624             // apply the substitutions (and normalize any projected types)
1625             let outlives = fcx.instantiate_type_scheme(span,
1626                                                        projection_ty.trait_ref.substs,
1627                                                        &outlives);
1628
1629             debug!("projection_bounds: outlives={} (2)",
1630                    outlives.repr(tcx));
1631
1632             let region_result = infcx.try(|_| {
1633                 let (outlives, _) =
1634                     infcx.replace_late_bound_regions_with_fresh_var(
1635                         span,
1636                         infer::AssocTypeProjection(projection_ty.item_name),
1637                         &outlives);
1638
1639                 debug!("projection_bounds: outlives={} (3)",
1640                        outlives.repr(tcx));
1641
1642                 // check whether this predicate applies to our current projection
1643                 match infer::mk_eqty(infcx, false, infer::Misc(span), ty, outlives.0) {
1644                     Ok(()) => { Ok(outlives.1) }
1645                     Err(_) => { Err(()) }
1646                 }
1647             });
1648
1649             debug!("projection_bounds: region_result={}",
1650                    region_result.repr(tcx));
1651
1652             region_result.ok()
1653         })
1654         .collect()
1655 }