mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-04 01:42:54 +03:00
Rollup merge of #152216 - GTimothy:map-diagnostics-fix, r=JonathanBrouwer
Fix 'assign to data in an index of' collection suggestions fixes https://github.com/rust-lang/rust/issues/150001 fixes https://github.com/rust-lang/rust-analyzer/issues/16076 fixes https://github.com/rust-lang/rust/issues/134917 The issues are threefold and linked: 1. Assigning data to a ~~collection~~BTreeMap/HashMap suggests 3 solutions all marked as `MachineApplicable` 2. The suggestions are slightly wrong with regards to their borrowing needs. 3. The suggestions are not guaranteed to produce code that is valid, and suggestion number two is equivalent to an update, not an insertion. This PR: - splits the large triple suggestion into three - sets them to `MaybeIncorrect` - automatically determines the required borrowing to use. I think this solution may not be very elegant, expecially the key typechecking / borrowing part, but it works. I am however very open to any improvement/change :) edit: edited to replace 'collection' with BTreeMap/HashMap'
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, Node};
|
||||
use rustc_hir::{self as hir, BindingMode, ByRef, Expr, Node};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::mir::visit::PlaceContext;
|
||||
@@ -669,7 +669,9 @@ struct SuggestIndexOperatorAlternativeVisitor<'a, 'infcx, 'tcx> {
|
||||
err: &'a mut Diag<'infcx>,
|
||||
ty: Ty<'tcx>,
|
||||
suggested: bool,
|
||||
infcx: &'a rustc_infer::infer::InferCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'infcx, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'infcx, 'tcx> {
|
||||
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
|
||||
hir::intravisit::walk_stmt(self, stmt);
|
||||
@@ -680,60 +682,166 @@ fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Because of TypeChecking and indexing, we know: index is &Q
|
||||
// with K: Eq + Hash + Borrow<Q>,
|
||||
// with Q: Eq + Hash + ?Sized,
|
||||
//
|
||||
// which fulfill the requirements of `get_mut`. If Q=K or Q=&{n}K, the requirements
|
||||
// of `entry` and `insert` are fulfilled too after dereferencing. If K is not
|
||||
// copy, a subsequent `clone` call may be needed.
|
||||
|
||||
/// Taken straight from https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/fn.peel_hir_ty_refs.html
|
||||
/// Adapted to mid using https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.peel_refs
|
||||
/// Simplified to counting only
|
||||
/// Peels off all references on the type. Returns the number of references
|
||||
/// removed.
|
||||
fn count_ty_refs<'tcx>(mut ty: Ty<'tcx>) -> usize {
|
||||
let mut count = 0;
|
||||
while let ty::Ref(_, inner_ty, _) = ty.kind() {
|
||||
ty = *inner_ty;
|
||||
count += 1;
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
/// Try to strip `n` `&` reference from an expression.
|
||||
/// If the expression does not have enough leading `&`, return an Error
|
||||
/// containing a count of the successfully stripped ones and the stripped
|
||||
/// expression.
|
||||
fn strip_n_refs<'a, 'b>(
|
||||
mut expr: &'a Expr<'b>,
|
||||
n: usize,
|
||||
) -> Result<&'a Expr<'b>, (usize, &'a Expr<'b>)> {
|
||||
for count in 0..n {
|
||||
match expr {
|
||||
Expr {
|
||||
kind: ExprKind::AddrOf(hir::BorrowKind::Ref, _, inner),
|
||||
..
|
||||
} => expr = inner,
|
||||
_ => return Err((count, expr)),
|
||||
}
|
||||
}
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
// we know ty is a map, with a key type at walk distance 2.
|
||||
let key_ty = self.ty.walk().nth(1).unwrap().expect_ty();
|
||||
|
||||
if let hir::ExprKind::Assign(place, rv, _sp) = expr.kind
|
||||
&& let hir::ExprKind::Index(val, index, _) = place.kind
|
||||
&& (expr.span == self.assign_span || place.span == self.assign_span)
|
||||
{
|
||||
// val[index] = rv;
|
||||
// ---------- place
|
||||
self.err.multipart_suggestions(
|
||||
format!(
|
||||
"use `.insert()` to insert a value into a `{}`, `.get_mut()` \
|
||||
to modify it, or the entry API for more flexibility",
|
||||
self.ty,
|
||||
),
|
||||
vec![
|
||||
let index_ty =
|
||||
self.infcx.tcx.typeck(val.hir_id.owner.def_id).expr_ty(index);
|
||||
|
||||
let (borrowed_prefix, borrowed_index);
|
||||
|
||||
// only suggest `insert` and `entry` if index is of type K or &{n}K or *{n}K (when there is a Borrow impl for this case).
|
||||
// We use `peel_refs` because borrow lifetimes may differ in both index and
|
||||
// key. I.e, if they are of the same base type:
|
||||
if index_ty.peel_refs() == key_ty.peel_refs() {
|
||||
let (index_refs, key_refs) =
|
||||
(count_ty_refs(index_ty), count_ty_refs(key_ty));
|
||||
|
||||
let (deref_prefix, deref_index) = if index_refs >= key_refs {
|
||||
// index is &{n}K
|
||||
strip_n_refs(index, index_refs - key_refs)
|
||||
.map(|val| ("".to_string(), val))
|
||||
.unwrap_or_else(|(depth, val)| {
|
||||
(
|
||||
if key_refs == 0 {
|
||||
"*".repeat(
|
||||
(index_refs-key_refs).checked_sub(depth).expect("return depth from strip_n_refs should be smaller than the input")
|
||||
)
|
||||
} else {
|
||||
String::new() //if key K is a ref, autoderef finish this for us.
|
||||
},
|
||||
val,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
// in this case the minimal ref addition works for all subcases
|
||||
("&".repeat(key_refs - index_refs), index)
|
||||
};
|
||||
|
||||
self.err.multipart_suggestion(
|
||||
format!("use `.insert()` to insert a value into a `{}`", self.ty),
|
||||
vec![
|
||||
// val.insert(index, rv);
|
||||
// val.insert({deref_prefix}{deref_index}, rv);
|
||||
(
|
||||
val.span.shrink_to_hi().with_hi(index.span.lo()),
|
||||
".insert(".to_string(),
|
||||
val.span.shrink_to_hi().with_hi(deref_index.span.lo()),
|
||||
format!(".insert({deref_prefix}"),
|
||||
),
|
||||
(
|
||||
index.span.shrink_to_hi().with_hi(rv.span.lo()),
|
||||
deref_index.span.shrink_to_hi().with_hi(rv.span.lo()),
|
||||
", ".to_string(),
|
||||
),
|
||||
(rv.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
self.err.multipart_suggestion(
|
||||
format!(
|
||||
"use the entry API to modify a `{}` for more flexibility",
|
||||
self.ty
|
||||
),
|
||||
vec![
|
||||
// if let Some(v) = val.get_mut(index) { *v = rv; }
|
||||
(val.span.shrink_to_lo(), "if let Some(val) = ".to_string()),
|
||||
(
|
||||
val.span.shrink_to_hi().with_hi(index.span.lo()),
|
||||
".get_mut(".to_string(),
|
||||
),
|
||||
(
|
||||
index.span.shrink_to_hi().with_hi(place.span.hi()),
|
||||
") { *val".to_string(),
|
||||
),
|
||||
(rv.span.shrink_to_hi(), "; }".to_string()),
|
||||
],
|
||||
vec![
|
||||
// let x = val.entry(index).or_insert(rv);
|
||||
// let x = val.entry({deref_prefix}{deref_index}).insert_entry(rv);
|
||||
(val.span.shrink_to_lo(), "let val = ".to_string()),
|
||||
(
|
||||
val.span.shrink_to_hi().with_hi(index.span.lo()),
|
||||
".entry(".to_string(),
|
||||
val.span.shrink_to_hi().with_hi(deref_index.span.lo()),
|
||||
format!(".entry({deref_prefix}"),
|
||||
),
|
||||
(
|
||||
index.span.shrink_to_hi().with_hi(rv.span.lo()),
|
||||
").or_insert(".to_string(),
|
||||
deref_index.span.shrink_to_hi().with_hi(rv.span.lo()),
|
||||
").insert_entry(".to_string(),
|
||||
),
|
||||
(rv.span.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
// we can make the next suggestions nicer by stripping as many leading `&` as
|
||||
// we can, autoderef will do the rest
|
||||
(borrowed_prefix, borrowed_index) = (
|
||||
String::new(),
|
||||
if index_refs > key_refs {
|
||||
strip_n_refs(index, index_refs - key_refs - 1)
|
||||
.unwrap_or_else(|(_depth, val)| val)
|
||||
// even if we tried to strip more, we can stop there thanks to autoderef
|
||||
} else {
|
||||
// when the diff is negative or zero, we already are in the index=&Q case.
|
||||
index
|
||||
},
|
||||
);
|
||||
} else {
|
||||
(borrowed_prefix, borrowed_index) = (String::new(), index)
|
||||
}
|
||||
// in all cases, suggest get_mut because K:Borrow<K> or Q:Borrow<K> as a
|
||||
// requirement of indexing.
|
||||
self.err.multipart_suggestion(
|
||||
format!(
|
||||
"use `.get_mut()` to modify an existing key in a `{}`",
|
||||
self.ty,
|
||||
),
|
||||
vec![
|
||||
// if let Some(v) = val.get_mut({borrowed_prefix}{borrowed_index}) { *v = rv; }
|
||||
(val.span.shrink_to_lo(), "if let Some(val) = ".to_string()),
|
||||
(
|
||||
val.span.shrink_to_hi().with_hi(borrowed_index.span.lo()),
|
||||
format!(".get_mut({borrowed_prefix}"),
|
||||
),
|
||||
(
|
||||
borrowed_index.span.shrink_to_hi().with_hi(place.span.hi()),
|
||||
") { *val".to_string(),
|
||||
),
|
||||
(rv.span.shrink_to_hi(), "; }".to_string()),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
self.suggested = true;
|
||||
} else if let hir::ExprKind::MethodCall(_path, receiver, _, sp) = expr.kind
|
||||
&& let hir::ExprKind::Index(val, index, _) = receiver.kind
|
||||
@@ -769,6 +877,7 @@ fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
|
||||
err,
|
||||
ty,
|
||||
suggested: false,
|
||||
infcx: self.infcx,
|
||||
};
|
||||
v.visit_body(&body);
|
||||
if !v.suggested {
|
||||
|
||||
@@ -18,16 +18,20 @@ LL | map["peter"] = "0".to_string();
|
||||
| ^^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>`
|
||||
help: use `.insert()` to insert a value into a `HashMap<&str, String>`, `.get_mut()` to modify it, or the entry API for more flexibility
|
||||
help: use `.insert()` to insert a value into a `HashMap<&str, String>`
|
||||
|
|
||||
LL - map["peter"] = "0".to_string();
|
||||
LL + map.insert("peter", "0".to_string());
|
||||
|
|
||||
LL - map["peter"] = "0".to_string();
|
||||
LL + if let Some(val) = map.get_mut("peter") { *val = "0".to_string(); };
|
||||
help: use the entry API to modify a `HashMap<&str, String>` for more flexibility
|
||||
|
|
||||
LL - map["peter"] = "0".to_string();
|
||||
LL + let val = map.entry("peter").or_insert("0".to_string());
|
||||
LL + let val = map.entry("peter").insert_entry("0".to_string());
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `HashMap<&str, String>`
|
||||
|
|
||||
LL - map["peter"] = "0".to_string();
|
||||
LL + if let Some(val) = map.get_mut("peter") { *val = "0".to_string(); };
|
||||
|
|
||||
|
||||
error[E0596]: cannot borrow data in an index of `HashMap<&str, String>` as mutable
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// When mutably indexing a type that implements `Index` but not `IndexMut`, a
|
||||
// special 'help' message is added to the output.
|
||||
// ... Except when it is not!
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct A {}
|
||||
#[derive(Hash, Eq, PartialEq, Copy, Clone)]
|
||||
struct ACopy {}
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct B {}
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct C {}
|
||||
#[derive(Hash, Eq, PartialEq)]
|
||||
struct D {}
|
||||
|
||||
impl Borrow<C> for D {
|
||||
fn borrow(&self) -> &C {
|
||||
&C {}
|
||||
}
|
||||
}
|
||||
|
||||
/// In this test the key is a A type.
|
||||
fn test_a_index() {
|
||||
let mut map = HashMap::<A, u32>::new();
|
||||
|
||||
let index = &&&&&A {};
|
||||
// index gets autodereferenced
|
||||
map[index] = 23; //~ ERROR E0594
|
||||
map[&&&&&&&&index] = 23; //~ ERROR E0594
|
||||
}
|
||||
/// In this test the key is a A type. Auto-dereferencing to &A works but dereferencing to A need
|
||||
/// the exact amount of `*`
|
||||
fn test_a_2() {
|
||||
let mut map = HashMap::<A, u32>::new();
|
||||
|
||||
let index = &&&&&A {};
|
||||
// complete dereferencing needs to be exact
|
||||
map.insert(*index, 23); //~ ERROR E0308
|
||||
// index gets autodereferenced
|
||||
if let Some(val) = map.get_mut(index) {
|
||||
*val = 23;
|
||||
} // passes
|
||||
}
|
||||
/// In this test the key is a A type. Could not be merged with 2 because compiler only shows error
|
||||
/// 0308
|
||||
fn test_a_3() {
|
||||
let mut map = HashMap::<A, u32>::new();
|
||||
|
||||
let index = &&&&&A {};
|
||||
// A does not implement Copy so a Clone might be required
|
||||
map.insert(*****index, 23); //~ ERROR E0507
|
||||
}
|
||||
|
||||
/// In this test the key is a ACopy type.
|
||||
fn test_acopy_index() {
|
||||
let mut map = HashMap::<ACopy, u32>::new();
|
||||
|
||||
let index = &&&&&ACopy {};
|
||||
// index gets autodereferenced
|
||||
map[index] = 23; //~ ERROR E0594
|
||||
}
|
||||
/// In this test the key is a ACopy type. Auto-dereferencing to &A works but dereferencing to A
|
||||
/// need the exact amount of `*`.
|
||||
fn test_acopy_2() {
|
||||
let mut map = HashMap::<ACopy, u32>::new();
|
||||
|
||||
let index = &&&&&ACopy {};
|
||||
// complete dereferencing needs to be exact
|
||||
map.insert(*index, 23); //~ ERROR E0308
|
||||
|
||||
// index gets autodereferenced
|
||||
if let Some(val) = map.get_mut(index) {
|
||||
*val = 23;
|
||||
} // passes
|
||||
}
|
||||
/// In this test the key is a ACopy type. Could not be merged with 2 because compiler only shows
|
||||
/// error 0308
|
||||
fn test_acopy_3() {
|
||||
let mut map = HashMap::<ACopy, u32>::new();
|
||||
|
||||
let index = &&&&&ACopy {};
|
||||
map.insert(*****index, 23); // no E057 error in this case because ACopy is Copy
|
||||
}
|
||||
|
||||
/// In this test the key type is B-reference. The autodereferencing does not work in this case for
|
||||
/// both for the map[index] part and `get_mut` call.
|
||||
/// This leads to E0277 errors.
|
||||
fn test_b() {
|
||||
let mut map = HashMap::<&B, u32>::new();
|
||||
|
||||
let index = &&&&&B {};
|
||||
// index does NOT get autorederefenced
|
||||
map[index] = 23; //~ ERROR E0277
|
||||
|
||||
// index does NOT get autorederefenced
|
||||
if let Some(val) = map.get_mut(index) { //~ ERROR E0277
|
||||
*val = 23;
|
||||
}
|
||||
if let Some(val) = map.get_mut(***index) {
|
||||
*val = 23;
|
||||
} // passes
|
||||
}
|
||||
|
||||
/// In this test the key type is C.
|
||||
/// The `Borrow<C> for D` implementation changes nothing here, same error as for test_a.
|
||||
fn test_c() {
|
||||
let mut map = HashMap::<C, u32>::new();
|
||||
|
||||
let index = &&&&&C {};
|
||||
// index gets autodereferenced
|
||||
map[index] = 23; //~ ERROR E0594
|
||||
|
||||
// index gets autodereferenced
|
||||
if let Some(val) = map.get_mut(index) {
|
||||
*val = 23;
|
||||
} // passes
|
||||
}
|
||||
|
||||
/// In this test the key type is D. The `Borrow<C> for D` implementation seems to prevent
|
||||
/// autodereferencing.
|
||||
/// The autodereferencing does not work in this case for both for the map[index] part and `get_mut`
|
||||
/// call.
|
||||
/// This leads to E0277 errors.
|
||||
fn test_d() {
|
||||
let mut map = HashMap::<D, u32>::new();
|
||||
|
||||
let index = &&&&&D {};
|
||||
// index does NOT get autorederefenced
|
||||
map[index] = 23; //~ ERROR E0277
|
||||
|
||||
// index does NOT get autorederefenced
|
||||
if let Some(val) = map.get_mut(index) {//~ ERROR E0277
|
||||
*val = 23;
|
||||
}
|
||||
if let Some(val) = map.get_mut(****index) {
|
||||
*val = 23;
|
||||
} // passes
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq)]
|
||||
struct S {}
|
||||
// it is possible to have a Borrowed version of a type be of the same type but less borrowed.
|
||||
// here, a borrowed version of `&&&S` is `&S`.
|
||||
impl Borrow<S> for &&&S {
|
||||
fn borrow(&self) -> &S {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// In this test, the index type is the same base type as the key, but because of a peculiar Borrow
|
||||
/// impl, it is of a lesser ref depth than the key.
|
||||
/// There are some E0716 errors that result from the suggestion, but they already have diagnostics
|
||||
fn test_s() {
|
||||
let mut map = HashMap::<&&&S, usize>::new();
|
||||
let index = &S{};
|
||||
map[index] = 12; //~ ERROR E0594
|
||||
map.insert(&&index, 12); //~ ERROR E0716
|
||||
let val = map.entry(&&index).insert_entry(12); //~ ERROR E0716
|
||||
if let Some(val) = map.get_mut(index) {
|
||||
*val = 12;
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_a_index();
|
||||
test_a_2();
|
||||
test_a_3();
|
||||
test_acopy_index();
|
||||
test_acopy_2();
|
||||
test_acopy_3();
|
||||
test_b();
|
||||
test_c();
|
||||
test_d();
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/index-mut-help2.rs:40:16
|
||||
|
|
||||
LL | map.insert(*index, 23);
|
||||
| ------ ^^^^^^ expected `A`, found `&&&&A`
|
||||
| |
|
||||
| arguments to this method are incorrect
|
||||
|
|
||||
note: method defined here
|
||||
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/index-mut-help2.rs:71:16
|
||||
|
|
||||
LL | map.insert(*index, 23);
|
||||
| ------ ^^^^^^ expected `ACopy`, found `&&&&ACopy`
|
||||
| |
|
||||
| arguments to this method are incorrect
|
||||
|
|
||||
note: method defined here
|
||||
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
||||
help: consider dereferencing the borrow
|
||||
|
|
||||
LL | map.insert(*****index, 23);
|
||||
| ++++
|
||||
|
||||
error[E0277]: the trait bound `&B: Borrow<&&&&B>` is not satisfied
|
||||
--> $DIR/index-mut-help2.rs:95:9
|
||||
|
|
||||
LL | map[index] = 23;
|
||||
| ^^^^^ the trait `Borrow<&&&&B>` is not implemented for `&B`
|
||||
|
|
||||
= note: required for `HashMap<&B, u32>` to implement `Index<&&&&&B>`
|
||||
|
||||
error[E0277]: the trait bound `&B: Borrow<&&&&B>` is not satisfied
|
||||
--> $DIR/index-mut-help2.rs:98:36
|
||||
|
|
||||
LL | if let Some(val) = map.get_mut(index) {
|
||||
| ------- ^^^^^ the trait `Borrow<&&&&B>` is not implemented for `&B`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `HashMap::<K, V, S, A>::get_mut`
|
||||
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
||||
|
||||
error[E0277]: the trait bound `D: Borrow<&&&&D>` is not satisfied
|
||||
--> $DIR/index-mut-help2.rs:131:9
|
||||
|
|
||||
LL | map[index] = 23;
|
||||
| ^^^^^ unsatisfied trait bound
|
||||
|
|
||||
help: the trait `Borrow<&&&&D>` is not implemented for `D`
|
||||
but trait `Borrow<C>` is implemented for it
|
||||
--> $DIR/index-mut-help2.rs:18:1
|
||||
|
|
||||
LL | impl Borrow<C> for D {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= help: for that trait implementation, expected `C`, found `&&&&D`
|
||||
= note: required for `HashMap<D, u32>` to implement `Index<&&&&&D>`
|
||||
|
||||
error[E0277]: the trait bound `D: Borrow<&&&&D>` is not satisfied
|
||||
--> $DIR/index-mut-help2.rs:134:36
|
||||
|
|
||||
LL | if let Some(val) = map.get_mut(index) {
|
||||
| ------- ^^^^^ unsatisfied trait bound
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
help: the trait `Borrow<&&&&D>` is not implemented for `D`
|
||||
but trait `Borrow<C>` is implemented for it
|
||||
--> $DIR/index-mut-help2.rs:18:1
|
||||
|
|
||||
LL | impl Borrow<C> for D {
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= help: for that trait implementation, expected `C`, found `&&&&D`
|
||||
note: required by a bound in `HashMap::<K, V, S, A>::get_mut`
|
||||
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
|
||||
|
||||
error[E0594]: cannot assign to data in an index of `HashMap<A, u32>`
|
||||
--> $DIR/index-mut-help2.rs:30:5
|
||||
|
|
||||
LL | map[index] = 23;
|
||||
| ^^^^^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<A, u32>`
|
||||
help: use `.insert()` to insert a value into a `HashMap<A, u32>`
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + map.insert(*****index, 23);
|
||||
|
|
||||
help: use the entry API to modify a `HashMap<A, u32>` for more flexibility
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + let val = map.entry(*****index).insert_entry(23);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `HashMap<A, u32>`
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
|
||||
|
|
||||
|
||||
error[E0594]: cannot assign to data in an index of `HashMap<A, u32>`
|
||||
--> $DIR/index-mut-help2.rs:31:5
|
||||
|
|
||||
LL | map[&&&&&&&&index] = 23;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<A, u32>`
|
||||
help: use `.insert()` to insert a value into a `HashMap<A, u32>`
|
||||
|
|
||||
LL - map[&&&&&&&&index] = 23;
|
||||
LL + map.insert(*****index, 23);
|
||||
|
|
||||
help: use the entry API to modify a `HashMap<A, u32>` for more flexibility
|
||||
|
|
||||
LL - map[&&&&&&&&index] = 23;
|
||||
LL + let val = map.entry(*****index).insert_entry(23);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `HashMap<A, u32>`
|
||||
|
|
||||
LL - map[&&&&&&&&index] = 23;
|
||||
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
|
||||
|
|
||||
|
||||
error[E0507]: cannot move out of `*****index` which is behind a shared reference
|
||||
--> $DIR/index-mut-help2.rs:53:16
|
||||
|
|
||||
LL | map.insert(*****index, 23);
|
||||
| ^^^^^^^^^^ move occurs because `*****index` has type `A`, which does not implement the `Copy` trait
|
||||
|
|
||||
note: if `A` implemented `Clone`, you could clone the value
|
||||
--> $DIR/index-mut-help2.rs:8:1
|
||||
|
|
||||
LL | struct A {}
|
||||
| ^^^^^^^^ consider implementing `Clone` for this type
|
||||
...
|
||||
LL | map.insert(*****index, 23);
|
||||
| ---------- you could clone this value
|
||||
|
||||
error[E0594]: cannot assign to data in an index of `HashMap<ACopy, u32>`
|
||||
--> $DIR/index-mut-help2.rs:62:5
|
||||
|
|
||||
LL | map[index] = 23;
|
||||
| ^^^^^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<ACopy, u32>`
|
||||
help: use `.insert()` to insert a value into a `HashMap<ACopy, u32>`
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + map.insert(*****index, 23);
|
||||
|
|
||||
help: use the entry API to modify a `HashMap<ACopy, u32>` for more flexibility
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + let val = map.entry(*****index).insert_entry(23);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `HashMap<ACopy, u32>`
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
|
||||
|
|
||||
|
||||
error[E0594]: cannot assign to data in an index of `HashMap<C, u32>`
|
||||
--> $DIR/index-mut-help2.rs:113:5
|
||||
|
|
||||
LL | map[index] = 23;
|
||||
| ^^^^^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<C, u32>`
|
||||
help: use `.insert()` to insert a value into a `HashMap<C, u32>`
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + map.insert(*****index, 23);
|
||||
|
|
||||
help: use the entry API to modify a `HashMap<C, u32>` for more flexibility
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + let val = map.entry(*****index).insert_entry(23);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `HashMap<C, u32>`
|
||||
|
|
||||
LL - map[index] = 23;
|
||||
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
|
||||
|
|
||||
|
||||
error[E0594]: cannot assign to data in an index of `HashMap<&&&S, usize>`
|
||||
--> $DIR/index-mut-help2.rs:158:5
|
||||
|
|
||||
LL | map[index] = 12;
|
||||
| ^^^^^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&&&S, usize>`
|
||||
help: use `.insert()` to insert a value into a `HashMap<&&&S, usize>`
|
||||
|
|
||||
LL - map[index] = 12;
|
||||
LL + map.insert(&&index, 12);
|
||||
|
|
||||
help: use the entry API to modify a `HashMap<&&&S, usize>` for more flexibility
|
||||
|
|
||||
LL - map[index] = 12;
|
||||
LL + let val = map.entry(&&index).insert_entry(12);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `HashMap<&&&S, usize>`
|
||||
|
|
||||
LL - map[index] = 12;
|
||||
LL + if let Some(val) = map.get_mut(index) { *val = 12; };
|
||||
|
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/index-mut-help2.rs:159:17
|
||||
|
|
||||
LL | map.insert(&&index, 12);
|
||||
| ^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | let val = map.entry(&&index).insert_entry(12);
|
||||
| --- borrow later used here
|
||||
|
|
||||
help: consider using a `let` binding to create a longer lived value
|
||||
|
|
||||
LL ~ let binding = &index;
|
||||
LL ~ map.insert(&binding, 12);
|
||||
|
|
||||
|
||||
error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/index-mut-help2.rs:160:26
|
||||
|
|
||||
LL | let val = map.entry(&&index).insert_entry(12);
|
||||
| ^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | if let Some(val) = map.get_mut(index) {
|
||||
| --- borrow later used here
|
||||
|
|
||||
help: consider using a `let` binding to create a longer lived value
|
||||
|
|
||||
LL ~ let binding = &index;
|
||||
LL ~ let val = map.entry(&binding).insert_entry(12);
|
||||
|
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308, E0507, E0594, E0716.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
@@ -5,17 +5,21 @@ LL | map[&0] = 1;
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `BTreeMap<u32, u32>`
|
||||
help: use `.insert()` to insert a value into a `BTreeMap<u32, u32>`, `.get_mut()` to modify it, or the entry API for more flexibility
|
||||
help: use `.insert()` to insert a value into a `BTreeMap<u32, u32>`
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + map.insert(&0, 1);
|
||||
LL + map.insert(0, 1);
|
||||
|
|
||||
help: use the entry API to modify a `BTreeMap<u32, u32>` for more flexibility
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + let val = map.entry(0).insert_entry(1);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `BTreeMap<u32, u32>`
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + if let Some(val) = map.get_mut(&0) { *val = 1; };
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + let val = map.entry(&0).or_insert(1);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -5,17 +5,21 @@ LL | map[&0] = 1;
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `BTreeMap<u32, u32>`
|
||||
help: use `.insert()` to insert a value into a `BTreeMap<u32, u32>`, `.get_mut()` to modify it, or the entry API for more flexibility
|
||||
help: use `.insert()` to insert a value into a `BTreeMap<u32, u32>`
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + map.insert(&0, 1);
|
||||
LL + map.insert(0, 1);
|
||||
|
|
||||
help: use the entry API to modify a `BTreeMap<u32, u32>` for more flexibility
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + let val = map.entry(0).insert_entry(1);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `BTreeMap<u32, u32>`
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + if let Some(val) = map.get_mut(&0) { *val = 1; };
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + let val = map.entry(&0).or_insert(1);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -5,17 +5,21 @@ LL | map[&0] = 1;
|
||||
| ^^^^^^^^^^^ cannot assign
|
||||
|
|
||||
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<u32, u32>`
|
||||
help: use `.insert()` to insert a value into a `HashMap<u32, u32>`, `.get_mut()` to modify it, or the entry API for more flexibility
|
||||
help: use `.insert()` to insert a value into a `HashMap<u32, u32>`
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + map.insert(&0, 1);
|
||||
LL + map.insert(0, 1);
|
||||
|
|
||||
help: use the entry API to modify a `HashMap<u32, u32>` for more flexibility
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + let val = map.entry(0).insert_entry(1);
|
||||
|
|
||||
help: use `.get_mut()` to modify an existing key in a `HashMap<u32, u32>`
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + if let Some(val) = map.get_mut(&0) { *val = 1; };
|
||||
|
|
||||
LL - map[&0] = 1;
|
||||
LL + let val = map.entry(&0).or_insert(1);
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user