Apparently MIR borrowck cares about at least one of these for checking variance.
In runtime MIR, though, there's no need for them as `PtrToPtr` does the same thing.
(Banning them simplifies passes like GVN that no longer need to handle multiple cast possibilities.)
Fix duplicated attributes on nonterminal expressions
This PR fixes a long-standing bug (#86055) whereby expression attributes can be duplicated when expanded through declarative macros.
First, consider how items are parsed in declarative macros:
```
Items:
- parse_nonterminal
- parse_item(ForceCollect::Yes)
- parse_item_
- attrs = parse_outer_attributes
- parse_item_common(attrs)
- maybe_whole!
- collect_tokens_trailing_token
```
The important thing is that the parsing of outer attributes is outside token collection, so the item's tokens don't include the attributes. This is how it's supposed to be.
Now consider how expression are parsed in declarative macros:
```
Exprs:
- parse_nonterminal
- parse_expr_force_collect
- collect_tokens_no_attrs
- collect_tokens_trailing_token
- parse_expr
- parse_expr_res(None)
- parse_expr_assoc_with
- parse_expr_prefix
- parse_or_use_outer_attributes
- parse_expr_dot_or_call
```
The important thing is that the parsing of outer attributes is inside token collection, so the the expr's tokens do include the attributes, i.e. in `AttributesData::tokens`.
This PR fixes the bug by rearranging expression parsing to that outer attribute parsing happens outside of token collection. This requires a number of small refactorings because expression parsing is somewhat complicated. While doing so the PR makes the code a bit cleaner and simpler, by eliminating `parse_or_use_outer_attributes` and `Option<AttrWrapper>` arguments (in favour of the simpler `parse_outer_attributes` and `AttrWrapper` arguments), and simplifying `LhsExpr`.
r? `@petrochenkov`
local_def_path_hash_to_def_id is used by Debug impl for DepNode and it
looks for DefPathHash inside the current compilation. During incremental
compilation we are going through nodes that belong to a previous
compilation and might not be present and a simple attempt to print such
node with tracing::debug (try_mark_parent_green does it for example)
results in a otherwise avoidable panic
Panic was added in https://github.com/rust-lang/rust/pull/82183,
specifically in 2b60338ee9, with a comment "We only use this mapping for
cases where we know that it must succeed.", but I'm not sure if this
property holds when we traverse nodes from the old compilation in order
to figure out if they are valid or not
The way it is implemented currently try_force_from_dep_node returns true
as long as there's a function to force the query. It wasn't this way
from the beginning, earlier version was producing forcing result and it
was changed in https://github.com/rust-lang/rust/pull/89978, I couldn't
find any comments addressing this change.
One way it can fail is by failing to recover the query in
DepNodeParams::recover - when we are trying to query something that no
longer exists in the current environment
Rollup of 6 pull requests
Successful merges:
- #125447 (Allow constraining opaque types during subtyping in the trait system)
- #125766 (MCDC Coverage: instrument last boolean RHS operands from condition coverage)
- #125880 (Remove `src/tools/rust-demangler`)
- #126154 (StorageLive: refresh storage (instead of UB) when local is already live)
- #126572 (override user defined channel when using precompiled rustc)
- #126662 (Unconditionally warn on usage of `wasm32-wasi`)
r? `@ghost`
`@rustbot` modify labels: rollup
Unconditionally warn on usage of `wasm32-wasi`
This commit is a continuation of the work originally proposed in rust-lang/compiler-team#607 and later amended in
rust-lang/compiler-team#695. The end goal is to rename `wasm32-wasi` to `wasm32-wasip1` to reflect WASI's development and distinguish the preexisting target from the `wasm32-wasip2` target that WASI is now developing. Work for this transition began in #120468 which landed in Rust 1.78 which became stable on 2024-05-02.
This implements the next phase of the transition plan to warn on usage of `wasm32-wasi`. This is intended to help alert users that a removal is pending and all release channels have the replacement available as well. This will reach stable on 2024-09-05. The next stage of the plan is to remove the `wasm32-wasi` target some time in October 2024 which means that the removal will reach stable on 2025-01-09. For reference a full schedule of this transition is listed [here].
Currently this implementation is a simple unconditional warning whenever `rustc --target wasm32-wasi` is invoked. As-implemented there's no way to turn off the warning other than to switch to the `wasm32-wasip1` target.
[here]: https://github.com/rust-lang/rust/pull/120468#issuecomment-1977878747
MCDC Coverage: instrument last boolean RHS operands from condition coverage
Fresh PR from #124652
--
This PR ensures that the top-level boolean expressions that are not part of the control flow are correctly instrumented thanks to condition coverage.
See discussion on https://github.com/rust-lang/rust/issues/124120.
Depends on `@Zalathar` 's condition coverage implementation #125756.
Allow constraining opaque types during subtyping in the trait system
Previous attempt: https://github.com/rust-lang/rust/pull/123979
Sometimes we don't immediately perform subtyping, but instead register a subtyping obligation and solve that obligation when its inference variables become resolved. Unlike immediate subtyping, we currently do not allow registering hidden types for opaque types. This PR also allows that.
It now parses outer attributes before collecting tokens. This avoids the
problem where the outer attribute tokens were being stored twice -- for
the attribute tokesn, and also for the expression tokens.
Fixes#86055.
Rollup of 7 pull requests
Successful merges:
- #123782 (Test that opaque types can't have themselves as a hidden type with incompatible lifetimes)
- #124580 (Suggest removing unused tuple fields if they are the last fields)
- #125787 (Migrate `bin-emit-no-symbols` `run-make` test to `rmake`)
- #126553 (match lowering: expand or-candidates mixed with candidates above)
- #126594 (Make async drop code more consistent with regular drop code)
- #126654 (Make pretty printing for `f16` and `f128` consistent)
- #126656 (rustc_type_ir: Omit some struct fields from Debug output)
r? `@ghost`
`@rustbot` modify labels: rollup
Combine `NotYetParsed` and `AttributesParsed` into a single variant,
because (a) that reflects the structure of the code that consumes
`LhsExpr`, and (b) because that variant will have the `Option` removed
in a later commit.
The `Option<AttrWrapper>` one maps to the first two variants, and the
`P<Expr>` one maps to the third. Weird. The code is shorter and clearer
without them.
The call in `parse_expr_prefix` for the `++` case passes an empty
`attrs`, but it doesn' need to. This commit changes it to pass the
parsed `attrs`, which doesn't change any behaviour. As a result,
`parse_expr_dot_or_call` no longer needs an `Option` argument, and no
longer needs to call `parse_or_use_outer_attributes`.
Make pretty printing for `f16` and `f128` consistent
Currently the docs show e.g.
{transmute(0xfffeffffffffffffffffffffffffffff): f128}
for f128 constants. This should fix that to instead use apfloat for printing, as is done for `f32` and `f64`.
match lowering: expand or-candidates mixed with candidates above
This PR tweaks match lowering of or-patterns. Consider this:
```rust
match (x, y) {
(1, true) => 1,
(2, false) => 2,
(1 | 2, true | false) => 3,
(3 | 4, true | false) => 4,
_ => 5,
}
```
One might hope that this can be compiled to a single `SwitchInt` on `x` followed by some boolean checks. Before this PR, we compile this to 3 `SwitchInt`s on `x`, because an arm that contains more than one or-pattern was compiled on its own. This PR groups branch `3` with the two branches above, getting us down to 2 `SwitchInt`s on `x`.
We can't in general expand or-patterns freely, because this interacts poorly with another optimization we do: or-pattern simplification. When an or-pattern doesn't involve bindings, we branch the success paths of all its alternatives to the same block. The drawback is that in a case like:
```rust
match (1, true) {
(1 | 2, false) => unreachable!(),
(2, _) => unreachable!(),
_ => {}
}
```
if we used a single `SwitchInt`, by the time we test `false` we don't know whether we came from the `1` case or the `2` case, so we don't know where to go if `false` doesn't match.
Hence the limitation: we can process or-pattern alternatives alongside candidates that precede it, but not candidates that follow it. (Unless the or-pattern is the only remaining match pair of its candidate, in which case we can process it alongside whatever).
This PR allows the processing of or-pattern alternatives alongside candidates that precede it. One benefit is that we now process or-patterns in a single place in `mod.rs`.
r? ``@matthewjasper``
Suggest removing unused tuple fields if they are the last fields
Fixes#124556
We now check if dead/unused fields are the last fields of the tuple and suggest their removal instead of suggesting them to be changed to `()`.
Condition coverage extends branch coverage to treat the specific case
of last operands of boolean decisions not involved in control flow.
This is ultimately made for MCDC to be exhaustive on all boolean expressions.
This patch adds a call to `visit_branch_coverage_operation` to track the
top-level operand of the said decisions, and changes
`visit_coverage_standalone_condition` so MCDC branch registration is called
when enabled on these _last RHS_ cases.
improve tip for inaccessible traits
Improve the tips when the candidate method is from an inaccessible trait.
For example:
```rs
mod m {
trait Trait {
fn f() {}
}
impl<T> Trait for T {}
}
fn main() {
struct S;
S::f();
}
```
The difference between before and now is:
```diff
error[E0599]: no function or associated item named `f` found for struct `S` in the current scope
--> ./src/main.rs:88:6
|
LL | struct S;
| -------- function or associated item `f` not found for this struct
LL | S::f();
| ^ function or associated item not found in `S`
|
= help: items from traits can only be used if the trait is implemented and in scope
- help: trait `Trait` which provides `f` is implemented but not in scope; perhaps you want to import it
+ help: trait `crate:Ⓜ️:Trait` which provides `f` is implemented but not reachable
|
- LL + use crate:Ⓜ️:Trait;
|
```
This commit is a continuation of the work originally proposed in
rust-lang/compiler-team#607 and later amended in
rust-lang/compiler-team#695. The end goal is to rename `wasm32-wasi` to
`wasm32-wasip1` to reflect WASI's development and distinguish the
preexisting target from the `wasm32-wasip2` target that WASI is now
developing. Work for this transition began in #120468 which landed in
Rust 1.78 which became stable on 2024-05-02.
This implements the next phase of the transition plan to warn on usage
of `wasm32-wasi`. This is intended to help alert users that a removal is
pending and all release channels have the replacement available as well.
This will reach stable on 2024-09-05. The next stage of the plan is to
remove the `wasm32-wasi` target some time in October 2024 which means
that the removal will reach stable on 2025-01-09. For reference a full
schedule of this transition is listed [here].
Currently this implementation is a simple unconditional warning whenever
`rustc --target wasm32-wasi` is invoked. As-implemented there's no way
to turn off the warning other than to switch to the `wasm32-wasip1`
target.
[here]: https://github.com/rust-lang/rust/pull/120468#issuecomment-1977878747
Replace `move||` with `move ||`
Edit from #126631 to revert changes in `tests/ui`.
There are 18 instances of `move||` across 6 files in the repo:
- `compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs`
- `library/core/src/sync/atomic.rs`
- `library/std/src/sync/condvar.rs`
- `library/std/src/sync/mpsc/mod.rs`
- `library/std/src/sync/barrier.rs`
- `library/std/src/thread/local.rs`
I have replaced all such instances with `move ||` instead as it better adheres to modern formatting standards.
Ideally, we would have this automated by rustfmt or some other tool, but I do not have the time to implement such a feature or tool.
Nonetheless, I would encourage any effort invested into such a tool or feature.
hir_typeck: be more conservative in making "note caller chooses ty param" note
In https://github.com/rust-lang/rust/pull/122195 I added a "caller chooses ty for type param" note for when the return expression type a.k.a. found type does not match the expected return type.
#126547 found that this note was confusing when the found return type *contains* the expected type, e.g.
```rs
fn f<T>(t: &T) -> T {
t
}
```
because the found return type `&T` will *always* be different from the expected return type `T`, so the note was needlessly redundant and confusing.
This PR addresses that by not making the note if the found return type contains the expected return type.
r? ``@fmease`` (since you reviewed the original PR)
Fixes https://github.com/rust-lang/rust/issues/126547
safe transmute: support non-ZST, variantful, uninhabited enums
Previously, `Tree::from_enum`'s implementation branched into three disjoint cases:
1. enums that uninhabited
2. enums for which all but one variant is uninhabited
3. enums with multiple variants
This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like:
enum Uninhabited { A(!, u128) }
...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in #126460.
In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like:
enum Uninhabited { A(!, !), B(!) }
The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like:
enum Uninhabited { A(!, u128) }
...which represent their variants with `Variants::Single`.
Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited enums like:
enum Uninhabited { A(u8, !), B(!, u32) }
...which represent their variants with `Variants::Multiple`.
This PR also adds a comment requested by ````@RalfJung```` in his review of #126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`.
Fixes#126460
r? ````@compiler-errors````
Suggest using a standalone doctest for non-local impl defs
This PR tweaks the lint output of the `non_local_definitions` lint to suggest using a standalone doctest instead of a moving the `impl` def to an impossible place as was already done with `macro_rules!` case in https://github.com/rust-lang/rust/pull/124568.
Fixes#126339
r? ```@fmease```
Place tail expression behind terminating scope
This PR implements #123739 so that we can do further experiments in nightly.
A little rewrite has been applied to `for await` lowering. It was previously `unsafe { Pin::unchecked_new(into_async_iter(..)) }`. Under the edition 2024 rule, however, `into_async_iter` gets dropped at the end of the `unsafe` block. This presumably the first Edition 2024 migration rule goes by hoisting `into_async_iter(..)` into `match` one level above, so it now looks like the following.
```rust
match into_async_iter($iter_expr) {
ref mut iter => match unsafe { Pin::unchecked_new(iter) } {
...
}
}
```
delegation: Implement glob delegation
Support delegating to all trait methods in one go.
Overriding globs with explicit definitions is also supported.
The implementation is generally based on the design from https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2020869823, but unlike with list delegation in https://github.com/rust-lang/rust/pull/123413 we cannot expand glob delegation eagerly.
We have to enqueue it into the queue of unexpanded macros (most other macros are processed this way too), and then a glob delegation waits in that queue until its trait path is resolved, and enough code expands to generate the identifier list produced from the glob.
Glob delegation is only allowed in impls, and can only point to traits.
Supporting it in other places gives very little practical benefit, but significantly raises the implementation complexity.
Part of https://github.com/rust-lang/rust/issues/118212.
Currently the docs show e.g.
{transmute(0xfffeffffffffffffffffffffffffffff): f128}
for f128 constants. This should fix that to instead use apfloat for
printing, as is done for `f32` and `f64`.
- Avoid "caller chooses ty for type param" note if the found type a.k.a.
the return expression type *contains* the type parameter, because e.g.
`&T` will always be different from `T` (i.e. "well duh").
- Rename `note_caller_chooses_ty_for_ty_param` to
`try_note_caller_chooses_ty_for_ty_param` because the note is not
always made.
Issue: https://github.com/rust-lang/rust/issues/126547
Uplift next trait solver to `rustc_next_trait_solver`
🎉
There's so many FIXMEs! Sorry! Ideally this merges with the FIXMEs and we track and squash them over the near future.
Also, this still doesn't build on anything other than rustc. I still need to fix `feature = "nightly"` in `rustc_type_ir`, and remove and fix all the nightly feature usage in the new trait solver (notably: let-chains).
Also, sorry `@lcnr` I know you asked for me to separate the commit where we `mv rustc_trait_selection/solve/... rustc_next_trait_solver/solve/...`, but I had already done all the work by that point. Luckily, `git` understands the file moves so it should still be relatively reviewable.
If this is still very difficult to review, then I can do some rebasing magic to try to separate this out. Please let me know!
r? lcnr
Replace all `&DiagCtxt` with a `DiagCtxtHandle<'_>` wrapper type
r? `@davidtwco`
This paves the way for tracking more state (e.g. error tainting) in the diagnostic context handle
Basically I will add a field to the `DiagCtxtHandle` that refers back to the `InferCtxt`'s (and others) `Option<ErrorHandled>`, allowing us to immediately taint these contexts when emitting an error and not needing manual tainting anymore (which is easy to forget and we don't do in general anyway)
coverage: Add debugging flag `-Zcoverage-options=no-mir-spans`
When set, this flag skips the code that normally extracts coverage spans from MIR statements and terminators. That sometimes makes it easier to debug branch coverage and MC/DC coverage instrumentation, because the coverage output is less noisy.
For internal debugging only. If future code changes would make it hard to keep supporting this flag, it should be removed at that time.
`@rustbot` label +A-code-coverage
Rework `feature(precise_capturing)` to represent `use<...>` as a syntactical bound
Reworks `precise_capturing` for a recent lang-team consensus.
Specifically:
> The conclusion of the team is that we'll make use<..> a bound. That is, we'll support impl use<..> + Trait, impl Trait + use<..>, etc.
> For now, we will support at most one such bound in a list of bounds, and semantically we'll only support these bounds in the item bounds of RPIT-like impl Trait opaque types (i.e., in the places discussed in the RFC).
Lang decision in favor of this approach:
- https://github.com/rust-lang/rust/issues/125836#issuecomment-2151351849
Tracking:
- https://github.com/rust-lang/rust/issues/123432
Rename `InstanceDef` -> `InstanceKind`
Renames `InstanceDef` to `InstanceKind`. The `Def` here is confusing, and makes it hard to distinguish `Instance` and `InstanceDef`. `InstanceKind` makes this more obvious, since it's really just describing what *kind* of instance we have.
Not sure if this is large enough to warrant a types team MCP -- it's only 53 files. I don't personally think it does, but happy to write one if anyone disagrees. cc ``@rust-lang/types``
r? types
Rollup of 3 pull requests
Successful merges:
- #126568 (mark undetermined if target binding in current ns is not got)
- #126577 (const_refs_to_static test and cleanup)
- #126584 (Do not ICE in privacy when type inference fails.)
r? `@ghost`
`@rustbot` modify labels: rollup
const_refs_to_static test and cleanup
r? ``@RalfJung``
test the existing behaviour of adt_const_params combined with const_refs_to_static.
also remove a dead error variant about consts referring to statics
Consistently use subtyping in method resolution
fixes#126062
An earlier version of this PR modified how we compute variance, but the root cause was an inconsistency between the usage of `eq` and `sub`, where we assumed that the latter passing implies the former will pass.
r? `@compiler-errors`
When set, this flag skips the code that normally extracts coverage spans from
MIR statements and terminators. That sometimes makes it easier to debug branch
coverage and MC/DC coverage, because the coverage output is less noisy.
For internal debugging only. If other code changes would make it hard to keep
supporting this flag, remove it.
Rollup of 3 pull requests
Successful merges:
- #126226 (Make suggestion to change `Fn` to `FnMut` work with methods as well)
- #126570 (Convert a `span_bug` to a `span_delayed_bug`.)
- #126580 (Add `run-make/const_fn_mir` missing test annotation)
r? `@ghost`
`@rustbot` modify labels: rollup
Convert a `span_bug` to a `span_delayed_bug`.
PR #121208 converted this from a `span_delayed_bug` to a `span_bug` because nothing in the test suite caused execution to hit this path. But now fuzzing has found a test case that does hit it. So this commit converts it back to `span_delayed_bug` and adds the relevant test.
Fixes#126385.
r? `@lcnr`
Make suggestion to change `Fn` to `FnMut` work with methods as well
Fixes#125325
The issue occurred because the code that emitted the suggestion to change `Fn` to `FnMut` worked only for function calls and not method calls. This PR makes it work with methods as well.
More preparation for new trait solver uplifting
Getting closer to being able to uplift the whole solver 🙏
Each commit should be self-justifying.
r? lcnr
PR #121208 converted this from a `span_delayed_bug` to a `span_bug`
because nothing in the test suite caused execution to hit this path. But
now fuzzing has found a test case that does hit it. So this commit
converts it back to `span_delayed_bug` and adds the relevant test.
Fixes#126385.
coverage: Several small improvements to graph code
This PR combines a few small improvements to coverage graph handling code:
- Remove some low-value implementation tests that were getting in the way of other changes.
- Clean up `pub` visibility.
- Flatten some code using let-else.
- Prefer `.copied()` over `.cloned()`.
`@rustbot` label +A-code-coverage
coverage: Arrange span extraction/refinement as a series of passes
The old code for extracting/refining coverage spans from MIR has been dismantled and split up into several passes (e.g. see #126294), but because this was done incrementally, the resulting code is disorganised.
This PR addresses that by moving the main control-flow into a single function (`coverage::spans::extract_refined_covspans`) that more clearly shows the process as a series of separate steps, most delegated to helper functions in the same file.
This should make it easier to understand and modify the refinement process. It also means that submodule `from_mir` is now only concerned with the details of extracting relevant spans from the various kinds of MIR statement/terminator.
There should be no change to the resulting coverage maps, as demonstrated by the lack of changes to tests.
Resolve elided lifetimes in assoc const to static if no other lifetimes are in scope
Implements the change to elided lifetime resolution in *associated consts* subject to FCP here: https://github.com/rust-lang/rust/issues/125190#issue-2301532282
Specifically, walk the enclosing lifetime ribs in an associated const, and if we find no other lifetimes, then resolve to `'static`.
Also make it work for traits, but don't lint -- just give a hard error in that case.
`boxed_slice_into_iter`: tiny doc correction
`CURRENT_RUSTC_VERSION` isn't flexible enough for this, so it got replaced by 1.80.0 instead of 1.79.0 in #126273 :/
Honor collapse_debuginfo for statics.
fixes#126363
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.
This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using
r? <reviewer name>
-->
Introduce `{IndexNewtype,SyntaxContext}::from_u16` for convenience because small indices are sometimes encoded as `u16`.
Use `SpanData::span` instead of `Span::new` where appropriate.
Add a clarifying comment about decoding span parents.
Spell out other trait diagnostic
I recently saw somebody confused about the diagnostic thinking it was suggesting to add an `as` cast. This change is longer but I think it's clearer
These tests might have originally been useful as an implementation aid, but now
they don't provide enough value to justify the burden of updating them as the
underlying code changes.
The code they test is still exercised by the main end-to-end coverage tests.
Only compute vtable information during codegen
This PR removes vtable information from the `Object` and `TraitUpcasting` candidate sources in the trait solvers, and defers the computation of relevant information to `Instance::resolve`. This is because vtables really aren't a thing in the trait world -- they're an implementation detail in codegen.
Previously it was just easiest to tangle this information together since we were already doing the work of looking at all the supertraits in the trait solver, and specifically because we use traits to represent when it's possible to call a method via a vtable (`Object` candidate) and do upcasting (`Unsize` candidate). but I am somewhat suspicious we're doing a *lot* of extra work, especially in polymorphic contexts, so let's see what perf says.
Make uninitialized_error_reported a set of locals
Another artifact of how places used to be able to be based on statics and not just locals. This set is exclusively filled with PlaceRefs that are just locals, so it should just contain locals directly.
Make proof tree probing and `Candidate`/`CandidateSource` generic over interner
`<TyCtxt<'tcx>>` is ugly, but will become `<I>` when things actually become generic.
r? lcnr
smir: merge identical Constant and ConstOperand types
The first commit renames the const operand visitor functions on regular MIR to match the type name, that was forgotten in the original rename.
The second commit changes stable MIR, fixing https://github.com/rust-lang/project-stable-mir/issues/71. Previously there were two different smir types for the MIR type `ConstOperand`, one used in `Operand` and one in `VarDebugInfoContents`.
Maybe we should have done this with https://github.com/rust-lang/rust/pull/125967, so there's only a single breaking change... but I saw that PR too late.
Fixes https://github.com/rust-lang/project-stable-mir/issues/71
Check that alias-relate terms are WF if reporting an error in alias-relate
Check that each of the left/right term is WF when deriving a best error obligation for an alias-relate goal. This will make sure that given `<i32 as NotImplemented>::Assoc = ()` will drill down into `i32: NotImplemented` since we currently treat the projection as rigid.
r? lcnr