Introduce #[diagnostic::on_move(message)]
cc rust-lang/rust#149862
This is a first proposal. I have deliberately kept it simpler than `diagnostic::on_unimplemented`.
Few questions/remarks:
- Do I need to move the OnMoveDirective logic into a dedicated module perhaps ? let's say into compiler/rustc_borrowck/src/diagnostics/on_move.rs
- No problems to depend on crates like `rustc_ast` from the borrowck ?
- Notes are not supported yet. While message and label are very static , in the sense that they are emitted in the same way from the same place in the borrowck, it is not the case for the notes. It would make the code more complex. But, I can add support for notes if it does make sense.
Suggestions are welcomed !
Show named lifetime in closure upvar diagnostics
Fixesrust-lang/rust#153545.
When a closure captures a variable whose type involves a named lifetime from the parent function (e.g., `'a`), the borrow checker's region renumbering creates a separate `RegionVid` for each occurrence of the erased lifetime in the closure's upvar type. These new `RegionVid`s have no `external_name`, so diagnostics fall back to synthetic names like `'1`.
This PR recovers the original lifetime name by matching the closure's upvar type against the parent function's parameter type (obtained via `liberate_late_bound_regions`). Both types have the same structure but different region representations, the parent has `ReLateParam`/`ReEarlyParam` with real names, the closure has `ReVar` from renumbering. Walking them in parallel with `for_each_free_region` lets us find which named lifetime corresponds to the anonymous `RegionVid`.
Before:
```rust
error[E0716]: temporary value dropped while borrowed
--> test.rs:11:21
|
6 | fn apply<'a>(
| -- lifetime `'1` defined here
```
After:
```rust
error[E0716]: temporary value dropped while borrowed
--> test.rs:11:21
|
6 | fn apply<'a>(
| -- lifetime `'a` defined here
```
The fix gracefully falls back to the existing `'1` naming when it can't match, nested closures, local variables (not parameters), destructuring patterns, or partial captures where the type structures diverge.
```
error[E0382]: use of moved value: `foo`
--> $DIR/as-ref-2.rs:10:14
|
LL | let foo = Some(Struct);
| --- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait
LL | let _x: Option<Struct> = foo.map(|s| bar(&s));
| ---------------- `foo` moved due to this method call
LL | let _y = foo;
| ^^^ value used here after move
|
note: `Option::<T>::map` takes ownership of the receiver `self`, which moves `foo`
--> $SRC_DIR/core/src/option.rs:LL:COL
help: consider calling `.as_ref()` to borrow the value's contents
|
LL | let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s));
| +++++++++
help: consider calling `.as_mut()` to mutably borrow the value's contents
|
LL | let _x: Option<Struct> = foo.as_mut().map(|s| bar(&s));
| +++++++++
```
Unify same-span labels in move error diagnostics
Fixesrust-lang/rust#153506.
When there's a single binding in a move error, we emit "data moved here" and "move occurs because ... does not implement the Copy trait" as two separate labels on the same span. This combines them into one label via a new `TypeNoCopy::LabelMovedHere` variant.
The multi-binding case still uses separate labels + a note since they point at different spans.
cc @estebank
This might be helpful for smart pointers to explains why they aren't Copy
and what to do instead or just to let the user know that .clone() is very
cheap and can be called without a performance penalty.
It's defined in `rustc_span::source_map` which doesn't make any sense
because it has nothing to do with source maps. This commit moves it to
the crate root, a more sensible spot for something this basic.
Overhaul `ensure_ok`
The interaction of `ensure_ok` and the `return_result_from_ensure_ok` query modifier is weird and hacky. This PR cleans it up. Details in the individual commits.
r? @Zalathar
`ensure_ok` provides a special, more efficient way of calling a query
when its return value isn't needed. But there is a complication: if the
query is marked with the `return_result_from_ensure_ok` modifier, then
it will return `Result<(), ErrorGuaranteed`. This is clunky and feels
tacked on. It's annoying to have to add a modifier to a query to declare
information present in its return type, and it's confusing that queries
called via `ensure_ok` have different return types depending on the
modifier.
This commit:
- Eliminates the `return_result_from_ensure_ok` modifier. The proc macro
now looks at the return type and detects if it matches `Result<_,
ErrorGuarantee>`. If so, it adds the modifier
`returns_error_guaranteed`. (Aside: We need better terminology to
distinguish modifiers written by the user in a `query` declaration
(e.g. `cycle_delayed_bug`) from modifiers added by the proc macro
(e.g. `cycle_error_handling`.))
- Introduces `ensure_result`, which replaces the use of `ensure_ok` for
queries that return `Result<_, ErrorGuarantee>`. As a result,
`ensure_ok` can now only be used for the "ignore the return value"
case.
Two places where `ensure_ok` can be used but currently isn't. (These
queries are marked with `return_result_from_ensure_ok`, which means that
`ensure_ok` returns `Result<(), ErrorGuaranteed>`.) This is potentially
a perf win, because `ensure_ok` query calls can be faster.
Clean up the eager formatting API
For https://github.com/rust-lang/rust/issues/151366#event-22181360642
Previously eager formatting worked by throwing the arguments into a diag, formatting, then removing the args again. This is ugly so instead we now just do the formatting completely separately.
This PR has nice commits, so I recommend reviewing commit by commit.
r? @GuillaumeGomez
Suppress invalid suggestions in destructuring assignment
Fixesrust-lang/rust#152694
When destructuring assignment hits a type with `Drop`, the compiler was emitting two broken suggestions: `ref *&mut String::new()` (invalid syntax) and `.clone()` on a temporary (useless).
Root cause: the suggestion logic didn't know these bindings were synthetic from assign desugaring. The fix reuses the existing `AssignDesugar` detection in `BindingFinder` to collect those spans and skip both suggestions.
refactor(mgca): Change `DefKind::Const` and `DefKind::AssocConst` to have a `is_type_const` flag
Addresses rust-lang/rust#152940
- Changed `DefKind::Const` and `DefKind::AssocConst` to have a `is_type_const` flag.
- changed `is_type_const` query to check for this flag
- removed `is_rhs_type_const` query
r? @BoxyUwU
* refactor: add `is_type_const` flag to `DefKind::Const` and `AssocConst`
* refactor(cleanup) remove the `rhs_is_type_const` query
* style: fix formatting
* refactor: refactor stuff in librustdoc for new Const and AssocConst
* refactor: refactor clippy for the changes
* chore: formatting
* fix: fix test
* fix: fix suggestions
* Update context.rs
Co-authored-by: Boxy <rust@boxyuwu.dev>
* changed AssocKind::Const to store data about being a type const
`IntoQueryParam` is a trait that lets query callers be a bit sloppy with
the passed-in key.
- Types similar to `DefId` will be auto-converted to `DefId`. Likewise
for `LocalDefId`.
- Reference types will be auto-derefed.
The auto-conversion is genuinely useful; the auto-derefing much less so.
In practice it's only used for passing `&DefId` to queries that accept
`DefId`, which is an anti-pattern because `DefId` is marked with
`#[rustc_pass_by_value]`.
This commit removes the auto-deref impl and makes the necessary sigil
adjustments. (I generally avoid using `*` to deref manually at call
sites, preferring to deref via `&` in patterns or via `*` in match
expressions. Mostly because that way a single deref often covers
multiple call sites.)
A couple of tiny polonius things
Here's a couple of tiny things I had ready to go @jackh726
- a tiny cleanup to avoid round-tripping through `Location`s to check for liveness, since we're already working with points
- while I was there, I fixed the doc which wasn't showing up properly (maybe a rustdoc or bootstrap bug when we build locally or during dist, either way, both don't show up correctly linked most of the time) for `PointIndex`es.
- and in the second commit slightly expand test coverage with [an example](https://internals.rust-lang.org/t/get-mut-map-back-from-entry-api/24003) that would have needed stdlib changes (cc author @Darksonn for visibility here)
More soon.
r? @jackh726
now that we need to hold the graph for MIR dumping, and the associated
data to traverse it, there is no difference between the main context and
diagnostics context, so we merge them.
we may need to traverse the lazy graph multiple times:
- to record loan liveness
- to dump the localized outlives constraint in the polonius MIR dump
to do that we extract the previous loan liveness code into an abstract
traversal + visitor handling the liveness-specific parts, while the MIR
dump will be able to record constraints in its own visitor.
now that the analysis is only using the regular liveness shape, we don't
need to store it transposed, and thus don't need the container where it
was stored: the liveness context would be alone in the polonius context.
we thus remove the latter, and rename the former.