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.
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.
13 The region check is a final pass that runs over the AST after we have
14 inferred the type constraints but before we have actually finalized
15 the types. Its purpose is to embed a variety of region constraints.
16 Inserting these constraints as a separate pass is good because (1) it
17 localizes the code that has to do with region inference and (2) often
18 we cannot know what constraints are needed until the basic types have
21 ### Interaction with the borrow checker
23 In general, the job of the borrowck module (which runs later) is to
24 check that all soundness criteria are met, given a particular set of
25 regions. The job of *this* module is to anticipate the needs of the
26 borrow checker and infer regions that will satisfy its requirements.
27 It is generally true that the inference doesn't need to be sound,
28 meaning that if there is a bug and we inferred bad regions, the borrow
29 checker should catch it. This is not entirely true though; for
30 example, the borrow checker doesn't check subtyping, and it doesn't
31 check that region pointers are always live when they are used. It
32 might be worthwhile to fix this so that borrowck serves as a kind of
33 verification step -- that would add confidence in the overall
34 correctness of the compiler, at the cost of duplicating some type
37 ### Inferring the duration of borrows, automatic and otherwise
39 Whenever we introduce a borrowed pointer, for example as the result of
40 a borrow expression `let x = &data`, the lifetime of the pointer `x`
41 is always specified as a region inference variable. `regionck` has the
42 job of adding constraints such that this inference variable is as
43 narrow as possible while still accommodating all uses (that is, every
44 dereference of the resulting pointer must be within the lifetime).
48 Generally speaking, `regionck` does NOT try to ensure that the data
49 `data` will outlive the pointer `x`. That is the job of borrowck. The
50 one exception is when "re-borrowing" the contents of another borrowed
51 pointer. For example, imagine you have a borrowed pointer `b` with
52 lifetime L1 and you have an expression `&*b`. The result of this
53 expression will be another borrowed pointer with lifetime L2 (which is
54 an inference variable). The borrow checker is going to enforce the
55 constraint that L2 < L1, because otherwise you are re-borrowing data
56 for a lifetime larger than the original loan. However, without the
57 routines in this module, the region inferencer would not know of this
58 dependency and thus it might infer the lifetime of L2 to be greater
59 than L1 (issue #3148).
61 There are a number of troublesome scenarios in the tests
62 `region-dependent-*.rs`, but here is one example:
65 struct Bar { foo: Foo }
66 fn get_i(x: &'a Bar) -> &'a int {
67 let foo = &x.foo; // Lifetime L1
71 Note that this comes up either with `&` expressions, `ref`
72 bindings, and `autorefs`, which are the three ways to introduce
75 The key point here is that when you are borrowing a value that
76 is "guaranteed" by a borrowed pointer, you must link the
77 lifetime of that borrowed pointer (L1, here) to the lifetime of
78 the borrow itself (L2). What do I mean by "guaranteed" by a
79 borrowed pointer? I mean any data that is reached by first
80 dereferencing a borrowed pointer and then either traversing
81 interior offsets or owned pointers. We say that the guarantor
82 of such data it the region of the borrowed pointer that was
83 traversed. This is essentially the same as the ownership
84 relation, except that a borrowed pointer never owns its
87 ### Inferring borrow kinds for upvars
89 Whenever there is a closure expression, we need to determine how each
90 upvar is used. We do this by initially assigning each upvar an
91 immutable "borrow kind" (see `ty::BorrowKind` for details) and then
92 "escalating" the kind as needed. The borrow kind proceeds according to
93 the following lattice:
95 ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
97 So, for example, if we see an assignment `x = 5` to an upvar `x`, we
98 will promote its borrow kind to mutable borrow. If we see an `&mut x`
99 we'll do the same. Naturally, this applies not just to the upvar, but
100 to everything owned by `x`, so the result is the same for something
101 like `x.f = 5` and so on (presuming `x` is not a borrowed pointer to a
102 struct). These adjustments are performed in
103 `adjust_upvar_borrow_kind()` (you can trace backwards through the code
106 The fact that we are inferring borrow kinds as we go results in a
107 semi-hacky interaction with mem-categorization. In particular,
108 mem-categorization will query the current borrow kind as it
109 categorizes, and we'll return the *current* value, but this may get
110 adjusted later. Therefore, in this module, we generally ignore the
111 borrow kind (and derived mutabilities) that are returned from
112 mem-categorization, since they may be inaccurate. (Another option
113 would be to use a unification scheme, where instead of returning a
114 concrete borrow kind like `ty::ImmBorrow`, we return a
115 `ty::InferBorrow(upvar_id)` or something like that, but this would
116 then mean that all later passes would have to check for these figments
117 and report an error, and it just seems like more mess in the end.)
122 use middle::def::{DefArg, DefBinding, DefLocal, DefUpvar};
123 use middle::freevars;
124 use middle::mem_categorization as mc;
125 use middle::ty::{ReScope};
127 use middle::typeck::astconv::AstConv;
128 use middle::typeck::check::FnCtxt;
129 use middle::typeck::check::regionmanip;
130 use middle::typeck::infer::resolve_and_force_all_but_regions;
131 use middle::typeck::infer::resolve_type;
132 use middle::typeck::infer;
133 use middle::typeck::MethodCall;
134 use middle::pat_util;
135 use util::nodemap::{DefIdMap, NodeMap};
136 use util::ppaux::{ty_to_string, Repr};
139 use syntax::codemap::Span;
141 use syntax::visit::Visitor;
143 use std::cell::RefCell;
145 ///////////////////////////////////////////////////////////////////////////
146 // PUBLIC ENTRY POINTS
148 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
149 let mut rcx = Rcx::new(fcx, e.id);
150 if fcx.err_count_since_creation() == 0 {
151 // regionck assumes typeck succeeded
153 rcx.visit_region_obligations(e.id);
155 fcx.infcx().resolve_regions_and_report_errors();
158 pub fn regionck_type_defn(fcx: &FnCtxt,
160 component_tys: &[ty::t]) {
161 let mut rcx = Rcx::new(fcx, 0);
162 for &component_ty in component_tys.iter() {
163 // Check that each type outlives the empty region. Since the
164 // empty region is a subregion of all others, this can't fail
165 // unless the type does not meet the well-formedness
167 type_must_outlive(&mut rcx, infer::RelateRegionParamBound(span),
168 component_ty, ty::ReEmpty);
170 fcx.infcx().resolve_regions_and_report_errors();
173 pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, blk: &ast::Block) {
174 let mut rcx = Rcx::new(fcx, blk.id);
175 if fcx.err_count_since_creation() == 0 {
176 // regionck assumes typeck succeeded
177 rcx.visit_fn_body(id, blk);
179 fcx.infcx().resolve_regions_and_report_errors();
182 ///////////////////////////////////////////////////////////////////////////
185 // If mem categorization results in an error, it's because the type
186 // check failed (or will fail, when the error is uncovered and
187 // reported during writeback). In this case, we just ignore this part
188 // of the code and don't try to add any more region constraints.
189 macro_rules! ignore_err(
198 pub struct Rcx<'a, 'tcx: 'a> {
199 fcx: &'a FnCtxt<'a, 'tcx>,
201 region_param_pairs: Vec<(ty::Region, ty::ParamTy)>,
203 // id of innermost fn or loop
204 repeating_scope: ast::NodeId,
207 /// When entering a function, we can derive relationships from the
208 /// signature between various regions and type parameters. Consider
211 /// fn foo<'a, A>(x: &'a A) { ... }
213 /// Here, we can derive that `A` must outlive `'a`, because otherwise
214 /// the caller would be illegal. We record this by storing a series of
215 /// pairs (in this case, `('a, A)`). These pairs will be consulted
216 /// later during regionck.
218 /// In the case of nested fns, additional relationships may be
219 /// derived. The result is a link list walking up the stack (hence
220 /// the `previous` field).
222 pub struct RegionSubParamConstraints<'a> {
223 pairs: Vec<(ty::Region, ty::ParamTy)>,
224 previous: Option<&'a RegionSubParamConstraints<'a>>,
227 fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
229 * Returns the validity region of `def` -- that is, how long
235 DefLocal(node_id, _) | DefArg(node_id, _) |
236 DefBinding(node_id, _) => {
237 tcx.region_maps.var_region(node_id)
239 DefUpvar(_, subdef, closure_id, body_id) => {
240 match ty::ty_closure_store(fcx.node_ty(closure_id)) {
241 ty::RegionTraitStore(..) => region_of_def(fcx, *subdef),
242 ty::UniqTraitStore => ReScope(body_id)
246 tcx.sess.bug(format!("unexpected def in region_of_def: {:?}",
252 impl<'a, 'tcx> Rcx<'a, 'tcx> {
253 pub fn new(fcx: &'a FnCtxt<'a, 'tcx>,
254 initial_repeating_scope: ast::NodeId) -> Rcx<'a, 'tcx> {
256 repeating_scope: initial_repeating_scope,
257 region_param_pairs: Vec::new() }
260 pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
264 pub fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId {
265 let old_scope = self.repeating_scope;
266 self.repeating_scope = scope;
270 pub fn resolve_type(&self, unresolved_ty: ty::t) -> ty::t {
272 * Try to resolve the type for the given node, returning
273 * t_err if an error results. Note that we never care
274 * about the details of the error, the same error will be
275 * detected and reported in the writeback phase.
277 * Note one important point: we do not attempt to resolve
278 * *region variables* here. This is because regionck is
279 * essentially adding constraints to those region variables
280 * and so may yet influence how they are resolved.
282 * Consider this silly example:
284 * fn borrow(x: &int) -> &int {x}
285 * fn foo(x: @int) -> int { // block: B
286 * let b = borrow(x); // region: <R0>
290 * Here, the region of `b` will be `<R0>`. `<R0>` is
291 * constrainted to be some subregion of the block B and some
292 * superregion of the call. If we forced it now, we'd choose
293 * the smaller region (the call). But that would make the *b
294 * illegal. Since we don't resolve, the type of b will be
295 * `&<R0>.int` and then `*b` will require that `<R0>` be
296 * bigger than the let and the `*b` expression, so we will
297 * effectively resolve `<R0>` to be the block B.
299 match resolve_type(self.fcx.infcx(), None, unresolved_ty,
300 resolve_and_force_all_but_regions) {
302 Err(_) => ty::mk_err()
306 /// Try to resolve the type for the given node.
307 fn resolve_node_type(&self, id: ast::NodeId) -> ty::t {
308 let t = self.fcx.node_ty(id);
312 fn resolve_method_type(&self, method_call: MethodCall) -> Option<ty::t> {
313 let method_ty = self.fcx.inh.method_map.borrow()
314 .find(&method_call).map(|method| method.ty);
315 method_ty.map(|method_ty| self.resolve_type(method_ty))
318 /// Try to resolve the type for the given node.
319 pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> ty::t {
320 let ty_unadjusted = self.resolve_node_type(expr.id);
321 if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) {
324 let tcx = self.fcx.tcx();
325 ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
326 self.fcx.inh.adjustments.borrow().find(&expr.id),
327 |method_call| self.resolve_method_type(method_call))
331 fn visit_fn_body(&mut self,
335 // When we enter a function, we can derive
337 let fn_sig_map = self.fcx.inh.fn_sig_map.borrow();
338 let fn_sig = match fn_sig_map.find(&id) {
342 format!("No fn-sig entry for id={}", id).as_slice());
346 let len = self.region_param_pairs.len();
347 self.relate_free_regions(fn_sig.as_slice(), body.id);
348 self.visit_block(body);
349 self.visit_region_obligations(body.id);
350 self.region_param_pairs.truncate(len);
353 fn visit_region_obligations(&mut self, node_id: ast::NodeId)
355 debug!("visit_region_obligations: node_id={}", node_id);
356 let region_obligations = self.fcx.inh.region_obligations.borrow();
357 match region_obligations.find(&node_id) {
360 for r_o in vec.iter() {
361 debug!("visit_region_obligations: r_o={}",
362 r_o.repr(self.tcx()));
363 let sup_type = self.resolve_type(r_o.sup_type);
364 type_must_outlive(self, r_o.origin.clone(),
365 sup_type, r_o.sub_region);
371 fn relate_free_regions(&mut self,
372 fn_sig_tys: &[ty::t],
373 body_id: ast::NodeId) {
375 * This method populates the region map's `free_region_map`.
376 * It walks over the transformed argument and return types for
377 * each function just before we check the body of that
378 * function, looking for types where you have a borrowed
379 * pointer to other borrowed data (e.g., `&'a &'b [uint]`. We
380 * do not allow references to outlive the things they point
381 * at, so we can assume that `'a <= 'b`. This holds for both
382 * the argument and return types, basically because, on the caller
383 * side, the caller is responsible for checking that the type of
384 * every expression (including the actual values for the arguments,
385 * as well as the return type of the fn call) is well-formed.
387 * Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs`
390 debug!("relate_free_regions >>");
391 let tcx = self.tcx();
393 for &ty in fn_sig_tys.iter() {
394 let ty = self.resolve_type(ty);
395 debug!("relate_free_regions(t={})", ty.repr(tcx));
396 let body_scope = ty::ReScope(body_id);
398 regionmanip::region_wf_constraints(
402 for constraint in constraints.iter() {
403 debug!("constraint: {}", constraint.repr(tcx));
405 regionmanip::RegionSubRegionConstraint(_,
407 ty::ReFree(free_b)) => {
408 tcx.region_maps.relate_free_regions(free_a, free_b);
410 regionmanip::RegionSubRegionConstraint(_,
412 ty::ReInfer(ty::ReVar(vid_b))) => {
413 self.fcx.inh.infcx.add_given(free_a, vid_b);
415 regionmanip::RegionSubRegionConstraint(..) => {
416 // In principle, we could record (and take
417 // advantage of) every relationship here, but
418 // we are also free not to -- it simply means
419 // strictly less that we can successfully type
420 // check. (It may also be that we should
421 // revise our inference system to be more
422 // general and to make use of *every*
423 // relationship that arises here, but
424 // presently we do not.)
426 regionmanip::RegionSubParamConstraint(_, r_a, p_b) => {
427 debug!("RegionSubParamConstraint: {} <= {}",
428 r_a.repr(tcx), p_b.repr(tcx));
430 self.region_param_pairs.push((r_a, p_b));
436 debug!("<< relate_free_regions");
440 impl<'fcx, 'tcx> mc::Typer<'tcx> for Rcx<'fcx, 'tcx> {
441 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
445 fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
446 let t = self.resolve_node_type(id);
447 if ty::type_is_error(t) {Err(())} else {Ok(t)}
450 fn node_method_ty(&self, method_call: MethodCall) -> Option<ty::t> {
451 self.resolve_method_type(method_call)
454 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
455 &self.fcx.inh.adjustments
458 fn is_method_call(&self, id: ast::NodeId) -> bool {
459 self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
462 fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
463 self.tcx().region_maps.temporary_scope(id)
466 fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
467 self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
470 fn capture_mode(&self, closure_expr_id: ast::NodeId)
471 -> freevars::CaptureMode {
472 self.tcx().capture_modes.borrow().get_copy(&closure_expr_id)
475 fn unboxed_closures<'a>(&'a self)
476 -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
477 &self.fcx.inh.unboxed_closures
481 impl<'a, 'tcx, 'v> Visitor<'v> for Rcx<'a, 'tcx> {
482 // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
483 // However, right now we run into an issue whereby some free
484 // regions are not properly related if they appear within the
485 // types of arguments that must be inferred. This could be
486 // addressed by deferring the construction of the region
487 // hierarchy, and in particular the relationships between free
488 // regions, until regionck, as described in #3238.
490 fn visit_fn(&mut self, _fk: visit::FnKind<'v>, _fd: &'v ast::FnDecl,
491 b: &'v ast::Block, _s: Span, id: ast::NodeId) {
492 self.visit_fn_body(id, b)
495 fn visit_item(&mut self, i: &ast::Item) { visit_item(self, i); }
497 fn visit_expr(&mut self, ex: &ast::Expr) { visit_expr(self, ex); }
499 //visit_pat: visit_pat, // (..) see above
501 fn visit_arm(&mut self, a: &ast::Arm) { visit_arm(self, a); }
503 fn visit_local(&mut self, l: &ast::Local) { visit_local(self, l); }
505 fn visit_block(&mut self, b: &ast::Block) { visit_block(self, b); }
508 fn visit_item(_rcx: &mut Rcx, _item: &ast::Item) {
512 fn visit_block(rcx: &mut Rcx, b: &ast::Block) {
513 visit::walk_block(rcx, b);
516 fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) {
518 for p in arm.pats.iter() {
519 constrain_bindings_in_pat(&**p, rcx);
522 visit::walk_arm(rcx, arm);
525 fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
527 constrain_bindings_in_pat(&*l.pat, rcx);
529 visit::walk_local(rcx, l);
532 fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
533 let tcx = rcx.fcx.tcx();
534 debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
535 pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
536 // If we have a variable that contains region'd data, that
537 // data will be accessible from anywhere that the variable is
538 // accessed. We must be wary of loops like this:
540 // // from src/test/compile-fail/borrowck-lend-flow.rs
541 // let mut v = box 3, w = box 4;
542 // let mut x = &mut w;
545 // borrow(v); //~ ERROR cannot borrow
546 // x = &mut v; // (1)
549 // Typically, we try to determine the region of a borrow from
550 // those points where it is dereferenced. In this case, one
551 // might imagine that the lifetime of `x` need only be the
552 // body of the loop. But of course this is incorrect because
553 // the pointer that is created at point (1) is consumed at
554 // point (2), meaning that it must be live across the loop
555 // iteration. The easiest way to guarantee this is to require
556 // that the lifetime of any regions that appear in a
557 // variable's type enclose at least the variable's scope.
559 let var_region = tcx.region_maps.var_region(id);
560 type_of_node_must_outlive(
561 rcx, infer::BindingTypeIsNotValidAtDecl(span),
566 fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
567 debug!("regionck::visit_expr(e={}, repeating_scope={:?})",
568 expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
570 // No matter what, the type of each expression must outlive the
571 // scope of that expression. This also guarantees basic WF.
572 let expr_ty = rcx.resolve_node_type(expr.id);
574 type_must_outlive(rcx, infer::ExprTypeIsNotInScope(expr_ty, expr.span),
575 expr_ty, ty::ReScope(expr.id));
577 let method_call = MethodCall::expr(expr.id);
578 let has_method_map = rcx.fcx.inh.method_map.borrow().contains_key(&method_call);
580 // Check any autoderefs or autorefs that appear.
581 for &adjustment in rcx.fcx.inh.adjustments.borrow().find(&expr.id).iter() {
582 debug!("adjustment={:?}", adjustment);
584 ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: ref opt_autoref}) => {
585 let expr_ty = rcx.resolve_node_type(expr.id);
586 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
587 for autoref in opt_autoref.iter() {
588 link_autoref(rcx, expr, autoderefs, autoref);
590 // Require that the resulting region encompasses
593 // FIXME(#6268) remove to support nested method calls
594 type_of_node_must_outlive(
595 rcx, infer::AutoBorrow(expr.span),
596 expr.id, ty::ReScope(expr.id));
600 ty::AutoObject(_, ref bounds, _, _) => {
601 // Determine if we are casting `expr` to a trait
602 // instance. If so, we have to be sure that the type
603 // of the source obeys the new region bound.
604 let source_ty = rcx.resolve_node_type(expr.id);
605 type_must_outlive(rcx, infer::RelateObjectBound(expr.span),
606 source_ty, bounds.region_bound);
614 ast::ExprCall(ref callee, ref args) => {
616 constrain_call(rcx, expr, Some(&**callee),
617 args.iter().map(|e| &**e), false);
619 constrain_callee(rcx, callee.id, expr, &**callee);
620 constrain_call(rcx, expr, None,
621 args.iter().map(|e| &**e), false);
624 visit::walk_expr(rcx, expr);
627 ast::ExprMethodCall(_, _, ref args) => {
628 constrain_call(rcx, expr, Some(&**args.get(0)),
629 args.slice_from(1).iter().map(|e| &**e), false);
631 visit::walk_expr(rcx, expr);
634 ast::ExprAssign(ref lhs, _) => {
635 adjust_borrow_kind_for_assignment_lhs(rcx, &**lhs);
636 visit::walk_expr(rcx, expr);
639 ast::ExprAssignOp(_, ref lhs, ref rhs) => {
641 constrain_call(rcx, expr, Some(&**lhs),
642 Some(&**rhs).move_iter(), true);
645 adjust_borrow_kind_for_assignment_lhs(rcx, &**lhs);
647 visit::walk_expr(rcx, expr);
650 ast::ExprIndex(ref lhs, ref rhs) |
651 ast::ExprBinary(_, ref lhs, ref rhs) if has_method_map => {
652 // As `expr_method_call`, but the call is via an
653 // overloaded op. Note that we (sadly) currently use an
654 // implicit "by ref" sort of passing style here. This
655 // should be converted to an adjustment!
656 constrain_call(rcx, expr, Some(&**lhs),
657 Some(&**rhs).move_iter(), true);
659 visit::walk_expr(rcx, expr);
662 ast::ExprUnary(_, ref lhs) if has_method_map => {
664 constrain_call(rcx, expr, Some(&**lhs),
665 None::<ast::Expr>.iter(), true);
667 visit::walk_expr(rcx, expr);
670 ast::ExprUnary(ast::UnBox, ref base) => {
671 // Managed data must not have borrowed pointers within it:
672 let base_ty = rcx.resolve_node_type(base.id);
673 type_must_outlive(rcx, infer::Managed(expr.span),
674 base_ty, ty::ReStatic);
675 visit::walk_expr(rcx, expr);
678 ast::ExprUnary(ast::UnDeref, ref base) => {
679 // For *a, the lifetime of a must enclose the deref
680 let method_call = MethodCall::expr(expr.id);
681 let base_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
683 constrain_call(rcx, expr, Some(&**base),
684 None::<ast::Expr>.iter(), true);
685 ty::ty_fn_ret(method.ty)
687 None => rcx.resolve_node_type(base.id)
689 match ty::get(base_ty).sty {
690 ty::ty_rptr(r_ptr, _) => {
691 mk_subregion_due_to_dereference(rcx, expr.span,
692 ty::ReScope(expr.id), r_ptr);
697 visit::walk_expr(rcx, expr);
700 ast::ExprIndex(ref vec_expr, _) => {
701 // For a[b], the lifetime of a must enclose the deref
702 let vec_type = rcx.resolve_expr_type_adjusted(&**vec_expr);
703 constrain_index(rcx, expr, vec_type);
705 visit::walk_expr(rcx, expr);
708 ast::ExprCast(ref source, _) => {
709 // Determine if we are casting `source` to a trait
710 // instance. If so, we have to be sure that the type of
711 // the source obeys the trait's region bound.
712 constrain_cast(rcx, expr, &**source);
713 visit::walk_expr(rcx, expr);
716 ast::ExprAddrOf(m, ref base) => {
717 link_addr_of(rcx, expr, m, &**base);
719 // Require that when you write a `&expr` expression, the
720 // resulting pointer has a lifetime that encompasses the
721 // `&expr` expression itself. Note that we constraining
722 // the type of the node expr.id here *before applying
725 // FIXME(#6268) nested method calls requires that this rule change
726 let ty0 = rcx.resolve_node_type(expr.id);
727 type_must_outlive(rcx, infer::AddrOf(expr.span),
728 ty0, ty::ReScope(expr.id));
729 visit::walk_expr(rcx, expr);
732 ast::ExprMatch(ref discr, ref arms) => {
733 link_match(rcx, &**discr, arms.as_slice());
735 visit::walk_expr(rcx, expr);
738 ast::ExprFnBlock(_, _, ref body) |
739 ast::ExprProc(_, ref body) |
740 ast::ExprUnboxedFn(_, _, _, ref body) => {
741 check_expr_fn_block(rcx, expr, &**body);
744 ast::ExprLoop(ref body, _) => {
745 let repeating_scope = rcx.set_repeating_scope(body.id);
746 visit::walk_expr(rcx, expr);
747 rcx.set_repeating_scope(repeating_scope);
750 ast::ExprWhile(ref cond, ref body, _) => {
751 let repeating_scope = rcx.set_repeating_scope(cond.id);
752 rcx.visit_expr(&**cond);
754 rcx.set_repeating_scope(body.id);
755 rcx.visit_block(&**body);
757 rcx.set_repeating_scope(repeating_scope);
760 ast::ExprForLoop(ref pat, ref head, ref body, _) => {
761 constrain_bindings_in_pat(&**pat, rcx);
764 let mc = mc::MemCategorizationContext::new(rcx);
765 let head_cmt = ignore_err!(mc.cat_expr(&**head));
766 link_pattern(rcx, mc, head_cmt, &**pat);
769 rcx.visit_expr(&**head);
770 type_of_node_must_outlive(rcx,
771 infer::AddrOf(expr.span),
773 ty::ReScope(expr.id));
775 let repeating_scope = rcx.set_repeating_scope(body.id);
776 rcx.visit_block(&**body);
777 rcx.set_repeating_scope(repeating_scope);
781 visit::walk_expr(rcx, expr);
786 fn constrain_cast(rcx: &mut Rcx,
787 cast_expr: &ast::Expr,
788 source_expr: &ast::Expr)
790 debug!("constrain_cast(cast_expr={}, source_expr={})",
791 cast_expr.repr(rcx.tcx()),
792 source_expr.repr(rcx.tcx()));
794 let source_ty = rcx.resolve_node_type(source_expr.id);
795 let target_ty = rcx.resolve_node_type(cast_expr.id);
797 walk_cast(rcx, cast_expr, source_ty, target_ty);
799 fn walk_cast(rcx: &mut Rcx,
800 cast_expr: &ast::Expr,
803 debug!("walk_cast(from_ty={}, to_ty={})",
804 from_ty.repr(rcx.tcx()),
805 to_ty.repr(rcx.tcx()));
806 match (&ty::get(from_ty).sty, &ty::get(to_ty).sty) {
807 /*From:*/ (&ty::ty_rptr(from_r, ref from_mt),
808 /*To: */ &ty::ty_rptr(to_r, ref to_mt)) => {
809 // Target cannot outlive source, naturally.
810 rcx.fcx.mk_subr(infer::Reborrow(cast_expr.span), to_r, from_r);
811 walk_cast(rcx, cast_expr, from_mt.ty, to_mt.ty);
815 /*To: */ &ty::ty_trait(box ty::TyTrait { bounds, .. })) => {
816 // When T is existentially quantified as a trait
817 // `Foo+'to`, it must outlive the region bound `'to`.
818 type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
819 from_ty, bounds.region_bound);
822 /*From:*/ (&ty::ty_uniq(from_referent_ty),
823 /*To: */ &ty::ty_uniq(to_referent_ty)) => {
824 walk_cast(rcx, cast_expr, from_referent_ty, to_referent_ty);
832 fn check_expr_fn_block(rcx: &mut Rcx,
835 let tcx = rcx.fcx.tcx();
836 let function_type = rcx.resolve_node_type(expr.id);
838 match ty::get(function_type).sty {
839 ty::ty_closure(box ty::ClosureTy{store: ty::RegionTraitStore(..),
842 // For closure, ensure that the variables outlive region
843 // bound, since they are captured by reference.
844 freevars::with_freevars(tcx, expr.id, |freevars| {
845 if freevars.is_empty() {
846 // No free variables means that the environment
847 // will be NULL at runtime and hence the closure
848 // has static lifetime.
850 // Variables being referenced must outlive closure.
851 constrain_free_variables_in_stack_closure(
852 rcx, bounds.region_bound, expr, freevars);
854 // Closure is stack allocated and hence cannot
855 // outlive the appropriate temporary scope.
856 let s = rcx.repeating_scope;
857 rcx.fcx.mk_subr(infer::InfStackClosure(expr.span),
858 bounds.region_bound, ty::ReScope(s));
862 ty::ty_closure(box ty::ClosureTy{store: ty::UniqTraitStore,
865 // For proc, ensure that the *types* of the variables
866 // outlive region bound, since they are captured by value.
867 freevars::with_freevars(tcx, expr.id, |freevars| {
868 ensure_free_variable_types_outlive_closure_bound(
869 rcx, bounds.region_bound, expr, freevars);
872 ty::ty_unboxed_closure(_, region) => {
873 freevars::with_freevars(tcx, expr.id, |freevars| {
874 // No free variables means that there is no environment and
875 // hence the closure has static lifetime. Otherwise, the
876 // closure must not outlive the variables it closes over
879 // NDM -- this seems wrong, discuss with pcwalton, should
880 // be straightforward enough.
881 if !freevars.is_empty() {
882 ensure_free_variable_types_outlive_closure_bound(
883 rcx, region, expr, freevars);
890 let repeating_scope = rcx.set_repeating_scope(body.id);
891 visit::walk_expr(rcx, expr);
892 rcx.set_repeating_scope(repeating_scope);
894 match ty::get(function_type).sty {
895 ty::ty_closure(box ty::ClosureTy {
896 store: ty::RegionTraitStore(..),
899 freevars::with_freevars(tcx, expr.id, |freevars| {
900 propagate_upupvar_borrow_kind(rcx, expr, freevars);
906 fn ensure_free_variable_types_outlive_closure_bound(
908 region_bound: ty::Region,
910 freevars: &[freevars::freevar_entry])
913 * Make sure that the type of all free variables referenced
914 * inside a closure/proc outlive the closure/proc's lifetime
915 * bound. This is just a special case of the usual rules about
916 * closed over values outliving the object's lifetime bound.
919 let tcx = rcx.fcx.ccx.tcx;
921 debug!("ensure_free_variable_types_outlive_closure_bound({}, {})",
922 region_bound.repr(tcx), expr.repr(tcx));
924 for freevar in freevars.iter() {
926 let def_id = freevar.def.def_id();
927 assert!(def_id.krate == ast::LOCAL_CRATE);
931 let var_ty = rcx.resolve_node_type(var_node_id);
934 rcx, infer::RelateProcBound(expr.span, var_node_id, var_ty),
935 var_ty, region_bound);
939 fn constrain_free_variables_in_stack_closure(
941 region_bound: ty::Region,
943 freevars: &[freevars::freevar_entry])
946 * Make sure that all free variables referenced inside the
947 * closure outlive the closure's lifetime bound. Also, create
948 * an entry in the upvar_borrows map with a region.
951 let tcx = rcx.fcx.ccx.tcx;
952 let infcx = rcx.fcx.infcx();
953 debug!("constrain_free_variables({}, {})",
954 region_bound.repr(tcx), expr.repr(tcx));
955 for freevar in freevars.iter() {
956 debug!("freevar def is {:?}", freevar.def);
958 // Identify the variable being closed over and its node-id.
959 let def = freevar.def;
961 let def_id = def.def_id();
962 assert!(def_id.krate == ast::LOCAL_CRATE);
965 let upvar_id = ty::UpvarId { var_id: var_node_id,
966 closure_expr_id: expr.id };
968 // Create a region variable to represent this borrow. This borrow
969 // must outlive the region on the closure.
970 let origin = infer::UpvarRegion(upvar_id, expr.span);
971 let freevar_region = infcx.next_region_var(origin);
972 rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id),
973 region_bound, freevar_region);
975 // Create a UpvarBorrow entry. Note that we begin with a
976 // const borrow_kind, but change it to either mut or
977 // immutable as dictated by the uses.
978 let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow,
979 region: freevar_region };
980 rcx.fcx.inh.upvar_borrow_map.borrow_mut().insert(upvar_id,
983 // Guarantee that the closure does not outlive the variable itself.
984 let enclosing_region = region_of_def(rcx.fcx, def);
985 debug!("enclosing_region = {}", enclosing_region.repr(tcx));
986 rcx.fcx.mk_subr(infer::FreeVariable(freevar.span, var_node_id),
987 region_bound, enclosing_region);
991 fn propagate_upupvar_borrow_kind(rcx: &mut Rcx,
993 freevars: &[freevars::freevar_entry]) {
994 let tcx = rcx.fcx.ccx.tcx;
995 debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
996 for freevar in freevars.iter() {
997 // Because of the semi-hokey way that we are doing
998 // borrow_kind inference, we need to check for
999 // indirect dependencies, like so:
1008 // Here, the `inner_call` is basically "reborrowing" the
1009 // outer pointer. With no other changes, `inner_call`
1010 // would infer that it requires a mutable borrow, but
1011 // `outer_call` would infer that a const borrow is
1012 // sufficient. This is because we haven't linked the
1013 // borrow_kind of the borrow that occurs in the inner
1014 // closure to the borrow_kind of the borrow in the outer
1015 // closure. Note that regions *are* naturally linked
1016 // because we have a proper inference scheme there.
1018 // Anyway, for borrow_kind, we basically go back over now
1019 // after checking the inner closure (and hence
1020 // determining the final borrow_kind) and propagate that as
1021 // a constraint on the outer closure.
1023 def::DefUpvar(var_id, _, outer_closure_id, _) => {
1024 // thing being captured is itself an upvar:
1025 let outer_upvar_id = ty::UpvarId {
1027 closure_expr_id: outer_closure_id };
1028 let inner_upvar_id = ty::UpvarId {
1030 closure_expr_id: expr.id };
1031 link_upvar_borrow_kind_for_nested_closures(rcx,
1041 fn constrain_callee(rcx: &mut Rcx,
1042 callee_id: ast::NodeId,
1043 call_expr: &ast::Expr,
1044 callee_expr: &ast::Expr) {
1045 let call_region = ty::ReScope(call_expr.id);
1047 let callee_ty = rcx.resolve_node_type(callee_id);
1048 match ty::get(callee_ty).sty {
1049 ty::ty_bare_fn(..) => { }
1050 ty::ty_closure(ref closure_ty) => {
1051 let region = match closure_ty.store {
1052 ty::RegionTraitStore(r, _) => {
1053 // While we're here, link the closure's region with a unique
1054 // immutable borrow (gathered later in borrowck)
1055 let mc = mc::MemCategorizationContext::new(rcx);
1056 let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
1057 link_region(rcx, callee_expr.span, call_region,
1058 ty::UniqueImmBorrow, expr_cmt);
1061 ty::UniqTraitStore => ty::ReStatic
1063 rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span),
1064 call_region, region);
1066 let region = closure_ty.bounds.region_bound;
1067 rcx.fcx.mk_subr(infer::InvokeClosure(callee_expr.span),
1068 call_region, region);
1071 // this should not happen, but it does if the program is
1074 // tcx.sess.span_bug(
1075 // callee_expr.span,
1076 // format!("Calling non-function: {}", callee_ty.repr(tcx)));
1081 fn constrain_call<'a, I: Iterator<&'a ast::Expr>>(rcx: &mut Rcx,
1082 call_expr: &ast::Expr,
1083 receiver: Option<&ast::Expr>,
1085 implicitly_ref_args: bool) {
1086 //! Invoked on every call site (i.e., normal calls, method calls,
1087 //! and overloaded operators). Constrains the regions which appear
1088 //! in the type of the function. Also constrains the regions that
1089 //! appear in the arguments appropriately.
1091 let tcx = rcx.fcx.tcx();
1092 debug!("constrain_call(call_expr={}, \
1094 implicitly_ref_args={:?})",
1095 call_expr.repr(tcx),
1097 implicitly_ref_args);
1099 // `callee_region` is the scope representing the time in which the
1102 // FIXME(#6268) to support nested method calls, should be callee_id
1103 let callee_scope = call_expr.id;
1104 let callee_region = ty::ReScope(callee_scope);
1106 debug!("callee_region={}", callee_region.repr(tcx));
1108 for arg_expr in arg_exprs {
1109 debug!("Argument: {}", arg_expr.repr(tcx));
1111 // ensure that any regions appearing in the argument type are
1112 // valid for at least the lifetime of the function:
1113 type_of_node_must_outlive(
1114 rcx, infer::CallArg(arg_expr.span),
1115 arg_expr.id, callee_region);
1117 // unfortunately, there are two means of taking implicit
1118 // references, and we need to propagate constraints as a
1119 // result. modes are going away and the "DerefArgs" code
1120 // should be ported to use adjustments
1121 if implicitly_ref_args {
1122 link_by_ref(rcx, arg_expr, callee_scope);
1126 // as loop above, but for receiver
1127 for r in receiver.iter() {
1128 debug!("receiver: {}", r.repr(tcx));
1129 type_of_node_must_outlive(
1130 rcx, infer::CallRcvr(r.span),
1131 r.id, callee_region);
1132 if implicitly_ref_args {
1133 link_by_ref(rcx, &**r, callee_scope);
1138 fn constrain_autoderefs(rcx: &mut Rcx,
1139 deref_expr: &ast::Expr,
1141 mut derefd_ty: ty::t) {
1143 * Invoked on any auto-dereference that occurs. Checks that if
1144 * this is a region pointer being dereferenced, the lifetime of
1145 * the pointer includes the deref expr.
1147 let r_deref_expr = ty::ReScope(deref_expr.id);
1148 for i in range(0u, derefs) {
1149 debug!("constrain_autoderefs(deref_expr=?, derefd_ty={}, derefs={:?}/{:?}",
1150 rcx.fcx.infcx().ty_to_string(derefd_ty),
1153 let method_call = MethodCall::autoderef(deref_expr.id, i);
1154 derefd_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
1156 // Treat overloaded autoderefs as if an AutoRef adjustment
1157 // was applied on the base type, as that is always the case.
1158 let fn_sig = ty::ty_fn_sig(method.ty);
1159 let self_ty = *fn_sig.inputs.get(0);
1160 let (m, r) = match ty::get(self_ty).sty {
1161 ty::ty_rptr(r, ref m) => (m.mutbl, r),
1162 _ => rcx.tcx().sess.span_bug(deref_expr.span,
1163 format!("bad overloaded deref type {}",
1164 method.ty.repr(rcx.tcx())).as_slice())
1167 let mc = mc::MemCategorizationContext::new(rcx);
1168 let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
1169 link_region(rcx, deref_expr.span, r,
1170 ty::BorrowKind::from_mutbl(m), self_cmt);
1173 // Specialized version of constrain_call.
1174 type_must_outlive(rcx, infer::CallRcvr(deref_expr.span),
1175 self_ty, r_deref_expr);
1176 type_must_outlive(rcx, infer::CallReturn(deref_expr.span),
1177 fn_sig.output, r_deref_expr);
1183 match ty::get(derefd_ty).sty {
1184 ty::ty_rptr(r_ptr, _) => {
1185 mk_subregion_due_to_dereference(rcx, deref_expr.span,
1186 r_deref_expr, r_ptr);
1191 match ty::deref(derefd_ty, true) {
1192 Some(mt) => derefd_ty = mt.ty,
1193 /* if this type can't be dereferenced, then there's already an error
1194 in the session saying so. Just bail out for now */
1200 pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
1202 minimum_lifetime: ty::Region,
1203 maximum_lifetime: ty::Region) {
1204 rcx.fcx.mk_subr(infer::DerefPointer(deref_span),
1205 minimum_lifetime, maximum_lifetime)
1209 fn constrain_index(rcx: &mut Rcx,
1210 index_expr: &ast::Expr,
1214 * Invoked on any index expression that occurs. Checks that if
1215 * this is a slice being indexed, the lifetime of the pointer
1216 * includes the deref expr.
1219 debug!("constrain_index(index_expr=?, indexed_ty={}",
1220 rcx.fcx.infcx().ty_to_string(indexed_ty));
1222 let r_index_expr = ty::ReScope(index_expr.id);
1223 match ty::get(indexed_ty).sty {
1224 ty::ty_rptr(r_ptr, mt) => match ty::get(mt.ty).sty {
1225 ty::ty_vec(_, None) | ty::ty_str => {
1226 rcx.fcx.mk_subr(infer::IndexSlice(index_expr.span),
1227 r_index_expr, r_ptr);
1236 fn type_of_node_must_outlive(
1238 origin: infer::SubregionOrigin,
1240 minimum_lifetime: ty::Region)
1243 * Guarantees that any lifetimes which appear in the type of
1244 * the node `id` (after applying adjustments) are valid for at
1245 * least `minimum_lifetime`
1248 let tcx = rcx.fcx.tcx();
1250 // Try to resolve the type. If we encounter an error, then typeck
1251 // is going to fail anyway, so just stop here and let typeck
1252 // report errors later on in the writeback phase.
1253 let ty0 = rcx.resolve_node_type(id);
1254 let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
1255 rcx.fcx.inh.adjustments.borrow().find(&id),
1256 |method_call| rcx.resolve_method_type(method_call));
1257 debug!("constrain_regions_in_type_of_node(\
1258 ty={}, ty0={}, id={}, minimum_lifetime={:?})",
1259 ty_to_string(tcx, ty), ty_to_string(tcx, ty0),
1260 id, minimum_lifetime);
1261 type_must_outlive(rcx, origin, ty, minimum_lifetime);
1264 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
1265 mutability: ast::Mutability, base: &ast::Expr) {
1267 * Computes the guarantor for an expression `&base` and then
1268 * ensures that the lifetime of the resulting pointer is linked
1269 * to the lifetime of its guarantor (if any).
1272 debug!("link_addr_of(base=?)");
1275 let mc = mc::MemCategorizationContext::new(rcx);
1276 ignore_err!(mc.cat_expr(base))
1278 link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
1281 fn link_local(rcx: &Rcx, local: &ast::Local) {
1283 * Computes the guarantors for any ref bindings in a `let` and
1284 * then ensures that the lifetime of the resulting pointer is
1285 * linked to the lifetime of the initialization expression.
1288 debug!("regionck::for_local()");
1289 let init_expr = match local.init {
1291 Some(ref expr) => &**expr,
1293 let mc = mc::MemCategorizationContext::new(rcx);
1294 let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
1295 link_pattern(rcx, mc, discr_cmt, &*local.pat);
1298 fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
1300 * Computes the guarantors for any ref bindings in a match and
1301 * then ensures that the lifetime of the resulting pointer is
1302 * linked to the lifetime of its guarantor (if any).
1305 debug!("regionck::for_match()");
1306 let mc = mc::MemCategorizationContext::new(rcx);
1307 let discr_cmt = ignore_err!(mc.cat_expr(discr));
1308 debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
1309 for arm in arms.iter() {
1310 for root_pat in arm.pats.iter() {
1311 link_pattern(rcx, mc, discr_cmt.clone(), &**root_pat);
1316 fn link_pattern(rcx: &Rcx,
1317 mc: mc::MemCategorizationContext<Rcx>,
1319 root_pat: &ast::Pat) {
1321 * Link lifetimes of any ref bindings in `root_pat` to
1322 * the pointers found in the discriminant, if needed.
1325 let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
1326 match sub_pat.node {
1328 ast::PatIdent(ast::BindByRef(mutbl), _, _) => {
1329 link_region_from_node_type(
1330 rcx, sub_pat.span, sub_pat.id,
1334 // `[_, ..slice, _]` pattern
1335 ast::PatVec(_, Some(ref slice_pat), _) => {
1336 match mc.cat_slice_pattern(sub_cmt, &**slice_pat) {
1337 Ok((slice_cmt, slice_mutbl, slice_r)) => {
1338 link_region(rcx, sub_pat.span, slice_r,
1339 ty::BorrowKind::from_mutbl(slice_mutbl),
1350 fn link_autoref(rcx: &Rcx,
1353 autoref: &ty::AutoRef) {
1355 * Link lifetime of borrowed pointer resulting from autoref
1356 * to lifetimes in the value being autoref'd.
1359 debug!("link_autoref(autoref={:?})", autoref);
1360 let mc = mc::MemCategorizationContext::new(rcx);
1361 let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
1362 debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
1365 ty::AutoPtr(r, m, _) => {
1366 link_region(rcx, expr.span, r,
1367 ty::BorrowKind::from_mutbl(m), expr_cmt);
1370 ty::AutoUnsafe(..) | ty::AutoUnsizeUniq(_) | ty::AutoUnsize(_) => {}
1374 fn link_by_ref(rcx: &Rcx,
1376 callee_scope: ast::NodeId) {
1378 * Computes the guarantor for cases where the `expr` is
1379 * being passed by implicit reference and must outlive
1383 let tcx = rcx.tcx();
1384 debug!("link_by_ref(expr={}, callee_scope={})",
1385 expr.repr(tcx), callee_scope);
1386 let mc = mc::MemCategorizationContext::new(rcx);
1387 let expr_cmt = ignore_err!(mc.cat_expr(expr));
1388 let borrow_region = ty::ReScope(callee_scope);
1389 link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
1392 fn link_region_from_node_type(rcx: &Rcx,
1395 mutbl: ast::Mutability,
1396 cmt_borrowed: mc::cmt) {
1398 * Like `link_region()`, except that the region is
1399 * extracted from the type of `id`, which must be some
1400 * reference (`&T`, `&str`, etc).
1403 let rptr_ty = rcx.resolve_node_type(id);
1404 if !ty::type_is_bot(rptr_ty) && !ty::type_is_error(rptr_ty) {
1405 let tcx = rcx.fcx.ccx.tcx;
1406 debug!("rptr_ty={}", ty_to_string(tcx, rptr_ty));
1407 let r = ty::ty_region(tcx, span, rptr_ty);
1408 link_region(rcx, span, r, ty::BorrowKind::from_mutbl(mutbl),
1413 fn link_region(rcx: &Rcx,
1415 borrow_region: ty::Region,
1416 borrow_kind: ty::BorrowKind,
1417 borrow_cmt: mc::cmt) {
1419 * Informs the inference engine that `borrow_cmt` is being
1420 * borrowed with kind `borrow_kind` and lifetime `borrow_region`.
1421 * In order to ensure borrowck is satisfied, this may create
1422 * constraints between regions, as explained in
1423 * `link_reborrowed_region()`.
1426 let mut borrow_cmt = borrow_cmt;
1427 let mut borrow_kind = borrow_kind;
1430 debug!("link_region(borrow_region={}, borrow_kind={}, borrow_cmt={})",
1431 borrow_region.repr(rcx.tcx()),
1432 borrow_kind.repr(rcx.tcx()),
1433 borrow_cmt.repr(rcx.tcx()));
1434 match borrow_cmt.cat.clone() {
1435 mc::cat_deref(ref_cmt, _,
1436 mc::Implicit(ref_kind, ref_region)) |
1437 mc::cat_deref(ref_cmt, _,
1438 mc::BorrowedPtr(ref_kind, ref_region)) => {
1439 match link_reborrowed_region(rcx, span,
1440 borrow_region, borrow_kind,
1441 ref_cmt, ref_region, ref_kind) {
1452 mc::cat_discr(cmt_base, _) |
1453 mc::cat_downcast(cmt_base) |
1454 mc::cat_deref(cmt_base, _, mc::GcPtr(..)) |
1455 mc::cat_deref(cmt_base, _, mc::OwnedPtr) |
1456 mc::cat_interior(cmt_base, _) => {
1457 // Borrowing interior or owned data requires the base
1458 // to be valid and borrowable in the same fashion.
1459 borrow_cmt = cmt_base;
1460 borrow_kind = borrow_kind;
1463 mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1464 mc::cat_static_item |
1465 mc::cat_copied_upvar(..) |
1469 mc::cat_rvalue(..) => {
1470 // These are all "base cases" with independent lifetimes
1471 // that are not subject to inference
1478 fn link_reborrowed_region(rcx: &Rcx,
1480 borrow_region: ty::Region,
1481 borrow_kind: ty::BorrowKind,
1483 ref_region: ty::Region,
1484 ref_kind: ty::BorrowKind)
1485 -> Option<(mc::cmt, ty::BorrowKind)>
1488 * This is the most complicated case: the path being borrowed is
1489 * itself the referent of a borrowed pointer. Let me give an
1490 * example fragment of code to make clear(er) the situation:
1492 * let r: &'a mut T = ...; // the original reference "r" has lifetime 'a
1494 * &'z *r // the reborrow has lifetime 'z
1496 * Now, in this case, our primary job is to add the inference
1497 * constraint that `'z <= 'a`. Given this setup, let's clarify the
1498 * parameters in (roughly) terms of the example:
1500 * A borrow of: `& 'z bk * r` where `r` has type `& 'a bk T`
1501 * borrow_region ^~ ref_region ^~
1502 * borrow_kind ^~ ref_kind ^~
1505 * Here `bk` stands for some borrow-kind (e.g., `mut`, `uniq`, etc).
1507 * Unfortunately, there are some complications beyond the simple
1508 * scenario I just painted:
1510 * 1. The reference `r` might in fact be a "by-ref" upvar. In that
1511 * case, we have two jobs. First, we are inferring whether this reference
1512 * should be an `&T`, `&mut T`, or `&uniq T` reference, and we must
1513 * adjust that based on this borrow (e.g., if this is an `&mut` borrow,
1514 * then `r` must be an `&mut` reference). Second, whenever we link
1515 * two regions (here, `'z <= 'a`), we supply a *cause*, and in this
1516 * case we adjust the cause to indicate that the reference being
1517 * "reborrowed" is itself an upvar. This provides a nicer error message
1518 * should something go wrong.
1520 * 2. There may in fact be more levels of reborrowing. In the
1521 * example, I said the borrow was like `&'z *r`, but it might
1522 * in fact be a borrow like `&'z **q` where `q` has type `&'a
1523 * &'b mut T`. In that case, we want to ensure that `'z <= 'a`
1524 * and `'z <= 'b`. This is explained more below.
1526 * The return value of this function indicates whether we need to
1527 * recurse and process `ref_cmt` (see case 2 above).
1530 // Detect references to an upvar `x`:
1531 let cause = match ref_cmt.cat {
1532 mc::cat_upvar(ref upvar_id, _) => {
1533 let mut upvar_borrow_map =
1534 rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1535 match upvar_borrow_map.find_mut(upvar_id) {
1536 Some(upvar_borrow) => {
1537 // Adjust mutability that we infer for the upvar
1538 // so it can accommodate being borrowed with
1539 // mutability `kind`:
1540 adjust_upvar_borrow_kind_for_loan(*upvar_id,
1544 infer::ReborrowUpvar(span, *upvar_id)
1547 rcx.tcx().sess.span_bug(
1549 format!("Illegal upvar id: {}",
1551 rcx.tcx())).as_slice());
1557 infer::Reborrow(span)
1561 debug!("link_reborrowed_region: {} <= {}",
1562 borrow_region.repr(rcx.tcx()),
1563 ref_region.repr(rcx.tcx()));
1564 rcx.fcx.mk_subr(cause, borrow_region, ref_region);
1566 // Decide whether we need to recurse and link any regions within
1567 // the `ref_cmt`. This is concerned for the case where the value
1568 // being reborrowed is in fact a borrowed pointer found within
1569 // another borrowed pointer. For example:
1571 // let p: &'b &'a mut T = ...;
1575 // What makes this case particularly tricky is that, if the data
1576 // being borrowed is a `&mut` or `&uniq` borrow, borrowck requires
1577 // not only that `'z <= 'a`, (as before) but also `'z <= 'b`
1578 // (otherwise the user might mutate through the `&mut T` reference
1579 // after `'b` expires and invalidate the borrow we are looking at
1582 // So let's re-examine our parameters in light of this more
1583 // complicated (possible) scenario:
1585 // A borrow of: `& 'z bk * * p` where `p` has type `&'b bk & 'a bk T`
1586 // borrow_region ^~ ref_region ^~
1587 // borrow_kind ^~ ref_kind ^~
1590 // (Note that since we have not examined `ref_cmt.cat`, we don't
1591 // know whether this scenario has occurred; but I wanted to show
1592 // how all the types get adjusted.)
1595 // The reference being reborrowed is a sharable ref of
1596 // type `&'a T`. In this case, it doesn't matter where we
1597 // *found* the `&T` pointer, the memory it references will
1598 // be valid and immutable for `'a`. So we can stop here.
1600 // (Note that the `borrow_kind` must also be ImmBorrow or
1601 // else the user is borrowed imm memory as mut memory,
1602 // which means they'll get an error downstream in borrowck
1607 ty::MutBorrow | ty::UniqueImmBorrow => {
1608 // The reference being reborrowed is either an `&mut T` or
1609 // `&uniq T`. This is the case where recursion is needed.
1611 // One interesting twist is that we can weaken the borrow
1612 // kind when we recurse: to reborrow an `&mut` referent as
1613 // mutable, borrowck requires a unique path to the `&mut`
1614 // reference but not necessarily a *mutable* path.
1615 let new_borrow_kind = match borrow_kind {
1618 ty::MutBorrow | ty::UniqueImmBorrow =>
1621 return Some((ref_cmt, new_borrow_kind));
1626 fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
1629 * Adjusts the inferred borrow_kind as needed to account
1630 * for upvars that are assigned to in an assignment
1634 let mc = mc::MemCategorizationContext::new(rcx);
1635 let cmt = ignore_err!(mc.cat_expr(lhs));
1636 adjust_upvar_borrow_kind_for_mut(rcx, cmt);
1639 fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
1642 * Indicates that `cmt` is being directly mutated (e.g., assigned
1643 * to). If cmt contains any by-ref upvars, this implies that
1644 * those upvars must be borrowed using an `&mut` borow.
1649 debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
1650 cmt.repr(rcx.tcx()));
1652 match cmt.cat.clone() {
1653 mc::cat_deref(base, _, mc::OwnedPtr) |
1654 mc::cat_interior(base, _) |
1655 mc::cat_downcast(base) |
1656 mc::cat_discr(base, _) => {
1657 // Interior or owned data is mutable if base is
1658 // mutable, so iterate to the base.
1663 mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
1664 mc::cat_deref(base, _, mc::Implicit(..)) => {
1666 mc::cat_upvar(ref upvar_id, _) => {
1667 // if this is an implicit deref of an
1668 // upvar, then we need to modify the
1669 // borrow_kind of the upvar to make sure it
1670 // is inferred to mutable if necessary
1671 let mut upvar_borrow_map =
1672 rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1673 let ub = upvar_borrow_map.get_mut(upvar_id);
1674 return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow);
1680 // assignment to deref of an `&mut`
1681 // borrowed pointer implies that the
1682 // pointer itself must be unique, but not
1683 // necessarily *mutable*
1684 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1687 mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1688 mc::cat_deref(_, _, mc::GcPtr) |
1689 mc::cat_static_item |
1691 mc::cat_copied_upvar(_) |
1694 mc::cat_upvar(..) => {
1701 fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
1704 debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
1705 cmt.repr(rcx.tcx()));
1707 match cmt.cat.clone() {
1708 mc::cat_deref(base, _, mc::OwnedPtr) |
1709 mc::cat_interior(base, _) |
1710 mc::cat_downcast(base) |
1711 mc::cat_discr(base, _) => {
1712 // Interior or owned data is unique if base is
1718 mc::cat_deref(base, _, mc::BorrowedPtr(..)) |
1719 mc::cat_deref(base, _, mc::Implicit(..)) => {
1721 mc::cat_upvar(ref upvar_id, _) => {
1722 // if this is an implicit deref of an
1723 // upvar, then we need to modify the
1724 // borrow_kind of the upvar to make sure it
1725 // is inferred to unique if necessary
1726 let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1727 let ub = ub.get_mut(upvar_id);
1728 return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow);
1734 // for a borrowed pointer to be unique, its
1735 // base must be unique
1736 return adjust_upvar_borrow_kind_for_unique(rcx, base);
1739 mc::cat_deref(_, _, mc::UnsafePtr(..)) |
1740 mc::cat_deref(_, _, mc::GcPtr) |
1741 mc::cat_static_item |
1743 mc::cat_copied_upvar(_) |
1746 mc::cat_upvar(..) => {
1753 fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx,
1754 inner_upvar_id: ty::UpvarId,
1755 outer_upvar_id: ty::UpvarId) {
1757 * Indicates that the borrow_kind of `outer_upvar_id` must
1758 * permit a reborrowing with the borrow_kind of `inner_upvar_id`.
1759 * This occurs in nested closures, see comment above at the call to
1763 debug!("link_upvar_borrow_kind: inner_upvar_id={:?} outer_upvar_id={:?}",
1764 inner_upvar_id, outer_upvar_id);
1766 let mut upvar_borrow_map = rcx.fcx.inh.upvar_borrow_map.borrow_mut();
1767 let inner_borrow = upvar_borrow_map.get_copy(&inner_upvar_id);
1768 match upvar_borrow_map.find_mut(&outer_upvar_id) {
1769 Some(outer_borrow) => {
1770 adjust_upvar_borrow_kind(outer_upvar_id, outer_borrow, inner_borrow.kind);
1772 None => { /* outer closure is not a stack closure */ }
1776 fn adjust_upvar_borrow_kind_for_loan(upvar_id: ty::UpvarId,
1777 upvar_borrow: &mut ty::UpvarBorrow,
1778 kind: ty::BorrowKind) {
1779 debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}",
1780 upvar_id, upvar_borrow.kind, kind);
1782 adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind)
1785 fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId,
1786 upvar_borrow: &mut ty::UpvarBorrow,
1787 kind: ty::BorrowKind) {
1789 * We infer the borrow_kind with which to borrow upvars in a stack
1790 * closure. The borrow_kind basically follows a lattice of
1791 * `imm < unique-imm < mut`, moving from left to right as needed (but never
1792 * right to left). Here the argument `mutbl` is the borrow_kind that
1793 * is required by some particular use.
1796 debug!("adjust_upvar_borrow_kind: id={:?} kind=({:?} -> {:?})",
1797 upvar_id, upvar_borrow.kind, kind);
1799 match (upvar_borrow.kind, kind) {
1801 (ty::ImmBorrow, ty::UniqueImmBorrow) |
1802 (ty::ImmBorrow, ty::MutBorrow) |
1803 (ty::UniqueImmBorrow, ty::MutBorrow) => {
1804 upvar_borrow.kind = kind;
1807 (ty::ImmBorrow, ty::ImmBorrow) |
1808 (ty::UniqueImmBorrow, ty::ImmBorrow) |
1809 (ty::UniqueImmBorrow, ty::UniqueImmBorrow) |
1810 (ty::MutBorrow, _) => {
1815 fn type_must_outlive(rcx: &mut Rcx,
1816 origin: infer::SubregionOrigin,
1821 * Ensures that all borrowed data reachable via `ty` outlives `region`.
1824 debug!("type_must_outlive(ty={}, region={})",
1826 region.repr(rcx.tcx()));
1829 regionmanip::region_wf_constraints(
1833 for constraint in constraints.iter() {
1834 debug!("constraint: {}", constraint.repr(rcx.tcx()));
1836 regionmanip::RegionSubRegionConstraint(None, r_a, r_b) => {
1837 rcx.fcx.mk_subr(origin.clone(), r_a, r_b);
1839 regionmanip::RegionSubRegionConstraint(Some(ty), r_a, r_b) => {
1840 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
1841 rcx.fcx.mk_subr(o1, r_a, r_b);
1843 regionmanip::RegionSubParamConstraint(None, r_a, param_b) => {
1844 param_must_outlive(rcx, origin.clone(), r_a, param_b);
1846 regionmanip::RegionSubParamConstraint(Some(ty), r_a, param_b) => {
1847 let o1 = infer::ReferenceOutlivesReferent(ty, origin.span());
1848 param_must_outlive(rcx, o1, r_a, param_b);
1854 fn param_must_outlive(rcx: &Rcx,
1855 origin: infer::SubregionOrigin,
1857 param_ty: ty::ParamTy) {
1858 let param_env = &rcx.fcx.inh.param_env;
1860 debug!("param_must_outlive(region={}, param_ty={})",
1861 region.repr(rcx.tcx()),
1862 param_ty.repr(rcx.tcx()));
1864 // Collect all regions that `param_ty` is known to outlive into
1866 let mut param_bounds;
1868 // To start, collect bounds from user:
1869 let param_bound = param_env.bounds.get(param_ty.space, param_ty.idx);
1871 ty::required_region_bounds(rcx.tcx(),
1872 param_bound.opt_region_bound.as_slice(),
1873 param_bound.builtin_bounds,
1874 param_bound.trait_bounds.as_slice());
1876 // Collect default bound of fn body that applies to all in scope
1878 param_bounds.push(param_env.implicit_region_bound);
1880 // Finally, collect regions we scraped from the well-formedness
1881 // constraints in the fn signature. To do that, we walk the list
1882 // of known relations from the fn ctxt.
1884 // This is crucial because otherwise code like this fails:
1886 // fn foo<'a, A>(x: &'a A) { x.bar() }
1888 // The problem is that the type of `x` is `&'a A`. To be
1889 // well-formed, then, A must be lower-bounded by `'a`, but we
1890 // don't know that this holds from first principles.
1891 for &(ref r, ref p) in rcx.region_param_pairs.iter() {
1892 debug!("param_ty={}/{} p={}/{}",
1893 param_ty.repr(rcx.tcx()),
1898 param_bounds.push(*r);
1902 // Inform region inference that this parameter type must be
1903 // properly bounded.
1904 infer::verify_param_bound(rcx.fcx.infcx(),