if !ptr.is_null() {
ptr
} else {
- oom(layout)
+ handle_alloc_error(layout)
}
}
}
///
/// The default behavior of this function is to print a message to standard error
/// and abort the process.
-/// It can be replaced with [`set_oom_hook`] and [`take_oom_hook`].
+/// It can be replaced with [`set_alloc_error_hook`] and [`take_alloc_error_hook`].
///
-/// [`set_oom_hook`]: ../../std/alloc/fn.set_oom_hook.html
-/// [`take_oom_hook`]: ../../std/alloc/fn.take_oom_hook.html
+/// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html
+/// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html
#[stable(feature = "global_alloc", since = "1.28.0")]
#[rustc_allocator_nounwind]
-pub fn oom(layout: Layout) -> ! {
+pub fn handle_alloc_error(layout: Layout) -> ! {
#[allow(improper_ctypes)]
extern "Rust" {
#[lang = "oom"]
extern crate test;
use self::test::Bencher;
use boxed::Box;
- use alloc::{Global, Alloc, Layout, oom};
+ use alloc::{Global, Alloc, Layout, handle_alloc_error};
#[test]
fn allocate_zeroed() {
unsafe {
let layout = Layout::from_size_align(1024, 1).unwrap();
let ptr = Global.alloc_zeroed(layout.clone())
- .unwrap_or_else(|_| oom(layout));
+ .unwrap_or_else(|_| handle_alloc_error(layout));
let mut i = ptr.cast::<u8>().as_ptr();
let end = i.offset(layout.size() as isize);
use core::{isize, usize};
use core::convert::From;
-use alloc::{Global, Alloc, Layout, box_free, oom};
+use alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
use boxed::Box;
use string::String;
use vec::Vec;
let layout = Layout::for_value(&*fake_ptr);
let mem = Global.alloc(layout)
- .unwrap_or_else(|_| oom(layout));
+ .unwrap_or_else(|_| handle_alloc_error(layout));
// Initialize the real ArcInner
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
use core::ptr::{self, NonNull, Unique};
use core::slice;
-use alloc::{Alloc, Layout, Global, oom};
+use alloc::{Alloc, Layout, Global, handle_alloc_error};
use alloc::CollectionAllocErr;
use alloc::CollectionAllocErr::*;
use boxed::Box;
};
match result {
Ok(ptr) => ptr.cast(),
- Err(_) => oom(layout),
+ Err(_) => handle_alloc_error(layout),
}
};
new_size);
match ptr_res {
Ok(ptr) => (new_cap, ptr.cast().into()),
- Err(_) => oom(Layout::from_size_align_unchecked(new_size, cur.align())),
+ Err(_) => handle_alloc_error(
+ Layout::from_size_align_unchecked(new_size, cur.align())
+ ),
}
}
None => {
let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
match self.a.alloc_array::<T>(new_cap) {
Ok(ptr) => (new_cap, ptr.into()),
- Err(_) => oom(Layout::array::<T>(new_cap).unwrap()),
+ Err(_) => handle_alloc_error(Layout::array::<T>(new_cap).unwrap()),
}
}
};
old_layout,
new_size) {
Ok(p) => self.ptr = p.cast().into(),
- Err(_) => oom(Layout::from_size_align_unchecked(new_size, align)),
+ Err(_) => handle_alloc_error(
+ Layout::from_size_align_unchecked(new_size, align)
+ ),
}
}
self.cap = amount;
};
match (&res, fallibility) {
- (Err(AllocErr), Infallible) => oom(new_layout),
+ (Err(AllocErr), Infallible) => handle_alloc_error(new_layout),
_ => {}
}
use core::ptr::{self, NonNull};
use core::convert::From;
-use alloc::{Global, Alloc, Layout, box_free, oom};
+use alloc::{Global, Alloc, Layout, box_free, handle_alloc_error};
use string::String;
use vec::Vec;
let layout = Layout::for_value(&*fake_ptr);
let mem = Global.alloc(layout)
- .unwrap_or_else(|_| oom(layout));
+ .unwrap_or_else(|_| handle_alloc_error(layout));
// Initialize the real RcBox
let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
/// library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to an
- /// allocation error are encouraged to call the [`oom`] function,
+ /// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn alloc(&self, layout: Layout) -> *mut u8;
/// just as in `alloc`.
///
/// Clients wishing to abort computation in response to an
- /// allocation error are encouraged to call the [`oom`] function,
+ /// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
let size = layout.size();
/// library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to a
- /// reallocation error are encouraged to call the [`oom`] function,
+ /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
#[stable(feature = "global_alloc", since = "1.28.0")]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
/// library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to an
- /// allocation error are encouraged to call the [`oom`] function,
+ /// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>;
/// Deallocate the memory referenced by `ptr`.
/// library that aborts on memory exhaustion.)
///
/// Clients wishing to abort computation in response to a
- /// reallocation error are encouraged to call the [`oom`] function,
+ /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn realloc(&mut self,
ptr: NonNull<u8>,
layout: Layout,
/// constraints, just as in `alloc`.
///
/// Clients wishing to abort computation in response to an
- /// allocation error are encouraged to call the [`oom`] function,
+ /// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
let size = layout.size();
let p = self.alloc(layout);
/// constraints, just as in `alloc`.
///
/// Clients wishing to abort computation in response to an
- /// allocation error are encouraged to call the [`oom`] function,
+ /// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
let usable_size = self.usable_size(&layout);
self.alloc(layout).map(|p| Excess(p, usable_size.1))
/// constraints, just as in `realloc`.
///
/// Clients wishing to abort computation in response to a
- /// reallocation error are encouraged to call the [`oom`] function,
+ /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn realloc_excess(&mut self,
ptr: NonNull<u8>,
layout: Layout,
/// unable to assert that the memory block referenced by `ptr`
/// could fit `layout`.
///
- /// Note that one cannot pass `CannotReallocInPlace` to the `oom`
+ /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
/// function; clients are expected either to be able to recover from
/// `grow_in_place` failures without aborting, or to fall back on
/// another reallocation method before resorting to an abort.
/// unable to assert that the memory block referenced by `ptr`
/// could fit `layout`.
///
- /// Note that one cannot pass `CannotReallocInPlace` to the `oom`
+ /// Note that one cannot pass `CannotReallocInPlace` to the `handle_alloc_error`
/// function; clients are expected either to be able to recover from
/// `shrink_in_place` failures without aborting, or to fall back
/// on another reallocation method before resorting to an abort.
/// will *not* yield undefined behavior.
///
/// Clients wishing to abort computation in response to an
- /// allocation error are encouraged to call the [`oom`] function,
+ /// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
fn alloc_one<T>(&mut self) -> Result<NonNull<T>, AllocErr>
where Self: Sized
{
/// Always returns `Err` on arithmetic overflow.
///
/// Clients wishing to abort computation in response to an
- /// allocation error are encouraged to call the [`oom`] function,
+ /// allocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
fn alloc_array<T>(&mut self, n: usize) -> Result<NonNull<T>, AllocErr>
where Self: Sized
{
/// Always returns `Err` on arithmetic overflow.
///
/// Clients wishing to abort computation in response to a
- /// reallocation error are encouraged to call the [`oom`] function,
+ /// reallocation error are encouraged to call the [`handle_alloc_error`] function,
/// rather than directly invoking `panic!` or similar.
///
- /// [`oom`]: ../../alloc/alloc/fn.oom.html
+ /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
unsafe fn realloc_array<T>(&mut self,
ptr: NonNull<T>,
n_old: usize,
})
}
+ fn fn_decl(&self) -> Option<&FnDecl> {
+ match self {
+ EntryItem(_, _, ref item) => {
+ match item.node {
+ ItemFn(ref fn_decl, _, _, _, _, _) => Some(&fn_decl),
+ _ => None,
+ }
+ }
+
+ EntryTraitItem(_, _, ref item) => {
+ match item.node {
+ TraitItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
+ _ => None
+ }
+ }
+
+ EntryImplItem(_, _, ref item) => {
+ match item.node {
+ ImplItemKind::Method(ref method_sig, _) => Some(&method_sig.decl),
+ _ => None,
+ }
+ }
+
+ EntryExpr(_, _, ref expr) => {
+ match expr.node {
+ ExprClosure(_, ref fn_decl, ..) => Some(&fn_decl),
+ _ => None,
+ }
+ }
+
+ _ => None
+ }
+ }
+
fn associated_body(self) -> Option<BodyId> {
match self {
EntryItem(_, _, item) => {
self.forest.krate.body(id)
}
+ pub fn fn_decl(&self, node_id: ast::NodeId) -> Option<FnDecl> {
+ if let Some(entry) = self.find_entry(node_id) {
+ entry.fn_decl().map(|fd| fd.clone())
+ } else {
+ bug!("no entry for node_id `{}`", node_id)
+ }
+ }
+
/// Returns the `NodeId` that corresponds to the definition of
/// which this is the body of, i.e. a `fn`, `const` or `static`
/// item (possibly associated), a closure, or a `hir::AnonConst`.
pub fn temps_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
(self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
- if self.local_decls[local].is_user_variable {
+ if self.local_decls[local].is_user_variable.is_some() {
None
} else {
Some(local)
pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
(self.arg_count+1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
- if self.local_decls[local].is_user_variable {
+ if self.local_decls[local].is_user_variable.is_some() {
Some(local)
} else {
None
(1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let decl = &self.local_decls[local];
- if (decl.is_user_variable || index < self.arg_count + 1)
+ if (decl.is_user_variable.is_some() || index < self.arg_count + 1)
&& decl.mutability == Mutability::Mut
{
Some(local)
}
}
-#[derive(Clone, Debug)]
+#[derive(Copy, Clone, Debug)]
pub enum ClearCrossCrate<T> {
Clear,
Set(T)
Not,
}
+impl From<Mutability> for hir::Mutability {
+ fn from(m: Mutability) -> Self {
+ match m {
+ Mutability::Mut => hir::MutMutable,
+ Mutability::Not => hir::MutImmutable,
+ }
+ }
+}
+
+
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
ReturnPointer,
}
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct VarBindingForm {
+ /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
+ pub binding_mode: ty::BindingMode,
+ /// If an explicit type was provided for this variable binding,
+ /// this holds the source Span of that type.
+ ///
+ /// NOTE: If you want to change this to a `HirId`, be wary that
+ /// doing so breaks incremental compilation (as of this writing),
+ /// while a `Span` does not cause our tests to fail.
+ pub opt_ty_info: Option<Span>,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub enum BindingForm {
+ /// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
+ Var(VarBindingForm),
+ /// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
+ ImplicitSelf,
+}
+
+CloneTypeFoldableAndLiftImpls! { BindingForm, }
+
+impl_stable_hash_for!(struct self::VarBindingForm { binding_mode, opt_ty_info });
+
+impl_stable_hash_for!(enum self::BindingForm { Var(binding), ImplicitSelf, });
+
/// A MIR local.
///
/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
/// Temporaries and the return place are always mutable.
pub mutability: Mutability,
- /// True if this corresponds to a user-declared local variable.
- pub is_user_variable: bool,
+ /// Some(binding_mode) if this corresponds to a user-declared local variable.
+ ///
+ /// This is solely used for local diagnostics when generating
+ /// warnings/errors when compiling the current crate, and
+ /// therefore it need not be visible across crates. pnkfelix
+ /// currently hypothesized we *need* to wrap this in a
+ /// `ClearCrossCrate` as long as it carries as `HirId`.
+ pub is_user_variable: Option<ClearCrossCrate<BindingForm>>,
/// True if this is an internal local
///
}
impl<'tcx> LocalDecl<'tcx> {
+ /// Returns true only if local is a binding that can itself be
+ /// made mutable via the addition of the `mut` keyword, namely
+ /// something like the occurrences of `x` in:
+ /// - `fn foo(x: Type) { ... }`,
+ /// - `let x = ...`,
+ /// - or `match ... { C(x) => ... }`
+ pub fn can_be_made_mutable(&self) -> bool
+ {
+ match self.is_user_variable {
+ Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+ binding_mode: ty::BindingMode::BindByValue(_),
+ opt_ty_info: _,
+ }))) => true,
+
+ // FIXME: might be able to thread the distinction between
+ // `self`/`mut self`/`&self`/`&mut self` into the
+ // `BindingForm::ImplicitSelf` variant, (and then return
+ // true here for solely the first case).
+ _ => false,
+ }
+ }
+
+ /// Returns true if local is definitely not a `ref ident` or
+ /// `ref mut ident` binding. (Such bindings cannot be made into
+ /// mutable bindings, but the inverse does not necessarily hold).
+ pub fn is_nonref_binding(&self) -> bool
+ {
+ match self.is_user_variable {
+ Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+ binding_mode: ty::BindingMode::BindByValue(_),
+ opt_ty_info: _,
+ }))) => true,
+
+ Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,
+
+ _ => false,
+ }
+ }
+
/// Create a new `LocalDecl` for a temporary.
#[inline]
pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
},
visibility_scope: OUTERMOST_SOURCE_SCOPE,
internal: false,
- is_user_variable: false
+ is_user_variable: None,
}
}
},
visibility_scope: OUTERMOST_SOURCE_SCOPE,
internal: true,
- is_user_variable: false
+ is_user_variable: None,
}
}
visibility_scope: OUTERMOST_SOURCE_SCOPE,
internal: false,
name: None, // FIXME maybe we do want some name here?
- is_user_variable: false
+ is_user_variable: None,
}
}
}
BindByValue(Mutability),
}
+CloneTypeFoldableAndLiftImpls! { BindingMode, }
+
impl BindingMode {
pub fn convert(ba: BindingAnnotation) -> BindingMode {
match ba {
err.emit();
}
+ /// Reports an illegal reassignment; for example, an assignment to
+ /// (part of) a non-`mut` local that occurs potentially after that
+ /// local has already been initialized. `place` is the path being
+ /// assigned; `err_place` is a place providing a reason why
+ /// `place` is not mutable (e.g. the non-`mut` local `x` in an
+ /// assignment to `x.f`).
pub(super) fn report_illegal_reassignment(
&mut self,
_context: Context,
(place, span): (&Place<'tcx>, Span),
assigned_span: Span,
+ err_place: &Place<'tcx>,
) {
let is_arg = if let Place::Local(local) = place {
if let LocalKind::Arg = self.mir.local_kind(*local) {
"cannot assign twice to immutable variable"
};
if span != assigned_span {
- if is_arg {
- err.span_label(assigned_span, "argument not declared as `mut`");
- } else {
+ if !is_arg {
let value_msg = match self.describe_place(place) {
Some(name) => format!("`{}`", name),
None => "value".to_owned(),
err.span_label(assigned_span, format!("first assignment to {}", value_msg));
}
}
+ if let Place::Local(local) = err_place {
+ let local_decl = &self.mir.local_decls[*local];
+ if let Some(name) = local_decl.name {
+ if local_decl.can_be_made_mutable() {
+ err.span_label(local_decl.source_info.span,
+ format!("consider changing this to `mut {}`", name));
+ }
+ }
+ }
err.span_label(span, msg);
err.emit();
}
use rustc::ty::{self, ParamEnv, TyCtxt};
use rustc::ty::query::Providers;
use rustc::lint::builtin::UNUSED_MUT;
-use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
+use rustc::mir::{self, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand};
use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind};
use rustc::mir::{Terminator, TerminatorKind};
// to the set.
let temporary_used_locals: FxHashSet<Local> =
mbcx.used_mut.iter()
- .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable)
+ .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some())
.cloned()
.collect();
) {
debug!("check_if_reassignment_to_immutable_state({:?})", place);
// determine if this path has a non-mut owner (and thus needs checking).
- if let Ok(..) = self.is_mutable(place, LocalMutationIsAllowed::No) {
- return;
- }
+ let err_place = match self.is_mutable(place, LocalMutationIsAllowed::No) {
+ Ok(..) => return,
+ Err(place) => place,
+ };
debug!(
"check_if_reassignment_to_immutable_state({:?}) - is an imm local",
place
let init = self.move_data.inits[i];
let init_place = &self.move_data.move_paths[init.path].place;
if places_conflict(self.tcx, self.mir, &init_place, place, Deep) {
- self.report_illegal_reassignment(context, (place, span), init.span);
+ self.report_illegal_reassignment(context, (place, span), init.span, err_place);
break;
}
}
}
}
- fn specialized_description(&self, place:&Place<'tcx>) -> Option<String>{
- if let Some(_name) = self.describe_place(place) {
- Some(format!("data in a `&` reference"))
- } else {
- None
- }
- }
-
- fn get_default_err_msg(&self, place:&Place<'tcx>) -> String{
- match self.describe_place(place) {
- Some(name) => format!("immutable item `{}`", name),
- None => "immutable item".to_owned(),
- }
- }
-
- fn get_secondary_err_msg(&self, place:&Place<'tcx>) -> String{
- match self.specialized_description(place) {
- Some(_) => format!("data in a `&` reference"),
- None => self.get_default_err_msg(place)
- }
- }
-
- fn get_primary_err_msg(&self, place:&Place<'tcx>) -> String{
- if let Some(name) = self.describe_place(place) {
- format!("`{}` is a `&` reference, so the data it refers to cannot be written", name)
- } else {
- format!("cannot assign through `&`-reference")
- }
- }
-
/// Check the permissions for the given place and read or write kind
///
/// Returns true if an error is reported, false otherwise.
"check_access_permissions({:?}, {:?}, {:?})",
place, kind, is_local_mutation_allowed
);
- let mut error_reported = false;
+
+ #[derive(Copy, Clone, Debug)]
+ enum AccessKind {
+ MutableBorrow,
+ Mutate,
+ }
+ let error_access;
+ let the_place_err;
+
match kind {
Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Unique))
| Reservation(WriteKind::MutableBorrow(borrow_kind @ BorrowKind::Mut { .. }))
BorrowKind::Shared => unreachable!(),
};
match self.is_mutable(place, is_local_mutation_allowed) {
- Ok(root_place) => self.add_used_mut(root_place, flow_state),
+ Ok(root_place) => {
+ self.add_used_mut(root_place, flow_state);
+ return false;
+ }
Err(place_err) => {
- error_reported = true;
- let item_msg = self.get_default_err_msg(place);
- let mut err = self.tcx
- .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
- err.span_label(span, "cannot borrow as mutable");
-
- if place != place_err {
- if let Some(name) = self.describe_place(place_err) {
- err.note(&format!("the value which is causing this path not to be \
- mutable is...: `{}`", name));
- }
- }
-
- err.emit();
+ error_access = AccessKind::MutableBorrow;
+ the_place_err = place_err;
}
}
}
Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => {
match self.is_mutable(place, is_local_mutation_allowed) {
- Ok(root_place) => self.add_used_mut(root_place, flow_state),
+ Ok(root_place) => {
+ self.add_used_mut(root_place, flow_state);
+ return false;
+ }
Err(place_err) => {
- error_reported = true;
-
- let err_info = if let Place::Projection(
- box Projection {
- base: Place::Local(local),
- elem: ProjectionElem::Deref
- }
- ) = *place_err {
- let locations = self.mir.find_assignments(local);
- if locations.len() > 0 {
- let item_msg = if error_reported {
- self.get_secondary_err_msg(&Place::Local(local))
- } else {
- self.get_default_err_msg(place)
- };
- let sp = self.mir.source_info(locations[0]).span;
- let mut to_suggest_span = String::new();
- if let Ok(src) =
- self.tcx.sess.codemap().span_to_snippet(sp) {
- to_suggest_span = src[1..].to_string();
- };
- Some((sp,
- "consider changing this to be a \
- mutable reference",
- to_suggest_span,
- item_msg,
- self.get_primary_err_msg(&Place::Local(local))))
- } else {
- None
- }
- } else {
- None
- };
-
- if let Some((err_help_span,
- err_help_stmt,
- to_suggest_span,
- item_msg,
- sec_span)) = err_info {
- let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
- err.span_suggestion(err_help_span,
- err_help_stmt,
- format!("&mut {}", to_suggest_span));
- if place != place_err {
- err.span_label(span, sec_span);
- }
- err.emit()
- } else {
- let item_msg = self.get_default_err_msg(place);
- let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
- err.span_label(span, "cannot mutate");
- if place != place_err {
- if let Some(name) = self.describe_place(place_err) {
- err.note(&format!("the value which is causing this path not \
- to be mutable is...: `{}`", name));
- }
- }
- err.emit();
- }
+ error_access = AccessKind::Mutate;
+ the_place_err = place_err;
}
}
}
+
Reservation(WriteKind::Move)
| Write(WriteKind::Move)
| Reservation(WriteKind::StorageDeadOrDrop)
),
);
}
+ return false;
+ }
+ Activation(..) => {
+ // permission checks are done at Reservation point.
+ return false;
}
- Activation(..) => {} // permission checks are done at Reservation point.
Read(ReadKind::Borrow(BorrowKind::Unique))
| Read(ReadKind::Borrow(BorrowKind::Mut { .. }))
| Read(ReadKind::Borrow(BorrowKind::Shared))
- | Read(ReadKind::Copy) => {} // Access authorized
+ | Read(ReadKind::Copy) => {
+ // Access authorized
+ return false;
+ }
}
- error_reported
+ // at this point, we have set up the error reporting state.
+
+ let mut err;
+ let item_msg = match self.describe_place(place) {
+ Some(name) => format!("immutable item `{}`", name),
+ None => "immutable item".to_owned(),
+ };
+
+ // `act` and `acted_on` are strings that let us abstract over
+ // the verbs used in some diagnostic messages.
+ let act; let acted_on;
+
+ match error_access {
+ AccessKind::Mutate => {
+ let item_msg = match the_place_err {
+ Place::Projection(box Projection {
+ base: _,
+ elem: ProjectionElem::Deref }
+ ) => match self.describe_place(place) {
+ Some(description) =>
+ format!("`{}` which is behind a `&` reference", description),
+ None => format!("data in a `&` reference"),
+ },
+ _ => item_msg,
+ };
+ err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir);
+ act = "assign"; acted_on = "written";
+ }
+ AccessKind::MutableBorrow => {
+ err = self.tcx
+ .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir);
+ act = "borrow as mutable"; acted_on = "borrowed as mutable";
+ }
+ }
+
+ match the_place_err {
+ // We want to suggest users use `let mut` for local (user
+ // variable) mutations...
+ Place::Local(local) if self.mir.local_decls[*local].can_be_made_mutable() => {
+ // ... but it doesn't make sense to suggest it on
+ // variables that are `ref x`, `ref mut x`, `&self`,
+ // or `&mut self` (such variables are simply not
+ // mutable)..
+ let local_decl = &self.mir.local_decls[*local];
+ assert_eq!(local_decl.mutability, Mutability::Not);
+
+ err.span_label(span, format!("cannot {ACT}", ACT=act));
+ err.span_suggestion(local_decl.source_info.span,
+ "consider changing this to be mutable",
+ format!("mut {}", local_decl.name.unwrap()));
+ }
+
+ // complete hack to approximate old AST-borrowck
+ // diagnostic: if the span starts with a mutable borrow of
+ // a local variable, then just suggest the user remove it.
+ Place::Local(_) if {
+ if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
+ snippet.starts_with("&mut ")
+ } else {
+ false
+ }
+ } => {
+ err.span_label(span, format!("cannot {ACT}", ACT=act));
+ err.span_label(span, "try removing `&mut` here");
+ }
+
+ // We want to point out when a `&` can be readily replaced
+ // with an `&mut`.
+ //
+ // FIXME: can this case be generalized to work for an
+ // arbitrary base for the projection?
+ Place::Projection(box Projection { base: Place::Local(local),
+ elem: ProjectionElem::Deref })
+ if self.mir.local_decls[*local].is_nonref_binding() =>
+ {
+ let (err_help_span, suggested_code) =
+ find_place_to_suggest_ampmut(self.tcx, self.mir, *local);
+ err.span_suggestion(err_help_span,
+ "consider changing this to be a mutable reference",
+ suggested_code);
+
+ let local_decl = &self.mir.local_decls[*local];
+ if let Some(name) = local_decl.name {
+ err.span_label(
+ span, format!("`{NAME}` is a `&` reference, \
+ so the data it refers to cannot be {ACTED_ON}",
+ NAME=name, ACTED_ON=acted_on));
+ } else {
+ err.span_label(span, format!("cannot {ACT} through `&`-reference", ACT=act));
+ }
+ }
+
+ _ => {
+ err.span_label(span, format!("cannot {ACT}", ACT=act));
+ }
+ }
+
+ err.emit();
+ return true;
+
+ // Returns the span to highlight and the associated text to
+ // present when suggesting that the user use an `&mut`.
+ //
+ // When we want to suggest a user change a local variable to be a `&mut`, there
+ // are three potential "obvious" things to highlight:
+ //
+ // let ident [: Type] [= RightHandSideExresssion];
+ // ^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
+ // (1.) (2.) (3.)
+ //
+ // We can always fallback on highlighting the first. But chances are good that
+ // the user experience will be better if we highlight one of the others if possible;
+ // for example, if the RHS is present and the Type is not, then the type is going to
+ // be inferred *from* the RHS, which means we should highlight that (and suggest
+ // that they borrow the RHS mutably).
+ fn find_place_to_suggest_ampmut<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+ mir: &Mir<'tcx>,
+ local: Local) -> (Span, String)
+ {
+ // This implementation attempts to emulate AST-borrowck prioritization
+ // by trying (3.), then (2.) and finally falling back on (1.).
+ let locations = mir.find_assignments(local);
+ if locations.len() > 0 {
+ let assignment_rhs_span = mir.source_info(locations[0]).span;
+ let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span);
+ if let Ok(src) = snippet {
+ // pnkfelix inherited code; believes intention is
+ // highlighted text will always be `&<expr>` and
+ // thus can transform to `&mut` by slicing off
+ // first ASCII character and prepending "&mut ".
+ let borrowed_expr = src[1..].to_string();
+ return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
+ }
+ }
+
+ let local_decl = &mir.local_decls[local];
+ let highlight_span = match local_decl.is_user_variable {
+ // if this is a variable binding with an explicit type,
+ // try to highlight that for the suggestion.
+ Some(ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
+ opt_ty_info: Some(ty_span), .. }))) => ty_span,
+
+ Some(ClearCrossCrate::Clear) => bug!("saw cleared local state"),
+
+ // otherwise, just highlight the span associated with
+ // the (MIR) LocalDecl.
+ _ => local_decl.source_info.span,
+ };
+
+ let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
+ assert_eq!(ty_mut.mutbl, hir::MutImmutable);
+ return (highlight_span, format!("&mut {}", ty_mut.ty));
+ }
}
/// Adds the place into the used mutable variables set
}
}
- this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
+ this.visit_bindings(&pattern, &mut |this, _, _, _, node, span, _| {
this.storage_live_binding(block, node, span, OutsideGuard);
this.schedule_drop_for_binding(node, span, OutsideGuard);
})
source_info,
visibility_scope: source_info.scope,
internal: true,
- is_user_variable: false
+ is_user_variable: None,
});
let ptr_temp = Place::Local(ptr_temp);
let block = unpack!(this.into(&ptr_temp, block, ptr));
assert!(!(visibility_scope.is_some() && lint_level.is_explicit()),
"can't have both a visibility and a lint scope at the same time");
let mut scope = self.source_scope;
- self.visit_bindings(pattern, &mut |this, mutability, name, var, span, ty| {
+ self.visit_bindings(pattern, &mut |this, mutability, name, mode, var, span, ty| {
if visibility_scope.is_none() {
visibility_scope = Some(this.new_source_scope(scope_span,
LintLevel::Inherited,
scope,
};
let visibility_scope = visibility_scope.unwrap();
- this.declare_binding(source_info, visibility_scope, mutability, name, var,
+ this.declare_binding(source_info, visibility_scope, mutability, name, mode, var,
ty, has_guard);
});
visibility_scope
}
pub fn visit_bindings<F>(&mut self, pattern: &Pattern<'tcx>, f: &mut F)
- where F: FnMut(&mut Self, Mutability, Name, NodeId, Span, Ty<'tcx>)
+ where F: FnMut(&mut Self, Mutability, Name, BindingMode, NodeId, Span, Ty<'tcx>)
{
match *pattern.kind {
- PatternKind::Binding { mutability, name, var, ty, ref subpattern, .. } => {
- f(self, mutability, name, var, pattern.span, ty);
+ PatternKind::Binding { mutability, name, mode, var, ty, ref subpattern, .. } => {
+ f(self, mutability, name, mode, var, pattern.span, ty);
if let Some(subpattern) = subpattern.as_ref() {
self.visit_bindings(subpattern, f);
}
visibility_scope: SourceScope,
mutability: Mutability,
name: Name,
+ mode: BindingMode,
var_id: NodeId,
var_ty: Ty<'tcx>,
has_guard: ArmHasGuard)
{
- debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, visibility_scope={:?}, \
- source_info={:?})",
- var_id, name, var_ty, visibility_scope, source_info);
+ debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
+ visibility_scope={:?}, source_info={:?})",
+ var_id, name, mode, var_ty, visibility_scope, source_info);
let tcx = self.hir.tcx();
+ let binding_mode = match mode {
+ BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
+ BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
+ };
let local = LocalDecl::<'tcx> {
mutability,
ty: var_ty.clone(),
source_info,
visibility_scope,
internal: false,
- is_user_variable: true,
+ is_user_variable: Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+ binding_mode,
+ // hypothetically, `visit_bindings` could try to unzip
+ // an outermost hir::Ty as we descend, matching up
+ // idents in pat; but complex w/ unclear UI payoff.
+ // Instead, just abandon providing diagnostic info.
+ opt_ty_info: None,
+ }))),
};
let for_arm_body = self.local_decls.push(local.clone());
let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() {
name: Some(name),
source_info,
visibility_scope,
+ // FIXME: should these secretly injected ref_for_guard's be marked as `internal`?
internal: false,
- is_user_variable: true,
+ is_user_variable: None,
});
LocalsForNode::Three { val_for_guard, ref_for_guard, for_arm_body }
} else {
// HACK(eddyb) Avoid having RustCall on closures,
// as it adds unnecessary (and wrong) auto-tupling.
abi = Abi::Rust;
- Some((liberated_closure_env_ty(tcx, id, body_id), None))
+ Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
}
ty::TyGenerator(..) => {
let gen_ty = tcx.body_tables(body_id).node_id_to_type(fn_hir_id);
- Some((gen_ty, None))
+ Some(ArgInfo(gen_ty, None, None, None))
}
_ => None,
};
.iter()
.enumerate()
.map(|(index, arg)| {
- (fn_sig.inputs()[index], Some(&*arg.pat))
+ let owner_id = tcx.hir.body_owner(body_id);
+ let opt_ty_info;
+ let self_arg;
+ if let Some(ref fn_decl) = tcx.hir.fn_decl(owner_id) {
+ let ty_hir_id = fn_decl.inputs[index].hir_id;
+ let ty_span = tcx.hir.span(tcx.hir.hir_to_node_id(ty_hir_id));
+ opt_ty_info = Some(ty_span);
+ self_arg = if index == 0 && fn_decl.has_implicit_self {
+ Some(ImplicitSelfBinding)
+ } else {
+ None
+ };
+ } else {
+ opt_ty_info = None;
+ self_arg = None;
+ }
+ ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
});
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
///////////////////////////////////////////////////////////////////////////
/// the main entry point for building MIR for a function
+struct ImplicitSelfBinding;
+
+struct ArgInfo<'gcx>(Ty<'gcx>,
+ Option<Span>,
+ Option<&'gcx hir::Pat>,
+ Option<ImplicitSelfBinding>);
+
fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
fn_id: ast::NodeId,
arguments: A,
yield_ty: Option<Ty<'gcx>>,
body: &'gcx hir::Body)
-> Mir<'tcx>
- where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
+ where A: Iterator<Item=ArgInfo<'gcx>>
{
let arguments: Vec<_> = arguments.collect();
fn args_and_body(&mut self,
mut block: BasicBlock,
- arguments: &[(Ty<'gcx>, Option<&'gcx hir::Pat>)],
+ arguments: &[ArgInfo<'gcx>],
argument_scope: region::Scope,
ast_body: &'gcx hir::Expr)
-> BlockAnd<()>
{
// Allocate locals for the function arguments
- for &(ty, pattern) in arguments.iter() {
+ for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
// If this is a simple binding pattern, give the local a nice name for debuginfo.
let mut name = None;
if let Some(pat) = pattern {
visibility_scope: source_info.scope,
name,
internal: false,
- is_user_variable: false,
+ is_user_variable: None,
});
}
let mut scope = None;
// Bind the argument patterns
- for (index, &(ty, pattern)) in arguments.iter().enumerate() {
+ for (index, arg_info) in arguments.iter().enumerate() {
// Function arguments always get the first Local indices after the return place
let local = Local::new(index + 1);
let place = Place::Local(local);
+ let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
if let Some(pattern) = pattern {
let pattern = self.hir.pattern_from_hir(pattern);
// Don't introduce extra copies for simple bindings
PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => {
self.local_decls[local].mutability = mutability;
+ self.local_decls[local].is_user_variable =
+ if let Some(ImplicitSelfBinding) = self_binding {
+ Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf))
+ } else {
+ let binding_mode = ty::BindingMode::BindByValue(mutability.into());
+ Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+ binding_mode, opt_ty_info })))
+ };
self.var_indices.insert(var, LocalsForNode::One(local));
}
_ => {
source_info,
visibility_scope: source_info.scope,
internal: false,
- is_user_variable: false
+ is_user_variable: None,
}
}
source_info,
visibility_scope: source_info.scope,
internal: false,
- is_user_variable: false,
+ is_user_variable: None,
};
let new_ret_local = Local::new(mir.local_decls.len());
mir.local_decls.push(new_ret);
source_info,
visibility_scope: source_info.scope,
internal: false,
- is_user_variable: false,
+ is_user_variable: None,
};
make_generator_state_argument_indirect(tcx, def_id, &mut mir);
source_info,
visibility_scope: source_info.scope,
internal: false,
- is_user_variable: false,
+ is_user_variable: None,
};
no_landing_pads(tcx, &mut mir);
static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
-/// Registers a custom OOM hook, replacing any that was previously registered.
+/// Registers a custom allocation error hook, replacing any that was previously registered.
///
-/// The OOM hook is invoked when an infallible memory allocation fails, before
+/// The allocation error hook is invoked when an infallible memory allocation fails, before
/// the runtime aborts. The default hook prints a message to standard error,
-/// but this behavior can be customized with the [`set_oom_hook`] and
-/// [`take_oom_hook`] functions.
+/// but this behavior can be customized with the [`set_alloc_error_hook`] and
+/// [`take_alloc_error_hook`] functions.
///
/// The hook is provided with a `Layout` struct which contains information
/// about the allocation that failed.
///
-/// The OOM hook is a global resource.
-#[unstable(feature = "oom_hook", issue = "51245")]
-pub fn set_oom_hook(hook: fn(Layout)) {
+/// The allocation error hook is a global resource.
+#[unstable(feature = "alloc_error_hook", issue = "51245")]
+pub fn set_alloc_error_hook(hook: fn(Layout)) {
HOOK.store(hook as *mut (), Ordering::SeqCst);
}
-/// Unregisters the current OOM hook, returning it.
+/// Unregisters the current allocation error hook, returning it.
///
-/// *See also the function [`set_oom_hook`].*
+/// *See also the function [`set_alloc_error_hook`].*
///
/// If no custom hook is registered, the default hook will be returned.
-#[unstable(feature = "oom_hook", issue = "51245")]
-pub fn take_oom_hook() -> fn(Layout) {
+#[unstable(feature = "alloc_error_hook", issue = "51245")]
+pub fn take_alloc_error_hook() -> fn(Layout) {
let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
if hook.is_null() {
- default_oom_hook
+ default_alloc_error_hook
} else {
unsafe { mem::transmute(hook) }
}
}
-fn default_oom_hook(layout: Layout) {
+fn default_alloc_error_hook(layout: Layout) {
dumb_print(format_args!("memory allocation of {} bytes failed", layout.size()));
}
pub extern fn rust_oom(layout: Layout) -> ! {
let hook = HOOK.load(Ordering::SeqCst);
let hook: fn(Layout) = if hook.is_null() {
- default_oom_hook
+ default_alloc_error_hook
} else {
unsafe { mem::transmute(hook) }
};
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use alloc::{Global, Alloc, Layout, LayoutErr, CollectionAllocErr, oom};
+use alloc::{Global, Alloc, Layout, LayoutErr, CollectionAllocErr, handle_alloc_error};
use hash::{BuildHasher, Hash, Hasher};
use marker;
use mem::{size_of, needs_drop};
// point into it.
let (layout, _) = calculate_layout::<K, V>(capacity)?;
let buffer = Global.alloc(layout).map_err(|e| match fallibility {
- Infallible => oom(layout),
+ Infallible => handle_alloc_error(layout),
Fallible => e,
})?;
fn test() {
let v: isize;
+ //[mir]~^ NOTE consider changing this to `mut v`
v = 1; //[ast]~ NOTE first assignment
//[mir]~^ NOTE first assignment
println!("v={}", v);
let y: Box<_> = box &mut x;
let p = &y;
***p = 2; //[ast]~ ERROR cannot assign to data in a `&` reference
- //[mir]~^ ERROR cannot assign to data in a `&` reference
+ //[mir]~^ ERROR cannot assign to `***p`
drop(p);
}
};
s[2] = 20;
//[ast]~^ ERROR cannot assign to immutable indexed content
- //[mir]~^^ ERROR cannot assign to immutable item
+ //[mir]~^^ ERROR cannot assign to data in a `&` reference
drop(rs);
}
fn test_drop_replace() {
let b: Box<isize>;
+ //[mir]~^ NOTE consider changing this to `mut b`
b = Box::new(1); //[ast]~ NOTE first assignment
//[mir]~^ NOTE first assignment
b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
fn test_call() {
let b = Box::new(1); //[ast]~ NOTE first assignment
//[mir]~^ NOTE first assignment
+ //[mir]~| NOTE consider changing this to `mut b`
b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
//[mir]~^ ERROR cannot assign twice to immutable variable `b`
//[ast]~| NOTE cannot assign twice to immutable
}
fn test_args(b: Box<i32>) { //[ast]~ NOTE first assignment
- //[mir]~^ NOTE argument not declared as `mut`
+ //[mir]~^ NOTE consider changing this to `mut b`
b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
//[mir]~^ ERROR cannot assign to immutable argument `b`
//[ast]~| NOTE cannot assign twice to immutable
fn test() {
let v: isize;
+ //[mir]~^ NOTE consider changing this to `mut v`
loop {
v = 1; //[ast]~ ERROR cannot assign twice to immutable variable
//[mir]~^ ERROR cannot assign twice to immutable variable `v`
fn test() {
let v: isize;
+ //[mir]~^ NOTE consider changing this to `mut v`
v = 2; //[ast]~ NOTE first assignment
//[mir]~^ NOTE first assignment
v += 1; //[ast]~ ERROR cannot assign twice to immutable variable
fn test() {
let b = Box::new(1); //[ast]~ NOTE first assignment
//[mir]~^ NOTE first assignment
+ //[mir]~| NOTE consider changing this to `mut b`
drop(b);
b = Box::new(2); //[ast]~ ERROR cannot assign twice to immutable variable
//[mir]~^ ERROR cannot assign twice to immutable variable `b`
fn test() {
let v: isize = 1; //[ast]~ NOTE first assignment
//[mir]~^ NOTE first assignment
+ //[mir]~| NOTE consider changing this to `mut v`
v.clone();
v = 2; //[ast]~ ERROR cannot assign twice to immutable variable
//[mir]~^ ERROR cannot assign twice to immutable variable `v`
call(|| {
counter += 1;
//[ast]~^ ERROR cannot assign to data in a captured outer variable in an `Fn` closure
- //[mir]~^^ ERROR cannot assign to immutable item `counter`
+ //[mir]~^^ ERROR cannot assign to `counter`
});
}
#![feature(allocator_api, nonnull)]
-use std::alloc::{Alloc, Global, Layout, oom};
+use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
fn main() {
unsafe {
- let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| oom(Layout::new::<i32>()));
+ let ptr = Global.alloc_one::<i32>().unwrap_or_else(|_| {
+ handle_alloc_error(Layout::new::<i32>())
+ });
*ptr.as_ptr() = 4;
assert_eq!(*ptr.as_ptr(), 4);
Global.dealloc_one(ptr);
#![feature(heap_api, allocator_api)]
-use std::alloc::{Global, Alloc, Layout, oom};
+use std::alloc::{Global, Alloc, Layout, handle_alloc_error};
use std::ptr::{self, NonNull};
fn main() {
println!("allocate({:?})", layout);
}
- let ret = Global.alloc(layout).unwrap_or_else(|_| oom(layout));
+ let ret = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
if PRINT {
println!("allocate({:?}) = {:?}", layout, ret);
}
let ret = Global.realloc(NonNull::new_unchecked(ptr), old, new.size())
- .unwrap_or_else(|_| oom(Layout::from_size_align_unchecked(new.size(), old.align())));
+ .unwrap_or_else(|_| handle_alloc_error(
+ Layout::from_size_align_unchecked(new.size(), old.align())
+ ));
if PRINT {
println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
#![feature(allocator_api)]
-use std::alloc::{Alloc, Global, Layout, oom};
+use std::alloc::{Alloc, Global, Layout, handle_alloc_error};
use std::ptr::NonNull;
struct arena(());
fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> {
unsafe {
let layout = Layout::new::<Bcx>();
- let ptr = Global.alloc(layout).unwrap_or_else(|_| oom(layout));
+ let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
&*(ptr.as_ptr() as *const _)
}
}
--- /dev/null
+error[E0384]: cannot assign twice to immutable variable `x`
+ --> $DIR/asm-out-assign-imm.rs:33:9
+ |
+LL | let x: isize;
+ | - consider changing this to `mut x`
+LL | x = 1;
+ | ----- first assignment to `x`
+...
+LL | asm!("mov $1, $0" : "=r"(x) : "r"(5));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0384`.
error[E0596]: cannot borrow immutable item `y` as mutable
--> $DIR/augmented-assignments.rs:30:5
|
+LL | let y = Int(2);
+ | - help: consider changing this to be mutable: `mut y`
+LL | //~^ consider changing this to `mut y`
LL | y //~ error: cannot borrow immutable local variable `y` as mutable
| ^ cannot borrow as mutable
--> $DIR/immutable-arg.rs:14:5
|
LL | fn foo(_x: u32) {
- | -- argument not declared as `mut`
+ | -- consider changing this to `mut _x`
LL | _x = 4;
| ^^^^^^ cannot assign to immutable argument
--> $DIR/issue-45983.rs:17:18
|
LL | give_any(|y| x = Some(y));
- | ^^^^^^^^^^^ cannot mutate
- |
- = note: the value which is causing this path not to be mutable is...: `x`
+ | ^^^^^^^^^^^ cannot assign
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/issue-45983.rs:17:14
|
+LL | let x = None;
+ | - help: consider changing this to be mutable: `mut x`
LL | give_any(|y| x = Some(y));
| ^^^^^^^^^^^^^^^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `b` as mutable
--> $DIR/mut-borrow-of-mut-ref.rs:18:7
|
+LL | fn f(b: &mut i32) {
+ | - help: consider changing this to be mutable: `mut b`
LL | g(&mut b) //~ ERROR cannot borrow
| ^^^^^^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/huge_multispan_highlight.rs:100:13
|
+LL | let x = "foo";
+ | - help: consider changing this to be mutable: `mut x`
+...
LL | let y = &mut x; //~ ERROR cannot borrow
| ^^^^^^ cannot borrow as mutable
--> $DIR/command-line-diagnostics.rs:16:5
|
LL | let x = 42;
- | -- first assignment to `x`
+ | - -- first assignment to `x`
+ | |
+ | consider changing this to `mut x`
LL | x = 43;
| ^^^^^^ cannot assign twice to immutable variable
error[E0596]: cannot borrow immutable item `self` as mutable
--> $DIR/issue-31424.rs:23:9
|
+LL | fn bar(self: &mut Self) {
+ | ---- help: consider changing this to be mutable: `mut self`
LL | (&mut self).bar(); //~ ERROR cannot borrow
| ^^^^^^^^^^^ cannot borrow as mutable
--> $DIR/issue-34126.rs:16:18
|
LL | self.run(&mut self); //~ ERROR cannot borrow
- | ^^^^^^^^^ cannot borrow as mutable
+ | ^^^^^^^^^
+ | |
+ | cannot borrow as mutable
+ | try removing `&mut` here
error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable
--> $DIR/issue-34126.rs:16:18
--> $DIR/issue-34337.rs:16:9
|
LL | get(&mut key); //~ ERROR cannot borrow
- | ^^^^^^^^ cannot borrow as mutable
+ | ^^^^^^^^
+ | |
+ | cannot borrow as mutable
+ | try removing `&mut` here
error: aborting due to previous error
error[E0596]: cannot borrow immutable item `f.v` as mutable
--> $DIR/issue-35937.rs:17:5
|
+LL | let f = Foo { v: Vec::new() };
+ | - help: consider changing this to be mutable: `mut f`
LL | f.v.push("cat".to_string()); //~ ERROR cannot borrow
| ^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `f`
error[E0384]: cannot assign twice to immutable variable `s.x`
--> $DIR/issue-35937.rs:26:5
|
LL | let s = S { x: 42 };
- | ----------- first assignment to `s.x`
+ | - ----------- first assignment to `s.x`
+ | |
+ | consider changing this to `mut s`
LL | s.x += 1; //~ ERROR cannot assign
| ^^^^^^^^ cannot assign twice to immutable variable
--> $DIR/issue-35937.rs:30:5
|
LL | fn bar(s: S) {
- | - first assignment to `s.x`
+ | -
+ | |
+ | first assignment to `s.x`
+ | consider changing this to `mut s`
LL | s.x += 1; //~ ERROR cannot assign
| ^^^^^^^^ cannot assign twice to immutable variable
--> $DIR/issue-37139.rs:22:18
|
LL | test(&mut x); //~ ERROR cannot borrow immutable
- | ^^^^^^ cannot borrow as mutable
+ | ^^^^^^
+ | |
+ | cannot borrow as mutable
+ | try removing `&mut` here
error: aborting due to previous error
error[E0596]: cannot borrow immutable item `*self.s` as mutable
--> $DIR/issue-38147-1.rs:27:9
|
+LL | fn f(&self) {
+ | ----- help: consider changing this to be a mutable reference: `&mut Foo<'_>`
LL | self.s.push('x'); //~ ERROR cannot borrow data mutably
- | ^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*self`
+ | ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to previous error
error[E0596]: cannot borrow immutable item `*f.s` as mutable
--> $DIR/issue-38147-4.rs:16:5
|
+LL | fn f(x: usize, f: &Foo) {
+ | ---- help: consider changing this to be a mutable reference: `&mut Foo<'_>`
LL | f.s.push('x'); //~ ERROR cannot borrow data mutably
- | ^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*f`
+ | ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to previous error
error[E0596]: cannot borrow immutable item `z.x` as mutable
--> $DIR/issue-39544.rs:21:13
|
+LL | let z = Z { x: X::Y };
+ | - help: consider changing this to be mutable: `mut z`
LL | let _ = &mut z.x; //~ ERROR cannot borrow
| ^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `z`
error[E0596]: cannot borrow immutable item `self.x` as mutable
--> $DIR/issue-39544.rs:26:17
|
+LL | fn foo<'z>(&'z self) {
+ | -------- help: consider changing this to be a mutable reference: `&mut Z`
LL | let _ = &mut self.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*self`
+ | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `self.x` as mutable
--> $DIR/issue-39544.rs:30:17
|
+LL | fn foo1(&self, other: &Z) {
+ | ----- help: consider changing this to be a mutable reference: `&mut Z`
LL | let _ = &mut self.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*self`
+ | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `other.x` as mutable
--> $DIR/issue-39544.rs:31:17
|
+LL | fn foo1(&self, other: &Z) {
+ | -- help: consider changing this to be a mutable reference: `&mut Z`
+LL | let _ = &mut self.x; //~ ERROR cannot borrow
LL | let _ = &mut other.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*other`
+ | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `self.x` as mutable
--> $DIR/issue-39544.rs:35:17
|
+LL | fn foo2<'a>(&'a self, other: &Z) {
+ | -------- help: consider changing this to be a mutable reference: `&mut Z`
LL | let _ = &mut self.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*self`
+ | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `other.x` as mutable
--> $DIR/issue-39544.rs:36:17
|
+LL | fn foo2<'a>(&'a self, other: &Z) {
+ | -- help: consider changing this to be a mutable reference: `&mut Z`
+LL | let _ = &mut self.x; //~ ERROR cannot borrow
LL | let _ = &mut other.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*other`
+ | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `self.x` as mutable
--> $DIR/issue-39544.rs:40:17
|
+LL | fn foo3<'a>(self: &'a Self, other: &Z) {
+ | -------- help: consider changing this to be a mutable reference: `&mut Z`
LL | let _ = &mut self.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*self`
+ | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `other.x` as mutable
--> $DIR/issue-39544.rs:41:17
|
+LL | fn foo3<'a>(self: &'a Self, other: &Z) {
+ | -- help: consider changing this to be a mutable reference: `&mut Z`
+LL | let _ = &mut self.x; //~ ERROR cannot borrow
LL | let _ = &mut other.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*other`
+ | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `other.x` as mutable
--> $DIR/issue-39544.rs:45:17
|
+LL | fn foo4(other: &Z) {
+ | -- help: consider changing this to be a mutable reference: `&mut Z`
LL | let _ = &mut other.x; //~ ERROR cannot borrow
- | ^^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*other`
+ | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `z.x` as mutable
--> $DIR/issue-39544.rs:51:13
|
+LL | pub fn with_arg(z: Z, w: &Z) {
+ | - help: consider changing this to be mutable: `mut z`
LL | let _ = &mut z.x; //~ ERROR cannot borrow
| ^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `z`
error[E0596]: cannot borrow immutable item `w.x` as mutable
--> $DIR/issue-39544.rs:52:13
|
+LL | pub fn with_arg(z: Z, w: &Z) {
+ | -- help: consider changing this to be a mutable reference: `&mut Z`
+LL | let _ = &mut z.x; //~ ERROR cannot borrow
LL | let _ = &mut w.x; //~ ERROR cannot borrow
- | ^^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*w`
+ | ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable
-error[E0594]: cannot assign to immutable item `*x.0`
+error[E0594]: cannot assign to `*x.0` which is behind a `&` reference
--> $DIR/issue-39544.rs:58:5
|
LL | *x.0 = 1;
- | ^^^^^^^^ cannot mutate
+ | ^^^^^^^^ cannot assign
error: aborting due to 12 previous errors
error[E0596]: cannot borrow immutable item `*buf` as mutable
--> $DIR/issue-40823.rs:13:5
|
+LL | let mut buf = &[1, 2, 3, 4];
+ | ------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4]`
LL | buf.iter_mut(); //~ ERROR cannot borrow immutable borrowed content
- | ^^^ cannot borrow as mutable
+ | ^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to previous error
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
--> $DIR/E0389.rs:18:5
|
LL | let fancy_ref = &(&mut fancy);
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/issue-36400.rs:15:7
|
+LL | let x = Box::new(3);
+ | - help: consider changing this to be mutable: `mut x`
LL | f(&mut *x); //~ ERROR cannot borrow immutable
| ^^^^^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `x`
error: aborting due to previous error
--> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:5
|
LL | fn foo(mut x: Ref, y: &u32) {
- | - argument not declared as `mut`
+ | - consider changing this to `mut y`
LL | y = x.b; //~ ERROR lifetime mismatch
| ^^^^^^^ cannot assign to immutable argument
error[E0596]: cannot borrow immutable item `y` as mutable
--> $DIR/ex3-both-anon-regions-using-fn-items.rs:11:3
|
+LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
+ | - help: consider changing this to be mutable: `mut y`
LL | y.push(z); //~ ERROR lifetime mismatch
| ^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `y` as mutable
--> $DIR/ex3-both-anon-regions-using-trait-objects.rs:11:3
|
+LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
+ | - help: consider changing this to be mutable: `mut y`
LL | y.push(z); //~ ERROR lifetime mismatch
| ^ cannot borrow as mutable
error[E0384]: cannot assign twice to immutable variable `x` (Mir)
--> $DIR/liveness-assign-imm-local-notes.rs:23:9
|
+LL | let x;
+ | - consider changing this to `mut x`
+...
LL | x = 2;
| ----- first assignment to `x`
LL | x = 3; //~ ERROR (Ast) [E0384]
error[E0384]: cannot assign twice to immutable variable `x` (Mir)
--> $DIR/liveness-assign-imm-local-notes.rs:35:13
|
+LL | let x;
+ | - consider changing this to `mut x`
+...
LL | x = 2;
| ----- first assignment to `x`
LL | x = 3; //~ ERROR (Ast) [E0384]
error[E0384]: cannot assign twice to immutable variable `x` (Mir)
--> $DIR/liveness-assign-imm-local-notes.rs:45:13
|
+LL | let x;
+ | - consider changing this to `mut x`
+...
LL | x = 1; //~ ERROR (Ast) [E0384]
| ^^^^^ cannot assign twice to immutable variable
error[E0384]: cannot assign twice to immutable variable `x` (Mir)
--> $DIR/liveness-assign-imm-local-notes.rs:48:13
|
+LL | let x;
+ | - consider changing this to `mut x`
+...
LL | x = 1; //~ ERROR (Ast) [E0384]
| ----- first assignment to `x`
...
error[E0596]: cannot borrow immutable item `foo` as mutable
--> $DIR/span-covering-argument-1.rs:15:14
|
+LL | let $s = 0;
+ | -- help: consider changing this to be mutable: `mut foo`
LL | *&mut $s = 0;
| ^^^^^^^ cannot borrow as mutable
...
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `fancy_ref.num` which is behind a `&` reference
--> $DIR/issue-47388.rs:18:5
|
LL | let fancy_ref = &(&mut fancy);
--- /dev/null
+// Copyright 2017 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.
+
+// Tests how we behave when the user attempts to mutate an immutable
+// binding that was introduced by either `ref` or `ref mut`
+// patterns.
+//
+// Such bindings cannot be made mutable via the mere addition of the
+// `mut` keyword, and thus we want to check that the compiler does not
+// suggest doing so.
+
+fn main() {
+ let (mut one_two, mut three_four) = ((1, 2), (3, 4));
+ let &mut (ref a, ref mut b) = &mut one_two;
+ a = &three_four.0;
+ //~^ ERROR cannot assign twice to immutable variable `a` [E0384]
+ b = &mut three_four.1;
+ //~^ ERROR cannot assign twice to immutable variable `b` [E0384]
+}
--- /dev/null
+error[E0384]: cannot assign twice to immutable variable `a`
+ --> $DIR/reassign-ref-mut.rs:22:5
+ |
+LL | let &mut (ref a, ref mut b) = &mut one_two;
+ | ----- first assignment to `a`
+LL | a = &three_four.0;
+ | ^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error[E0384]: cannot assign twice to immutable variable `b`
+ --> $DIR/reassign-ref-mut.rs:24:5
+ |
+LL | let &mut (ref a, ref mut b) = &mut one_two;
+ | --------- first assignment to `b`
+...
+LL | b = &mut three_four.1;
+ | ^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0384`.
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
--> $DIR/enum.rs:19:5
|
-LL | let Wrap(x) = &Wrap(3);
- | - help: consider changing this to be a mutable reference: `&mut`
LL | *x += 1; //~ ERROR cannot assign to immutable
- | ^^^^^^^
+ | ^^^^^^^ cannot assign
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
--> $DIR/enum.rs:23:9
|
-LL | if let Some(x) = &Some(3) {
- | - help: consider changing this to be a mutable reference: `&mut`
LL | *x += 1; //~ ERROR cannot assign to immutable
- | ^^^^^^^
+ | ^^^^^^^ cannot assign
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*x` which is behind a `&` reference
--> $DIR/enum.rs:29:9
|
-LL | while let Some(x) = &Some(3) {
- | - help: consider changing this to be a mutable reference: `&mut`
LL | *x += 1; //~ ERROR cannot assign to immutable
- | ^^^^^^^
+ | ^^^^^^^ cannot assign
error: aborting due to 3 previous errors
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
--> $DIR/explicit-mut.rs:17:13
|
-LL | Some(n) => {
- | - help: consider changing this to be a mutable reference: `&mut`
LL | *n += 1; //~ ERROR cannot assign to immutable
- | ^^^^^^^
+ | ^^^^^^^ cannot assign
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
--> $DIR/explicit-mut.rs:25:13
|
-LL | Some(n) => {
- | - help: consider changing this to be a mutable reference: `&mut`
LL | *n += 1; //~ ERROR cannot assign to immutable
- | ^^^^^^^
+ | ^^^^^^^ cannot assign
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to `*n` which is behind a `&` reference
--> $DIR/explicit-mut.rs:33:13
|
-LL | Some(n) => {
- | - help: consider changing this to be a mutable reference: `&mut`
LL | *n += 1; //~ ERROR cannot assign to immutable
- | ^^^^^^^
+ | ^^^^^^^ cannot assign
error: aborting due to 3 previous errors
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
|
+LL | fn deref_mut_field1(x: Own<Point>) {
+ | - help: consider changing this to be mutable: `mut x`
LL | let __isize = &mut x.y; //~ ERROR cannot borrow
| ^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:75:10
|
+LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
+ | ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
LL | &mut x.y //~ ERROR cannot borrow
- | ^ cannot borrow as mutable
+ | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
|
+LL | fn assign_field1<'a>(x: Own<Point>) {
+ | - help: consider changing this to be mutable: `mut x`
LL | x.y = 3; //~ ERROR cannot borrow
| ^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
|
+LL | fn assign_field2<'a>(x: &'a Own<Point>) {
+ | -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
LL | x.y = 3; //~ ERROR cannot borrow
- | ^ cannot borrow as mutable
+ | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
|
+LL | fn deref_mut_method1(x: Own<Point>) {
+ | - help: consider changing this to be mutable: `mut x`
LL | x.set(0, 0); //~ ERROR cannot borrow
| ^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:131:5
|
+LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
+ | ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
LL | x.y_mut() //~ ERROR cannot borrow
- | ^ cannot borrow as mutable
+ | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
|
+LL | fn assign_method1<'a>(x: Own<Point>) {
+ | - help: consider changing this to be mutable: `mut x`
LL | *x.y_mut() = 3; //~ ERROR cannot borrow
| ^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
|
+LL | fn assign_method2<'a>(x: &'a Own<Point>) {
+ | -------------- help: consider changing this to be a mutable reference: `&mut Own<Point>`
LL | *x.y_mut() = 3; //~ ERROR cannot borrow
- | ^ cannot borrow as mutable
+ | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to 8 previous errors
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
|
+LL | fn deref_mut1(x: Own<isize>) {
+ | - help: consider changing this to be mutable: `mut x`
LL | let __isize = &mut *x; //~ ERROR cannot borrow
| ^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
|
+LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
+ | -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
LL | &mut **x //~ ERROR cannot borrow
- | ^^ cannot borrow as mutable
+ | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `x` as mutable
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
|
+LL | fn assign1<'a>(x: Own<isize>) {
+ | - help: consider changing this to be mutable: `mut x`
LL | *x = 3; //~ ERROR cannot borrow
| ^ cannot borrow as mutable
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
|
+LL | fn assign2<'a>(x: &'a Own<isize>) {
+ | -------------- help: consider changing this to be a mutable reference: `&mut Own<isize>`
LL | **x = 3; //~ ERROR cannot borrow
- | ^^ cannot borrow as mutable
+ | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to 4 previous errors
error[E0596]: cannot borrow immutable item `*f` as mutable
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
|
+LL | fn test2<F>(f: &F) where F: FnMut() {
+ | -- help: consider changing this to be a mutable reference: `&mut F`
LL | (*f)();
- | ^^^^ cannot borrow as mutable
+ | ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `*f.f` as mutable
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
|
+LL | fn test4(f: &Test) {
+ | ----- help: consider changing this to be a mutable reference: `&mut Test<'_>`
LL | f.f.call_mut(())
- | ^^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*f`
+ | ^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-call-method-from-mut-aliasable.rs:27:5
|
+LL | fn b(x: &Foo) {
+ | ---- help: consider changing this to be a mutable reference: `&mut Foo`
+LL | x.f();
LL | x.h(); //~ ERROR cannot borrow
- | ^ cannot borrow as mutable
+ | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to previous error
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-fn-in-const-b.rs:17:9
|
+LL | fn broken(x: &Vec<String>) {
+ | ------------ help: consider changing this to be a mutable reference: `&mut std::vec::Vec<std::string::String>`
LL | x.push(format!("this is broken"));
- | ^ cannot borrow as mutable
+ | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to previous error
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-object-mutability.rs:19:5
|
+LL | fn borrowed_receiver(x: &Foo) {
+ | ---- help: consider changing this to be a mutable reference: `&mut Foo`
+LL | x.borrowed();
LL | x.borrowed_mut(); //~ ERROR cannot borrow
- | ^ cannot borrow as mutable
+ | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `*x` as mutable
--> $DIR/borrowck-object-mutability.rs:29:5
|
+LL | fn owned_receiver(x: Box<Foo>) {
+ | - help: consider changing this to be mutable: `mut x`
+LL | x.borrowed();
LL | x.borrowed_mut(); //~ ERROR cannot borrow
| ^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `x`
error: aborting due to 2 previous errors
error[E0596]: cannot borrow immutable item `*a` as mutable
--> $DIR/mut-arg-hint.rs:13:9
|
+LL | fn foo(mut a: &String) {
+ | ------- help: consider changing this to be a mutable reference: `&mut std::string::String`
LL | a.push_str("bar"); //~ ERROR cannot borrow immutable borrowed content
- | ^ cannot borrow as mutable
+ | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `*a` as mutable
--> $DIR/mut-arg-hint.rs:18:5
|
+LL | pub fn foo<'a>(mut a: &'a String) {
+ | ---------- help: consider changing this to be a mutable reference: `&mut std::string::String`
LL | a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
- | ^ cannot borrow as mutable
+ | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `*a` as mutable
--> $DIR/mut-arg-hint.rs:25:9
|
+LL | pub fn foo(mut a: &String) {
+ | ------- help: consider changing this to be a mutable reference: `&mut std::string::String`
LL | a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
- | ^ cannot borrow as mutable
+ | ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to 3 previous errors
--> $DIR/closure-immutable-outer-variable.rs:21:26
|
LL | foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
- | ^^^^^^^^^ cannot mutate
+ | ^^^^^^^^^ cannot assign
error: aborting due to previous error
-error[E0594]: cannot assign to immutable item `x`
+error[E0594]: cannot assign to `x` which is behind a `&` reference
--> $DIR/fn-closure-mutable-capture.rs:15:17
|
LL | bar(move || x = 1);
- | ^^^^^ cannot mutate
+ | ^^^^^ cannot assign
error: aborting due to previous error
error[E0596]: cannot borrow immutable item `**t` as mutable
--> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:16:5
|
+LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+ | --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
LL | *t //~ ERROR
- | ^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*t`
+ | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow immutable item `**t` as mutable
--> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:20:6
|
+LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy {
+ | --------------- help: consider changing this to be a mutable reference: `&mut &mut i32`
LL | {*t} //~ ERROR
- | ^^ cannot borrow as mutable
- |
- = note: the value which is causing this path not to be mutable is...: `*t`
+ | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error: aborting due to 2 previous errors