Skip to content

Improve canonicalization performance by introducing TypingMode::ErasedNotCoherence#155443

Open
jdonszelmann wants to merge 9 commits intorust-lang:mainfrom
jdonszelmann:canonical
Open

Improve canonicalization performance by introducing TypingMode::ErasedNotCoherence#155443
jdonszelmann wants to merge 9 commits intorust-lang:mainfrom
jdonszelmann:canonical

Conversation

@jdonszelmann
Copy link
Copy Markdown
Contributor

@jdonszelmann jdonszelmann commented Apr 17, 2026

r? @lcnr

This introduces TypingMode::ErasedNotCoherence. Most typing modes contain a list of opaque types, which are quite often unused during canonicalization. With this change, any time we try canonicalization, we replace whichever typing mode we're currently in with ErasedNotcoherence, attempt to canonicalize, and if that fails retry in the original typing mode. If erased mode succeeds, this is beneficial because that way the opaque types don't end up in the cache key, allowing more cache reuse.

This seems to have a small (0.5%) slowdown on most programs, but a dramatic (>60%) speedup in specific cases like the rustc-perf wg-grammar benchmark. Some more improvements are expected with "eager normalization", which is work that's under way right now.

@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. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver) labels Apr 17, 2026
@jdonszelmann
Copy link
Copy Markdown
Contributor Author

@bors try

@rust-bors

This comment has been minimized.

@jdonszelmann
Copy link
Copy Markdown
Contributor Author

@bors try parent=14196dbfa3eb7c30195251eac092b1b86c8a2d84

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 17, 2026
[DO NOT MERGE] Improve canonicalization performance
@jdonszelmann
Copy link
Copy Markdown
Contributor Author

@rust-timer queue

@rust-timer

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Apr 17, 2026
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 17, 2026

☀️ Try build successful (CI)
Build commit: db1df07 (db1df07682e37be559858ab003b949a2c17b5b3b, parent: 14196dbfa3eb7c30195251eac092b1b86c8a2d84)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (db1df07): comparison URL.

Overall result: ❌✅ regressions and improvements - please read:

Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf.

Next, please: If you can, justify the regressions found in this try perf run in writing along with @rustbot label: +perf-regression-triaged. If not, fix the regressions and do another perf run. Neutral or positive results will clear the label automatically.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.8% [0.2%, 1.8%] 11
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.6% [-1.0%, -0.2%] 2
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (primary -0.9%, secondary 1.7%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
1.1% [1.1%, 1.1%] 1
Regressions ❌
(secondary)
1.7% [1.0%, 2.6%] 7
Improvements ✅
(primary)
-2.8% [-2.8%, -2.8%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -0.9% [-2.8%, 1.1%] 2

Cycles

Results (primary -2.4%, secondary 28.5%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
28.5% [28.5%, 28.5%] 1
Improvements ✅
(primary)
-2.4% [-2.4%, -2.4%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -2.4% [-2.4%, -2.4%] 1

Binary size

This perf run didn't have relevant results for this metric.

Bootstrap: 491.114s -> 492.029s (0.19%)
Artifact size: 394.23 MiB -> 394.80 MiB (0.14%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Apr 17, 2026
@jdonszelmann jdonszelmann marked this pull request as ready for review April 28, 2026 08:12
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 28, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 28, 2026

changes to the core type system

cc @lcnr

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred to the core trait solver

cc @rust-lang/initiative-trait-system-refactor

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Apr 28, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@jdonszelmann jdonszelmann changed the title [DO NOT MERGE] Improve canonicalization performance Improve canonicalization performance by introducing TypingMode::ErasedNotCoherence Apr 28, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job x86_64-gnu-gcc failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
---- [run-make] tests/run-make-cargo/rustc-crates-on-stable stdout ----

error: rmake recipe failed to complete
status: exit status: 1
command: cd "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-make-cargo/rustc-crates-on-stable/rmake_out" && env -u RUSTFLAGS -u __RUSTC_DEBUG_ASSERTIONS_ENABLED -u __STD_DEBUG_ASSERTIONS_ENABLED -u __STD_REMAP_DEBUGINFO_ENABLED AR="ar" BUILD_ROOT="/checkout/obj/build/x86_64-unknown-linux-gnu" CARGO="/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools-bin/cargo" CC="cc" CC_DEFAULT_FLAGS="-ffunction-sections -fdata-sections -fPIC -m64" CXX="c++" CXX_DEFAULT_FLAGS="-ffunction-sections -fdata-sections -fPIC -m64" HOST_RUSTC_DYLIB_PATH="/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" LD_LIBRARY_PATH="/checkout/obj/build/x86_64-unknown-linux-gnu/bootstrap-tools/x86_64-unknown-linux-gnu/release/deps:/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib" LD_LIB_PATH_ENVVAR="LD_LIBRARY_PATH" LLVM_BIN_DIR="/checkout/obj/build/x86_64-unknown-linux-gnu/ci-llvm/bin" LLVM_COMPONENTS="aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils abi aggressiveinstcombine all all-targets amdgpu amdgpuasmparser amdgpucodegen amdgpudesc amdgpudisassembler amdgpuinfo amdgputargetmca amdgpuutils analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils asmparser asmprinter avr avrasmparser avrcodegen avrdesc avrdisassembler avrinfo binaryformat bitreader bitstreamreader bitwriter bpf bpfasmparser bpfcodegen bpfdesc bpfdisassembler bpfinfo cas cfguard cgdata codegen codegentypes core coroutines coverage csky cskyasmparser cskycodegen cskydesc cskydisassembler cskyinfo debuginfobtf debuginfocodeview debuginfodwarf debuginfodwarflowlevel debuginfogsym debuginfologicalview debuginfomsf debuginfopdb demangle dlltooldriver dtlto dwarfcfichecker dwarflinker dwarflinkerclassic dwarflinkerparallel dwp engine executionengine extensions filecheck frontendatomic frontenddirective frontenddriver frontendhlsl frontendoffloading frontendopenacc frontendopenmp fuzzercli fuzzmutate globalisel hexagon hexagonasmparser hexagoncodegen hexagondesc hexagondisassembler hexagoninfo hipstdpar instcombine instrumentation interfacestub interpreter ipo irprinter irreader jitlink libdriver lineeditor linker loongarch loongarchasmparser loongarchcodegen loongarchdesc loongarchdisassembler loongarchinfo lto m68k m68kasmparser m68kcodegen m68kdesc m68kdisassembler m68kinfo mc mca mcdisassembler mcjit mcparser mips mipsasmparser mipscodegen mipsdesc mipsdisassembler mipsinfo mirparser msp430 msp430asmparser msp430codegen msp430desc msp430disassembler msp430info native nativecodegen nvptx nvptxcodegen nvptxdesc nvptxinfo objcarcopts objcopy object objectyaml option orcdebugging orcjit orcshared orctargetprocess passes plugins powerpc powerpcasmparser powerpccodegen powerpcdesc powerpcdisassembler powerpcinfo profiledata remarks riscv riscvasmparser riscvcodegen riscvdesc riscvdisassembler riscvinfo riscvtargetmca runtimedyld sandboxir scalaropts selectiondag sparc sparcasmparser sparccodegen sparcdesc sparcdisassembler sparcinfo support supportlsp symbolize systemz systemzasmparser systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen target targetparser telemetry textapi textapibinaryreader transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler webassemblyinfo webassemblyutils windowsdriver windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info x86targetmca xray xtensa xtensaasmparser xtensacodegen xtensadesc xtensadisassembler xtensainfo" LLVM_FILECHECK="/checkout/obj/build/x86_64-unknown-linux-gnu/ci-llvm/bin/FileCheck" PYTHON="/usr/bin/python3" RUSTC="/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" RUSTDOC="/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustdoc" SOURCE_ROOT="/checkout" TARGET="x86_64-unknown-linux-gnu" TARGET_EXE_DYLIB_PATH="/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" __BOOTSTRAP_JOBS="4" __RMAKE_VERBOSE_SUBPROCESS_OUTPUT="1" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-make-cargo/rustc-crates-on-stable/rmake"
stdout: none
--- stderr -------------------------------
command failed at line 41
LD_LIBRARY_PATH="/checkout/obj/build/x86_64-unknown-linux-gnu/test/run-make-cargo/rustc-crates-on-stable/rmake_out:/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib:/checkout/obj/build/x86_64-unknown-linux-gnu/bootstrap-tools/x86_64-unknown-linux-gnu/release/deps:/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/lib/rustlib/x86_64-unknown-linux-gnu/lib" RUSTC="/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" RUSTC_STAGE="0" RUSTFLAGS="-Zallow-features=" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools-bin/cargo" "build" "--manifest-path" "/checkout/Cargo.toml" "--no-default-features" "--target-dir" "target" "-p" "rustc_type_ir" "-p" "rustc_next_trait_solver" "-p" "rustc_pattern_analysis" "-p" "rustc_lexer" "-p" "rustc_abi" "-p" "rustc_parse_format" "-p" "rustc_hashes"
output status: `exit status: 101`
=== STDOUT ===



=== STDERR ===
    Blocking waiting for file lock on package cache
---

error: cannot find derive macro `GenericTypeVisitable` in this scope
##[error]   --> compiler/rustc_type_ir/src/solve/mod.rs:318:33
    |
318 | #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
    |                                 ^^^^^^^^^^^^^^^^^^^^
    |
help: consider importing one of these derive macros
    |
  3 + use crate::GenericTypeVisitable;

For more information how to resolve CI failures of this job, visit this link.

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 29, 2026

☔ The latest upstream changes (presumably #155953) made this pull request unmergeable. Please resolve the merge conflicts.

Comment thread compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs Outdated
Comment thread compiler/rustc_type_ir/src/solve/mod.rs Outdated
Comment thread compiler/rustc_type_ir/src/solve/mod.rs Outdated
Comment thread compiler/rustc_type_ir/src/solve/mod.rs Outdated
Comment thread compiler/rustc_const_eval/src/const_eval/valtrees.rs
Comment thread compiler/rustc_infer/src/infer/mod.rs
Comment on lines +1072 to +1076
// If we get here in erased mode, we don't know the original typing mode.
// It could be post analysis, or something else.
// Regardless of what it was, we want to continue in erased mode,
// if we end up accessing any opaque types we bail out anyway.
| TypingMode::ErasedNotCoherence(MayBeErased) => return self,
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not too happy about this, want to get back to this

View changes since the review

Comment thread compiler/rustc_mir_transform/src/elaborate_drop.rs
Comment thread compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Comment thread compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
self.opaque_accesses
.rerun_if_in_post_analysis("normalize opaque type non local");
}
if self.opaque_accesses.should_bail() {
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

canfn rerun_if_in_post_analysis just return a Result<(), ShouldBail> or what not so we don't have to manually call should_bail afterwards

View changes since the review

Comment thread compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
Comment thread compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -71,7 +71,13 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
// FIXME: Properly consider opaques here.
&& self.inner.borrow_mut().opaque_types().is_empty()
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe have a self.known_no_opaque_types_in_storage which returns false if typng mode is erased?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we still should return None though right? Cause we can keep the fast path

Comment thread compiler/rustc_trait_selection/src/traits/normalize.rs
Comment thread compiler/rustc_ty_utils/src/instance.rs
Comment thread compiler/rustc_type_ir/src/relate/combine.rs
Comment thread compiler/rustc_type_ir/src/search_graph/mod.rs
Comment thread compiler/rustc_type_ir/src/infer_ctxt.rs
Comment thread tests/ui/traits/next-solver/canonical/erased-opaques.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-trait-system-refactor The Rustc Trait System Refactor Initiative (-Znext-solver)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants