From 5aff0e7cec9a3833ea67477bca13efcb4d950db7 Mon Sep 17 00:00:00 2001 From: Cameron Zwarich Date: Thu, 29 May 2014 21:17:49 -0700 Subject: [PATCH] Fix the handling of assignments to owning pointer paths in check_loans Make check_for_assignment_to_restricted_or_frozen_location treat mutation through an owning pointer the same way it treats mutation through an &mut pointer, where mutability must be inherited from the base path. I also included GC pointers in this check, as that is what the corresponding code in gather_loans/restrictions.rs does, but I don't think there is a way to test this with the current language. Fixes #14498. --- src/librustc/middle/borrowck/check_loans.rs | 2 + src/test/compile-fail/borrowck-issue-14498.rs | 63 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 src/test/compile-fail/borrowck-issue-14498.rs diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 052baac7855..77fad454e6e 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -641,6 +641,8 @@ impl<'a> CheckLoanCtxt<'a> { // with inherited mutability and with `&mut` // pointers. LpExtend(ref lp_base, mc::McInherited, _) | + LpExtend(ref lp_base, _, LpDeref(mc::OwnedPtr)) | + LpExtend(ref lp_base, _, LpDeref(mc::GcPtr)) | LpExtend(ref lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => { lp_base.clone() } diff --git a/src/test/compile-fail/borrowck-issue-14498.rs b/src/test/compile-fail/borrowck-issue-14498.rs new file mode 100644 index 00000000000..45dda5fee5a --- /dev/null +++ b/src/test/compile-fail/borrowck-issue-14498.rs @@ -0,0 +1,63 @@ +// Copyright 2014 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. + +// This tests that we can't modify Box<&mut T> contents while they +// are borrowed. + +struct A { a: int } +struct B<'a> { a: Box<&'a mut int> } + +fn borrow_in_var_from_var() { + let mut x: int = 1; + let y = box &mut x; + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_var_from_field() { + let mut x = A { a: 1 }; + let y = box &mut x.a; + let p = &y; + let q = &***p; + **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_var() { + let mut x: int = 1; + let y = B { a: box &mut x }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn borrow_in_field_from_field() { + let mut x = A { a: 1 }; + let y = B { a: box &mut x.a }; + let p = &y.a; + let q = &***p; + **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed + drop(p); + drop(q); +} + +fn main() { + borrow_in_var_from_var(); + borrow_in_var_from_field(); + borrow_in_field_from_var(); + borrow_in_field_from_field(); +} +