Skip to content

Commit

Permalink
Rollup merge of #33493 - Manishearth:more-diag, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
Librustc_resolve diagnostics fixes

r? @GuillaumeGomez
  • Loading branch information
Manishearth committed May 8, 2016
2 parents 6249772 + a795419 commit 24ff1e0
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 21 deletions.
89 changes: 85 additions & 4 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,90 @@ impl Bar {
```
"##,

E0408: r##"
An "or" pattern was used where the variable bindings are not consistently bound
across patterns.
Example of erroneous code:
```compile_fail
match x {
Some(y) | None => { /* use y */ } // error: variable `y` from pattern #1 is
// not bound in pattern #2
_ => ()
}
```
Here, `y` is bound to the contents of the `Some` and can be used within the
block corresponding to the match arm. However, in case `x` is `None`, we have
not specified what `y` is, and the block will use a nonexistent variable.
To fix this error, either split into multiple match arms:
```
let x = Some(1);
match x {
Some(y) => { /* use y */ }
None => { /* ... */ }
}
```
or, bind the variable to a field of the same type in all sub-patterns of the
or pattern:
```
let x = (0, 2);
match x {
(0, y) | (y, 0) => { /* use y */}
}
```
In this example, if `x` matches the pattern `(0, _)`, the second field is set
to `y`. If it matches `(_, 0)`, the first field is set to `y`; so in all
cases `y` is set to some value.
"##,

E0409: r##"
An "or" pattern was used where the variable bindings are not consistently bound
across patterns.
Example of erroneous code:
```compile_fail
let x = (0, 2);
match x {
(0, ref y) | (y, 0) => { /* use y */} // error: variable `y` is bound with
// different mode in pattern #2
// than in pattern #1
_ => ()
}
```
Here, `y` is bound by-value in one case and by-reference in the other.
To fix this error, just use the same mode in both cases.
Generally using `ref` or `ref mut` where not already used will fix this:
```
let x = (0, 2);
match x {
(0, ref y) | (ref y, 0) => { /* use y */}
_ => ()
}
```
Alternatively, split the pattern:
```
let x = (0, 2);
match x {
(y, 0) => { /* use y */ }
(0, ref y) => { /* use y */}
_ => ()
}
```
"##,

E0411: r##"
The `Self` keyword was used outside an impl or a trait. Erroneous code example:
Expand Down Expand Up @@ -1145,10 +1229,7 @@ register_diagnostics! {
// E0258,
E0402, // cannot use an outer type parameter in this context
E0406, // undeclared associated type
E0408, // variable from pattern #1 is not bound in pattern #
E0409, // variable is bound with different mode in pattern # than in
// pattern #1
E0410, // variable from pattern is not bound in pattern 1
// E0410, merged into 408
E0418, // is not an enum variant, struct or const
E0420, // is not an associated const
E0421, // unresolved associated const
Expand Down
25 changes: 8 additions & 17 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,10 @@ enum ResolutionError<'a> {
TypeNotMemberOfTrait(Name, &'a str),
/// error E0438: const is not a member of trait
ConstNotMemberOfTrait(Name, &'a str),
/// error E0408: variable `{}` from pattern #1 is not bound in pattern
VariableNotBoundInPattern(Name, usize),
/// error E0408: variable `{}` from pattern #{} is not bound in pattern #{}
VariableNotBoundInPattern(Name, usize, usize),
/// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
VariableBoundWithDifferentMode(Name, usize),
/// error E0410: variable from pattern is not bound in pattern #1
VariableNotBoundInParentPattern(Name, usize),
/// error E0411: use of `Self` outside of an impl or trait
SelfUsedOutsideImplOrTrait,
/// error E0412: use of undeclared
Expand Down Expand Up @@ -272,13 +270,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
const_,
trait_)
}
ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => {
ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
struct_span_err!(resolver.session,
span,
E0408,
"variable `{}` from pattern #1 is not bound in pattern #{}",
"variable `{}` from pattern #{} is not bound in pattern #{}",
variable_name,
pattern_number)
from,
to)
}
ResolutionError::VariableBoundWithDifferentMode(variable_name, pattern_number) => {
struct_span_err!(resolver.session,
Expand All @@ -289,14 +288,6 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
variable_name,
pattern_number)
}
ResolutionError::VariableNotBoundInParentPattern(variable_name, pattern_number) => {
struct_span_err!(resolver.session,
span,
E0410,
"variable `{}` from pattern #{} is not bound in pattern #1",
variable_name,
pattern_number)
}
ResolutionError::SelfUsedOutsideImplOrTrait => {
struct_span_err!(resolver.session,
span,
Expand Down Expand Up @@ -2038,7 +2029,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None => {
resolve_error(self,
p.span,
ResolutionError::VariableNotBoundInPattern(key, i + 1));
ResolutionError::VariableNotBoundInPattern(key, 1, i + 1));
}
Some(binding_i) => {
if binding_0.binding_mode != binding_i.binding_mode {
Expand All @@ -2055,7 +2046,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if !map_0.contains_key(&key) {
resolve_error(self,
binding.span,
ResolutionError::VariableNotBoundInParentPattern(key, i + 1));
ResolutionError::VariableNotBoundInPattern(key, i + 1, 1));
}
}
}
Expand Down

0 comments on commit 24ff1e0

Please sign in to comment.