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:
Jonathan Brouwer
2026-05-03 16:33:21 +02:00
committed by GitHub
7 changed files with 596 additions and 51 deletions
@@ -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 {
+8 -4
View File
@@ -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
+176
View File
@@ -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();
}
+244
View File
@@ -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