about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-08-24 18:20:13 +0200
committerGitHub <noreply@github.com>2022-08-24 18:20:13 +0200
commit95135bed61d4403a294ab0ba25aa706748b54bbf (patch)
tree50f53a3f918b3ab3b01c449103acbba0ca0e0da4
parent1c0f60f904fbbee214b17306a8155079df01b2c4 (diff)
parentb0255a1849dea3e39ebd9089230a17446230c3d8 (diff)
downloadrust-95135bed61d4403a294ab0ba25aa706748b54bbf.tar.gz
rust-95135bed61d4403a294ab0ba25aa706748b54bbf.zip
Rollup merge of #100906 - ChayimFriedman2:map-index-mut, r=davidtwco
Suggest alternatives when trying to mutate a `HashMap`/`BTreeMap` via indexing

The error can be quite confusing to newcomers.

Fixes #100873.

I'm not so sure about the message, open to wording suggestions.
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs19
-rw-r--r--src/test/ui/borrowck/index-mut-help.stderr3
-rw-r--r--src/test/ui/btreemap/btreemap-index-mut.rs6
-rw-r--r--src/test/ui/btreemap/btreemap-index-mut.stderr12
-rw-r--r--src/test/ui/hashmap/hashmap-index-mut.rs6
-rw-r--r--src/test/ui/hashmap/hashmap-index-mut.stderr12
-rw-r--r--src/test/ui/issues/issue-41726.stderr1
7 files changed, 57 insertions, 2 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 0ad4abbce20..56721cc3f5c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1,3 +1,4 @@
+use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::Node;
 use rustc_middle::hir::map::Map;
@@ -12,12 +13,11 @@ use rustc_middle::{
 };
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, Symbol};
-use rustc_span::{BytePos, Span};
+use rustc_span::{sym, BytePos, Span};
 
 use crate::diagnostics::BorrowedContentSource;
 use crate::MirBorrowckCtxt;
 use rustc_const_eval::util::collect_writes::FindAssignments;
-use rustc_errors::{Applicability, Diagnostic};
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub(crate) enum AccessKind {
@@ -614,6 +614,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                             "trait `IndexMut` is required to modify indexed content, \
                                 but it is not implemented for `{ty}`",
                         ));
+                        self.suggest_map_index_mut_alternatives(ty, &mut err);
                     }
                     _ => (),
                 }
@@ -627,6 +628,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         self.buffer_error(err);
     }
 
+    fn suggest_map_index_mut_alternatives(
+        &self,
+        ty: Ty<'_>,
+        err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+    ) {
+        let Some(adt) = ty.ty_adt_def() else { return };
+        let did = adt.did();
+        if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
+            || self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did)
+        {
+            err.help(format!("to modify a `{ty}`, use `.get_mut()`, `.insert()` or the entry API"));
+        }
+    }
+
     /// User cannot make signature of a trait mutable without changing the
     /// trait. So we find if this error belongs to a trait and if so we move
     /// suggestion to the trait or disable it if it is out of scope of this crate
diff --git a/src/test/ui/borrowck/index-mut-help.stderr b/src/test/ui/borrowck/index-mut-help.stderr
index 057c6ee15f3..0ce60e3eb1d 100644
--- a/src/test/ui/borrowck/index-mut-help.stderr
+++ b/src/test/ui/borrowck/index-mut-help.stderr
@@ -5,6 +5,7 @@ LL |     map["peter"].clear();
    |     ^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
    |
    = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>`
+   = help: to modify a `HashMap<&str, String>`, use `.get_mut()`, `.insert()` or the entry API
 
 error[E0594]: cannot assign to data in an index of `HashMap<&str, String>`
   --> $DIR/index-mut-help.rs:12:5
@@ -13,6 +14,7 @@ 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: to modify a `HashMap<&str, String>`, use `.get_mut()`, `.insert()` or the entry API
 
 error[E0596]: cannot borrow data in an index of `HashMap<&str, String>` as mutable
   --> $DIR/index-mut-help.rs:13:13
@@ -21,6 +23,7 @@ LL |     let _ = &mut map["peter"];
    |             ^^^^^^^^^^^^^^^^^ cannot borrow as mutable
    |
    = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>`
+   = help: to modify a `HashMap<&str, String>`, use `.get_mut()`, `.insert()` or the entry API
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/btreemap/btreemap-index-mut.rs b/src/test/ui/btreemap/btreemap-index-mut.rs
new file mode 100644
index 00000000000..62972acab86
--- /dev/null
+++ b/src/test/ui/btreemap/btreemap-index-mut.rs
@@ -0,0 +1,6 @@
+use std::collections::BTreeMap;
+
+fn main() {
+    let mut map = BTreeMap::<u32, u32>::new();
+    map[&0] = 1; //~ ERROR cannot assign
+}
diff --git a/src/test/ui/btreemap/btreemap-index-mut.stderr b/src/test/ui/btreemap/btreemap-index-mut.stderr
new file mode 100644
index 00000000000..260f7100074
--- /dev/null
+++ b/src/test/ui/btreemap/btreemap-index-mut.stderr
@@ -0,0 +1,12 @@
+error[E0594]: cannot assign to data in an index of `BTreeMap<u32, u32>`
+  --> $DIR/btreemap-index-mut.rs:5:5
+   |
+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: to modify a `BTreeMap<u32, u32>`, use `.get_mut()`, `.insert()` or the entry API
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/hashmap/hashmap-index-mut.rs b/src/test/ui/hashmap/hashmap-index-mut.rs
new file mode 100644
index 00000000000..98448e9d5f0
--- /dev/null
+++ b/src/test/ui/hashmap/hashmap-index-mut.rs
@@ -0,0 +1,6 @@
+use std::collections::HashMap;
+
+fn main() {
+    let mut map = HashMap::<u32, u32>::new();
+    map[&0] = 1; //~ ERROR cannot assign
+}
diff --git a/src/test/ui/hashmap/hashmap-index-mut.stderr b/src/test/ui/hashmap/hashmap-index-mut.stderr
new file mode 100644
index 00000000000..c72b380f466
--- /dev/null
+++ b/src/test/ui/hashmap/hashmap-index-mut.stderr
@@ -0,0 +1,12 @@
+error[E0594]: cannot assign to data in an index of `HashMap<u32, u32>`
+  --> $DIR/hashmap-index-mut.rs:5:5
+   |
+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: to modify a `HashMap<u32, u32>`, use `.get_mut()`, `.insert()` or the entry API
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-41726.stderr b/src/test/ui/issues/issue-41726.stderr
index 22631e7c2a3..9c70ab7d971 100644
--- a/src/test/ui/issues/issue-41726.stderr
+++ b/src/test/ui/issues/issue-41726.stderr
@@ -5,6 +5,7 @@ LL |         things[src.as_str()].sort();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
    |
    = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<String, Vec<String>>`
+   = help: to modify a `HashMap<String, Vec<String>>`, use `.get_mut()`, `.insert()` or the entry API
 
 error: aborting due to previous error