Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Librustc_resolve diagnostics fixes #33493

Merged
merged 2 commits into from
May 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 86 additions & 4 deletions src/librustc_resolve/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,91 @@ 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't "or" be "Or"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I think the comma is too much here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's part of the same sentence

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think the comma is too much. ;)

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:

```ignore
let x = (0, 2);
match x {
(0, ref y) | (ref y, 0) => { /* use y */}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an ICE. I already filed it. We need to add "ignore" on this one or to find a workaround...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. r?

(I didn't mention a bug number here since this is supposed to be read by the user. I've left a note on the ICE bug.)

_ => ()
}
```

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 +1230,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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be totally removed. Not sure about this. cc @steveklabnik

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we need to keep it mentioned like the other obsolete ones

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