]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/check/regionck.rs
Auto merge of #61361 - estebank:infer-type, r=varkor
[rust.git] / src / librustc_typeck / check / regionck.rs
1 //! The region check is a final pass that runs over the AST after we have
2 //! inferred the type constraints but before we have actually finalized
3 //! the types. Its purpose is to embed a variety of region constraints.
4 //! Inserting these constraints as a separate pass is good because (1) it
5 //! localizes the code that has to do with region inference and (2) often
6 //! we cannot know what constraints are needed until the basic types have
7 //! been inferred.
8 //!
9 //! ### Interaction with the borrow checker
10 //!
11 //! In general, the job of the borrowck module (which runs later) is to
12 //! check that all soundness criteria are met, given a particular set of
13 //! regions. The job of *this* module is to anticipate the needs of the
14 //! borrow checker and infer regions that will satisfy its requirements.
15 //! It is generally true that the inference doesn't need to be sound,
16 //! meaning that if there is a bug and we inferred bad regions, the borrow
17 //! checker should catch it. This is not entirely true though; for
18 //! example, the borrow checker doesn't check subtyping, and it doesn't
19 //! check that region pointers are always live when they are used. It
20 //! might be worthwhile to fix this so that borrowck serves as a kind of
21 //! verification step -- that would add confidence in the overall
22 //! correctness of the compiler, at the cost of duplicating some type
23 //! checks and effort.
24 //!
25 //! ### Inferring the duration of borrows, automatic and otherwise
26 //!
27 //! Whenever we introduce a borrowed pointer, for example as the result of
28 //! a borrow expression `let x = &data`, the lifetime of the pointer `x`
29 //! is always specified as a region inference variable. `regionck` has the
30 //! job of adding constraints such that this inference variable is as
31 //! narrow as possible while still accommodating all uses (that is, every
32 //! dereference of the resulting pointer must be within the lifetime).
33 //!
34 //! #### Reborrows
35 //!
36 //! Generally speaking, `regionck` does NOT try to ensure that the data
37 //! `data` will outlive the pointer `x`. That is the job of borrowck. The
38 //! one exception is when "re-borrowing" the contents of another borrowed
39 //! pointer. For example, imagine you have a borrowed pointer `b` with
40 //! lifetime `L1` and you have an expression `&*b`. The result of this
41 //! expression will be another borrowed pointer with lifetime `L2` (which is
42 //! an inference variable). The borrow checker is going to enforce the
43 //! constraint that `L2 < L1`, because otherwise you are re-borrowing data
44 //! for a lifetime larger than the original loan. However, without the
45 //! routines in this module, the region inferencer would not know of this
46 //! dependency and thus it might infer the lifetime of `L2` to be greater
47 //! than `L1` (issue #3148).
48 //!
49 //! There are a number of troublesome scenarios in the tests
50 //! `region-dependent-*.rs`, but here is one example:
51 //!
52 //!     struct Foo { i: i32 }
53 //!     struct Bar { foo: Foo  }
54 //!     fn get_i<'a>(x: &'a Bar) -> &'a i32 {
55 //!        let foo = &x.foo; // Lifetime L1
56 //!        &foo.i            // Lifetime L2
57 //!     }
58 //!
59 //! Note that this comes up either with `&` expressions, `ref`
60 //! bindings, and `autorefs`, which are the three ways to introduce
61 //! a borrow.
62 //!
63 //! The key point here is that when you are borrowing a value that
64 //! is "guaranteed" by a borrowed pointer, you must link the
65 //! lifetime of that borrowed pointer (`L1`, here) to the lifetime of
66 //! the borrow itself (`L2`). What do I mean by "guaranteed" by a
67 //! borrowed pointer? I mean any data that is reached by first
68 //! dereferencing a borrowed pointer and then either traversing
69 //! interior offsets or boxes. We say that the guarantor
70 //! of such data is the region of the borrowed pointer that was
71 //! traversed. This is essentially the same as the ownership
72 //! relation, except that a borrowed pointer never owns its
73 //! contents.
74
75 use crate::check::dropck;
76 use crate::check::FnCtxt;
77 use crate::middle::mem_categorization as mc;
78 use crate::middle::mem_categorization::Categorization;
79 use crate::middle::region;
80 use rustc::hir::def_id::DefId;
81 use rustc::infer::outlives::env::OutlivesEnvironment;
82 use rustc::infer::{self, RegionObligation, SuppressRegionErrors};
83 use rustc::ty::adjustment;
84 use rustc::ty::subst::{SubstsRef, UnpackedKind};
85 use rustc::ty::{self, Ty};
86
87 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
88 use rustc::hir::{self, PatKind};
89 use std::mem;
90 use std::ops::Deref;
91 use std::rc::Rc;
92 use syntax_pos::Span;
93
94 // a variation on try that just returns unit
95 macro_rules! ignore_err {
96     ($e:expr) => {
97         match $e {
98             Ok(e) => e,
99             Err(_) => {
100                 debug!("ignoring mem-categorization error!");
101                 return ();
102             }
103         }
104     };
105 }
106
107 ///////////////////////////////////////////////////////////////////////////
108 // PUBLIC ENTRY POINTS
109
110 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
111     pub fn regionck_expr(&self, body: &'gcx hir::Body) {
112         let subject = self.tcx.hir().body_owner_def_id(body.id());
113         let id = body.value.hir_id;
114         let mut rcx = RegionCtxt::new(
115             self,
116             RepeatingScope(id),
117             id,
118             Subject(subject),
119             self.param_env,
120         );
121
122         // There are no add'l implied bounds when checking a
123         // standalone expr (e.g., the `E` in a type like `[u32; E]`).
124         rcx.outlives_environment.save_implied_bounds(id);
125
126         if self.err_count_since_creation() == 0 {
127             // regionck assumes typeck succeeded
128             rcx.visit_body(body);
129             rcx.visit_region_obligations(id);
130         }
131         rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
132
133         assert!(self.tables.borrow().free_region_map.is_empty());
134         self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
135     }
136
137     /// Region checking during the WF phase for items. `wf_tys` are the
138     /// types from which we should derive implied bounds, if any.
139     pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
140         debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
141         let subject = self.tcx.hir().local_def_id_from_hir_id(item_id);
142         let mut rcx = RegionCtxt::new(
143             self,
144             RepeatingScope(item_id),
145             item_id,
146             Subject(subject),
147             self.param_env,
148         );
149         rcx.outlives_environment
150             .add_implied_bounds(self, wf_tys, item_id, span);
151         rcx.outlives_environment.save_implied_bounds(item_id);
152         rcx.visit_region_obligations(item_id);
153         rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default());
154     }
155
156     /// Region check a function body. Not invoked on closures, but
157     /// only on the "root" fn item (in which closures may be
158     /// embedded). Walks the function body and adds various add'l
159     /// constraints that are needed for region inference. This is
160     /// separated both to isolate "pure" region constraints from the
161     /// rest of type check and because sometimes we need type
162     /// inference to have completed before we can determine which
163     /// constraints to add.
164     pub fn regionck_fn(&self, fn_id: hir::HirId, body: &'gcx hir::Body) {
165         debug!("regionck_fn(id={})", fn_id);
166         let subject = self.tcx.hir().body_owner_def_id(body.id());
167         let hir_id = body.value.hir_id;
168         let mut rcx = RegionCtxt::new(
169             self,
170             RepeatingScope(hir_id),
171             hir_id,
172             Subject(subject),
173             self.param_env,
174         );
175
176         if self.err_count_since_creation() == 0 {
177             // regionck assumes typeck succeeded
178             rcx.visit_fn_body(fn_id, body, self.tcx.hir().span_by_hir_id(fn_id));
179         }
180
181         rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx));
182
183         // In this mode, we also copy the free-region-map into the
184         // tables of the enclosing fcx. In the other regionck modes
185         // (e.g., `regionck_item`), we don't have an enclosing tables.
186         assert!(self.tables.borrow().free_region_map.is_empty());
187         self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
188     }
189 }
190
191 ///////////////////////////////////////////////////////////////////////////
192 // INTERNALS
193
194 pub struct RegionCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
195     pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
196
197     pub region_scope_tree: &'gcx region::ScopeTree,
198
199     outlives_environment: OutlivesEnvironment<'tcx>,
200
201     // id of innermost fn body id
202     body_id: hir::HirId,
203     body_owner: DefId,
204
205     // call_site scope of innermost fn
206     call_site_scope: Option<region::Scope>,
207
208     // id of innermost fn or loop
209     repeating_scope: hir::HirId,
210
211     // id of AST node being analyzed (the subject of the analysis).
212     subject_def_id: DefId,
213 }
214
215 impl<'a, 'gcx, 'tcx> Deref for RegionCtxt<'a, 'gcx, 'tcx> {
216     type Target = FnCtxt<'a, 'gcx, 'tcx>;
217     fn deref(&self) -> &Self::Target {
218         &self.fcx
219     }
220 }
221
222 pub struct RepeatingScope(hir::HirId);
223 pub struct Subject(DefId);
224
225 impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
226     pub fn new(
227         fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
228         RepeatingScope(initial_repeating_scope): RepeatingScope,
229         initial_body_id: hir::HirId,
230         Subject(subject): Subject,
231         param_env: ty::ParamEnv<'tcx>,
232     ) -> RegionCtxt<'a, 'gcx, 'tcx> {
233         let region_scope_tree = fcx.tcx.region_scope_tree(subject);
234         let outlives_environment = OutlivesEnvironment::new(param_env);
235         RegionCtxt {
236             fcx,
237             region_scope_tree,
238             repeating_scope: initial_repeating_scope,
239             body_id: initial_body_id,
240             body_owner: subject,
241             call_site_scope: None,
242             subject_def_id: subject,
243             outlives_environment,
244         }
245     }
246
247     fn set_repeating_scope(&mut self, scope: hir::HirId) -> hir::HirId {
248         mem::replace(&mut self.repeating_scope, scope)
249     }
250
251     /// Try to resolve the type for the given node, returning `t_err` if an error results. Note that
252     /// we never care about the details of the error, the same error will be detected and reported
253     /// in the writeback phase.
254     ///
255     /// Note one important point: we do not attempt to resolve *region variables* here. This is
256     /// because regionck is essentially adding constraints to those region variables and so may yet
257     /// influence how they are resolved.
258     ///
259     /// Consider this silly example:
260     ///
261     /// ```
262     /// fn borrow(x: &i32) -> &i32 {x}
263     /// fn foo(x: @i32) -> i32 {  // block: B
264     ///     let b = borrow(x);    // region: <R0>
265     ///     *b
266     /// }
267     /// ```
268     ///
269     /// Here, the region of `b` will be `<R0>`. `<R0>` is constrained to be some subregion of the
270     /// block B and some superregion of the call. If we forced it now, we'd choose the smaller
271     /// region (the call). But that would make the *b illegal. Since we don't resolve, the type
272     /// of b will be `&<R0>.i32` and then `*b` will require that `<R0>` be bigger than the let and
273     /// the `*b` expression, so we will effectively resolve `<R0>` to be the block B.
274     pub fn resolve_type(&self, unresolved_ty: Ty<'tcx>) -> Ty<'tcx> {
275         self.resolve_vars_if_possible(&unresolved_ty)
276     }
277
278     /// Try to resolve the type for the given node.
279     fn resolve_node_type(&self, id: hir::HirId) -> Ty<'tcx> {
280         let t = self.node_ty(id);
281         self.resolve_type(t)
282     }
283
284     /// Try to resolve the type for the given node.
285     pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> {
286         let ty = self.tables.borrow().expr_ty_adjusted(expr);
287         self.resolve_type(ty)
288     }
289
290     /// This is the "main" function when region-checking a function item or a closure
291     /// within a function item. It begins by updating various fields (e.g., `call_site_scope`
292     /// and `outlives_environment`) to be appropriate to the function and then adds constraints
293     /// derived from the function body.
294     ///
295     /// Note that it does **not** restore the state of the fields that
296     /// it updates! This is intentional, since -- for the main
297     /// function -- we wish to be able to read the final
298     /// `outlives_environment` and other fields from the caller. For
299     /// closures, however, we save and restore any "scoped state"
300     /// before we invoke this function. (See `visit_fn` in the
301     /// `intravisit::Visitor` impl below.)
302     fn visit_fn_body(
303         &mut self,
304         id: hir::HirId, // the id of the fn itself
305         body: &'gcx hir::Body,
306         span: Span,
307     ) {
308         // When we enter a function, we can derive
309         debug!("visit_fn_body(id={:?})", id);
310
311         let body_id = body.id();
312         self.body_id = body_id.hir_id;
313         self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
314
315         let call_site = region::Scope {
316             id: body.value.hir_id.local_id,
317             data: region::ScopeData::CallSite,
318         };
319         self.call_site_scope = Some(call_site);
320
321         let fn_sig = {
322             match self.tables.borrow().liberated_fn_sigs().get(id) {
323                 Some(f) => f.clone(),
324                 None => {
325                     bug!("No fn-sig entry for id={:?}", id);
326                 }
327             }
328         };
329
330         // Collect the types from which we create inferred bounds.
331         // For the return type, if diverging, substitute `bool` just
332         // because it will have no effect.
333         //
334         // FIXME(#27579) return types should not be implied bounds
335         let fn_sig_tys: Vec<_> = fn_sig
336             .inputs()
337             .iter()
338             .cloned()
339             .chain(Some(fn_sig.output()))
340             .collect();
341
342         self.outlives_environment.add_implied_bounds(
343             self.fcx,
344             &fn_sig_tys[..],
345             body_id.hir_id,
346             span,
347         );
348         self.outlives_environment
349             .save_implied_bounds(body_id.hir_id);
350         self.link_fn_args(
351             region::Scope {
352                 id: body.value.hir_id.local_id,
353                 data: region::ScopeData::Node,
354             },
355             &body.arguments,
356         );
357         self.visit_body(body);
358         self.visit_region_obligations(body_id.hir_id);
359
360         let call_site_scope = self.call_site_scope.unwrap();
361         debug!(
362             "visit_fn_body body.id {:?} call_site_scope: {:?}",
363             body.id(),
364             call_site_scope
365         );
366         let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
367
368         self.type_of_node_must_outlive(infer::CallReturn(span), body_id.hir_id, call_site_region);
369
370         self.constrain_opaque_types(
371             &self.fcx.opaque_types.borrow(),
372             self.outlives_environment.free_region_map(),
373         );
374     }
375
376     fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
377         debug!("visit_region_obligations: hir_id={:?}", hir_id);
378
379         // region checking can introduce new pending obligations
380         // which, when processed, might generate new region
381         // obligations. So make sure we process those.
382         self.select_all_obligations_or_error();
383     }
384
385     fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) {
386         self.infcx.process_registered_region_obligations(
387             self.outlives_environment.region_bound_pairs_map(),
388             self.implicit_region_bound,
389             self.param_env,
390         );
391
392         self.fcx.resolve_regions_and_report_errors(
393             self.subject_def_id,
394             &self.region_scope_tree,
395             &self.outlives_environment,
396             suppress,
397         );
398     }
399
400     fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
401         debug!("regionck::visit_pat(pat={:?})", pat);
402         pat.each_binding(|_, hir_id, span, _| {
403             // If we have a variable that contains region'd data, that
404             // data will be accessible from anywhere that the variable is
405             // accessed. We must be wary of loops like this:
406             //
407             //     // from src/test/compile-fail/borrowck-lend-flow.rs
408             //     let mut v = box 3, w = box 4;
409             //     let mut x = &mut w;
410             //     loop {
411             //         **x += 1;   // (2)
412             //         borrow(v);  //~ ERROR cannot borrow
413             //         x = &mut v; // (1)
414             //     }
415             //
416             // Typically, we try to determine the region of a borrow from
417             // those points where it is dereferenced. In this case, one
418             // might imagine that the lifetime of `x` need only be the
419             // body of the loop. But of course this is incorrect because
420             // the pointer that is created at point (1) is consumed at
421             // point (2), meaning that it must be live across the loop
422             // iteration. The easiest way to guarantee this is to require
423             // that the lifetime of any regions that appear in a
424             // variable's type enclose at least the variable's scope.
425             let var_scope = self.region_scope_tree.var_scope(hir_id.local_id);
426             let var_region = self.tcx.mk_region(ty::ReScope(var_scope));
427
428             let origin = infer::BindingTypeIsNotValidAtDecl(span);
429             self.type_of_node_must_outlive(origin, hir_id, var_region);
430
431             let typ = self.resolve_node_type(hir_id);
432             let body_id = self.body_id;
433             let _ = dropck::check_safety_of_destructor_if_necessary(
434                 self, typ, span, body_id, var_scope,
435             );
436         })
437     }
438 }
439
440 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
441     // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
442     // However, right now we run into an issue whereby some free
443     // regions are not properly related if they appear within the
444     // types of arguments that must be inferred. This could be
445     // addressed by deferring the construction of the region
446     // hierarchy, and in particular the relationships between free
447     // regions, until regionck, as described in #3238.
448
449     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
450         NestedVisitorMap::None
451     }
452
453     fn visit_fn(
454         &mut self,
455         fk: intravisit::FnKind<'gcx>,
456         _: &'gcx hir::FnDecl,
457         body_id: hir::BodyId,
458         span: Span,
459         hir_id: hir::HirId,
460     ) {
461         assert!(
462             match fk {
463                 intravisit::FnKind::Closure(..) => true,
464                 _ => false,
465             },
466             "visit_fn invoked for something other than a closure"
467         );
468
469         // Save state of current function before invoking
470         // `visit_fn_body`.  We will restore afterwards.
471         let old_body_id = self.body_id;
472         let old_body_owner = self.body_owner;
473         let old_call_site_scope = self.call_site_scope;
474         let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
475
476         let body = self.tcx.hir().body(body_id);
477         self.visit_fn_body(hir_id, body, span);
478
479         // Restore state from previous function.
480         self.outlives_environment
481             .pop_snapshot_post_closure(env_snapshot);
482         self.call_site_scope = old_call_site_scope;
483         self.body_id = old_body_id;
484         self.body_owner = old_body_owner;
485     }
486
487     //visit_pat: visit_pat, // (..) see above
488
489     fn visit_arm(&mut self, arm: &'gcx hir::Arm) {
490         // see above
491         for p in &arm.pats {
492             self.constrain_bindings_in_pat(p);
493         }
494         intravisit::walk_arm(self, arm);
495     }
496
497     fn visit_local(&mut self, l: &'gcx hir::Local) {
498         // see above
499         self.constrain_bindings_in_pat(&l.pat);
500         self.link_local(l);
501         intravisit::walk_local(self, l);
502     }
503
504     fn visit_expr(&mut self, expr: &'gcx hir::Expr) {
505         debug!(
506             "regionck::visit_expr(e={:?}, repeating_scope={:?})",
507             expr, self.repeating_scope
508         );
509
510         // No matter what, the type of each expression must outlive the
511         // scope of that expression. This also guarantees basic WF.
512         let expr_ty = self.resolve_node_type(expr.hir_id);
513         // the region corresponding to this expression
514         let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
515             id: expr.hir_id.local_id,
516             data: region::ScopeData::Node,
517         }));
518         self.type_must_outlive(
519             infer::ExprTypeIsNotInScope(expr_ty, expr.span),
520             expr_ty,
521             expr_region,
522         );
523
524         let is_method_call = self.tables.borrow().is_method_call(expr);
525
526         // If we are calling a method (either explicitly or via an
527         // overloaded operator), check that all of the types provided as
528         // arguments for its type parameters are well-formed, and all the regions
529         // provided as arguments outlive the call.
530         if is_method_call {
531             let origin = match expr.node {
532                 hir::ExprKind::MethodCall(..) => infer::ParameterOrigin::MethodCall,
533                 hir::ExprKind::Unary(op, _) if op == hir::UnDeref => {
534                     infer::ParameterOrigin::OverloadedDeref
535                 }
536                 _ => infer::ParameterOrigin::OverloadedOperator,
537             };
538
539             let substs = self.tables.borrow().node_substs(expr.hir_id);
540             self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
541             // Arguments (sub-expressions) are checked via `constrain_call`, below.
542         }
543
544         // Check any autoderefs or autorefs that appear.
545         let cmt_result = self.constrain_adjustments(expr);
546
547         // If necessary, constrain destructors in this expression. This will be
548         // the adjusted form if there is an adjustment.
549         match cmt_result {
550             Ok(head_cmt) => {
551                 self.check_safety_of_rvalue_destructor_if_necessary(&head_cmt, expr.span);
552             }
553             Err(..) => {
554                 self.tcx.sess.delay_span_bug(expr.span, "cat_expr Errd");
555             }
556         }
557
558         debug!(
559             "regionck::visit_expr(e={:?}, repeating_scope={:?}) - visiting subexprs",
560             expr, self.repeating_scope
561         );
562         match expr.node {
563             hir::ExprKind::Path(_) => {
564                 let substs = self.tables.borrow().node_substs(expr.hir_id);
565                 let origin = infer::ParameterOrigin::Path;
566                 self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
567             }
568
569             hir::ExprKind::Call(ref callee, ref args) => {
570                 if is_method_call {
571                     self.constrain_call(expr, Some(&callee), args.iter().map(|e| &*e));
572                 } else {
573                     self.constrain_callee(&callee);
574                     self.constrain_call(expr, None, args.iter().map(|e| &*e));
575                 }
576
577                 intravisit::walk_expr(self, expr);
578             }
579
580             hir::ExprKind::MethodCall(.., ref args) => {
581                 self.constrain_call(expr, Some(&args[0]), args[1..].iter().map(|e| &*e));
582
583                 intravisit::walk_expr(self, expr);
584             }
585
586             hir::ExprKind::AssignOp(_, ref lhs, ref rhs) => {
587                 if is_method_call {
588                     self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
589                 }
590
591                 intravisit::walk_expr(self, expr);
592             }
593
594             hir::ExprKind::Index(ref lhs, ref rhs) if is_method_call => {
595                 self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
596
597                 intravisit::walk_expr(self, expr);
598             }
599
600             hir::ExprKind::Binary(_, ref lhs, ref rhs) if is_method_call => {
601                 // As `ExprKind::MethodCall`, but the call is via an overloaded op.
602                 self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
603
604                 intravisit::walk_expr(self, expr);
605             }
606
607             hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
608                 // If you do `x OP y`, then the types of `x` and `y` must
609                 // outlive the operation you are performing.
610                 let lhs_ty = self.resolve_expr_type_adjusted(&lhs);
611                 let rhs_ty = self.resolve_expr_type_adjusted(&rhs);
612                 for &ty in &[lhs_ty, rhs_ty] {
613                     self.type_must_outlive(infer::Operand(expr.span), ty, expr_region);
614                 }
615                 intravisit::walk_expr(self, expr);
616             }
617
618             hir::ExprKind::Unary(hir::UnDeref, ref base) => {
619                 // For *a, the lifetime of a must enclose the deref
620                 if is_method_call {
621                     self.constrain_call(expr, Some(base), None::<hir::Expr>.iter());
622                 }
623                 // For overloaded derefs, base_ty is the input to `Deref::deref`,
624                 // but it's a reference type uing the same region as the output.
625                 let base_ty = self.resolve_expr_type_adjusted(base);
626                 if let ty::Ref(r_ptr, _, _) = base_ty.sty {
627                     self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
628                 }
629
630                 intravisit::walk_expr(self, expr);
631             }
632
633             hir::ExprKind::Unary(_, ref lhs) if is_method_call => {
634                 // As above.
635                 self.constrain_call(expr, Some(&lhs), None::<hir::Expr>.iter());
636
637                 intravisit::walk_expr(self, expr);
638             }
639
640             hir::ExprKind::Index(ref vec_expr, _) => {
641                 // For a[b], the lifetime of a must enclose the deref
642                 let vec_type = self.resolve_expr_type_adjusted(&vec_expr);
643                 self.constrain_index(expr, vec_type);
644
645                 intravisit::walk_expr(self, expr);
646             }
647
648             hir::ExprKind::Cast(ref source, _) => {
649                 // Determine if we are casting `source` to a trait
650                 // instance.  If so, we have to be sure that the type of
651                 // the source obeys the trait's region bound.
652                 self.constrain_cast(expr, &source);
653                 intravisit::walk_expr(self, expr);
654             }
655
656             hir::ExprKind::AddrOf(m, ref base) => {
657                 self.link_addr_of(expr, m, &base);
658
659                 // Require that when you write a `&expr` expression, the
660                 // resulting pointer has a lifetime that encompasses the
661                 // `&expr` expression itself. Note that we constraining
662                 // the type of the node expr.id here *before applying
663                 // adjustments*.
664                 //
665                 // FIXME(https://github.com/rust-lang/rfcs/issues/811)
666                 // nested method calls requires that this rule change
667                 let ty0 = self.resolve_node_type(expr.hir_id);
668                 self.type_must_outlive(infer::AddrOf(expr.span), ty0, expr_region);
669                 intravisit::walk_expr(self, expr);
670             }
671
672             hir::ExprKind::Match(ref discr, ref arms, _) => {
673                 self.link_match(&discr, &arms[..]);
674
675                 intravisit::walk_expr(self, expr);
676             }
677
678             hir::ExprKind::Closure(.., body_id, _, _) => {
679                 self.check_expr_fn_block(expr, body_id);
680             }
681
682             hir::ExprKind::Loop(ref body, _, _) => {
683                 let repeating_scope = self.set_repeating_scope(body.hir_id);
684                 intravisit::walk_expr(self, expr);
685                 self.set_repeating_scope(repeating_scope);
686             }
687
688             hir::ExprKind::While(ref cond, ref body, _) => {
689                 let repeating_scope = self.set_repeating_scope(cond.hir_id);
690                 self.visit_expr(&cond);
691
692                 self.set_repeating_scope(body.hir_id);
693                 self.visit_block(&body);
694
695                 self.set_repeating_scope(repeating_scope);
696             }
697
698             hir::ExprKind::Ret(Some(ref ret_expr)) => {
699                 let call_site_scope = self.call_site_scope;
700                 debug!(
701                     "visit_expr ExprKind::Ret ret_expr.hir_id {} call_site_scope: {:?}",
702                     ret_expr.hir_id, call_site_scope
703                 );
704                 let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope.unwrap()));
705                 self.type_of_node_must_outlive(
706                     infer::CallReturn(ret_expr.span),
707                     ret_expr.hir_id,
708                     call_site_region,
709                 );
710                 intravisit::walk_expr(self, expr);
711             }
712
713             _ => {
714                 intravisit::walk_expr(self, expr);
715             }
716         }
717     }
718 }
719
720 impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
721     fn constrain_cast(&mut self, cast_expr: &hir::Expr, source_expr: &hir::Expr) {
722         debug!(
723             "constrain_cast(cast_expr={:?}, source_expr={:?})",
724             cast_expr, source_expr
725         );
726
727         let source_ty = self.resolve_node_type(source_expr.hir_id);
728         let target_ty = self.resolve_node_type(cast_expr.hir_id);
729
730         self.walk_cast(cast_expr, source_ty, target_ty);
731     }
732
733     fn walk_cast(&mut self, cast_expr: &hir::Expr, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) {
734         debug!("walk_cast(from_ty={:?}, to_ty={:?})", from_ty, to_ty);
735         match (&from_ty.sty, &to_ty.sty) {
736             /*From:*/
737             (&ty::Ref(from_r, from_ty, _), /*To:  */ &ty::Ref(to_r, to_ty, _)) => {
738                 // Target cannot outlive source, naturally.
739                 self.sub_regions(infer::Reborrow(cast_expr.span), to_r, from_r);
740                 self.walk_cast(cast_expr, from_ty, to_ty);
741             }
742
743             /*From:*/
744             (_, /*To:  */ &ty::Dynamic(.., r)) => {
745                 // When T is existentially quantified as a trait
746                 // `Foo+'to`, it must outlive the region bound `'to`.
747                 self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r);
748             }
749
750             /*From:*/
751             (&ty::Adt(from_def, _), /*To:  */ &ty::Adt(to_def, _))
752                 if from_def.is_box() && to_def.is_box() =>
753             {
754                 self.walk_cast(cast_expr, from_ty.boxed_ty(), to_ty.boxed_ty());
755             }
756
757             _ => {}
758         }
759     }
760
761     fn check_expr_fn_block(&mut self, expr: &'gcx hir::Expr, body_id: hir::BodyId) {
762         let repeating_scope = self.set_repeating_scope(body_id.hir_id);
763         intravisit::walk_expr(self, expr);
764         self.set_repeating_scope(repeating_scope);
765     }
766
767     fn constrain_callee(&mut self, callee_expr: &hir::Expr) {
768         let callee_ty = self.resolve_node_type(callee_expr.hir_id);
769         match callee_ty.sty {
770             ty::FnDef(..) | ty::FnPtr(_) => {}
771             _ => {
772                 // this should not happen, but it does if the program is
773                 // erroneous
774                 //
775                 // bug!(
776                 //     callee_expr.span,
777                 //     "Calling non-function: {}",
778                 //     callee_ty);
779             }
780         }
781     }
782
783     fn constrain_call<'b, I: Iterator<Item = &'b hir::Expr>>(
784         &mut self,
785         call_expr: &hir::Expr,
786         receiver: Option<&hir::Expr>,
787         arg_exprs: I,
788     ) {
789         //! Invoked on every call site (i.e., normal calls, method calls,
790         //! and overloaded operators). Constrains the regions which appear
791         //! in the type of the function. Also constrains the regions that
792         //! appear in the arguments appropriately.
793
794         debug!(
795             "constrain_call(call_expr={:?}, receiver={:?})",
796             call_expr, receiver
797         );
798
799         // `callee_region` is the scope representing the time in which the
800         // call occurs.
801         //
802         // FIXME(#6268) to support nested method calls, should be callee_id
803         let callee_scope = region::Scope {
804             id: call_expr.hir_id.local_id,
805             data: region::ScopeData::Node,
806         };
807         let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
808
809         debug!("callee_region={:?}", callee_region);
810
811         for arg_expr in arg_exprs {
812             debug!("Argument: {:?}", arg_expr);
813
814             // ensure that any regions appearing in the argument type are
815             // valid for at least the lifetime of the function:
816             self.type_of_node_must_outlive(
817                 infer::CallArg(arg_expr.span),
818                 arg_expr.hir_id,
819                 callee_region,
820             );
821         }
822
823         // as loop above, but for receiver
824         if let Some(r) = receiver {
825             debug!("receiver: {:?}", r);
826             self.type_of_node_must_outlive(infer::CallRcvr(r.span), r.hir_id, callee_region);
827         }
828     }
829
830     /// Creates a temporary `MemCategorizationContext` and pass it to the closure.
831     fn with_mc<F, R>(&self, f: F) -> R
832     where
833         F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R,
834     {
835         f(mc::MemCategorizationContext::with_infer(
836             &self.infcx,
837             self.body_owner,
838             &self.region_scope_tree,
839             &self.tables.borrow(),
840         ))
841     }
842
843     /// Invoked on any adjustments that occur. Checks that if this is a region pointer being
844     /// dereferenced, the lifetime of the pointer includes the deref expr.
845     fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult<mc::cmt_<'tcx>> {
846         debug!("constrain_adjustments(expr={:?})", expr);
847
848         let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
849
850         let tables = self.tables.borrow();
851         let adjustments = tables.expr_adjustments(&expr);
852         if adjustments.is_empty() {
853             return Ok(cmt);
854         }
855
856         debug!("constrain_adjustments: adjustments={:?}", adjustments);
857
858         // If necessary, constrain destructors in the unadjusted form of this
859         // expression.
860         self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span);
861
862         let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
863             id: expr.hir_id.local_id,
864             data: region::ScopeData::Node,
865         }));
866         for adjustment in adjustments {
867             debug!(
868                 "constrain_adjustments: adjustment={:?}, cmt={:?}",
869                 adjustment, cmt
870             );
871
872             if let adjustment::Adjust::Deref(Some(deref)) = adjustment.kind {
873                 debug!("constrain_adjustments: overloaded deref: {:?}", deref);
874
875                 // Treat overloaded autoderefs as if an AutoBorrow adjustment
876                 // was applied on the base type, as that is always the case.
877                 let input = self.tcx.mk_ref(
878                     deref.region,
879                     ty::TypeAndMut {
880                         ty: cmt.ty,
881                         mutbl: deref.mutbl,
882                     },
883                 );
884                 let output = self.tcx.mk_ref(
885                     deref.region,
886                     ty::TypeAndMut {
887                         ty: adjustment.target,
888                         mutbl: deref.mutbl,
889                     },
890                 );
891
892                 self.link_region(
893                     expr.span,
894                     deref.region,
895                     ty::BorrowKind::from_mutbl(deref.mutbl),
896                     &cmt,
897                 );
898
899                 // Specialized version of constrain_call.
900                 self.type_must_outlive(infer::CallRcvr(expr.span), input, expr_region);
901                 self.type_must_outlive(infer::CallReturn(expr.span), output, expr_region);
902             }
903
904             if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind {
905                 self.link_autoref(expr, &cmt, autoref);
906
907                 // Require that the resulting region encompasses
908                 // the current node.
909                 //
910                 // FIXME(#6268) remove to support nested method calls
911                 self.type_of_node_must_outlive(
912                     infer::AutoBorrow(expr.span),
913                     expr.hir_id,
914                     expr_region,
915                 );
916             }
917
918             cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?;
919
920             if let Categorization::Deref(_, mc::BorrowedPtr(_, r_ptr)) = cmt.cat {
921                 self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
922             }
923         }
924
925         Ok(cmt)
926     }
927
928     pub fn mk_subregion_due_to_dereference(
929         &mut self,
930         deref_span: Span,
931         minimum_lifetime: ty::Region<'tcx>,
932         maximum_lifetime: ty::Region<'tcx>,
933     ) {
934         self.sub_regions(
935             infer::DerefPointer(deref_span),
936             minimum_lifetime,
937             maximum_lifetime,
938         )
939     }
940
941     fn check_safety_of_rvalue_destructor_if_necessary(&mut self, cmt: &mc::cmt_<'tcx>, span: Span) {
942         if let Categorization::Rvalue(region) = cmt.cat {
943             match *region {
944                 ty::ReScope(rvalue_scope) => {
945                     let typ = self.resolve_type(cmt.ty);
946                     let body_id = self.body_id;
947                     let _ = dropck::check_safety_of_destructor_if_necessary(
948                         self,
949                         typ,
950                         span,
951                         body_id,
952                         rvalue_scope,
953                     );
954                 }
955                 ty::ReStatic => {}
956                 _ => {
957                     span_bug!(
958                         span,
959                         "unexpected rvalue region in rvalue \
960                          destructor safety checking: `{:?}`",
961                         region
962                     );
963                 }
964             }
965         }
966     }
967
968     /// Invoked on any index expression that occurs. Checks that if this is a slice
969     /// being indexed, the lifetime of the pointer includes the deref expr.
970     fn constrain_index(&mut self, index_expr: &hir::Expr, indexed_ty: Ty<'tcx>) {
971         debug!(
972             "constrain_index(index_expr=?, indexed_ty={}",
973             self.ty_to_string(indexed_ty)
974         );
975
976         let r_index_expr = ty::ReScope(region::Scope {
977             id: index_expr.hir_id.local_id,
978             data: region::ScopeData::Node,
979         });
980         if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.sty {
981             match r_ty.sty {
982                 ty::Slice(_) | ty::Str => {
983                     self.sub_regions(
984                         infer::IndexSlice(index_expr.span),
985                         self.tcx.mk_region(r_index_expr),
986                         r_ptr,
987                     );
988                 }
989                 _ => {}
990             }
991         }
992     }
993
994     /// Guarantees that any lifetimes which appear in the type of the node `id` (after applying
995     /// adjustments) are valid for at least `minimum_lifetime`
996     fn type_of_node_must_outlive(
997         &mut self,
998         origin: infer::SubregionOrigin<'tcx>,
999         hir_id: hir::HirId,
1000         minimum_lifetime: ty::Region<'tcx>,
1001     ) {
1002         // Try to resolve the type.  If we encounter an error, then typeck
1003         // is going to fail anyway, so just stop here and let typeck
1004         // report errors later on in the writeback phase.
1005         let ty0 = self.resolve_node_type(hir_id);
1006
1007         let ty = self.tables
1008             .borrow()
1009             .adjustments()
1010             .get(hir_id)
1011             .and_then(|adj| adj.last())
1012             .map_or(ty0, |adj| adj.target);
1013         let ty = self.resolve_type(ty);
1014         debug!(
1015             "constrain_regions_in_type_of_node(\
1016              ty={}, ty0={}, id={:?}, minimum_lifetime={:?})",
1017             ty, ty0, hir_id, minimum_lifetime
1018         );
1019         self.type_must_outlive(origin, ty, minimum_lifetime);
1020     }
1021
1022     /// Adds constraints to inference such that `T: 'a` holds (or
1023     /// reports an error if it cannot).
1024     ///
1025     /// # Parameters
1026     ///
1027     /// - `origin`, the reason we need this constraint
1028     /// - `ty`, the type `T`
1029     /// - `region`, the region `'a`
1030     pub fn type_must_outlive(
1031         &self,
1032         origin: infer::SubregionOrigin<'tcx>,
1033         ty: Ty<'tcx>,
1034         region: ty::Region<'tcx>,
1035     ) {
1036         self.infcx.register_region_obligation(
1037             self.body_id,
1038             RegionObligation {
1039                 sub_region: region,
1040                 sup_type: ty,
1041                 origin,
1042             },
1043         );
1044     }
1045
1046     /// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the
1047     /// resulting pointer is linked to the lifetime of its guarantor (if any).
1048     fn link_addr_of(&mut self, expr: &hir::Expr, mutability: hir::Mutability, base: &hir::Expr) {
1049         debug!("link_addr_of(expr={:?}, base={:?})", expr, base);
1050
1051         let cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(base)));
1052
1053         debug!("link_addr_of: cmt={:?}", cmt);
1054
1055         self.link_region_from_node_type(expr.span, expr.hir_id, mutability, &cmt);
1056     }
1057
1058     /// Computes the guarantors for any ref bindings in a `let` and
1059     /// then ensures that the lifetime of the resulting pointer is
1060     /// linked to the lifetime of the initialization expression.
1061     fn link_local(&self, local: &hir::Local) {
1062         debug!("regionck::for_local()");
1063         let init_expr = match local.init {
1064             None => {
1065                 return;
1066             }
1067             Some(ref expr) => &**expr,
1068         };
1069         let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))));
1070         self.link_pattern(discr_cmt, &local.pat);
1071     }
1072
1073     /// Computes the guarantors for any ref bindings in a match and
1074     /// then ensures that the lifetime of the resulting pointer is
1075     /// linked to the lifetime of its guarantor (if any).
1076     fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) {
1077         debug!("regionck::for_match()");
1078         let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))));
1079         debug!("discr_cmt={:?}", discr_cmt);
1080         for arm in arms {
1081             for root_pat in &arm.pats {
1082                 self.link_pattern(discr_cmt.clone(), &root_pat);
1083             }
1084         }
1085     }
1086
1087     /// Computes the guarantors for any ref bindings in a match and
1088     /// then ensures that the lifetime of the resulting pointer is
1089     /// linked to the lifetime of its guarantor (if any).
1090     fn link_fn_args(&self, body_scope: region::Scope, args: &[hir::Arg]) {
1091         debug!("regionck::link_fn_args(body_scope={:?})", body_scope);
1092         for arg in args {
1093             let arg_ty = self.node_ty(arg.hir_id);
1094             let re_scope = self.tcx.mk_region(ty::ReScope(body_scope));
1095             let arg_cmt = self.with_mc(|mc| {
1096                 Rc::new(mc.cat_rvalue(arg.hir_id, arg.pat.span, re_scope, arg_ty))
1097             });
1098             debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, arg_cmt, arg);
1099             self.link_pattern(arg_cmt, &arg.pat);
1100         }
1101     }
1102
1103     /// Link lifetimes of any ref bindings in `root_pat` to the pointers found
1104     /// in the discriminant, if needed.
1105     fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) {
1106         debug!(
1107             "link_pattern(discr_cmt={:?}, root_pat={:?})",
1108             discr_cmt, root_pat
1109         );
1110         ignore_err!(self.with_mc(|mc| {
1111             mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, sub_pat| {
1112                 // `ref x` pattern
1113                 if let PatKind::Binding(..) = sub_pat.node {
1114                     if let Some(&bm) = mc.tables.pat_binding_modes().get(sub_pat.hir_id) {
1115                         if let ty::BindByReference(mutbl) = bm {
1116                             self.link_region_from_node_type(
1117                                 sub_pat.span,
1118                                 sub_pat.hir_id,
1119                                 mutbl,
1120                                 &sub_cmt,
1121                             );
1122                         }
1123                     } else {
1124                         self.tcx
1125                             .sess
1126                             .delay_span_bug(sub_pat.span, "missing binding mode");
1127                     }
1128                 }
1129             })
1130         }));
1131     }
1132
1133     /// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being
1134     /// autoref'd.
1135     fn link_autoref(
1136         &self,
1137         expr: &hir::Expr,
1138         expr_cmt: &mc::cmt_<'tcx>,
1139         autoref: &adjustment::AutoBorrow<'tcx>,
1140     ) {
1141         debug!(
1142             "link_autoref(autoref={:?}, expr_cmt={:?})",
1143             autoref, expr_cmt
1144         );
1145
1146         match *autoref {
1147             adjustment::AutoBorrow::Ref(r, m) => {
1148                 self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
1149             }
1150
1151             adjustment::AutoBorrow::RawPtr(m) => {
1152                 let r = self.tcx.mk_region(ty::ReScope(region::Scope {
1153                     id: expr.hir_id.local_id,
1154                     data: region::ScopeData::Node,
1155                 }));
1156                 self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt);
1157             }
1158         }
1159     }
1160
1161     /// Like `link_region()`, except that the region is extracted from the type of `id`,
1162     /// which must be some reference (`&T`, `&str`, etc).
1163     fn link_region_from_node_type(
1164         &self,
1165         span: Span,
1166         id: hir::HirId,
1167         mutbl: hir::Mutability,
1168         cmt_borrowed: &mc::cmt_<'tcx>,
1169     ) {
1170         debug!(
1171             "link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})",
1172             id, mutbl, cmt_borrowed
1173         );
1174
1175         let rptr_ty = self.resolve_node_type(id);
1176         if let ty::Ref(r, _, _) = rptr_ty.sty {
1177             debug!("rptr_ty={}", rptr_ty);
1178             self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed);
1179         }
1180     }
1181
1182     /// Informs the inference engine that `borrow_cmt` is being borrowed with
1183     /// kind `borrow_kind` and lifetime `borrow_region`.
1184     /// In order to ensure borrowck is satisfied, this may create constraints
1185     /// between regions, as explained in `link_reborrowed_region()`.
1186     fn link_region(
1187         &self,
1188         span: Span,
1189         borrow_region: ty::Region<'tcx>,
1190         borrow_kind: ty::BorrowKind,
1191         borrow_cmt: &mc::cmt_<'tcx>,
1192     ) {
1193         let origin = infer::DataBorrowed(borrow_cmt.ty, span);
1194         self.type_must_outlive(origin, borrow_cmt.ty, borrow_region);
1195
1196         let mut borrow_kind = borrow_kind;
1197         let mut borrow_cmt_cat = borrow_cmt.cat.clone();
1198
1199         loop {
1200             debug!(
1201                 "link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})",
1202                 borrow_region, borrow_kind, borrow_cmt
1203             );
1204             match borrow_cmt_cat {
1205                 Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => {
1206                     match self.link_reborrowed_region(
1207                         span,
1208                         borrow_region,
1209                         borrow_kind,
1210                         ref_cmt,
1211                         ref_region,
1212                         ref_kind,
1213                         borrow_cmt.note,
1214                     ) {
1215                         Some((c, k)) => {
1216                             borrow_cmt_cat = c.cat.clone();
1217                             borrow_kind = k;
1218                         }
1219                         None => {
1220                             return;
1221                         }
1222                     }
1223                 }
1224
1225                 Categorization::Downcast(cmt_base, _)
1226                 | Categorization::Deref(cmt_base, mc::Unique)
1227                 | Categorization::Interior(cmt_base, _) => {
1228                     // Borrowing interior or owned data requires the base
1229                     // to be valid and borrowable in the same fashion.
1230                     borrow_cmt_cat = cmt_base.cat.clone();
1231                     borrow_kind = borrow_kind;
1232                 }
1233
1234                 Categorization::Deref(_, mc::UnsafePtr(..))
1235                 | Categorization::StaticItem
1236                 | Categorization::Upvar(..)
1237                 | Categorization::Local(..)
1238                 | Categorization::ThreadLocal(..)
1239                 | Categorization::Rvalue(..) => {
1240                     // These are all "base cases" with independent lifetimes
1241                     // that are not subject to inference
1242                     return;
1243                 }
1244             }
1245         }
1246     }
1247
1248     /// This is the most complicated case: the path being borrowed is
1249     /// itself the referent of a borrowed pointer. Let me give an
1250     /// example fragment of code to make clear(er) the situation:
1251     ///
1252     ///    let r: &'a mut T = ...;  // the original reference "r" has lifetime 'a
1253     ///    ...
1254     ///    &'z *r                   // the reborrow has lifetime 'z
1255     ///
1256     /// Now, in this case, our primary job is to add the inference
1257     /// constraint that `'z <= 'a`. Given this setup, let's clarify the
1258     /// parameters in (roughly) terms of the example:
1259     ///
1260     /// ```plain,ignore (pseudo-Rust)
1261     ///     A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T`
1262     ///     borrow_region   ^~                 ref_region    ^~
1263     ///     borrow_kind        ^~               ref_kind        ^~
1264     ///     ref_cmt                 ^
1265     /// ```
1266     ///
1267     /// Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc).
1268     ///
1269     /// Unfortunately, there are some complications beyond the simple
1270     /// scenario I just painted:
1271     ///
1272     /// 1. The reference `r` might in fact be a "by-ref" upvar. In that
1273     ///    case, we have two jobs. First, we are inferring whether this reference
1274     ///    should be an `&T`, `&mut T`, or `&uniq T` reference, and we must
1275     ///    adjust that based on this borrow (e.g., if this is an `&mut` borrow,
1276     ///    then `r` must be an `&mut` reference). Second, whenever we link
1277     ///    two regions (here, `'z <= 'a`), we supply a *cause*, and in this
1278     ///    case we adjust the cause to indicate that the reference being
1279     ///    "reborrowed" is itself an upvar. This provides a nicer error message
1280     ///    should something go wrong.
1281     ///
1282     /// 2. There may in fact be more levels of reborrowing. In the
1283     ///    example, I said the borrow was like `&'z *r`, but it might
1284     ///    in fact be a borrow like `&'z **q` where `q` has type `&'a
1285     ///    &'b mut T`. In that case, we want to ensure that `'z <= 'a`
1286     ///    and `'z <= 'b`. This is explained more below.
1287     ///
1288     /// The return value of this function indicates whether we need to
1289     /// recurse and process `ref_cmt` (see case 2 above).
1290     fn link_reborrowed_region(
1291         &self,
1292         span: Span,
1293         borrow_region: ty::Region<'tcx>,
1294         borrow_kind: ty::BorrowKind,
1295         ref_cmt: mc::cmt<'tcx>,
1296         ref_region: ty::Region<'tcx>,
1297         mut ref_kind: ty::BorrowKind,
1298         note: mc::Note,
1299     ) -> Option<(mc::cmt<'tcx>, ty::BorrowKind)> {
1300         // Possible upvar ID we may need later to create an entry in the
1301         // maybe link map.
1302
1303         // Detect by-ref upvar `x`:
1304         let cause = match note {
1305             mc::NoteUpvarRef(ref upvar_id) => {
1306                 match self.tables.borrow().upvar_capture_map.get(upvar_id) {
1307                     Some(&ty::UpvarCapture::ByRef(ref upvar_borrow)) => {
1308                         // The mutability of the upvar may have been modified
1309                         // by the above adjustment, so update our local variable.
1310                         ref_kind = upvar_borrow.kind;
1311
1312                         infer::ReborrowUpvar(span, *upvar_id)
1313                     }
1314                     _ => {
1315                         span_bug!(span, "Illegal upvar id: {:?}", upvar_id);
1316                     }
1317                 }
1318             }
1319             mc::NoteClosureEnv(ref upvar_id) => {
1320                 // We don't have any mutability changes to propagate, but
1321                 // we do want to note that an upvar reborrow caused this
1322                 // link
1323                 infer::ReborrowUpvar(span, *upvar_id)
1324             }
1325             _ => infer::Reborrow(span),
1326         };
1327
1328         debug!(
1329             "link_reborrowed_region: {:?} <= {:?}",
1330             borrow_region, ref_region
1331         );
1332         self.sub_regions(cause, borrow_region, ref_region);
1333
1334         // If we end up needing to recurse and establish a region link
1335         // with `ref_cmt`, calculate what borrow kind we will end up
1336         // needing. This will be used below.
1337         //
1338         // One interesting twist is that we can weaken the borrow kind
1339         // when we recurse: to reborrow an `&mut` referent as mutable,
1340         // borrowck requires a unique path to the `&mut` reference but not
1341         // necessarily a *mutable* path.
1342         let new_borrow_kind = match borrow_kind {
1343             ty::ImmBorrow => ty::ImmBorrow,
1344             ty::MutBorrow | ty::UniqueImmBorrow => ty::UniqueImmBorrow,
1345         };
1346
1347         // Decide whether we need to recurse and link any regions within
1348         // the `ref_cmt`. This is concerned for the case where the value
1349         // being reborrowed is in fact a borrowed pointer found within
1350         // another borrowed pointer. For example:
1351         //
1352         //    let p: &'b &'a mut T = ...;
1353         //    ...
1354         //    &'z **p
1355         //
1356         // What makes this case particularly tricky is that, if the data
1357         // being borrowed is a `&mut` or `&uniq` borrow, borrowck requires
1358         // not only that `'z <= 'a`, (as before) but also `'z <= 'b`
1359         // (otherwise the user might mutate through the `&mut T` reference
1360         // after `'b` expires and invalidate the borrow we are looking at
1361         // now).
1362         //
1363         // So let's re-examine our parameters in light of this more
1364         // complicated (possible) scenario:
1365         //
1366         //     A borrow of: `& 'z bk * * p` where `p` has type `&'b bk & 'a bk T`
1367         //     borrow_region   ^~                 ref_region             ^~
1368         //     borrow_kind        ^~               ref_kind                 ^~
1369         //     ref_cmt                 ^~~
1370         //
1371         // (Note that since we have not examined `ref_cmt.cat`, we don't
1372         // know whether this scenario has occurred; but I wanted to show
1373         // how all the types get adjusted.)
1374         match ref_kind {
1375             ty::ImmBorrow => {
1376                 // The reference being reborrowed is a shareable ref of
1377                 // type `&'a T`. In this case, it doesn't matter where we
1378                 // *found* the `&T` pointer, the memory it references will
1379                 // be valid and immutable for `'a`. So we can stop here.
1380                 //
1381                 // (Note that the `borrow_kind` must also be ImmBorrow or
1382                 // else the user is borrowed imm memory as mut memory,
1383                 // which means they'll get an error downstream in borrowck
1384                 // anyhow.)
1385                 return None;
1386             }
1387
1388             ty::MutBorrow | ty::UniqueImmBorrow => {
1389                 // The reference being reborrowed is either an `&mut T` or
1390                 // `&uniq T`. This is the case where recursion is needed.
1391                 return Some((ref_cmt, new_borrow_kind));
1392             }
1393         }
1394     }
1395
1396     /// Checks that the values provided for type/region arguments in a given
1397     /// expression are well-formed and in-scope.
1398     fn substs_wf_in_scope(
1399         &mut self,
1400         origin: infer::ParameterOrigin,
1401         substs: SubstsRef<'tcx>,
1402         expr_span: Span,
1403         expr_region: ty::Region<'tcx>,
1404     ) {
1405         debug!(
1406             "substs_wf_in_scope(substs={:?}, \
1407              expr_region={:?}, \
1408              origin={:?}, \
1409              expr_span={:?})",
1410             substs, expr_region, origin, expr_span
1411         );
1412
1413         let origin = infer::ParameterInScope(origin, expr_span);
1414
1415         for kind in substs {
1416             match kind.unpack() {
1417                 UnpackedKind::Lifetime(lt) => {
1418                     self.sub_regions(origin.clone(), expr_region, lt);
1419                 }
1420                 UnpackedKind::Type(ty) => {
1421                     let ty = self.resolve_type(ty);
1422                     self.type_must_outlive(origin.clone(), ty, expr_region);
1423                 }
1424                 UnpackedKind::Const(_) => {
1425                     // Const parameters don't impose constraints.
1426                 }
1427             }
1428         }
1429     }
1430 }