Auto merge of #62468 - rust-lang:mutable-overloaded-operators, r=estebank

Improve diagnostics for invalid mutation through overloaded operators

Closes #58864
Closes #52941
Closes #57839
This commit is contained in:
bors
2019-07-13 13:44:40 +00:00
13 changed files with 282 additions and 269 deletions
@@ -4,9 +4,9 @@
use rustc::mir::{
AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
Place, PlaceBase, ProjectionElem, Rvalue, Statement, StatementKind, Static,
StaticKind, TerminatorKind,
StaticKind, Terminator, TerminatorKind,
};
use rustc::ty::{self, DefIdTree, Ty};
use rustc::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
use rustc::ty::print::Print;
use rustc_errors::DiagnosticBuilder;
@@ -15,6 +15,7 @@
use super::borrow_set::BorrowData;
use super::{MirBorrowckCtxt};
use crate::dataflow::move_paths::{InitLocation, LookupResult};
pub(super) struct IncludingDowncast(pub(super) bool);
@@ -401,6 +402,70 @@ pub(super) fn note_type_does_not_implement_copy(
err.note(&message);
}
}
pub(super) fn borrowed_content_source(
&self,
deref_base: &Place<'tcx>,
) -> BorrowedContentSource<'tcx> {
let tcx = self.infcx.tcx;
// Look up the provided place and work out the move path index for it,
// we'll use this to check whether it was originally from an overloaded
// operator.
match self.move_data.rev_lookup.find(deref_base) {
LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => {
debug!("borrowed_content_source: mpi={:?}", mpi);
for i in &self.move_data.init_path_map[mpi] {
let init = &self.move_data.inits[*i];
debug!("borrowed_content_source: init={:?}", init);
// We're only interested in statements that initialized a value, not the
// initializations from arguments.
let loc = match init.location {
InitLocation::Statement(stmt) => stmt,
_ => continue,
};
let bbd = &self.body[loc.block];
let is_terminator = bbd.statements.len() == loc.statement_index;
debug!(
"borrowed_content_source: loc={:?} is_terminator={:?}",
loc,
is_terminator,
);
if !is_terminator {
continue;
} else if let Some(Terminator {
kind: TerminatorKind::Call {
ref func,
from_hir_call: false,
..
},
..
}) = bbd.terminator {
if let Some(source)
= BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
{
return source;
}
}
}
}
// Base is a `static` so won't be from an overloaded operator
_ => (),
};
// If we didn't find an overloaded deref or index, then assume it's a
// built in deref and check the type of the base.
let base_ty = deref_base.ty(self.body, tcx).ty;
if base_ty.is_unsafe_ptr() {
BorrowedContentSource::DerefRawPointer
} else if base_ty.is_mutable_pointer() {
BorrowedContentSource::DerefMutableRef
} else {
BorrowedContentSource::DerefSharedRef
}
}
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
@@ -547,6 +612,90 @@ pub(super) fn or_else<F>(self, if_other: F) -> Self
}
}
pub(super) enum BorrowedContentSource<'tcx> {
DerefRawPointer,
DerefMutableRef,
DerefSharedRef,
OverloadedDeref(Ty<'tcx>),
OverloadedIndex(Ty<'tcx>),
}
impl BorrowedContentSource<'tcx> {
pub(super) fn describe_for_unnamed_place(&self) -> String {
match *self {
BorrowedContentSource::DerefRawPointer => format!("a raw pointer"),
BorrowedContentSource::DerefSharedRef => format!("a shared reference"),
BorrowedContentSource::DerefMutableRef => {
format!("a mutable reference")
}
BorrowedContentSource::OverloadedDeref(ty) => {
if ty.is_rc() {
format!("an `Rc`")
} else if ty.is_arc() {
format!("an `Arc`")
} else {
format!("dereference of `{}`", ty)
}
}
BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
}
}
pub(super) fn describe_for_named_place(&self) -> Option<&'static str> {
match *self {
BorrowedContentSource::DerefRawPointer => Some("raw pointer"),
BorrowedContentSource::DerefSharedRef => Some("shared reference"),
BorrowedContentSource::DerefMutableRef => Some("mutable reference"),
// Overloaded deref and index operators should be evaluated into a
// temporary. So we don't need a description here.
BorrowedContentSource::OverloadedDeref(_)
| BorrowedContentSource::OverloadedIndex(_) => None
}
}
pub(super) fn describe_for_immutable_place(&self) -> String {
match *self {
BorrowedContentSource::DerefRawPointer => format!("a `*const` pointer"),
BorrowedContentSource::DerefSharedRef => format!("a `&` reference"),
BorrowedContentSource::DerefMutableRef => {
bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
},
BorrowedContentSource::OverloadedDeref(ty) => {
if ty.is_rc() {
format!("an `Rc`")
} else if ty.is_arc() {
format!("an `Arc`")
} else {
format!("a dereference of `{}`", ty)
}
}
BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
}
}
fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Self> {
match func.sty {
ty::FnDef(def_id, substs) => {
let trait_id = tcx.trait_of_item(def_id)?;
let lang_items = tcx.lang_items();
if Some(trait_id) == lang_items.deref_trait()
|| Some(trait_id) == lang_items.deref_mut_trait()
{
Some(BorrowedContentSource::OverloadedDeref(substs.type_at(0)))
} else if Some(trait_id) == lang_items.index_trait()
|| Some(trait_id) == lang_items.index_mut_trait()
{
Some(BorrowedContentSource::OverloadedIndex(substs.type_at(0)))
} else {
None
}
}
_ => None,
}
}
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Finds the spans associated to a move or copy of move_place at location.
pub(super) fn move_spans(
+2 -127
View File
@@ -1,7 +1,7 @@
use core::unicode::property::Pattern_White_Space;
use rustc::mir::*;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty;
use rustc_errors::{DiagnosticBuilder,Applicability};
use syntax_pos::Span;
@@ -9,7 +9,7 @@
use crate::borrow_check::prefixes::PrefixSet;
use crate::borrow_check::error_reporting::UseSpans;
use crate::dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind, InitLocation,
IllegalMoveOrigin, IllegalMoveOriginKind,
LookupResult, MoveError, MovePathIndex,
};
use crate::util::borrowck_errors::{BorrowckErrors, Origin};
@@ -55,70 +55,6 @@ enum GroupedMoveError<'tcx> {
},
}
enum BorrowedContentSource<'tcx> {
DerefRawPointer,
DerefMutableRef,
DerefSharedRef,
OverloadedDeref(Ty<'tcx>),
OverloadedIndex(Ty<'tcx>),
}
impl BorrowedContentSource<'tcx> {
fn describe_for_unnamed_place(&self) -> String {
match *self {
BorrowedContentSource::DerefRawPointer => format!("a raw pointer"),
BorrowedContentSource::DerefSharedRef => format!("a shared reference"),
BorrowedContentSource::DerefMutableRef => {
format!("a mutable reference")
}
BorrowedContentSource::OverloadedDeref(ty) => {
if ty.is_rc() {
format!("an `Rc`")
} else if ty.is_arc() {
format!("an `Arc`")
} else {
format!("dereference of `{}`", ty)
}
}
BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
}
}
fn describe_for_named_place(&self) -> Option<&'static str> {
match *self {
BorrowedContentSource::DerefRawPointer => Some("raw pointer"),
BorrowedContentSource::DerefSharedRef => Some("shared reference"),
BorrowedContentSource::DerefMutableRef => Some("mutable reference"),
// Overloaded deref and index operators should be evaluated into a
// temporary. So we don't need a description here.
BorrowedContentSource::OverloadedDeref(_)
| BorrowedContentSource::OverloadedIndex(_) => None
}
}
fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Self> {
match func.sty {
ty::FnDef(def_id, substs) => {
let trait_id = tcx.trait_of_item(def_id)?;
let lang_items = tcx.lang_items();
if Some(trait_id) == lang_items.deref_trait()
|| Some(trait_id) == lang_items.deref_mut_trait()
{
Some(BorrowedContentSource::OverloadedDeref(substs.type_at(0)))
} else if Some(trait_id) == lang_items.index_trait()
|| Some(trait_id) == lang_items.index_mut_trait()
{
Some(BorrowedContentSource::OverloadedIndex(substs.type_at(0)))
} else {
None
}
}
_ => None,
}
}
}
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
pub(crate) fn report_move_errors(&mut self, move_errors: Vec<(Place<'tcx>, MoveError<'tcx>)>) {
let grouped_errors = self.group_move_errors(move_errors);
@@ -646,65 +582,4 @@ fn add_move_error_details(
);
}
}
fn borrowed_content_source(&self, deref_base: &Place<'tcx>) -> BorrowedContentSource<'tcx> {
let tcx = self.infcx.tcx;
// Look up the provided place and work out the move path index for it,
// we'll use this to check whether it was originally from an overloaded
// operator.
match self.move_data.rev_lookup.find(deref_base) {
LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => {
debug!("borrowed_content_source: mpi={:?}", mpi);
for i in &self.move_data.init_path_map[mpi] {
let init = &self.move_data.inits[*i];
debug!("borrowed_content_source: init={:?}", init);
// We're only interested in statements that initialized a value, not the
// initializations from arguments.
let loc = match init.location {
InitLocation::Statement(stmt) => stmt,
_ => continue,
};
let bbd = &self.body[loc.block];
let is_terminator = bbd.statements.len() == loc.statement_index;
debug!(
"borrowed_content_source: loc={:?} is_terminator={:?}",
loc,
is_terminator,
);
if !is_terminator {
continue;
} else if let Some(Terminator {
kind: TerminatorKind::Call {
ref func,
from_hir_call: false,
..
},
..
}) = bbd.terminator {
if let Some(source)
= BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
{
return source;
}
}
}
}
// Base is a `static` so won't be from an overloaded operator
_ => (),
};
// If we didn't find an overloaded deref or index, then assume it's a
// built in deref and check the type of the base.
let base_ty = deref_base.ty(self.body, tcx).ty;
if base_ty.is_unsafe_ptr() {
BorrowedContentSource::DerefRawPointer
} else if base_ty.is_mutable_pointer() {
BorrowedContentSource::DerefMutableRef
} else {
BorrowedContentSource::DerefSharedRef
}
}
}
@@ -1,17 +1,14 @@
use rustc::hir;
use rustc::hir::Node;
use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Body};
use rustc::mir::{
Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
};
use rustc::mir::{Terminator, TerminatorKind};
use rustc::ty::{self, Const, DefIdTree, Ty, TyS, TyCtxt};
use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Body};
use rustc::mir::{Mutability, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind};
use rustc::ty::{self, Ty, TyCtxt};
use rustc_data_structures::indexed_vec::Idx;
use syntax_pos::Span;
use syntax_pos::symbol::kw;
use crate::dataflow::move_paths::InitLocation;
use crate::borrow_check::MirBorrowckCtxt;
use crate::borrow_check::error_reporting::BorrowedContentSource;
use crate::util::borrowck_errors::{BorrowckErrors, Origin};
use crate::util::collect_writes::FindAssignments;
use crate::util::suggest_ref_mut;
@@ -43,6 +40,7 @@ pub(super) fn report_mutability_error(
let mut err;
let item_msg;
let reason;
let mut opt_source = None;
let access_place_desc = self.describe_place(access_place);
debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
@@ -103,23 +101,20 @@ pub(super) fn report_mutability_error(
item_msg = format!("`{}`", access_place_desc.unwrap());
reason = ", as it is immutable for the pattern guard".to_string();
} else {
let pointer_type =
if base.ty(self.body, self.infcx.tcx).ty.is_region_ptr() {
"`&` reference"
} else {
"`*const` pointer"
};
let source = self.borrowed_content_source(base);
let pointer_type = source.describe_for_immutable_place();
opt_source = Some(source);
if let Some(desc) = access_place_desc {
item_msg = format!("`{}`", desc);
reason = match error_access {
AccessKind::Move |
AccessKind::Mutate => format!(" which is behind a {}", pointer_type),
AccessKind::Mutate => format!(" which is behind {}", pointer_type),
AccessKind::MutableBorrow => {
format!(", as it is behind a {}", pointer_type)
format!(", as it is behind {}", pointer_type)
}
}
} else {
item_msg = format!("data in a {}", pointer_type);
item_msg = format!("data in {}", pointer_type);
reason = String::new();
}
}
@@ -457,59 +452,31 @@ pub(super) fn report_mutability_error(
}
Place::Projection(box Projection {
base: Place::Base(PlaceBase::Local(local)),
base: _,
elem: ProjectionElem::Deref,
}) if error_access == AccessKind::MutableBorrow => {
}) => {
err.span_label(span, format!("cannot {ACT}", ACT = act));
let mpi = self.move_data.rev_lookup.find_local(*local);
for i in self.move_data.init_path_map[mpi].iter() {
if let InitLocation::Statement(location) = self.move_data.inits[*i].location {
if let Some(
Terminator {
kind: TerminatorKind::Call {
func: Operand::Constant(box Constant {
literal: Const {
ty: &TyS {
sty: ty::FnDef(id, substs),
..
},
..
},
..
}),
..
},
..
}
) = &self.body.basic_blocks()[location.block].terminator {
let index_trait = self.infcx.tcx.lang_items().index_trait();
if self.infcx.tcx.parent(id) == index_trait {
let mut found = false;
self.infcx.tcx.for_each_relevant_impl(
self.infcx.tcx.lang_items().index_mut_trait().unwrap(),
substs.type_at(0),
|_relevant_impl| {
found = true;
}
);
let extra = if found {
String::new()
} else {
format!(", but it is not implemented for `{}`",
substs.type_at(0))
};
err.help(
&format!(
"trait `IndexMut` is required to modify indexed content{}",
extra,
),
);
}
}
match opt_source {
Some(BorrowedContentSource::OverloadedDeref(ty)) => {
err.help(
&format!(
"trait `DerefMut` is required to modify through a dereference, \
but it is not implemented for `{}`",
ty,
),
);
},
Some(BorrowedContentSource::OverloadedIndex(ty)) => {
err.help(
&format!(
"trait `IndexMut` is required to modify indexed content, \
but it is not implemented for `{}`",
ty,
),
);
}
_ => (),
}
}
@@ -2,18 +2,7 @@
// Deref and not DerefMut is implemented.
use std::ops::Deref;
struct Rc<T> {
value: *const T
}
impl<T> Deref for Rc<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.value }
}
}
use std::rc::Rc;
struct Point {
x: isize,
@@ -1,86 +1,114 @@
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:47:19
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:36:19
|
LL | let __isize = &mut x.y;
| ^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:51:19
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:40:19
|
LL | let __isize = &mut x.y;
| ^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:59:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:48:5
|
LL | &mut x.y
| ^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:63:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:52:5
|
LL | &mut x.y
| ^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0594]: cannot assign to data in a `&` reference
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:67:5
error[E0594]: cannot assign to data in an `Rc`
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:56:5
|
LL | x.y = 3;
| ^^^^^^^ cannot assign
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0594]: cannot assign to data in a `&` reference
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:71:5
error[E0594]: cannot assign to data in an `Rc`
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:60:5
|
LL | x.y = 3;
| ^^^^^^^ cannot assign
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0594]: cannot assign to data in a `&` reference
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:75:5
error[E0594]: cannot assign to data in an `Rc`
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:64:5
|
LL | x.y = 3;
| ^^^^^^^ cannot assign
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:83:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:72:5
|
LL | x.set(0, 0);
| ^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:87:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:76:5
|
LL | x.set(0, 0);
| ^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:95:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:84:5
|
LL | x.y_mut()
| ^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:99:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:88:5
|
LL | x.y_mut()
| ^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:103:6
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:92:6
|
LL | *x.y_mut() = 3;
| ^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:107:6
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:96:6
|
LL | *x.y_mut() = 3;
| ^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:111:6
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref.rs:100:6
|
LL | *x.y_mut() = 3;
| ^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
error: aborting due to 14 previous errors
@@ -2,18 +2,7 @@
// Deref and not DerefMut is implemented.
use std::ops::Deref;
struct Rc<T> {
value: *const T
}
impl<T> Deref for Rc<T> {
type Target = T;
fn deref<'a>(&'a self) -> &'a T {
unsafe { &*self.value }
}
}
use std::rc::Rc;
fn deref_imm(x: Rc<isize>) {
let __isize = &*x;
@@ -1,44 +1,58 @@
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:23:19
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:12:19
|
LL | let __isize = &mut *x;
| ^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:27:19
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:16:19
|
LL | let __isize = &mut *x;
| ^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:35:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:24:5
|
LL | &mut **x
| ^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:39:5
error[E0596]: cannot borrow data in an `Rc` as mutable
--> $DIR/borrowck-borrow-overloaded-deref.rs:28:5
|
LL | &mut **x
| ^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
error[E0594]: cannot assign to data in a `&` reference
--> $DIR/borrowck-borrow-overloaded-deref.rs:43:5
error[E0594]: cannot assign to data in an `Rc`
--> $DIR/borrowck-borrow-overloaded-deref.rs:32:5
|
LL | *x = 3;
| ^^^^^^ cannot assign
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
error[E0594]: cannot assign to data in a `&` reference
--> $DIR/borrowck-borrow-overloaded-deref.rs:47:5
error[E0594]: cannot assign to data in an `Rc`
--> $DIR/borrowck-borrow-overloaded-deref.rs:36:5
|
LL | **x = 3;
| ^^^^^^^ cannot assign
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
error[E0594]: cannot assign to data in a `&` reference
--> $DIR/borrowck-borrow-overloaded-deref.rs:51:5
error[E0594]: cannot assign to data in an `Rc`
--> $DIR/borrowck-borrow-overloaded-deref.rs:40:5
|
LL | **x = 3;
| ^^^^^^^ cannot assign
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
error: aborting due to 7 previous errors
@@ -54,6 +54,6 @@ fn main() {
x: 1,
};
s[2] = 20;
//~^ ERROR cannot assign to data in a `&` reference
//~^ ERROR cannot assign to data in an index of `Bar`
drop(rs);
}
@@ -21,11 +21,13 @@ LL | f[&s] = 10;
LL | drop(rs);
| -- mutable borrow later used here
error[E0594]: cannot assign to data in a `&` reference
error[E0594]: cannot assign to data in an index of `Bar`
--> $DIR/borrowck-overloaded-index-ref-index.rs:56:5
|
LL | s[2] = 20;
| ^^^^^^^^^ cannot assign
|
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Bar`
error: aborting due to 3 previous errors
@@ -3,8 +3,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
|
LL | Index::index(&v, 1..2).make_ascii_uppercase();
| ^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `IndexMut` is required to modify indexed content
error: aborting due to previous error
+5 -3
View File
@@ -1,4 +1,4 @@
error[E0596]: cannot borrow data in a `&` reference as mutable
error[E0596]: cannot borrow data in an index of `std::collections::HashMap<&str, std::string::String>` as mutable
--> $DIR/index-mut-help.rs:11:5
|
LL | map["peter"].clear();
@@ -6,13 +6,15 @@ LL | map["peter"].clear();
|
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
error[E0594]: cannot assign to data in a `&` reference
error[E0594]: cannot assign to data in an index of `std::collections::HashMap<&str, std::string::String>`
--> $DIR/index-mut-help.rs:12:5
|
LL | map["peter"] = "0".to_string();
| ^^^^^^^^^^^^ cannot assign
|
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
error[E0596]: cannot borrow data in a `&` reference as mutable
error[E0596]: cannot borrow data in an index of `std::collections::HashMap<&str, std::string::String>` as mutable
--> $DIR/index-mut-help.rs:13:13
|
LL | let _ = &mut map["peter"];
+1 -1
View File
@@ -2,6 +2,6 @@
fn main() {
let things: HashMap<String, Vec<String>> = HashMap::new();
for src in things.keys() {
things[src.as_str()].sort(); //~ ERROR cannot borrow data in a `&` reference as mutable
things[src.as_str()].sort(); //~ ERROR cannot borrow data in an index of
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
error[E0596]: cannot borrow data in a `&` reference as mutable
error[E0596]: cannot borrow data in an index of `std::collections::HashMap<std::string::String, std::vec::Vec<std::string::String>>` as mutable
--> $DIR/issue-41726.rs:5:9
|
LL | things[src.as_str()].sort();