diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index ea222839ffe..9a4869fb6d1 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -67,6 +67,9 @@ impl<'a> GuaranteeLifetimeContext<'a> { fn check(&self, cmt: mc::cmt, discr_scope: Option) -> R { //! Main routine. Walks down `cmt` until we find the "guarantor". + debug!("guarantee_lifetime.check(cmt={}, loan_region={})", + cmt.repr(self.bccx.tcx), + self.loan_region.repr(self.bccx.tcx)); match cmt.cat { mc::cat_rvalue(..) | diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 490a9cb9853..c6e43bf968e 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -213,6 +213,7 @@ fn visit_arm(rcx: &mut Rcx, arm: &ast::Arm) { fn visit_local(rcx: &mut Rcx, l: &ast::Local) { // see above constrain_bindings_in_pat(l.pat, rcx); + guarantor::for_local(rcx, l); visit::walk_local(rcx, l, ()); } @@ -828,6 +829,30 @@ pub mod guarantor { } } + pub fn for_local(rcx: &mut Rcx, local: &ast::Local) { + /*! + * Link the lifetimes of any ref bindings in a let + * pattern to the lifetimes in the initializer. + * + * For example, given something like this: + * + * let &Foo(ref x) = ...; + * + * this would ensure that the lifetime 'a of the + * region pointer being matched must be >= the lifetime + * of the ref binding. + */ + + debug!("regionck::for_match()"); + let init_expr = match local.init { + None => { return; } + Some(e) => e + }; + let init_guarantor = guarantor(rcx, init_expr); + debug!("init_guarantor={}", init_guarantor.repr(rcx.tcx())); + link_ref_bindings_in_pat(rcx, local.pat, init_guarantor); + } + pub fn for_autoref(rcx: &mut Rcx, expr: &ast::Expr, autoderefs: uint, diff --git a/src/test/compile-fail/borrowck-borrow-from-temporary.rs b/src/test/compile-fail/borrowck-borrow-from-temporary.rs new file mode 100644 index 00000000000..fa84b91e43d --- /dev/null +++ b/src/test/compile-fail/borrowck-borrow-from-temporary.rs @@ -0,0 +1,22 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test lifetimes are linked properly when we take reference +// to interior. + +struct Foo(int); + +fn foo() -> &int { + let &Foo(ref x) = &Foo(3); //~ ERROR borrowed value does not live long enough + x +} + +pub fn main() { +} diff --git a/src/test/debug-info/destructured-local.rs b/src/test/debug-info/destructured-local.rs index bbe453594bc..0d415a85172 100644 --- a/src/test/debug-info/destructured-local.rs +++ b/src/test/debug-info/destructured-local.rs @@ -196,13 +196,13 @@ fn main() { let Unit(ii) = Unit(51); // univariant enum with ref binding - let Unit(ref jj) = Unit(52); + let &Unit(ref jj) = &Unit(52); // tuple struct - let TupleStruct(kk, ll) = TupleStruct(53.0, 54); + let &TupleStruct(kk, ll) = &TupleStruct(53.0, 54); // tuple struct with ref binding - let TupleStruct(mm, ref nn) = TupleStruct(55.0, 56); + let &TupleStruct(mm, ref nn) = &TupleStruct(55.0, 56); zzz(); } diff --git a/src/test/run-pass/regions-dependent-let-ref.rs b/src/test/run-pass/regions-dependent-let-ref.rs new file mode 100644 index 00000000000..e065146c7a3 --- /dev/null +++ b/src/test/run-pass/regions-dependent-let-ref.rs @@ -0,0 +1,19 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test lifetimes are linked properly when we take reference +// to interior. + +struct Foo(int); +pub fn main() { + // Here the lifetime of the `&` should be at least the + // block, since a ref binding is created to the interior. + let &Foo(ref _x) = &Foo(3); +}