Skip to content

Commit b799514

Browse files
committed
add index-mut test case where mut index access to a map produces E0277 instead of E0594
a set of slightly different tests showing that E0594 can be reached in some cases via autodereferencing, but also that slight variations produce E0277 instead.
1 parent 9a9a742 commit b799514

2 files changed

Lines changed: 342 additions & 0 deletions

File tree

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
// When mutably indexing a type that implements `Index` but not `IndexMut`, a
2+
// special 'help' message is added to the output.
3+
// ... Except when it is not!
4+
use std::borrow::Borrow;
5+
use std::collections::HashMap;
6+
7+
#[derive(Hash, Eq, PartialEq)]
8+
struct A {}
9+
#[derive(Hash, Eq, PartialEq, Copy, Clone)]
10+
struct ACopy {}
11+
#[derive(Hash, Eq, PartialEq)]
12+
struct B {}
13+
#[derive(Hash, Eq, PartialEq)]
14+
struct C {}
15+
#[derive(Hash, Eq, PartialEq)]
16+
struct D {}
17+
18+
impl Borrow<C> for D {
19+
fn borrow(&self) -> &C {
20+
&C {}
21+
}
22+
}
23+
24+
/// In this test the key is a A type.
25+
fn test_a_index() {
26+
let mut map = HashMap::<A, u32>::new();
27+
28+
let index = &&&&&A {};
29+
// index gets autodereferenced
30+
map[index] = 23; //~ ERROR E0594
31+
map[&&&&&&&&index] = 23; //~ ERROR E0594
32+
}
33+
/// In this test the key is a A type. Auto-dereferencing to &A works but dereferencing to A need
34+
/// the exact amount of `*`
35+
fn test_a_2() {
36+
let mut map = HashMap::<A, u32>::new();
37+
38+
let index = &&&&&A {};
39+
// complete dereferencing needs to be exact
40+
map.insert(*index, 23); //~ ERROR E0308
41+
// index gets autodereferenced
42+
if let Some(val) = map.get_mut(index) {
43+
*val = 23;
44+
} // passes
45+
}
46+
/// In this test the key is a A type. Could not be merged with 2 because compiler only shows error
47+
/// 0308
48+
fn test_a_3() {
49+
let mut map = HashMap::<A, u32>::new();
50+
51+
let index = &&&&&A {};
52+
// A does not implement Copy so a Clone might be required
53+
map.insert(*****index, 23); //~ ERROR E0507
54+
}
55+
56+
/// In this test the key is a ACopy type.
57+
fn test_acopy_index() {
58+
let mut map = HashMap::<ACopy, u32>::new();
59+
60+
let index = &&&&&ACopy {};
61+
// index gets autodereferenced
62+
map[index] = 23; //~ ERROR E0594
63+
}
64+
/// In this test the key is a ACopy type. Auto-dereferencing to &A works but dereferencing to A
65+
/// need the exact amount of `*`.
66+
fn test_acopy_2() {
67+
let mut map = HashMap::<ACopy, u32>::new();
68+
69+
let index = &&&&&ACopy {};
70+
// complete dereferencing needs to be exact
71+
map.insert(*index, 23); //~ ERROR E0308
72+
73+
// index gets autodereferenced
74+
if let Some(val) = map.get_mut(index) {
75+
*val = 23;
76+
} // passes
77+
}
78+
/// In this test the key is a ACopy type. Could not be merged with 2 because compiler only shows
79+
/// error 0308
80+
fn test_acopy_3() {
81+
let mut map = HashMap::<ACopy, u32>::new();
82+
83+
let index = &&&&&ACopy {};
84+
map.insert(*****index, 23); // no E057 error in this case because ACopy is Copy
85+
}
86+
87+
/// In this test the key type is B-reference. The autodereferencing does not work in this case for
88+
/// both for the map[index] part and `get_mut` call.
89+
/// This leads to E0277 errors.
90+
fn test_b() {
91+
let mut map = HashMap::<&B, u32>::new();
92+
93+
let index = &&&&&B {};
94+
// index does NOT get autorederefenced
95+
map[index] = 23; //~ ERROR E0277
96+
97+
// index does NOT get autorederefenced
98+
if let Some(val) = map.get_mut(index) { //~ ERROR E0277
99+
*val = 23;
100+
}
101+
if let Some(val) = map.get_mut(***index) {
102+
*val = 23;
103+
} // passes
104+
}
105+
106+
107+
/// In this test the key type is C.
108+
/// The `Borrow<C> for D` implementation changes nothing here, same error as for test_a.
109+
fn test_c() {
110+
let mut map = HashMap::<C, u32>::new();
111+
112+
let index = &&&&&C {};
113+
// index gets autodereferenced
114+
map[index] = 23; //~ ERROR E0594
115+
116+
// index gets autodereferenced
117+
if let Some(val) = map.get_mut(index) {
118+
*val = 23;
119+
} // passes
120+
}
121+
122+
/// In this test the key type is D. The `Borrow<C> for D` implementation seems to prevent
123+
/// autodereferencing.
124+
/// The autodereferencing does not work in this case for both for the map[index] part and `get_mut`
125+
/// call.
126+
/// This leads to E0277 errors.
127+
fn test_d() {
128+
let mut map = HashMap::<D, u32>::new();
129+
130+
let index = &&&&&D {};
131+
// index does NOT get autorederefenced
132+
map[index] = 23; //~ ERROR E0277
133+
134+
// index does NOT get autorederefenced
135+
if let Some(val) = map.get_mut(index) {//~ ERROR E0277
136+
*val = 23;
137+
}
138+
if let Some(val) = map.get_mut(****index) {
139+
*val = 23;
140+
} // passes
141+
}
142+
143+
fn main() {
144+
test_a_index();
145+
test_a_2();
146+
test_a_3();
147+
test_acopy_index();
148+
test_acopy_2();
149+
test_acopy_3();
150+
test_b();
151+
test_c();
152+
test_d();
153+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/index-mut-help2.rs:40:16
3+
|
4+
LL | map.insert(*index, 23);
5+
| ------ ^^^^^^ expected `A`, found `&&&&A`
6+
| |
7+
| arguments to this method are incorrect
8+
|
9+
note: method defined here
10+
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
11+
12+
error[E0308]: mismatched types
13+
--> $DIR/index-mut-help2.rs:71:16
14+
|
15+
LL | map.insert(*index, 23);
16+
| ------ ^^^^^^ expected `ACopy`, found `&&&&ACopy`
17+
| |
18+
| arguments to this method are incorrect
19+
|
20+
note: method defined here
21+
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
22+
help: consider dereferencing the borrow
23+
|
24+
LL | map.insert(*****index, 23);
25+
| ++++
26+
27+
error[E0277]: the trait bound `&B: Borrow<&&&&B>` is not satisfied
28+
--> $DIR/index-mut-help2.rs:95:9
29+
|
30+
LL | map[index] = 23;
31+
| ^^^^^ the trait `Borrow<&&&&B>` is not implemented for `&B`
32+
|
33+
= note: required for `HashMap<&B, u32>` to implement `Index<&&&&&B>`
34+
35+
error[E0277]: the trait bound `&B: Borrow<&&&&B>` is not satisfied
36+
--> $DIR/index-mut-help2.rs:98:36
37+
|
38+
LL | if let Some(val) = map.get_mut(index) {
39+
| ------- ^^^^^ the trait `Borrow<&&&&B>` is not implemented for `&B`
40+
| |
41+
| required by a bound introduced by this call
42+
|
43+
note: required by a bound in `HashMap::<K, V, S, A>::get_mut`
44+
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
45+
46+
error[E0277]: the trait bound `D: Borrow<&&&&D>` is not satisfied
47+
--> $DIR/index-mut-help2.rs:132:9
48+
|
49+
LL | map[index] = 23;
50+
| ^^^^^ unsatisfied trait bound
51+
|
52+
help: the trait `Borrow<&&&&D>` is not implemented for `D`
53+
but trait `Borrow<C>` is implemented for it
54+
--> $DIR/index-mut-help2.rs:18:1
55+
|
56+
LL | impl Borrow<C> for D {
57+
| ^^^^^^^^^^^^^^^^^^^^
58+
= help: for that trait implementation, expected `C`, found `&&&&D`
59+
= note: required for `HashMap<D, u32>` to implement `Index<&&&&&D>`
60+
61+
error[E0277]: the trait bound `D: Borrow<&&&&D>` is not satisfied
62+
--> $DIR/index-mut-help2.rs:135:36
63+
|
64+
LL | if let Some(val) = map.get_mut(index) {
65+
| ------- ^^^^^ unsatisfied trait bound
66+
| |
67+
| required by a bound introduced by this call
68+
|
69+
help: the trait `Borrow<&&&&D>` is not implemented for `D`
70+
but trait `Borrow<C>` is implemented for it
71+
--> $DIR/index-mut-help2.rs:18:1
72+
|
73+
LL | impl Borrow<C> for D {
74+
| ^^^^^^^^^^^^^^^^^^^^
75+
= help: for that trait implementation, expected `C`, found `&&&&D`
76+
note: required by a bound in `HashMap::<K, V, S, A>::get_mut`
77+
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
78+
79+
error[E0594]: cannot assign to data in an index of `HashMap<A, u32>`
80+
--> $DIR/index-mut-help2.rs:30:5
81+
|
82+
LL | map[index] = 23;
83+
| ^^^^^^^^^^^^^^^ cannot assign
84+
|
85+
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<A, u32>`
86+
help: use `.insert()` to insert a value into a `HashMap<A, u32>`
87+
|
88+
LL - map[index] = 23;
89+
LL + map.insert(*****index, 23);
90+
|
91+
help: use the entry API to modify a `HashMap<A, u32>` for more flexibility
92+
|
93+
LL - map[index] = 23;
94+
LL + let val = map.entry(*****index).insert_entry(23);
95+
|
96+
help: use `.get_mut()` to modify an existing key in a `HashMap<A, u32>`
97+
|
98+
LL - map[index] = 23;
99+
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
100+
|
101+
102+
error[E0594]: cannot assign to data in an index of `HashMap<A, u32>`
103+
--> $DIR/index-mut-help2.rs:31:5
104+
|
105+
LL | map[&&&&&&&&index] = 23;
106+
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot assign
107+
|
108+
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<A, u32>`
109+
help: use `.insert()` to insert a value into a `HashMap<A, u32>`
110+
|
111+
LL - map[&&&&&&&&index] = 23;
112+
LL + map.insert(*****index, 23);
113+
|
114+
help: use the entry API to modify a `HashMap<A, u32>` for more flexibility
115+
|
116+
LL - map[&&&&&&&&index] = 23;
117+
LL + let val = map.entry(*****index).insert_entry(23);
118+
|
119+
help: use `.get_mut()` to modify an existing key in a `HashMap<A, u32>`
120+
|
121+
LL - map[&&&&&&&&index] = 23;
122+
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
123+
|
124+
125+
error[E0507]: cannot move out of `*****index` which is behind a shared reference
126+
--> $DIR/index-mut-help2.rs:53:16
127+
|
128+
LL | map.insert(*****index, 23);
129+
| ^^^^^^^^^^ move occurs because `*****index` has type `A`, which does not implement the `Copy` trait
130+
|
131+
note: if `A` implemented `Clone`, you could clone the value
132+
--> $DIR/index-mut-help2.rs:8:1
133+
|
134+
LL | struct A {}
135+
| ^^^^^^^^ consider implementing `Clone` for this type
136+
...
137+
LL | map.insert(*****index, 23);
138+
| ---------- you could clone this value
139+
140+
error[E0594]: cannot assign to data in an index of `HashMap<ACopy, u32>`
141+
--> $DIR/index-mut-help2.rs:62:5
142+
|
143+
LL | map[index] = 23;
144+
| ^^^^^^^^^^^^^^^ cannot assign
145+
|
146+
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<ACopy, u32>`
147+
help: use `.insert()` to insert a value into a `HashMap<ACopy, u32>`
148+
|
149+
LL - map[index] = 23;
150+
LL + map.insert(*****index, 23);
151+
|
152+
help: use the entry API to modify a `HashMap<ACopy, u32>` for more flexibility
153+
|
154+
LL - map[index] = 23;
155+
LL + let val = map.entry(*****index).insert_entry(23);
156+
|
157+
help: use `.get_mut()` to modify an existing key in a `HashMap<ACopy, u32>`
158+
|
159+
LL - map[index] = 23;
160+
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
161+
|
162+
163+
error[E0594]: cannot assign to data in an index of `HashMap<C, u32>`
164+
--> $DIR/index-mut-help2.rs:114:5
165+
|
166+
LL | map[index] = 23;
167+
| ^^^^^^^^^^^^^^^ cannot assign
168+
|
169+
= help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `HashMap<C, u32>`
170+
help: use `.insert()` to insert a value into a `HashMap<C, u32>`
171+
|
172+
LL - map[index] = 23;
173+
LL + map.insert(*****index, 23);
174+
|
175+
help: use the entry API to modify a `HashMap<C, u32>` for more flexibility
176+
|
177+
LL - map[index] = 23;
178+
LL + let val = map.entry(*****index).insert_entry(23);
179+
|
180+
help: use `.get_mut()` to modify an existing key in a `HashMap<C, u32>`
181+
|
182+
LL - map[index] = 23;
183+
LL + if let Some(val) = map.get_mut(index) { *val = 23; };
184+
|
185+
186+
error: aborting due to 11 previous errors
187+
188+
Some errors have detailed explanations: E0277, E0308, E0507, E0594.
189+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)