Commit graph

3181 commits

Author SHA1 Message Date
Stuart Cook
544462ad8b
Rollup merge of #152474 - sgasho:opt-bisect-limit-mir, r=saethlin
Implement opt-bisect-limit for MIR

closes: rust-lang/rust#150910

Enable bisecting MIR optimization passes to enhance debuggability.

discussions on zulip: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/MIR.20dump.20the.20pass.20names/with/573219207

### Check it works
#### Sample code
```rust
fn abs(num: isize) -> usize {
    if num < 0 { -num as usize } else { num as usize }
}

fn main() {
    println!("{}", abs(-10));
}
```

#### Output

```shell
rustc +mir -Zmir-opt-bisect-limit=30 src/main.rs
BISECT: running pass (1) CheckAlignment on main[89d5]::main
BISECT: running pass (2) CheckNull on main[89d5]::main
BISECT: running pass (3) CheckEnums on main[89d5]::main
BISECT: running pass (4) LowerSliceLenCalls on main[89d5]::main
BISECT: running pass (5) InstSimplify-before-inline on main[89d5]::main
BISECT: running pass (6) ForceInline on main[89d5]::main
BISECT: running pass (7) RemoveStorageMarkers on main[89d5]::main
BISECT: running pass (8) RemoveZsts on main[89d5]::main
BISECT: running pass (9) RemoveUnneededDrops on main[89d5]::main
BISECT: running pass (10) UnreachableEnumBranching on main[89d5]::main
BISECT: running pass (11) SimplifyCfg-after-unreachable-enum-branching on main[89d5]::main
BISECT: running pass (12) InstSimplify-after-simplifycfg on main[89d5]::main
BISECT: running pass (13) SimplifyConstCondition-after-inst-simplify on main[89d5]::main
BISECT: running pass (14) SimplifyLocals-before-const-prop on main[89d5]::main
BISECT: running pass (15) SimplifyLocals-after-value-numbering on main[89d5]::main
BISECT: running pass (16) MatchBranchSimplification on main[89d5]::main
BISECT: running pass (17) SingleUseConsts on main[89d5]::main
BISECT: running pass (18) SimplifyConstCondition-after-const-prop on main[89d5]::main
BISECT: running pass (19) SimplifyConstCondition-final on main[89d5]::main
BISECT: running pass (20) RemoveNoopLandingPads on main[89d5]::main
BISECT: running pass (21) SimplifyCfg-final on main[89d5]::main
BISECT: running pass (22) CopyProp on main[89d5]::main
BISECT: running pass (23) SimplifyLocals-final on main[89d5]::main
BISECT: running pass (24) AddCallGuards on main[89d5]::main
BISECT: running pass (25) PreCodegen on main[89d5]::main
BISECT: running pass (26) CheckAlignment on main[89d5]::abs
BISECT: running pass (27) CheckNull on main[89d5]::abs
BISECT: running pass (28) CheckEnums on main[89d5]::abs
BISECT: running pass (29) LowerSliceLenCalls on main[89d5]::abs
BISECT: running pass (30) InstSimplify-before-inline on main[89d5]::abs
BISECT: NOT running pass (31) ForceInline on main[89d5]::abs
BISECT: NOT running pass (32) RemoveStorageMarkers on main[89d5]::abs
BISECT: NOT running pass (33) RemoveZsts on main[89d5]::abs
BISECT: NOT running pass (34) RemoveUnneededDrops on main[89d5]::abs
BISECT: NOT running pass (35) UnreachableEnumBranching on main[89d5]::abs
BISECT: NOT running pass (36) SimplifyCfg-after-unreachable-enum-branching on main[89d5]::abs
BISECT: NOT running pass (37) InstSimplify-after-simplifycfg on main[89d5]::abs
BISECT: NOT running pass (38) SimplifyConstCondition-after-inst-simplify on main[89d5]::abs
BISECT: NOT running pass (39) SimplifyLocals-before-const-prop on main[89d5]::abs
BISECT: NOT running pass (40) SimplifyLocals-after-value-numbering on main[89d5]::abs
BISECT: NOT running pass (41) MatchBranchSimplification on main[89d5]::abs
BISECT: NOT running pass (42) SingleUseConsts on main[89d5]::abs
BISECT: NOT running pass (43) SimplifyConstCondition-after-const-prop on main[89d5]::abs
BISECT: NOT running pass (44) SimplifyConstCondition-final on main[89d5]::abs
BISECT: NOT running pass (45) RemoveNoopLandingPads on main[89d5]::abs
BISECT: NOT running pass (46) SimplifyCfg-final on main[89d5]::abs
BISECT: NOT running pass (47) CopyProp on main[89d5]::abs
BISECT: NOT running pass (48) SimplifyLocals-final on main[89d5]::abs
BISECT: NOT running pass (49) AddCallGuards on main[89d5]::abs
BISECT: NOT running pass (50) PreCodegen on main[89d5]::abs
```

r? @saethlin
2026-02-18 17:29:46 +11:00
Stuart Cook
d5e9f9d67b
Rollup merge of #152758 - cjgillot:noinit-box, r=RalfJung
Remove ShallowInitBox.

All uses of this were removed by https://github.com/rust-lang/rust/pull/148190
Split from https://github.com/rust-lang/rust/pull/147862

r? @RalfJung
2026-02-18 17:29:44 +11:00
Stuart Cook
dbc2193d37
Rollup merge of #152729 - Enselic:single_use_consts-not-required, r=cjgillot
compiler: Don't mark `SingleUseConsts` MIR pass as "required for soundness"

I don't think this MIR pass is required for soundness. The reasons are:
* Something like it was not enabled by default before PR rust-lang/rust#107404 which was the precursor to `SingleUseConsts` (see rust-lang/rust#125910 for the switch).
* By following the advice from https://github.com/rust-lang/rust/pull/128657#discussion_r1705114015 we can conclude it is not required for soundness since it has only ever run on MIR opt level > 0.
* Its [`MirPass::can_be_overridden()`](0ee7d96253/compiler/rustc_mir_transform/src/pass_manager.rs (L98-L102)) is unchanged and thus returns `true`, indicating that it is not a required MIR pass.
* PR CI pass in rust-lang/rust#151426 which stops enabling it by default in non-optimized builds.

As shown in the updated test `tests/mir-opt/optimize_none.rs`, `#[optimize(none)]` functions become even less optimized, as expected and desired.

Unblocks https://github.com/rust-lang/rust/pull/151426.
2026-02-18 17:29:43 +11:00
sgasho
28c8d71544 Implement opt-bisect-limit for mir 2026-02-17 21:26:39 +09:00
Camille Gillot
6d4b1b38e7 Remove ShallowInitBox. 2026-02-17 11:25:50 +00:00
Martin Nordholts
52b19f7dda compiler: Don't mark SingleUseConsts MIR pass as "required for soundness"
Because:
* Something like it did not exist before PR 107404
* That it is not run our mir-opt-level 0 indicates that it is not
  required for soundness
* Its `MirPass::can_be_overridden()` is unchanged and thus returns true,
  indicating that it is not a required MIR pass.
* No test fails in PR 151426 that stops enabling by default in non-optimized builds

As can be seen from the updated test `tests/mir-opt/optimize_none.rs`,
this means that `#[optimize(none)]` functions become even less
optimized. As expected and as desired.
2026-02-17 06:22:39 +01:00
bors
3c9faa0d03 Auto merge of #148190 - RalfJung:box_new, r=RalfJung
replace box_new with lower-level intrinsics

The `box_new` intrinsic is super special: during THIR construction it turns into an `ExprKind::Box` (formerly known as the `box` keyword), which then during MIR building turns into a special instruction sequence that invokes the exchange_malloc lang item (which has a name from a different time) and a special MIR statement to represent a shallowly-initialized `Box` (which raises [interesting opsem questions](https://github.com/rust-lang/rust/issues/97270)).

This PR is the n-th attempt to get rid of `box_new`. That's non-trivial because it usually causes a perf regression: replacing `box_new` by naive unsafe code will incur extra copies in debug builds, making the resulting binaries a lot slower, and will generate a lot more MIR, making compilation measurably slower. Furthermore, `vec!` is a macro, so the exact code it expands to is highly relevant for borrow checking, type inference, and temporary scopes.

To avoid those problems, this PR does its best to make the MIR almost exactly the same as what it was before. `box_new` is used in two places, `Box::new` and `vec!`:
- For `Box::new` that is fairly easy: the `move_by_value` intrinsic is basically all we need. However, to avoid the extra copy that would usually be generated for the argument of a function call, we need to special-case this intrinsic during MIR building. That's what the first commit does.
- `vec!` is a lot more tricky. As a macro, its details leak to stable code, so almost every variant I tried broke either type inference or the lifetimes of temporaries in some ui test or ended up accepting unsound code due to the borrow checker not enforcing all the constraints I hoped it would enforce. I ended up with a variant that involves a new intrinsic, `fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, x: T) -> Box<MaybeUninit<T>>`, that writes a value into a `Box<MaybeUninit<T>>` and returns that box again. In exchange we can get rid of somewhat similar code in the lowering for `ExprKind::Box`, and the `exchange_malloc` lang item. (We can also get rid of `Rvalue::ShallowInitBox`; I didn't include that in this PR -- I think @cjgillot has a commit for this somewhere [around here](https://github.com/rust-lang/rust/pull/147862/commits).)

See [here](https://github.com/rust-lang/rust/pull/148190#issuecomment-3457454814) for the latest perf numbers. Most of the regressions are in deep-vector which consists entirely of an invocation of `vec!`, so any change to that macro affects this benchmark disproportionally.

This is my first time even looking at MIR building code, so I am very low confidence in that part of the patch, in particular when it comes to scopes and drops and things like that.

I also had do nerf some clippy tests because clippy gets confused by the new expansion of `vec!` so it makes fewer suggestions when `vec!` is involved.

### `vec!` FAQ

- Why does `write_box_via_move` return the `Box` again? Because we need to expand `vec!` to a bunch of method invocations without any blocks or let-statements, or else the temporary scopes (and type inference) don't work out.
- Why is `box_assume_init_into_vec_unsafe` (unsoundly!) a safe function? Because we can't use an unsafe block in `vec!` as that would necessarily also include the `$x` (due to it all being one big method invocation) and therefore interpret the user's code as being inside `unsafe`, which would be bad (and 10 years later, we still don't have safe blocks for macros like this).
- Why does `write_box_via_move` use `Box` as input/output type, and not, say, raw pointers? Because that is the only way to get the correct behavior when `$x` panics or has control effects: we need the `Box` to be dropped in that case. (As a nice side-effect this also makes the intrinsic safe, which is imported as explained in the previous bullet.)
- Can't we make it safe by having `write_box_via_move` return `Box<T>`? Yes we could, but there's no easy way for the intrinsic to convert its `Box<MaybeUninit<T>>` to a `Box<T>`. Transmuting would be unsound as the borrow checker would no longer properly enforce that lifetimes involved in a `vec!` invocation behave correctly.
- Is this macro truly cursed? Yes, yes it is.
2026-02-16 18:46:10 +00:00
Jacob Pratt
c9a7f8afa9
Rollup merge of #152103 - eggyal:caught-divergence-not-unused, r=cjgillot
Consider captures to be used by closures that unwind

Assignments to a captured variable within a diverging closure should not be considered unused if the divergence is caught.

This patch considers such assignments/captures to be used by diverging closures irrespective of whether the divergence is caught, but better a false negative unused lint than a false positive one (the latter having caused a stable-to-stable regression).

Fixes rust-lang/rust#152079
r? compiler
2026-02-16 04:28:57 -05:00
Ralf Jung
93d45480aa replace box_new in Box::new with write_via_move
requires lowering write_via_move during MIR building to make it just like an assignment
2026-02-16 08:44:56 +01:00
Jonathan Brouwer
018a5efcf7
Rename inline_fluent! to msg! 2026-02-14 13:47:52 +01:00
Jonathan Brouwer
f1b935d08f
Rollup merge of #152356 - JonathanBrouwer:inline_diag4, r=jdonszelmann
Improve the `inline_fluent!` macro

For https://github.com/rust-lang/rust/issues/151366

This PR turns `inline_fluent!` into a proc macro, so we can run validation on the messages in this macro :)
I started a thread here because I don't like the name of the macro, but that's for a future PR: [#t-compiler > Bikeshed the new &#96;inline_fluent!&#96; macro](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Bikeshed.20the.20new.20.60inline_fluent!.60.20macro/with/572646242)
2026-02-13 13:35:01 +01:00
Lukas Bergdoll
2f3b952349 Stabilize assert_matches 2026-02-11 14:13:44 +01:00
Jana Dönszelmann
eab26e329b
Port rustc_no_mir_inline to the new attribute parser 2026-02-10 10:25:19 +01:00
Jonathan Brouwer
6eb2a8fa9e
Reformat existing error messages 2026-02-09 19:12:22 +01:00
bors
13c38730d9 Auto merge of #150485 - dianqk:gvn-ssa-borrow, r=cjgillot
GVN: Only propagate borrows from SSA locals

Fixes https://github.com/rust-lang/rust/issues/141313. This is a more principled fix than https://github.com/rust-lang/rust/pull/147886.

Using a reference that is not a borrowing of an SSA local at a new location may be UB.

The PR has two major changes.

The first one, when introducing a new dereference at a new location, is that the reference must point to an SSA local or be an immutable argument. `dereference_address` has handled SSA locals.

The second one, if we cannot guard to the reference point to an SSA local in `visit_assign`, we have to rewrite the value to opaque. This avoids unifying the following dereferences that also are references:

```rust
let b: &T = *a;
// ... `a` is allowed to be modified. `c` and `b` have different borrowing lifetime.
// Unifying them will extend the lifetime of `b`.
let c: &T = *a; 
```

See also https://github.com/rust-lang/rust/issues/130853.

This still allows unifying non-reference dereferences:

```rust
let a: &T = ...;
let b: T = *a;
// ... a is NOT allowed to be modified.
let c: T = *a; 
```

r? @cjgillot
2026-02-08 05:03:48 +00:00
Jana Dönszelmann
9249e9f78a
Port rustc_intrinsic to the new attribute parser 2026-02-07 14:12:56 +01:00
bors
f889772d65 Auto merge of #152096 - bjorn3:mir_encoding_cleanups, r=oli-obk
Couple of cleanups and optimizations around MIR encoding
2026-02-05 15:30:48 +00:00
Jonathan Brouwer
40695f18be
Convert to inline diagnostics in rustc_mir_transform 2026-02-04 18:29:47 +01:00
bjorn3
ef00ebfdec Remove is_ctfe_mir_available query
It isn't called anywhere anymore.
2026-02-04 15:58:47 +00:00
dianqk
9c029d2102
GVN: Do not unify dereferences if they are references 2026-02-04 21:55:57 +08:00
dianqk
bc2bf6b544
GVN: Do not introduce new dereferences if they borrow from non-SSA locals 2026-02-04 21:55:54 +08:00
dianqk
9f9c4c8b0b
GVN: Remove invalidate_derefs 2026-02-04 21:50:52 +08:00
Alan Egerton
58292e2a53
Consider captures to be used by closures that unwind
Assignments to a captured variable within a diverging closure should not
be considered unused if the divergence is caught.

This patch considers such assignments/captures to be used by diverging
closures irrespective of whether the divergence is caught, but better a
false negative unused lint than a false positive one (the latter having
caused a stable-to-stable regression).
2026-02-04 12:35:34 +00:00
Zalathar
0418f9aa42 coverage: Add a test case for a previously-unknown span mismatch 2026-02-03 22:53:38 +11:00
Jacob Pratt
9e21300b02
Rollup merge of #152009 - Ozzy1423:attrs4, r=JonathanBrouwer
Port rustc_preserve_ub_checks to attr parser

Tracking issue: https://github.com/rust-lang/rust/issues/131229

Port rustc_preserve_ub_checks to attr parser

r? @JonathanBrouwer
2026-02-02 23:12:08 -05:00
Oscar Bray
6b1d4059cb Port rustc_preserve_ub_checks to attr parser. 2026-02-02 21:14:30 +00:00
Alan Egerton
5aba6b1635
Fix missing unused_variables lint when using a match guard
Within a binding pattern match guard, only real reads of a bound local
impact its liveness analysis - not the fake read that is injected.
2026-02-02 10:57:54 +00:00
bors
a1db344c08 Auto merge of #151924 - JonathanBrouwer:rollup-Pqp8PIn, r=JonathanBrouwer
Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#151886 (Skip unused_allocation lint when method takes &Box<Self>)
 - rust-lang/rust#150300 (Constify `fmt::from_fn`)
 - rust-lang/rust#151102 (Feature-gate `mut ref` patterns in struct pattern field shorthand)
 - rust-lang/rust#151866 (Reorganizing `tests/ui/issues` 10 tests [4/N] )
 - rust-lang/rust#151890 (Re-export `hashbrown::hash_table` from `rustc_data_structures`)
2026-01-31 23:56:07 +00:00
bors
905b926967 Auto merge of #151622 - scottmcm:elide-more-transmutes, r=cjgillot
GVN: Elide more intermediate transmutes

We already skipped intermediate steps like `u32` or `i32` that support any (initialized) value.

This extends that to also allow skipping intermediate steps whose values are a superset of either the source or destination type.  Most importantly, that means that `usize` → `NonZeroUsize` → `ptr::Alignment` and `ptr::Alignment` → `NonZeroUsize` → `usize` can skip the middle because `NonZeroUsize` is a superset of `Alignment`.

Then `Alignment::as_usize` is updated to take advantage of that and let us remove some more locals in a few places.

r? cjgillot
2026-01-31 20:42:37 +00:00
Zalathar
04e6afe20a Re-export hashbrown::hash_table from rustc_data_structures 2026-01-31 14:48:50 +11:00
Jonathan Brouwer
a4b553804b
Rollup merge of #151376 - chenyukang:yukang-fix-perf, r=lqd
Fix performance issue in liveness checking

r? @ghost

from https://github.com/rust-lang/rust/pull/150955#issuecomment-3769274223
2026-01-30 13:20:23 +01:00
yukang
d2aa64fa2d Fix performance issue in liveness checking 2026-01-30 01:54:39 +00:00
Stuart Cook
9f0483e5f0
Rollup merge of #151596 - sgasho:150910_SimplifyCfg_passes_warn, r=nnethercote,saethlin
Fix -Zmir-enable-passes to detect unregistered enum names in declare_passes macro

related: https://github.com/rust-lang/rust/issues/150910

I fixed declare_passes macro to detect unregistered enum names

### UI Results
+nightly --> before: no warnings
+stage1 --> after: detect SimplifyCfg as an unknown pass

<img width="591" height="199" alt="スクリーンショット 2026-01-24 23 53 41" src="https://github.com/user-attachments/assets/ddabaa58-b4c6-4e80-a3c9-f40d866db273" />
2026-01-29 19:03:30 +11:00
sgasho
99591e6d42 Fix -Zmir-enable-passes to detect unregistered enum names 2026-01-29 09:01:05 +09:00
dianne
5ddb7f6dd2 clean up checks for integer div/rem promotion 2026-01-27 17:18:14 -08:00
dianne
4039cef09e Don't evaluate const blocks in constant promotion 2026-01-27 04:31:57 -08:00
Scott McMurray
3a33ab0595 GVN: Elide more intermediate transmutes 2026-01-25 17:14:06 -08:00
bors
9415853279 Auto merge of #151556 - eggyal:unused-assignment-to-unused-variable, r=cjgillot
Fix suppression of `unused_assignment` in binding of `unused_variable`

Unused assignments to an unused variable should trigger only the `unused_variables` lint and not also the `unused_assignments` lint. This was previously implemented by checking whether the span of the assignee was within the span of the binding pattern, however that failed to capture situations was imported from elsewhere (eg from the input tokenstream of a proc-macro that generates the binding pattern).

By comparing the span of the assignee to those of the variable introductions instead, a reported stable-to-stable regression is resolved.

This fix also impacted some other preexisting tests, which had (undesirably) been triggering both the `unused_variables` and `unused_assignments` lints on the same initializing assignment; those tests have therefore now been updated to expect only the former lint.

Fixes rust-lang/rust#151514
r? cjgillot (as author of reworked liveness testing in rust-lang/rust#142390)
2026-01-25 13:10:32 +00:00
Alan Egerton
22b3f59882
Fix suppression of unused_assignment in binding of unused_variable
Unused assignments to an unused variable should trigger only the
`unused_variables` lint and not also the `unused_assignments` lint.
This was previously implemented by checking whether the span of the
assignee was within the span of the binding pattern, however that failed
to capture situations was imported from elsewhere (eg from the input
tokenstream of a proc-macro that generates the binding pattern).

By comparing the span of the assignee to those of the variable
introductions instead, a reported stable-to-stable regression is
resolved.

This fix also impacted some other preexisting tests, which had
(undesirably) been triggering both the `unused_variables` and
`unused_assignments` lints on the same initializing assignment; those
tests have therefore now been updated to expect only the former lint.
2026-01-23 22:20:52 +00:00
Mark Rousskov
3dc7a1f33b Bump stage0 2026-01-21 20:03:56 -05:00
bors
fffc4fcf96 Auto merge of #151395 - Zalathar:rollup-8gANGZS, r=Zalathar
Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#149587 (coverage: Sort the expansion tree to help choose a single BCB for child expansions)
 - rust-lang/rust#150071 (Add dist step for Enzyme)
 - rust-lang/rust#150288 (Add scalar support for offload)
 - rust-lang/rust#151091 (Add new "hide deprecated items" setting in rustdoc)
 - rust-lang/rust#151255 (rustdoc: Fix ICE when deprecated note is not resolved on the correct `DefId`)
 - rust-lang/rust#151375 (Fix terminal  width dependent tests)
 - rust-lang/rust#151384 (add basic `TokenStream` api tests)
 - rust-lang/rust#151391 (rustc-dev-guide subtree update)

r? @ghost
2026-01-20 09:01:18 +00:00
bors
7981818138 Auto merge of #151076 - cuviper:compiler-hashbrown-0.16.1, r=Amanieu
compiler: upgrade to hashbrown 0.16.1

See also rust-lang/rust#135634, rust-lang/rust#149159, and rust-lang/hashbrown#662.

This includes an in-tree upgrade of `indexmap` as well, which uses the
new `HashTable` buckets API internally, hopefully impacting performance
for the better.

And finally, we can remove `#[rustc_unsafe_specialization_marker]` on `Copy`!

cc @joboet
r? @Amanieu
2026-01-20 05:44:13 +00:00
Zalathar
986db13c17 coverage: Use the sorted expansion tree to determine min/max BCBs 2026-01-20 13:29:09 +11:00
Zalathar
7a3e5cd57e coverage: Sort the expansion tree in depth-first order
This makes it possible for subsequent operations to iterate over all nodes,
while assuming that every node occurs before all of its descendants.
2026-01-20 13:29:09 +11:00
Jonathan Brouwer
0ee7d96253
Remove all allows for diagnostic_outside_of_impl and untranslatable_diagnostic throughout the codebase
This PR was mostly made by search&replacing
2026-01-19 17:39:49 +01:00
Zalathar
7ec34defe9 Temporarily re-export assert_matches! to reduce stabilization churn 2026-01-19 18:26:53 +11:00
bors
3d087e6044 Auto merge of #150309 - dianqk:ssa-range, r=cjgillot
New MIR Pass: SsaRangePropagation

As an alternative to https://github.com/rust-lang/rust/pull/150192.

Introduces a new pass that propagates the known ranges of SSA locals.
We can know the ranges of SSA locals at some locations for the following code:
```rust
fn foo(a: u32) {
  let b = a < 9;
  if b {
    let c = b; // c is true since b is whitin the range [1, 2)
    let d = a < 8; // d is true since b whitin the range [0, 9)
  }
}
```

This PR only implements a trivial range: we know one value on switch, assert, and assume.
2026-01-19 03:04:55 +00:00
Jacob Pratt
0331284ffc
Rollup merge of #150955 - yukang-fix-149889-unused-assign, r=fee1-dead
Underscore-prefixed bindings are explicitly allowed to be unused

Fixes rust-lang/rust#149889
2026-01-18 03:16:45 -05:00
bors
18ae990755 Auto merge of #150925 - dianqk:if-cmp, r=saethlin
Only use SSA locals in SimplifyComparisonIntegral

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

The place may be modified from the comparison statement to the switchInt terminator.

Best reviewed commit by commit.
2026-01-15 23:54:21 +00:00
Jonathan Brouwer
db10879fd1
Rollup merge of #151096 - rm-providers-deref, r=oli-obk
Remove `Deref`/`DerefMut` impl for `Providers`.

It's described as a "backwards compatibility hack to keep the diff small". Removing it requires only a modest amount of churn, and the resulting code is clearer without the invisible derefs.

r? @oli-obk
2026-01-14 11:05:42 +01:00