2447 Commits

Author SHA1 Message Date
bors
b2dd217dd0 Auto merge of #140737 - amandasystems:revised-constraint-search, r=lcnr
Region inference: Use outlives-static constraints in constraint search

Revise the extra `r: 'static` constraints added upon universe issues to add an explanation, and use that explanation during constraint blame search. This greatly simplifies the region inference logic, which now does not need to reverse-engineer the event that caused a region to outlive `'static`.

This cosmetically changes the output of two UI tests. I blessed them i separate commits with separate motivations, but that can of course be squashed as desired. We probably want that.

The PR was extracted out of rust-lang/rust#130227 and consists of one-third of its functional payload.

r? lcnr
2025-08-27 09:25:46 +00:00
bors
d327d651e2 Auto merge of #145711 - lcnr:non-defining-uses-hir-typeck, r=BoxyUwU
Support non-defining uses in HIR typeck

This changes the impl of `NormalizesTo` for opaque types to be structural during HIR typeck. The previous impl equated region variables of the opaque type key with existing entries which can result in spurious leak check errors and also results in mismatches with MIR borrowck, theoretically causing ICE.

The approach is very similar to rust-lang/rust#145244 in MIR typeck:
- we collect all uses of opaque types during HIR typeck
- before writeback, we search for *defining uses*
  - the opaque type key has fully universal generic args modulo regions
  - the hidden type has no infer vars
- we use these defining uses to compute the concrete type for the opaque and map it to the definition site
- we use this concrete type to check the type of all uses of opaques during HIR typeck. This also constrains infer vars in non-defining uses

Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/135, fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/49.

r? `@BoxyUwU`
2025-08-25 22:56:37 +00:00
lcnr
d6a18e1867 change non-defining use error message 2025-08-25 14:20:18 +02:00
lcnr
14b0ba6a05 support non-defining uses in HIR typeck 2025-08-25 14:20:18 +02:00
Stuart Cook
8a2568a3b6
Rollup merge of #145620 - compiler-errors:fake-dyn-to-dyn, r=lcnr
Account for impossible bounds making seemingly unsatisfyable dyn-to-dyn casts

Fixes https://github.com/rust-lang/rust/issues/141806

When we have an impossible where clause like `dyn Trait<u8>: Sized`, this may make a dyn-to-dyn cast like `dyn Trait<()> -> dyn trait<u8>` to successfully type check as if it were a wide-to-thin ptr cast (discarding metadata):

16ad385579/compiler/rustc_hir_typeck/src/cast.rs (L862-L865)

In borrowck, we are expecting that the only meaningful dyn-to-dyn cast to be a metadata-preserving wide-to-wide ptr cast, which requires that the principals of the dyn pointers are equal. Borrowck additionally assumes that these principals have already been proven equal *modulo regions*, and we thus ICE since `Trait<u8>` and `Trait<()>` do not unify:

16ad385579/compiler/rustc_borrowck/src/type_check/mod.rs (L1481-L1524)

This PR fixes this ICE by checking whether the RHS of the cast is considered to be Sized in the environment of the MIR typeck, and if so then skipping over this dyn->dyn principal compatibility check.

r? `@lcnr` perhaps?
2025-08-25 19:52:19 +10:00
Amanda Stjerna
ae622bb6af Simplify SCC annotations somewhat 2025-08-23 22:25:50 +02:00
Michael Goulet
e0fb6ebf7b Nits 2025-08-23 17:13:22 +00:00
Michael Goulet
c957c4e704 Account for impossible bounds making seemingly unsatisfyable dyn-to-dyn casts 2025-08-23 16:49:15 +00:00
lcnr
17ac2fc96d change HIR typeck unification handling approach 2025-08-22 13:39:38 +02:00
Amanda Stjerna
7dd56b10ad Region inference: Use outlives-static constraints in constraint search
Revise the extra `r: 'static` constraints added upon universe issues
to add an explanation, and use that explanation during constraint blame
search. This greatly simplifies the region inference logic, which
now does not need to reverse-engineer the event that caused a region
to outlive 'static.
2025-08-22 13:38:22 +02:00
bors
57e620e56b Auto merge of #145701 - jhpratt:rollup-a0kg33p, r=jhpratt
Rollup of 19 pull requests

Successful merges:

 - rust-lang/rust#143383 (stabilize `const_array_each_ref`)
 - rust-lang/rust#144758 ([Doc] Add links to the various collections)
 - rust-lang/rust#144915 (Defer tail call ret ty equality to check_tail_calls)
 - rust-lang/rust#145256 (Add new `--test-codegen-backend` bootstrap option)
 - rust-lang/rust#145297 (fix(debuginfo): handle false positives in overflow check)
 - rust-lang/rust#145390 (Shorten some dependency chains in the compiler)
 - rust-lang/rust#145415 (std_detect: RISC-V: implement implication to "C")
 - rust-lang/rust#145525 (stdlib: Replace typedef -> type alias in doc comment)
 - rust-lang/rust#145590 (Prevent impossible combinations in `ast::ModKind`.)
 - rust-lang/rust#145593 (UnsafePinned::raw_get: sync signature with get)
 - rust-lang/rust#145621 (Fix some doc typos)
 - rust-lang/rust#145627 (Unconditionally-const supertraits are considered not dyn compatible)
 - rust-lang/rust#145642 (Do not use effective_visibilities query for Adt types of a local trait while proving a where-clause)
 - rust-lang/rust#145650 (Fix JS search scripts path)
 - rust-lang/rust#145654 (Download CI GCC into the correct directory)
 - rust-lang/rust#145662 (Enforce correct number of arguments for `"x86-interrupt"` functions)
 - rust-lang/rust#145673 (Add flock support for cygwin)
 - rust-lang/rust#145674 (Enable triagebot `[review-changes-since]` feature)
 - rust-lang/rust#145678 (Fix typo in docstring)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-08-21 07:03:07 +00:00
lcnr
c2a0fa86ad diagnostics :3 2025-08-20 11:10:38 +02:00
lcnr
8365ad17da handle opaque types before region inference 2025-08-20 11:04:38 +02:00
lcnr
e255a9b28a region_infer::opaque_types to folder 2025-08-20 11:04:38 +02:00
lcnr
ff0a11b7db fully_perform_op_raw out of TypeChecker 2025-08-20 11:04:38 +02:00
Michael Goulet
6a088fd584 Defer tail call ret ty equality to check_tail_calls 2025-08-19 20:16:19 +00:00
许杰友 Jieyou Xu (Joe)
bd0e768fff
Rollup merge of #142079 - lcnr:opaque-types-universes, r=BoxyUwU
nll-relate: improve hr opaque types support

This should currently not be user-facing outside of diagnostics as even if we successfully relate the opaque types, we don't support opaque types with non-param arguments and also require all member regions to be equal to the arguments or `'static`. This means there's no way to end up with a placeholder in the hidden type.

r? types
2025-08-19 19:42:02 +08:00
Stuart Cook
f3f1847e40
Rollup merge of #145041 - lcnr:borrowck-limitations-error, r=BoxyUwU
rework GAT borrowck limitation error

The old one depends on the `ConstraintCategory` of the constraint which meant we did not emit this note if we had to prove the higher ranked trait bound due to e.g. normalization.

This made it annoying brittle and caused MIR borrowck errors to be order dependent, fixes the issue in https://github.com/rust-lang/rust/pull/140737#discussion_r2259592651.

r? types cc ```@amandasystems```
2025-08-19 14:18:22 +10:00
Deadbeef
c6db6f20ff comment style changes 2025-08-18 23:33:27 +08:00
lcnr
f5e43d5ee3 nll-relate: improve hr opaque types support 2025-08-18 09:09:42 +02:00
Deadbeef
e78b41703f refactor return type of suggest_ampmut into an enum 2025-08-17 01:33:49 +08:00
Deadbeef
4335405fa7 overhaul &mut suggestions in borrowck errors 2025-08-16 22:34:17 +08:00
bors
cd7cbe818e Auto merge of #142071 - lcnr:revealing-use, r=compiler-errors
`apply_member_constraints`: fix placeholder check

Checking whether the member region is *an existential region from a higher universe* is just wrong and I am pretty sure we've added that check by accident as the naming was just horribly confusing before rust-lang/rust#140466.

I've encountered this issue separately while working on rust-lang/rust#139587, but feel like it's probably easier to separately FCP this change. This allows the following code to compile
```rust
trait Proj<'a> {
    type Assoc;
}
impl<'a, 'b, F: FnOnce() -> &'b ()> Proj<'a> for F {
    type Assoc = ();
}

fn is_proj<F: for<'a> Proj<'a>>(f: F) {}
fn define<'a>() -> impl Sized + use<'a> {
    // This adds a use of `opaque::<'a>` with hidden type `&'unconstrained_b ()`.
    // 'unconstrained_b is an inference variable from a higher universe as it gets
    // created inside of the binder of `F: for<'a> Proj<'a>`. This previously
    // caused us to not apply member constraints. We now do, constraining
    // it to `'a`.
    is_proj(define::<'a>);
    &()
}

fn main() {}
```

This should not be breaking change, even in theory. Applying member constraints is incomplete in rare circumstances which means that applying them in more cases can cause spurious errors, cc rust-lang/rust#140569/rust-lang/rust#142073. However, as we always skipped these member regions in `apply_member_constraints` the skipped region is guaranteed to cause an error in `check_member_constraints` later on.
2025-08-15 18:52:12 +00:00
Jake Goulding
65d329d189 Adjust error message grammar to be less awkward 2025-08-14 12:50:07 -04:00
lcnr
5c716bdc87 add comment 2025-08-14 17:43:39 +02:00
Cameron Steffen
d4eb0947f1 Cleanup assoc parent utils 2025-08-13 09:33:09 -05:00
lcnr
a95a2ac476 rework add_placeholder_from_predicate_note 2025-08-13 14:03:26 +02:00
lcnr
d62e8578c5 also consider HR bounds 2025-08-13 14:03:25 +02:00
lcnr
4e2d420ac5 avoid duplicate error string 2025-08-13 14:03:25 +02:00
Guillaume Gomez
77d7a2c1eb
Rollup merge of #145111 - fee1-dead-contrib:push-rlvnyrztlkpq, r=jieyouxu
remove some unused private trait impls

they're neither required for completeness nor used
2025-08-11 16:19:05 +02:00
lcnr
e1e1385ce0 remove from_forall 2025-08-11 09:18:46 +02:00
Esteban Küber
74496bc4d9 review comments 2025-08-10 19:26:03 +00:00
Esteban Küber
2484e189bf Add support for method calls 2025-08-10 19:22:49 +00:00
Esteban Küber
1aa5668d20 Point at the Fn() or FnMut() bound that coerced a closure, which caused a move error
When encountering a move error involving a closure because the captured value isn't `Copy`, and the obligation comes from a bound on a type parameter that requires `Fn` or `FnMut`, we point at it and explain that an `FnOnce` wouldn't cause the move error.

```
error[E0507]: cannot move out of `foo`, a captured variable in an `Fn` closure
  --> f111.rs:15:25
   |
14 | fn do_stuff(foo: Option<Foo>) {
   |             ---  ----------- move occurs because `foo` has type `Option<Foo>`, which does not implement the `Copy` trait
   |             |
   |             captured outer variable
15 |     require_fn_trait(|| async {
   |                      -- ^^^^^ `foo` is moved here
   |                      |
   |                      captured by this `Fn` closure
16 |         if foo.map_or(false, |f| f.foo()) {
   |            --- variable moved due to use in coroutine
   |
help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once
  --> f111.rs:12:53
   |
12 | fn require_fn_trait<F: Future<Output = ()>>(_: impl Fn() -> F) {}
   |                                                     ^^^^^^^^^
help: consider cloning the value if the performance cost is acceptable
   |
16 |         if foo.clone().map_or(false, |f| f.foo()) {
   |               ++++++++
```
2025-08-10 19:22:49 +00:00
Stuart Cook
934cb10f1b
Rollup merge of #145191 - dianne:fix-borrow-suggestion-args, r=compiler-errors
`suggest_borrow_generic_arg`: use the correct generic args

The suggestion now gets calls' generic arguments from the callee's type to handle cases where the callee isn't an identifier expression. Fixes rust-lang/rust#145164.
2025-08-10 19:45:56 +10:00
Stuart Cook
e5b98a9c21
Rollup merge of #143093 - lqd:polonius-pre-alpha, r=jackh726
Simplify polonius location-sensitive analysis

This PR reworks the location-sensitive analysis into what we think is a worthwhile subset of the datalog analysis. A sort of polonius alpha analysis that handles NLL problem case 3 and more, but is still using the faster "reachability as an approximation of liveness", as well as the same loans-in-scope computation as NLLs -- and thus doesn't handle full flow-sensitivity like the datalog implementation.

In the last few months, we've identified this subset as being actionable:
- we believe we can make a stabilizable version of this analysis
- it is an improvement over the status quo
- it can also be modeled in a-mir-formality, or some other formalism, for assurances about soundness, and I believe ````````@nikomatsakis```````` is interested in looking into this during H2.
- and we've identified the areas of work we wish to explore later to gradually expand the supported cases: the differences between reachability and liveness, support of kills, and considerations of time-traveling, for example.

The approach in this PR is to try less to have the graph only represent live paths, by checking whether we reach a live region during traversal and recording the loan as live there, instead of equating traversal with liveness like today because it has subtleties with the typeck edges in statements (that could forward loans to the successor point without ensuring their liveness). We can then also simplify these typeck stmt edges. And we also can simplify traversal by removing looking at kills, because that's enough to handle a bunch of NLL problem 3 cases -- and we can gradually support them more and more in traversal in the future, to reduce the approximation of liveness.

There's still some in-progress pieces of work w/r/t opaque types that I'm expecting [lcnr's opaque types rework](https://github.com/rust-lang/rust/pull/139587), and [amanda's SCCs rework](https://github.com/rust-lang/rust/pull/130227) to handle. That didn't seem to show up in tests until I rebased today (and shows lack of test coverage once again) when https://github.com/rust-lang/rust/pull/142255 introduced a couple of test failures with the new captures rules from edition 2024. It's not unexpected since we know more work is needed with member constraints (and we're not even using SCCs in this prototype yet)

I'll look into these anyways, both for future work, and checking how these other 2 PRs would change things.

---

I'm not sure the following means a lot until we have some formalism in-place, but:
- I've changed the polonius compare-mode to use this analysis: the tests pass with it, except 2 cases with minor diagnostics differences, and the 2 edition 2024 opaque types one I mentioned above and need to investigate
- things that are expected to work still do work: it bootstraps, can run our rustc-perf benchmarks (and the results are not even that bad), and a crater run didn't find any regressions (forgetting that crater currently fails to test around a quarter of all crates 👼)
- I've added tests with improvements, like the NLL problem case 3 and others, as well as some that behave the same as NLLs today and are thus worse than the datalog implementation

r? ````````@jackh726````````

(no rush I know you're deep in phd work and "implmentating" the new trait solver for r-a :p <3)

This also fixes rust-lang/rust#135646, a diagnostics ICE from the previous implementation.
2025-08-10 19:45:46 +10:00
dianne
a70a312f17 suggest_borrow_generic_arg: use the correct generic args 2025-08-09 18:31:35 -07:00
Stuart Cook
9d989bf1cf
Rollup merge of #145115 - lcnr:less-borrowck-tainting, r=compiler-errors
defer opaque type errors, generally greatly reduce tainting

fixes the test for rust-lang/rust#135528, does not actually fix that issue properly.

This is useful as it causes the migration to rust-lang/rust#139587 to be a lot easier.
2025-08-09 13:58:53 +10:00
Stuart Cook
35f2fb9453
Rollup merge of #144988 - amandasystems:more-detailed-region-graph, r=lcnr
Add annotations to the graphviz region graph on region origins

This adds
- `(ex<'e>)` for regions whose origin is existential, with name if one exists,
- `(for<'p>)` for regions whose origin is a placeholder, with name if one exists

For any region whose name we don't know, use `'_`.

This has helped _my_ debugging and it doesn't create too bad clutter, I feel.

The change  ~~is~~was ridiculously small, but I turned it into a separate PR so we can bikeshed the format.

The following snippet:
```rust
struct Co<'a>(&'a ());
struct Contra<'a>(fn(&'a ()));

// `exists<'e> forall<'p> 'p: 'e` -> ERROR
fn p_outlives_e(
    x: for<'e> fn(for<'p> fn(fn(fn(Contra<'e>, Co<'p>)))),
) -> fn(fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) {
    x
```

Gives this graph:
![new-naming](https://github.com/user-attachments/assets/f2c8f17c-d29b-4d42-9da7-4b8e520e76a6)
2025-08-09 13:58:45 +10:00
lcnr
4eee55691a borrowck: defer opaque type errors 2025-08-08 19:24:53 +02:00
lcnr
8b95291cd4 borrowck: move error tainting earlier 2025-08-08 19:16:03 +02:00
Deadbeef
57dc64ea32 remove some unused private trait impls 2025-08-09 00:02:11 +08:00
Rémy Rakic
d4bbd681bb turn expensive assert into debug assertion 2025-08-08 15:14:51 +00:00
Rémy Rakic
a5adde8eaa simplify polonius=next
Remove incomplete handling of kills during traversal for loan liveness
to get to a simpler and actionable prototype.

This handles the cases, on sufficiently simple examples, that were
deferred from NLLs (NLL problem case 3, lending iterators), and is still
a good step to put in people's hands without needing to wait for another
full implementation. This is a practical cut in scope, but it also
shows where are the areas of improvement, that we will explore in the
future.
2025-08-08 15:14:17 +00:00
lcnr
cde14e65bf apply_member_constraints: fix placeholder check 2025-08-08 14:32:35 +02:00
lcnr
1c428ec987 move type_check out of compute_regions 2025-08-07 14:04:59 +02:00
Guillaume Gomez
65479f7353
Rollup merge of #144917 - compiler-errors:tail-call-linked-lifetimes, r=lcnr
Enforce tail call type is related to body return type in borrowck

Like all call terminators, tail call terminators instantiate the binder of the callee signature with region variables and equate the arg operand types with that signature's args to ensure that the call is valid.

However, unlike normal call terminators, we were forgetting to also relate the return type of the call terminator to anything. In the case of tail call terminators, the correct thing is to relate it to the return type of the caller function (or in other words, the return local `_0`).

This meant that if the caller's return type had some lifetime constraint, then that constraint wouldn't flow through the signature and affect the args.

This is what's happening in the example test I committed:

```rust
fn link(x: &str) -> &'static str {
    become passthrough(x);
}

fn passthrough<T>(t: T) -> T { t }

fn main() {
    let x = String::from("hello, world");
    let s = link(&x);
    drop(x);
    println!("{s}");
}
```

Specifically, the type `x` is `'?0 str`, where `'?0` is some *universal* arg. The type of `passthrough` is `fn(&'?1 str) -> &'?1 str`. Equating the args sets `'?0 = '?1`. However, we need to also equate the return type `&'?1 str` to `&'static str` so that we eventually require that `'?0 = 'static`, which is a borrowck error!

-----

Look at the first commit for the functional change, and the second commit is just a refactor because we don't need to pass `Option<BasicBlock>` to `check_call_dest`, but just whether or not the terminator is expected to be diverging (i.e. if the return type is `!`).

Fixes rust-lang/rust#144916
2025-08-06 21:29:29 +02:00
Amanda Stjerna
648e3fc393 Track names of existentials 2025-08-06 16:58:42 +02:00
Amanda Stjerna
61e8869ed9 Proposed format 2025-08-06 16:35:20 +02:00
Amanda Stjerna
bcefc2ee97 Add annotations to the graphviz region graph on region origins
This adds
- (ex) for regions whose origin is existential,
- (p) for regoins whose origin is a placeholder, and
- (p for <name>) if the originating placeholder is named.

This has helped _my_ debugging and it doesn't create too bad clutter, I feel.

The change is ridiculously small, but I turned it into a separate PR so we can bikeshed the format.
2025-08-06 11:12:51 +02:00