Auto merge of #52405 - matthewjasper:mutability-errors, r=pnkfelix
[NLL] Mutability errors cc #51028 cc #51170 cc #46559 Closes #46629 * Better explain why the place is immutable ("immutable item" is gone) * Distinguish &T and *const T * Use better spans when a mutable borrow is for a closure capture r? @pnkfelix
This commit is contained in:
commit
942b384d61
@ -531,6 +531,8 @@ pub enum BindingForm<'tcx> {
|
||||
Var(VarBindingForm<'tcx>),
|
||||
/// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
|
||||
ImplicitSelf,
|
||||
/// Reference used in a guard expression to ensure immutability.
|
||||
RefForGuard,
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! { BindingForm<'tcx>, }
|
||||
@ -555,6 +557,7 @@ mod binding_form_impl {
|
||||
match self {
|
||||
Var(binding) => binding.hash_stable(hcx, hasher),
|
||||
ImplicitSelf => (),
|
||||
RefForGuard => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
/// the local assigned at `location`.
|
||||
/// This is done by searching in statements succeeding `location`
|
||||
/// and originating from `maybe_closure_span`.
|
||||
fn find_closure_span(
|
||||
pub(super) fn find_closure_span(
|
||||
&self,
|
||||
maybe_closure_span: Span,
|
||||
location: Location,
|
||||
@ -742,6 +742,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
autoderef,
|
||||
&including_downcast,
|
||||
)?;
|
||||
} else if let Place::Local(local) = proj.base {
|
||||
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
|
||||
= self.mir.local_decls[local].is_user_variable {
|
||||
self.append_place_to_string(
|
||||
&proj.base,
|
||||
buf,
|
||||
autoderef,
|
||||
&including_downcast,
|
||||
)?;
|
||||
} else {
|
||||
buf.push_str(&"*");
|
||||
self.append_place_to_string(
|
||||
&proj.base,
|
||||
buf,
|
||||
autoderef,
|
||||
&including_downcast,
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
buf.push_str(&"*");
|
||||
self.append_place_to_string(
|
||||
|
@ -16,7 +16,7 @@ use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::definitions::DefPathData;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::lint::builtin::UNUSED_MUT;
|
||||
use rustc::mir::{self, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
|
||||
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
|
||||
use rustc::mir::{Terminator, TerminatorKind};
|
||||
@ -43,14 +43,13 @@ use dataflow::{do_dataflow, DebugFormatted};
|
||||
use dataflow::{EverInitializedPlaces, MovingOutStatements};
|
||||
use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
|
||||
use util::borrowck_errors::{BorrowckErrors, Origin};
|
||||
use util::collect_writes::FindAssignments;
|
||||
use util::suggest_ref_mut;
|
||||
|
||||
use self::borrow_set::{BorrowData, BorrowSet};
|
||||
use self::flows::Flows;
|
||||
use self::location::LocationTable;
|
||||
use self::prefixes::PrefixSet;
|
||||
use self::MutateMode::{JustWrite, WriteAndRead};
|
||||
use self::mutability_errors::AccessKind;
|
||||
|
||||
use self::path_utils::*;
|
||||
|
||||
@ -58,12 +57,13 @@ crate mod borrow_set;
|
||||
mod error_reporting;
|
||||
mod flows;
|
||||
mod location;
|
||||
mod move_errors;
|
||||
mod mutability_errors;
|
||||
mod path_utils;
|
||||
crate mod place_ext;
|
||||
mod places_conflict;
|
||||
mod prefixes;
|
||||
mod used_muts;
|
||||
mod move_errors;
|
||||
|
||||
pub(crate) mod nll;
|
||||
|
||||
@ -922,7 +922,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
let mutability_error =
|
||||
self.check_access_permissions(place_span, rw, is_local_mutation_allowed, flow_state);
|
||||
self.check_access_permissions(
|
||||
place_span,
|
||||
rw,
|
||||
is_local_mutation_allowed,
|
||||
flow_state,
|
||||
context.loc,
|
||||
);
|
||||
let conflict_error =
|
||||
self.check_access_for_conflict(context, place_span, sd, rw, flow_state);
|
||||
|
||||
@ -1668,6 +1674,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Check the permissions for the given place and read or write kind
|
||||
///
|
||||
/// Returns true if an error is reported, false otherwise.
|
||||
@ -1677,17 +1684,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
kind: ReadOrWrite,
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
flow_state: &Flows<'cx, 'gcx, 'tcx>,
|
||||
location: Location,
|
||||
) -> bool {
|
||||
debug!(
|
||||
"check_access_permissions({:?}, {:?}, {:?})",
|
||||
place, kind, is_local_mutation_allowed
|
||||
);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum AccessKind {
|
||||
MutableBorrow,
|
||||
Mutate,
|
||||
}
|
||||
let error_access;
|
||||
let the_place_err;
|
||||
|
||||
@ -1756,206 +1759,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// 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_user_variable.is_some() => {
|
||||
let local_decl = &self.mir.local_decls[*local];
|
||||
let suggestion = match local_decl.is_user_variable.as_ref().unwrap() {
|
||||
ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
|
||||
Some(suggest_ampmut_self(local_decl))
|
||||
},
|
||||
|
||||
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
..
|
||||
})) => Some(suggest_ampmut(
|
||||
self.tcx,
|
||||
self.mir,
|
||||
*local,
|
||||
local_decl,
|
||||
*opt_ty_info,
|
||||
)),
|
||||
|
||||
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
})) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
|
||||
|
||||
ClearCrossCrate::Clear => bug!("saw cleared local state"),
|
||||
};
|
||||
|
||||
if let Some((err_help_span, suggested_code)) = suggestion {
|
||||
err.span_suggestion(
|
||||
err_help_span,
|
||||
"consider changing this to be a mutable reference",
|
||||
suggested_code,
|
||||
);
|
||||
}
|
||||
|
||||
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();
|
||||
self.report_mutability_error(
|
||||
place,
|
||||
span,
|
||||
the_place_err,
|
||||
error_access,
|
||||
location,
|
||||
);
|
||||
return true;
|
||||
|
||||
fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
|
||||
local_decl: &mir::LocalDecl<'tcx>,
|
||||
) -> (Span, String) {
|
||||
(local_decl.source_info.span, "&mut self".to_string())
|
||||
}
|
||||
|
||||
// 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] [= RightHandSideExpression];
|
||||
// ^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// (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).
|
||||
//
|
||||
// This implementation attempts to emulate AST-borrowck prioritization
|
||||
// by trying (3.), then (2.) and finally falling back on (1.).
|
||||
fn suggest_ampmut<'cx, 'gcx, 'tcx>(
|
||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
local: Local,
|
||||
local_decl: &mir::LocalDecl<'tcx>,
|
||||
opt_ty_info: Option<Span>,
|
||||
) -> (Span, String) {
|
||||
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 {
|
||||
if src.starts_with('&') {
|
||||
let borrowed_expr = src[1..].to_string();
|
||||
return (
|
||||
assignment_rhs_span,
|
||||
format!("&mut {}", borrowed_expr),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let highlight_span = match opt_ty_info {
|
||||
// if this is a variable binding with an explicit type,
|
||||
// try to highlight that for the suggestion.
|
||||
Some(ty_span) => ty_span,
|
||||
|
||||
// otherwise, just highlight the span associated with
|
||||
// the (MIR) LocalDecl.
|
||||
None => local_decl.source_info.span,
|
||||
};
|
||||
|
||||
let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
|
||||
assert_eq!(ty_mut.mutbl, hir::MutImmutable);
|
||||
(highlight_span, format!("&mut {}", ty_mut.ty))
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds the place into the used mutable variables set
|
||||
|
469
src/librustc_mir/borrow_check/mutability_errors.rs
Normal file
469
src/librustc_mir/borrow_check/mutability_errors.rs
Normal file
@ -0,0 +1,469 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Mir};
|
||||
use rustc::mir::{Mutability, Place, Projection, ProjectionElem, Static};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use borrow_check::MirBorrowckCtxt;
|
||||
use util::borrowck_errors::{BorrowckErrors, Origin};
|
||||
use util::collect_writes::FindAssignments;
|
||||
use util::suggest_ref_mut;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(super) enum AccessKind {
|
||||
MutableBorrow,
|
||||
Mutate,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
||||
pub(super) fn report_mutability_error(
|
||||
&mut self,
|
||||
access_place: &Place<'tcx>,
|
||||
span: Span,
|
||||
the_place_err: &Place<'tcx>,
|
||||
error_access: AccessKind,
|
||||
location: Location,
|
||||
) {
|
||||
let mut err;
|
||||
let item_msg;
|
||||
let reason;
|
||||
let access_place_desc = self.describe_place(access_place);
|
||||
|
||||
match the_place_err {
|
||||
Place::Local(local) => {
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
if let Place::Local(_) = access_place {
|
||||
reason = ", as it is not declared as mutable".to_string();
|
||||
} else {
|
||||
let name = self.mir.local_decls[*local]
|
||||
.name
|
||||
.expect("immutable unnamed local");
|
||||
reason = format!(", as `{}` is not declared as mutable", name);
|
||||
}
|
||||
}
|
||||
|
||||
Place::Projection(box Projection {
|
||||
base,
|
||||
elem: ProjectionElem::Field(upvar_index, _),
|
||||
}) => {
|
||||
debug_assert!(is_closure_or_generator(
|
||||
base.ty(self.mir, self.tcx).to_ty(self.tcx)
|
||||
));
|
||||
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
if self.is_upvar(access_place) {
|
||||
reason = ", as it is not declared as mutable".to_string();
|
||||
} else {
|
||||
let name = self.mir.upvar_decls[upvar_index.index()].debug_name;
|
||||
reason = format!(", as `{}` is not declared as mutable", name);
|
||||
}
|
||||
}
|
||||
|
||||
Place::Projection(box Projection {
|
||||
base,
|
||||
elem: ProjectionElem::Deref,
|
||||
}) => {
|
||||
if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() {
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr());
|
||||
debug_assert!(is_closure_or_generator(
|
||||
the_place_err.ty(self.mir, self.tcx).to_ty(self.tcx)
|
||||
));
|
||||
|
||||
reason = if self.is_upvar(access_place) {
|
||||
", as it is a captured variable in a `Fn` closure".to_string()
|
||||
} else {
|
||||
format!(", as `Fn` closures cannot mutate their captured variables")
|
||||
}
|
||||
} else if {
|
||||
if let Place::Local(local) = *base {
|
||||
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
|
||||
= self.mir.local_decls[local].is_user_variable {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} {
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
reason = format!(", as it is immutable for the pattern guard");
|
||||
} else {
|
||||
let pointer_type =
|
||||
if base.ty(self.mir, self.tcx).to_ty(self.tcx).is_region_ptr() {
|
||||
"`&` reference"
|
||||
} else {
|
||||
"`*const` pointer"
|
||||
};
|
||||
if let Some(desc) = access_place_desc {
|
||||
item_msg = format!("`{}`", desc);
|
||||
reason = match error_access {
|
||||
AccessKind::Mutate => format!(" which is behind a {}", pointer_type),
|
||||
AccessKind::MutableBorrow => {
|
||||
format!(", as it is behind a {}", pointer_type)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
item_msg = format!("data in a {}", pointer_type);
|
||||
reason = "".to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Place::Static(box Static { def_id, ty: _ }) => {
|
||||
if let Place::Static(_) = access_place {
|
||||
item_msg = format!("immutable static item `{}`", access_place_desc.unwrap());
|
||||
reason = "".to_string();
|
||||
} else {
|
||||
item_msg = format!("`{}`", access_place_desc.unwrap());
|
||||
let static_name = &self.tcx.item_name(*def_id);
|
||||
reason = format!(", as `{}` is an immutable static item", static_name);
|
||||
}
|
||||
}
|
||||
|
||||
Place::Projection(box Projection {
|
||||
base: _,
|
||||
elem: ProjectionElem::Index(_),
|
||||
})
|
||||
| Place::Projection(box Projection {
|
||||
base: _,
|
||||
elem: ProjectionElem::ConstantIndex { .. },
|
||||
})
|
||||
| Place::Projection(box Projection {
|
||||
base: _,
|
||||
elem: ProjectionElem::Subslice { .. },
|
||||
})
|
||||
| Place::Projection(box Projection {
|
||||
base: _,
|
||||
elem: ProjectionElem::Downcast(..),
|
||||
}) => bug!("Unexpected immutable place."),
|
||||
}
|
||||
|
||||
// `act` and `acted_on` are strings that let us abstract over
|
||||
// the verbs used in some diagnostic messages.
|
||||
let act;
|
||||
let acted_on;
|
||||
|
||||
|
||||
let span = match error_access {
|
||||
AccessKind::Mutate => {
|
||||
err = self.tcx
|
||||
.cannot_assign(span, &(item_msg + &reason), Origin::Mir);
|
||||
act = "assign";
|
||||
acted_on = "written";
|
||||
span
|
||||
}
|
||||
AccessKind::MutableBorrow => {
|
||||
act = "borrow as mutable";
|
||||
acted_on = "borrowed as mutable";
|
||||
|
||||
let closure_span = self.find_closure_span(span, location);
|
||||
if let Some((args, var)) = closure_span {
|
||||
err = self.tcx.cannot_borrow_path_as_mutable_because(
|
||||
args,
|
||||
&item_msg,
|
||||
&reason,
|
||||
Origin::Mir,
|
||||
);
|
||||
err.span_label(
|
||||
var,
|
||||
format!(
|
||||
"mutable borrow occurs due to use of `{}` in closure",
|
||||
self.describe_place(access_place).unwrap(),
|
||||
),
|
||||
);
|
||||
args
|
||||
} else {
|
||||
err = self.tcx.cannot_borrow_path_as_mutable_because(
|
||||
span,
|
||||
&item_msg,
|
||||
&reason,
|
||||
Origin::Mir,
|
||||
);
|
||||
span
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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()),
|
||||
);
|
||||
}
|
||||
|
||||
// Also suggest adding mut for upvars
|
||||
Place::Projection(box Projection {
|
||||
base,
|
||||
elem: ProjectionElem::Field(upvar_index, _),
|
||||
}) => {
|
||||
debug_assert!(is_closure_or_generator(
|
||||
base.ty(self.mir, self.tcx).to_ty(self.tcx)
|
||||
));
|
||||
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
|
||||
let upvar_hir_id = self.mir.upvar_decls[upvar_index.index()]
|
||||
.var_hir_id
|
||||
.assert_crate_local();
|
||||
let upvar_node_id = self.tcx.hir.hir_to_node_id(upvar_hir_id);
|
||||
if let Some(hir::map::NodeBinding(pat)) = self.tcx.hir.find(upvar_node_id) {
|
||||
if let hir::PatKind::Binding(
|
||||
hir::BindingAnnotation::Unannotated,
|
||||
_,
|
||||
upvar_ident,
|
||||
_,
|
||||
) = pat.node
|
||||
{
|
||||
err.span_suggestion(
|
||||
upvar_ident.span,
|
||||
"consider changing this to be mutable",
|
||||
format!("mut {}", upvar_ident.name),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
Place::Projection(box Projection {
|
||||
base: Place::Local(local),
|
||||
elem: ProjectionElem::Deref,
|
||||
}) if {
|
||||
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard)) =
|
||||
self.mir.local_decls[*local].is_user_variable
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} =>
|
||||
{
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
err.note(
|
||||
"variables bound in patterns are immutable until the end of the pattern guard",
|
||||
);
|
||||
}
|
||||
|
||||
// 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_user_variable.is_some() =>
|
||||
{
|
||||
let local_decl = &self.mir.local_decls[*local];
|
||||
let suggestion = match local_decl.is_user_variable.as_ref().unwrap() {
|
||||
ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
|
||||
Some(suggest_ampmut_self(local_decl))
|
||||
}
|
||||
|
||||
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
..
|
||||
})) => Some(suggest_ampmut(
|
||||
self.tcx,
|
||||
self.mir,
|
||||
*local,
|
||||
local_decl,
|
||||
*opt_ty_info,
|
||||
)),
|
||||
|
||||
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
})) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
|
||||
|
||||
//
|
||||
ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => unreachable!(),
|
||||
|
||||
ClearCrossCrate::Clear => bug!("saw cleared local state"),
|
||||
};
|
||||
|
||||
let (pointer_sigil, pointer_desc) = if local_decl.ty.is_region_ptr() {
|
||||
("&", "reference")
|
||||
} else {
|
||||
("*const", "pointer")
|
||||
};
|
||||
|
||||
if let Some((err_help_span, suggested_code)) = suggestion {
|
||||
err.span_suggestion(
|
||||
err_help_span,
|
||||
&format!("consider changing this to be a mutable {}", pointer_desc),
|
||||
suggested_code,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(name) = local_decl.name {
|
||||
err.span_label(
|
||||
span,
|
||||
format!(
|
||||
"`{NAME}` is a `{SIGIL}` {DESC}, \
|
||||
so the data it refers to cannot be {ACTED_ON}",
|
||||
NAME = name,
|
||||
SIGIL = pointer_sigil,
|
||||
DESC = pointer_desc,
|
||||
ACTED_ON = acted_on
|
||||
),
|
||||
);
|
||||
} else {
|
||||
err.span_label(
|
||||
span,
|
||||
format!(
|
||||
"cannot {ACT} through `{SIGIL}` {DESC}",
|
||||
ACT = act,
|
||||
SIGIL = pointer_sigil,
|
||||
DESC = pointer_desc
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Place::Projection(box Projection {
|
||||
base,
|
||||
elem: ProjectionElem::Deref,
|
||||
}) if *base == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() =>
|
||||
{
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
err.span_help(
|
||||
self.mir.span,
|
||||
"consider changing this to accept closures that implement `FnMut`"
|
||||
);
|
||||
}
|
||||
|
||||
_ => {
|
||||
err.span_label(span, format!("cannot {ACT}", ACT = act));
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
// Does this place refer to what the user sees as an upvar
|
||||
fn is_upvar(&self, place: &Place<'tcx>) -> bool {
|
||||
match *place {
|
||||
Place::Projection(box Projection {
|
||||
ref base,
|
||||
elem: ProjectionElem::Field(_, _),
|
||||
}) => {
|
||||
let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
is_closure_or_generator(base_ty)
|
||||
}
|
||||
Place::Projection(box Projection {
|
||||
base:
|
||||
Place::Projection(box Projection {
|
||||
ref base,
|
||||
elem: ProjectionElem::Field(upvar_index, _),
|
||||
}),
|
||||
elem: ProjectionElem::Deref,
|
||||
}) => {
|
||||
let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
|
||||
is_closure_or_generator(base_ty) && self.mir.upvar_decls[upvar_index.index()].by_ref
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(local_decl: &mir::LocalDecl<'tcx>) -> (Span, String) {
|
||||
(local_decl.source_info.span, "&mut self".to_string())
|
||||
}
|
||||
|
||||
// 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] [= RightHandSideExpression];
|
||||
// ^^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// (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).
|
||||
//
|
||||
// This implementation attempts to emulate AST-borrowck prioritization
|
||||
// by trying (3.), then (2.) and finally falling back on (1.).
|
||||
fn suggest_ampmut<'cx, 'gcx, 'tcx>(
|
||||
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
local: Local,
|
||||
local_decl: &mir::LocalDecl<'tcx>,
|
||||
opt_ty_info: Option<Span>,
|
||||
) -> (Span, String) {
|
||||
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 {
|
||||
if src.starts_with('&') {
|
||||
let borrowed_expr = src[1..].to_string();
|
||||
return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let highlight_span = match opt_ty_info {
|
||||
// if this is a variable binding with an explicit type,
|
||||
// try to highlight that for the suggestion.
|
||||
Some(ty_span) => ty_span,
|
||||
|
||||
// otherwise, just highlight the span associated with
|
||||
// the (MIR) LocalDecl.
|
||||
None => local_decl.source_info.span,
|
||||
};
|
||||
|
||||
let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
|
||||
assert_eq!(ty_mut.mutbl, hir::MutImmutable);
|
||||
if local_decl.ty.is_region_ptr() {
|
||||
(highlight_span, format!("&mut {}", ty_mut.ty))
|
||||
} else {
|
||||
(highlight_span, format!("*mut {}", ty_mut.ty))
|
||||
}
|
||||
}
|
||||
|
||||
fn is_closure_or_generator(ty: ty::Ty) -> bool {
|
||||
ty.is_closure() || ty.is_generator()
|
||||
}
|
@ -206,7 +206,27 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
this.consume_by_copy_or_move(place)
|
||||
}
|
||||
_ => {
|
||||
unpack!(block = this.as_operand(block, scope, upvar))
|
||||
// Turn mutable borrow captures into unique
|
||||
// borrow captures when capturing an immutable
|
||||
// variable. This is sound because the mutation
|
||||
// that caused the capture will cause an error.
|
||||
match upvar.kind {
|
||||
ExprKind::Borrow {
|
||||
borrow_kind: BorrowKind::Mut {
|
||||
allow_two_phase_borrow: false
|
||||
},
|
||||
region,
|
||||
arg,
|
||||
} => unpack!(block = this.limit_capture_mutability(
|
||||
upvar.span,
|
||||
upvar.ty,
|
||||
scope,
|
||||
block,
|
||||
arg,
|
||||
region,
|
||||
)),
|
||||
_ => unpack!(block = this.as_operand(block, scope, upvar)),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -393,6 +413,101 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn limit_capture_mutability(
|
||||
&mut self,
|
||||
upvar_span: Span,
|
||||
upvar_ty: Ty<'tcx>,
|
||||
temp_lifetime: Option<region::Scope>,
|
||||
mut block: BasicBlock,
|
||||
arg: ExprRef<'tcx>,
|
||||
region: &'tcx ty::RegionKind,
|
||||
) -> BlockAnd<Operand<'tcx>> {
|
||||
let this = self;
|
||||
|
||||
let source_info = this.source_info(upvar_span);
|
||||
let temp = this.local_decls.push(LocalDecl::new_temp(upvar_ty, upvar_span));
|
||||
|
||||
this.cfg.push(block, Statement {
|
||||
source_info,
|
||||
kind: StatementKind::StorageLive(temp)
|
||||
});
|
||||
|
||||
let arg_place = unpack!(block = this.as_place(block, arg));
|
||||
|
||||
let mutability = match arg_place {
|
||||
Place::Local(local) => this.local_decls[local].mutability,
|
||||
Place::Projection(box Projection {
|
||||
base: Place::Local(local),
|
||||
elem: ProjectionElem::Deref,
|
||||
}) => {
|
||||
debug_assert!(
|
||||
if let Some(ClearCrossCrate::Set(BindingForm::RefForGuard))
|
||||
= this.local_decls[local].is_user_variable {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
},
|
||||
"Unexpected capture place",
|
||||
);
|
||||
this.local_decls[local].mutability
|
||||
}
|
||||
Place::Projection(box Projection {
|
||||
ref base,
|
||||
elem: ProjectionElem::Field(upvar_index, _),
|
||||
})
|
||||
| Place::Projection(box Projection {
|
||||
base: Place::Projection(box Projection {
|
||||
ref base,
|
||||
elem: ProjectionElem::Field(upvar_index, _),
|
||||
}),
|
||||
elem: ProjectionElem::Deref,
|
||||
}) => {
|
||||
// Not projected from the implicit `self` in a closure.
|
||||
debug_assert!(
|
||||
match *base {
|
||||
Place::Local(local) => local == Local::new(1),
|
||||
Place::Projection(box Projection {
|
||||
ref base,
|
||||
elem: ProjectionElem::Deref,
|
||||
}) => *base == Place::Local(Local::new(1)),
|
||||
_ => false,
|
||||
},
|
||||
"Unexpected capture place"
|
||||
);
|
||||
// Not in a closure
|
||||
debug_assert!(
|
||||
this.upvar_decls.len() > upvar_index.index(),
|
||||
"Unexpected capture place"
|
||||
);
|
||||
this.upvar_decls[upvar_index.index()].mutability
|
||||
}
|
||||
_ => bug!("Unexpected capture place"),
|
||||
};
|
||||
|
||||
let borrow_kind = match mutability {
|
||||
Mutability::Not => BorrowKind::Unique,
|
||||
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
};
|
||||
|
||||
this.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
&Place::Local(temp),
|
||||
Rvalue::Ref(region, borrow_kind, arg_place),
|
||||
);
|
||||
|
||||
// In constants, temp_lifetime is None. We should not need to drop
|
||||
// anything because no values with a destructor can be created in
|
||||
// a constant at this time, even if the type may need dropping.
|
||||
if let Some(temp_lifetime) = temp_lifetime {
|
||||
this.schedule_drop_storage_and_value(
|
||||
upvar_span, temp_lifetime, &Place::Local(temp), upvar_ty,
|
||||
);
|
||||
}
|
||||
|
||||
block.and(Operand::Move(Place::Local(temp)))
|
||||
}
|
||||
|
||||
// Helper to get a `-1` value of the appropriate type
|
||||
fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
|
||||
let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap());
|
||||
|
@ -1198,7 +1198,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
visibility_scope,
|
||||
// FIXME: should these secretly injected ref_for_guard's be marked as `internal`?
|
||||
internal: false,
|
||||
is_user_variable: None,
|
||||
is_user_variable: Some(ClearCrossCrate::Set(BindingForm::RefForGuard)),
|
||||
});
|
||||
LocalsForNode::Three { val_for_guard, ref_for_guard, for_arm_body }
|
||||
} else {
|
||||
|
@ -286,6 +286,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
/// (A match binding can have two locals; the 2nd is for the arm's guard.)
|
||||
var_indices: NodeMap<LocalsForNode>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
unit_temp: Option<Place<'tcx>>,
|
||||
|
||||
/// cached block with the RESUME terminator; this is created
|
||||
@ -472,11 +473,52 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
|
||||
let tcx = hir.tcx();
|
||||
let span = tcx.hir.span(fn_id);
|
||||
|
||||
// Gather the upvars of a closure, if any.
|
||||
let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
|
||||
freevars.iter().map(|fv| {
|
||||
let var_id = fv.var_id();
|
||||
let var_hir_id = tcx.hir.node_to_hir_id(var_id);
|
||||
let closure_expr_id = tcx.hir.local_def_id(fn_id);
|
||||
let capture = hir.tables().upvar_capture(ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
|
||||
});
|
||||
let by_ref = match capture {
|
||||
ty::UpvarCapture::ByValue => false,
|
||||
ty::UpvarCapture::ByRef(..) => true
|
||||
};
|
||||
let mut decl = UpvarDecl {
|
||||
debug_name: keywords::Invalid.name(),
|
||||
var_hir_id: ClearCrossCrate::Set(var_hir_id),
|
||||
by_ref,
|
||||
mutability: Mutability::Not,
|
||||
};
|
||||
if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_id) {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
|
||||
decl.debug_name = ident.name;
|
||||
|
||||
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
|
||||
if bm == ty::BindByValue(hir::MutMutable) {
|
||||
decl.mutability = Mutability::Mut;
|
||||
} else {
|
||||
decl.mutability = Mutability::Not;
|
||||
}
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
decl
|
||||
}).collect()
|
||||
});
|
||||
|
||||
let mut builder = Builder::new(hir.clone(),
|
||||
span,
|
||||
arguments.len(),
|
||||
safety,
|
||||
return_ty);
|
||||
return_ty,
|
||||
upvar_decls);
|
||||
|
||||
let fn_def_id = tcx.hir.local_def_id(fn_id);
|
||||
let call_site_scope = region::Scope::CallSite(body.value.hir_id.local_id);
|
||||
@ -519,46 +561,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
info!("fn_id {:?} has attrs {:?}", closure_expr_id,
|
||||
tcx.get_attrs(closure_expr_id));
|
||||
|
||||
// Gather the upvars of a closure, if any.
|
||||
let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| {
|
||||
freevars.iter().map(|fv| {
|
||||
let var_id = fv.var_id();
|
||||
let var_hir_id = tcx.hir.node_to_hir_id(var_id);
|
||||
let closure_expr_id = tcx.hir.local_def_id(fn_id);
|
||||
let capture = hir.tables().upvar_capture(ty::UpvarId {
|
||||
var_id: var_hir_id,
|
||||
closure_expr_id: LocalDefId::from_def_id(closure_expr_id),
|
||||
});
|
||||
let by_ref = match capture {
|
||||
ty::UpvarCapture::ByValue => false,
|
||||
ty::UpvarCapture::ByRef(..) => true
|
||||
};
|
||||
let mut decl = UpvarDecl {
|
||||
debug_name: keywords::Invalid.name(),
|
||||
var_hir_id: ClearCrossCrate::Set(var_hir_id),
|
||||
by_ref,
|
||||
mutability: Mutability::Not,
|
||||
};
|
||||
if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_id) {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
|
||||
decl.debug_name = ident.name;
|
||||
|
||||
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
|
||||
if bm == ty::BindByValue(hir::MutMutable) {
|
||||
decl.mutability = Mutability::Mut;
|
||||
} else {
|
||||
decl.mutability = Mutability::Not;
|
||||
}
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
decl
|
||||
}).collect()
|
||||
});
|
||||
|
||||
let mut mir = builder.finish(upvar_decls, yield_ty);
|
||||
let mut mir = builder.finish(yield_ty);
|
||||
mir.spread_arg = spread_arg;
|
||||
mir
|
||||
}
|
||||
@ -571,7 +574,7 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let ty = hir.tables().expr_ty_adjusted(ast_expr);
|
||||
let owner_id = tcx.hir.body_owner(body_id);
|
||||
let span = tcx.hir.span(owner_id);
|
||||
let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty);
|
||||
let mut builder = Builder::new(hir.clone(), span, 0, Safety::Safe, ty, vec![]);
|
||||
|
||||
let mut block = START_BLOCK;
|
||||
let expr = builder.hir.mirror(ast_expr);
|
||||
@ -590,7 +593,7 @@ fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
TerminatorKind::Unreachable);
|
||||
}
|
||||
|
||||
builder.finish(vec![], None)
|
||||
builder.finish(None)
|
||||
}
|
||||
|
||||
fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
@ -599,10 +602,10 @@ fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
let owner_id = hir.tcx().hir.body_owner(body_id);
|
||||
let span = hir.tcx().hir.span(owner_id);
|
||||
let ty = hir.tcx().types.err;
|
||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty);
|
||||
let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, vec![]);
|
||||
let source_info = builder.source_info(span);
|
||||
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
|
||||
builder.finish(vec![], None)
|
||||
builder.finish(None)
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
@ -610,7 +613,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
span: Span,
|
||||
arg_count: usize,
|
||||
safety: Safety,
|
||||
return_ty: Ty<'tcx>)
|
||||
return_ty: Ty<'tcx>,
|
||||
upvar_decls: Vec<UpvarDecl>)
|
||||
-> Builder<'a, 'gcx, 'tcx> {
|
||||
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
||||
let mut builder = Builder {
|
||||
@ -628,6 +632,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
breakable_scopes: vec![],
|
||||
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_place(return_ty,
|
||||
span), 1),
|
||||
upvar_decls,
|
||||
var_indices: NodeMap(),
|
||||
unit_temp: None,
|
||||
cached_resume_block: None,
|
||||
@ -645,7 +650,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
fn finish(self,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
yield_ty: Option<Ty<'tcx>>)
|
||||
-> Mir<'tcx> {
|
||||
for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
|
||||
@ -661,7 +665,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
yield_ty,
|
||||
self.local_decls,
|
||||
self.arg_count,
|
||||
upvar_decls,
|
||||
self.upvar_decls,
|
||||
self.fn_span
|
||||
)
|
||||
}
|
||||
|
@ -519,24 +519,35 @@ pub trait BorrowckErrors<'cx>: Sized + Copy {
|
||||
self.cancel_if_wrong_origin(err, o)
|
||||
}
|
||||
|
||||
fn cannot_borrow_path_as_mutable(
|
||||
fn cannot_borrow_path_as_mutable_because(
|
||||
self,
|
||||
span: Span,
|
||||
path: &str,
|
||||
reason: &str,
|
||||
o: Origin,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
let err = struct_span_err!(
|
||||
self,
|
||||
span,
|
||||
E0596,
|
||||
"cannot borrow {} as mutable{OGN}",
|
||||
"cannot borrow {} as mutable{}{OGN}",
|
||||
path,
|
||||
OGN = o
|
||||
reason,
|
||||
OGN = o,
|
||||
);
|
||||
|
||||
self.cancel_if_wrong_origin(err, o)
|
||||
}
|
||||
|
||||
fn cannot_borrow_path_as_mutable(
|
||||
self,
|
||||
span: Span,
|
||||
path: &str,
|
||||
o: Origin,
|
||||
) -> DiagnosticBuilder<'cx> {
|
||||
self.cannot_borrow_path_as_mutable_because(span, path, "", o)
|
||||
}
|
||||
|
||||
fn cannot_borrow_across_generator_yield(
|
||||
self,
|
||||
span: Span,
|
||||
|
@ -15,5 +15,5 @@ static NUM: i32 = 18;
|
||||
|
||||
fn main() {
|
||||
NUM = 20; //[ast]~ ERROR E0594
|
||||
//[mir]~^ ERROR cannot assign to immutable item `NUM`
|
||||
//[mir]~^ ERROR cannot assign to immutable static item `NUM`
|
||||
}
|
||||
|
@ -16,5 +16,5 @@ static foo: isize = 5;
|
||||
fn main() {
|
||||
// assigning to various global constants
|
||||
foo = 6; //[ast]~ ERROR cannot assign to immutable static item
|
||||
//[mir]~^ ERROR cannot assign to immutable item `foo`
|
||||
//[mir]~^ ERROR cannot assign to immutable static item `foo`
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ fn main() {
|
||||
let x = 1;
|
||||
to_fn_once(move|| { x = 2; });
|
||||
//[ast]~^ ERROR: cannot assign to immutable captured outer variable
|
||||
//[mir]~^^ ERROR: cannot assign to immutable item `x`
|
||||
//[mir]~^^ ERROR: cannot assign to `x`, as it is not declared as mutable
|
||||
|
||||
let s = std::io::stdin();
|
||||
to_fn_once(move|| { s.read_to_end(&mut Vec::new()); });
|
||||
//[ast]~^ ERROR: cannot borrow immutable captured outer variable
|
||||
//[mir]~^^ ERROR: cannot borrow immutable item `s` as mutable
|
||||
//[mir]~^^ ERROR: cannot borrow `s` as mutable, as it is not declared as mutable
|
||||
}
|
||||
|
@ -17,5 +17,5 @@
|
||||
static FOO: isize = 5;
|
||||
|
||||
fn main() {
|
||||
FOO = 6; //~ ERROR cannot assign to immutable item `FOO` [E0594]
|
||||
FOO = 6; //~ ERROR cannot assign to immutable static item `FOO` [E0594]
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ LL | | x; //~ value moved here
|
||||
| |_____move out of `x` occurs here
|
||||
| borrow later used here
|
||||
|
||||
error[E0596]: cannot borrow immutable item `y` as mutable
|
||||
error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable
|
||||
--> $DIR/augmented-assignments.rs:30:5
|
||||
|
|
||||
LL | let y = Int(2);
|
||||
|
@ -14,21 +14,14 @@ LL | give_any(|y| x = Some(y));
|
||||
| |
|
||||
| lifetime `'1` appears in this argument
|
||||
|
||||
error[E0594]: cannot assign to immutable item `x`
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/issue-45983.rs:17:18
|
||||
|
|
||||
LL | give_any(|y| x = Some(y));
|
||||
| ^^^^^^^^^^^ 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
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors occurred: E0594, E0596.
|
||||
For more information about an error, try `rustc --explain E0594`.
|
||||
For more information about this error, try `rustc --explain E0594`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `b` as mutable
|
||||
error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
|
||||
--> $DIR/mut-borrow-of-mut-ref.rs:18:7
|
||||
|
|
||||
LL | fn f(b: &mut i32) {
|
||||
|
379
src/test/ui/borrowck/mutability-errors.nll.stderr
Normal file
379
src/test/ui/borrowck/mutability-errors.nll.stderr
Normal file
@ -0,0 +1,379 @@
|
||||
error[E0594]: cannot assign to `*x` which is behind a `&` reference
|
||||
--> $DIR/mutability-errors.rs:19:5
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
|
||||
LL | *x = (1,); //~ ERROR
|
||||
| ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
error[E0594]: cannot assign to `x.0` which is behind a `&` reference
|
||||
--> $DIR/mutability-errors.rs:20:5
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
|
||||
LL | *x = (1,); //~ ERROR
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
|
||||
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/mutability-errors.rs:21:5
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
|
||||
...
|
||||
LL | &mut *x; //~ ERROR
|
||||
| ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/mutability-errors.rs:22:5
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- help: consider changing this to be a mutable reference: `&mut (i32,)`
|
||||
...
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0594]: cannot assign to data in a `&` reference
|
||||
--> $DIR/mutability-errors.rs:26:5
|
||||
|
|
||||
LL | *f() = (1,); //~ ERROR
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to data in a `&` reference
|
||||
--> $DIR/mutability-errors.rs:27:5
|
||||
|
|
||||
LL | f().0 = 1; //~ ERROR
|
||||
| ^^^^^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow data in a `&` reference as mutable
|
||||
--> $DIR/mutability-errors.rs:28:5
|
||||
|
|
||||
LL | &mut *f(); //~ ERROR
|
||||
| ^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow data in a `&` reference as mutable
|
||||
--> $DIR/mutability-errors.rs:29:5
|
||||
|
|
||||
LL | &mut f().0; //~ ERROR
|
||||
| ^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to `*x` which is behind a `*const` pointer
|
||||
--> $DIR/mutability-errors.rs:33:5
|
||||
|
|
||||
LL | unsafe fn named_ptr(x: *const (i32,)) {
|
||||
| ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
|
||||
LL | *x = (1,); //~ ERROR
|
||||
| ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
|
||||
|
||||
error[E0594]: cannot assign to `x.0` which is behind a `*const` pointer
|
||||
--> $DIR/mutability-errors.rs:34:5
|
||||
|
|
||||
LL | unsafe fn named_ptr(x: *const (i32,)) {
|
||||
| ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
|
||||
LL | *x = (1,); //~ ERROR
|
||||
LL | (*x).0 = 1; //~ ERROR
|
||||
| ^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written
|
||||
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer
|
||||
--> $DIR/mutability-errors.rs:35:5
|
||||
|
|
||||
LL | unsafe fn named_ptr(x: *const (i32,)) {
|
||||
| ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
|
||||
...
|
||||
LL | &mut *x; //~ ERROR
|
||||
| ^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `*const` pointer
|
||||
--> $DIR/mutability-errors.rs:36:5
|
||||
|
|
||||
LL | unsafe fn named_ptr(x: *const (i32,)) {
|
||||
| ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)`
|
||||
...
|
||||
LL | &mut (*x).0; //~ ERROR
|
||||
| ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0594]: cannot assign to data in a `*const` pointer
|
||||
--> $DIR/mutability-errors.rs:40:5
|
||||
|
|
||||
LL | *f() = (1,); //~ ERROR
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to data in a `*const` pointer
|
||||
--> $DIR/mutability-errors.rs:41:5
|
||||
|
|
||||
LL | (*f()).0 = 1; //~ ERROR
|
||||
| ^^^^^^^^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow data in a `*const` pointer as mutable
|
||||
--> $DIR/mutability-errors.rs:42:5
|
||||
|
|
||||
LL | &mut *f(); //~ ERROR
|
||||
| ^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow data in a `*const` pointer as mutable
|
||||
--> $DIR/mutability-errors.rs:43:5
|
||||
|
|
||||
LL | &mut (*f()).0; //~ ERROR
|
||||
| ^^^^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:50:9
|
||||
|
|
||||
LL | x = (1,); //~ ERROR
|
||||
| ^^^^^^^^ cannot assign
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
|
||||
--> $DIR/mutability-errors.rs:51:9
|
||||
|
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot assign
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:52:9
|
||||
|
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^^^^^^ cannot borrow as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
|
||||
--> $DIR/mutability-errors.rs:53:9
|
||||
|
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:56:9
|
||||
|
|
||||
LL | x = (1,); //~ ERROR
|
||||
| ^^^^^^^^ cannot assign
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:55:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables
|
||||
--> $DIR/mutability-errors.rs:57:9
|
||||
|
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot assign
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:55:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:58:9
|
||||
|
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^^^^^^ cannot borrow as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:55:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables
|
||||
--> $DIR/mutability-errors.rs:59:9
|
||||
|
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/mutability-errors.rs:55:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:64:5
|
||||
|
|
||||
LL | fn imm_local(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:65:5
|
||||
|
|
||||
LL | fn imm_local(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | &mut x; //~ ERROR
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:70:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | || { //~ ERROR
|
||||
LL | x = (1,);
|
||||
| ^^^^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:71:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x.0 = 1;
|
||||
| ^^^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:72:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:73:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | &mut x.0;
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:76:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = (1,); //~ ERROR
|
||||
| ^^^^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:77:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:78:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
|
||||
--> $DIR/mutability-errors.rs:79:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to immutable static item `X`
|
||||
--> $DIR/mutability-errors.rs:86:5
|
||||
|
|
||||
LL | X = (1,); //~ ERROR
|
||||
| ^^^^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to `X.0`, as `X` is an immutable static item
|
||||
--> $DIR/mutability-errors.rs:87:5
|
||||
|
|
||||
LL | X.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow immutable static item `X` as mutable
|
||||
--> $DIR/mutability-errors.rs:88:5
|
||||
|
|
||||
LL | &mut X; //~ ERROR
|
||||
| ^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item
|
||||
--> $DIR/mutability-errors.rs:89:5
|
||||
|
|
||||
LL | &mut X.0; //~ ERROR
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error: aborting due to 38 previous errors
|
||||
|
||||
Some errors occurred: E0594, E0596.
|
||||
For more information about an error, try `rustc --explain E0594`.
|
92
src/test/ui/borrowck/mutability-errors.rs
Normal file
92
src/test/ui/borrowck/mutability-errors.rs
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// All the possible mutability error cases.
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
type MakeRef = fn() -> &'static (i32,);
|
||||
type MakePtr = fn() -> *const (i32,);
|
||||
|
||||
fn named_ref(x: &(i32,)) {
|
||||
*x = (1,); //~ ERROR
|
||||
x.0 = 1; //~ ERROR
|
||||
&mut *x; //~ ERROR
|
||||
&mut x.0; //~ ERROR
|
||||
}
|
||||
|
||||
fn unnamed_ref(f: MakeRef) {
|
||||
*f() = (1,); //~ ERROR
|
||||
f().0 = 1; //~ ERROR
|
||||
&mut *f(); //~ ERROR
|
||||
&mut f().0; //~ ERROR
|
||||
}
|
||||
|
||||
unsafe fn named_ptr(x: *const (i32,)) {
|
||||
*x = (1,); //~ ERROR
|
||||
(*x).0 = 1; //~ ERROR
|
||||
&mut *x; //~ ERROR
|
||||
&mut (*x).0; //~ ERROR
|
||||
}
|
||||
|
||||
unsafe fn unnamed_ptr(f: MakePtr) {
|
||||
*f() = (1,); //~ ERROR
|
||||
(*f()).0 = 1; //~ ERROR
|
||||
&mut *f(); //~ ERROR
|
||||
&mut (*f()).0; //~ ERROR
|
||||
}
|
||||
|
||||
fn fn_ref<F: Fn()>(f: F) -> F { f }
|
||||
|
||||
fn ref_closure(mut x: (i32,)) {
|
||||
fn_ref(|| {
|
||||
x = (1,); //~ ERROR
|
||||
x.0 = 1; //~ ERROR
|
||||
&mut x; //~ ERROR
|
||||
&mut x.0; //~ ERROR
|
||||
});
|
||||
fn_ref(move || {
|
||||
x = (1,); //~ ERROR
|
||||
x.0 = 1; //~ ERROR
|
||||
&mut x; //~ ERROR
|
||||
&mut x.0; //~ ERROR
|
||||
});
|
||||
}
|
||||
|
||||
fn imm_local(x: (i32,)) {
|
||||
&mut x; //~ ERROR
|
||||
&mut x.0; //~ ERROR
|
||||
}
|
||||
|
||||
fn imm_capture(x: (i32,)) {
|
||||
|| { //~ ERROR
|
||||
x = (1,);
|
||||
x.0 = 1;
|
||||
&mut x;
|
||||
&mut x.0;
|
||||
};
|
||||
move || {
|
||||
x = (1,); //~ ERROR
|
||||
x.0 = 1; //~ ERROR
|
||||
&mut x; //~ ERROR
|
||||
&mut x.0; //~ ERROR
|
||||
};
|
||||
}
|
||||
|
||||
static X: (i32,) = (0,);
|
||||
|
||||
fn imm_static() {
|
||||
X = (1,); //~ ERROR
|
||||
X.0 = 1; //~ ERROR
|
||||
&mut X; //~ ERROR
|
||||
&mut X.0; //~ ERROR
|
||||
}
|
||||
|
||||
fn main() {}
|
308
src/test/ui/borrowck/mutability-errors.stderr
Normal file
308
src/test/ui/borrowck/mutability-errors.stderr
Normal file
@ -0,0 +1,308 @@
|
||||
error[E0594]: cannot assign to immutable borrowed content `*x`
|
||||
--> $DIR/mutability-errors.rs:19:5
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- use `&mut (i32,)` here to make mutable
|
||||
LL | *x = (1,); //~ ERROR
|
||||
| ^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to field `x.0` of immutable binding
|
||||
--> $DIR/mutability-errors.rs:20:5
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- use `&mut (i32,)` here to make mutable
|
||||
LL | *x = (1,); //~ ERROR
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
|
||||
--> $DIR/mutability-errors.rs:21:10
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- use `&mut (i32,)` here to make mutable
|
||||
...
|
||||
LL | &mut *x; //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:22:10
|
||||
|
|
||||
LL | fn named_ref(x: &(i32,)) {
|
||||
| ------- use `&mut (i32,)` here to make mutable
|
||||
...
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0594]: cannot assign to immutable borrowed content
|
||||
--> $DIR/mutability-errors.rs:26:5
|
||||
|
|
||||
LL | *f() = (1,); //~ ERROR
|
||||
| ^^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to field of immutable binding
|
||||
--> $DIR/mutability-errors.rs:27:5
|
||||
|
|
||||
LL | f().0 = 1; //~ ERROR
|
||||
| ^^^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow immutable borrowed content as mutable
|
||||
--> $DIR/mutability-errors.rs:28:10
|
||||
|
|
||||
LL | &mut *f(); //~ ERROR
|
||||
| ^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow field of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:29:10
|
||||
|
|
||||
LL | &mut f().0; //~ ERROR
|
||||
| ^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0594]: cannot assign to immutable dereference of raw pointer `*x`
|
||||
--> $DIR/mutability-errors.rs:33:5
|
||||
|
|
||||
LL | *x = (1,); //~ ERROR
|
||||
| ^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to field `x.0` of immutable binding
|
||||
--> $DIR/mutability-errors.rs:34:5
|
||||
|
|
||||
LL | (*x).0 = 1; //~ ERROR
|
||||
| ^^^^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow immutable dereference of raw pointer `*x` as mutable
|
||||
--> $DIR/mutability-errors.rs:35:10
|
||||
|
|
||||
LL | &mut *x; //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:36:10
|
||||
|
|
||||
LL | &mut (*x).0; //~ ERROR
|
||||
| ^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0594]: cannot assign to immutable dereference of raw pointer
|
||||
--> $DIR/mutability-errors.rs:40:5
|
||||
|
|
||||
LL | *f() = (1,); //~ ERROR
|
||||
| ^^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0594]: cannot assign to field of immutable binding
|
||||
--> $DIR/mutability-errors.rs:41:5
|
||||
|
|
||||
LL | (*f()).0 = 1; //~ ERROR
|
||||
| ^^^^^^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow immutable dereference of raw pointer as mutable
|
||||
--> $DIR/mutability-errors.rs:42:10
|
||||
|
|
||||
LL | &mut *f(); //~ ERROR
|
||||
| ^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow field of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:43:10
|
||||
|
|
||||
LL | &mut (*f()).0; //~ ERROR
|
||||
| ^^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:50:9
|
||||
|
|
||||
LL | x = (1,); //~ ERROR
|
||||
| ^^^^^^^^
|
||||
|
|
||||
help: consider changing this closure to take self by mutable reference
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0387]: cannot assign to data in a captured outer variable in an `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:51:9
|
||||
|
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: consider changing this closure to take self by mutable reference
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:52:14
|
||||
|
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^
|
||||
|
|
||||
help: consider changing this closure to take self by mutable reference
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:53:14
|
||||
|
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^
|
||||
|
|
||||
help: consider changing this closure to take self by mutable reference
|
||||
--> $DIR/mutability-errors.rs:49:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0594]: cannot assign to captured outer variable in an `Fn` closure
|
||||
--> $DIR/mutability-errors.rs:56:9
|
||||
|
|
||||
LL | x = (1,); //~ ERROR
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: `Fn` closures cannot capture their enclosing environment for modifications
|
||||
help: consider changing this closure to take self by mutable reference
|
||||
--> $DIR/mutability-errors.rs:55:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0594]: cannot assign to field `x.0` of immutable binding
|
||||
--> $DIR/mutability-errors.rs:57:9
|
||||
|
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow captured outer variable in an `Fn` closure as mutable
|
||||
--> $DIR/mutability-errors.rs:58:14
|
||||
|
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^
|
||||
|
|
||||
help: consider changing this closure to take self by mutable reference
|
||||
--> $DIR/mutability-errors.rs:55:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | x = (1,); //~ ERROR
|
||||
LL | | x.0 = 1; //~ ERROR
|
||||
LL | | &mut x; //~ ERROR
|
||||
LL | | &mut x.0; //~ ERROR
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:59:14
|
||||
|
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow immutable argument `x` as mutable
|
||||
--> $DIR/mutability-errors.rs:64:10
|
||||
|
|
||||
LL | fn imm_local(x: (i32,)) {
|
||||
| - consider changing this to `mut x`
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^ cannot borrow mutably
|
||||
|
||||
error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:65:10
|
||||
|
|
||||
LL | fn imm_local(x: (i32,)) {
|
||||
| - consider changing this to `mut x`
|
||||
LL | &mut x; //~ ERROR
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0595]: closure cannot assign to immutable argument `x`
|
||||
--> $DIR/mutability-errors.rs:69:5
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - consider changing this to `mut x`
|
||||
LL | || { //~ ERROR
|
||||
| ^^ cannot borrow mutably
|
||||
|
||||
error[E0594]: cannot assign to captured outer variable in an `FnMut` closure
|
||||
--> $DIR/mutability-errors.rs:76:9
|
||||
|
|
||||
LL | fn imm_capture(x: (i32,)) {
|
||||
| - help: consider making `x` mutable: `mut x`
|
||||
...
|
||||
LL | x = (1,); //~ ERROR
|
||||
| ^^^^^^^^
|
||||
|
||||
error[E0594]: cannot assign to field `x.0` of immutable binding
|
||||
--> $DIR/mutability-errors.rs:77:9
|
||||
|
|
||||
LL | x.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow captured outer variable in an `FnMut` closure as mutable
|
||||
--> $DIR/mutability-errors.rs:78:14
|
||||
|
|
||||
LL | &mut x; //~ ERROR
|
||||
| ^
|
||||
|
||||
error[E0596]: cannot borrow field `x.0` of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:79:14
|
||||
|
|
||||
LL | &mut x.0; //~ ERROR
|
||||
| ^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0594]: cannot assign to immutable static item
|
||||
--> $DIR/mutability-errors.rs:86:5
|
||||
|
|
||||
LL | X = (1,); //~ ERROR
|
||||
| ^^^^^^^^
|
||||
|
||||
error[E0594]: cannot assign to field of immutable binding
|
||||
--> $DIR/mutability-errors.rs:87:5
|
||||
|
|
||||
LL | X.0 = 1; //~ ERROR
|
||||
| ^^^^^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error[E0596]: cannot borrow immutable static item as mutable
|
||||
--> $DIR/mutability-errors.rs:88:10
|
||||
|
|
||||
LL | &mut X; //~ ERROR
|
||||
| ^
|
||||
|
||||
error[E0596]: cannot borrow field of immutable binding as mutable
|
||||
--> $DIR/mutability-errors.rs:89:10
|
||||
|
|
||||
LL | &mut X.0; //~ ERROR
|
||||
| ^^^ cannot mutably borrow field of immutable binding
|
||||
|
||||
error: aborting due to 35 previous errors
|
||||
|
||||
Some errors occurred: E0387, E0594, E0595, E0596.
|
||||
For more information about an error, try `rustc --explain E0387`.
|
@ -1,6 +1,8 @@
|
||||
error[E0594]: cannot assign to immutable item `y`
|
||||
error[E0594]: cannot assign to `y`, as it is not declared as mutable
|
||||
--> $DIR/closure-immutable-outer-variable.rs:21:26
|
||||
|
|
||||
LL | let y = true;
|
||||
| - help: consider changing this to be mutable: `mut y`
|
||||
LL | foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
|
||||
| ^^^^^^^^^ cannot assign
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/huge_multispan_highlight.rs:100:13
|
||||
|
|
||||
LL | let x = "foo";
|
||||
|
@ -1,10 +1,10 @@
|
||||
error[E0596]: cannot borrow immutable item `self` as mutable
|
||||
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-31424.rs:17:9
|
||||
|
|
||||
LL | (&mut self).bar(); //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `self` as mutable
|
||||
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-31424.rs:23:9
|
||||
|
|
||||
LL | fn bar(self: &mut Self) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `self` as mutable
|
||||
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-34126.rs:16:18
|
||||
|
|
||||
LL | self.run(&mut self); //~ ERROR cannot borrow
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `key` as mutable
|
||||
error[E0596]: cannot borrow `key` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-34337.rs:16:9
|
||||
|
|
||||
LL | get(&mut key); //~ ERROR cannot borrow
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `f.v` as mutable
|
||||
error[E0596]: cannot borrow `f.v` as mutable, as `f` is not declared as mutable
|
||||
--> $DIR/issue-35937.rs:17:5
|
||||
|
|
||||
LL | let f = Foo { v: Vec::new() };
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-37139.rs:22:18
|
||||
|
|
||||
LL | test(&mut x); //~ ERROR cannot borrow immutable
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*self.s` as mutable
|
||||
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-38147-1.rs:27:9
|
||||
|
|
||||
LL | fn f(&self) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*self.s` as mutable
|
||||
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-38147-2.rs:17:9
|
||||
|
|
||||
LL | self.s.push('x');
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*self.s` as mutable
|
||||
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-38147-3.rs:17:9
|
||||
|
|
||||
LL | self.s.push('x');
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*f.s` as mutable
|
||||
error[E0596]: cannot borrow `*f.s` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-38147-4.rs:16:5
|
||||
|
|
||||
LL | fn f(x: usize, f: &Foo) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `z.x` as mutable
|
||||
error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable
|
||||
--> $DIR/issue-39544.rs:21:13
|
||||
|
|
||||
LL | let z = Z { x: X::Y };
|
||||
@ -6,7 +6,7 @@ LL | let z = Z { x: X::Y };
|
||||
LL | let _ = &mut z.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `self.x` as mutable
|
||||
error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:26:17
|
||||
|
|
||||
LL | fn foo<'z>(&'z self) {
|
||||
@ -14,7 +14,7 @@ LL | fn foo<'z>(&'z self) {
|
||||
LL | let _ = &mut self.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:30:17
|
||||
|
|
||||
LL | fn foo1(&self, other: &Z) {
|
||||
@ -22,7 +22,7 @@ LL | fn foo1(&self, other: &Z) {
|
||||
LL | let _ = &mut self.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:31:17
|
||||
|
|
||||
LL | fn foo1(&self, other: &Z) {
|
||||
@ -31,7 +31,7 @@ LL | let _ = &mut self.x; //~ ERROR cannot borrow
|
||||
LL | let _ = &mut other.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:35:17
|
||||
|
|
||||
LL | fn foo2<'a>(&'a self, other: &Z) {
|
||||
@ -39,7 +39,7 @@ LL | fn foo2<'a>(&'a self, other: &Z) {
|
||||
LL | let _ = &mut self.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:36:17
|
||||
|
|
||||
LL | fn foo2<'a>(&'a self, other: &Z) {
|
||||
@ -48,7 +48,7 @@ LL | let _ = &mut self.x; //~ ERROR cannot borrow
|
||||
LL | let _ = &mut other.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:40:17
|
||||
|
|
||||
LL | fn foo3<'a>(self: &'a Self, other: &Z) {
|
||||
@ -56,7 +56,7 @@ LL | fn foo3<'a>(self: &'a Self, other: &Z) {
|
||||
LL | let _ = &mut self.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:41:17
|
||||
|
|
||||
LL | fn foo3<'a>(self: &'a Self, other: &Z) {
|
||||
@ -65,7 +65,7 @@ LL | let _ = &mut self.x; //~ ERROR cannot borrow
|
||||
LL | let _ = &mut other.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:45:17
|
||||
|
|
||||
LL | fn foo4(other: &Z) {
|
||||
@ -73,7 +73,7 @@ LL | fn foo4(other: &Z) {
|
||||
LL | let _ = &mut other.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^^^^^ `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
|
||||
error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable
|
||||
--> $DIR/issue-39544.rs:51:13
|
||||
|
|
||||
LL | pub fn with_arg(z: Z, w: &Z) {
|
||||
@ -81,7 +81,7 @@ LL | pub fn with_arg(z: Z, w: &Z) {
|
||||
LL | let _ = &mut z.x; //~ ERROR cannot borrow
|
||||
| ^^^^^^^^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `w.x` as mutable
|
||||
error[E0596]: cannot borrow `w.x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-39544.rs:52:13
|
||||
|
|
||||
LL | pub fn with_arg(z: Z, w: &Z) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*buf` as mutable
|
||||
error[E0596]: cannot borrow `*buf` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/issue-40823.rs:13:5
|
||||
|
|
||||
LL | let mut buf = &[1, 2, 3, 4];
|
||||
|
@ -10,7 +10,7 @@ error[E0017]: references in statics may only refer to immutable values
|
||||
LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
|
||||
| ^^^^^^ statics require immutable values
|
||||
|
||||
error[E0596]: cannot borrow immutable item `X` as mutable
|
||||
error[E0596]: cannot borrow immutable static item `X` as mutable
|
||||
--> $DIR/E0017.rs:15:39
|
||||
|
|
||||
LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
|
||||
|
@ -10,7 +10,7 @@ error[E0017]: references in statics may only refer to immutable values
|
||||
LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
|
||||
| ^^^^^^ statics require immutable values
|
||||
|
||||
error[E0596]: cannot borrow immutable item `X` as mutable
|
||||
error[E0596]: cannot borrow immutable static item `X` as mutable
|
||||
--> $DIR/E0388.rs:15:39
|
||||
|
|
||||
LL | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0017
|
||||
|
@ -1,8 +1,14 @@
|
||||
error[E0594]: cannot assign to `x` which is behind a `&` reference
|
||||
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/fn-closure-mutable-capture.rs:15:17
|
||||
|
|
||||
LL | bar(move || x = 1);
|
||||
| ^^^^^ cannot assign
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/fn-closure-mutable-capture.rs:15:9
|
||||
|
|
||||
LL | bar(move || x = 1);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,14 +1,33 @@
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/issue-21600.rs:24:20
|
||||
|
|
||||
LL | call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/issue-21600.rs:24:17
|
||||
|
|
||||
LL | call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
|
||||
| ^^^^^^^^^^^^^^ cannot borrow as mutable
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/issue-21600.rs:24:17
|
||||
|
|
||||
LL | call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
|
||||
| ^^ - mutable borrow occurs due to use of `x` in closure
|
||||
| |
|
||||
| cannot borrow as mutable
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/issue-21600.rs:22:13
|
||||
|
|
||||
LL | call_it(|| {
|
||||
| _____________^
|
||||
LL | | call_it(|| x.gen());
|
||||
LL | | call_it(|| x.gen_mut()); //~ ERROR cannot borrow data mutably in a captured outer
|
||||
LL | | //~^ ERROR cannot borrow data mutably in a captured outer
|
||||
LL | | });
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -24,7 +24,7 @@ fn main() {
|
||||
match b {
|
||||
&mut false => {},
|
||||
ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
|
||||
//~^ ERROR cannot borrow immutable item `*r` as mutable
|
||||
//~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard
|
||||
false } => { &mut *r; },
|
||||
&mut true => { println!("You might think we should get here"); },
|
||||
_ => panic!("surely we could never get here, since rustc warns it is unreachable."),
|
||||
|
@ -1,8 +1,12 @@
|
||||
error[E0596]: cannot borrow immutable item `*r` as mutable
|
||||
--> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:26:24
|
||||
error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard
|
||||
--> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:26:25
|
||||
|
|
||||
LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
||||
| ^^ - mutable borrow occurs due to use of `r` in closure
|
||||
| |
|
||||
| cannot borrow as mutable
|
||||
|
|
||||
= note: variables bound in patterns are immutable until the end of the pattern guard
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `v` as mutable
|
||||
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-33819.rs:13:34
|
||||
|
|
||||
LL | Some(ref v) => { let a = &mut v; },
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
|
||||
--> $DIR/issue-36400.rs:15:7
|
||||
|
|
||||
LL | let x = Box::new(3);
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item as mutable
|
||||
error[E0596]: cannot borrow data in a `&` reference as mutable
|
||||
--> $DIR/issue-41726.rs:15:9
|
||||
|
|
||||
LL | things[src.as_str()].sort(); //~ ERROR cannot borrow immutable
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*TAB[..]` as mutable
|
||||
error[E0596]: cannot borrow `*TAB[..]` as mutable, as `TAB` is an immutable static item
|
||||
--> $DIR/issue-42344.rs:14:5
|
||||
|
|
||||
LL | TAB[0].iter_mut(); //~ ERROR cannot borrow data mutably in a `&` reference [E0389]
|
||||
|
@ -1,6 +1,9 @@
|
||||
error[E0594]: cannot assign to immutable item `x`
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/issue-46023.rs:18:9
|
||||
|
|
||||
LL | let x = 0;
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = 1;
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
error[E0594]: cannot assign to immutable item `x`
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/issue-46023.rs:18:9
|
||||
|
|
||||
LL | let x = 0;
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = 1;
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
|
@ -16,7 +16,7 @@ fn main() {
|
||||
|
||||
(move || {
|
||||
x = 1;
|
||||
//[mir]~^ ERROR cannot assign to immutable item `x` [E0594]
|
||||
//[mir]~^ ERROR cannot assign to `x`, as it is not declared as mutable [E0594]
|
||||
//[ast]~^^ ERROR cannot assign to captured outer variable in an `FnMut` closure [E0594]
|
||||
})()
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values
|
||||
LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017
|
||||
| ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
|
||||
|
||||
error[E0594]: cannot assign to immutable item `buf[..]`
|
||||
error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item
|
||||
--> $DIR/issue-46604.rs:20:5
|
||||
|
|
||||
LL | buf[0]=2; //[ast]~ ERROR E0389
|
||||
|
@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values
|
||||
LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017
|
||||
| ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
|
||||
|
||||
error[E0594]: cannot assign to immutable item `buf[..]`
|
||||
error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item
|
||||
--> $DIR/issue-46604.rs:20:5
|
||||
|
|
||||
LL | buf[0]=2; //[ast]~ ERROR E0389
|
||||
|
@ -12,7 +12,7 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
|
||||
LL | y.push(z); //~ ERROR lifetime mismatch
|
||||
| ^ ...but data from `z` flows into `y` here
|
||||
|
||||
error[E0596]: cannot borrow immutable item `y` as mutable
|
||||
error[E0596]: cannot borrow `y` as mutable, as it is not declared 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) {
|
||||
|
@ -12,7 +12,7 @@ LL | fn foo(x:Box<Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
|
||||
LL | y.push(z); //~ ERROR lifetime mismatch
|
||||
| ^ ...but data from `z` flows into `y` here
|
||||
|
||||
error[E0596]: cannot borrow immutable item `y` as mutable
|
||||
error[E0596]: cannot borrow `y` as mutable, as it is not declared 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) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `foo` as mutable
|
||||
error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable
|
||||
--> $DIR/span-covering-argument-1.rs:15:14
|
||||
|
|
||||
LL | let $s = 0;
|
||||
|
68
src/test/ui/nll/closure-captures.rs
Normal file
68
src/test/ui/nll/closure-captures.rs
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// Some cases with closures that might be problems
|
||||
|
||||
#![allow(unused)]
|
||||
#![feature(nll)]
|
||||
|
||||
// Should have one error per assigment
|
||||
|
||||
fn one_closure(x: i32) {
|
||||
||
|
||||
x = 1; //~ ERROR
|
||||
move ||
|
||||
x = 1; //~ ERROR
|
||||
}
|
||||
|
||||
fn two_closures(x: i32) {
|
||||
|| {
|
||||
||
|
||||
x = 1; //~ ERROR
|
||||
};
|
||||
move || {
|
||||
||
|
||||
x = 1; //~ ERROR
|
||||
};
|
||||
}
|
||||
|
||||
fn fn_ref<F: Fn()>(f: F) -> F { f }
|
||||
|
||||
fn two_closures_ref_mut(mut x: i32) {
|
||||
fn_ref(|| {
|
||||
|| //~ ERROR
|
||||
x = 1;}
|
||||
);
|
||||
fn_ref(move || {
|
||||
|| //~ ERROR
|
||||
x = 1;});
|
||||
}
|
||||
|
||||
// This still gives two messages, but it requires two things to be fixed.
|
||||
fn two_closures_ref(x: i32) {
|
||||
fn_ref(|| {
|
||||
|| //~ ERROR
|
||||
x = 1;} //~ ERROR
|
||||
);
|
||||
fn_ref(move || {
|
||||
|| //~ ERROR
|
||||
x = 1;}); //~ ERROR
|
||||
}
|
||||
|
||||
fn two_closures_two_refs(x: &mut i32) {
|
||||
fn_ref(|| {
|
||||
|| //~ ERROR
|
||||
*x = 1;});
|
||||
fn_ref(move || {
|
||||
|| //~ ERROR
|
||||
*x = 1;});
|
||||
}
|
||||
|
||||
fn main() {}
|
160
src/test/ui/nll/closure-captures.stderr
Normal file
160
src/test/ui/nll/closure-captures.stderr
Normal file
@ -0,0 +1,160 @@
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/closure-captures.rs:20:5
|
||||
|
|
||||
LL | fn one_closure(x: i32) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | ||
|
||||
LL | x = 1; //~ ERROR
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/closure-captures.rs:22:5
|
||||
|
|
||||
LL | fn one_closure(x: i32) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = 1; //~ ERROR
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/closure-captures.rs:28:9
|
||||
|
|
||||
LL | fn two_closures(x: i32) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = 1; //~ ERROR
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/closure-captures.rs:32:9
|
||||
|
|
||||
LL | fn two_closures(x: i32) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = 1; //~ ERROR
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/closure-captures.rs:40:9
|
||||
|
|
||||
LL | || //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
LL | x = 1;}
|
||||
| - mutable borrow occurs due to use of `x` in closure
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/closure-captures.rs:39:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | || //~ ERROR
|
||||
LL | | x = 1;}
|
||||
| |________________^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/closure-captures.rs:44:9
|
||||
|
|
||||
LL | || //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
LL | x = 1;});
|
||||
| - mutable borrow occurs due to use of `x` in closure
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/closure-captures.rs:43:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | || //~ ERROR
|
||||
LL | | x = 1;});
|
||||
| |___________^
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/closure-captures.rs:52:10
|
||||
|
|
||||
LL | fn two_closures_ref(x: i32) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = 1;} //~ ERROR
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/closure-captures.rs:51:9
|
||||
|
|
||||
LL | || //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
LL | x = 1;} //~ ERROR
|
||||
| - mutable borrow occurs due to use of `x` in closure
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/closure-captures.rs:50:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | || //~ ERROR
|
||||
LL | | x = 1;} //~ ERROR
|
||||
| |________________^
|
||||
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/closure-captures.rs:56:5
|
||||
|
|
||||
LL | fn two_closures_ref(x: i32) {
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
...
|
||||
LL | x = 1;}); //~ ERROR
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/closure-captures.rs:55:9
|
||||
|
|
||||
LL | || //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
LL | x = 1;}); //~ ERROR
|
||||
| - mutable borrow occurs due to use of `x` in closure
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/closure-captures.rs:54:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | || //~ ERROR
|
||||
LL | | x = 1;}); //~ ERROR
|
||||
| |___________^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/closure-captures.rs:61:9
|
||||
|
|
||||
LL | || //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
LL | *x = 1;});
|
||||
| - mutable borrow occurs due to use of `x` in closure
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/closure-captures.rs:60:12
|
||||
|
|
||||
LL | fn_ref(|| {
|
||||
| ____________^
|
||||
LL | | || //~ ERROR
|
||||
LL | | *x = 1;});
|
||||
| |________________^
|
||||
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
|
||||
--> $DIR/closure-captures.rs:64:9
|
||||
|
|
||||
LL | || //~ ERROR
|
||||
| ^^ cannot borrow as mutable
|
||||
LL | *x = 1;});
|
||||
| - mutable borrow occurs due to use of `x` in closure
|
||||
|
|
||||
help: consider changing this to accept closures that implement `FnMut`
|
||||
--> $DIR/closure-captures.rs:63:12
|
||||
|
|
||||
LL | fn_ref(move || {
|
||||
| ____________^
|
||||
LL | | || //~ ERROR
|
||||
LL | | *x = 1;});
|
||||
| |________________^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
Some errors occurred: E0594, E0596.
|
||||
For more information about an error, try `rustc --explain E0594`.
|
@ -1,6 +1,9 @@
|
||||
error[E0594]: cannot assign to immutable item `x`
|
||||
error[E0594]: cannot assign to `x`, as it is not declared as mutable
|
||||
--> $DIR/generator-upvar-mutability.rs:18:9
|
||||
|
|
||||
LL | let x = 0;
|
||||
| - help: consider changing this to be mutable: `mut x`
|
||||
LL | move || {
|
||||
LL | x = 1;
|
||||
| ^^^^^ cannot assign
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
|
||||
|
|
||||
LL | fn deref_mut_field1(x: Own<Point>) {
|
||||
@ -6,7 +6,7 @@ LL | fn deref_mut_field1(x: Own<Point>) {
|
||||
LL | let __isize = &mut x.y; //~ ERROR cannot borrow
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:75:10
|
||||
|
|
||||
LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
|
||||
@ -14,7 +14,7 @@ LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize {
|
||||
LL | &mut x.y //~ ERROR cannot borrow
|
||||
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
|
||||
|
|
||||
LL | fn assign_field1<'a>(x: Own<Point>) {
|
||||
@ -22,7 +22,7 @@ LL | fn assign_field1<'a>(x: Own<Point>) {
|
||||
LL | x.y = 3; //~ ERROR cannot borrow
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:102:5
|
||||
|
|
||||
LL | fn assign_field2<'a>(x: &'a Own<Point>) {
|
||||
@ -30,7 +30,7 @@ LL | fn assign_field2<'a>(x: &'a Own<Point>) {
|
||||
LL | x.y = 3; //~ ERROR cannot borrow
|
||||
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
|
||||
|
|
||||
LL | fn deref_mut_method1(x: Own<Point>) {
|
||||
@ -38,7 +38,7 @@ LL | fn deref_mut_method1(x: Own<Point>) {
|
||||
LL | x.set(0, 0); //~ ERROR cannot borrow
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:131:5
|
||||
|
|
||||
LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
|
||||
@ -46,7 +46,7 @@ LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize {
|
||||
LL | x.y_mut() //~ ERROR cannot borrow
|
||||
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
|
||||
|
|
||||
LL | fn assign_method1<'a>(x: Own<Point>) {
|
||||
@ -54,7 +54,7 @@ LL | fn assign_method1<'a>(x: Own<Point>) {
|
||||
LL | *x.y_mut() = 3; //~ ERROR cannot borrow
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:143:6
|
||||
|
|
||||
LL | fn assign_method2<'a>(x: &'a Own<Point>) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
|
||||
|
|
||||
LL | fn deref_mut1(x: Own<isize>) {
|
||||
@ -6,7 +6,7 @@ LL | fn deref_mut1(x: Own<isize>) {
|
||||
LL | let __isize = &mut *x; //~ ERROR cannot borrow
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:51:11
|
||||
|
|
||||
LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
|
||||
@ -14,7 +14,7 @@ LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize {
|
||||
LL | &mut **x //~ ERROR cannot borrow
|
||||
| ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `x` as mutable
|
||||
error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
|
||||
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
|
||||
|
|
||||
LL | fn assign1<'a>(x: Own<isize>) {
|
||||
@ -22,7 +22,7 @@ LL | fn assign1<'a>(x: Own<isize>) {
|
||||
LL | *x = 3; //~ ERROR cannot borrow
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-borrow-overloaded-deref-mut.rs:63:6
|
||||
|
|
||||
LL | fn assign2<'a>(x: &'a Own<isize>) {
|
||||
|
@ -12,7 +12,7 @@ LL | | f((Box::new(|| {})))
|
||||
LL | | }));
|
||||
| |_______- borrow later used here
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*f` as mutable
|
||||
error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
|
||||
|
|
||||
LL | fn test2<F>(f: &F) where F: FnMut() {
|
||||
@ -20,7 +20,7 @@ LL | fn test2<F>(f: &F) where F: FnMut() {
|
||||
LL | (*f)();
|
||||
| ^^^^ `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
|
||||
error[E0596]: cannot borrow `*f.f` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:44:5
|
||||
|
|
||||
LL | fn test4(f: &Test) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-call-method-from-mut-aliasable.rs:27:5
|
||||
|
|
||||
LL | fn b(x: &Foo) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-fn-in-const-b.rs:17:9
|
||||
|
|
||||
LL | fn broken(x: &Vec<String>) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/borrowck-object-mutability.rs:19:5
|
||||
|
|
||||
LL | fn borrowed_receiver(x: &Foo) {
|
||||
@ -7,7 +7,7 @@ LL | x.borrowed();
|
||||
LL | x.borrowed_mut(); //~ ERROR cannot borrow
|
||||
| ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*x` as mutable
|
||||
error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable
|
||||
--> $DIR/borrowck-object-mutability.rs:29:5
|
||||
|
|
||||
LL | fn owned_receiver(x: Box<Foo>) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `*a` as mutable
|
||||
error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/mut-arg-hint.rs:13:9
|
||||
|
|
||||
LL | fn foo(mut a: &String) {
|
||||
@ -6,7 +6,7 @@ LL | fn foo(mut a: &String) {
|
||||
LL | a.push_str("bar"); //~ ERROR cannot borrow immutable borrowed content
|
||||
| ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*a` as mutable
|
||||
error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/mut-arg-hint.rs:18:5
|
||||
|
|
||||
LL | pub fn foo<'a>(mut a: &'a String) {
|
||||
@ -14,7 +14,7 @@ LL | pub fn foo<'a>(mut a: &'a String) {
|
||||
LL | a.push_str("foo"); //~ ERROR cannot borrow immutable borrowed content
|
||||
| ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `*a` as mutable
|
||||
error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
|
||||
--> $DIR/mut-arg-hint.rs:25:9
|
||||
|
|
||||
LL | pub fn foo(mut a: &String) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0596]: cannot borrow immutable item `**t` as mutable
|
||||
error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
|
||||
--> $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 {
|
||||
@ -6,7 +6,7 @@ LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: C
|
||||
LL | *t //~ ERROR
|
||||
| ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||
|
||||
error[E0596]: cannot borrow immutable item `**t` as mutable
|
||||
error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference
|
||||
--> $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 {
|
||||
|
Loading…
Reference in New Issue
Block a user