use rustc::dep_graph::DepNode;
use rustc::hir::map as hir_map;
-use rustc::hir::map::blocks::FnParts;
+use rustc::hir::map::blocks::{FnParts, FnLikeNode};
use rustc::cfg;
use rustc::middle::dataflow::DataFlowContext;
use rustc::middle::dataflow::BitwiseOperator;
pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>,
error_span: Span) {
- let code = err.code;
- match code {
- err_mutbl => {
- match err.cmt.note {
- mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
- // If this is an `Fn` closure, it simply can't mutate upvars.
- // If it's an `FnMut` closure, the original variable was declared immutable.
- // We need to determine which is the case here.
- let kind = match err.cmt.upvar().unwrap().cat {
- Categorization::Upvar(mc::Upvar { kind, .. }) => kind,
- _ => bug!()
- };
- if kind == ty::ClosureKind::Fn {
- db.span_help(
- self.tcx.map.span(upvar_id.closure_expr_id),
- "consider changing this closure to take \
- self by mutable reference");
- }
- }
- _ => {
- if let Categorization::Local(local_id) = err.cmt.cat {
- let span = self.tcx.map.span(local_id);
- if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
- if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") {
- db.span_label(error_span, &format!("cannot reborrow mutably"));
- db.span_label(error_span, &format!("try removing `&mut` here"));
- } else {
- if snippet.starts_with("ref ") {
- db.span_label(span,
- &format!("use `{}` here to make mutable",
- snippet.replace("ref ", "ref mut ")));
- } else if snippet != "self" {
- db.span_label(span,
- &format!("use `mut {}` here to make mutable", snippet));
- }
- db.span_label(error_span, &format!("cannot borrow mutably"));
- }
- } else {
- db.span_label(error_span, &format!("cannot borrow mutably"));
- }
- }
- }
- }
- }
-
+ match err.code {
+ err_mutbl => self.note_and_explain_mutbl_error(db, &err, &error_span),
err_out_of_scope(super_scope, sub_scope, cause) => {
let (value_kind, value_msg) = match err.cmt.cat {
mc::Categorization::Rvalue(_) =>
}
}
+ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'tcx>,
+ error_span: &Span) {
+ match err.cmt.note {
+ mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
+ // If this is an `Fn` closure, it simply can't mutate upvars.
+ // If it's an `FnMut` closure, the original variable was declared immutable.
+ // We need to determine which is the case here.
+ let kind = match err.cmt.upvar().unwrap().cat {
+ Categorization::Upvar(mc::Upvar { kind, .. }) => kind,
+ _ => bug!()
+ };
+ if kind == ty::ClosureKind::Fn {
+ db.span_help(self.tcx.map.span(upvar_id.closure_expr_id),
+ "consider changing this closure to take \
+ self by mutable reference");
+ }
+ }
+ _ => {
+ if let Categorization::Deref(ref inner_cmt, ..) = err.cmt.cat {
+ if let Categorization::Local(local_id) = inner_cmt.cat {
+ let parent = self.tcx.map.get_parent_node(local_id);
+ let opt_fn_decl = FnLikeNode::from_node(self.tcx.map.get(parent))
+ .map(|fn_like| fn_like.decl());
+
+ if let Some(fn_decl) = opt_fn_decl {
+ if let Some(ref arg) = fn_decl.inputs.iter()
+ .find(|ref arg| arg.pat.id == local_id) {
+ if let hir::TyRptr(
+ opt_lifetime,
+ hir::MutTy{mutbl: hir::Mutability::MutImmutable, ref ty}) =
+ arg.ty.node {
+ if let Some(lifetime) = opt_lifetime {
+ if let Ok(snippet) = self.tcx.sess.codemap()
+ .span_to_snippet(ty.span) {
+ if let Ok(lifetime_snippet) = self.tcx.sess.codemap()
+ .span_to_snippet(lifetime.span) {
+ db.span_label(arg.ty.span,
+ &format!("use `&{} mut {}` \
+ here to make mutable",
+ lifetime_snippet,
+ snippet));
+ }
+ }
+ }
+ else if let Ok(snippet) = self.tcx.sess.codemap()
+ .span_to_snippet(arg.ty.span) {
+ if snippet.starts_with("&") {
+ db.span_label(arg.ty.span,
+ &format!("use `{}` here to make mutable",
+ snippet.replace("&", "&mut ")));
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if let Categorization::Local(local_id) = err.cmt.cat {
+ let span = self.tcx.map.span(local_id);
+ if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
+ if snippet.starts_with("ref mut ") || snippet.starts_with("&mut ") {
+ db.span_label(*error_span, &format!("cannot reborrow mutably"));
+ db.span_label(*error_span, &format!("try removing `&mut` here"));
+ } else {
+ if snippet.starts_with("ref ") {
+ db.span_label(span, &format!("use `{}` here to make mutable",
+ snippet.replace("ref ", "ref mut ")));
+ } else if snippet != "self" {
+ db.span_label(span,
+ &format!("use `mut {}` here to make mutable",
+ snippet));
+ }
+ db.span_label(*error_span, &format!("cannot borrow mutably"));
+ }
+ } else {
+ db.span_label(*error_span, &format!("cannot borrow mutably"));
+ }
+ }
+ }
+ }
+ }
pub fn append_loan_path_to_string(&self,
loan_path: &LoanPath<'tcx>,
out: &mut String) {
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test how overloaded deref interacts with borrows when DerefMut
-// is implemented.
-
-use std::ops::{Deref, DerefMut};
-
-struct Own<T> {
- value: *mut T
-}
-
-impl<T> Deref for Own<T> {
- type Target = T;
-
- fn deref(&self) -> &T {
- unsafe { &*self.value }
- }
-}
-
-impl<T> DerefMut for Own<T> {
- fn deref_mut(&mut self) -> &mut T {
- unsafe { &mut *self.value }
- }
-}
-
-struct Point {
- x: isize,
- y: isize
-}
-
-impl Point {
- fn get(&self) -> (isize, isize) {
- (self.x, self.y)
- }
-
- fn set(&mut self, x: isize, y: isize) {
- self.x = x;
- self.y = y;
- }
-
- fn x_ref(&self) -> &isize {
- &self.x
- }
-
- fn y_mut(&mut self) -> &mut isize {
- &mut self.y
- }
-}
-
-fn deref_imm_field(x: Own<Point>) {
- let __isize = &x.y;
-}
-
-fn deref_mut_field1(x: Own<Point>) {
- let __isize = &mut x.y; //~ ERROR cannot borrow
-}
-
-fn deref_mut_field2(mut x: Own<Point>) {
- let __isize = &mut x.y;
-}
-
-fn deref_extend_field(x: &Own<Point>) -> &isize {
- &x.y
-}
-
-fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
- &mut x.y //~ ERROR cannot borrow
-}
-
-fn deref_extend_mut_field2(x: &mut Own<Point>) -> &mut isize {
- &mut x.y
-}
-
-fn deref_extend_mut_field3(x: &mut Own<Point>) {
- // Hmm, this is unfortunate, because with box it would work,
- // but it's presently the expected outcome. See `deref_extend_mut_field4`
- // for the workaround.
-
- let _x = &mut x.x;
- let _y = &mut x.y; //~ ERROR cannot borrow
-}
-
-fn deref_extend_mut_field4<'a>(x: &'a mut Own<Point>) {
- let p = &mut **x;
- let _x = &mut p.x;
- let _y = &mut p.y;
-}
-
-fn assign_field1<'a>(x: Own<Point>) {
- x.y = 3; //~ ERROR cannot borrow
-}
-
-fn assign_field2<'a>(x: &'a Own<Point>) {
- x.y = 3; //~ ERROR cannot borrow
-}
-
-fn assign_field3<'a>(x: &'a mut Own<Point>) {
- x.y = 3;
-}
-
-fn assign_field4<'a>(x: &'a mut Own<Point>) {
- let _p: &mut Point = &mut **x;
- x.y = 3; //~ ERROR cannot borrow
-}
-
-fn deref_imm_method(x: Own<Point>) {
- let __isize = x.get();
-}
-
-fn deref_mut_method1(x: Own<Point>) {
- x.set(0, 0); //~ ERROR cannot borrow
-}
-
-fn deref_mut_method2(mut x: Own<Point>) {
- x.set(0, 0);
-}
-
-fn deref_extend_method(x: &Own<Point>) -> &isize {
- x.x_ref()
-}
-
-fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
- x.y_mut() //~ ERROR cannot borrow
-}
-
-fn deref_extend_mut_method2(x: &mut Own<Point>) -> &mut isize {
- x.y_mut()
-}
-
-fn assign_method1<'a>(x: Own<Point>) {
- *x.y_mut() = 3; //~ ERROR cannot borrow
-}
-
-fn assign_method2<'a>(x: &'a Own<Point>) {
- *x.y_mut() = 3; //~ ERROR cannot borrow
-}
-
-fn assign_method3<'a>(x: &'a mut Own<Point>) {
- *x.y_mut() = 3;
-}
-
-pub fn main() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test how overloaded deref interacts with borrows when DerefMut
-// is implemented.
-
-use std::ops::{Deref, DerefMut};
-
-struct Own<T> {
- value: *mut T
-}
-
-impl<T> Deref for Own<T> {
- type Target = T;
-
- fn deref<'a>(&'a self) -> &'a T {
- unsafe { &*self.value }
- }
-}
-
-impl<T> DerefMut for Own<T> {
- fn deref_mut<'a>(&'a mut self) -> &'a mut T {
- unsafe { &mut *self.value }
- }
-}
-
-fn deref_imm(x: Own<isize>) {
- let __isize = &*x;
-}
-
-fn deref_mut1(x: Own<isize>) {
- let __isize = &mut *x; //~ ERROR cannot borrow
-}
-
-fn deref_mut2(mut x: Own<isize>) {
- let __isize = &mut *x;
-}
-
-fn deref_extend<'a>(x: &'a Own<isize>) -> &'a isize {
- &**x
-}
-
-fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
- &mut **x //~ ERROR cannot borrow
-}
-
-fn deref_extend_mut2<'a>(x: &'a mut Own<isize>) -> &'a mut isize {
- &mut **x
-}
-
-fn assign1<'a>(x: Own<isize>) {
- *x = 3; //~ ERROR cannot borrow
-}
-
-fn assign2<'a>(x: &'a Own<isize>) {
- **x = 3; //~ ERROR cannot borrow
-}
-
-fn assign3<'a>(x: &'a mut Own<isize>) {
- **x = 3;
-}
-
-pub fn main() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(fn_traits)]
-
-// Ensure that invoking a closure counts as a unique immutable borrow
-
-type Fn<'a> = Box<FnMut() + 'a>;
-
-struct Test<'a> {
- f: Box<FnMut() + 'a>
-}
-
-// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-fn call<F>(mut f: F) where F: FnMut(Fn) {
- f(Box::new(|| {
- //~^ ERROR: cannot borrow `f` as mutable more than once
- f((Box::new(|| {})))
- }));
-}
-
-fn test1() {
- call(|mut a| {
- a.call_mut(());
- });
-}
-
-fn test2<F>(f: &F) where F: FnMut() {
- (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
-}
-
-fn test3<F>(f: &mut F) where F: FnMut() {
- (*f)();
-}
-
-fn test4(f: &Test) {
- f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
-}
-
-fn test5(f: &mut Test) {
- f.f.call_mut(())
-}
-
-fn test6() {
- let mut f = || {};
- (|| {
- f();
- })();
-}
-
-fn test7() {
- fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
- let mut f = |g: Box<FnMut(isize)>, b: isize| {};
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
- f(Box::new(|a| {
- foo(f);
- //~^ ERROR cannot move `f` into closure because it is borrowed
- //~| ERROR cannot move out of captured outer variable in an `FnMut` closure
- }), 3);
-}
-
-fn main() {}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Foo {
- x: isize,
-}
-
-impl Foo {
- pub fn f(&self) {}
- pub fn h(&mut self) {}
-}
-
-fn a(x: &mut Foo) {
- x.f();
- x.h();
-}
-
-fn b(x: &Foo) {
- x.f();
- x.h(); //~ ERROR cannot borrow
-}
-
-fn main() {
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Check that we check fns appearing in constant declarations.
-// Issue #22382.
-
-// How about mutating an immutable vector?
-const MUTATE: fn(&Vec<String>) = {
- fn broken(x: &Vec<String>) {
- x.push(format!("this is broken"));
- //~^ ERROR cannot borrow
- }
- broken
-};
-
-fn main() {
-}
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-trait Foo {
- fn borrowed(&self);
- fn borrowed_mut(&mut self);
-}
-
-fn borrowed_receiver(x: &Foo) {
- x.borrowed();
- x.borrowed_mut(); //~ ERROR cannot borrow
-}
-
-fn borrowed_mut_receiver(x: &mut Foo) {
- x.borrowed();
- x.borrowed_mut();
-}
-
-fn owned_receiver(x: Box<Foo>) {
- x.borrowed();
- x.borrowed_mut(); //~ ERROR cannot borrow
-}
-
-fn mut_owned_receiver(mut x: Box<Foo>) {
- x.borrowed();
- x.borrowed_mut();
-}
-
-fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test how overloaded deref interacts with borrows when DerefMut
+// is implemented.
+
+use std::ops::{Deref, DerefMut};
+
+struct Own<T> {
+ value: *mut T
+}
+
+impl<T> Deref for Own<T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ unsafe { &*self.value }
+ }
+}
+
+impl<T> DerefMut for Own<T> {
+ fn deref_mut(&mut self) -> &mut T {
+ unsafe { &mut *self.value }
+ }
+}
+
+struct Point {
+ x: isize,
+ y: isize
+}
+
+impl Point {
+ fn get(&self) -> (isize, isize) {
+ (self.x, self.y)
+ }
+
+ fn set(&mut self, x: isize, y: isize) {
+ self.x = x;
+ self.y = y;
+ }
+
+ fn x_ref(&self) -> &isize {
+ &self.x
+ }
+
+ fn y_mut(&mut self) -> &mut isize {
+ &mut self.y
+ }
+}
+
+fn deref_imm_field(x: Own<Point>) {
+ let __isize = &x.y;
+}
+
+fn deref_mut_field1(x: Own<Point>) {
+ let __isize = &mut x.y; //~ ERROR cannot borrow
+}
+
+fn deref_mut_field2(mut x: Own<Point>) {
+ let __isize = &mut x.y;
+}
+
+fn deref_extend_field(x: &Own<Point>) -> &isize {
+ &x.y
+}
+
+fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
+ &mut x.y //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut_field2(x: &mut Own<Point>) -> &mut isize {
+ &mut x.y
+}
+
+fn deref_extend_mut_field3(x: &mut Own<Point>) {
+ // Hmm, this is unfortunate, because with box it would work,
+ // but it's presently the expected outcome. See `deref_extend_mut_field4`
+ // for the workaround.
+
+ let _x = &mut x.x;
+ let _y = &mut x.y; //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut_field4<'a>(x: &'a mut Own<Point>) {
+ let p = &mut **x;
+ let _x = &mut p.x;
+ let _y = &mut p.y;
+}
+
+fn assign_field1<'a>(x: Own<Point>) {
+ x.y = 3; //~ ERROR cannot borrow
+}
+
+fn assign_field2<'a>(x: &'a Own<Point>) {
+ x.y = 3; //~ ERROR cannot borrow
+}
+
+fn assign_field3<'a>(x: &'a mut Own<Point>) {
+ x.y = 3;
+}
+
+fn assign_field4<'a>(x: &'a mut Own<Point>) {
+ let _p: &mut Point = &mut **x;
+ x.y = 3; //~ ERROR cannot borrow
+}
+
+fn deref_imm_method(x: Own<Point>) {
+ let __isize = x.get();
+}
+
+fn deref_mut_method1(x: Own<Point>) {
+ x.set(0, 0); //~ ERROR cannot borrow
+}
+
+fn deref_mut_method2(mut x: Own<Point>) {
+ x.set(0, 0);
+}
+
+fn deref_extend_method(x: &Own<Point>) -> &isize {
+ x.x_ref()
+}
+
+fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
+ x.y_mut() //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut_method2(x: &mut Own<Point>) -> &mut isize {
+ x.y_mut()
+}
+
+fn assign_method1<'a>(x: Own<Point>) {
+ *x.y_mut() = 3; //~ ERROR cannot borrow
+}
+
+fn assign_method2<'a>(x: &'a Own<Point>) {
+ *x.y_mut() = 3; //~ ERROR cannot borrow
+}
+
+fn assign_method3<'a>(x: &'a mut Own<Point>) {
+ *x.y_mut() = 3;
+}
+
+pub fn main() {}
--- /dev/null
+error: cannot borrow immutable argument `x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
+ |
+62 | fn deref_mut_field1(x: Own<Point>) {
+ | - use `mut x` here to make mutable
+63 | let __isize = &mut x.y; //~ ERROR cannot borrow
+ | ^ cannot borrow mutably
+
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:75:10
+ |
+74 | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
+ | ----------- use `&mut Own<Point>` here to make mutable
+75 | &mut x.y //~ ERROR cannot borrow
+ | ^
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:19
+ |
+87 | let _x = &mut x.x;
+ | - first mutable borrow occurs here
+88 | let _y = &mut x.y; //~ ERROR cannot borrow
+ | ^ second mutable borrow occurs here
+89 | }
+ | - first borrow ends here
+
+error: cannot borrow immutable argument `x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
+ |
+97 | fn assign_field1<'a>(x: Own<Point>) {
+ | - use `mut x` here to make mutable
+98 | x.y = 3; //~ ERROR cannot borrow
+ | ^ cannot borrow mutably
+
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
+ |
+101 | fn assign_field2<'a>(x: &'a Own<Point>) {
+ | -------------- use `&'a mut Own<Point>` here to make mutable
+102 | x.y = 3; //~ ERROR cannot borrow
+ | ^
+
+error[E0499]: cannot borrow `*x` as mutable more than once at a time
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:111:5
+ |
+110 | let _p: &mut Point = &mut **x;
+ | -- first mutable borrow occurs here
+111 | x.y = 3; //~ ERROR cannot borrow
+ | ^ second mutable borrow occurs here
+112 | }
+ | - first borrow ends here
+
+error: cannot borrow immutable argument `x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
+ |
+118 | fn deref_mut_method1(x: Own<Point>) {
+ | - use `mut x` here to make mutable
+119 | x.set(0, 0); //~ ERROR cannot borrow
+ | ^ cannot borrow mutably
+
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:131:5
+ |
+130 | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
+ | ----------- use `&mut Own<Point>` here to make mutable
+131 | x.y_mut() //~ ERROR cannot borrow
+ | ^
+
+error: cannot borrow immutable argument `x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
+ |
+138 | fn assign_method1<'a>(x: Own<Point>) {
+ | - use `mut x` here to make mutable
+139 | *x.y_mut() = 3; //~ ERROR cannot borrow
+ | ^ cannot borrow mutably
+
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
+ |
+142 | fn assign_method2<'a>(x: &'a Own<Point>) {
+ | -------------- use `&'a mut Own<Point>` here to make mutable
+143 | *x.y_mut() = 3; //~ ERROR cannot borrow
+ | ^
+
+error: aborting due to 10 previous errors
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test how overloaded deref interacts with borrows when DerefMut
+// is implemented.
+
+use std::ops::{Deref, DerefMut};
+
+struct Own<T> {
+ value: *mut T
+}
+
+impl<T> Deref for Own<T> {
+ type Target = T;
+
+ fn deref<'a>(&'a self) -> &'a T {
+ unsafe { &*self.value }
+ }
+}
+
+impl<T> DerefMut for Own<T> {
+ fn deref_mut<'a>(&'a mut self) -> &'a mut T {
+ unsafe { &mut *self.value }
+ }
+}
+
+fn deref_imm(x: Own<isize>) {
+ let __isize = &*x;
+}
+
+fn deref_mut1(x: Own<isize>) {
+ let __isize = &mut *x; //~ ERROR cannot borrow
+}
+
+fn deref_mut2(mut x: Own<isize>) {
+ let __isize = &mut *x;
+}
+
+fn deref_extend<'a>(x: &'a Own<isize>) -> &'a isize {
+ &**x
+}
+
+fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
+ &mut **x //~ ERROR cannot borrow
+}
+
+fn deref_extend_mut2<'a>(x: &'a mut Own<isize>) -> &'a mut isize {
+ &mut **x
+}
+
+fn assign1<'a>(x: Own<isize>) {
+ *x = 3; //~ ERROR cannot borrow
+}
+
+fn assign2<'a>(x: &'a Own<isize>) {
+ **x = 3; //~ ERROR cannot borrow
+}
+
+fn assign3<'a>(x: &'a mut Own<isize>) {
+ **x = 3;
+}
+
+pub fn main() {}
--- /dev/null
+error: cannot borrow immutable argument `x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
+ |
+38 | fn deref_mut1(x: Own<isize>) {
+ | - use `mut x` here to make mutable
+39 | let __isize = &mut *x; //~ ERROR cannot borrow
+ | ^ cannot borrow mutably
+
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
+ |
+50 | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
+ | -------------- use `&'a mut Own<isize>` here to make mutable
+51 | &mut **x //~ ERROR cannot borrow
+ | ^^
+
+error: cannot borrow immutable argument `x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
+ |
+58 | fn assign1<'a>(x: Own<isize>) {
+ | - use `mut x` here to make mutable
+59 | *x = 3; //~ ERROR cannot borrow
+ | ^ cannot borrow mutably
+
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
+ |
+62 | fn assign2<'a>(x: &'a Own<isize>) {
+ | -------------- use `&'a mut Own<isize>` here to make mutable
+63 | **x = 3; //~ ERROR cannot borrow
+ | ^^
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(fn_traits)]
+
+// Ensure that invoking a closure counts as a unique immutable borrow
+
+type Fn<'a> = Box<FnMut() + 'a>;
+
+struct Test<'a> {
+ f: Box<FnMut() + 'a>
+}
+
+// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
+fn call<F>(mut f: F) where F: FnMut(Fn) {
+ f(Box::new(|| {
+ //~^ ERROR: cannot borrow `f` as mutable more than once
+ f((Box::new(|| {})))
+ }));
+}
+
+fn test1() {
+ call(|mut a| {
+ a.call_mut(());
+ });
+}
+
+fn test2<F>(f: &F) where F: FnMut() {
+ (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
+}
+
+fn test3<F>(f: &mut F) where F: FnMut() {
+ (*f)();
+}
+
+fn test4(f: &Test) {
+ f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
+}
+
+fn test5(f: &mut Test) {
+ f.f.call_mut(())
+}
+
+fn test6() {
+ let mut f = || {};
+ (|| {
+ f();
+ })();
+}
+
+fn test7() {
+ fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
+ let mut f = |g: Box<FnMut(isize)>, b: isize| {};
+ // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
+ f(Box::new(|a| {
+ foo(f);
+ //~^ ERROR cannot move `f` into closure because it is borrowed
+ //~| ERROR cannot move out of captured outer variable in an `FnMut` closure
+ }), 3);
+}
+
+fn main() {}
--- /dev/null
+error[E0499]: cannot borrow `f` as mutable more than once at a time
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:23:16
+ |
+23 | f(Box::new(|| {
+ | - ^^ second mutable borrow occurs here
+ | |
+ | first mutable borrow occurs here
+24 | //~^ ERROR: cannot borrow `f` as mutable more than once
+25 | f((Box::new(|| {})))
+ | - borrow occurs due to use of `f` in closure
+26 | }));
+ | - first borrow ends here
+
+error: cannot borrow immutable borrowed content `*f` as mutable
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:36:5
+ |
+35 | fn test2<F>(f: &F) where F: FnMut() {
+ | -- use `&mut F` here to make mutable
+36 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
+ | ^^^^
+
+error: cannot borrow immutable `Box` content `*f.f` as mutable
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
+ |
+44 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
+ | ^^^
+
+error[E0504]: cannot move `f` into closure because it is borrowed
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13
+ |
+62 | f(Box::new(|a| {
+ | - borrow of `f` occurs here
+63 | foo(f);
+ | ^ move into closure occurs here
+
+error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
+ --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13
+ |
+63 | foo(f);
+ | ^ cannot move out of captured outer variable in an `FnMut` closure
+
+error: aborting due to 5 previous errors
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+ x: isize,
+}
+
+impl Foo {
+ pub fn f(&self) {}
+ pub fn h(&mut self) {}
+}
+
+fn a(x: &mut Foo) {
+ x.f();
+ x.h();
+}
+
+fn b(x: &Foo) {
+ x.f();
+ x.h(); //~ ERROR cannot borrow
+}
+
+fn main() {
+}
--- /dev/null
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-call-method-from-mut-aliasable.rs:27:5
+ |
+25 | fn b(x: &Foo) {
+ | ---- use `&mut Foo` here to make mutable
+26 | x.f();
+27 | x.h(); //~ ERROR cannot borrow
+ | ^
+
+error: aborting due to previous error
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+// How about mutating an immutable vector?
+const MUTATE: fn(&Vec<String>) = {
+ fn broken(x: &Vec<String>) {
+ x.push(format!("this is broken"));
+ //~^ ERROR cannot borrow
+ }
+ broken
+};
+
+fn main() {
+}
--- /dev/null
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-fn-in-const-b.rs:17:9
+ |
+16 | fn broken(x: &Vec<String>) {
+ | ------------ use `&mut Vec<String>` here to make mutable
+17 | x.push(format!("this is broken"));
+ | ^
+
+error: aborting due to previous error
+
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+trait Foo {
+ fn borrowed(&self);
+ fn borrowed_mut(&mut self);
+}
+
+fn borrowed_receiver(x: &Foo) {
+ x.borrowed();
+ x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn borrowed_mut_receiver(x: &mut Foo) {
+ x.borrowed();
+ x.borrowed_mut();
+}
+
+fn owned_receiver(x: Box<Foo>) {
+ x.borrowed();
+ x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn mut_owned_receiver(mut x: Box<Foo>) {
+ x.borrowed();
+ x.borrowed_mut();
+}
+
+fn main() {}
--- /dev/null
+error: cannot borrow immutable borrowed content `*x` as mutable
+ --> $DIR/borrowck-object-mutability.rs:19:5
+ |
+17 | fn borrowed_receiver(x: &Foo) {
+ | ---- use `&mut Foo` here to make mutable
+18 | x.borrowed();
+19 | x.borrowed_mut(); //~ ERROR cannot borrow
+ | ^
+
+error: cannot borrow immutable `Box` content `*x` as mutable
+ --> $DIR/borrowck-object-mutability.rs:29:5
+ |
+29 | x.borrowed_mut(); //~ ERROR cannot borrow
+ | ^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Copyright 2015 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait B {
+ fn foo(mut a: &String) {
+ a.push_str("bar");
+ }
+}
+
+pub fn foo<'a>(mut a: &'a String) {
+ a.push_str("foo");
+}
+
+struct A {}
+
+impl A {
+ pub fn foo(mut a: &String) {
+ a.push_str("foo");
+ }
+}
+
+fn main() {
+ foo(&"a".to_string());
+ A::foo(&"a".to_string());
+}
--- /dev/null
+error: cannot borrow immutable borrowed content `*a` as mutable
+ --> $DIR/mut-arg-hint.rs:13:9
+ |
+12 | fn foo(mut a: &String) {
+ | ------- use `&mut String` here to make mutable
+13 | a.push_str("bar");
+ | ^
+
+error: cannot borrow immutable borrowed content `*a` as mutable
+ --> $DIR/mut-arg-hint.rs:18:5
+ |
+17 | pub fn foo<'a>(mut a: &'a String) {
+ | ---------- use `&'a mut String` here to make mutable
+18 | a.push_str("foo");
+ | ^
+
+error: cannot borrow immutable borrowed content `*a` as mutable
+ --> $DIR/mut-arg-hint.rs:25:9
+ |
+24 | pub fn foo(mut a: &String) {
+ | ------- use `&mut String` here to make mutable
+25 | a.push_str("foo");
+ | ^
+
+error: aborting due to 3 previous errors
+