Give a special message when the later use is from a call. Use the span
of the callee instead of the whole expression. For conflicting borrow
messages say that the later use is of the first borrow.
This commit improves mutability error suggestions by suggesting the
removal of `&mut` where a mutable borrow is being taken of a `&mut self`
or a `self: &mut Self`.
This commit is concerned with the case where the user tries to mutably
borrow a mutable reference, thereby triggering an error. Instead of the
existing suggestion to make the binding mutable, the compiler will now
suggest to avoid borrowing altogether.
The `FatalError.raise()` might seem unmotivated (in most places in
the compiler, `err.emit()` suffices), but it's actually used to
maintain behavior (viz., stop lexing, don't emit potentially spurious
errors looking for the next token after the bad Unicodepoint in the
exponent): the previous revision's `self.err_span_` ultimately calls
`Handler::emit`, which aborts if the `Handler`'s continue_after_error
flag is set, which seems to typically be true during lexing (see
`phase_1_parse_input` and and how `CompileController::basic` has
`continue_parse_after_error: false` in librustc_driver).
Also, let's avoid apostrophes in error messages (the present author
would argue that users expect a reassuringly detached, formal,
above-it-all tone from a Serious tool like a compiler), and use an
RLS-friendly structured suggestion.
Resolves#49746.
Blindly checkpoint status of NLL mode ui tests
This takes the next (and potentially final?) step with #48879.
Namely, this PR got things to the point where I can successfully run `compiletest` on `src/test/ui` with `--compile-mode=nll`.
Here are the main pieces of it:
1. To figure out how to even run `compiletest` normally on the ui directory, I ran `x.py test -vv`, and then looked for the `compiletest` invocation that mentioned `src/test/ui`.
2. I took the aforementioned `compiletest` invocation and used it, adding `--compile-mode=nll` to the end. It had 170 failing cases.
3. Due to #49855, I had to edit some of the tests so that they fail even under NLL, via `#[rustc_error]`. That's the first commit. (Then goto 2 to double-check no such tests remain.)
4. I took the generated `build/target/test/foo.stderr` file for every case that failed, and blindly copied it to `src/test/foo.nll.stderr`. That's the second commit.
5. Goto 2 until there were no failing cases.
6. Remove any stamp files, and re-run `x.py test` to make sure that the edits and new `.nll.stderr` files haven't broken the pre-existing test suite.
Impressing confused Python users with magical diagnostics is perhaps
worth this not-grossly-unreasonable (only 40ish lines) extra complexity
in the parser?
Thanks to Vadim Petrochenkov for guidance.
This resolves#46836.
(Meanwhile, a couple of parse-fail tests are moved to UI tests so that
the reader can see the new output, and an existing UI test is given a
more evocative name.)
Programmers used to working in some other languages (such as Python or
Go) might expect to be able to destructure values with comma-separated
identifiers but no parentheses on the left side of an assignment.
Previously, the first name in such code would get parsed as a
single-indentifier pattern—recognizing, for example, the
`let a` in `let a, b = (1, 2);`—whereupon we would have a fatal syntax
error on seeing an unexpected comma rather than the expected semicolon
(all the way nearer to the end of `parse_full_stmt`).
Instead, let's look for that comma when parsing the pattern, and if we
see it, momentarily make-believe that we're parsing the remaining
elements in a tuple pattern, so that we can suggest wrapping it all in
parentheses. We need to do this in a separate wrapper method called on
the top-level pattern (or `|`-patterns) in a `let` statement, `for`
loop, `if`- or `while let` expression, or match arm rather than within
`parse_pat` itself, because `parse_pat` gets called recursively to parse
the sub-patterns within a tuple pattern.
Resolves#48492.
When unnecessarily using a fat arrow after an if condition, suggest the
removal of it.
When finding an if statement with no block, point at the `if` keyword to
provide more context.
Rustc explain
Fixes#48041.
To make the review easier, I separated tests update to code update. Also, I used this script to generate new ui tests stderr:
```python
from os import listdir
from os.path import isdir, isfile, join
PATH = "src/test/ui"
def do_something(path):
files = [join(path, f) for f in listdir(path)]
for f in files:
if isdir(f):
do_something(f)
continue
if not isfile(f) or not f.endswith(".stderr"):
continue
x = open(f, "r")
content = x.read().strip()
if "error[E" not in content:
continue
errors = dict()
for y in content.splitlines():
if y.startswith("error[E"):
errors[y[6:11]] = True
errors = sorted(errors.keys())
if len(errors) < 1:
print("weird... {}".format(f))
continue
if len(errors) > 1:
content += "\n\nYou've got a few errors: {}".format(", ".join(errors))
content += "\nIf you want more information on an error, try using \"rustc --explain {}\"".format(errors[0])
else:
content += "\n\nIf you want more information on this error, try using \"rustc --explain {}\"".format(errors[0])
content += "\n"
x = open(f, "w")
x.write(content)
do_something(PATH)
```
type error method suggestions use whitelisted identity-like conversions
![method_jamboree_summit](https://user-images.githubusercontent.com/1076988/33523646-e5c43184-d7c0-11e7-98e5-1bff426ade86.png)
Previously, on a type mismatch (and if this wasn't preëmpted by a
higher-priority suggestion), we would look for argumentless methods
returning the expected type, and list them in a `help` note. This had two
major shortcomings: firstly, a lot of the suggestions didn't really make
sense (if you used a &str where a String was expected,
`.to_ascii_uppercase()` is probably not the solution you were hoping
for). Secondly, we weren't generating suggestions from the most useful
traits! We address the first problem with an internal
`#[rustc_conversion_suggestion]` attribute meant to mark methods that keep
the "same value" in the relevant sense, just converting the type. We
address the second problem by making `FnCtxt.probe_for_return_type` pass
the `ProbeScope::AllTraits` to `probe_op`: this would seem to be safe
because grep reveals no other callers of `probe_for_return_type`.
Also, structured suggestions are pretty and good for RLS and friends.
Unfortunately, the trait probing is still not all one would hope for: at a
minimum, we don't know how to rule out `into()` in cases where it wouldn't
actually work, and we don't know how to rule in `.to_owned()` where it
would. Issues #46459 and #46460 have been filed and are ref'd in a FIXME.
This is hoped to resolve#42929, #44672, and #45777.
Previously, on a type mismatch (and if this wasn't preëmpted by a
higher-priority suggestion), we would look for argumentless methods
returning the expected type, and list them in a `help` note.
This had two major shortcomings. Firstly, a lot of the suggestions didn't
really make sense (if you used a &str where a String was expected,
`.to_ascii_uppercase()` is probably not the solution you were hoping
for). Secondly, we weren't generating suggestions from the most useful
traits!
We address the first problem with an internal
`#[rustc_conversion_suggestion]` attribute meant to mark methods that keep
the "same value" in the relevant sense, just converting the type. We
address the second problem by making `FnCtxt.probe_for_return_type` pass
the `ProbeScope::AllTraits` to `probe_op`: this would seem to be safe
because grep reveals no other callers of `probe_for_return_type`.
Also, structured suggestions are preferred (because they're pretty, but
also for RLS and friends).
Also also, we make the E0055 autoderef recursion limit error use the
one-time-diagnostics set, because we can potentially hit the limit a lot
during probing. (Without this,
test/ui/did_you_mean/recursion_limit_deref.rs would report "aborting due to
51 errors").
Unfortunately, the trait probing is still not all one would hope for: at a
minimum, we don't know how to rule out `into()` in cases where it wouldn't
actually work, and we don't know how to rule in `.to_owned()` where it
would. Issues #46459 and #46460 have been filed and are ref'd in a FIXME.
This is hoped to resolve#42929, #44672, and #45777.
The previous message ("cannot assign/mutably borrow immutable field")
when trying to modify a field of an immutable binding gave the
(incorrect) impression that fields can be mutable independently of their
ADT's binding. Slightly reword the message to read "cannot
assign/mutably borrow field of immutable binding".