Use proper type when applying deref adjustment in const
When applying a deref adjustment to some type `Wrap<T>` which derefs to `T`, we were checking that `T: ~const Deref`, not `Wrap<T>: ~const Deref` like we should have been.
r? project-const-traits
Fixes#136273Fixes#135210 -- I just deleted the test since the regression test is uninteresting
Manually walk into WF obligations in `BestObligation` proof tree visitor
When we encounter a `WellFormed` obligation in the `BestObligation` proof tree visitor, ignore the proof tree and call `wf::unnormalized_obligations` to derive well-formed obligations with the correct cause codes. This is to avoid having to replicate the somewhat delicate logic that `wf.rs` does to set up its obligation causes... Don't see a better way to do this.
vibes?? r? lcnr
Make it so more type-system types can be printed in a shortened version (like `Predicate`s).
Centralize printing the information about the "full type name path".
Make the "long type path" for the file where long types are written part of `Diag`, so that it becomes easier to keep track of it, and ensure it will always will be printed out last in the diagnostic by making its addition to the output implicit.
Tweak the shortening of types in "expected/found" labels.
Remove dead file `note.rs`.
Provide a new function `listify`, meant to be used in cases similar to `pluralize!`. When you have a slice of arbitrary elements that need to be presented to the user, `listify` allows you to turn that into a list of comma separated strings.
This reduces a lot of redundant logic that happens often in diagnostics.
Insert null checks for pointer dereferences when debug assertions are enabled
Similar to how the alignment is already checked, this adds a check
for null pointer dereferences in debug mode. It is implemented similarly
to the alignment check as a `MirPass`.
This inserts checks in the same places as the `CheckAlignment` pass and additionally
also inserts checks for `Borrows`, so code like
```rust
let ptr: *const u32 = std::ptr::null();
let val: &u32 = unsafe { &*ptr };
```
will have a check inserted on dereference. This is done because null references
are UB. The alignment check doesn't cover these places, because in `&(*ptr).field`,
the exact requirement is that the final reference must be aligned. This is something to
consider further enhancements of the alignment check.
For now this is implemented as a separate `MirPass`, to make it easy to disable
this check if necessary.
This is related to a 2025H1 project goal for better UB checks in debug
mode: https://github.com/rust-lang/rust-project-goals/pull/177.
r? `@saethlin`
Replace our `LLVMRustDIBuilderRef` with LLVM-C's `LLVMDIBuilderRef`
Inspired by trying to split #134009 into smaller steps that are easier to review individually.
This makes it possible to start incrementally replacing our debuginfo bindings with the ones in the LLVM-C API, all of which operate on `LLVMDIBuilderRef`.
There should be no change to compiler behaviour.
Compiler: Finalize dyn compatibility renaming
Update the Reference link to use the new URL fragment from https://github.com/rust-lang/reference/pull/1666 (this change has finally hit stable). Fixes a FIXME.
Follow-up to #130826.
Part of #130852.
~~Blocking it on #133372.~~ (merged)
r? ghost
Similar to how the alignment is already checked, this adds a check
for null pointer dereferences in debug mode. It is implemented similarly
to the alignment check as a MirPass.
This is related to a 2025H1 project goal for better UB checks in debug
mode: https://github.com/rust-lang/rust-project-goals/pull/177.
Rollup of 8 pull requests
Successful merges:
- #135414 (Stabilize `const_black_box`)
- #136150 (ci: use windows 2025 for i686-mingw)
- #136258 (rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 11))
- #136270 (Remove `NamedVarMap`.)
- #136278 (add constraint graph to polonius MIR dump)
- #136287 (LLVM changed the nocapture attribute to captures(none))
- #136291 (some test suite cleanups)
- #136296 (float::min/max: mention the non-determinism around signed 0)
r? `@ghost`
`@rustbot` modify labels: rollup
Autodiff Upstreaming - rustc_codegen_ssa, rustc_middle
This PR should not be merged until the rustc_codegen_llvm part is merged.
I will also alter it a little based on what get's shaved off from the cg_llvm PR,
and address some of the feedback I received in the other PR (including cleanups).
I am putting it already up to
1) Discuss with `@jieyouxu` if there is more work needed to add tests to this and
2) Pray that there is someone reviewing who can tell me why some of my autodiff invocations get lost.
Re 1: My test require fat-lto. I also modify the compilation pipeline. So if there are any other llvm-ir tests in the same compilation unit then I will likely break them. Luckily there are two groups who currently have the same fat-lto requirement for their GPU code which I have for my autodiff code and both groups have some plans to enable support for thin-lto. Once either that work pans out, I'll copy it over for this feature. I will also work on not changing the optimization pipeline for functions not differentiated, but that will require some thoughts and engineering, so I think it would be good to be able to run the autodiff tests isolated from the rest for now. Can you guide me here please?
For context, here are some of my tests in the samples folder: https://github.com/EnzymeAD/rustbook
Re 2: This is a pretty serious issue, since it effectively prevents publishing libraries making use of autodiff: https://github.com/EnzymeAD/rust/issues/173. For some reason my dummy code persists till the end, so the code which calls autodiff, deletes the dummy, and inserts the code to compute the derivative never gets executed. To me it looks like the rustc_autodiff attribute just get's dropped, but I don't know WHY? Any help would be super appreciated, as rustc queries look a bit voodoo to me.
Tracking:
- https://github.com/rust-lang/rust/issues/124509
r? `@jieyouxu`
When encountering unexpected closure return type, point at return type/expression
```
error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to be a closure that returns `()`, but it returns `!`
--> $DIR/fallback-closure-wrap.rs:19:9
|
LL | let error = Closure::wrap(Box::new(move || {
| -------
LL | panic!("Can't connect to server.");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `!`
|
= note: expected unit type `()`
found type `!`
= note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box<dyn FnMut()>`
```
```
error[E0271]: expected `{closure@dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10}` to be a closure that returns `bool`, but it returns `Option<()>`
--> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:16
|
LL | call(|| -> Option<()> {
| ---- ------^^^^^^^^^^
| | |
| | expected `bool`, found `Option<()>`
| required by a bound introduced by this call
|
= note: expected type `bool`
found enum `Option<()>`
note: required by a bound in `call`
--> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:3:25
|
LL | fn call(_: impl Fn() -> bool) {}
| ^^^^ required by this bound in `call`
```
```
error[E0271]: expected `{closure@f670.rs:28:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
--> f670.rs:28:20
|
28 | let c = |e| -> ! {
| -------^
| |
| expected `Result<(), _>`, found `!`
...
32 | f().or_else(c);
| ------- required by a bound introduced by this call
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:1433:28
|
= note: expected enum `Result<(), _>`
found type `!`
note: required by a bound in `Result::<T, E>::or_else`
--> /home/gh-estebank/rust/library/core/src/result.rs:1406:39
|
1406 | pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
| ^^^^^^^^^^^^ required by this bound in `Result::<T, E>::or_else`
```
CC #111539.
add constraint graph to polonius MIR dump
Another easy one while I work on diagnostics. This PR adds a mermaid visualization of the polonius constraint graph to the polonius MIR dump.
Adding kills is left to a future PR (until they're encoded in edges directly or I set up recording debugging info in and out of the analysis), because right now they're only computed during traversal.
[Here's](https://gistpreview.github.io/?096b0131e8258f9a3125c55c7ac369bc) how that looks.
r? `@matthewjasper` but as always feel free to reroll.
Remove `NamedVarMap`.
`NamedVarMap` is extremely similar to `ResolveBoundVars`. The former contains two `UnordMap<ItemLocalId, T>` fields (obscured behind `ItemLocalMap` typedefs). The latter contains two
`SortedMap<ItemLocalId, T>` fields. We construct a `NamedVarMap` and then convert it into a `ResolveBoundVars` by sorting the `UnordMap`s, which is unnecessary busywork.
This commit removes `NamedVarMap` and constructs a `ResolveBoundVars` directly. `SortedMap` and `NamedVarMap` have slightly different perf characteristics during construction (e.g. speed of insertion) but this code isn't hot enough for that to matter.
A few details to note.
- A `FIXME` comment is removed.
- The detailed comments on the fields of `NamedVarMap` are copied to `ResolveBoundVars` (which has a single, incorrect comment).
- `BoundVarContext::map` is renamed.
- `ResolveBoundVars` gets a derived `Default` impl.
r? `@jackh726`
Stabilize `const_black_box`
This has been unstably const since #92226, but a tracking issue was never created. Per [discussion on Zulip][zulip], there should not be any blockers to making this const-stable. The function does not provide any functionality at compile time but does allow code reuse between const- and non-const functions, so stabilize it here.
[zulip]: https://rust-lang.zulipchat.com/#narrow/channel/146212-t-compiler.2Fconst-eval/topic/const_black_box
It's a function that prints numbers with underscores inserted for
readability (e.g. "1_234_567"), used by `-Zmeta-stats` and
`-Zinput-stats`. It's the only thing in `rustc_middle::util::common`,
which is a bizarre location for it.
This commit:
- moves it to `rustc_data_structures`, a more logical crate for it;
- puts it in a module `thousands`, like the similar crates.io crate;
- renames it `format_with_underscores`, which is a clearer name;
- rewrites it to be more concise;
- slightly improves the testing.
It's a function that does stuff with MIR and yet it weirdly has its own
module in `rustc_middle::util`. This commit moves it into
`rustc_middle::mir`, a more sensible home.
Fix deduplication mismatches in vtables leading to upcasting unsoundness
We currently have two cases where subtleties in supertraits can trigger disagreements in the vtable layout, e.g. leading to a different vtable layout being accessed at a callsite compared to what was prepared during unsizing. Namely:
### #135315
In this example, we were not normalizing supertraits when preparing vtables. In the example,
```
trait Supertrait<T> {
fn _print_numbers(&self, mem: &[usize; 100]) {
println!("{mem:?}");
}
}
impl<T> Supertrait<T> for () {}
trait Identity {
type Selff;
}
impl<Selff> Identity for Selff {
type Selff = Selff;
}
trait Middle<T>: Supertrait<()> + Supertrait<T> {
fn say_hello(&self, _: &usize) {
println!("Hello!");
}
}
impl<T> Middle<T> for () {}
trait Trait: Middle<<() as Identity>::Selff> {}
impl Trait for () {}
fn main() {
(&() as &dyn Trait as &dyn Middle<()>).say_hello(&0);
}
```
When we prepare `dyn Trait`, we see a supertrait of `Middle<<() as Identity>::Selff>`, which itself has two supertraits `Supertrait<()>` and `Supertrait<<() as Identity>::Selff>`. These two supertraits are identical, but they are not duplicated because we were using structural equality and *not* considering normalization. This leads to a vtable layout with two trait pointers.
When we upcast to `dyn Middle<()>`, those two supertraits are now the same, leading to a vtable layout with only one trait pointer. This leads to an offset error, and we call the wrong method.
### #135316
This one is a bit more interesting, and is the bulk of the changes in this PR. It's a bit similar, except it uses binder equality instead of normalization to make the compiler get confused about two vtable layouts. In the example,
```
trait Supertrait<T> {
fn _print_numbers(&self, mem: &[usize; 100]) {
println!("{mem:?}");
}
}
impl<T> Supertrait<T> for () {}
trait Trait<T, U>: Supertrait<T> + Supertrait<U> {
fn say_hello(&self, _: &usize) {
println!("Hello!");
}
}
impl<T, U> Trait<T, U> for () {}
fn main() {
(&() as &'static dyn for<'a> Trait<&'static (), &'a ()>
as &'static dyn Trait<&'static (), &'static ()>)
.say_hello(&0);
}
```
When we prepare the vtable for `dyn for<'a> Trait<&'static (), &'a ()>`, we currently consider the PolyTraitRef of the vtable as the key for a supertrait. This leads two two supertraits -- `Supertrait<&'static ()>` and `for<'a> Supertrait<&'a ()>`.
However, we can upcast[^up] without offsetting the vtable from `dyn for<'a> Trait<&'static (), &'a ()>` to `dyn Trait<&'static (), &'static ()>`. This is just instantiating the principal trait ref for a specific `'a = 'static`. However, when considering those supertraits, we now have only one distinct supertrait -- `Supertrait<&'static ()>` (which is deduplicated since there are two supertraits with the same substitutions). This leads to similar offsetting issues, leading to the wrong method being called.
[^up]: I say upcast but this is a cast that is allowed on stable, since it's not changing the vtable at all, just instantiating the binder of the principal trait ref for some lifetime.
The solution here is to recognize that a vtable isn't really meaningfully higher ranked, and to just treat a vtable as corresponding to a `TraitRef` so we can do this deduplication more faithfully. That is to say, the vtable for `dyn for<'a> Tr<'a>` and `dyn Tr<'x>` are always identical, since they both would correspond to a set of free regions on an impl... Do note that `Tr<for<'a> fn(&'a ())>` and `Tr<fn(&'static ())>` are still distinct.
----
There's a bit more that can be cleaned up. In codegen, we can stop using `PolyExistentialTraitRef` basically everywhere. We can also fix SMIR to stop storing `PolyExistentialTraitRef` in its vtable allocations.
As for testing, it's difficult to actually turn this into something that can be tested with `rustc_dump_vtable`, since having multiple supertraits that are identical is a recipe for ambiguity errors. Maybe someone else is more creative with getting that attr to work, since the tests I added being run-pass tests is a bit unsatisfying. Miri also doesn't help here, since it doesn't really generate vtables that are offset by an index in the same way as codegen.
r? `@lcnr` for the vibe check? Or reassign, idk. Maybe let's talk about whether this makes sense.
<sup>(I guess an alternative would also be to not do any deduplication of vtable supertraits (or only a really conservative subset) rather than trying to normalize and deduplicate more faithfully here. Not sure if that works and is sufficient tho.)</sup>
cc `@steffahn` -- ty for the minimizations
cc `@WaffleLapkin` -- since you're overseeing the feature stabilization :3
Fixes#135315Fixes#135316
This makes it possible to start incrementally replacing our debuginfo bindings
with the ones in the LLVM-C API, all of which operate on `LLVMDIBuilderRef`.
Instead re-export `rustc_hir_analysis::collect::suggest_impl_trait`,
which is the only thing from the module used in another crate. This
fixes a `FIXME` comment. Also adjust some visibilities to satisfy the
`unreachable_pub` lint.
This changes requires downgrading a link in a comment on `FnCtxt`
because `collect` is no longer public and rustdoc complains otherwise.
This is annoying but I can't see how to avoid it.
`delegation.rs` has three builders: `GenericsBuilder`,
`PredicatesBuilder`, and `GenericArgsBuilder`. The first two builders
have just two optional parameters, and the third one has zero. Each
builder is used within a single function. The code is over-engineered.
This commit removes the builders, replacing each with with a single
`build_*` function. This makes the code shorter and simpler.
There is a comment `Delegation to inherent methods is not yet
supported.` that appears three times mid-pattern and somehow inhibits
rustfmt from formatting the enclosing `match` statement. This commit
moves them to the top of the pattern, which enables more formatting.
This comment made sense when this crate was called `rustc_typeck`, but
makes less sense now that it's called `rustc_hir_analysis`. Especially
given that `check_drop_impl` is only called within the crate.
Target option to require explicit cpu
Some targets have many different CPUs and no generic CPU that can be used as a default. For these targets, the user needs to explicitly specify a CPU through `-C target-cpu=`.
Add an option for targets and an error message if no CPU is set.
This affects the proposed amdgpu and avr targets.
amdgpu tracking issue: #135024
AVR MCP: https://github.com/rust-lang/compiler-team/issues/800
Introduce a wrapper for "typed valtrees" and properly check the type before extracting the value
This PR adds a new wrapper type `ty::Value` to replace the tuple `(Ty, ty::ValTree)` and become the new canonical representation of type-level constant values.
The value extraction methods `try_to_bits`/`try_to_bool`/`try_to_target_usize` are moved to this new type. For `try_to_bits` in particular, this avoids some redundant matches on `ty::ConstKind::Value`. Furthermore, these methods and will now properly check the type before extracting the value, which fixes some ICEs.
The name `ty::Value` was chosen to be consistent with `ty::Expr`.
Commit 1 should be non-functional and commit 2 adds the type check.
---
fixes https://github.com/rust-lang/rust/issues/131102
supercedes https://github.com/rust-lang/rust/pull/136130
r? `@oli-obk`
cc `@FedericoBruzzone` `@BoxyUwU`
Cast global variables to default address space
Pointers for variables all need to be in the same address space for correct compilation. Therefore ensure that even if a global variable is created in a different address space, it is casted to the default address space before its value is used.
This is necessary for the amdgpu target and others where the default address space for global variables is not 0.
For example `core` does not compile in debug mode when not casting the address space to the default one because it tries to emit the following (simplified) LLVM IR, containing a type mismatch:
```llvm
`@alloc_0` = addrspace(1) constant <{ [6 x i8] }> <{ [6 x i8] c"bit.rs" }>, align 1
`@alloc_1` = addrspace(1) constant <{ ptr }> <{ ptr addrspace(1) `@alloc_0` }>, align 8
; ^ here a struct containing a `ptr` is needed, but it is created using a `ptr addrspace(1)`
```
For this to compile, we need to insert a constant `addrspacecast` before we use a global variable:
```llvm
`@alloc_0` = addrspace(1) constant <{ [6 x i8] }> <{ [6 x i8] c"bit.rs" }>, align 1
`@alloc_1` = addrspace(1) constant <{ ptr }> <{ ptr addrspacecast (ptr addrspace(1) `@alloc_0` to ptr) }>, align 8
```
As vtables are global variables as well, they are also created with an `addrspacecast`. In the SSA backend, after a vtable global is created, metadata is added to it. To add metadata, we need the non-casted global variable. Therefore we strip away an addrspacecast if there is one, to get the underlying global.
Tracking issue: #135024
```
error[E0271]: expected `{closure@return-type-doesnt-match-bound.rs:18:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
--> tests/ui/closures/return-type-doesnt-match-bound.rs:18:20
|
18 | let c = |e| -> ! { //~ ERROR to be a closure that returns
| -------^
| |
| expected `Result<(), _>`, found `!`
...
22 | f().or_else(c);
| ------- -
| |
| required by a bound introduced by this call
|
= note: expected enum `Result<(), _>`
found type `!`
note: required by a bound in `Result::<T, E>::or_else`
--> /home/gh-estebank/rust/library/core/src/result.rs:1406:39
|
1406 | pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
| ^^^^^^^^^^^^ required by this bound in `Result::<T, E>::or_else`
```
```
error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to be a closure that returns `()`, but it returns `!`
--> $DIR/fallback-closure-wrap.rs:19:9
|
LL | let error = Closure::wrap(Box::new(move || {
| -------
LL | panic!("Can't connect to server.");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `!`
|
= note: expected unit type `()`
found type `!`
= note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box<dyn FnMut()>`
```
```
error[E0271]: expected `{closure@dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10}` to be a closure that returns `bool`, but it returns `Option<()>`
--> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:16
|
LL | call(|| -> Option<()> {
| ---- ------^^^^^^^^^^
| | |
| | expected `bool`, found `Option<()>`
| required by a bound introduced by this call
|
= note: expected type `bool`
found enum `Option<()>`
note: required by a bound in `call`
--> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:3:25
|
LL | fn call(_: impl Fn() -> bool) {}
| ^^^^ required by this bound in `call`
```
```
error[E0271]: expected `{closure@f670.rs:28:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
--> f670.rs:28:20
|
28 | let c = |e| -> ! {
| -------^
| |
| expected `Result<(), _>`, found `!`
...
32 | f().or_else(c);
| ------- required by a bound introduced by this call
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:1433:28
|
= note: expected enum `Result<(), _>`
found type `!`
note: required by a bound in `Result::<T, E>::or_else`
--> /home/gh-estebank/rust/library/core/src/result.rs:1406:39
|
1406 | pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> {
| ^^^^^^^^^^^^ required by this bound in `Result::<T, E>::or_else`
```
Allow transmuting generic pattern types to and from their base
Pattern types always have the same size as their base type, so we can just ignore the pattern and look at the base type for figuring out whether transmuting is possible.
Clean up uses of the unstable `dwarf_version` option
- Consolidate calculation of the effective value.
- Check the target `DebuginfoKind` instead of using `is_like_msvc`.
- Add the tracking issue to the unstable book page for this feature.
cc #103057
Simplify and consolidate the way we handle construct `OutlivesEnvironment` for lexical region resolution
This is best reviewed commit-by-commit. I tried to consolidate the API for lexical region resolution *first*, then change the API when it was finally behind a single surface.
r? lcnr or reassign
This also parameterize the "excluded pointee types" and exposes a
general method for inserting checks on pointers.
This is a preparation for adding a NullCheck that makes use of the same
code.
miri: optimize zeroed alloc
When allocating zero-initialized memory in MIR interpretation, rustc allocates zeroed memory, marks it as initialized and then re-zeroes it. Remove the last step.
I don't expect this to have much of an effect on performance normally, but in my case in which I'm creating a large allocation via mmap it gets in the way.
`NamedVarMap` is extremely similar to `ResolveBoundVars`. The former
contains two `UnordMap<ItemLocalId, T>` fields (obscured behind
`ItemLocalMap` typedefs). The latter contains two
`SortedMap<ItemLocalId, T>` fields. We construct a `NamedVarMap` and
then convert it into a `ResolveBoundVars` by sorting the `UnordMap`s,
which is unnecessary busywork.
This commit removes `NamedVarMap` and constructs a `ResolveBoundVars`
directly. `SortedMap` and `NamedVarMap` have slightly different
perf characteristics during construction (e.g. speed of insertion) but
this code isn't hot enough for that to matter.
A few details to note.
- A `FIXME` comment is removed.
- The detailed comments on the fields of `NamedVarMap` are copied to
`ResolveBoundVars` (which has a single, incorrect comment).
- `BoundVarContext::map` is renamed.
- `ResolveBoundVars` gets a derived `Default` impl.
Merge `PatKind::Path` into `PatKind::Expr`
Follow-up to #134228
We always had a duplication where `Path`s could be represented as `PatKind::Path` or `PatKind::Lit(ExprKind::Path)`. We had to handle both everywhere, and still do after #134228, so I'm removing it now.
Rollup of 8 pull requests
Successful merges:
- #133382 (Suggest considering casting fn item as fn pointer in more cases)
- #136092 (Test pipes also when not running on Windows and Linux simultaneously)
- #136190 (Remove duplicated code in RISC-V asm bad-reg test)
- #136192 (ci: remove unused windows runner)
- #136205 (Properly check that array length is valid type during built-in unsizing in index)
- #136211 (Update mdbook to 0.4.44)
- #136212 (Tweak `&mut self` suggestion span)
- #136214 (Make crate AST mutation accessible for driver callback)
r? `@ghost`
`@rustbot` modify labels: rollup
Tweak `&mut self` suggestion span
```
error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference
--> $DIR/issue-38147-1.rs:17:9
|
LL | self.s.push('x');
| ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
help: consider changing this to be a mutable reference
|
LL | fn f(&mut self) {
| +++
```
Note the suggestion to add `mut` instead of replacing the entire `&self` with `&mut self`.
Properly check that array length is valid type during built-in unsizing in index
This results in duplicated errors, but this class of errors is not new; in general, we aren't really equipped to detect cases where a WF error due to a field type would be shadowed by the parent struct of that field also not being WF.
This also adds a note for these types of mismatches to make it clear that this is due to an array type.
Fixes#134352
r? boxyuwu