Skip to content

Commit 2e22102

Browse files
committed
fix: the same borrowed type (ignoring lifetime differences) for index and key is ok too for insert and entry
1 parent 193b59c commit 2e22102

2 files changed

Lines changed: 32 additions & 7 deletions

File tree

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
707707
// where
708708
// Q: Hash + Equivalent<K> + ?Sized,
709709

710+
/// testing if index AND key are &Q. We cannot simply test equality because the
711+
/// lifetimes differ.
712+
fn index_and_key_are_same_borrowed_type<'tcx>(
713+
index: Ty<'tcx>,
714+
key: Ty<'tcx>,
715+
) -> bool {
716+
if let (ty::Ref(_, index_inner_ty, _), ty::Ref(_, key_inner_ty, _)) =
717+
(index.kind(), key.kind())
718+
{
719+
*index_inner_ty == *key_inner_ty
720+
} else {
721+
false
722+
}
723+
}
710724
/// testing if index is &K:
711725
fn index_is_borrowed_key<'tcx>(index: Ty<'tcx>, key: Ty<'tcx>) -> bool {
712726
if let ty::Ref(_, inner_ty, _) = index.kind() {
@@ -730,15 +744,18 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
730744
let index_ty =
731745
self.infcx.tcx.typeck(val.hir_id.owner.def_id).expr_ty(index);
732746
// only suggest `insert` and `entry` if K is copy/clone because of the signature.
733-
if index_is_borrowed_key(index_ty, key_type) && key_is_copyclone(key_type) {
747+
let index_is_borrowed_key = index_is_borrowed_key(index_ty, key_type);
748+
if (index_is_borrowed_key
749+
|| index_and_key_are_same_borrowed_type(index_ty, key_type))
750+
&& key_is_copyclone(key_type)
751+
{
752+
let offset = BytePos(index_is_borrowed_key as u32);
734753
self.err.multipart_suggestion(
735754
format!("use `.insert()` to insert a value into a `{}`", self.ty),
736755
vec![
737756
// val.insert(index, rv);
738757
(
739-
val.span
740-
.shrink_to_hi()
741-
.with_hi(index.span.lo() + BytePos(1)), //remove the
758+
val.span.shrink_to_hi().with_hi(index.span.lo() + offset), //remove the
742759
//leading &
743760
format!(".insert("),
744761
),
@@ -759,9 +776,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
759776
// let x = val.entry(index).insert_entry(rv);
760777
(val.span.shrink_to_lo(), "let val = ".to_string()),
761778
(
762-
val.span
763-
.shrink_to_hi()
764-
.with_hi(index.span.lo() + BytePos(1)), //remove the
779+
val.span.shrink_to_hi().with_hi(index.span.lo() + offset), //remove the
765780
//leading &
766781
format!(".entry("),
767782
),

tests/ui/borrowck/index-mut-help.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ LL | map["peter"] = "0".to_string();
1818
| ^^^^^^^^^^^^ cannot assign
1919
|
2020
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<&str, String>`
21+
help: use `.insert()` to insert a value into a `HashMap<&str, String>`
22+
|
23+
LL - map["peter"] = "0".to_string();
24+
LL + map.insert("peter", "0".to_string());
25+
|
26+
help: use the entry API to modify a `HashMap<&str, String>` for more flexibility
27+
|
28+
LL - map["peter"] = "0".to_string();
29+
LL + let val = map.entry("peter").insert_entry("0".to_string());
30+
|
2131
help: use `.get_mut()` to modify an existing key in a `HashMap<&str, String>`
2232
|
2333
LL - map["peter"] = "0".to_string();

0 commit comments

Comments
 (0)