Commit Graph

3681 Commits

Author SHA1 Message Date
aerooneqq c2383b53a2 Don't propagate synthetic params, remove lifetime hacks 2026-03-25 13:04:03 +03:00
bors 362211dc29 Auto merge of #154326 - JonathanBrouwer:rollup-MflIdQW, r=JonathanBrouwer
Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#152710 (Unalign `PackedFingerprint` on all hosts, not just x86 and x86-64)
 - rust-lang/rust#153874 (constify const Fn*: Destruct)
 - rust-lang/rust#154097 (improve validation error messages: show surrounding type)
 - rust-lang/rust#154277 (use `minicore` more in testing inline assembly)
 - rust-lang/rust#154293 (Use verbose span suggestion for type const)
2026-03-24 18:37:19 +00:00
Jonathan Brouwer 1cfbc509e6 Rollup merge of #154142 - aerooneqq:dont-create-ast-generics-2, r=petrochenkov
Delegation: eliminate usage of AST from generics creation

This PR eliminates all interaction with AST during creation of generics, then it supports proper const param types propagation. Fixes rust-lang/rust#153433. Fixes rust-lang/rust#153499. Part of rust-lang/rust#118212.

r? @petrochenkov
2026-03-24 16:22:49 +01:00
Redddy e03983878f Use verbose span suggestion for type const 2026-03-24 15:02:10 +00:00
aerooneqq 1d325ce436 Eliminate usage of AST from generics creation 2026-03-24 14:16:36 +03:00
bors f66622c7ec Auto merge of #152931 - khyperia:always-check-constarghastype, r=BoxyUwU
Always check `ConstArgHasType` even when otherwise ignoring



fixes https://github.com/rust-lang/rust/issues/149774

helping @BoxyUwU finish up https://github.com/rust-lang/rust/pull/150322, this is a simple tweak/finishing-up of that PR.

this is a breaking change that crater detected has some issues with in Boxy's PR, and hence needs a t-types FCP. I can go and help fix those crates if/once the break is signed off on.
2026-03-23 19:06:58 +00:00
Jonathan Brouwer 7d43ebc519 Rollup merge of #153312 - b-naber:namespaced-crate-names-pt1, r=petrochenkov
Packages as namespaces part 1

Part 1 of https://github.com/rust-lang/rust/pull/152299

r? @petrochenkov
2026-03-23 12:14:52 +01:00
bors 562dee4820 Auto merge of #154122 - Zalathar:no-anon, r=nnethercote
Remove the `anon` query modifier



Prior experiments:
- https://github.com/rust-lang/rust/pull/152268
- https://github.com/rust-lang/rust/pull/153996

[Zulip thread: *Removing the `anon` query modifier*](https://rust-lang.zulipchat.com/#narrow/channel/582699-t-compiler.2Fquery-system/topic/Removing.20the.20.60anon.60.20query.20modifier/with/580760962)

---

There are currently three queries that use the `anon` modifier:
- `check_representability`
- `check_representability_adt_ty`
- `erase_and_anonymize_regions_ty`

It seems that none of them are using `anon` in an essential way.

According to comments and tests, the *representability* queries mainly care about not being eligible for forcing (despite having a recoverable key type), so that if a cycle does occur then the entire cycle will be on the query stack. Replacing `anon` with a new `no_force` modifier gives a modest perf improvement.

The `erase_and_anonymize_regions_ty` query appears to be using `anon` to reduce the dep-graph overhead of a query that is expected to not call any other queries (and thus have no dependencies). Replacing `anon` with either `no_hash` or nothing appears to give only a very small perf hit on `cargo` benchmarks, which is justified by the fact that it lets us remove a lot of machinery for anonymous queries.

We still need to retain some of the machinery for anonymous *tasks*, because the non-query task `DepKind::TraitSelect` still uses it.

---

I have some ideas for a follow-up that will reduce dep-graph overhead by replacing *all* zero-dependency nodes with a singleton node, but I want to keep that separate in case it causes unexpected issues and needs to be bisected or reverted.
2026-03-21 21:53:47 +00:00
b-naber e844c24122 resolve namespaced crates with open modules 2026-03-21 12:38:17 +00:00
Zalathar 70f3e09225 Always call check_representability with tcx.ensure_ok()
This was previously not possible because `check_representability` was `anon`.
2026-03-21 14:22:10 +11:00
Jonathan Brouwer edf808b524 Rollup merge of #154154 - estebank:issue-134087, r=mati865
Emit fewer errors for incorrect rtn and `=` -> `:` typos in bindings

Make all existing `:` -> `=` typo suggestions verbose and tweak the suggested code.

Stash parse errors when pasing rtn that doesn't use `(..)`.

Emit single error on `Foo::bar(qux)` that looks like rtn in incorrect position and suggest `Foo::bar(..)`.
```
error: return type notation not allowed in this position yet
  --> $DIR/let-binding-init-expr-as-ty.rs:18:10
   |
LL | struct K(S::new(()));
   |          ^^^^^^^^^^
   |
help: furthermore, argument types not allowed with return type notation
   |
LL - struct K(S::new(()));
LL + struct K(S::new(..));
   |
```
On incorrect rtn in let binding type for an existing inherent associated function, suggest `:` -> `=` to turn the "type" into a call expression. (Fix rust-lang/rust#134087)
```
error: expected type, found associated function call
  --> $DIR/let-binding-init-expr-as-ty.rs:29:12
   |
LL |     let x: S::new(());
   |            ^^^^^^^^^^
   |
help: use `=` if you meant to assign
   |
LL -     let x: S::new(());
LL +     let x = S::new(());
   |
```
2026-03-21 00:42:46 +01:00
Esteban Küber d48e699b6c Emit fewer errors for incorrect rtn and = -> : typos in bindings
Stash parse errors when pasing rtn that doesn't use `(..)`.
Emit single error on `Foo::bar(qux)` that looks like rtn in incorrect position and suggest `Foo::bar(..)`.
```
error: return type notation not allowed in this position yet
  --> $DIR/let-binding-init-expr-as-ty.rs:18:10
   |
LL | struct K(S::new(()));
   |          ^^^^^^^^^^
   |
help: furthermore, argument types not allowed with return type notation
   |
LL - struct K(S::new(()));
LL + struct K(S::new(..));
   |
```
On incorrect rtn in let binding type for an existing inherent associated function, suggest `:` -> `=` to turn the "type" into a call expression.
```
error: expected type, found associated function call
  --> $DIR/let-binding-init-expr-as-ty.rs:29:12
   |
LL |     let x: S::new(());
   |            ^^^^^^^^^^
   |
help: use `=` if you meant to assign
   |
LL -     let x: S::new(());
LL +     let x = S::new(());
   |
```
2026-03-20 19:33:05 +00:00
Jonathan Brouwer a3898aaeb3 Rollup merge of #153557 - Human9000-bit:issue-153525, r=BoxyUwU
fix inference variables leaking into HIR const literal lowering logic

Inference variables could leak into further const lowering logic

It ICEs when query system tries to cache `lit_to_const()` after its execution and panics, because inference variables are not hashable for some reason

Fixes rust-lang/rust#153524
Fixes rust-lang/rust#153525
2026-03-19 13:42:35 +01:00
khyperia e9c273e377 Always check ConstArgHasType even when otherwise ignoring 2026-03-18 11:48:09 +01:00
human9000 5113488163 Improve ty::Infer handling during const literal lowering
Co-authored-by: BoxyUwU <rust@boxyuwu.dev>
2026-03-17 21:02:09 +05:00
human9000 11810b8dd9 fix inference variables leaking into HIR const lowering logic 2026-03-17 21:02:09 +05:00
Stuart Cook 1c3429f136 Rollup merge of #153738 - fmease:dyn-ace-gingerly-care, r=BoxyUwU
Don't look for non-type-level assoc consts when checking trait object types

On main, when looking for assoc items that weren't specified in a given trait object type (via binding), we comb through all (eligible) assoc consts whether type-level or not even though you're not allowed to bind non-type-level assoc consts.

That's usually fine because traits containing (eligible) non-type-level assoc consts are dyn incompatible, so the trait object type is ~already considered ill-formed. Therefore, in PR rust-lang/rust#150843, I saved myself the extra effort, esp. since back then it was more annoying to check if the const item was declared type-level.

<sub>(More concretely: In bodies, we check for all dyn compatibility violations when lowering the trait object type, so we will bail out early with an error; in contrast, item signatures / non-bodies get wfchecked (`WellFormed` obligation) after lowering which includes dyn compatiblity checking (`DynCompatible` obligation); however to reduce the amount of diags, during lowering if there are any unspecified assoc items, we'll check them for dyn compatibility and bail out early if any of them tests negative.)</sub>

Now, we obviously don't wfcheck the defsite of (eager) type aliases which breaks the assumption that such trait object types get rejected. This led to the regression found in rust-lang/rust#153731: The ill-formed trait object type doesn't get rejected (as is expected) but we now require the single (non-type-level) assoc const to be bound in the dyn-Trait which we didn't do before. The actual error talks about dyn incompatibility due to the aforementioned extra check that's usually there to contain the number of diags.

Fixes [after beta backport] rust-lang/rust#153731.
2026-03-17 15:53:11 +11:00
León Orell Valerian Liehr f8bce56b39 Don't look for non-type-level assoc consts when checking trait object types 2026-03-17 01:52:28 +01:00
Ralf Jung c7220f423b rename min/maxnum intrinsics to min/maximum_number and fix their LLVM lowering 2026-03-15 14:53:00 +01:00
Stuart Cook 4625821025 Rollup merge of #153818 - oli-obk:const-closures, r=fee1-dead
Reimplement const closures

Tracking issue: rust-lang/rust#106003

Best reviewed commit-by-commit

The old solver can't handle `for<'a> |x: &'a()| ()` closures in const contexts, but that feature is unstable itself, so we can just leave it to the next solver to handle.

We need a lot more tests, we're testing the bare minimum of success and failure paths right now.

r? @fee1-dead
2026-03-14 17:30:24 +11:00
Oli Scherer 1867653c81 Allow calling const closures in const items 2026-03-13 20:29:43 +00:00
Jonathan Brouwer 3d486d2ffc Rollup merge of #153705 - aerooneqq:delegation-impl-trait-generics, r=petrochenkov
Always generate generics in delegation that match trait in trait impl scenario

After rust-lang/rust#151864 there is a change in delegation code generation in `trait impl` cases: after rust-lang/rust#151864 we started to look at user-specified args and generate functions, whose generics may not match the signature of the function that is defined in trait. Such handling of delegation from trait impl is not correct, as the generated function should always have the same generics as its signature function in trait.

This addresses the "Fix generic params generation in trait impl case" future work from rust-lang/rust#151864

r? @petrochenkov
2026-03-12 15:52:10 +01:00
aerooneqq d87d7b94f8 Always generate generics that match trait in trait impl scenario 2026-03-12 17:25:05 +03:00
Jonathan Brouwer 77134bd3e2 Rollup merge of #153611 - RalfJung:interp-error-strings, r=oli-obk
interpret: go back to regular string interpolation for error messages

Using the translatable diagnostic infrastructure adds a whole lot of boilerplate which isn't actually useful for const-eval errors, so let's get rid of it. This effectively reverts https://github.com/rust-lang/rust/pull/111677. That PR effectively added 1000 lines and this PR only removes around 600 -- the difference is caused by (a) keeping some of the types around for validation, where we can use them to share error strings and to trigger the extra help for pointer byte shenanigans during CTFE, and (b) this not being a full revert of rust-lang/rust#111677; I am not touching diagnostics outside the interpreter such as all the const-checking code which also got converted to fluent in the same PR.

The last commit does something similar for `LayoutError`, which also helps deduplicate a bunch of error strings. I can make that into a separate PR if you prefer.

r? @oli-obk
Fixes https://github.com/rust-lang/rust/issues/113117
Fixes https://github.com/rust-lang/rust/issues/116764
Fixes https://github.com/rust-lang/rust/issues/112618
2026-03-11 22:05:44 +01:00
Jonathan Brouwer 4e64a8b568 Rollup merge of #153581 - nnethercote:rm-cycle_stash, r=oli-obk
Simplify `type_of_opaque`.

There is a bunch of complexity supporting the "cannot check whether the hidden type of opaque type satisfies auto traits" error that shows up in `tests/ui/impl-trait/auto-trait-leak.rs`. This is an obscure error that shows up in a single test. If we are willing to downgrade that error message to a cycle error, we can do the following.

- Simplify the `type_of_opaque` return value.
- Remove the `cycle_stash` query modifier.
- Remove the `CyclePlaceholder` type.
- Remove the `SelectionError::OpaqueTypeAutoTraitLeakageUnknown` variant.
- Remove a `FromCycleError` impl.
- Remove `report_opaque_type_auto_trait_leakage`.
- Remove the `StashKey::Cycle` variant.
- Remove the `CycleErrorHandling::Stash` variant.

That's a lot! I think this is a worthwhile trade-off.

r? @oli-obk
2026-03-11 22:05:43 +01:00
Jonathan Brouwer 627a150072 Rollup merge of #153571 - TaKO8Ki:eii-ice-153502, r=jdonszelmann
Avoid ICE when an EII declaration conflicts with a constructor

Fixes rust-lang/rust#153502

When an `#[eii]` declaration conflicts with a tuple-struct constructor of the same name, error recovery can resolve
the EII target to the constructor instead of the generated foreign item. `compare_eii_function_types` then assumes
that target is a foreign function and later ICEs while building diagnostics.

This pull request adds an early guard in `compare_eii_function_types` to skip EII signature comparison unless the resolved target is actually a foreign function.
2026-03-11 22:05:43 +01:00
GokhanKabar 86880c90c2 Fix ICE in fn_delegation when child segment resolves to a trait
When a delegation path like `reuse Trait::<> as bar4` has a child segment
that resolves to a trait instead of a function, the compiler would ICE
because `lower_generic_args_of_path` asserts that `self_ty` is `Some`
when `has_self` is true and `parent` is `None`.

Fix this by filtering out non-function child segments early using
`.filter()` in the method chain, so that when the child segment resolves
to a trait (error recovery for E0423), we skip generic args computation
entirely and return an empty list via `unwrap_or_default()`.

Also make `get_segment` return `Option` by using `opt_def_id()` instead
of `def_id()` to gracefully handle unresolved segments.
2026-03-11 16:40:54 +01:00
Ralf Jung fe1f92af4b de-duplicate LayoutError formatting 2026-03-11 13:55:03 +01:00
Nicholas Nethercote 3399ed3c9a Simplify type_of_opaque.
There is a bunch of complexity supporting the "cannot check whether the
hidden type of opaque type satisfies auto traits" error that shows up in
`tests/ui/impl-trait/auto-trait-leak.rs`. This is an obscure error that
shows up in a single test. If we are willing to downgrade that error
message to a cycle error, we can do the following.

- Simplify the `type_of_opaque` return value.
- Remove the `cycle_stash` query modifier.
- Remove the `CyclePlaceholder` type.
- Remove the `SelectionError::OpaqueTypeAutoTraitLeakageUnknown`
  variant.
- Remove a `FromCycleError` impl.
- Remove `report_opaque_type_auto_trait_leakage`.
- Remove the `StashKey::Cycle` variant.
- Remove the `CycleErrorHandling::Stash` variant.

That's a lot! I think this is a worthwhile trade-off.
2026-03-11 21:54:42 +11:00
Takayuki Maeda be78a0d629 avoid ICE when EII target resolves to a constructor
remove span_delayed_bug
2026-03-11 19:04:46 +09:00
bors b2fabe39bd Auto merge of #153673 - JonathanBrouwer:rollup-cGOKonI, r=JonathanBrouwer
Rollup of 7 pull requests

Successful merges:

 - rust-lang/rust#153560 (Introduce granular tidy_ctx's check in extra_checks)
 - rust-lang/rust#153666 (Add a regression test for rust-lang/rust#153599)
 - rust-lang/rust#153493 (Remove `FromCycleError` trait)
 - rust-lang/rust#153549 (tests/ui/binop: add annotations for reference rules)
 - rust-lang/rust#153641 (Move `Spanned`.)
 - rust-lang/rust#153663 (Remove `TyCtxt::node_lint` method and `rustc_middle::lint_level` function)
 - rust-lang/rust#153664 (Add test for rust-lang/rust#109804)
2026-03-11 05:12:10 +00:00
Nicholas Nethercote c12ab08c14 Move Spanned.
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.
2026-03-11 06:25:23 +11:00
David Wood f760fdd8dc hir_analysis: check number of vectors in tuples
Introduces a new check in `rustc_hir_analysis` enforcing that tuples of
scalable vectors should only up to eight vectors.
2026-03-10 11:52:15 +00:00
Zalathar 985b41d387 Remove the rustc_data_structures::assert_matches! re-exports 2026-03-08 22:02:23 +11:00
bors c7b206bba4 Auto merge of #153383 - nnethercote:overhaul-ensure_ok, r=Zalathar
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
2026-03-08 07:03:35 +00:00
Nicholas Nethercote d4503b017e Overhaul ensure_ok.
`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.
2026-03-08 09:39:39 +11:00
Josh Stone eb093cfd5d Reformat with the new stage0 2026-03-07 10:42:02 -08:00
Josh Stone 32bae1353e Update cfg(bootstrap) 2026-03-07 10:42:02 -08:00
Jonathan Brouwer 69dc318464 Rollup merge of #153452 - GuillaumeGomez:migrate-diag, r=JonathanBrouwer
Cleanup unused diagnostic emission methods

Part of https://github.com/rust-lang/rust/issues/153099.

To remove `lint_level`, we need to remove all functions calling it. One of them is `TyCtxt::node_span_lint`, so removing it.

r? @JonathanBrouwer
2026-03-06 18:49:51 +01:00
Yuki Okushi 1190845a3d Do not emit ConstEvaluatable goals if type-const 2026-03-06 21:51:31 +09:00
Guillaume Gomez e1ee66935e Remove TyCtxt::node_span_lint usage from rustc_hir_analysis 2026-03-05 23:53:54 +01:00
aerooneqq 169dd72d47 Fix obtaining def_id from unresolved segment 2026-03-05 10:38:56 +03:00
Jonathan Brouwer 23e27344e9 Rollup merge of #153300 - fmease:test-attrs-tweaks, r=JonathanBrouwer
Tweak some of our internal `#[rustc_*]` TEST attributes

I think I might be the one who's used the internal TEST attrs `#[rustc_{dump_predicates,object_lifetime_default,outlives,variance}]` the most in recent times, I might even be the only one. As such I've noticed some recent-ish issues that haven't been fixed so far and which keep bothering me. Moreover I have a longstanding urge to rename several of these attributes which I couldn't contain anymore.

[`#[rustc_*]` TEST attributes](https://rustc-dev-guide.rust-lang.org/compiler-debugging.html#rustc_-test-attributes) are internal attributes that basically allow you to dump the output of specific queries for use in UI tests or for debugging purposes.

1. When some of these attributes were ported over to the new parsing API, their targets were unnecessarily restricted. I've kept encountering these incorrect "attribute cannot be used" errors all the while HIR analysis happily & correctly dumped the requested data below it. I've now relaxed their targets.
2. Since we now have target checking for the internal attributes I figured that it's unhelpful if we still intentionally crashed on invalid targets, so I've got rid of that.
3. I've always been annoyed that most of these (very old) attributes don't contain the word `dump` in their name (rendering their purpose non-obvious) and that some of their names diverge quite a bit from the corresponding query name. I've now rectified that. The new names take longer to type but it's still absolutely acceptable imo.

---

I haven't renamed all of the TEST attributes to follow the `rustc_dump_` scheme since that's quite tedious. If it's okay with you I'd like to postpone that (e.g., `rustc_{def_path,hidden_type…,layout,regions,symbol_name}`).

I've noticed that the parsers for TEST attrs are spread across `rustc_dump.rs`, `rustc_internal.rs` & `test_attrs.rs` which is a bit confusing. Since the new names are prefixed with `rustc_dump_` I've moved their parsers into `rustc_dump.rs` but of course they are still TEST attrs. IIRC, `test_attrs.rs` also contains non-`rustc_`-TEST attrs, so we can't just merge these two files. I guess that'll sort itself out in the future when I tackle the other internal TEST attrs.

r\? Jana || Jonathan
2026-03-04 19:30:39 +01:00
Jonathan Brouwer febe0bc218 Rollup merge of #153317 - nnethercote:abort-after-infinite-errors, r=oli-obk
Abort after `representability` errors

Doing so results in better error messages and makes the code a bit simpler. Details in individual commits.

r? @oli-obk
2026-03-04 19:30:38 +01:00
Matthias Krüger 5bd6a0c2f9 Rollup merge of #153274 - ValorZard:async-drop-multi-crate-crash, r=oli-obk
Fix async drop multi crate crash

fixes rust-lang/rust#142572
Again, I've been talking in the Zulip about this: [#wg-async > is there a way I can help with Async Drop? @ 💬](https://rust-lang.zulipchat.com/#narrow/channel/187312-wg-async/topic/is.20there.20a.20way.20I.20can.20help.20with.20Async.20Drop.3F/near/575627286)

TL;DR: This is going to be a bit of a refactor, hold your horses

Also, I might end up splitting this into two PRs, so I can first merge my elaborate_drop.rs refactor, and then my fix for the crash later, but IDK yet
2026-03-04 09:49:02 +01:00
root db6ee18fd0 Fix multi-crate crash if dependency has enabled AsyncDrop 2026-03-04 00:40:47 -08:00
Nicholas Nethercote ff3d308966 Eliminate Representability::Infinite.
This variant was a fallback value used to continue analysis after a
`Representability` error, but it's no longer needed thanks to the
previous commit. This means `Representability` can now be reduced to a
unit type that exists just so `FromCycleError` can exist for the
`representability` query. (There is potential for additional cleanups
here, but those are beyond the scope of this PR.)

This means the `representability`/`representability_adt_ty` queries no
longer have a meaningful return value, i.e. they are check-only queries.
So they now have a `check_` prefix added. And the `rtry!` macro is no
longer needed.
2026-03-04 07:02:39 +11:00
human9000 ee1d0cfbe6 MGCA: fix type error handling for array and tuple lowering logic 2026-03-03 17:08:26 +05:00
bors 1b7d722f42 Auto merge of #153331 - JonathanBrouwer:rollup-hr9XbEa, r=JonathanBrouwer
Rollup of 12 pull requests

Successful merges:

 - rust-lang/rust#152941 (prefer actual ABI-controling fields over target.abi when making ABI decisions)
 - rust-lang/rust#153227 (Don’t report missing fields in struct exprs with syntax errors.)
 - rust-lang/rust#153265 (Clarified doc comments + added tests confirming current behavior for intersperse/intersperse_with)
 - rust-lang/rust#152966 (Migrate 11 tests from tests/ui/issues to specific directories)
 - rust-lang/rust#153003 (rustdoc: make `--emit` and `--out-dir` mimic rustc)
 - rust-lang/rust#153034 (Remove unhelpful hint from trivial bound errors)
 - rust-lang/rust#153152 (Migration of LintDiagnostic - part 5)
 - rust-lang/rust#153177 (disable the ptr_fragment_in_final test on s390x)
 - rust-lang/rust#153221 (Add release notes for 1.94.0)
 - rust-lang/rust#153279 (feat: Provide an '.item_kind()' method on ItemEnum)
 - rust-lang/rust#153297 (Update the name of the Hermit operating system)
 - rust-lang/rust#153309 (Cleanup of c-variadic link test)
2026-03-03 07:00:49 +00:00
bors d3877ec332 Auto merge of #151864 - aerooneqq:delegation-generics-propagation, r=petrochenkov
Implement AST -> HIR generics propagation in delegation



This PR adds support for generics propagation during AST -> HIR lowering and is a part of rust-lang/rust#118212.

# High-level design overview

## Motivation
The task is to generate generics for delegations (i.e. in this context we assume a function that is created for `reuse` statements) during AST -> HIR lowering. Then we want to propagate those generated params to generated method call (or default call) in delegation. This will help to solve issues like the following:

```rust
mod to_reuse {
    pub fn consts<const N: i32>() -> i32 {
        N
    }
}

reuse to_reuse::consts;
//~^ ERROR  type annotations needed

// DESUGARED CURRENT:
#[attr = Inline(Hint)]
fn consts() -> _ { to_reuse::consts() }

// DESUGARED DESIRED:
#[attr = Inline(Hint)]
fn consts<const N: i32>() -> _ { to_reuse::consts::<N>() }
```

Moreover, user can specify generic args in `reuse`, we need to propagate them (works now) and inherit signature with substituted generic args:

```rust
mod to_reuse {
    pub fn foo<T>(t: T) -> i32 {
        0
    }
}

reuse to_reuse::foo::<i32>;
//~^ ERROR  mismatched types

fn main() {
    foo(123);
}

error[E0308]: mismatched types
  --> src/main.rs:24:17
   |
19 |     pub fn foo<T>(t: T) -> i32 {
   |                - found this type parameter
...
24 | reuse to_reuse::foo::<i32>;
   |                 ^^^
   |                 |
   |                 expected `i32`, found type parameter `T`
   |                 arguments to this function are incorrect
   |
   = note:        expected type `i32`
           found type parameter `T`
```
In this case we want the delegation to have signature that have one `i32` parameter (not `T` parameter).
Considering all other cases, for now we want to preserve existing behavior, which was almost fully done (at this stage there are changes in behavior of delegations with placeholders and late-bound lifetimes).

## Main approach overview
The main approach is as follows:
- We determine generic params of delegee parent (now only trait can act as a parent as delegation to inherent impls is not yet supported) and delegee function,
- Based on presence of user-specified args in `reuse` statement (i.e. `reuse Trait::<'static, i32, 123>::foo::<String>`)  we either generate delegee generic params or not. If not, then we should include user-specified generic args into the signature of delegation,
- The general order of generic params generation is as following: 
   `[DELEGEE PARENT LIFETIMES, DELEGEE LIFETIMES, DELEGEE PARENT TYPES AND CONSTS, DELEGEE TYPES AND CONSTS]`,
- There are two possible generic params orderings (they differ only in a position of `Self` generic param):
  - When Self is after lifetimes, this happens only in free to trait delegation scenario, as we need to generate implicit Self param of the delegee trait,
  - When Self is in the beginning and we should not generate Self param, this is basically all other cases if there is an implicit Self generic param in delegation parent.
- Considering propagation, we do not propagate lifetimes for child, as at AST -> HIR lowering stage we can not know whether the lifetime is late-bound or early bound, so for now we do not propagate them at all. There is one more hack with child lifetimes, for the same reason we create predicates of kind `'a: 'a` in order to preserve all lifetimes in HIR, so for now we can generate more lifetimes params then needed. This will be partially fixed in one of next pull requests.

## Implementation details

- We obtain AST generics either from AST of a current crate if delegee is local or from external crate through `generics_of` of `tcx`. Next, as we want to generate new generic params we generate new node ids for them, remove default types and then invoke already existent routine for lowering AST generic params into HIR,
- If there are user-specified args in either parent or child parts of the path, we save HIR ids of those segments and pass them to `hir_analysis` part, where user-specified args are obtained, then lowered through existing API and then used during signature and predicates inheritance,
- If there are no user-specified args then we propagate generic args that correspond to generic params during generation of delegation,
- During signature inheritance we know whether parent or child generic args were specified by the user, if so, we should merge them with generic params (i.e. cases when parent args are specified and child args are not: `reuse Trait::<String>::foo`), next we use those generic args and mapping for delegee parent and child generic params into those args in order to fold delegee signature and delegee predicates.

## Tests

New tests were developed and can be found in `ast-hir-engine` folder, those tests cover all cases of delegation with different number of lifetimes, types, consts in generic params and different user-specified args cases (parent and child, parent/child only, none). 

## Edge cases
There are some edge cases worth mentioning. 

### Free to trait delegation. 
Consider this example:
```rust
trait Trait<'a, T, const N: usize> {
    fn foo<'x: 'x, A, B>(&self) {}
}

reuse Trait::foo;
```

As we are reusing from trait and delegee has `&self` param it means that delegation must have `Self` generic param:
```rust
fn foo<'a, 'x, Self, T, const N: usize, A, B>(self) {}
```

We inherit predicates from Self implicit generic param in `Trait`, thus we can pass to delegation anything that implements this trait. Now, consider the case when user explicitly specifies parent generic args.
```rust
reuse Trait::<'static, String, 1>::foo;
```

In this case we do not need to generate parent generic params, but we still need to generate `Self` in delegation (`DelegationGenerics::SelfAndUserSpecified` variant):
```rust
fn foo<'x, Self, A, B>(self) {}
```
User-specified generic arguments should be used to replace parent generic params in delegation, so if we had param of type `T` in `foo`, during signature inheritance we should replace it with user-specified `String` type.

### impl trait delegation
When we delegate from impl trait to something, we want the delegation to have signature that matches signature in trait. For this reason we already resolve delegation not to the actual delegee but to the trait method in order to inherit its signature. That is why when processing user-specified args when the caller kind is `impl trait` (`FnKind::AssocTraitImpl`), we discard parent user-specified args and replace them with those that are specified in trait header. In future we will also discard `child_args` but we need proper error handling for this case, so it will be addressed in one of future pull requests that are approximately specified in "Nearest future work" section.

## Nearest future work (approximate future pull requests):
- Late-bound lifetimes
- `impl Trait` params in functions
- Proper propagation of parent generics when generating method call
- ~Fix diagnostics duplication during lowering of user-specified types~
- Support for recursive delegations
- Self types support `reuse <u8 as Trait<_>>::foo as generic_arguments2`
- Decide what to do with infer args `reuse Trait::<_, _>::foo::<_>`
- Proper error handling when there is a mismatch between actual and expected args (impl trait case)

r? @petrochenkov
2026-03-03 02:39:40 +00:00