During borrowck, the `MultiSpan` from a buffered diagnostic is cloned and
used to emit a delayed bug indicating a diagnostic was buffered - when
the buffered diagnostic is translated, then the cloned `MultiSpan` may
contain labels which can only render with the diagnostic's arguments, but
the delayed bug being emitted won't have those arguments. Adds a function
which clones `MultiSpan` without also cloning the contained labels, and
use this function when creating the buffered diagnostic delayed bug.
Signed-off-by: David Wood <david@davidtw.co>
Use maybe_body_owned_by for multiple suggestions
This is a continued work from https://github.com/rust-lang/rust/pull/113567
We have several other suggestions not working for closure, this PR use `maybe_body_owned_by` to fix them and add test cases for them.
(re-)tighten sourceinfo span of adjustments in MIR
Diagnostics rely on the spans of MIR statements being (approximately) correct in order to give suggestions relative to that span (i.e. `shrink_to_hi` and `shrink_to_lo`).
I discovered that we're *intentionally* lowering THIR exprs with their parent expr's span if they come from adjustments that are due to a parent expression. While I understand why that may be desirable to demonstrate the relationship of an adjustment and the expression that requires it, it leads to
1. very verbose borrowck output
2. incorrect spans for suggestions
Some diagnostics get around that by giving suggestions relative to other spans we've collected during MIR lowering, such as the span of the method's identifier (e.g. `name` in `.name()`), but this doesn't work too well when things come from desugaring.
I assume it also has lead to numerous tweaks and complications to diagnostics code down the road, which this PR doesn't necessarily aim to fix but may open the gates to fixing later... The last three commits are simplifications due to the fact that we can assume that the move span actually points to what is being moved (and a test).
This regressed in #89110, which was debated somewhat in #90286. cc `@Aaron1011` who originally made this change.
r? diagnostics
Fixes#113547Fixes#111016
Rewrite `UnDerefer`, again
This PR is intended to improve the perf regression introduced by #112882.
`UnDerefer` has been separated out again for borrowck reasons. It was a bit overzealous to remove it in the previous PR.
r? `@oli-obk`
It makes it sound like the `ExprKind` and `Rvalue` are supposed to represent all pointer related
casts, when in reality their just used to share a some enum variants. Make it clear there these
are only coercion to make it clear why only some pointer related "casts" are in the enum.
Rewrite `UnDerefer`
Currently, `UnDerefer` is used by drop elaboration to undo the effects of the `Derefer` pass. However, it just recreates the original places with derefs in the middle of the projection. Because `ProjectionElem::Deref` is intended to be removed completely in the future, this will not work forever.
This PR introduces a `deref_chain` method that returns the places behind `DerefTemp` locals in a place and rewrites the move path code to use this. In the process, `UnDerefer` was merged into `MovePathLookup`. Now that move paths use the same places as in the MIR, the other uses of `UnDerefer` no longer require it.
See #98145
cc `@ouz-a`
r? `@oli-obk`
suggest `slice::swap` for `mem::swap(&mut x[0], &mut x[1])` borrowck error
Recently saw someone ask why this code (example slightly modified):
```rs
fn main() {
let mut foo = [1, 2];
std::mem::swap(&mut foo[0], &mut foo[1]);
}
```
triggers this error and how to fix it:
```
error[E0499]: cannot borrow `foo[_]` as mutable more than once at a time
--> src/main.rs:4:33
|
4 | std::mem::swap(&mut foo[0], &mut foo[1]);
| -------------- ----------- ^^^^^^^^^^^ second mutable borrow occurs here
| | |
| | first mutable borrow occurs here
| first borrow later used by call
|
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
```
The current help message is nice and goes in the right direction, but I think we can do better for this specific instance and suggest `slice::swap`, which makes this compile
Migrate `TyCtxt::predicates_of` and `ParamEnv::caller_bounds` to `Clause`
The last big change in the series.
I will follow-up with additional filed issues once this PR lands:
- [ ] Investigate making `TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx>` implementation less weird: 2efe091705/compiler/rustc_middle/src/ty/structural_impls.rs (L672)
- [ ] Clean up the elaborator since it should only be emitting child clauses, not predicates
- [ ] Rename identifiers like `pred` and `predicates` to `clause` if they're actually clauses around the codebase
- [ ] Validate that all of the `ToPredicate` impls are acutally still needed, or prune them if they're not
r? `@ghost` until the other branch lands
[-Ztrait-solver=next, mir-typeck] instantiate hidden types in the root universe
Fixes an ICE in the test `member-constraints-in-root-universe`.
Main motivation is to make #112691 pass under the new solver.
r? ``@compiler-errors``
Migrate `item_bounds` to `ty::Clause`
Should be simpler than the next PR that's coming up. Last three commits are the relevant ones.
r? ``@oli-obk`` or ``@lcnr``
Add a fully fledged `Clause` type, rename old `Clause` to `ClauseKind`
Does two basic things before I put up a more delicate set of PRs (along the lines of #112714, but hopefully much cleaner) that migrate existing usages of `ty::Predicate` to `ty::Clause` (`predicates_of`/`item_bounds`/`ParamEnv::caller_bounds`).
1. Rename `Clause` to `ClauseKind`, so it's parallel with `PredicateKind`.
2. Add a new `Clause` type which is parallel to `Predicate`.
* This type exposes `Clause::kind(self) -> Binder<'tcx, ClauseKind<'tcx>>` which is parallel to `Predicate::kind` 😸
The new `Clause` type essentially acts as a newtype wrapper around `Predicate` that asserts that it is specifically a `PredicateKind::Clause`. Turns out from experimentation[^1] that this is not negative performance-wise, which is wonderful, since this a much simpler design than something that requires encoding the discriminant into the alignment bits of a predicate kind, or something else like that...
r? ``@lcnr`` or ``@oli-obk``
[^1]: https://github.com/rust-lang/rust/pull/112714#issuecomment-1595653910
Don't consider TAIT normalizable to hidden ty if it would result in impossible item bounds
See test for example where we shouldn't consider it possible to alias-relate a TAIT and hidden type.
r? `@lcnr`
Take MIR dataflow analyses by mutable reference
The main motivation here is any analysis requiring dynamically sized scratch memory to work. One concrete example would be pointer target tracking, where tracking the results of a dereference can result in multiple possible targets. This leads to processing multi-level dereferences requiring the ability to handle a changing number of potential targets per step. A (simplified) function for this would be `fn apply_deref(potential_targets: &mut Vec<Target>)` which would use the scratch space contained in the analysis to send arguments and receive the results.
The alternative to this would be to wrap everything in a `RefCell`, which is what `MaybeRequiresStorage` currently does. This comes with a small perf cost and loses the compiler's guarantee that we don't try to take multiple borrows at the same time.
For the implementation:
* `AnalysisResults` is an unfortunate requirement to avoid an unconstrained type parameter error.
* `CloneAnalysis` could just be `Clone` instead, but that would result in more work than is required to have multiple cursors over the same result set.
* `ResultsVisitor` now takes the results type on in each function as there's no other way to have access to the analysis without cloning it. This could use an associated type rather than a type parameter, but the current approach makes it easier to not care about the type when it's not necessary.
* `MaybeRequiresStorage` now no longer uses a `RefCell`, but the graphviz formatter now does. It could be removed, but that would require even more changes and doesn't really seem necessary.
Add `-Ztrait-solver=next-coherence`
Flag that conditionally uses the trait solver *only* during coherence, for more testing and/or eventual partial-migration onto the trait solver (in the medium- to long-term).
* This still uses the selection context in some of the coherence methods I think, so it's not "complete". Putting this up for review and/or for further work in-tree.
* I probably need to spend a bit more time making sure that we don't sneakily create any other infcx's during coherence that also need the new solver enabled.
r? `@lcnr`
Remove default visitor impl in region constraint generation
I wanted to group it together with other possibly minor borrowck cleanups but that's all I have right now so I rather put it up than forget about it before doing something else.
r? `@compiler-errors`
Don't suggest changing `&self` and `&mut self` in function signature to be mutable when taking `&mut self` in closure
Current suggestion for when taking a mutable reference to `self` in a closure (as an upvar) will produce a machine-applicable suggestion to change the `self` in the function signature to `mut self`, but does not account for the specialness of implicit self in that it can already have `&` and `&mut` (see #111554). This causes the function signature to become `test(&mut mut self)` which does not seem desirable.
```
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> src/sound_player.rs:870:11
|
869 | pub fn test(&mut self) {
| ---- help: consider changing this to be mutable: `mut self`
870 | || test2(&mut self);
| ^^^^^^^^^ cannot borrow as mutable
```
This PR suppresses the "changing this to be mutable" suggestion if the implicit self is either `ImplicitSelfKind::ImmRef` or `ImplicitSelfKind::MutRef`.
Fixes#111554.
Preserve substs in opaques recorded in typeck results
This means that we now prepopulate MIR with opaques with the right substs.
The first commit is a hack that I think we discussed, having to do with `DefiningAnchor::Bubble` basically being equivalent to `DefiningAnchor::Error` in the new solver, so having to use `DefiningAnchor::Bind` instead, lol.
r? `@lcnr`
change `BorrowKind::Unique` to be a mutating `PlaceContext`
fixes#112056
I believe that `BorrowKind::Unique` is a footgun in general, so I added a FIXME and opened https://github.com/rust-lang/rust/issues/112072. This is a bit too involved for this PR though.
Perform MIR type ops locally in new solver
The new solver already does caching, and it's generally more correct to be using the infcx of the MIR typeck (which has the defining anchor set correctly and has already initialized all the opaques from HIR typeck).
This is based on #111918 so look at the final 3 commits.
This actually causes some tests to go from passing to failing, and failing to passing. Here's the full diff: https://www.diffchecker.com/hB4bh1A9/
Putting this up for exposure mostly.
r? `@lcnr`
Rollup of 5 pull requests
Successful merges:
- #111741 (Use `ObligationCtxt` in custom type ops)
- #111840 (Expose more information in `get_body_with_borrowck_facts`)
- #111876 (Roll compiler_builtins to 0.1.92)
- #111912 (Use `Option::is_some_and` and `Result::is_ok_and` in the compiler )
- #111915 (libtest: Improve error when missing `-Zunstable-options`)
r? `@ghost`
`@rustbot` modify labels: rollup
Use `Option::is_some_and` and `Result::is_ok_and` in the compiler
`.is_some_and(..)`/`.is_ok_and(..)` replace `.map_or(false, ..)` and `.map(..).unwrap_or(false)`, making the code more readable.
This PR is a sibling of https://github.com/rust-lang/rust/pull/111873#issuecomment-1561316515
Expose more information in `get_body_with_borrowck_facts`
Verification tools for Rust such as, for example, Creusot or Prusti would benefit from having access to more information computed by the borrow checker.
As a first step in that direction, #86977 added the `get_body_with_borrowck_facts` API, allowing compiler consumers to obtain a `mir::Body` with accompanying borrow checker information.
At RustVerify 2023, multiple people working on verification tools expressed their need for a more comprehensive API.
While eventually borrow information could be part of Stable MIR, in the meantime, this PR proposes a more limited approach, extending the existing `get_body_with_borrowck_facts` API.
In summary, we propose the following changes:
- Permit obtaining the borrow-checked body without necessarily running Polonius
- Return the `BorrowSet` and the `RegionInferenceContext` in `BodyWithBorrowckFacts`
- Provide a way to compute the `borrows_out_of_scope_at_location` map
- Make some helper methods public
This is similar to #108328 but smaller in scope.
`@smoelius` Do you think these changes would also be sufficient for your needs?
r? `@oli-obk`
cc `@JonasAlaif`
Use `ObligationCtxt` in custom type ops
We already make one when evaluating the `CustomTypeOp`, so it's simpler to just pass it to the user. Removes a redundant `ObligationCtxt::new_in_snapshot` usage and simplifies some other code.
This makes several refactorings related to opaque types in the new solver simpler, but those are not included in this PR.
Don't skip mir typeck if body has errors
Comment says:
```
// if verifier failed, don't do further checks to avoid ICEs
```
But there are no ICEs to be found. The comment is quite old, so perhaps something fixed it... maybe because the MIR typechecker is delaying span bugs rather than panicking via eager bugs? IDK
I'm generally inclined to fix the ICEs themselves that were to arise from this, rather than just totally skipping large parts of the compiler that have impacts on downstream logic (namely, our opaque type results are affected). Anyways, this happens on the error path, so it shouldn't really matter.
Fixes this hack: https://github.com/rust-lang/rust/pull/111853/files#r1201501540
Preprocess and cache dominator tree
Preprocessing dominators has a very strong effect for https://github.com/rust-lang/rust/pull/111344.
That pass checks that assignments dominate their uses repeatedly. Using the unprocessed dominator tree caused a quadratic runtime (number of bbs x depth of the dominator tree).
This PR also caches the dominator tree and the pre-processed dominators in the MIR cfg cache.
Rebase of https://github.com/rust-lang/rust/pull/107157
cc `@tmiasko`
Error message all end up passing into a function as an `impl
Into<{D,Subd}iagnosticMessage>`. If an error message is creatd as
`&format("...")` that means we allocate a string (in the `format!`
call), then take a reference, and then clone (allocating again) the
reference to produce the `{D,Subd}iagnosticMessage`, which is silly.
This commit removes the leading `&` from a lot of these cases. This
means the original `String` is moved into the
`{D,Subd}iagnosticMessage`, avoiding the double allocations. This
requires changing some function argument types from `&str` to `String`
(when all arguments are `String`) or `impl
Into<{D,Subd}iagnosticMessage>` (when some arguments are `String` and
some are `&str`).
Require impl Trait in associated types to appear in method signatures
This implements the limited version of TAIT that was proposed in https://github.com/rust-lang/rust/issues/107645#issuecomment-1477899536
Similar to `impl Trait` in return types, `impl Trait` in associated types may only be used within the impl block which it is a part of. To make everything simpler and forward compatible to getting desugared to a plain type alias impl trait in the future, we're requiring that any associated functions or constants that want to register hidden types must be using the associated type in their signature (type of the constant or argument/return type of the associated method. Where bounds mentioning the associated type are ignored).
We have preexisting tests checking that this works transitively across multiple associated types in situations like
```rust
impl Foo for Bar {
type A = impl Trait;
type B = impl Iterator<Item = Self::A>;
fn foo() -> Self::B { ...... }
}
```
Reduce BitSet size used in `Borrows` dataflow analysis
It looks like it is not needed to multiply the number of borrows by 2. Bits greater than `self.borrow_set.len()` are never set in this bitset. This should decrease the memory usage by an epsilon.
tweak "make mut" spans when assigning to locals
Work towards fixing #106857
This PR just cleans up a lot of spans which is helpful before properly fixing the issues. Best reviewed commit-by-commit.
r? `@estebank`
Fix lifetime suggestion for type aliases with objects in them
Fixes an issue identified in https://github.com/rust-lang/rust/issues/110761#issuecomment-1520678479
This suggestion, like many other borrowck suggestions, are very fragile and there are other ways to trigger strange behavior even after this PR, so this is just a small improvement and not a total rework 💀
try to downgrade Arc -> Lrc -> Rc -> no-Rc in few places
Expecting this be not slower on non-parallel compiler and probably faster on parallel (checked that this PR builds on it).
check array type of repeat exprs is wf
Fixes#111091
Also makes sure that we actually renumber regions in the length of repeat exprs which we previously weren't doing and would cause ICEs in `adt_const_params` + `generic_const_exprs` from attempting to prove the wf goals when the length was an unevaluated constant with `'erased` in the `ty` field of `Const`
The duplicate errors are caused by the fact that `const_arg_to_const`/`array_len_to_const` in `FnCtxt` adds a `WellFormed` goal for the created `Const` which is also checked by the added `WellFormed(array_ty)`. I don't want to change this to just emit a `T: Sized` goal for the element type since that would ignore `ConstArgHasType` wf requirements and generally uncomfortable with the idea of trying to sync up `wf::obligations` for arrays and the code in hir typeck for repeat exprs.
r? `@compiler-errors`
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
Tweak await span to not contain dot
Fixes a discrepancy between method calls and await expressions where the latter are desugared to have a span that *contains* the dot (i.e. `.await`) but method call identifiers don't contain the dot. This leads to weird suggestions suggestions in borrowck -- see linked issue.
Fixes#110761
This mostly touches a bunch of tests to tighten their `await` span.
fix false negative for `unused_mut`
fixes https://github.com/rust-lang/rust/issues/110849
We want to avoid double diagnostics for code like this, but only if an error actually occurs:
```rust
fn main() {
let mut x: (i32, i32);
x.0 = 1;
}
```
The first commit fixes the lint and the second one removes all the unused `mut`s it found.
Switch to `EarlyBinder` for `explicit_item_bounds`
Part of the work to finish https://github.com/rust-lang/rust/issues/105779.
This PR adds `EarlyBinder` to the return type of the `explicit_item_bounds` query and removes `bound_explicit_item_bounds`.
r? `@compiler-errors` (hope it's okay to request you, since you reviewed #110299 and #110498😃)
Run various queries from other queries instead of explicitly in phases
These are just legacy leftovers from when rustc didn't have a query system. While there are more cleanups of this sort that can be done here, I want to land them in smaller steps.
This phased order of query invocations was already a lie, as any query that looks at types (e.g. the wf checks run before) can invoke e.g. const eval which invokes borrowck, which invokes typeck, ...
Clone region var origins instead of taking them in borrowck
Fixes an issue with the new solver where reporting a borrow-checker error ICEs because it calls `InferCtxt::evaluate_obligation`.
This also removes a handful of unnecessary `tcx.infer_ctxt().build()` calls that are only there to mitigate this same exact issue, but with the old solver.
Fixescompiler-errors/next-solver-hir-issues#12.
----
This implements `@aliemjay's` solution where we just don't *take* the region constraints, but clone them. This potentially makes it easier to write a bug about taking region constraints twice or never at all, but again, not many folks are touching this code.
Evaluate place expression in `PlaceMention`
https://github.com/rust-lang/rust/pull/102256 introduces a `PlaceMention(place)` MIR statement which keep trace of `let _ = place` statements from surface rust, but without semantics.
This PR proposes to change the behaviour of `let _ =` patterns with respect to the borrow-checker to verify that the bound place is live.
Specifically, consider this code:
```rust
let _ = {
let a = 5;
&a
};
```
This passes borrowck without error on stable. Meanwhile, replacing `_` by `_: _` or `_p` errors with "error[E0597]: `a` does not live long enough", [see playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c448d25a7c205dc95a0967fe96bccce8).
This PR *does not* change how `_` patterns behave with respect to initializedness: it remains ok to bind a moved-from place to `_`.
The relevant test is `tests/ui/borrowck/let_underscore_temporary.rs`. Crater check found no regression.
For consistency, this PR changes miri to evaluate the place found in `PlaceMention`, and report eventual dangling pointers found within it.
r? `@RalfJung`
Add offset_of! macro (RFC 3308)
Implements https://github.com/rust-lang/rfcs/pull/3308 (tracking issue #106655) by adding the built in macro `core::mem::offset_of`. Two of the future possibilities are also implemented:
* Nested field accesses (without array indexing)
* DST support (for `Sized` fields)
I wrote this a few months ago, before the RFC merged. Now that it's merged, I decided to rebase and finish it.
cc `@thomcc` (RFC author)