Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

instantiate higher ranked goals outside of candidate selection #119820

Merged
merged 2 commits into from Apr 4, 2024

Conversation

lcnr
Copy link
Contributor

@lcnr lcnr commented Jan 10, 2024

This PR modifies evaluate to more eagerly instantiate higher-ranked goals, preventing the leak_check during candidate selection from detecting placeholder errors involving that binder.

For a general background regarding higher-ranked region solving and the leak check, see https://hackmd.io/qd9Wp03cQVy06yOLnro2Kg.

The first is something called the leak check. You can think of it as a "quick and dirty" approximation for the region check, which will come later. The leak check detects some kinds of errors early, essentially deciding between "this set of outlives constraints are guaranteed to result in an error eventually" or "this set of outlives constraints may be solvable".

The ideal future

We would like to end up with the following idealized design to handle universal binders:

fn enter_forall<'tcx, T, R>(
    forall: Binder<'tcx, T>,
    f: impl FnOnce(T) -> R,
) -> R {
    let new_universe = infcx.increment_universe_index();
    let value = instantiate_binder_with_placeholders_in(new_universe, forall);
    
    let result = f(value);
    
    eagerly_handle_higher_ranked_region_constraints_in(new_universe);
    infcx.decrement_universe_index();
    
    assert!(!result.has_placeholders_in_or_above(new_universe));
    result
}

That is, when universally instantiating a binder, anything using the placeholders has to happen inside of a limited scope (the closure f). After this closure has completed, all constraints involving placeholders are known.

We then handle any external constraints which name these placeholders. We destructure TypeOutlives constraints involving placeholders and eagerly handle any region constraints involving these placeholders. We do not return anything mentioning the placeholders created inside of this function to the caller.

Being able to eagerly handle all region constraints involving placeholders will be difficult due to complex TypeOutlives constraints, involving inference variables or alias types, and higher ranked implied bounds. The exact issues and possible solutions are out of scope of this FCP.

How does the leak check fit into this

The leak_check is an underapproximation of eagerly_handle_higher_ranked_region_constraints_in. It detects some kinds of errors involving placeholders from new_universe, but not all of them.

It only looks at region outlives constraints, ignoring TypeOutlives, and checks whether one of the following two conditions are met for placeholders in or above new_universe, in which case it results in an error:

  • '!p1: '!p2 a placeholder '!p2 outlives a different placeholder '!p1
  • '!p1: '?2 an inference variable '?2 outlives a placeholder '!p1 which it cannot name

It does not handle all higher ranked region constraints, so we still return constraints involving placeholders from new_universe which are then (re)checked by lexical_region_resolve or MIR borrowck.

As we check higher ranked constraints in the full regionck anyways, the leak_check is not soundness critical. It's current only purpose is to move some higher ranked region errors earlier, enabling it to guide type inference and trait solving. Adding additional uses of the leak_check in the future would only strengthen inference and is therefore not breaking.

Where do we use currently use the leak check

The leak_check is currently used in two places:

Coherence does not use a proper regionck, only relying on the leak_check called at the end of the implicit negative overlap check. During coherence all parameters are instantiated with inference variables, so the only possible region errors are higher-ranked. We currently also sometimes make guesses when destructuring TypeOutlives constraints which can theoretically result in incorrect errors. This could result in overlapping impls.

We also use the leak_check at the end of fn evaluation_probe. This function is used during candidate assembly for Trait goals. Most notably we use inside of evaluate_candidate during winnowing. Conceptionally, it is as if we compute each candidate in a separate enter_forall.

The current use in fn evaluation_probe is undesirable

Because we only instantiate a higher-ranked goal once inside of fn evaluation_probe, errors involving placeholders from that binder can impact selection. This results in inconsistent behavior (playground):

trait Leak<'a> {}
impl Leak<'_>      for Box<u32> {}
impl Leak<'static> for Box<u16> {}

fn impls_leak<T: for<'a> Leak<'a>>() {}

trait IndirectLeak<'a> {}
impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}

fn main() {
    // ok
    //
    // The `Box<u16>` impls fails the leak check,
    // meaning that we apply the `Box<u32>` impl.
    impls_leak::<Box<_>>();
    
    // error: type annotations needed
    //
    // While the `Box<u16>` impl would fail the leak check
    // we have already instantiated the binder while applying
    // the generic `IndirectLeak` impl, so during candidate
    // selection of `Leak` we do not detect the placeholder error.
    // Evaluation of `Box<_>: Leak<'!a>` is therefore ambiguous,
    // resulting in `for<'a> Box<_>: Leak<'a>` also being ambiguous.
    impls_indirect_leak::<Box<_>>();
}

We generally prefer where-bounds over implementations during candidate selection, both for trait goals and during normalization. However, we currently do not use the leak_check during candidate assembly in normalizing. This can result in inconsistent behavior:

trait Trait<'a> {
    type Assoc;
}
impl<'a, T> Trait<'a> for T {
    type Assoc = usize;
}

fn trait_bound<T: for<'a> Trait<'a>>() {}
fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}

// A function with a trivial where-bound which is more
// restrictive than the impl.
fn function<T: Trait<'static, Assoc = usize>>() {
    // ok
    //
    // Proving `for<'a> T: Trait<'a>` using the where-bound results
    // in a leak check failure, so we use the more general impl,
    // causing this to succeed.
    trait_bound::<T>();
    
    // error
    //
    // Proving the `Projection` goal `for<'a> T: Trait<'a, Assoc = usize>`
    // does not use the leak check when trying the where-bound, causing us
    // to prefer it over the impl, resulting in a placeholder error.
    projection_bound::<T>();
    
    // error
    //
    // Trying to normalize the type `for<'a> fn(<T as Trait<'a>>::Assoc)`
    // only gets to `<T as Trait<'a>>::Assoc` once `'a` has been already
    // instantiated, causing us to prefer the where-bound over the impl
    // resulting in a placeholder error. Even if were were to also use the
    // leak check during candidate selection for normalization, this
    // case would still not compile.
    let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
}

This is also likely to be more performant. It enables more caching in the new trait solver by simply recursively calling the canonical query after instantiating the higher-ranked goal.

It is also unclear how to add the leak check to normalization in the new solver. To handle rust-lang/trait-system-refactor-initiative#1 Projection goals are implemented via AliasRelate. This again means that we instantiate the binder before ever normalizing any alias. Even if we were to avoid this, we lose the ability to cache normalization by itself, ignoring the expected term. We cannot replace the term with an inference variable before instantiating the binder, as otherwise for<'a> T: Trait<Assoc<'a> = &'a ()> breaks. If we only replace the term after instantiating the binder, we cannot easily evaluate the goal in a separate context, as we'd then lose the information necessary for the leak check. Adding this information to the canonical input also seems non-trivial.

Proposed solution

I propose to instantiate the binder outside of candidate assembly, causing placeholders from higher-ranked goals to get ignored while selecting their candidate. This mostly1 matches the current behavior of the new solver. The impact of this change is therefore as follows:

trait Leak<'a> {}
impl Leak<'_>      for Box<u32> {}
impl Leak<'static> for Box<u16> {}

fn impls_leak<T: for<'a> Leak<'a>>() {}

trait IndirectLeak<'a> {}
impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}

fn guide_selection() {
    // ok -> ambiguous
    impls_leak::<Box<_>>();
    
    // ambiguous
    impls_indirect_leak::<Box<_>>();
}

trait Trait<'a> {
    type Assoc;
}
impl<'a, T> Trait<'a> for T {
    type Assoc = usize;
}

fn trait_bound<T: for<'a> Trait<'a>>() {}
fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}

// A function which a trivial where-bound which is more
// restrictive than the impl.
fn function<T: Trait<'static, Assoc = usize>>() {
    // ok -> error
    trait_bound::<T>();
    
    // error
    projection_bound::<T>();
    
    // error
    let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
}

This does not change the behavior if candidates have higher ranked nested goals, as in this case the leak_check causes the nested goal to result in an error (playground):

trait LeakCheckFailure<'a> {}
impl LeakCheckFailure<'static> for () {}

trait Trait<T> {}
impl Trait<u32> for () where for<'a> (): LeakCheckFailure<'a> {}
impl Trait<u16> for () {}
fn impls_trait<T: Trait<U>, U>() {}
fn main() {
    // ok
    //
    // It does not matter whether candidate assembly
    // considers the placeholders from higher-ranked goal.
    // 
    // Either `for<'a> (): LeakCheckFailure<'a>` has no 
    // applicable candidate or it has a single applicable candidate
    // when then later results in an error. This allows us to
    // infer `U` to `u16`.
    impls_trait::<(), _>()
}

Impact on existing crates

This is a breaking change. A crater run found 17 regressed crates with 7 root causes.

For a full analysis of all affected crates, see https://gist.github.com/lcnr/7c1c652f30567048ea240554a36ed95c.


I believe this breakage to be acceptable and would merge this change. I am confident that the new position of the leak check matches our idealized future and cannot envision any other consistent alternative. Where possible, I intend to open PRs fixing/avoiding the regressions before landing this PR.

I originally intended to remove the coherence_leak_check lint in the same PR. However, while I am confident in the position of the leak check, deciding on its exact behavior is left as future work, cc #112999. This PR therefore only moves the leak check while keeping the lint when relying on it in coherence.

r? @nikomatsakis

Footnotes

  1. the new solver has a separate cause of inconsistent behavior rn https://github.com/rust-lang/trait-system-refactor-initiative/issues/53#issuecomment-1914310171

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 10, 2024
@rustbot
Copy link
Collaborator

rustbot commented Jan 10, 2024

Type relation code was changed

cc @compiler-errors, @lcnr

@lcnr
Copy link
Contributor Author

lcnr commented Jan 10, 2024

@bors try @rust-timer queue

(perf and need crater for rust-lang/trait-system-refactor-initiative#34)

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Jan 10, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 10, 2024
remove the `coherence_leak_check` future compat lint

and adapt the old solver to not rely on universe errors for higher ranked goals to impact candidate selection. This matches the behavior of the new solver: rust-lang/trait-system-refactor-initiative#34

r? `@nikomatsakis`
@bors
Copy link
Contributor

bors commented Jan 10, 2024

⌛ Trying commit e49e69b with merge b69bfee...

@lcnr lcnr added the needs-fcp This change is insta-stable, so needs a completed FCP to proceed. label Jan 10, 2024
@bors
Copy link
Contributor

bors commented Jan 10, 2024

☀️ Try build successful - checks-actions
Build commit: b69bfee (b69bfeecc49bf5661cf54497638430035ff61aa4)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (b69bfee): comparison URL.

Overall result: ❌ regressions - ACTION NEEDED

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.5% [0.2%, 0.8%] 8
Regressions ❌
(secondary)
1.2% [1.2%, 1.2%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.5% [0.2%, 0.8%] 8

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
1.0% [0.6%, 1.2%] 3
Regressions ❌
(secondary)
1.7% [1.3%, 2.2%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-1.9% [-1.9%, -1.9%] 1
All ❌✅ (primary) 1.0% [0.6%, 1.2%] 3

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
6.1% [6.1%, 6.1%] 1
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.0% [-2.0%, -2.0%] 1
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 666.26s -> 666.778s (0.08%)
Artifact size: 308.39 MiB -> 308.42 MiB (0.01%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Jan 10, 2024
@lcnr
Copy link
Contributor Author

lcnr commented Jan 11, 2024

@craterbot check

@craterbot
Copy link
Collaborator

👌 Experiment pr-119820 created and queued.
🤖 Automatically detected try build b69bfee
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 11, 2024
@craterbot
Copy link
Collaborator

🚧 Experiment pr-119820 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot
Copy link
Collaborator

🎉 Experiment pr-119820 is completed!
📊 61 regressed and 5 fixed (406907 total)
📰 Open the full report.

⚠️ If you notice any spurious failure please add them to the blacklist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels Jan 15, 2024
@lcnr
Copy link
Contributor Author

lcnr commented Jan 16, 2024

looking at https://crates.io/crates/rene, I think the error pattern is the following:

trait Trait {}

impl<T: Trait> Trait for &T {}
impl Trait for u32 {}


fn hr_bound<T>() 
where
    for<'a> &'a T: Trait,
{}

fn foo<T>()
where
    T: Trait,
    for<'a> &'a &'a T: Trait,
{
    hr_bound::<&T>();
    // We get a universe error when using the `param_env` candidate
    // but are able to successfully use the impl candidate. Without
    // the leak check both candidates may apply and we prefer the
    // `param_env` candidate in winnowing.
}

fn main() {}

@lcnr
Copy link
Contributor Author

lcnr commented Jan 16, 2024

@craterbot
Copy link
Collaborator

👌 Experiment pr-119820-1 created and queued.
🤖 Automatically detected try build b69bfee
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 16, 2024
@craterbot
Copy link
Collaborator

🚧 Experiment pr-119820-1 is now running

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

lcnr and others added 2 commits April 3, 2024 22:32
this prevents higher ranked goals from guiding selection
@rustbot rustbot added A-testsuite Area: The testsuite used to check the correctness of rustc T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) labels Apr 3, 2024
@BoxyUwU
Copy link
Member

BoxyUwU commented Apr 4, 2024

r? @jackh726
@bors r=jackh726

@bors
Copy link
Contributor

bors commented Apr 4, 2024

📌 Commit f090de8 has been approved by jackh726

It is now in the queue for this repository.

@rustbot rustbot assigned jackh726 and unassigned nikomatsakis Apr 4, 2024
@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 4, 2024
@BoxyUwU
Copy link
Member

BoxyUwU commented Apr 4, 2024

@bors rollup=never

@bors
Copy link
Contributor

bors commented Apr 4, 2024

⌛ Testing commit f090de8 with merge 43f4f2a...

@bors
Copy link
Contributor

bors commented Apr 4, 2024

☀️ Test successful - checks-actions
Approved by: jackh726
Pushing 43f4f2a to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 4, 2024
@bors bors merged commit 43f4f2a into rust-lang:master Apr 4, 2024
12 checks passed
@rustbot rustbot added this to the 1.79.0 milestone Apr 4, 2024
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (43f4f2a): comparison URL.

Overall result: ❌ regressions - ACTION NEEDED

Next Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please open an issue or create a new PR that fixes the regressions, add a comment linking to the newly created issue or PR, and then add the perf-regression-triaged label to this PR.

@rustbot label: +perf-regression
cc @rust-lang/wg-compiler-performance

Instruction count

This is a highly reliable metric that was used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.6% [0.3%, 0.8%] 8
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.6% [0.3%, 0.8%] 8

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
0.6% [0.1%, 1.1%] 2
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 0.6% [0.1%, 1.1%] 2

Cycles

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-2.0% [-2.2%, -1.8%] 3
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 669.809s -> 667.94s (-0.28%)
Artifact size: 318.07 MiB -> 318.08 MiB (0.00%)

@Kobzol
Copy link
Contributor

Kobzol commented Apr 4, 2024

Expected small perf. regression.

@rustbot label: +perf-regression-triaged

@rustbot rustbot added the perf-regression-triaged The performance regression has been triaged. label Apr 4, 2024
@lcnr lcnr deleted the leak-check-2 branch April 4, 2024 09:10
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Apr 4, 2024
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 5, 2024
stabilize `-Znext-solver=coherence`

r? `@compiler-errors`

---

This PR stabilizes the use of the next generation trait solver in coherence checking by enabling `-Znext-solver=coherence` by default. More specifically its use in the *implicit negative overlap check*. The tracking issue for this is rust-lang#114862.

## Background

### The next generation trait solver

The new solver lives in [`rustc_trait_selection::solve`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_trait_selection/src/solve/mod.rs) and is intended to replace the existing *evaluate*, *fulfill*, and *project* implementation. It also has a wider impact on the rest of the type system, for example by changing our approach to handling associated types.

For a more detailed explanation of the new trait solver, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/solve/trait-solving.html). This does not stabilize the current behavior of the new trait solver, only the behavior impacting the implicit negative overlap check. There are many areas in the new solver which are not yet finalized. We are confident that their final design will not conflict with the user-facing behavior observable via coherence. More on that further down.

Please check out [the chapter](https://rustc-dev-guide.rust-lang.org/solve/significant-changes.html) summarizing the most significant changes between the existing and new implementations.

### Coherence and the implicit negative overlap check

Coherence checking detects any overlapping impls. Overlapping trait impls always error while overlapping inherent impls result in an error if they have methods with the same name. Coherence also results in an error if any other impls could exist, even if they are currently unknown. This affects impls which may get added to upstream crates in a backwards compatible way and impls from downstream crates.

Coherence failing to detect overlap is generally considered to be unsound, even if it is difficult to actually get runtime UB this way. It is quite easy to get ICEs due to bugs in coherence.

It currently consists of two checks:

The [orphan check] validates that impls do not overlap with other impls we do not know about: either because they may be defined in a sibling crate, or because an upstream crate is allowed to add it without being considered a breaking change.

The [overlap check] validates that impls do not overlap with other impls we know about. This is done as follows:
- Instantiate the generic parameters of both impls with inference variables
- Equate the `TraitRef`s of both impls. If it fails there is no overlap.
- [implicit negative]: Check whether any of the instantiated `where`-bounds of one of the impls definitely do not hold when using the constraints from the previous step. If a `where`-bound does not hold, there is no overlap.
- *explicit negative (still unstable, ignored going forward)*: Check whether the any negated `where`-bounds can be proven, e.g. a `&mut u32: Clone` bound definitely does not hold as an explicit `impl<T> !Clone for &mut T` exists.

The overlap check has to *prove that unifying the impls does not succeed*. This means that **incorrectly getting a type error during coherence is unsound** as it would allow impls to overlap: coherence has to be *complete*.

Completeness means that we never incorrectly error. This means that during coherence we must only add inference constraints if they are definitely necessary. During ordinary type checking [this does not hold](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=01d93b592bd9036ac96071cbf1d624a9), so the trait solver has to behave differently, depending on whether we're in coherence or not.

The implicit negative check only considers goals to "definitely not hold" if they could not be implemented downstream, by a sibling, or upstream in a backwards compatible way. If the goal is is "unknowable" as it may get added in another crate, we add an ambiguous candidate: [source](https://github.com/rust-lang/rust/blob/bea5bebf3defc56e5e3446b4a95c685dbb885fd3/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L858-L883).

[orphan check]: https://github.com/rust-lang/rust/blob/fd80c02c168c2dfbb82c29d2617f524d2723205b/compiler/rustc_trait_selection/src/traits/coherence.rs#L566-L579
[overlap check]: https://github.com/rust-lang/rust/blob/fd80c02c168c2dfbb82c29d2617f524d2723205b/compiler/rustc_trait_selection/src/traits/coherence.rs#L92-L98
[implicit negative]: https://github.com/rust-lang/rust/blob/fd80c02c168c2dfbb82c29d2617f524d2723205b/compiler/rustc_trait_selection/src/traits/coherence.rs#L223-L281

## Motivation

Replacing the existing solver in coherence fixes soundness bugs by removing sources of incompleteness in the type system. The new solver separately strengthens coherence, resulting in more impls being disjoint and passing the coherence check. The concrete changes will be elaborated further down. We believe the stabilization to reduce the likelihood of future bugs in coherence as the new implementation is easier to understand and reason about.

It allows us to remove the support for coherence and implicit-negative reasoning in the old solver, allowing us to remove some code and simplifying the old trait solver. We will only remove the old solver support once this stabilization has reached stable to make sure we're able to quickly revert in case any unexpected issues are detected before then.

Stabilizing the use of the next-generation trait solver expresses our confidence that its current behavior is intended and our work towards enabling its use everywhere will not require any breaking changes to the areas used by coherence checking. We are also confident that we will be able to replace the existing solver everywhere, as maintaining two separate systems adds a significant maintainance burden.

## User-facing impact and reasoning

### Breakage due to improved handling of associated types

The new solver fixes multiple issues related to associated types. As these issues caused coherence to consider more types distinct, fixing them results in more overlap errors. This is therefore a breaking change.

#### Structurally relating aliases containing bound vars

Fixes rust-lang#102048. In the existing solver relating ambiguous projections containing bound variables is structural. This is *incomplete* and allows overlapping impls. These was mostly not exploitable as the same issue also caused impls to not apply when trying to use them. The new solver defers alias-relating to a nested goal, fixing this issue:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Trait {}

trait Project {
    type Assoc<'a>;
}

impl Project for u32 {
    type Assoc<'a> = &'a u32;
}

// Eagerly normalizing `<?infer as Project>::Assoc<'a>` is ambiguous,
// so the old solver ended up structurally relating
//
//     (?infer, for<'a> fn(<?infer as Project>::Assoc<'a>))
//
// with
//
//     ((u32, fn(&'a u32)))
//
// Equating `&'a u32` with `<u32 as Project>::Assoc<'a>` failed, even
// though these types are equal modulo normalization.
impl<T: Project> Trait for (T, for<'a> fn(<T as Project>::Assoc<'a>)) {}

impl<'a> Trait for (u32, fn(&'a u32)) {}
//[next]~^ ERROR conflicting implementations of trait `Trait` for type `(u32, for<'a> fn(&'a u32))`
```

A crater run did not discover any breakage due to this change.

#### Unknowable candidates for higher ranked trait goals

This avoids an unsoundness by attempting to normalize in `trait_ref_is_knowable`: rust-lang#114061. This is a side-effect of supporting lazy normalization, as that forces us to attempt to normalize when checking whether a `TraitRef` is knowable: [source](https://github.com/rust-lang/rust/blob/47dd709bedda8127e8daec33327e0a9d0cdae845/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L754-L764).

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait IsUnit {}
impl IsUnit for () {}

pub trait WithAssoc<'a> {
    type Assoc;
}

// We considered `for<'a> <T as WithAssoc<'a>>::Assoc: IsUnit`
// to be knowable, even though the projection is ambiguous.
pub trait Trait {}
impl<T> Trait for T
where
    T: 'static,
    for<'a> T: WithAssoc<'a>,
    for<'a> <T as WithAssoc<'a>>::Assoc: IsUnit,
{
}
impl<T> Trait for Box<T> {}
//[next]~^ ERROR conflicting implementations of trait `Trait`
```
The two impls of `Trait` overlap given the following downstream crate:
```rust
use dep::*;
struct Local;
impl WithAssoc<'_> for Box<Local> {
    type Assoc = ();
}
```

There a similar coherence unsoundness caused by our handling of aliases which is fixed separately in rust-lang#117164.

### Evaluating goals to a fixpoint and applying inference constraints

In the old implementation of the implicit-negative check, each obligation is [checked separately without applying its inference constraints](https://github.com/rust-lang/rust/blob/bea5bebf3defc56e5e3446b4a95c685dbb885fd3/compiler/rustc_trait_selection/src/traits/coherence.rs#L323-L338). The new solver instead [uses a `FulfillmentCtxt`](https://github.com/rust-lang/rust/blob/bea5bebf3defc56e5e3446b4a95c685dbb885fd3/compiler/rustc_trait_selection/src/traits/coherence.rs#L315-L321) for this, which evaluates all obligations in a loop until there's no further inference progress.

This is necessary for backwards compatibility as we do not eagerly normalize with the new solver, resulting in constraints from normalization to only get applied by evaluating a separate obligation. This also allows more code to compile:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Mirror {
    type Assoc;
}
impl<T> Mirror for T {
    type Assoc = T;
}

trait Foo {}
trait Bar {}

// The self type starts out as `?0` but is constrained to `()`
// due to the where-clause below. Because `(): Bar` is known to
// not hold, we can prove the impls disjoint.
impl<T> Foo for T where (): Mirror<Assoc = T> {}
//[current]~^ ERROR conflicting implementations of trait `Foo` for type `()`
impl<T> Foo for T where T: Bar {}

fn main() {}
```
The old solver does not run nested goals to a fixpoint in evaluation. The new solver does do so, strengthening inference and improving the overlap check:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Foo {}
impl<T> Foo for (u8, T, T) {}
trait NotU8 {}
trait Bar {}
impl<T, U: NotU8> Bar for (T, T, U) {}

trait NeedsFixpoint {}
impl<T: Foo + Bar> NeedsFixpoint for T {}
impl NeedsFixpoint for (u8, u8, u8) {}

trait Overlap {}
impl<T: NeedsFixpoint> Overlap for T {}
impl<T, U: NotU8, V> Overlap for (T, U, V) {}
//[current]~^ ERROR conflicting implementations of trait `Foo`
```

### Breakage due to removal of incomplete candidate preference

Fixes rust-lang#107887. In the old solver we incompletely prefer the builtin trait object impl over user defined impls. This can break inference guidance, inferring `?x` in `dyn Trait<u32>: Trait<?x>` to `u32`, even if an explicit impl of `Trait<u64>` also exists.

This caused coherence to incorrectly allow overlapping impls, resulting in ICEs and a theoretical unsoundness. See rust-lang#107887 (comment). This compiles on stable but results in an overlap error with `-Znext-solver=coherence`:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
struct W<T: ?Sized>(*const T);

trait Trait<T: ?Sized> {
    type Assoc;
}

// This would trigger the check for overlap between automatic and custom impl.
// They actually don't overlap so an impl like this should remain possible
// forever.
//
// impl Trait<u64> for dyn Trait<u32> {}
trait Indirect {}
impl Indirect for dyn Trait<u32, Assoc = ()> {}
impl<T: Indirect + ?Sized> Trait<u64> for T {
    type Assoc = ();
}

// Incomplete impl where `dyn Trait<u32>: Trait<_>` does not hold, but
// `dyn Trait<u32>: Trait<u64>` does.
trait EvaluateHack<U: ?Sized> {}
impl<T: ?Sized, U: ?Sized> EvaluateHack<W<U>> for T
where
    T: Trait<U, Assoc = ()>, // incompletely constrains `_` to `u32`
    U: IsU64,
    T: Trait<U, Assoc = ()>, // incompletely constrains `_` to `u32`
{
}

trait IsU64 {}
impl IsU64 for u64 {}

trait Overlap<U: ?Sized> {
    type Assoc: Default;
}
impl<T: ?Sized + EvaluateHack<W<U>>, U: ?Sized> Overlap<U> for T {
    type Assoc = Box<u32>;
}
impl<U: ?Sized> Overlap<U> for dyn Trait<u32, Assoc = ()> {
//[next]~^ ERROR conflicting implementations of trait `Overlap<_>`
    type Assoc = usize;
}
```

### Considering region outlives bounds in the `leak_check`

For details on the `leak_check`, see the FCP proposal in rust-lang#119820.[^leak_check]

[^leak_check]: which should get moved to the dev-guide once that PR lands :3

In both coherence and during candidate selection, the `leak_check` relies on the region constraints added in `evaluate`. It therefore currently does not register outlives obligations: [source](https://github.com/rust-lang/rust/blob/ccb1415eac3289b5ebf64691c0190dc52e0e3d0e/compiler/rustc_trait_selection/src/traits/select/mod.rs#L792-L810). This was likely done as a performance optimization without considering its impact on the `leak_check`. This is the case as in the old solver, *evaluatation* and *fulfillment* are split, with evaluation being responsible for candidate selection and fulfillment actually registering all the constraints.

This split does not exist with the new solver. The `leak_check` can therefore eagerly detect errors caused by region outlives obligations. This improves both coherence itself and candidate selection:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait LeakErr<'a, 'b> {}
// Using this impl adds an `'b: 'a` bound which results
// in a higher-ranked region error. This bound has been
// previously ignored but is now considered.
impl<'a, 'b: 'a> LeakErr<'a, 'b> for () {}

trait NoOverlapDir<'a> {}
impl<'a, T: for<'b> LeakErr<'a, 'b>> NoOverlapDir<'a> for T {}
impl<'a> NoOverlapDir<'a> for () {}
//[current]~^ ERROR conflicting implementations of trait `NoOverlapDir<'_>`

// --------------------------------------

// necessary to avoid coherence unknowable candidates
struct W<T>(T);

trait GuidesSelection<'a, U> {}
impl<'a, T: for<'b> LeakErr<'a, 'b>> GuidesSelection<'a, W<u32>> for T {}
impl<'a, T> GuidesSelection<'a, W<u8>> for T {}

trait NotImplementedByU8 {}
trait NoOverlapInd<'a, U> {}
impl<'a, T: GuidesSelection<'a, W<U>>, U> NoOverlapInd<'a, U> for T {}
impl<'a, U: NotImplementedByU8> NoOverlapInd<'a, U> for () {}
//[current]~^ conflicting implementations of trait `NoOverlapInd<'_, _>`
```

### Removal of `fn match_fresh_trait_refs`

The old solver tries to [eagerly detect unbounded recursion](https://github.com/rust-lang/rust/blob/b14fd2359f47fb9a14bbfe55359db4bb3af11861/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1196-L1211), forcing the affected goals to be ambiguous. This check is only an approximation and has not been added to the new solver.

The check is not necessary in the new solver and it would be problematic for caching. As it depends on all goals currently on the stack, using a global cache entry would have to always make sure that doing so does not circumvent this check.

This changes some goals to error - or succeed - instead of failing with ambiguity. This allows more code to compile:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence

// Need to use this local wrapper for the impls to be fully
// knowable as unknowable candidate result in ambiguity.
struct Local<T>(T);

trait Trait<U> {}
// This impl does not hold, but is ambiguous in the old
// solver due to its overflow approximation.
impl<U> Trait<U> for Local<u32> where Local<u16>: Trait<U> {}
// This impl holds.
impl Trait<Local<()>> for Local<u8> {}

// In the old solver, `Local<?t>: Trait<Local<?u>>` is ambiguous,
// resulting in `Local<?u>: NoImpl`, also being ambiguous.
//
// In the new solver the first impl does not apply, constraining
// `?u` to `Local<()>`, causing `Local<()>: NoImpl` to error.
trait Indirect<T> {}
impl<T, U> Indirect<U> for T
where
    T: Trait<U>,
    U: NoImpl
{}

// Not implemented for `Local<()>`
trait NoImpl {}
impl NoImpl for Local<u8> {}
impl NoImpl for Local<u16> {}

// `Local<?t>: Indirect<Local<?u>>` cannot hold, so
// these impls do not overlap.
trait NoOverlap<U> {}
impl<T: Indirect<U>, U> NoOverlap<U> for T {}
impl<T, U> NoOverlap<Local<U>> for Local<T> {}
//~^ ERROR conflicting implementations of trait `NoOverlap<Local<_>>`
```

### Non-fatal overflow

The old solver immediately emits a fatal error when hitting the recursion limit. The new solver instead returns overflow. This both allows more code to compile and is results in performance and potential future compatability issues.

Non-fatal overflow is generally desirable. With fatal overflow, changing the order in which we evaluate nested goals easily causes breakage if we have goal which errors and one which overflows. It is also required to prevent breakage due to the removal of `fn match_fresh_trait_refs`, e.g. [in `typenum`](rust-lang/trait-system-refactor-initiative#73).

#### Enabling more code to compile

In the below example, the old solver first tried to prove an overflowing goal, resulting in a fatal error. The new solver instead returns ambiguity due to overflow for that goal, causing the implicit negative overlap check to succeed as `Box<u32>: NotImplemented` does not hold.
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
//[current] ERROR overflow evaluating the requirement

trait Indirect<T> {}
impl<T: Overflow<()>> Indirect<T> for () {}

trait Overflow<U> {}
impl<T, U> Overflow<U> for Box<T>
where
    U: Indirect<Box<Box<T>>>,
{}

trait NotImplemented {}

trait Trait<U> {}
impl<T, U> Trait<U> for T
where
    // T: NotImplemented, // causes old solver to succeed
    U: Indirect<T>,
    T: NotImplemented,
{}

impl Trait<()> for Box<u32> {}
```

#### Avoiding hangs with non-fatal overflow

Simply returning ambiguity when reaching the recursion limit can very easily result in hangs, e.g.
```rust
trait Recur {}
impl<T, U> Recur for ((T, U), (U, T))
where
    (T, U): Recur,
    (U, T): Recur,
{}

trait NotImplemented {}
impl<T: NotImplemented> Recur for T {}
```
This can happen quite frequently as it's easy to have exponential blowup due to multiple nested goals at each step. As the trait solver is depth-first, this immediately caused a fatal overflow error in the old solver. In the new solver we have to handle the whole proof tree instead, which can very easily hang.

To avoid this we restrict the recursion depth after hitting the recursion limit for the first time. We also **ignore all inference constraints from goals resulting in overflow**. This is mostly backwards compatible as any overflow in the old solver resulted in a fatal error.

### sidenote about normalization

We return ambiguous nested goals of `NormalizesTo` goals to the caller and ignore their impact when computing the `Certainty` of the current goal. See the [normalization chapter](https://rustc-dev-guide.rust-lang.org/solve/normalization.html) for more details.This means we apply constraints resulting from other nested goals and from equating the impl header when normalizing, even if a nested goal results in overflow. This is necessary to avoid breaking the following example:
```rust
trait Trait {
    type Assoc;
}

struct W<T: ?Sized>(*mut T);
impl<T: ?Sized> Trait for W<W<T>>
where
    W<T>: Trait,
{
    type Assoc = ();
}

// `W<?t>: Trait<Assoc = u32>` does not hold as
// `Assoc` gets normalized to `()`. However, proving
// the where-bounds of the impl results in overflow.
//
// For this to continue to compile we must not discard
// constraints from normalizing associated types.
trait NoOverlap {}
impl<T: Trait<Assoc = u32>> NoOverlap for T {}
impl<T: ?Sized> NoOverlap for W<T> {}
```

#### Future compatability concerns

Non-fatal overflow results in some unfortunate future compatability concerns. Changing the approach to avoid more hangs by more strongly penalizing overflow can cause breakage as we either drop constraints or ignore candidates necessary to successfully compile. Weakening the overflow penalities instead allows more code to compile and strengthens inference while potentially causing more code to hang.

While the current approach is not perfect, we believe it to be good enough. We believe it to apply the necessary inference constraints to avoid breakage and expect there to not be any desirable patterns broken by our current penalities. Similarly we believe the current constraints to avoid most accidental hangs. Ignoring constraints of overflowing goals is especially useful, as it may allow major future optimizations to our overflow handling. See [this summary](https://hackmd.io/ATf4hN0NRY-w2LIVgeFsVg) and the linked documents in case you want to know more.

### changes to performance

In general, trait solving during coherence checking is not significant for performance. Enabling the next-generation trait solver in coherence does not impact our compile time benchmarks. We are still unable to compile the benchmark suite when fully enabling the new trait solver.

There are rare cases where the new solver has significantly worse performance due to non-fatal overflow, its reliance on fixpoint algorithms and the removal of the `fn match_fresh_trait_refs` approximation. We encountered such issues in [`typenum`](https://crates.io/crates/typenum) and believe it should be [pretty much as bad as it can get](rust-lang/trait-system-refactor-initiative#73).

Due to an improved structure and far better caching, we believe that there is a lot of room for improvement and that the new solver will outperform the existing implementation in nearly all cases, sometimes significantly. We have not yet spent any time micro-optimizing the implementation and have many unimplemented major improvements, such as fast-paths for trivial goals.

TODO: get some rough results here and put them in a table

### Unsupported unstable features

The new solver currently does not support all unstable features, most notably `#![feature(generic_const_exprs)]`, `#![feature(associated_const_equality)]` and `#![feature(adt_const_params)]` are not yet fully supported in the new solver. We are confident that supporting them is possible, but did not consider this to be a priority. This stabilization introduces new ICE when using these features in impl headers.

## This does not stabilize the whole solver

While this stabilizes the use of the new solver in coherence checking, there are many parts of the solver which will remain fully unstable. We may still adapt these areas while working towards stabilizing the new solver everywhere. We are confident that we are able to do so without negatively impacting coherence.

### goals with a non-empty `ParamEnv`

Coherence always uses an empty environment. We therefore do not depend on the behavior of `AliasBound` and `ParamEnv` candidates. We only stabilizes the behavior of user-defined and builtin implementations of traits. There are still many open questions there.

### opaque types in the defining scope

The handling of opaque types - `impl Trait` - in both the new and old solver is still not fully figured out. Luckily this can be ignored for now. While opaque types are reachable during coherence checking by using `impl_trait_in_associated_types`, the behavior during coherence is separate and self-contained. The old and new solver fully agree here.

### normalization is hard

This stabilizes that we equate associated types involving bound variables using deferred-alias-equality. We also stop eagerly normalizing in coherence, which should not have any user-facing impact.

We do not stabilize the normalization behavior outside of coherence, e.g. we currently deeply normalize all types during writeback with the new solver. This may change going forward

### how to replace `select` from the old solver

We sometimes depend on getting a single `impl` for a given trait bound, e.g. when resolving a concrete method for codegen/CTFE. We do not depend on this during coherence, so the exact approach here can still be freely changed going forward.

## Acknowledgements

This work would not have been possible without `@compiler-errors.` He implemented large chunks of the solver himself but also and did a lot of testing and experimentation, eagerly discovering multiple issues which had a significant impact on our approach. `@BoxyUwU` has also done some amazing work on the solver. Thank you for the endless hours of discussion resulting in the current approach. Especially the way aliases are handled has gone through multiple revisions to get to its current state.

There were also many contributions from - and discussions with - other members of the community and the rest of `@rust-lang/types.` This solver builds upon previous improvements to the compiler, as well as lessons learned from `chalk` and `a-mir-formality`. Getting to this point  would not have been possible without that and I am incredibly thankful to everyone involved. See the [list of relevant PRs](https://github.com/rust-lang/rust/pulls?q=is%3Apr+is%3Amerged+label%3AWG-trait-system-refactor+-label%3Arollup+closed%3A%3C2024-03-22+).
RalfJung pushed a commit to RalfJung/miri that referenced this pull request Apr 6, 2024
instantiate higher ranked goals outside of candidate selection

This PR modifies `evaluate` to more eagerly instantiate higher-ranked goals, preventing the `leak_check` during candidate selection from detecting placeholder errors involving that binder.

For a general background regarding higher-ranked region solving and the leak check, see https://hackmd.io/qd9Wp03cQVy06yOLnro2Kg.

> The first is something called the **leak check**. You can think of it as a "quick and dirty" approximation for the region check, which will come later. The leak check detects some kinds of errors early, essentially deciding between "this set of outlives constraints are guaranteed to result in an error eventually" or "this set of outlives constraints may be solvable".

## The ideal future

We would like to end up with the following idealized design to handle universal binders:
```rust
fn enter_forall<'tcx, T, R>(
    forall: Binder<'tcx, T>,
    f: impl FnOnce(T) -> R,
) -> R {
    let new_universe = infcx.increment_universe_index();
    let value = instantiate_binder_with_placeholders_in(new_universe, forall);

    let result = f(value);

    eagerly_handle_higher_ranked_region_constraints_in(new_universe);
    infcx.decrement_universe_index();

    assert!(!result.has_placeholders_in_or_above(new_universe));
    result
}
```

That is, when universally instantiating a binder, anything using the placeholders has to happen inside of a limited scope (the closure `f`). After this closure has completed, all constraints involving placeholders are known.

We then handle any *external constraints* which name these placeholders. We destructure `TypeOutlives` constraints involving placeholders and eagerly handle any region constraints involving these placeholders. We do not return anything mentioning the placeholders created inside of this function to the caller.

Being able to eagerly handle *all* region constraints involving placeholders will be difficult due to complex `TypeOutlives` constraints, involving inference variables or alias types, and higher ranked implied bounds. The exact issues and possible solutions are out of scope of this FCP.

#### How does the leak check fit into this

The `leak_check` is an underapproximation of `eagerly_handle_higher_ranked_region_constraints_in`. It detects some kinds of errors involving placeholders from `new_universe`, but not all of them.

It only looks at region outlives constraints, ignoring `TypeOutlives`, and checks whether one of the following two conditions are met for **placeholders in or above `new_universe`**, in which case it results in an error:
- `'!p1: '!p2` a placeholder `'!p2` outlives a different placeholder `'!p1`
- `'!p1: '?2` an inference variable `'?2` outlives a placeholder `'!p1` *which it cannot name*

It does not handle all higher ranked region constraints, so we still return constraints involving placeholders from `new_universe` which are then (re)checked by `lexical_region_resolve` or MIR borrowck.

As we check higher ranked constraints in the full regionck anyways, the `leak_check` is not soundness critical. It's current only purpose is to move some higher ranked region errors earlier, enabling it to guide type inference and trait solving. Adding additional uses of the `leak_check` in the future would only strengthen inference and is therefore not breaking.

## Where do we use currently use the leak check

The `leak_check` is currently used in two places:

Coherence does not use a proper regionck, only relying on the `leak_check` called [at the end of the implicit negative overlap check](https://github.com/rust-lang/rust/blob/8b94152af68a0ed6d6af0b5ba57491e40481008e/compiler/rustc_trait_selection/src/traits/coherence.rs#L235-L238). During coherence all parameters are instantiated with inference variables, so the only possible region errors are higher-ranked. We currently also sometimes make guesses when destructuring `TypeOutlives` constraints which can theoretically result in incorrect errors. This could result in overlapping impls.

We also use the `leak_check` [at the end of `fn evaluation_probe`](https://github.com/rust-lang/rust/blob/8b94152af68a0ed6d6af0b5ba57491e40481008e/compiler/rustc_trait_selection/src/traits/select/mod.rs#L607-L610). This function is used during candidate assembly for `Trait` goals. Most notably we use [inside of `evaluate_candidate` during winnowing](https://github.com/rust-lang/rust/blob/0e4243538b9119654c22dce688f8a63c81864de9/compiler/rustc_trait_selection/src/traits/select/mod.rs#L491-L502). Conceptionally, it is as if we compute each candidate in a separate `enter_forall`.

## The current use in `fn evaluation_probe` is undesirable

Because we only instantiate a higher-ranked goal once inside of `fn evaluation_probe`, errors involving placeholders from that binder can impact selection. This results in inconsistent behavior ([playground](
*[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=dac60ebdd517201788899ffa77364831)*)):

```rust
trait Leak<'a> {}
impl Leak<'_>      for Box<u32> {}
impl Leak<'static> for Box<u16> {}

fn impls_leak<T: for<'a> Leak<'a>>() {}

trait IndirectLeak<'a> {}
impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}

fn main() {
    // ok
    //
    // The `Box<u16>` impls fails the leak check,
    // meaning that we apply the `Box<u32>` impl.
    impls_leak::<Box<_>>();

    // error: type annotations needed
    //
    // While the `Box<u16>` impl would fail the leak check
    // we have already instantiated the binder while applying
    // the generic `IndirectLeak` impl, so during candidate
    // selection of `Leak` we do not detect the placeholder error.
    // Evaluation of `Box<_>: Leak<'!a>` is therefore ambiguous,
    // resulting in `for<'a> Box<_>: Leak<'a>` also being ambiguous.
    impls_indirect_leak::<Box<_>>();
}
```

We generally prefer `where`-bounds over implementations during candidate selection, both for [trait goals](https://github.com/rust-lang/rust/blob/11f32b73e0dc9287e305b5b9980d24aecdc8c17f/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1863-L1887) and during [normalization](https://github.com/rust-lang/rust/blob/11f32b73e0dc9287e305b5b9980d24aecdc8c17f/compiler/rustc_trait_selection/src/traits/project.rs#L184-L198). However, we currently **do not** use the `leak_check` during candidate assembly in normalizing. This can result in inconsistent behavior:
```rust
trait Trait<'a> {
    type Assoc;
}
impl<'a, T> Trait<'a> for T {
    type Assoc = usize;
}

fn trait_bound<T: for<'a> Trait<'a>>() {}
fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}

// A function with a trivial where-bound which is more
// restrictive than the impl.
fn function<T: Trait<'static, Assoc = usize>>() {
    // ok
    //
    // Proving `for<'a> T: Trait<'a>` using the where-bound results
    // in a leak check failure, so we use the more general impl,
    // causing this to succeed.
    trait_bound::<T>();

    // error
    //
    // Proving the `Projection` goal `for<'a> T: Trait<'a, Assoc = usize>`
    // does not use the leak check when trying the where-bound, causing us
    // to prefer it over the impl, resulting in a placeholder error.
    projection_bound::<T>();

    // error
    //
    // Trying to normalize the type `for<'a> fn(<T as Trait<'a>>::Assoc)`
    // only gets to `<T as Trait<'a>>::Assoc` once `'a` has been already
    // instantiated, causing us to prefer the where-bound over the impl
    // resulting in a placeholder error. Even if were were to also use the
    // leak check during candidate selection for normalization, this
    // case would still not compile.
    let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
}
```

This is also likely to be more performant. It enables more caching in the new trait solver by simply [recursively calling the canonical query][new solver] after instantiating the higher-ranked goal.

It is also unclear how to add the leak check to normalization in the new solver. To handle rust-lang/trait-system-refactor-initiative#1 `Projection` goals are implemented via `AliasRelate`. This again means that we instantiate the binder before ever normalizing any alias. Even if we were to avoid this, we lose the ability to [cache normalization by itself, ignoring the expected `term`](https://github.com/rust-lang/rust/blob/5bd5d214effd494f4bafb29b3a7a2f6c2070ca5c/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs#L34-L49). We cannot replace the `term` with an inference variable before instantiating the binder, as otherwise `for<'a> T: Trait<Assoc<'a> = &'a ()>` breaks. If we only replace the term after instantiating the binder, we cannot easily evaluate the goal in a separate context, as [we'd then lose the information necessary for the leak check](https://github.com/rust-lang/rust/blob/11f32b73e0dc9287e305b5b9980d24aecdc8c17f/compiler/rustc_next_trait_solver/src/canonicalizer.rs#L230-L232). Adding this information to the canonical input also seems non-trivial.

## Proposed solution

I propose to instantiate the binder outside of candidate assembly, causing placeholders from higher-ranked goals to get ignored while selecting their candidate. This mostly[^1] matches the [current behavior of the new solver][new solver]. The impact of this change is therefore as follows:

```rust
trait Leak<'a> {}
impl Leak<'_>      for Box<u32> {}
impl Leak<'static> for Box<u16> {}

fn impls_leak<T: for<'a> Leak<'a>>() {}

trait IndirectLeak<'a> {}
impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}

fn guide_selection() {
    // ok -> ambiguous
    impls_leak::<Box<_>>();

    // ambiguous
    impls_indirect_leak::<Box<_>>();
}

trait Trait<'a> {
    type Assoc;
}
impl<'a, T> Trait<'a> for T {
    type Assoc = usize;
}

fn trait_bound<T: for<'a> Trait<'a>>() {}
fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}

// A function which a trivial where-bound which is more
// restrictive than the impl.
fn function<T: Trait<'static, Assoc = usize>>() {
    // ok -> error
    trait_bound::<T>();

    // error
    projection_bound::<T>();

    // error
    let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
}
```

This does not change the behavior if candidates have higher ranked nested goals, as in this case the `leak_check` causes the nested goal to result in an error ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a74c25300b23db9022226de99d8a2fa6)):
```rust
trait LeakCheckFailure<'a> {}
impl LeakCheckFailure<'static> for () {}

trait Trait<T> {}
impl Trait<u32> for () where for<'a> (): LeakCheckFailure<'a> {}
impl Trait<u16> for () {}
fn impls_trait<T: Trait<U>, U>() {}
fn main() {
    // ok
    //
    // It does not matter whether candidate assembly
    // considers the placeholders from higher-ranked goal.
    //
    // Either `for<'a> (): LeakCheckFailure<'a>` has no
    // applicable candidate or it has a single applicable candidate
    // when then later results in an error. This allows us to
    // infer `U` to `u16`.
    impls_trait::<(), _>()
}
```

## Impact on existing crates

This is a **breaking change**. [A crater run](rust-lang/rust#119820 (comment)) found 17 regressed crates with 7 root causes.

For a full analysis of all affected crates, see https://gist.github.com/lcnr/7c1c652f30567048ea240554a36ed95c.

---

I believe this breakage to be acceptable and would merge this change. I am confident that the new position of the leak check matches our idealized future and cannot envision any other consistent alternative. Where possible, I intend to open PRs fixing/avoiding the regressions before landing this PR.

I originally intended to remove the `coherence_leak_check` lint in the same PR. However, while I am confident in the *position* of the leak check, deciding on its exact behavior is left as future work, cc #112999. This PR therefore only moves the leak check while keeping the lint when relying on it in coherence.

[new solver]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs#L479-L484

[^1]: the new solver has a separate cause of inconsistent behavior rn rust-lang/trait-system-refactor-initiative#53 (comment)

r? `@nikomatsakis`
Oneirical added a commit to Oneirical/rust that referenced this pull request Apr 6, 2024
commit bbab2cf0209279cef607f859097c35d21939b898
Merge: 61b07b7f599 ea40fa210b8
Author: Julien <96022417+Oneirical@users.noreply.github.com>
Date:   Fri Apr 5 20:23:58 2024 +0000

    Merge branch 'master' into version

commit 61b07b7f599417bee714a6e8924b64b7ae466694
Author: Oneirical <manchot@videotron.ca>
Date:   Fri Apr 5 16:22:49 2024 -0400

    attempt to fix merge conflict

commit bebb3c4edeb12ef0a27b087508501d8c0e6d7d0c
Author: Oneirical <manchot@videotron.ca>
Date:   Fri Apr 5 16:14:32 2024 -0400

    try making tidy happy again

commit 6c727321f26ce61a52adc69cf965e0877de530d3
Author: Oneirical <manchot@videotron.ca>
Date:   Fri Apr 5 16:13:44 2024 -0400

    sync ui_tests.rs with master

commit 44bc9cae014808afad6b76cb7a02832b181adf76
Author: Oneirical <manchot@videotron.ca>
Date:   Fri Apr 5 16:10:19 2024 -0400

    a worthy sacrifice to tidy (possible merge conflict)

commit ea40fa210b87a322d2259852c149ffa212a3a0da
Merge: 1921968cc54 6cf6fd38ec0
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 17:28:45 2024 +0000

    Auto merge of #123502 - bjorn3:sync_cg_clif-2024-04-05, r=bjorn3

    Subtree sync for rustc_codegen_cranelift

    This fixes an ICE when compiling unchecked_shl/unchecked_shr.

    r? `@ghost`

    `@rustbot` label +A-codegen +A-cranelift +T-compiler

commit 6cf6fd38ec06decc2e5896ca3659cd74b0b03363
Merge: 5958f5e08fa fbda869b4e2
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Fri Apr 5 16:20:23 2024 +0000

    Merge commit 'fbda869b4e230c788b6bce426038ba8419956f2d' into sync_cg_clif-2024-04-05

commit 1921968cc5403892739b43bdefe793a130badd15
Merge: 5958f5e08fa 9cb517aede5
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 15:20:50 2024 +0000

    Auto merge of #123497 - GuillaumeGomez:rollup-usqb4q9, r=GuillaumeGomez

    Rollup of 8 pull requests

    Successful merges:

     - #122334 (Vendor rustc_codegen_gcc)
     - #122894 (Move check for error in impl header outside of reporting)
     - #123149 (Port argument-non-c-like-enum to Rust)
     - #123311 (Match ergonomics: implement "`&`pat everywhere")
     - #123350 (Actually use the inferred `ClosureKind` from signature inference in coroutine-closures)
     - #123474 (Port `run-make/issue-7349` to a codegen test)
     - #123489 (handle rustc args properly in bootstrap)
     - #123496 (ping on wf changes, remove fixme)

    r? `@ghost`
    `@rustbot` modify labels: rollup

commit fbda869b4e230c788b6bce426038ba8419956f2d
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Wed Mar 27 20:43:19 2024 +0000

    Add a couple more sync impls to mini_core

commit 454c87bdd442636b474d943c0e587750b46d822b
Merge: 40d40fb2293 1bab6df32b7
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Fri Apr 5 15:01:30 2024 +0000

    Merge branch 'build_system_changes'

commit 158c301cee972e36b2a615f98ce0ddd5db41a6f7
Author: Oneirical <manchot@videotron.ca>
Date:   Wed Apr 3 14:16:06 2024 -0400

    rewrite version as an UI test

    try fixing merge conflict

    also fix root_entry_limit

    make tidy happy

    remove does-nothing

    fix: set back to 860

commit 9cb517aede5500e80d25a39ba9f079dcf29fb8d4
Merge: b0ca3cd9d42 6db7ac62332
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:52 2024 +0200

    Rollup merge of #123496 - lcnr:wf-ping, r=compiler-errors

    ping on wf changes, remove fixme

    extend core type system pings to `wf.rs`

    r? `@compiler-errors`

commit b0ca3cd9d42d797ccf8a2b172a237921d721dfed
Merge: 0d5ee650f86 199589d8146
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:52 2024 +0200

    Rollup merge of #123489 - onur-ozkan:handle-rustc-args-properly, r=clubby789

    handle rustc args properly in bootstrap

    Because `RUSTFLAGS` gets overwritten during the conversion from `Cargo` to `Command`, the passed rustc args were being lost. This change combines the rustc args with the values that override `RUSTFLAGS`.

    Fixes #123228

commit 0d5ee650f8619021635e255447a036b2e98d42b8
Merge: 02ee8a8ceef 476156aedf4
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:51 2024 +0200

    Rollup merge of #123474 - jieyouxu:issue-7349-port, r=Mark-Simulacrum

    Port `run-make/issue-7349` to a codegen test

    The test does not need to be a run-make test, it can use the codegen test infrastructure.

    Also took the opportunity to rename the test to `no-redundant-item-monomorphization` so it's not just some opaque issue number.

    Part of #121876.

commit 02ee8a8ceeff811adfb065028a48c1947d97ef91
Merge: f2f8d8b722f 55e46612c1c
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:51 2024 +0200

    Rollup merge of #123350 - compiler-errors:async-closure-by-move, r=oli-obk

    Actually use the inferred `ClosureKind` from signature inference in coroutine-closures

    A follow-up to https://github.com/rust-lang/rust/pull/123349, which fixes another subtle bug: We were not taking into account the async closure kind we infer during closure signature inference.

    When I pass a closure directly to an arg like `fn(x: impl async FnOnce())`, that should have the side-effect of artificially restricting the kind of the async closure to `ClosureKind::FnOnce`. We weren't doing this -- that's a quick fix; however, it uncovers a second, more subtle bug with the way that `move`, async closures, and `FnOnce` interact.

    Specifically, when we have an async closure like:
    ```
    let x = Struct;
    let c = infer_as_fnonce(async move || {
      println!("{x:?}");
    }
    ```

    The outer closure captures `x` by move, but the inner coroutine still immutably borrows `x` from the outer closure. Since we've forced the closure to by `async FnOnce()`, we can't actually *do* a self borrow, since the signature of `AsyncFnOnce::call_once` doesn't have a borrowed lifetime. This means that all `async move` closures that are constrained to `FnOnce` will fail borrowck.

    We can fix that by detecting this case specifically, and making the *inner* async closure `move` as well. This is always beneficial to closure analysis, since if we have an `async FnOnce()` that's `move`, there's no reason to ever borrow anything, so `move` isn't artificially restrictive.

commit f2f8d8b722fdacc6a6e02c2289e3e36571749a68
Merge: c36c0095776 e5376f3947b
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:50 2024 +0200

    Rollup merge of #123311 - Jules-Bertholet:andpat-everywhere, r=Nadrieril

    Match ergonomics: implement "`&`pat everywhere"

    Implements the eat-two-layers (feature gate `and_pat_everywhere`, all editions) ~and the eat-one-layer (feature gate `and_eat_one_layer_2024`, edition 2024 only, takes priority on that edition when both feature gates are active)~ (EDIT: will be done in later PR) semantics.

    cc #123076

    r? ``@Nadrieril``

    ``@rustbot`` label A-patterns A-edition-2024

commit c36c0095776f1cbc39d15a206b4b1018b329b4aa
Merge: cb6a1c8d455 fad8213150b
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:50 2024 +0200

    Rollup merge of #123149 - jieyouxu:rmake-arguments-non-c-like-enum, r=Mark-Simulacrum

    Port argument-non-c-like-enum to Rust

    Part of #121876.

commit cb6a1c8d455a26c82165e3285557da2d82e22385
Merge: 8873ca57f86 5333f2a9d15
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:49 2024 +0200

    Rollup merge of #122894 - compiler-errors:downgrade, r=lcnr

    Move check for error in impl header outside of reporting

    Fixes #121006

    r? lcnr

    test location kinda sucks, can move it if needed

commit 8873ca57f8646328bf0a10ee94918c8c597706e9
Merge: 4563f70c3b5 0f5140e3834
Author: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date:   Fri Apr 5 16:38:49 2024 +0200

    Rollup merge of #122334 - GuillaumeGomez:vendor-cg_gcc, r=Mark-Simulacrum

    Vendor rustc_codegen_gcc

    I used https://github.com/rust-lang/rust/pull/115274 as base for this update.

    r? `@bjorn3`

commit 1bab6df32b7e593f75ab6470c0b650b345107995
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Tue Apr 2 14:17:35 2024 +0000

    Remove all checks for CI in the build system

    And introduce the CG_CLIF_EXPENSIVE_CHECKS env var in the place.

commit f269cdd80582ec92972483641676e4a933b583a0
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Fri Apr 5 13:56:21 2024 +0000

    Move disabling incr comp and denying warnings to the CI config

commit 603b2800f7fa61947b35419f1a5a33e265792001
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Tue Apr 2 15:17:56 2024 +0000

    Revoke all permissions from GHA workflows where possible

commit 65342df8cd9ed8ca5311edc69f445fdb7b60a191
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Tue Apr 2 15:11:20 2024 +0000

    Dedup default shell specification for GHA

commit 91ffd74de41fa473bf8e7ac94b8159578ba3e94c
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Tue Apr 2 15:05:06 2024 +0000

    Simplify GHA CI workflow

commit 5958f5e08fa88ee95ede8c00f1b89befe0372d54
Merge: 4563f70c3b5 3ad9c83cd25
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 13:17:09 2024 +0000

    Auto merge of #123317 - RalfJung:test-in-miri, r=m-ou-se,saethlin,onur-ozkan

    Support running library tests in Miri

    This adds a new bootstrap subcommand `./x.py miri` which can test libraries in Miri. This is in preparation for eventually doing that as part of bors CI, but this PR only adds the infrastructure, and doesn't enable it yet.

    `@rust-lang/bootstrap` should this be `x.py test --miri library/core` or `x.py miri library/core`? The flag has the advantage that we don't have to copy all the arguments from `Subcommand::Test`. It has the disadvantage that most test steps just ignore `--miri` and still run tests the regular way. For clippy you went the route of making it a separate subcommand. ~~I went with a flag now as that seemed easier, but I can change this.~~ I made it a new subcommand. Note however that the regular cargo invocation would be `cargo miri test ...`, so `x.py` is still going to be different in that the `test` is omitted. That said, we could also make it `./x.py miri-test` to make that difference smaller -- that's in fact more consistent with the internal name of the command when bootstrap invokes cargo.

    `@rust-lang/libs` ~~unfortunately this PR does some unholy things to the `lib.rs` files of our library crates.~~
    `@m-ou-se` found a way that entirely avoids library-level hacks, except for some new small `lib.miri.rs` files that hopefully you will never have to touch. There's a new hack in cargo-miri but there it is in good company...

commit 6db7ac6233244c550b3b0a030387419ab2ac9ddd
Author: lcnr <rust@lcnr.de>
Date:   Fri Apr 5 15:09:48 2024 +0200

    ping on wf changes, remove fixme

commit 40d40fb2293734b6ac9c77e764bf0183819e4a95
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Tue Apr 2 14:29:00 2024 +0000

    Fix warning in mini_core

commit 737421a25b9a46aca017ffef1b1d648e278d1d87
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Fri Apr 5 12:15:41 2024 +0000

    Rustup to rustc 1.79.0-nightly (385fa9d84 2024-04-04)

commit 5a9940fe3dd8e48d98b92d13a03372ff7da93f31
Merge: 64d6da5cda2 6728f2fef42
Author: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date:   Fri Apr 5 11:39:51 2024 +0000

    Sync from rust 385fa9d845dd326c6bbfd58c22244215e431948a

commit 4563f70c3b599411836e285591479f4a3d364708
Merge: d009f60b55f aa9c9a36c06
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 11:11:17 2024 +0000

    Auto merge of #122070 - Zoxc:dep-edges-from-previous, r=cjgillot

    Encode dep graph edges directly from the previous graph when promoting

    This encodes dep graph edges directly from the previous graph when promoting nodes from a previous session, avoiding allocations / copies.

    ~~Based on https://github.com/rust-lang/rust/pull/122064 and https://github.com/rust-lang/rust/pull/116375.~~

    <table><tr><td rowspan="2">Benchmark</td><td colspan="1"><b>Before</b></th><td colspan="2"><b>After</b></th></tr><tr><td align="right">Time</td><td align="right">Time</td><td align="right">%</th></tr><tr><td>🟣 <b>clap</b>:check:unchanged</td><td align="right">0.4177s</td><td align="right">0.4072s</td><td align="right">💚  -2.52%</td></tr><tr><td>🟣 <b>hyper</b>:check:unchanged</td><td align="right">0.1430s</td><td align="right">0.1420s</td><td align="right"> -0.69%</td></tr><tr><td>🟣 <b>regex</b>:check:unchanged</td><td align="right">0.3106s</td><td align="right">0.3038s</td><td align="right">💚  -2.19%</td></tr><tr><td>🟣 <b>syn</b>:check:unchanged</td><td align="right">0.5823s</td><td align="right">0.5688s</td><td align="right">💚  -2.33%</td></tr><tr><td>🟣 <b>syntex_syntax</b>:check:unchanged</td><td align="right">1.3992s</td><td align="right">1.3692s</td><td align="right">💚  -2.14%</td></tr><tr><td>Total</td><td align="right">2.8528s</td><td align="right">2.7910s</td><td align="right">💚  -2.17%</td></tr><tr><td>Summary</td><td align="right">1.0000s</td><td align="right">0.9803s</td><td align="right">💚  -1.97%</td></tr></table>

commit 3ad9c83cd2538f865b62c87f998cb25e599da029
Author: Ralf Jung <post@ralfj.de>
Date:   Fri Apr 5 08:51:46 2024 +0200

    miri: go look for the item in all crates of the right name

commit d009f60b55fe4527e7ddf122bc4520f351d7b9d4
Merge: c0ddaef0757 af81ab76288
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 09:09:35 2024 +0000

    Auto merge of #123469 - belovdv:remove-miri-jobserver-fixme, r=petrochenkov

    remove miri jobserver workaround

    This PR removes workaround, added in #113730, since jobserver is kept after [rust-lang/cargo#12776](https://github.com/rust-lang/cargo/pull/12776)

commit 199589d81466a4b436bd41cc0dfd2f35c908a951
Author: onur-ozkan <work@onurozkan.dev>
Date:   Fri Apr 5 10:52:36 2024 +0300

    handle rustc args properly in bootstrap

    Because `RUSTFLAGS` gets overwritten during the conversion from `Cargo` to `Command`,
    the passed rustc args were being lost. This change combines the rustc args with the values
    that override `RUSTFLAGS`.

    Signed-off-by: onur-ozkan <work@onurozkan.dev>

commit c0ddaef075748674140263840a185082f44458e9
Merge: 3d7e88148a0 b0b7c860e13
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 04:34:05 2024 +0000

    Auto merge of #123444 - saethlin:const-eval-inline-cycles, r=tmiasko

    Teach MIR inliner query cycle avoidance about const_eval_select

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

    r? tmiasko

commit 3d7e88148a00c99e444c8f287d73ebe1846bc7aa
Merge: 9cbaa015991 e8b0c305780
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 02:32:03 2024 +0000

    Auto merge of #123484 - jhpratt:rollup-usz4e64, r=jhpratt

    Rollup of 9 pull requests

    Successful merges:

     - #123206 (Require Pointee::Metadata to be Freeze)
     - #123363 (change `NormalizesTo` to fully structurally normalize)
     - #123407 (Default to light theme if JS is enabled but not working)
     - #123417 (Add Description for cargo in rustdoc documentation)
     - #123437 (Manually run `clang-format` on `CoverageMappingWrapper.cpp`)
     - #123454 (hir: Use `ItemLocalId::ZERO` in a couple more places)
     - #123464 (Cleanup: Rename `HAS_PROJECTIONS` to `HAS_ALIASES` etc.)
     - #123477 (do not ICE in `fn forced_ambiguity` if we get an error)
     - #123478 (CFI: Add test for `call_once` addr taken)

    r? `@ghost`
    `@rustbot` modify labels: rollup

commit e8b0c3057807e50ac1f95fdba36d79b72fbd206d
Merge: e01d3e0824c b53a0f2c9e9
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:59 2024 -0400

    Rollup merge of #123478 - maurer:cfi-call-once-addr-taken, r=compiler-errors

    CFI: Add test for `call_once` addr taken

    One of the proposed ways to reduce the non-passed argument erasure would cause this test to fail. Adding this now ensures that any attempt to reduce non-passed argument erasure won't make the same mistake.

    r? `@compiler-errors`

    cc `@rcvalle`

commit e01d3e0824cd24dc02c0b22db2fa0d4677f1a0c3
Merge: 58eb6e58031 9444ca354a5
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:58 2024 -0400

    Rollup merge of #123477 - lcnr:forced_ambig-no-ice, r=compiler-errors

    do not ICE in `fn forced_ambiguity` if we get an error

    see the comment. currently causing an ICE in typenum which we've been unable to minimize.

    r? `@compiler-errors`

commit 58eb6e580316b01cfbd68d9d02c98e1e68daf249
Merge: 929e0db6a9a 6f17b7f0aba
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:58 2024 -0400

    Rollup merge of #123464 - fmease:rn-has-proj-to-has-aliases, r=compiler-errors

    Cleanup: Rename `HAS_PROJECTIONS` to `HAS_ALIASES` etc.

    The name of the bitflag `HAS_PROJECTIONS` and of its corresponding method `has_projections` is quite historical dating back to a time when projections were the only kind of alias type.

    I think it's time to update it to clear up any potential confusion for newcomers and to reduce unnecessary friction during contributor onboarding.

    r? types

commit 929e0db6a9a31b6079839df5834ee211d191802f
Merge: daef0fd8782 17475de5de1
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:57 2024 -0400

    Rollup merge of #123454 - petrochenkov:zeroindex2, r=fmease

    hir: Use `ItemLocalId::ZERO` in a couple more places

    Follow up to https://github.com/rust-lang/rust/pull/123415 and https://github.com/rust-lang/rust/pull/123419.

commit daef0fd87829dc063201828f591c70ac47beffd9
Merge: 50603cbb6d0 f6b97ef5e56
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:57 2024 -0400

    Rollup merge of #123437 - Zalathar:clang-format, r=cuviper

    Manually run `clang-format` on `CoverageMappingWrapper.cpp`

    In the current version of #123409, there are several unrelated changes to `CoverageMappingWrapper.cpp` that seem to be the result of running `clang-format` on that file.

    Instead of asking for those changes to be undone, I figure it's easier to just make them myself as a separate PR, since I was vaguely intending to do that at some point anyway.

    In a few cases I've strategically added comments to make the grouping of parameters a little nicer, but mostly it doesn't matter much.

commit 50603cbb6d019789e5838a0ff720102c38a5ee58
Merge: ac298726afb 612acf8397f
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:56 2024 -0400

    Rollup merge of #123417 - harryhanYuhao:master, r=GuillaumeGomez

    Add Description for cargo in rustdoc documentation

    As most people use cargo now, I prioritised the description for cargo in rustdoc documentation.

    I also added how to open the generated doc with cargo.

    Btw, may I ask how to use `./x tidy`? It says `warning: `tidy` is not installed;`

commit ac298726afbb2719c966153539b4229da6c8b8b6
Merge: fcb0e9d07a3 a815b97850e
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:56 2024 -0400

    Rollup merge of #123407 - GuillaumeGomez:js-failed-theme, r=notriddle

    Default to light theme if JS is enabled but not working

    It doesn't [fix] #123399 but it allows to reduce the problem:

    * if JS is completely disabled, then `noscript.css` will be applied
    * if JS failed for any reason, then the light theme will be applied (because `noscript.css` won't be applied)

    r? `@notriddle`

commit fcb0e9d07a3397731acd20059b8adf47b6863cd6
Merge: de2cb0d76c7 92b280ce81e
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:56 2024 -0400

    Rollup merge of #123363 - lcnr:normalizes-to-zero-to-inf, r=BoxyUwU

    change `NormalizesTo` to fully structurally normalize

    notes in https://hackmd.io/wZ016dE4QKGIhrOnHLlThQ

    need to also update the dev-guide once this PR lands. in short, the setup is now as follows:

    `normalizes-to` internally implements one step normalization, applying that normalization to the `goal.predicate.term` causes the projected term to get recursively normalized. With this `normalizes-to` normalizes until the projected term is rigid, meaning that we normalize as many steps necessary, but at least 1.

    To handle rigid aliases, we add another candidate only if the 1 to inf step normalization failed. With this `normalizes-to` is now full structural normalization. We can now change `AliasRelate` to simply emit `normalizes-to` goals for the rhs and lhs.

    This avoids the concerns from https://github.com/rust-lang/trait-system-refactor-initiative/issues/103 and generally feels cleaner

commit de2cb0d76c79720eb641e3ebbacf26907eac69dc
Merge: 385fa9d845d 8f5a28e0aa3
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Thu Apr 4 21:16:55 2024 -0400

    Rollup merge of #123206 - stepancheg:pointee-metadata-freeze, r=Amanieu

    Require Pointee::Metadata to be Freeze

    So pointee metadata can be used in anonymous statics.

    This is prerequisite for implementing ThinBox without allocation for ZST.

    See https://github.com/rust-lang/rust/pull/123184#discussion_r1544627488

    r? joboet

commit 9cbaa015991b7ac5f6e1b4d713ab9096573ad30d
Merge: 385fa9d845d 5d66521dfef
Author: bors <bors@rust-lang.org>
Date:   Fri Apr 5 00:30:47 2024 +0000

    Auto merge of #123465 - flip1995:clippy-subtree-update, r=Manishearth

    Clippy subtree update

    r? `@Manishearth`

commit 55e46612c1ccceb30a7a6acf11fd485f34e393e5
Author: Michael Goulet <michael@errs.io>
Date:   Wed Apr 3 12:16:17 2024 -0400

    Force `move` async-closures that are `FnOnce` to make their inner coroutines also `move`

commit 3d9d5d7c96ae3df2cfc47e933ab11ad5fa30f3bc
Author: Michael Goulet <michael@errs.io>
Date:   Mon Apr 1 14:47:12 2024 -0400

    Actually use the inferred ClosureKind from signature inference in coroutine-closures

commit 5d66521dfefe64c0e4f571edcd4408a07505ff48
Author: y21 <30553356+y21@users.noreply.github.com>
Date:   Fri Apr 5 00:17:27 2024 +0200

    use `Lrc` instead of the aliased type `Arc` directly

commit b53a0f2c9e96778a044cb72472aa898f9804471d
Author: Matthew Maurer <mmaurer@google.com>
Date:   Thu Apr 4 22:06:58 2024 +0000

    CFI: Add test for `call_once` addr taken

    One of the proposed ways to reduce the non-passed argument erasure would
    cause this test to fail. Adding this now ensures that any attempt to
    reduce non-passed argument erasure won't make the same mistake.

commit 9444ca354a5ed82ab7c8b264117c9a9436948ce9
Author: lcnr <rust@lcnr.de>
Date:   Thu Apr 4 07:47:13 2024 +0200

    do not ICE in forced ambiguity if we get an error

commit a815b97850e487f5c668edf83357cf871b3db57a
Author: Guillaume Gomez <guillaume.gomez@huawei.com>
Date:   Thu Apr 4 23:49:34 2024 +0200

    Add regression test to ensure that even if JS is enabled but not working, a theme will still get applied

commit f2ff9c903548d88211df90cd4e1673577ff58ad5
Author: Guillaume Gomez <guillaume.gomez@huawei.com>
Date:   Thu Apr 4 23:48:35 2024 +0200

    Update browser-ui-test version to 0.17.1

commit 476156aedf4b4bc74e10d82d59c3a7c4429a8d0e
Author: 许杰友 Jieyou Xu (Joe) <jieyouxu@outlook.com>
Date:   Thu Apr 4 21:59:08 2024 +0100

    Port issue-7349 to a codegen test

commit 385fa9d845dd326c6bbfd58c22244215e431948a
Merge: a4b11c8e605 0dca1368411
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 20:52:52 2024 +0000

    Auto merge of #123097 - oli-obk:perf_experiment, r=petrochenkov

    Try using a `dyn Debug` trait object instead of a closure

    These closures were introduced in https://github.com/rust-lang/rust/pull/93098

    let's see if we can't use fmt::Arguments instead

    cc `@Aaron1011`

commit af81ab762888eb04d01e9ad5269df5202d6a38b8
Author: belovdv <70999565+belovdv@users.noreply.github.com>
Date:   Thu Apr 4 22:40:00 2024 +0300

    remove miri jobserver workaround

commit a809a726671bc81206e2ab9cba59873f6e741212
Author: Philipp Krones <hello@philkrones.com>
Date:   Thu Apr 4 19:53:00 2024 +0200

    Update Cargo.lock

commit eedf15a1dc54097439ecd524e315665f18eaf31c
Merge: 96eaf553e54 9725c4a1625
Author: Philipp Krones <hello@philkrones.com>
Date:   Thu Apr 4 19:52:55 2024 +0200

    Merge commit '9725c4a162502a02c1c67fdca6b797fe09b2b73c' into clippy-subtree-update

commit 9725c4a162502a02c1c67fdca6b797fe09b2b73c
Merge: 5a9e9b0e65d bb023e90d8d
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 17:50:22 2024 +0000

    Auto merge of #12632 - flip1995:rustup, r=flip1995

    Rustup

    r? `@ghost`

    changelog: none

commit bb023e90d8dfbdee714aa33cfa44b91753a99a03
Author: Philipp Krones <hello@philkrones.com>
Date:   Thu Apr 4 19:48:53 2024 +0200

    Bump nightly version -> 2024-04-04

commit 277303b210a3501211961d69ad2a09cae0b2643f
Merge: 53e31dc45ce 5a9e9b0e65d
Author: Philipp Krones <hello@philkrones.com>
Date:   Thu Apr 4 19:26:44 2024 +0200

    Merge remote-tracking branch 'upstream/master' into rustup

commit a4b11c8e6057bd47f8d241baafd5ae1e813d62fd
Merge: 0fd571286ef 4e8d2f0040f
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 17:42:07 2024 +0000

    Auto merge of #121394 - oli-obk:define_opaque_types, r=compiler-errors

    some smaller DefiningOpaqueTypes::No -> Yes switches

    r? `@compiler-errors`

    These are some easy cases, so let's get them out of the way first.
    I added tests exercising the specialization code paths that I believe weren't tested so far.

    follow-up to https://github.com/rust-lang/rust/pull/117348

commit 6f17b7f0aba4e07f5aa202ecb1e95e0e3d97f828
Author: León Orell Valerian Liehr <me@fmease.dev>
Date:   Thu Apr 4 19:26:17 2024 +0200

    Rename HAS_PROJECTIONS to HAS_ALIASES etc.

commit 4e8d2f0040f108e3f07854b231a5987005217763
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 15:50:40 2024 +0000

    Add regression test

commit ede0556ab538ccaa928299812519db95aff9d7ca
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 15:36:49 2024 +0000

    Effects are boolean consts and don't contain opaque types

commit 0183d92df0591b25363b3e12ae0a4a8f1b0b076c
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 15:33:09 2024 +0000

    Allow defining opaque types when checking const equality bounds

commit 0fd571286ef6df8a6cce06d432013239a8c0665f
Merge: 96eaf553e54 83bd12c70fd
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 15:39:00 2024 +0000

    Auto merge of #123377 - oli-obk:private_projection, r=compiler-errors

    Only inspect user-written predicates for privacy concerns

    fixes #123288

    Previously we looked at the elaborated predicates, which, due to adding various bounds on fields, end up requiring trivially true bounds. But these bounds can contain private types, which the privacy visitor then found and errored about.

commit 29fba9f994d5c32448cb6937aaae9b319ddcf392
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 15:29:44 2024 +0000

    Add regression test

commit 8e226e092eba650ce0e71d1336519e4045a8ba0e
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 14:59:43 2024 +0000

    Add some regression tests for opaque types and const generics

commit ba316a902d4a350f41bfaeba17df66b582de9d99
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Thu Apr 4 14:53:31 2024 +0000

    amend to  Switch `can_eq` and `can_sub` to `DefineOpaqueTypes::Yes`

commit 83bd12c70fd34dece71bcc632ee3df64036ca1d8
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Tue Apr 2 17:27:35 2024 +0000

    Only inspect user-written predicates for privacy concerns

commit 169a045dca0e8cc7c720a962cef274fb5f8fafef
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 14:50:17 2024 +0000

    Switch upcast projections to allowing opaque types and add a test showing it works.

    The old solver was already ICEing on this test before this change

commit cdcca7e8f4842fe4a3b64c0e5ac7d25025950889
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 14:29:28 2024 +0000

    Switch `can_eq` and `can_sub` to `DefineOpaqueTypes::Yes`

    They are mostly used in diagnostics anyway

commit 612acf8397f0f8d55fc533d61ea835b73a1e696d
Author: Harry Han <s2162783@ed.ac.uk>
Date:   Thu Apr 4 15:04:46 2024 +0100

    rustdoc prioritise cargo doc: suggestions applied

commit 96eaf553e547e36003e235a9de26c11460712231
Merge: ca7d34efa94 4ba3f46be3c
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 13:10:22 2024 +0000

    Auto merge of #123455 - matthiaskrgr:rollup-b6nu296, r=matthiaskrgr

    Rollup of 9 pull requests

    Successful merges:

     - #121546 (Error out of layout calculation if a non-last struct field is unsized)
     - #122448 (Port hir-tree run-make test to ui test)
     - #123212 (CFI: Change type transformation to use TypeFolder)
     - #123218 (Add test for getting parent HIR for synthetic HIR node)
     - #123324 (match lowering: make false edges more precise)
     - #123389 (Avoid panicking unnecessarily on startup)
     - #123397 (Fix diagnostic for qualifier in extern block)
     - #123431 (Stabilize `proc_macro_byte_character` and `proc_macro_c_str_literals`)
     - #123439 (coverage: Remove useless constants)

    r? `@ghost`
    `@rustbot` modify labels: rollup

commit 4ba3f46be3c28ba5b17c9a7b732b569868ad7d01
Merge: ad300b67386 e08fdb0f2fc
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:18 2024 +0200

    Rollup merge of #123439 - Zalathar:constants, r=oli-obk

    coverage: Remove useless constants

    After #122972 and #123419, these constants don't serve any useful purpose, so get rid of them.

    `@rustbot` label +A-code-coverage

commit ad300b673865d25b76e4d00da58c80df0bcba271
Merge: f254ab08f15 fbc56dfac13
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:18 2024 +0200

    Rollup merge of #123431 - slanterns:literal_byte_character_c_string_stabilize, r=dtolnay

    Stabilize `proc_macro_byte_character` and `proc_macro_c_str_literals`

    This PR stabilizes `proc_macro_byte_character` and `proc_macro_c_str_literals`:

    ```rust
    // proc_macro::Literal

    impl Literal {
        pub fn byte_character(byte: u8) -> Literal;
        pub fn c_string(string: &CStr) -> Literal
    }
    ```

    <br>

    Tracking issue: https://github.com/rust-lang/rust/issues/115268, https://github.com/rust-lang/rust/issues/119750.
    Implementation PR: https://github.com/rust-lang/rust/pull/112711, https://github.com/rust-lang/rust/pull/119651.

    FCPs already completed in their respective tracking issues.

    Closes https://github.com/rust-lang/rust/issues/115268. Closes https://github.com/rust-lang/rust/issues/119750.

    r? libs-api

commit f254ab08f155ae118a71b438fa56d85e9251b0ce
Merge: ee5009e745b 109daa2d4ba
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:17 2024 +0200

    Rollup merge of #123397 - krtab:foreign_fn_qualif_diag, r=petrochenkov

    Fix diagnostic for qualifier in extern block

    Closes: https://github.com/rust-lang/rust/issues/123306

commit ee5009e745b4088f8ef942ab9bcf6f28b7bbac0d
Merge: 504a78e2f24 7b8f93ef4c2
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:17 2024 +0200

    Rollup merge of #123389 - ChrisDenton:dont-panic-on-startup, r=joboet

    Avoid panicking unnecessarily on startup

    On Windows, in `lang_start` we add an exception handler to catch stack overflows and we also reserve some stack space for the handler. Both of these are useful but they're not strictly necessary. The standard library has to work without them (e.g. if Rust is used from a foreign entry point) and the negative effect of not doing them is limited (i.e. you don't get the friendly stack overflow message).

    As we really don't want to panic pre-main unless absolutely necessary, it now won't panic on failure. I've added some debug assertions so as to avoid programmer error.

commit 504a78e2f24a7ce0e11116429c86c0be9553c79c
Merge: 7c2d4eaf922 e2ebaa1a08a
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:16 2024 +0200

    Rollup merge of #123324 - Nadrieril:false-edges2, r=matthewjasper

    match lowering: make false edges more precise

    When lowering match expressions, we add false edges to hide details of the lowering from borrowck. Morally we pretend we're testing the patterns (and guards) one after the other in order. See the tests for examples. Problem is, the way we implement this today is too coarse for deref patterns.

    In deref patterns, a pattern like `deref [1, x]` matches on a `Vec` by creating a temporary to store the output of the call to `deref()` and then uses that to continue matching. Here the pattern has a binding, which we set up after the pre-binding block. Problem is, currently the false edges tell borrowck that the pre-binding block can be reached from a previous arm as well, so the `deref()` temporary may not be initialized. This triggers an error when we try to use the binding `x`.

    We could call `deref()` a second time, but this opens the door to soundness issues if the deref impl is weird. Instead in this PR I rework false edges a little bit.

    What we need from false edges is a (fake) path from each candidate to the next, specifically from candidate C's pre-binding block to next candidate D's pre-binding block. Today, we link the pre-binding blocks directly. In this PR, I link them indirectly by choosing an earlier node on D's success path. Specifically, I choose the earliest block on D's success path that doesn't make a loop (if I chose e.g. the start block of the whole match (which is on the success path of all candidates), that would make a loop). This turns out to be rather straightforward to implement.

    r? `@matthewjasper` if you have the bandwidth, otherwise let me know

commit 7c2d4eaf922664882d3af1041f776019d02f9562
Merge: f03535b2971 f0296029206
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:16 2024 +0200

    Rollup merge of #123218 - compiler-errors:synthetic-hir-parent, r=petrochenkov

    Add test for getting parent HIR for synthetic HIR node

    Fixes #122991, which was actually fixed by #123415

commit f03535b29712441999544e3306582fb41b5c0f4f
Merge: 0b54db7e3fe bc8c3eff6b8
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:15 2024 +0200

    Rollup merge of #123212 - rcvalle:rust-cfi-use-type-folder, r=compiler-errors

    CFI: Change type transformation to use TypeFolder

    Change type transformation to use TypeFolder.

    cc `@compiler-errors` `@maurer`

commit 0b54db7e3feffad43cc55c17ee26104feb24739f
Merge: d5a657c95ca 2575b8e79c8
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:15 2024 +0200

    Rollup merge of #122448 - high-cloud:move-hir-tree, r=oli-obk

    Port hir-tree run-make test to ui test

    As part of #121876

    cc `@jieyouxu`

commit d5a657c95ca2f29c356c278b4e0be43bd8a7743d
Merge: 4c6c6298664 313714331ac
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Thu Apr 4 14:51:14 2024 +0200

    Rollup merge of #121546 - gurry:121473-ice-sizeof-mir-op, r=oli-obk

    Error out of layout calculation if a non-last struct field is unsized

    Fixes #121473
    Fixes #123152

commit 17475de5de1978afbea982ba4efeaa6cea259d4a
Author: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date:   Thu Apr 4 14:43:49 2024 +0300

    hir: Use `ItemLocalId` in a couple more places

commit 5a9e9b0e65d27bb294a5e13ca554878b43af6224
Merge: 398a52a8dc6 b6486fae5c9
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 11:39:45 2024 +0000

    Auto merge of #12628 - franciscoBSalgueiro:fix-book-links, r=flip1995

    Add missing links in the book

    Added a few missing links marked with FIXME in the development book.

    changelog: none

commit 7b8f93ef4c2b01b6cc7656123301f0f5e322b603
Author: Chris Denton <chris@chrisdenton.dev>
Date:   Thu Apr 4 10:48:11 2024 +0000

    Add comments about using debug_assert

commit ca7d34efa94afe271accf2bd3d44152a5bd6fff1
Merge: 4c6c6298664 8289dadfbc5
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 10:45:21 2024 +0000

    Auto merge of #121026 - Zalathar:version, r=oli-obk

    coverage: Correctly report and check LLVM's coverage mapping version

    I was puzzled by the fact that the LLVM 18 update (#120055) didn't need to modify this version check, despite the fact that LLVM 18 uses a newer version of the coverage mapping format.

    This turned out to be because we were inappropriately hard-coding a specific version (`Version6`) in the C++ wrapper, instead of using `CovMapVersion::CurrentVersion` to reflect the version actually used by LLVM on our behalf.

    This PR fixes that, and also changes the Rust-side version check to accept the new coverage mapping version used by LLVM 18, since the necessary compatibility work has already been done.

    ---

    ### Quick history of `LLVMRustCoverageMappingVersion`:

    - Originally it returned LLVM's `coverage::CovMapVersion::CurrentVersion`, as intended. The Rust-side code would verify it, and also embed it as the actual coverage version number in the output binary.
    - At some point it was changed to a hard-coded value, to work around a (now-irrelevant) compatibility issue. This was incorrect (but mostly benign), because the override should have been performed on the Rust side instead, after verifying LLVM's value.
    - Later contributors dutifully updated the hard-coded value, because they didn't have enough context to identify the problem.
    - With this PR, it once again returns LLVM's current coverage version number, and the Rust-side code checks it against an expected range. We don't override the result, but we do indicate where that override should occur if it ever becomes necessary.

commit 2575b8e79c881db316af12ad66191a4b1000ff54
Author: Yaodong Yang <highcloud333@outlook.com>
Date:   Thu Mar 14 01:23:43 2024 +0800

    move hir-tree test from run-make to ui test

commit 92b280ce81e2cf9834ed1965ae4e63e80bce0dc1
Author: lcnr <rust@lcnr.de>
Date:   Tue Apr 2 15:12:20 2024 +0200

    normalizes-to change from '1' to '0 to inf' steps

commit 313714331ac3fbc63e767fe95d175f293cf5d875
Author: Gurinder Singh <frederick.the.fool@gmail.com>
Date:   Thu Apr 4 15:50:36 2024 +0530

    Error out of layout calculation if a non-last struct field is unsized

    Fixes an ICE that occurs when a struct with an unsized field
    at a non-last position is const evaluated.

commit 10e8bca7fe00b4b10eca33a8d70ebb06d71cd621
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 12:31:41 2024 +0000

    FRU remaining fields does not actually define opaque types

commit 95948b75b2e036f07462c3f7a51d7ced659057a3
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 11:44:59 2024 +0000

    Use `DefineOpaqueTypes::Yes` since we are guaranteed to error already

commit 2247aaf276029888fc7c14a372d9033276ec0c86
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 11:42:39 2024 +0000

    Use `DefineOpaqueTypes::Yes` where the new solver is unconditionally used already

commit 82ceed2add79244d53a960735a68ce85d55a4232
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 11:35:50 2024 +0000

    Specialization can switch to `DefineOpaqueTypes::Yes` without having an effect.

    The reason is that in specialization graph computation we use `DefiningAnchor::Error`, so there's no difference anyway. And in the other use cases, we

    * already errored in the specialization_graph computation, or
    * already errored in coherence, or
    * are comparing opaque types with inference variables already, or
    * there are no opaque types involved

commit b8bd9815455ac3c1bff865dee30aa694ad19beb6
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 11:30:57 2024 +0000

    Specialization already rejects defining opaque types

commit 150448d2e043061cfa39f94b0d87e1c80fb6a121
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 10:43:50 2024 +0000

    use `DefineOpaqueTypes::Yes` in rustdoc

    Since we have a `DefiningAnchor::Error`, we will reject registering hidden types already

commit b54d72264aebf88e1099004c52aac6e4a06affd8
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Wed Feb 21 10:38:54 2024 +0000

    Use `DefineOpaqueTypes::Yes` in diagnostics code

commit 109daa2d4bafc37b9e86a751b930aa033b7d4b14
Author: Arthur Carcano <arthur.carcano@ocamlpro.com>
Date:   Wed Apr 3 02:43:54 2024 +0200

    Fix diagnostic for qualifier in extern block

    Closes: https://github.com/rust-lang/rust/issues/123306

commit 0dca136841191074e1703ae9eccc8b15aadb643f
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Thu Apr 4 09:46:53 2024 +0000

    Try explicitly outlining the panic machinery

commit 769ab55558488d1ff786fa13e8ba1fb071a9791b
Author: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date:   Tue Apr 2 16:20:04 2024 +0000

    Add regression test

commit 398a52a8dc6aa96f2c942b24715288f4f96b9c31
Merge: e80ca2f3816 0478d26c8b3
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 09:16:44 2024 +0000

    Auto merge of #12340 - not-elm:fix/issue-12334, r=llogiq

    FIX(12334): manual_swap auto fix

    Fixed: #12334

    Initialization expressions are now generated as needed if the slice index is bound to a variable.

    ----

    changelog: Fix [`manual_swap`]

commit 4c6c6298664fff9f3549f05ba2b689bcd30b0fc7
Merge: 29fe618f750 82789763c7c
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 08:43:53 2024 +0000

    Auto merge of #115538 - lcnr:fn-def-wf, r=compiler-errors

    check `FnDef` return type for WF

    better version of #106807, fixes #84533 (mostly). It's not perfect given that we still ignore WF requirements involving bound regions but I wasn't able to quickly write an example, so even if theoretically exploitable, it should be far harder to trigger.

    This is strictly more restrictive than checking the return type for WF as part of the builtin `FnDef: FnOnce` impl (#106807) and moving to this approach in the future will not break any code.

    ~~It also agrees with my theoretical view of how this should behave~~

    r? types

commit c2e4916cf8b28404f60523f22c096652c172070d
Author: Ralf Jung <post@ralfj.de>
Date:   Tue Apr 2 08:23:38 2024 +0200

    adjust frame_in_std to recognize std tests

commit 9e35555474a40d20ebe8d29da56f2d715af21cdd
Author: Ralf Jung <post@ralfj.de>
Date:   Sat Mar 30 17:22:28 2024 +0100

    smoke-test 'x.py test --miri' on CI

commit ecc714d88ee0781192cfedcd7b717a7c0a9a4f05
Author: Ralf Jung <post@ralfj.de>
Date:   Fri Mar 29 19:18:51 2024 +0100

    fix parsing the test harness JSON when time could not be measured

commit 29fe618f750c5ff7f8fb75871e75280b569b4e67
Merge: 43f4f2a3b1a 473a70de845
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 06:40:30 2024 +0000

    Auto merge of #123052 - maurer:addr-taken, r=compiler-errors

    CFI: Support function pointers for trait methods

    Adds support for both CFI and KCFI for function pointers to trait methods by attaching both concrete and abstract types to functions.

    KCFI does this through generation of a `ReifyShim` on any function pointer for a method that could go into a vtable, and keeping this separate from `ReifyShim`s that are *intended* for vtable us by setting a `ReifyReason` on them.

    CFI does this by setting both the concrete and abstract type on every instance.

    This should land after #123024 or a similar PR, as it diverges the implementation of CFI vs KCFI.

    r? `@compiler-errors`

commit d99c775febff75f578437504fed69c9f4df5e92d
Author: lcnr <rust@lcnr.de>
Date:   Tue Apr 2 13:20:03 2024 +0200

    unconstrained `NormalizesTo` term for opaques

commit 43f4f2a3b1a3d3fb3dbbbe4fde33fb97c780ee98
Merge: 0accf4ec4c0 f090de88759
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 04:36:12 2024 +0000

    Auto merge of #119820 - lcnr:leak-check-2, r=jackh726

    instantiate higher ranked goals outside of candidate selection

    This PR modifies `evaluate` to more eagerly instantiate higher-ranked goals, preventing the `leak_check` during candidate selection from detecting placeholder errors involving that binder.

    For a general background regarding higher-ranked region solving and the leak check, see https://hackmd.io/qd9Wp03cQVy06yOLnro2Kg.

    > The first is something called the **leak check**. You can think of it as a "quick and dirty" approximation for the region check, which will come later. The leak check detects some kinds of errors early, essentially deciding between "this set of outlives constraints are guaranteed to result in an error eventually" or "this set of outlives constraints may be solvable".

    ## The ideal future

    We would like to end up with the following idealized design to handle universal binders:
    ```rust
    fn enter_forall<'tcx, T, R>(
        forall: Binder<'tcx, T>,
        f: impl FnOnce(T) -> R,
    ) -> R {
        let new_universe = infcx.increment_universe_index();
        let value = instantiate_binder_with_placeholders_in(new_universe, forall);

        let result = f(value);

        eagerly_handle_higher_ranked_region_constraints_in(new_universe);
        infcx.decrement_universe_index();

        assert!(!result.has_placeholders_in_or_above(new_universe));
        result
    }
    ```

    That is, when universally instantiating a binder, anything using the placeholders has to happen inside of a limited scope (the closure `f`). After this closure has completed, all constraints involving placeholders are known.

    We then handle any *external constraints* which name these placeholders. We destructure `TypeOutlives` constraints involving placeholders and eagerly handle any region constraints involving these placeholders. We do not return anything mentioning the placeholders created inside of this function to the caller.

    Being able to eagerly handle *all* region constraints involving placeholders will be difficult due to complex `TypeOutlives` constraints, involving inference variables or alias types, and higher ranked implied bounds. The exact issues and possible solutions are out of scope of this FCP.

    #### How does the leak check fit into this

    The `leak_check` is an underapproximation of `eagerly_handle_higher_ranked_region_constraints_in`. It detects some kinds of errors involving placeholders from `new_universe`, but not all of them.

    It only looks at region outlives constraints, ignoring `TypeOutlives`, and checks whether one of the following two conditions are met for **placeholders in or above `new_universe`**, in which case it results in an error:
    - `'!p1: '!p2` a placeholder `'!p2` outlives a different placeholder `'!p1`
    - `'!p1: '?2` an inference variable `'?2` outlives a placeholder `'!p1` *which it cannot name*

    It does not handle all higher ranked region constraints, so we still return constraints involving placeholders from `new_universe` which are then (re)checked by `lexical_region_resolve` or MIR borrowck.

    As we check higher ranked constraints in the full regionck anyways, the `leak_check` is not soundness critical. It's current only purpose is to move some higher ranked region errors earlier, enabling it to guide type inference and trait solving. Adding additional uses of the `leak_check` in the future would only strengthen inference and is therefore not breaking.

    ## Where do we use currently use the leak check

    The `leak_check` is currently used in two places:

    Coherence does not use a proper regionck, only relying on the `leak_check` called [at the end of the implicit negative overlap check](https://github.com/rust-lang/rust/blob/8b94152af68a0ed6d6af0b5ba57491e40481008e/compiler/rustc_trait_selection/src/traits/coherence.rs#L235-L238). During coherence all parameters are instantiated with inference variables, so the only possible region errors are higher-ranked. We currently also sometimes make guesses when destructuring `TypeOutlives` constraints which can theoretically result in incorrect errors. This could result in overlapping impls.

    We also use the `leak_check` [at the end of `fn evaluation_probe`](https://github.com/rust-lang/rust/blob/8b94152af68a0ed6d6af0b5ba57491e40481008e/compiler/rustc_trait_selection/src/traits/select/mod.rs#L607-L610). This function is used during candidate assembly for `Trait` goals. Most notably we use [inside of `evaluate_candidate` during winnowing](https://github.com/rust-lang/rust/blob/0e4243538b9119654c22dce688f8a63c81864de9/compiler/rustc_trait_selection/src/traits/select/mod.rs#L491-L502). Conceptionally, it is as if we compute each candidate in a separate `enter_forall`.

    ## The current use in `fn evaluation_probe` is undesirable

    Because we only instantiate a higher-ranked goal once inside of `fn evaluation_probe`, errors involving placeholders from that binder can impact selection. This results in inconsistent behavior ([playground](
    *[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=dac60ebdd517201788899ffa77364831)*)):

    ```rust
    trait Leak<'a> {}
    impl Leak<'_>      for Box<u32> {}
    impl Leak<'static> for Box<u16> {}

    fn impls_leak<T: for<'a> Leak<'a>>() {}

    trait IndirectLeak<'a> {}
    impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
    fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}

    fn main() {
        // ok
        //
        // The `Box<u16>` impls fails the leak check,
        // meaning that we apply the `Box<u32>` impl.
        impls_leak::<Box<_>>();

        // error: type annotations needed
        //
        // While the `Box<u16>` impl would fail the leak check
        // we have already instantiated the binder while applying
        // the generic `IndirectLeak` impl, so during candidate
        // selection of `Leak` we do not detect the placeholder error.
        // Evaluation of `Box<_>: Leak<'!a>` is therefore ambiguous,
        // resulting in `for<'a> Box<_>: Leak<'a>` also being ambiguous.
        impls_indirect_leak::<Box<_>>();
    }
    ```

    We generally prefer `where`-bounds over implementations during candidate selection, both for [trait goals](https://github.com/rust-lang/rust/blob/11f32b73e0dc9287e305b5b9980d24aecdc8c17f/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1863-L1887) and during [normalization](https://github.com/rust-lang/rust/blob/11f32b73e0dc9287e305b5b9980d24aecdc8c17f/compiler/rustc_trait_selection/src/traits/project.rs#L184-L198). However, we currently **do not** use the `leak_check` during candidate assembly in normalizing. This can result in inconsistent behavior:
    ```rust
    trait Trait<'a> {
        type Assoc;
    }
    impl<'a, T> Trait<'a> for T {
        type Assoc = usize;
    }

    fn trait_bound<T: for<'a> Trait<'a>>() {}
    fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}

    // A function with a trivial where-bound which is more
    // restrictive than the impl.
    fn function<T: Trait<'static, Assoc = usize>>() {
        // ok
        //
        // Proving `for<'a> T: Trait<'a>` using the where-bound results
        // in a leak check failure, so we use the more general impl,
        // causing this to succeed.
        trait_bound::<T>();

        // error
        //
        // Proving the `Projection` goal `for<'a> T: Trait<'a, Assoc = usize>`
        // does not use the leak check when trying the where-bound, causing us
        // to prefer it over the impl, resulting in a placeholder error.
        projection_bound::<T>();

        // error
        //
        // Trying to normalize the type `for<'a> fn(<T as Trait<'a>>::Assoc)`
        // only gets to `<T as Trait<'a>>::Assoc` once `'a` has been already
        // instantiated, causing us to prefer the where-bound over the impl
        // resulting in a placeholder error. Even if were were to also use the
        // leak check during candidate selection for normalization, this
        // case would still not compile.
        let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
    }
    ```

    This is also likely to be more performant. It enables more caching in the new trait solver by simply [recursively calling the canonical query][new solver] after instantiating the higher-ranked goal.

    It is also unclear how to add the leak check to normalization in the new solver. To handle https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 `Projection` goals are implemented via `AliasRelate`. This again means that we instantiate the binder before ever normalizing any alias. Even if we were to avoid this, we lose the ability to [cache normalization by itself, ignoring the expected `term`](https://github.com/rust-lang/rust/blob/5bd5d214effd494f4bafb29b3a7a2f6c2070ca5c/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs#L34-L49). We cannot replace the `term` with an inference variable before instantiating the binder, as otherwise `for<'a> T: Trait<Assoc<'a> = &'a ()>` breaks. If we only replace the term after instantiating the binder, we cannot easily evaluate the goal in a separate context, as [we'd then lose the information necessary for the leak check](https://github.com/rust-lang/rust/blob/11f32b73e0dc9287e305b5b9980d24aecdc8c17f/compiler/rustc_next_trait_solver/src/canonicalizer.rs#L230-L232). Adding this information to the canonical input also seems non-trivial.

    ## Proposed solution

    I propose to instantiate the binder outside of candidate assembly, causing placeholders from higher-ranked goals to get ignored while selecting their candidate. This mostly[^1] matches the [current behavior of the new solver][new solver]. The impact of this change is therefore as follows:

    ```rust
    trait Leak<'a> {}
    impl Leak<'_>      for Box<u32> {}
    impl Leak<'static> for Box<u16> {}

    fn impls_leak<T: for<'a> Leak<'a>>() {}

    trait IndirectLeak<'a> {}
    impl<'a, T: Leak<'a>> IndirectLeak<'a> for T {}
    fn impls_indirect_leak<T: for<'a> IndirectLeak<'a>>() {}

    fn guide_selection() {
        // ok -> ambiguous
        impls_leak::<Box<_>>();

        // ambiguous
        impls_indirect_leak::<Box<_>>();
    }

    trait Trait<'a> {
        type Assoc;
    }
    impl<'a, T> Trait<'a> for T {
        type Assoc = usize;
    }

    fn trait_bound<T: for<'a> Trait<'a>>() {}
    fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}

    // A function which a trivial where-bound which is more
    // restrictive than the impl.
    fn function<T: Trait<'static, Assoc = usize>>() {
        // ok -> error
        trait_bound::<T>();

        // error
        projection_bound::<T>();

        // error
        let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
    }
    ```

    This does not change the behavior if candidates have higher ranked nested goals, as in this case the `leak_check` causes the nested goal to result in an error ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=a74c25300b23db9022226de99d8a2fa6)):
    ```rust
    trait LeakCheckFailure<'a> {}
    impl LeakCheckFailure<'static> for () {}

    trait Trait<T> {}
    impl Trait<u32> for () where for<'a> (): LeakCheckFailure<'a> {}
    impl Trait<u16> for () {}
    fn impls_trait<T: Trait<U>, U>() {}
    fn main() {
        // ok
        //
        // It does not matter whether candidate assembly
        // considers the placeholders from higher-ranked goal.
        //
        // Either `for<'a> (): LeakCheckFailure<'a>` has no
        // applicable candidate or it has a single applicable candidate
        // when then later results in an error. This allows us to
        // infer `U` to `u16`.
        impls_trait::<(), _>()
    }
    ```

    ## Impact on existing crates

    This is a **breaking change**. [A crater run](https://github.com/rust-lang/rust/pull/119820#issuecomment-1926862174) found 17 regressed crates with 7 root causes.

    For a full analysis of all affected crates, see https://gist.github.com/lcnr/7c1c652f30567048ea240554a36ed95c.

    ---

    I believe this breakage to be acceptable and would merge this change. I am confident that the new position of the leak check matches our idealized future and cannot envision any other consistent alternative. Where possible, I intend to open PRs fixing/avoiding the regressions before landing this PR.

    I originally intended to remove the `coherence_leak_check` lint in the same PR. However, while I am confident in the *position* of the leak check, deciding on its exact behavior is left as future work, cc #112999. This PR therefore only moves the leak check while keeping the lint when relying on it in coherence.

    [new solver]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs#L479-L484

    [^1]: the new solver has a separate cause of inconsistent behavior rn https://github.com/rust-lang/trait-system-refactor-initiative/issues/53#issuecomment-1914310171

    r? `@nikomatsakis`

commit b0b7c860e13858cbc344dcf2baf860752e3a2dd3
Author: Ben Kimock <kimockb@gmail.com>
Date:   Thu Apr 4 00:10:01 2024 -0400

    Teach MIR inliner query cycle avoidance about const_eval_select

commit 0accf4ec4c07d23aa86f6a97aeb8797941abc30e
Merge: b4acbe4233b 4332498a6da
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 02:11:23 2024 +0000

    Auto merge of #123440 - jhpratt:rollup-yat6crk, r=jhpratt

    Rollup of 4 pull requests

    Successful merges:

     - #122356 (std::rand: fix dragonflybsd after #121942.)
     - #123093 (Add a nice header to our README.md)
     - #123307 (Fix f16 and f128 feature gating on different editions)
     - #123401 (Check `x86_64` size assertions on `aarch64`, too)

    r? `@ghost`
    `@rustbot` modify labels: rollup

commit 82789763c7c5c09c6b0481d18cf00ef67b4b6fa3
Author: Boxy <supbscripter@gmail.com>
Date:   Thu Apr 4 02:14:52 2024 +0100

    rebase

commit 2b67f0104a9fcdb3a6aa41bceb33e62e609e6b6c
Author: lcnr <rust@lcnr.de>
Date:   Mon Sep 4 17:35:51 2023 +0200

    check `FnDef` return type for WF

commit e5376f3947ba8faf0f7c3a9543366060d662357d
Author: Jules Bertholet <julesbertholet@quoi.xyz>
Date:   Wed Apr 3 20:35:02 2024 -0400

    Address final nits

commit 4332498a6daff23e4403d9bce43d97ed63cad382
Merge: 819568a7b41 2d47cd77ac7
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Wed Apr 3 20:17:06 2024 -0400

    Rollup merge of #123401 - Zalathar:assert-size-aarch64, r=fmease

    Check `x86_64` size assertions on `aarch64`, too

    (Context: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Checking.20size.20assertions.20on.20aarch64.3F)

    Currently the compiler has around 30 sets of `static_assert_size!` for various size-critical data structures (e.g. various IR nodes), guarded by `#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]`.

    (Presumably this cfg avoids having to maintain separate size values for 32-bit targets and unusual 64-bit targets. Apparently it may have been necessary before the i128/u128 alignment changes, too.)

    This is slightly incovenient for people on aarch64 workstations (e.g. Macs), because the assertions normally aren't checked until we push to a PR. So this PR adds `aarch64` to the `#[cfg(..)]` guarding all of those assertions in the compiler.

    ---

    Implemented with a simple find/replace. Verified by manually inspecting each `static_assert_size!` in `compiler/`, and checking that either the replacement succeeded, or adding aarch64 wouldn't have been appropriate.

commit 819568a7b41cf5b453df675b41569b311216460c
Merge: c8cd010616d 5afe072ead1
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Wed Apr 3 20:17:05 2024 -0400

    Rollup merge of #123307 - tgross35:f16-f128-feature-gate-fix, r=petrochenkov

    Fix f16 and f128 feature gating on different editions

    Apply the fix from https://github.com/rust-lang/rust/issues/123282#issuecomment-2035063388 to correctly gates `f16` and `f128` in editions other than 2015

commit c8cd010616d9dfa49864527388e7c065937e94c9
Merge: 875d2547500 ce4cc9df960
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Wed Apr 3 20:17:05 2024 -0400

    Rollup merge of #123093 - Urgau:improve-readme, r=workingjubilee

    Add a nice header to our README.md

    This PR improves our README, it is greatly inspired by [esbuild](https://github.com/evanw/esbuild/blob/9d1777f23d9b64c186345223d92f319e59388d8b/README.md) README.

    Context: As was reading https://johnjago.com/great-docs/ I though we could greatly improve ours. So that's what I did.

    It provides direct "quick-access" links to pages in rust-lang.org.

    The "Why Rust?" section is ~~a direct copy/paste of the same~~ modified version of section in [rust-lang.org](https://www.rust-lang.org/).

    | Before | After |
    |--------|-------|
    | ![before](https://github.com/rust-lang/rust/assets/3616612/4afb6753-18a9-4881-919e-2a79328beb5a) | ![after](https://github.com/rust-lang/rust/assets/3616612/408dea7b-5d97-4bb8-a77e-35541ddd50cb) <details> ![after](https://github.com/rust-lang/rust/assets/3616612/76e4a8c6-b61c-46e8-b5ba-4f09c13cfc94) </details> <details> ![after -1](https://github.com/rust-lang/rust/assets/3616612/ed50675c-8301-457c-8b9a-a1199c515fb7) </details> |

    Note: I removed the manual TOC, since GitHub provides it's own at the top right corner and I don't think it's needed anymore.
    Same for the notice about the readme being for users, it's now clear enough and that notice was distracting anyway.

commit 875d2547500f9c588c0537ab12672b4cf844eca4
Merge: 4fd4797c265 6a16638de64
Author: Jacob Pratt <jacob@jhpratt.dev>
Date:   Wed Apr 3 20:17:04 2024 -0400

    Rollup merge of #122356 - devnexen:dfbsd_build_fix, r=jhpratt

    std::rand: fix dragonflybsd after #121942.

commit b4acbe4233b97ec51605c513ce6b215470574f80
Merge: 4fd4797c265 bd8ca780a51
Author: bors <bors@rust-lang.org>
Date:   Thu Apr 4 00:09:02 2024 +0000

    Auto merge of #123240 - compiler-errors:assert-args-compat, r=fmease

    Assert that args are actually compatible with their generics, rather than just their count

    Right now we just check that the number of args is right, rather than actually checking the kinds. Uplift a helper fn that I wrote from trait selection to do just that. Found a couple bugs along the way.

    r? `@lcnr` or `@fmease` (or anyone really lol)

commit e08fdb0f2fcb4cabb430b0512331bb781b4ea653
Author: Zalathar <Zalathar@users.noreply.github.com>
Date:   Thu Apr 4 11:04:32 2024 +1100

    coverage: Remove useless constants

commit f6b97ef5e567f9893cd58b6fd00fee033593bd59
Author: Zalathar <Zalathar@users.noreply.github.com>
Date:   Thu Apr 4 10:55:20 2024 +1100

    Manually run `clang-format` on `CoverageMappingWrapper.cpp`

commit f090de88759ed9abc65074ff9926e03a3d550d77
Author: Boxy <supbscripter@gmail.com>
Date:   Wed Apr 3 22:48:48 2024 +0100

    rebase oddity

commit f029602920638d0f73488e2517ce7547d287a14b
Author: Michael Goulet <michael@errs.io>
Date:   Wed Apr 3 17:41:03 2024 -0400

    Tests for getting parent of synthetic HIR

commit 4fa5fb684e891978303db0b8f100fab1e19eb06d
Author: lcnr <rust@lcnr.de>
Date:   Wed Apr 3 22:27:13 2024 +0100

    move leak check out of candidate evaluation

    this prevents higher ranked goals from guiding selection

commit e2ebaa1a08aff195487cd7afacdaf7fb0ef62aa7
Author: Nadrieril <nadrieril+git@gmail.com>
Date:   Wed Apr 3 21:17:36 2024 +0200

    Add `if let` tests

commit fbc56dfac13ba6fb81bca6439e120a9c554c3a57
Author: Slanterns <slanterns.w@gmail.com>
Date:   Thu Apr 4 05:04:27 2024 +0800

    Stabilize `Literal::c_string`

commit 61ac7812c65601695460a1ab6a4999d35efb66cc
Author: Slanterns <slanterns.w@gmail.com>
Date:   Thu Apr 4 05:00:49 2024 +0800

    Stabilize `Literal::byte_character`

commit 4fd4797c2654977f545c9a91e2aa4e6cdbb38919
Merge: 98efd808e1b 65398c46b82
Author: bors <bors@rust-lang.org>
Date:   Wed Apr 3 20:19:51 2024 +0000

    Auto merge of #123429 - matthiaskrgr:rollup-4emw4e9, r=matthiaskrgr

    Rollup of 8 pull requests

    Successful merges:

     - #121595 (Better reporting on generic argument mismatchs)
     - #122619 (Fix some unsoundness with PassMode::Cast ABI)
     - #122964 (Rename `expose_addr` to `expose_provenance`)
     - #123291 (Move some tests)
     - #123301 (pattern analysis: fix union handling)
     - #123395 (More postfix match fixes)
     - #123419 (rustc_index: Add a `ZERO` constant to index types)
     - #123421 (Fix target name in NetBSD platform-support doc)

    r? `@ghost`
    `@rustbot` modify labels: rollup

commit 6728f2fef4286d7060feb7667b5da9ef3f512e34
Merge: b0710dc5f5b 46fc398706d
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Wed Apr 3 22:11:02 2024 +0200

    Rollup merge of #123419 - petrochenkov:zeroindex, r=compiler-errors

    rustc_index: Add a `ZERO` constant to index types

    It is commonly used.

commit 65398c46b8207fb36d85bdab1ff2d68c38f0e3a4
Merge: 25b0e841705 6edb021fd36
Author: Matthias Krüger <matthias.krueger@famsik.de>
Date:   Wed Apr 3 22:11:02 2024 +0200

    Rollup me…
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 23, 2024
stabilize `-Znext-solver=coherence`

r? `@compiler-errors`

---

This PR stabilizes the use of the next generation trait solver in coherence checking by enabling `-Znext-solver=coherence` by default. More specifically its use in the *implicit negative overlap check*. The tracking issue for this is rust-lang#114862.

## Background

### The next generation trait solver

The new solver lives in [`rustc_trait_selection::solve`](https://github.com/rust-lang/rust/blob/master/compiler/rustc_trait_selection/src/solve/mod.rs) and is intended to replace the existing *evaluate*, *fulfill*, and *project* implementation. It also has a wider impact on the rest of the type system, for example by changing our approach to handling associated types.

For a more detailed explanation of the new trait solver, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/solve/trait-solving.html). This does not stabilize the current behavior of the new trait solver, only the behavior impacting the implicit negative overlap check. There are many areas in the new solver which are not yet finalized. We are confident that their final design will not conflict with the user-facing behavior observable via coherence. More on that further down.

Please check out [the chapter](https://rustc-dev-guide.rust-lang.org/solve/significant-changes.html) summarizing the most significant changes between the existing and new implementations.

### Coherence and the implicit negative overlap check

Coherence checking detects any overlapping impls. Overlapping trait impls always error while overlapping inherent impls result in an error if they have methods with the same name. Coherence also results in an error if any other impls could exist, even if they are currently unknown. This affects impls which may get added to upstream crates in a backwards compatible way and impls from downstream crates.

Coherence failing to detect overlap is generally considered to be unsound, even if it is difficult to actually get runtime UB this way. It is quite easy to get ICEs due to bugs in coherence.

It currently consists of two checks:

The [orphan check] validates that impls do not overlap with other impls we do not know about: either because they may be defined in a sibling crate, or because an upstream crate is allowed to add it without being considered a breaking change.

The [overlap check] validates that impls do not overlap with other impls we know about. This is done as follows:
- Instantiate the generic parameters of both impls with inference variables
- Equate the `TraitRef`s of both impls. If it fails there is no overlap.
- [implicit negative]: Check whether any of the instantiated `where`-bounds of one of the impls definitely do not hold when using the constraints from the previous step. If a `where`-bound does not hold, there is no overlap.
- *explicit negative (still unstable, ignored going forward)*: Check whether the any negated `where`-bounds can be proven, e.g. a `&mut u32: Clone` bound definitely does not hold as an explicit `impl<T> !Clone for &mut T` exists.

The overlap check has to *prove that unifying the impls does not succeed*. This means that **incorrectly getting a type error during coherence is unsound** as it would allow impls to overlap: coherence has to be *complete*.

Completeness means that we never incorrectly error. This means that during coherence we must only add inference constraints if they are definitely necessary. During ordinary type checking [this does not hold](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=01d93b592bd9036ac96071cbf1d624a9), so the trait solver has to behave differently, depending on whether we're in coherence or not.

The implicit negative check only considers goals to "definitely not hold" if they could not be implemented downstream, by a sibling, or upstream in a backwards compatible way. If the goal is is "unknowable" as it may get added in another crate, we add an ambiguous candidate: [source](https://github.com/rust-lang/rust/blob/bea5bebf3defc56e5e3446b4a95c685dbb885fd3/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L858-L883).

[orphan check]: https://github.com/rust-lang/rust/blob/fd80c02c168c2dfbb82c29d2617f524d2723205b/compiler/rustc_trait_selection/src/traits/coherence.rs#L566-L579
[overlap check]: https://github.com/rust-lang/rust/blob/fd80c02c168c2dfbb82c29d2617f524d2723205b/compiler/rustc_trait_selection/src/traits/coherence.rs#L92-L98
[implicit negative]: https://github.com/rust-lang/rust/blob/fd80c02c168c2dfbb82c29d2617f524d2723205b/compiler/rustc_trait_selection/src/traits/coherence.rs#L223-L281

## Motivation

Replacing the existing solver in coherence fixes soundness bugs by removing sources of incompleteness in the type system. The new solver separately strengthens coherence, resulting in more impls being disjoint and passing the coherence check. The concrete changes will be elaborated further down. We believe the stabilization to reduce the likelihood of future bugs in coherence as the new implementation is easier to understand and reason about.

It allows us to remove the support for coherence and implicit-negative reasoning in the old solver, allowing us to remove some code and simplifying the old trait solver. We will only remove the old solver support once this stabilization has reached stable to make sure we're able to quickly revert in case any unexpected issues are detected before then.

Stabilizing the use of the next-generation trait solver expresses our confidence that its current behavior is intended and our work towards enabling its use everywhere will not require any breaking changes to the areas used by coherence checking. We are also confident that we will be able to replace the existing solver everywhere, as maintaining two separate systems adds a significant maintainance burden.

## User-facing impact and reasoning

### Breakage due to improved handling of associated types

The new solver fixes multiple issues related to associated types. As these issues caused coherence to consider more types distinct, fixing them results in more overlap errors. This is therefore a breaking change.

#### Structurally relating aliases containing bound vars

Fixes rust-lang#102048. In the existing solver relating ambiguous projections containing bound variables is structural. This is *incomplete* and allows overlapping impls. These was mostly not exploitable as the same issue also caused impls to not apply when trying to use them. The new solver defers alias-relating to a nested goal, fixing this issue:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Trait {}

trait Project {
    type Assoc<'a>;
}

impl Project for u32 {
    type Assoc<'a> = &'a u32;
}

// Eagerly normalizing `<?infer as Project>::Assoc<'a>` is ambiguous,
// so the old solver ended up structurally relating
//
//     (?infer, for<'a> fn(<?infer as Project>::Assoc<'a>))
//
// with
//
//     ((u32, fn(&'a u32)))
//
// Equating `&'a u32` with `<u32 as Project>::Assoc<'a>` failed, even
// though these types are equal modulo normalization.
impl<T: Project> Trait for (T, for<'a> fn(<T as Project>::Assoc<'a>)) {}

impl<'a> Trait for (u32, fn(&'a u32)) {}
//[next]~^ ERROR conflicting implementations of trait `Trait` for type `(u32, for<'a> fn(&'a u32))`
```

A crater run did not discover any breakage due to this change.

#### Unknowable candidates for higher ranked trait goals

This avoids an unsoundness by attempting to normalize in `trait_ref_is_knowable`: rust-lang#114061. This is a side-effect of supporting lazy normalization, as that forces us to attempt to normalize when checking whether a `TraitRef` is knowable: [source](https://github.com/rust-lang/rust/blob/47dd709bedda8127e8daec33327e0a9d0cdae845/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L754-L764).

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait IsUnit {}
impl IsUnit for () {}

pub trait WithAssoc<'a> {
    type Assoc;
}

// We considered `for<'a> <T as WithAssoc<'a>>::Assoc: IsUnit`
// to be knowable, even though the projection is ambiguous.
pub trait Trait {}
impl<T> Trait for T
where
    T: 'static,
    for<'a> T: WithAssoc<'a>,
    for<'a> <T as WithAssoc<'a>>::Assoc: IsUnit,
{
}
impl<T> Trait for Box<T> {}
//[next]~^ ERROR conflicting implementations of trait `Trait`
```
The two impls of `Trait` overlap given the following downstream crate:
```rust
use dep::*;
struct Local;
impl WithAssoc<'_> for Box<Local> {
    type Assoc = ();
}
```

There a similar coherence unsoundness caused by our handling of aliases which is fixed separately in rust-lang#117164.

### Evaluating goals to a fixpoint and applying inference constraints

In the old implementation of the implicit-negative check, each obligation is [checked separately without applying its inference constraints](https://github.com/rust-lang/rust/blob/bea5bebf3defc56e5e3446b4a95c685dbb885fd3/compiler/rustc_trait_selection/src/traits/coherence.rs#L323-L338). The new solver instead [uses a `FulfillmentCtxt`](https://github.com/rust-lang/rust/blob/bea5bebf3defc56e5e3446b4a95c685dbb885fd3/compiler/rustc_trait_selection/src/traits/coherence.rs#L315-L321) for this, which evaluates all obligations in a loop until there's no further inference progress.

This is necessary for backwards compatibility as we do not eagerly normalize with the new solver, resulting in constraints from normalization to only get applied by evaluating a separate obligation. This also allows more code to compile:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Mirror {
    type Assoc;
}
impl<T> Mirror for T {
    type Assoc = T;
}

trait Foo {}
trait Bar {}

// The self type starts out as `?0` but is constrained to `()`
// due to the where-clause below. Because `(): Bar` is known to
// not hold, we can prove the impls disjoint.
impl<T> Foo for T where (): Mirror<Assoc = T> {}
//[current]~^ ERROR conflicting implementations of trait `Foo` for type `()`
impl<T> Foo for T where T: Bar {}

fn main() {}
```
The old solver does not run nested goals to a fixpoint in evaluation. The new solver does do so, strengthening inference and improving the overlap check:
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait Foo {}
impl<T> Foo for (u8, T, T) {}
trait NotU8 {}
trait Bar {}
impl<T, U: NotU8> Bar for (T, T, U) {}

trait NeedsFixpoint {}
impl<T: Foo + Bar> NeedsFixpoint for T {}
impl NeedsFixpoint for (u8, u8, u8) {}

trait Overlap {}
impl<T: NeedsFixpoint> Overlap for T {}
impl<T, U: NotU8, V> Overlap for (T, U, V) {}
//[current]~^ ERROR conflicting implementations of trait `Foo`
```

### Breakage due to removal of incomplete candidate preference

Fixes rust-lang#107887. In the old solver we incompletely prefer the builtin trait object impl over user defined impls. This can break inference guidance, inferring `?x` in `dyn Trait<u32>: Trait<?x>` to `u32`, even if an explicit impl of `Trait<u64>` also exists.

This caused coherence to incorrectly allow overlapping impls, resulting in ICEs and a theoretical unsoundness. See rust-lang#107887 (comment). This compiles on stable but results in an overlap error with `-Znext-solver=coherence`:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
struct W<T: ?Sized>(*const T);

trait Trait<T: ?Sized> {
    type Assoc;
}

// This would trigger the check for overlap between automatic and custom impl.
// They actually don't overlap so an impl like this should remain possible
// forever.
//
// impl Trait<u64> for dyn Trait<u32> {}
trait Indirect {}
impl Indirect for dyn Trait<u32, Assoc = ()> {}
impl<T: Indirect + ?Sized> Trait<u64> for T {
    type Assoc = ();
}

// Incomplete impl where `dyn Trait<u32>: Trait<_>` does not hold, but
// `dyn Trait<u32>: Trait<u64>` does.
trait EvaluateHack<U: ?Sized> {}
impl<T: ?Sized, U: ?Sized> EvaluateHack<W<U>> for T
where
    T: Trait<U, Assoc = ()>, // incompletely constrains `_` to `u32`
    U: IsU64,
    T: Trait<U, Assoc = ()>, // incompletely constrains `_` to `u32`
{
}

trait IsU64 {}
impl IsU64 for u64 {}

trait Overlap<U: ?Sized> {
    type Assoc: Default;
}
impl<T: ?Sized + EvaluateHack<W<U>>, U: ?Sized> Overlap<U> for T {
    type Assoc = Box<u32>;
}
impl<U: ?Sized> Overlap<U> for dyn Trait<u32, Assoc = ()> {
//[next]~^ ERROR conflicting implementations of trait `Overlap<_>`
    type Assoc = usize;
}
```

### Considering region outlives bounds in the `leak_check`

For details on the `leak_check`, see the FCP proposal in rust-lang#119820.[^leak_check]

[^leak_check]: which should get moved to the dev-guide once that PR lands :3

In both coherence and during candidate selection, the `leak_check` relies on the region constraints added in `evaluate`. It therefore currently does not register outlives obligations: [source](https://github.com/rust-lang/rust/blob/ccb1415eac3289b5ebf64691c0190dc52e0e3d0e/compiler/rustc_trait_selection/src/traits/select/mod.rs#L792-L810). This was likely done as a performance optimization without considering its impact on the `leak_check`. This is the case as in the old solver, *evaluatation* and *fulfillment* are split, with evaluation being responsible for candidate selection and fulfillment actually registering all the constraints.

This split does not exist with the new solver. The `leak_check` can therefore eagerly detect errors caused by region outlives obligations. This improves both coherence itself and candidate selection:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
trait LeakErr<'a, 'b> {}
// Using this impl adds an `'b: 'a` bound which results
// in a higher-ranked region error. This bound has been
// previously ignored but is now considered.
impl<'a, 'b: 'a> LeakErr<'a, 'b> for () {}

trait NoOverlapDir<'a> {}
impl<'a, T: for<'b> LeakErr<'a, 'b>> NoOverlapDir<'a> for T {}
impl<'a> NoOverlapDir<'a> for () {}
//[current]~^ ERROR conflicting implementations of trait `NoOverlapDir<'_>`

// --------------------------------------

// necessary to avoid coherence unknowable candidates
struct W<T>(T);

trait GuidesSelection<'a, U> {}
impl<'a, T: for<'b> LeakErr<'a, 'b>> GuidesSelection<'a, W<u32>> for T {}
impl<'a, T> GuidesSelection<'a, W<u8>> for T {}

trait NotImplementedByU8 {}
trait NoOverlapInd<'a, U> {}
impl<'a, T: GuidesSelection<'a, W<U>>, U> NoOverlapInd<'a, U> for T {}
impl<'a, U: NotImplementedByU8> NoOverlapInd<'a, U> for () {}
//[current]~^ conflicting implementations of trait `NoOverlapInd<'_, _>`
```

### Removal of `fn match_fresh_trait_refs`

The old solver tries to [eagerly detect unbounded recursion](https://github.com/rust-lang/rust/blob/b14fd2359f47fb9a14bbfe55359db4bb3af11861/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1196-L1211), forcing the affected goals to be ambiguous. This check is only an approximation and has not been added to the new solver.

The check is not necessary in the new solver and it would be problematic for caching. As it depends on all goals currently on the stack, using a global cache entry would have to always make sure that doing so does not circumvent this check.

This changes some goals to error - or succeed - instead of failing with ambiguity. This allows more code to compile:

```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence

// Need to use this local wrapper for the impls to be fully
// knowable as unknowable candidate result in ambiguity.
struct Local<T>(T);

trait Trait<U> {}
// This impl does not hold, but is ambiguous in the old
// solver due to its overflow approximation.
impl<U> Trait<U> for Local<u32> where Local<u16>: Trait<U> {}
// This impl holds.
impl Trait<Local<()>> for Local<u8> {}

// In the old solver, `Local<?t>: Trait<Local<?u>>` is ambiguous,
// resulting in `Local<?u>: NoImpl`, also being ambiguous.
//
// In the new solver the first impl does not apply, constraining
// `?u` to `Local<()>`, causing `Local<()>: NoImpl` to error.
trait Indirect<T> {}
impl<T, U> Indirect<U> for T
where
    T: Trait<U>,
    U: NoImpl
{}

// Not implemented for `Local<()>`
trait NoImpl {}
impl NoImpl for Local<u8> {}
impl NoImpl for Local<u16> {}

// `Local<?t>: Indirect<Local<?u>>` cannot hold, so
// these impls do not overlap.
trait NoOverlap<U> {}
impl<T: Indirect<U>, U> NoOverlap<U> for T {}
impl<T, U> NoOverlap<Local<U>> for Local<T> {}
//~^ ERROR conflicting implementations of trait `NoOverlap<Local<_>>`
```

### Non-fatal overflow

The old solver immediately emits a fatal error when hitting the recursion limit. The new solver instead returns overflow. This both allows more code to compile and is results in performance and potential future compatability issues.

Non-fatal overflow is generally desirable. With fatal overflow, changing the order in which we evaluate nested goals easily causes breakage if we have goal which errors and one which overflows. It is also required to prevent breakage due to the removal of `fn match_fresh_trait_refs`, e.g. [in `typenum`](rust-lang/trait-system-refactor-initiative#73).

#### Enabling more code to compile

In the below example, the old solver first tried to prove an overflowing goal, resulting in a fatal error. The new solver instead returns ambiguity due to overflow for that goal, causing the implicit negative overlap check to succeed as `Box<u32>: NotImplemented` does not hold.
```rust
// revisions: current next
//[next] compile-flags: -Znext-solver=coherence
//[current] ERROR overflow evaluating the requirement

trait Indirect<T> {}
impl<T: Overflow<()>> Indirect<T> for () {}

trait Overflow<U> {}
impl<T, U> Overflow<U> for Box<T>
where
    U: Indirect<Box<Box<T>>>,
{}

trait NotImplemented {}

trait Trait<U> {}
impl<T, U> Trait<U> for T
where
    // T: NotImplemented, // causes old solver to succeed
    U: Indirect<T>,
    T: NotImplemented,
{}

impl Trait<()> for Box<u32> {}
```

#### Avoiding hangs with non-fatal overflow

Simply returning ambiguity when reaching the recursion limit can very easily result in hangs, e.g.
```rust
trait Recur {}
impl<T, U> Recur for ((T, U), (U, T))
where
    (T, U): Recur,
    (U, T): Recur,
{}

trait NotImplemented {}
impl<T: NotImplemented> Recur for T {}
```
This can happen quite frequently as it's easy to have exponential blowup due to multiple nested goals at each step. As the trait solver is depth-first, this immediately caused a fatal overflow error in the old solver. In the new solver we have to handle the whole proof tree instead, which can very easily hang.

To avoid this we restrict the recursion depth after hitting the recursion limit for the first time. We also **ignore all inference constraints from goals resulting in overflow**. This is mostly backwards compatible as any overflow in the old solver resulted in a fatal error.

### sidenote about normalization

We return ambiguous nested goals of `NormalizesTo` goals to the caller and ignore their impact when computing the `Certainty` of the current goal. See the [normalization chapter](https://rustc-dev-guide.rust-lang.org/solve/normalization.html) for more details.This means we apply constraints resulting from other nested goals and from equating the impl header when normalizing, even if a nested goal results in overflow. This is necessary to avoid breaking the following example:
```rust
trait Trait {
    type Assoc;
}

struct W<T: ?Sized>(*mut T);
impl<T: ?Sized> Trait for W<W<T>>
where
    W<T>: Trait,
{
    type Assoc = ();
}

// `W<?t>: Trait<Assoc = u32>` does not hold as
// `Assoc` gets normalized to `()`. However, proving
// the where-bounds of the impl results in overflow.
//
// For this to continue to compile we must not discard
// constraints from normalizing associated types.
trait NoOverlap {}
impl<T: Trait<Assoc = u32>> NoOverlap for T {}
impl<T: ?Sized> NoOverlap for W<T> {}
```

#### Future compatability concerns

Non-fatal overflow results in some unfortunate future compatability concerns. Changing the approach to avoid more hangs by more strongly penalizing overflow can cause breakage as we either drop constraints or ignore candidates necessary to successfully compile. Weakening the overflow penalities instead allows more code to compile and strengthens inference while potentially causing more code to hang.

While the current approach is not perfect, we believe it to be good enough. We believe it to apply the necessary inference constraints to avoid breakage and expect there to not be any desirable patterns broken by our current penalities. Similarly we believe the current constraints to avoid most accidental hangs. Ignoring constraints of overflowing goals is especially useful, as it may allow major future optimizations to our overflow handling. See [this summary](https://hackmd.io/ATf4hN0NRY-w2LIVgeFsVg) and the linked documents in case you want to know more.

### changes to performance

In general, trait solving during coherence checking is not significant for performance. Enabling the next-generation trait solver in coherence does not impact our compile time benchmarks. We are still unable to compile the benchmark suite when fully enabling the new trait solver.

There are rare cases where the new solver has significantly worse performance due to non-fatal overflow, its reliance on fixpoint algorithms and the removal of the `fn match_fresh_trait_refs` approximation. We encountered such issues in [`typenum`](https://crates.io/crates/typenum) and believe it should be [pretty much as bad as it can get](rust-lang/trait-system-refactor-initiative#73).

Due to an improved structure and far better caching, we believe that there is a lot of room for improvement and that the new solver will outperform the existing implementation in nearly all cases, sometimes significantly. We have not yet spent any time micro-optimizing the implementation and have many unimplemented major improvements, such as fast-paths for trivial goals.

TODO: get some rough results here and put them in a table

### Unstable features

#### Unsupported unstable features

The new solver currently does not support all unstable features, most notably `#![feature(generic_const_exprs)]`, `#![feature(associated_const_equality)]` and `#![feature(adt_const_params)]` are not yet fully supported in the new solver. We are confident that supporting them is possible, but did not consider this to be a priority. This stabilization introduces new ICE when using these features in impl headers.

#### fixes to `#![feature(specialization)]`

- fixes rust-lang#105782
- fixes rust-lang#118987

#### fixes to `#![feature(type_alias_impl_trait)]`

- fixes rust-lang#119272
- rust-lang#105787 (comment)

## This does not stabilize the whole solver

While this stabilizes the use of the new solver in coherence checking, there are many parts of the solver which will remain fully unstable. We may still adapt these areas while working towards stabilizing the new solver everywhere. We are confident that we are able to do so without negatively impacting coherence.

### goals with a non-empty `ParamEnv`

Coherence always uses an empty environment. We therefore do not depend on the behavior of `AliasBound` and `ParamEnv` candidates. We only stabilizes the behavior of user-defined and builtin implementations of traits. There are still many open questions there.

### opaque types in the defining scope

The handling of opaque types - `impl Trait` - in both the new and old solver is still not fully figured out. Luckily this can be ignored for now. While opaque types are reachable during coherence checking by using `impl_trait_in_associated_types`, the behavior during coherence is separate and self-contained. The old and new solver fully agree here.

### normalization is hard

This stabilizes that we equate associated types involving bound variables using deferred-alias-equality. We also stop eagerly normalizing in coherence, which should not have any user-facing impact.

We do not stabilize the normalization behavior outside of coherence, e.g. we currently deeply normalize all types during writeback with the new solver. This may change going forward

### how to replace `select` from the old solver

We sometimes depend on getting a single `impl` for a given trait bound, e.g. when resolving a concrete method for codegen/CTFE. We do not depend on this during coherence, so the exact approach here can still be freely changed going forward.

## Acknowledgements

This work would not have been possible without `@compiler-errors.` He implemented large chunks of the solver himself but also and did a lot of testing and experimentation, eagerly discovering multiple issues which had a significant impact on our approach. `@BoxyUwU` has also done some amazing work on the solver. Thank you for the endless hours of discussion resulting in the current approach. Especially the way aliases are handled has gone through multiple revisions to get to its current state.

There were also many contributions from - and discussions with - other members of the community and the rest of `@rust-lang/types.` This solver builds upon previous improvements to the compiler, as well as lessons learned from `chalk` and `a-mir-formality`. Getting to this point  would not have been possible without that and I am incredibly thankful to everyone involved. See the [list of relevant PRs](https://github.com/rust-lang/rust/pulls?q=is%3Apr+is%3Amerged+label%3AWG-trait-system-refactor+-label%3Arollup+closed%3A%3C2024-03-22+).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-testsuite Area: The testsuite used to check the correctness of rustc disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. merged-by-bors This PR was explicitly merged by bors. needs-fcp This change is insta-stable, so needs a completed FCP to proceed. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet