Skip to content

Commit 71d68f4

Browse files
Add back the E0008 error code long explanation
1 parent 667db34 commit 71d68f4

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

src/librustc_error_codes/error_codes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ E0003: include_str!("./error_codes/E0003.md"),
1414
E0004: include_str!("./error_codes/E0004.md"),
1515
E0005: include_str!("./error_codes/E0005.md"),
1616
E0007: include_str!("./error_codes/E0007.md"),
17+
E0008: include_str!("./error_codes/E0008.md"),
1718
E0009: include_str!("./error_codes/E0009.md"),
1819
E0010: include_str!("./error_codes/E0010.md"),
1920
E0013: include_str!("./error_codes/E0013.md"),
@@ -413,7 +414,6 @@ E0744: include_str!("./error_codes/E0744.md"),
413414
E0745: include_str!("./error_codes/E0745.md"),
414415
;
415416
// E0006, // merged with E0005
416-
// E0008, // cannot bind by-move into a pattern guard
417417
// E0035, merged into E0087/E0089
418418
// E0036, merged into E0087/E0089
419419
// E0068,
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
3+
Names bound in match arms retain their type in pattern guards. As such, if a
4+
name is bound by move in a pattern, it should also be moved to wherever it is
5+
referenced in the pattern guard code. Doing so however would prevent the name
6+
from being available in the body of the match arm. Consider the following:
7+
8+
```
9+
match Some("hi".to_string()) {
10+
Some(s) if s.len() == 0 => {}, // use s.
11+
_ => {},
12+
}
13+
```
14+
15+
The variable `s` has type `String`, and its use in the guard is as a variable of
16+
type `String`. The guard code effectively executes in a separate scope to the
17+
body of the arm, so the value would be moved into this anonymous scope and
18+
therefore becomes unavailable in the body of the arm.
19+
The problem above can be solved by using the `ref` keyword.
20+
21+
```
22+
match Some("hi".to_string()) {
23+
Some(ref s) if s.len() == 0 => {},
24+
_ => {},
25+
}
26+
```
27+
28+
Though this example seems innocuous and easy to solve, the problem becomes clear
29+
when it encounters functions which consume the value:
30+
31+
```compile_fail,E0507
32+
struct A {}
33+
34+
impl A {
35+
fn consume(self) -> usize {
36+
0
37+
}
38+
}
39+
40+
fn main() {
41+
let a = Some(A{});
42+
match a {
43+
Some(y) if y.consume() > 0 => {}
44+
_ => {}
45+
}
46+
}
47+
```
48+
49+
In this situation, even the `ref` keyword cannot solve it, since borrowed
50+
content cannot be moved. This problem cannot be solved generally. If the value
51+
can be cloned, here is a not-so-specific solution:
52+
53+
```
54+
#[derive(Clone)]
55+
struct A {}
56+
57+
impl A {
58+
fn consume(self) -> usize {
59+
0
60+
}
61+
}
62+
63+
fn main() {
64+
let a = Some(A{});
65+
match a{
66+
Some(ref y) if y.clone().consume() > 0 => {}
67+
_ => {}
68+
}
69+
}
70+
```
71+
72+
If the value will be consumed in the pattern guard, using its clone will not
73+
move its ownership, so the code works.

0 commit comments

Comments
 (0)