Skip to content

Bubble up post-monomorphization errors for the instantiation note#157318

Draft
xmakro wants to merge 2 commits into
rust-lang:mainfrom
xmakro:fix/parallel-pme-note-bubble
Draft

Bubble up post-monomorphization errors for the instantiation note#157318
xmakro wants to merge 2 commits into
rust-lang:mainfrom
xmakro:fix/parallel-pme-note-bubble

Conversation

@xmakro
Copy link
Copy Markdown

@xmakro xmakro commented Jun 2, 2026

Alternative implementation to #157282, opened so the two approaches can be compared. After implementing and testing it, the conclusion is that bubbling does not work for every post-monomorphization
error.

Bubbling requires every post-monomorphization error source to hand back an ErrorGuaranteed. Some errors are emitted and then absorbed during collection, so no token reaches the collector along any return path.

tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs is one such case, and it regresses under this PR (the three instantiation notes are dropped). Instrumenting the recursion-limit emit site in struct_tail_raw with a backtrace shows that all twelve struct-tail errors in this test funnel through one path:

collect_items_rec -> items_of_instance -> visit_const_operand
  -> MirUsedCollector::eval_constant
    -> const_.eval() -> CTFE eval_to_allocation_raw / eval_in_interpreter
      -> eval_callee_and_args -> normalize callee FnSig
        -> <_ as Pointee>::Metadata projection
          -> ptr_metadata_ty_or_tail -> struct_tail_raw -> emit_err + recover to unit

The error is emitted inside CTFE while normalizing a callee FnSig that contains a Pointee::Metadata projection. struct_tail_raw calls emit_err and returns Ty::new_error(reported); ptr_metadata_ty_or_tail then maps that error tail to unit metadata (ty::Error(_) => Ok(tcx.types.unit)) and the token is dropped there. The const evaluation continues with unit metadata and returns a successful Ok, so eval_constant has nothing to bubble. This is a single choke point, not a spread of sources, so the problem here is not that bubbling fails to scale to many emitters.

Making the token survive the recovery does not work, and this was tried two ways. Returning ty::Error metadata for an error tail globally in ptr_metadata_ty_or_tail turns the recovery into a runaway expansion: on the
test above the output grows from 13 errors and a clean abort to several million lines of struct-tail errors. Localizing the change so that only the trait-solver metadata projection keeps the ty::Error (matching what the new solver does in normalizes_to), while the direct ptr_metadata_ty callers in codegen, CTFE and layout still recover to unit, does make the note fire again, but it still does not terminate: the collector then spirals through ever-deeper VirtualWrapper<.., N> instantiations, emitting the note hundreds of thousands of times without aborting. The unit-metadata recovery for an error tail is not just hiding the token; it is what makes these tails Sized so the instantiation recursion can reach its limit and abort. It cannot be removed: this recovery is what avoids the original #114484 ICE (a rigid Pointee::Metadata projection left behind after the recursion limit), and ptr_metadata_ty_or_tail is context-agnostic, so it cannot be made to fail only on the CTFE path without re-introducing that ICE in layout and codegen.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 2, 2026
@rust-log-analyzer

This comment has been minimized.

@xmakro xmakro force-pushed the fix/parallel-pme-note-bubble branch from 38bb530 to e27e1f6 Compare June 2, 2026 16:28
@rust-log-analyzer

This comment has been minimized.

xmakro added 2 commits June 2, 2026 10:12
…count

`collect_items_rec` snapshots the error count before processing a mono item
and compares it afterwards to decide whether to attach the "the above error
was encountered while instantiating ..." note. The mono item graph is walked
in parallel, so the global error count can be bumped by an error emitted while
collecting a different item on another thread between the two reads, which
makes an unrelated item (often lang_start) get blamed.

Instead of consulting the global count, bubble up an `ErrorGuaranteed` from the
places that actually emit post-monomorphization errors during collection:
const-eval failures in `eval_constant` and, through `check_mono_item`, the
feature-dependent ABI checks and a `large_assignments` lint that has been
escalated to `deny`/`forbid`. `items_of_instance` now returns whether such an
error was encountered, and `collect_items_rec` uses that to decide whether to
emit the note. This is unaffected by what other threads are doing.

`large_assignments` is normally a warning and so does not hand back an
`ErrorGuaranteed`. When it is escalated to an error we recover the proof token
from the `DiagCtxt` right after emitting, gated on the lint's effective level
at the relevant node so the note is only attributed to an instantiation whose
own lint became the error.
These were marked ignore-parallel-frontend because the spurious instantiation
note made their output nondeterministic under -Zthreads. With that fixed they
pass reliably, so remove the directive and bless the line numbers that shift
from removing it.

Also add a regression test for a deny-level large_assignments lint inside a
generic function, which must produce the instantiation note now that the lint
is bubbled up as a post-monomorphization error.
@xmakro xmakro force-pushed the fix/parallel-pme-note-bubble branch from e27e1f6 to e1cade8 Compare June 2, 2026 17:13
@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)

17    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
18    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
19 
- note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<..., 1>>`
-   --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:38:18
-    |
- LL |         unsafe { virtualize_my_trait(L, self) }
-    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: the full name for the type has been written to '$TEST_BUILD_DIR/infinite-instantiation-struct-tail-ice-114484.long-type-$LONG_TYPE_HASH.txt'
-    = note: consider using `--verbose` to print the full type name to the console
- 
29 error: reached the recursion limit finding the struct tail for `SomeData<256>`
30    |
31    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`

45    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
46    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
47 
- note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<..., 1>>`
-   --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:38:18
-    |
- LL |         unsafe { virtualize_my_trait(L, self) }
-    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: the full name for the type has been written to '$TEST_BUILD_DIR/infinite-instantiation-struct-tail-ice-114484.long-type-$LONG_TYPE_HASH.txt'
-    = note: consider using `--verbose` to print the full type name to the console
- 
57 error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>`
58    |
59    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`

72    |
73    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
74    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
- 
- note: the above error was encountered while instantiating `fn virtualize_my_trait::<VirtualWrapper<..., 1>>`
-   --> $DIR/infinite-instantiation-struct-tail-ice-114484.rs:38:18
-    |
- LL |         unsafe { virtualize_my_trait(L, self) }
-    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    |
-    = note: the full name for the type has been written to '$TEST_BUILD_DIR/infinite-instantiation-struct-tail-ice-114484.long-type-$LONG_TYPE_HASH.txt'
-    = note: consider using `--verbose` to print the full type name to the console
84 
85 error: reached the recursion limit while instantiating `<VirtualWrapper<..., 1> as MyTrait>::virtualize`
86    |


The actual stderr differed from the expected stderr
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args infinite/infinite-instantiation-struct-tail-ice-114484.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/infinite/infinite-instantiation-struct-tail-ice-114484" "-A" "unused" "-W" "unused_attributes" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers" "--diagnostic-width=100" "-Zwrite-long-types-to-disk=yes"
stdout: none
--- stderr -------------------------------
error: reached the recursion limit finding the struct tail for `[u8; 256]`
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
---
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>`
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`

error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>`
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>`
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: reached the recursion limit finding the struct tail for `VirtualWrapper<SomeData<256>, 0>`
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: reached the recursion limit while instantiating `<VirtualWrapper<..., 1> as MyTrait>::virtualize`
   |
note: `<VirtualWrapper<T, L> as MyTrait>::virtualize` defined here
  --> /checkout/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs:37:5
   |
LL |     fn virtualize(&self) -> &dyn MyTrait {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: the full name for the type has been written to '/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/infinite/infinite-instantiation-struct-tail-ice-114484/infinite-instantiation-struct-tail-ice-114484.long-type-3066089734022795835.txt'
   = note: consider using `--verbose` to print the full type name to the console

error: aborting due to 13 previous errors
------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants