Commit Graph

44170 Commits

Author SHA1 Message Date
bendn
c39f33baae
stabilize extract_if 2025-02-23 21:11:12 +07:00
Jacob Pratt
d41520052e
Rollup merge of #137458 - compiler-errors:render-fn, r=fmease
Fix missing self subst when rendering `impl Fn*<T>` with no output type

r? `@fmease` or reassign

Fixes #133597
cc #137456
2025-02-23 02:44:20 -05:00
Jacob Pratt
f5c6287d76
Rollup merge of #137448 - compiler-errors:control-flow-oops, r=scottmcm
Fix bugs due to unhandled `ControlFlow` in compiler

Well, one bug and one nit.
2025-02-23 02:44:20 -05:00
Jacob Pratt
da493c91d6
Rollup merge of #137435 - estebank:match-arm-2, r=compiler-errors
Fix "missing match arm body" suggestion involving `!`

Include the match arm guard in the gated span, so that the suggestion to add a body is correct instead of inserting the body before the guard.

Make the suggestion verbose.

```
error: `match` arm with no body
  --> $DIR/feature-gate-never_patterns.rs:43:9
   |
LL |         Some(_) if false,
   |         ^^^^^^^^^^^^^^^^
   |
help: add a body after the pattern
   |
LL |         Some(_) if false => { todo!() },
   |                          ++++++++++++++
```

r? `@compiler-errors`
2025-02-23 02:44:19 -05:00
Jacob Pratt
4bed9eca0e
Rollup merge of #137423 - Urgau:imprv-pretty-hir, r=compiler-errors
Improve a bit HIR pretty printer

This PR improve (a bit) the HIR pretty printer.

It does so by:
 - Not printing elided lifetimes (those are not expressible in surface Rust anyway)
 - And by rendering implicit self with the shorthand syntax

I also tried fixing some indentation and other things but gave up for now.

Best reviewed commit by commit.
2025-02-23 02:44:19 -05:00
Jacob Pratt
7f14d2eba4
Rollup merge of #137334 - compiler-errors:edition-2024-fresh-2, r=saethlin,traviscross
Greatly simplify lifetime captures in edition 2024

Remove most of the `+ Captures` and `+ '_` from the compiler, since they are now unnecessary with the new edition 2021 lifetime capture rules. Use some `+ 'tcx` and `+ 'static` rather than being overly verbose with precise capturing syntax.
2025-02-23 02:44:18 -05:00
Michael Goulet
431b9aa38f Fix missing self subst when rendering Fn* trait with no output type 2025-02-23 04:46:51 +00:00
Michael Goulet
04c453c4bc Fix bugs due to unhandled ControlFlow 2025-02-22 23:56:14 +00:00
Matthias Krüger
e780b89959
Rollup merge of #137415 - chenyukang:yukang-fix-137345-invalid-sugg, r=estebank
Remove invalid suggestion of into_iter for extern macro

Fixes #137345

#109082 is closed due to performance issue, do we have any other solution for this kind of issue?
2025-02-23 00:16:21 +01:00
Matthias Krüger
86008eaeac
Rollup merge of #137256 - workingjubilee:untangle-vector-abi-assumptions, r=bjorn3,RalfJung
compiler: untangle SIMD alignment assumptions

There were a number of puzzling assumptions being made about SIMD types and their layout that I have corrected in this diff. These are mostly no-op edits in actual fact, but they do subtly alter a pair of checks in our invariant-checking and union layout computation that rested on those peculiar assumptions. Those unfortunately stand in the way of any further actual fixes. I submit this for review, even though it's not clearly motivated without its followups, because it should still be possible to independently conclude whether this is correct.
2025-02-23 00:16:19 +01:00
Matthias Krüger
4115f51d15
Rollup merge of #137180 - compiler-errors:sym-regions, r=oli-obk
Give `global_asm` a fake body to store typeck results, represent `sym fn` as a hir expr to fix `sym fn` operands with lifetimes

There are a few intertwined problems with `sym fn` operands in both inline and global asm macros.

Specifically, unlike other anon consts, they may evaluate to a type with free regions in them without actually having an item-level type annotation to give them a "proper" type. This is in contrast to named constants, which always have an item-level type annotation, or unnamed constants which are constrained by their position (e.g. a const arg in a turbofish, or a const array length).

Today, we infer the type of the operand by looking at the HIR typeck results; however, those results are region-erased, so during borrowck we ICE since we don't expect to encounter erased regions. We can't just fill this type with something like `'static`, since we may want to use real (free) regions:

```rust
fn foo<'a>() {
  asm!("/* ... */", sym bar::<&'a ()>);
}
```

The first idea may be to represent `sym fn` operands using *inline* consts instead of anon consts. This makes sense, since inline consts can reference regions from the parent body (like the `'a` in the example above). However, this introduces a problem with `global_asm!`, which doesn't *have* a parent body; inline consts *must* be associated with a parent body since they are not a body owner of their own. In #116087, I attempted to fix this by using two separate `sym` operands for global and inline asm. However, this led to a lot of confusion and also some unattractive code duplication.

In this PR, I adjust the lowering of `global_asm!` so that it's lowered in a "fake" HIR body. This body contains a single expression which is `ExprKind::InlineAsm`; we don't *use* this HIR body, but it's used in typeck and borrowck so that we can properly infer and validate the the lifetimes of `sym fn` operands.

I then adjust the lowering of `sym fn` to instead be represented with a HIR expression. This is both because it's no longer necessary to represent this operand as an anon const, since it's *just* a path expression, and also more importantly to sidestep yet another ICE (https://github.com/rust-lang/rust/issues/137179), which has to do with the existing code breaking an invariant of def-id creation and anon consts. Specifically, we are not allowed to synthesize a def-id for an anon const when that anon const contains expressions with def-ids whose parent is *not* that anon const. This is somewhat related to https://github.com/rust-lang/rust/pull/130443#issuecomment-2445678945, which is also a place in the compiler where synthesizing anon consts leads to def-id parenting issue.

As a side-effect, this consolidates the type checking for inline and global asm, so it allows us to simplify `InlineAsmCtxt` a bit. It also allows us to delete a bit of hacky code from anon const `type_of` which was there to detect `sym fn` operands specifically. This also could be generalized to support `const` asm operands with types with lifetimes in them. Since we specifically reject these consts today, I'm not going to change the representation of those consts (but they'd just be turned into inline consts).

r? oli-obk -- mostly b/c you're patient and also understand the breadth of the code that this touches, please reassign if you don't want to review this.

Fixes #111709
Fixes #96304
Fixes #137179
2025-02-23 00:16:19 +01:00
Matthias Krüger
929423a4f0
Rollup merge of #137121 - bend-n:master, r=Noratrieb
stabilize `(const_)ptr_sub_ptr`

Tracking issue: #95892
Closes #95892
FCP Completed: https://github.com/rust-lang/rust/issues/95892#issuecomment-2561139730

r? ````@Noratrieb````
2025-02-23 00:16:18 +01:00
Matthias Krüger
1610bfb6af
Rollup merge of #135501 - tgross35:stdlib-dependencies-private, r=bjorn3
Inject `compiler_builtins` during postprocessing and ensure it is made private

Follow up of https://github.com/rust-lang/rust/pull/135278

Do the following:

* Inject `compiler_builtins` during postprocessing, rather than injecting `extern crate compiler_builtins as _` into the AST
* Do not make dependencies of `std` private by default (this was added in #135278)
* Make sure sysroot crates correctly mark their dependencies private/public
* Ensure that marking a dependency private makes its dependents private by default as well, unless otherwise specified
* Do the `compiler_builtins` update that has been blocked on this

There is more detail in the commit messages. This includes the changes I was working on in https://github.com/rust-lang/rust/pull/136226.

try-job: test-various
try-job: x86_64-msvc-1
try-job: x86_64-msvc-2
try-job: i686-mingw-1
try-job: i686-mingw-2
2025-02-23 00:16:18 +01:00
Michael Goulet
12e3911d81 Greatly simplify lifetime captures in edition 2024 2025-02-22 22:24:52 +00:00
Esteban Küber
a8f8b8de66 Fix "missing match arm body" suggestion involving !
Include the match arm guard in the gated span, so that the suggestion to add a body is correct instead of inserting the body before the guard.

Make the suggestion verbose.

```
error: `match` arm with no body
  --> $DIR/feature-gate-never_patterns.rs:43:9
   |
LL |         Some(_) if false,
   |         ^^^^^^^^^^^^^^^^
   |
help: add a body after the pattern
   |
LL |         Some(_) if false => { todo!() },
   |                          ++++++++++++++
```
2025-02-22 18:30:14 +00:00
Urgau
d0e7bfd205 Render implicit self with their shorthand syntax in HIR pretty printing 2025-02-22 17:12:19 +01:00
Urgau
46154c9b09 Filter elided lifetimes in HIR pretty printing 2025-02-22 17:12:19 +01:00
bors
15469f8f8a Auto merge of #137420 - matthiaskrgr:rollup-rr0q37f, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #136910 (Implement feature `isolate_most_least_significant_one` for integer types)
 - #137183 (Prune dead regionck code)
 - #137333 (Use `edition = "2024"` in the compiler (redux))
 - #137356 (Ferris 🦀 Identifier naming conventions)
 - #137362 (Add build step log for `run-make-support`)
 - #137377 (Always allow reusing cratenum in CrateLoader::load)
 - #137388 (Fix(lib/fs/tests): Disable rename POSIX semantics FS tests under Windows 7)
 - #137410 (Use StableHasher + Hash64 for dep_tracking_hash)
 - #137413 (jubilee cleared out the review queue)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-02-22 13:32:44 +00:00
Matthias Krüger
1066af5b1a
Rollup merge of #137410 - saethlin:stable-dep-tracking-hash, r=workingjubilee
Use StableHasher + Hash64 for dep_tracking_hash

This is similar to https://github.com/rust-lang/rust/pull/137095. We currently have a +/- 1 byte jitter in the size of dep graphs reported on perf.rust-lang.org. I think this fixes that jitter.

When I introduced `Hash64`, I wired it through most of the compiler by making it an output of `StableHasher::finalize` then fixing the compile errors. I missed this case because the `u64` hash in this function is being produced by `DefaultHasher` instead. That seems pretty sketchy because the code seems confident that the hash needs to be stable, and we have a mechanism for stable hashing that we weren't using here.
2025-02-22 11:36:46 +01:00
Matthias Krüger
f13feb34dc
Rollup merge of #137377 - bjorn3:crate_loader_cleanup, r=compiler-errors
Always allow reusing cratenum in CrateLoader::load

The only case where can_reuse_cratenum could have been false in the past are rustc plugins, support for which has been removed over a year ago now. Nowadays the only case where locator.tuple is not target_triple is when loading a proc macro, in which case we also set can_reuse_cratenum to true. As such it is always true and we can remove some dead code.
2025-02-22 11:36:45 +01:00
Matthias Krüger
72e41e5d65
Rollup merge of #137356 - nik-rev:FERRIS, r=compiler-errors
Ferris 🦀 Identifier naming conventions

You cannot use Ferris as an identifier in Rust, this code will suggest to correct the  🦀 to `ferris`:

```rs
fn main() {
  let  🦀 = 4;
}
```

But it also suggests to correct to `ferris` in these cases, too:

```rs
struct  🦀 {}
fn main() {}
```

^ suggests: `ferris`
~ with this PR: `Ferris`

```rs
static 🦀: &str = "ferris!";
fn main() {}
```

^ suggests: `ferris`
~ with this PR: `FERRIS`

This is my first pull requests here!
2025-02-22 11:36:44 +01:00
Matthias Krüger
37e0d138cf
Rollup merge of #137333 - compiler-errors:edition-2024-fresh, r=Nadrieril
Use `edition = "2024"` in the compiler (redux)

Most of this is binding mode changes, which I fixed by running `x.py fix`.

Also adds some miscellaneous `unsafe` blocks for new unsafe standard library functions (the setenv ones), and a missing `unsafe extern` block in some enzyme codegen code, and fixes some precise capturing lifetime changes (but only when they led to errors).

cc ``@ehuss`` ``@traviscross``
2025-02-22 11:36:43 +01:00
Matthias Krüger
72535fec55
Rollup merge of #137183 - compiler-errors:dead-regionck-code, r=lcnr
Prune dead regionck code

We never encounter `ObligationCauseCode`s that correspond to region obligations that originate from "within" a body, since we don't do HIR regionck anymore on bodies. So prune some dead code.
2025-02-22 11:36:42 +01:00
bors
8dac72bb1d Auto merge of #136428 - EnzymeAD:enable-autodiff, r=oli-obk
test building enzyme in CI

1) This PR fixes a significant compile-time regression, by only running the expensive autodiff pipeline, if the users pass the newly introduced Enable value to the `-Zautodiff=` flag. It updates the test(s) accordingly. It gives a nice error if users forget that.
2) It fixes macos support by explicitly linking against the Enzyme build folder. This doesn't cover CI macos yet.
3) It fixes the issue that setting ENZYME_RUNPASS was ignored by enzyme and in fact did not schedule enzyme's opt pass.
4) It also re-enables support for various other values for the autodiff flag, which were ignored since the refactor.
5) I merged some improvements to Enzyme core, which means we do not longer depend on LLVM being build with the Plugin Interface enabled.
6) Unrelated to other fixes, this changes `rustc_autodiff` to `EncodeCrossCrate::Yes`. It is not enough on it's own to enable usage of Enzyme in libraries, but it is for sure a piece of the fixes needed to get this to work.

try-job: x86_64-gnu

r? `@oli-obk`

Tracking:

- https://github.com/rust-lang/rust/issues/124509
2025-02-22 10:30:06 +00:00
bors
b6d3be4948 Auto merge of #133436 - nnethercote:rm-NtVis-NtTy, r=petrochenkov
Remove `NtVis` and `NtTy`

The next part of #124141. The first actual remove of `Nonterminal` variants. `NtVis` is a simple case that doesn't get much use, but `NtTy` is more complex.

r? `@petrochenkov`
2025-02-22 06:09:14 +00:00
yukang
c45463ec8b remove invalid suggestion of into_iter for extern macro 2025-02-22 13:30:41 +08:00
bors
b87eda7fdf Auto merge of #137406 - matthiaskrgr:rollup-9nknrsb, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #136458 (Do not deduplicate list of associated types provided by dyn principal)
 - #136474 ([`compiletest`-related cleanups 3/7] Make the distinction between sources root vs test suite sources root in compiletest less confusing)
 - #136592 (Make sure we don't overrun the stack in canonicalizer)
 - #136787 (Remove `lifetime_capture_rules_2024` feature)
 - #137207 (Add #[track_caller] to Duration Div impl)
 - #137245 (Tweak E0277 when predicate comes indirectly from ?)
 - #137257 (Ignore fake borrows for packed field check)
 - #137399 (fix ICE in layout computation with unnormalizable const)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-02-22 03:05:26 +00:00
Manuel Drehwald
49e9630641 enable rustc_autodiff cross-crate encoding 2025-02-21 21:53:31 -05:00
Manuel Drehwald
e2d250c3f6 update autodiff flags 2025-02-21 21:51:20 -05:00
Manuel Drehwald
161a4bf6ff update enzyme submodule and users 2025-02-21 21:49:46 -05:00
Manuel Drehwald
f4e2218b13 clean up autodiff code/comments 2025-02-21 21:47:48 -05:00
Manuel Drehwald
fe90883ef7 fix build regressions 2025-02-21 21:45:29 -05:00
Ben Kimock
fd451dc057 Use StableHasher + Hash64 for dep_tracking_hash 2025-02-21 21:36:58 -05:00
Michael Goulet
3d5438accd Fix binding mode problems 2025-02-22 00:13:19 +00:00
Michael Goulet
6ba39f7dc7 Make a fake body to store typeck results for global_asm 2025-02-22 00:12:07 +00:00
Michael Goulet
37060aae13 Initial cleanups of InlineAsmCtxt 2025-02-22 00:05:09 +00:00
Michael Goulet
2a6daaf89a Make asm a named field 2025-02-22 00:05:09 +00:00
Michael Goulet
b2b2e53916 Even more dead code -- we don't HIR regionck anymore 2025-02-22 00:02:56 +00:00
Michael Goulet
9001e55302 More dead code 2025-02-22 00:02:11 +00:00
Michael Goulet
681c95c55c Remove UnifyReceiver cause code 2025-02-22 00:02:11 +00:00
Michael Goulet
e1819a889a Fix overcapturing, unsafe extern blocks, and new unsafe ops 2025-02-22 00:01:48 +00:00
Michael Goulet
7f6873f64c Fix builtin lints 2025-02-22 00:01:48 +00:00
Michael Goulet
76d341fa09 Upgrade the compiler to edition 2024 2025-02-22 00:01:48 +00:00
Matthias Krüger
6352044269
Rollup merge of #137399 - lukas-code:oopsie-woopsie, r=compiler-errors
fix ICE in layout computation with unnormalizable const

The first commit reverts half of 7a667d206c, where I removed a case from `layout_of` for handling non-generic unevaluated consts in array length, that I incorrectly assumed to be unreachable. This can actually happen with the combination of `feature(generic_const_exprs)` and `feature(trivial_bounds)`, because GCE makes anon consts inherit their parent's predicates and with an impossible predicate like `u8: A` it's possible to have an array whose length is an associated const like `<u8 as A>::B` that is not generic, but also can't be normalized:

```rust
#![feature(generic_const_exprs)]
#![feature(trivial_bounds)]

trait A {
    const B: usize;
}

// With GCE + trivial bounds this definition is not a compile error.
// Computing the layout of this type shouldn't ICE.
struct S([u8; <u8 as A>::B])
where
    u8: A;
```

---

The first commit also incidentally fixes https://github.com/rust-lang/rust/issues/137308, which also managed to get an unnormalizable assoc const into an array length:

```rust
trait A {
    const B: usize;
}

impl<C: ?Sized> A for u8 { //~ ERROR: the type parameter `C` is not constrained
    const B: usize = 42;
}

// Computing the layout of this type shouldn't ICE, even with the compile error above.
struct S([u8; <u8 as A>::B]);
```

This happens, because we bail out from `codegen_select_candidate` with an error if the selected impl has unconstrained params to avoid leaking infer vars out of a query. `Instance::try_resolve` will then return `Ok(None)`, which for assoc consts roughly means "this const can't be evaluated in a generic context" and is treated as such: 71e06b9c59/compiler/rustc_middle/src/mir/interpret/queries.rs (L84) (and this can ICE if the const isn't generic: https://github.com/rust-lang/rust/issues/135617).

However, here `<u8 as A>::B` is definitely not "too generic" and also not unresolvable due to an unsatisfiable `u8: A` bound, so I've included the second commit to change the result of `Instance::try_resolve` from `Ok(None)` to `Err(ErrorGuaranteed)` when resolving an assoc item to an impl with unconstrained generic params. This has the effect that `<u8 as A>::B` will now be normalized to `ConstKind::Error` in the example above.

This properly fixes https://github.com/rust-lang/rust/issues/137308, by no longer treating `<u8 as A>::B` as unresolvable even though it clearly has a unique impl that it resolves to. It also has the effect of changing the layout error from `Unknown` ("the type may be valid but has no sensible layout") to `ReferencesError` ("a non-layout error is reported elsewhere") which seems more appropriate.

r? ```@compiler-errors```
2025-02-22 01:01:42 +01:00
Matthias Krüger
fa62fbe4b8
Rollup merge of #137257 - compiler-errors:fake-borrow-of-packed-field, r=oli-obk
Ignore fake borrows for packed field check

We should not emit unaligned packed field reference errors for the fake borrows that we generate during match lowering.

These fake borrows are there to ensure in *borrow-checking* that we don't modify the value being matched (which is why this only occurs when there's a match guard, in this case `if true`), but they are removed after the MIR is processed by `CleanupPostBorrowck`, since they're really just there to cause borrowck errors if necessary.

I modified `PlaceContext::is_borrow` since that's used by the packed field check:
17c1c329a5/compiler/rustc_mir_transform/src/check_packed_ref.rs (L40)

It's only used in one other place, in the SROA optimization (by which fake borrows are removed, so it doesn't matter):
17c1c329a5/compiler/rustc_mir_dataflow/src/value_analysis.rs (L922)

Fixes https://github.com/rust-lang/rust/issues/137250
2025-02-22 01:01:41 +01:00
Matthias Krüger
890c4d2e26
Rollup merge of #137245 - estebank:from-residual-note-2, r=oli-obk
Tweak E0277 when predicate comes indirectly from ?

When a `?` operation requires an `Into` conversion with additional bounds (like having a concrete error but wanting to convert to a trait object), we handle it speficically and provide the same kind of information we give other `?` related errors.

```
error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied
  --> $DIR/bad-question-mark-on-trait-object.rs:7:13
   |
LL | fn foo() -> Result<(), Box<dyn std::error::Error>> {
   |             -------------------------------------- required `E: std::error::Error` because of this
LL |     Ok(bar()?)
   |        -----^ the trait `std::error::Error` is not implemented for `E`
   |        |
   |        this has type `Result<_, E>`
   |
note: `E` needs to implement `std::error::Error`
  --> $DIR/bad-question-mark-on-trait-object.rs:1:1
   |
LL | struct E;
   | ^^^^^^^^
   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
   = note: required for `Box<dyn std::error::Error>` to implement `From<E>`
```

Avoid talking about `FromResidual` when other more relevant information is being given, particularly from `rust_on_unimplemented`.

Fix #137238.

-----

CC #137232, which was a smaller step related to this.
2025-02-22 01:01:41 +01:00
Matthias Krüger
085adfda3c
Rollup merge of #136787 - compiler-errors:lt2024feat, r=oli-obk
Remove `lifetime_capture_rules_2024` feature

Just use edition 2024 instead
2025-02-22 01:01:40 +01:00
Matthias Krüger
7f1089efdf
Rollup merge of #136592 - compiler-errors:ensure-stack-in-canonical, r=lcnr
Make sure we don't overrun the stack in canonicalizer

r? lcnr

Addresses https://github.com/rust-lang/trait-system-refactor-initiative/issues/160
2025-02-22 01:01:39 +01:00
Matthias Krüger
326072ac20
Rollup merge of #136458 - compiler-errors:fix-3, r=lcnr
Do not deduplicate list of associated types provided by dyn principal

## Background

The way that we handle a dyn trait type's projection bounds is very *structural* today. A dyn trait is represented as a list of `PolyExistentialPredicate`s, which in most cases will be a principal trait (like `Iterator`) and a list of projections (like `Item = u32`). Importantly, the list of projections comes from user-written associated type bounds on the type *and* from elaborating the projections from the principal's supertraits.

For example, given a set of traits like:

```rust
trait Foo<T> {
    type Assoc;
}

trait Bar<A, B>: Foo<A, Assoc = A> + Foo<B, Assoc = B> {}
```

For the type `dyn Bar<i32, u32>`, the list of projections will be something like `[Foo<i32>::Assoc = i32, Foo<u32>::Assoc = u32]`. We deduplicate these projections when they're identical, so for `dyn Bar<(), ()>` would be something like `[Foo<()>::Assoc = ()]`.

## Shortcomings 1: inference

We face problems when we begin to mix this structural notion of projection bounds with inference and associated type normalization. For example, let's try calling a generic function that takes `dyn Bar<A, B>` with a value of type `dyn Bar<(), ()>`:

```rust
trait Foo<T> {
    type Assoc;
}

trait Bar<A, B>: Foo<A, Assoc = A> + Foo<B, Assoc = B> {}

fn call_bar<A, B>(_: &dyn Bar<A, B>) {}

fn test(x: &dyn Bar<(), ()>) {
    call_bar(x);
    // ^ ERROR mismatched types
}
```

```
error[E0308]: mismatched types
  --> /home/mgx/test.rs:10:14
   |
10 |     call_bar(x);
   |     -------- ^ expected trait `Bar<_, _>`, found trait `Bar<(), ()>`
```

What's going on here? Well, when calling `call_bar`, the generic signature `&dyn Bar<?A, ?B>` does not unify with `&dyn Bar<(), ()>` because the list of projections differ -- `[Foo<?A>::Assoc = ?A, Foo<?B>::Assoc = ?B]` vs `[Foo<()>::Assoc = ()]`.

A simple solution to this may be to unify the principal traits first, then attempt to deduplicate them after inference. In this case, if we constrain `?A = ?B = ()`, then we would be able to deduplicate those projections in the first list.

However, this idea is still pretty fragile, and it's not a complete solution.

## Shortcomings 2: normalization

Consider a slightly modified example:

```rust
//@ compile-flags: -Znext-solver

trait Mirror {
    type Assoc;
}
impl<T> Mirror for T {
    type Assoc = T;
}

fn call_bar(_: &dyn Bar<(), <() as Mirror>::Assoc>) {}

fn test(x: &dyn Bar<(), ()>) {
    call_bar(x);
}
```

This fails in the new solver. In this example, we try to unify `dyn Bar<(), ()>` and `dyn Bar<(), <() as Mirror>::Assoc>`. We are faced with the same problem even though there are no inference variables, and making this work relies on eagerly and deeply normalizing all projections so that they can be structurally deduplicated.

This is incompatible with how we handle associated types in the new trait solver, and while we could perhaps support it with some major gymnastics in the new solver, it suggests more fundamental shortcomings with how we deal with projection bounds in the new solver.

## Shortcomings 3: redundant projections

Consider a final example:

```rust
trait Foo {
    type Assoc;
}

trait Bar: Foo<Assoc = ()> {}

fn call_bar1(_: &dyn Bar) {}

fn call_bar2(_: &dyn Bar<Assoc = ()>) {}

fn main() {
    let x: &dyn Bar<Assoc = _> = todo!();
    call_bar1(x);
    //~^ ERROR mismatched types
    call_bar2(x);
    //~^ ERROR mismatched types
}
```

In this case, we have a user-written associated type bound (`Assoc = _`) which overlaps the bound that comes from the supertrait projection of `Bar` (namely, `Foo<Assoc = ()>`). In a similar way to the two examples above, this causes us to have a projection list mismatch that the compiler is not able to deduplicate.

## Solution

### Do not deduplicate after elaborating projections when lowering `dyn` types

The root cause of this issue has to do with mismatches of the deduplicated projection list before and after substitution or inference. This PR aims to avoid these issues by *never* deduplicating the projection list after elaborating the list of projections from the *identity* substituted principal trait ref.

For example,

```rust
trait Foo<T> {
    type Assoc;
}

trait Bar<A, B>: Foo<A, Assoc = A> + Foo<B, Assoc = B> {}
```

When computing the projections for `dyn Bar<(), ()>`, before this PR we'd elaborate `Bar<(), ()>` to find a (deduplicated) projection list of `[Foo<()>::Assoc = ()]`.

After this PR, we take the principal trait and use its *identity* substitutions `Bar<A, B>` during elaboration, giving us projections `[Foo<A>::Assoc = A, Foo<B>::Assoc = B]`. Only after this elaboration do we substitute `A = (), B = ()` to get `[Foo<()>::Assoc = (), Foo<()>::Assoc = ()]`. This allows the type to be unified with the projections for `dyn Bar<?A, ?B>`, which are `[Foo<?A>::Assoc = ?A, Foo<?B>::Assoc = ?B]`.

This helps us avoid shorcomings 1 noted above.

### Do not deduplicate projections when relating `dyn` types

Similarly, we also do not call deduplicate when relating dyn types. This means that the list of projections does not differ depending on if the type has been normalized or not, which should avoid shortcomings 2 noted above.

Following from the example above, when relating projection lists like `[Foo<()>::Assoc = (), Foo<()>::Assoc = ()]` and `[Foo<?A>::Assoc = ?A, Foo<?B>::Assoc = ?B]`, the latter won't be deduplicated to a list of length 1 which would immediately fail to relate to the latter which is a list of length 2.

### Implement proper precedence between supertrait and user-written projection bounds when lowering `dyn` types

```rust
trait Foo {
    type Assoc;
}

trait Bar: Foo<Assoc = ()> {}
```

Given a type like `dyn Foo<Assoc = _>`, we used to previously include *both* the supertrait and user-written associated type bounds in the projection list, giving us `[Foo::Assoc = (), Foo::Assoc = _]`. This would never unify with `dyn Foo`. However, this PR implements a strategy which overwrites the supertrait associated type bound with the one provided by the user, giving us a projection list of `[Foo::Assoc = _]`.

Why is this OK? Well, if a user wrote an associated type bound that is unsatisfiable (e.g. `dyn Bar<Assoc = i32>`) then the dyn type would never implement `Bar` or `Foo` anyways. If the user wrote something that is either structurally equal or equal modulo normalization to the supertrait bound, then it should be unaffected. And if the user wrote something that needs inference guidance (e.g. `dyn Bar<Assoc = _>`), then it'll be constrained when proving `dyn Bar<Assoc = _>: Bar`.

Importantly, this differs from the strategy in https://github.com/rust-lang/rust/pull/133397, which preferred the *supertrait* bound and ignored the user-written bound. While that's also theoretically justifiable in its own way, it does lead to code which does not (and probably should not) compile either today or after this PR, like:

```rust
trait IteratorOfUnit: Iterator<Item = ()> {}
impl<T> IteratorOfUnit for T where T: Iterator<Item = ()> {}

fn main() {
    let iter = [()].into_iter();
    let iter: &dyn IteratorOfUnit<Item = i32> = &iter;
}
```

### Conclusion

This is a far less invasive change compared to #133397, and doesn't necessarily necessitate the addition of new lints or any breakage of existing code. While we could (and possibly should) eventually introduce lints to warn users of redundant or mismatched associated type bounds, we don't *need* to do so as part of fixing this unsoundness, which leads me to believe this is a much safer solution.
2025-02-22 01:01:38 +01:00
bors
dc37ff82e8 Auto merge of #137348 - compiler-errors:span-trim, r=estebank
More sophisticated span trimming for suggestions

Previously #136958 only cared about prefixes or suffixes. Now it detects more cases where a suggestion is "sandwiched" by unchanged code on the left or the right. Would be cool if we could detect several insertions, like `ACE` going to `ABCDE`, extracting `B` and `D`, but that seems unwieldy.

r? `@estebank`
2025-02-21 23:59:08 +00:00