Skip to content

Commit 039a553

Browse files
committed
Add more extended error messages for match exprs.
1 parent 19e9828 commit 039a553

File tree

1 file changed

+81
-6
lines changed

1 file changed

+81
-6
lines changed

src/librustc/diagnostics.rs

+81-6
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,24 @@ This means that perhaps some of the preceding patterns are too general, this one
2424
is too specific or the ordering is incorrect.
2525
"##,
2626

27+
E0002: r##"
28+
This error indicates that an empty match expression is illegal because the type
29+
it is matching on is non-empty (there exist values of this type). In safe code
30+
it is impossible to create an instance of an empty type, so empty match
31+
expressions are almost never desired. This error is typically fixed by adding
32+
one or more cases to the match expression.
33+
34+
An example of an empty type is `enum Empty { }`.
35+
"##,
36+
2737
E0003: r##"
28-
Not-a-Number (NaN) values can not be compared for equality and hence can never
38+
Not-a-Number (NaN) values cannot be compared for equality and hence can never
2939
match the input to a match expression. To match against NaN values, you should
3040
instead use the `is_nan` method in a guard, as in: x if x.is_nan() => ...
3141
"##,
3242

3343
E0004: r##"
34-
This error indicates that the compiler can not guarantee a matching pattern for
44+
This error indicates that the compiler cannot guarantee a matching pattern for
3545
one or more possible inputs to a match expression. Guaranteed matches are
3646
required in order to assign values to match expressions, or alternatively,
3747
determine the flow of execution.
@@ -54,14 +64,80 @@ E0006: r##"
5464
Patterns used to bind names must be irrefutable, that is, they must guarantee that a
5565
name will be extracted in all cases. If you encounter this error you probably need
5666
to use a `match` or `if let` to deal with the possibility of failure.
67+
"##,
68+
69+
E0007: r##"
70+
This error indicates that the bindings in a match arm would require a value to
71+
be moved into more than one location, thus violating unique ownership. Code like
72+
the following is invalid as it requires the entire Option<String> to be moved
73+
into a variable called `op_string` while simultaneously requiring the inner
74+
String to be moved into a variable called `s`.
75+
76+
let x = Some("s".to_string());
77+
match x {
78+
op_string @ Some(s) => ...
79+
None => ...
80+
}
81+
82+
See also Error 303.
83+
"##,
84+
85+
E0008: r##"
86+
Names bound in match arms retain their type in pattern guards. As such, if a
87+
name is bound by move in a pattern, it should also be moved to wherever it is
88+
referenced in the pattern guard code. Doing so however would prevent the name
89+
from being available in the body of the match arm. Consider the following:
90+
91+
match Some("hi".to_string()) {
92+
Some(s) if s.len() == 0 => // use s.
93+
...
94+
}
95+
96+
The variable `s` has type String, and its use in the guard is as a variable of
97+
type String. The guard code effectively executes in a separate scope to the body
98+
of the arm, so the value would be moved into this anonymous scope and therefore
99+
become unavailable in the body of the arm. Although this example seems
100+
innocuous, the problem is most clear when considering functions that take their
101+
argument by value.
102+
103+
match Some("hi".to_string()) {
104+
Some(s) if { drop(s); false } => (),
105+
Some(s) => // use s.
106+
...
107+
}
108+
109+
The value would be dropped in the guard then become unavailable not only in the
110+
body of that arm but also in all subsequent arms! The solution is to bind by
111+
reference when using guards or refactor the entire expression, perhaps by
112+
putting the condition inside the body of the arm.
113+
"##,
114+
115+
E0303: r##"
116+
In certain cases it is possible for sub-bindings to violate memory safety.
117+
Updates to the borrow checker in a future version of Rust may remove this
118+
restriction, but for now patterns must be rewritten without sub-bindings.
119+
120+
// Code like this...
121+
match Some(5) {
122+
ref op_num @ Some(num) => ...
123+
None => ...
124+
}
125+
126+
// ... should be updated to code like this.
127+
match Some(5) {
128+
Some(num) => {
129+
let op_num = &Some(num);
130+
...
131+
}
132+
None => ...
133+
}
134+
135+
See also https://github.com/rust-lang/rust/issues/14587
57136
"##
58137

59138
}
60139

61140
register_diagnostics! {
62-
E0002,
63-
E0007,
64-
E0008,
65141
E0009,
66142
E0010,
67143
E0011,
@@ -124,7 +200,6 @@ register_diagnostics! {
124200
E0300, // unexpanded macro
125201
E0301, // cannot mutable borrow in a pattern guard
126202
E0302, // cannot assign in a pattern guard
127-
E0303, // pattern bindings are not allowed after an `@`
128203
E0304, // expected signed integer constant
129204
E0305, // expected constant
130205
E0306, // expected positive integer for repeat count

0 commit comments

Comments
 (0)