Skip to content

Introduce Unnormalized wrapper#155083

Open
adwinwhite wants to merge 4 commits intorust-lang:mainfrom
adwinwhite:introduce-unnormalized
Open

Introduce Unnormalized wrapper#155083
adwinwhite wants to merge 4 commits intorust-lang:mainfrom
adwinwhite:introduce-unnormalized

Conversation

@adwinwhite
Copy link
Copy Markdown
Contributor

@adwinwhite adwinwhite commented Apr 10, 2026

View all comments

This is the first step of the eager normalization series.

API changes are in the first commit. The compiler errors are mostly fixed via ast-grep, with exceptions handled manually.

This initial PR contains no behavior change.

r? @ghost

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. PG-exploit-mitigations Project group: Exploit mitigations 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 10, 2026
@adwinwhite
Copy link
Copy Markdown
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Apr 10, 2026
@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Apr 10, 2026
@rust-log-analyzer

This comment has been minimized.

@adwinwhite
Copy link
Copy Markdown
Contributor Author

@bors try cancel

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Apr 10, 2026

Try build cancelled. Cancelled workflows:

@rustbot rustbot added the T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. label Apr 10, 2026
@adwinwhite adwinwhite force-pushed the introduce-unnormalized branch from 309b0de to a616210 Compare April 10, 2026 07:51
@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added the T-clippy Relevant to the Clippy team. label Apr 10, 2026
@adwinwhite
Copy link
Copy Markdown
Contributor Author

@bors try @rust-timer queue

@rust-timer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors bot pushed a commit that referenced this pull request Apr 10, 2026
@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Apr 10, 2026

☀️ Try build successful (CI)
Build commit: 10d0ef4 (10d0ef4e7995ca1d162f402be9f0b39b15d7a78a, parent: 7659cec4ed1457bc0d1f636127e66e8fe5008928)

@rust-timer

This comment has been minimized.

@rust-timer
Copy link
Copy Markdown
Collaborator

Finished benchmarking commit (10d0ef4): comparison URL.

Overall result: no relevant changes - no action needed

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.

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

Instruction count

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

Max RSS (memory usage)

Results (primary -2.4%, secondary -6.4%)

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)
- - 0
Improvements ✅
(primary)
-2.4% [-2.4%, -2.4%] 1
Improvements ✅
(secondary)
-6.4% [-6.4%, -6.4%] 1
All ❌✅ (primary) -2.4% [-2.4%, -2.4%] 1

Cycles

Results (secondary -0.7%)

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)
2.4% [2.1%, 2.7%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-3.7% [-3.8%, -3.6%] 2
All ❌✅ (primary) - - 0

Binary size

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

Bootstrap: 492.281s -> 489.321s (-0.60%)
Artifact size: 395.57 MiB -> 395.56 MiB (-0.00%)

@rustbot rustbot removed the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Apr 10, 2026
@adwinwhite adwinwhite force-pushed the introduce-unnormalized branch from 3b64c2b to 5407a88 Compare April 10, 2026 13:37
@adwinwhite
Copy link
Copy Markdown
Contributor Author

r? @lcnr

@adwinwhite adwinwhite marked this pull request as ready for review April 10, 2026 13:41
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 10, 2026

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in abstract_const.rs

cc @BoxyUwU

Some changes occurred to the core trait solver

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

Some changes occurred in need_type_info.rs

cc @lcnr

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_sanitizers

cc @rcvalle

HIR ty lowering was modified

cc @fmease

Some changes occurred in match checking

cc @Nadrieril

Some changes occurred to constck

cc @fee1-dead

Some changes occurred in exhaustiveness checking

cc @Nadrieril

changes to the core type system

cc @lcnr

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

The Miri subtree was changed

cc @rust-lang/miri

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 10, 2026
Unnormalized { value }
}

pub fn skip_normalization(self) -> T {
Copy link
Copy Markdown
Member

@RalfJung RalfJung Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

Please also add a doc comment to this function giving the rest of us compiler folks some hint of what this is all about when we encounter it in the source. :)

pub fn instantiate_own_identity(
self,
) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
) -> impl Iterator<Item = Unnormalized<(Clause<'tcx>, Span)>> + DoubleEndedIterator + ExactSizeIterator
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

`(Unnormalized<Clause<'tcx>>, Span)

args: GenericArgsRef<'tcx>,
) -> impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
{
) -> impl Iterator<Item = Unnormalized<(ty::PolyTraitRef<'tcx>, Span)>>
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

same for all the other ones, no need to wrap the span with Unnormalized. Only need to do so for things which contain types

pub fn instantiate_identity(
self,
tcx: TyCtxt<'tcx>,
) -> Unnormalized<InstantiatedPredicates<'tcx>> {
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

instead change InstantiatedPredicates to contain Unnormalized clauses

pub struct IterIdentityCopied<Iter: IntoIterator> {
pub struct IterIdentityCopied<I: Interner, Iter: IntoIterator> {
it: Iter::IntoIter,
_tcx: PhantomData<fn() -> I>,
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

what do we need this one for?

@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job pr-check-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
- compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
- compiler/rustc_borrowck/src/type_check/mod.rs
- compiler/rustc_borrowck/src/universal_regions.rs
- ... and 184 more
skipping rustc download due to `download-rustc = 'if-unchanged'`
##[group]Checking stage1 compiler artifacts{rustc-main, rustc_abi, rustc_arena, rustc_ast, rustc_ast_ir, rustc_ast_lowering, rustc_ast_passes, rustc_ast_pretty, rustc_attr_parsing, rustc_baked_icu_data, rustc_borrowck, rustc_builtin_macros, rustc_codegen_llvm, rustc_codegen_ssa, rustc_const_eval, rustc_data_structures, rustc_driver, rustc_driver_impl, rustc_error_codes, rustc_error_messages, rustc_errors, rustc_expand, rustc_feature, rustc_fs_util, rustc_graphviz, rustc_hashes, rustc_hir, rustc_hir_analysis, rustc_hir_id, rustc_hir_pretty, rustc_hir_typeck, rustc_incremental, rustc_index, rustc_index_macros, rustc_infer, rustc_interface, rustc_lexer, rustc_lint, rustc_lint_defs, rustc_llvm, rustc_log, rustc_macros, rustc_metadata, rustc_middle, rustc_mir_build, rustc_mir_dataflow, rustc_mir_transform, rustc_monomorphize, rustc_next_trait_solver, rustc_parse, rustc_parse_format, rustc_passes, rustc_pattern_analysis, rustc_privacy, rustc_proc_macro, rustc_public, rustc_public_bridge, rustc_query_impl, rustc_resolve, rustc_sanitizers, rustc_serialize, rustc_session, rustc_span, rustc_symbol_mangling, rustc_target, rustc_thread_pool, rustc_trait_selection, rustc_traits, rustc_transmute, rustc_ty_utils, rustc_type_ir, rustc_type_ir_macros, rustc_windows_rc} (stage0 -> stage1, x86_64-unknown-linux-gnu)
##[endgroup]
##[group]Checking stage1 compiler artifacts (stage0 -> stage1, x86_64-unknown-linux-gnu)
##[endgroup]
##[group]Checking stage1 rustdoc (stage0 -> stage1, x86_64-unknown-linux-gnu)
---


# RECOMMENDATIONS

* Fix missing copyright/licensing information: For one or more files, the tool
  cannot find copyright and/or licensing information. You typically do this by
  adding 'SPDX-FileCopyrightText' and 'SPDX-License-Identifier' tags to each
  file. The tutorial explains additional ways to do this:
  <https://reuse.software/tutorial/>

  local time: Fri Apr 10 14:34:59 UTC 2026
  network time: Fri, 10 Apr 2026 14:34:59 GMT
##[error]Process completed with exit code 1.
##[group]Run echo "disk usage:"

Comment on lines +480 to +481
.skip_normalization()
.skip_binder()
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

can you add fn skip_binder to Unnormalized<[Early]Binder<T>> directly. When skipping binders we also don't care about normalization

// This keeps us from suggesting borrowing the argument to `mem::drop`, e.g.
if !clauses.instantiate_identity(tcx).predicates.iter().any(|clause| {
if !clauses.instantiate_identity(tcx).skip_normalization().predicates.iter().any(|clause| {
clause.as_trait_clause().is_some_and(|tc| {
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

we probably want a function fn as_trait_clause on Unnormalized to return Unnormalized<Binder<PolyTraitClause>> and duplicate a bunch of the field projections we already have for binder, instead also returning Unnormalized` of the field/wrapped thing

ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args).skip_normalization();
let new_ty =
ty::EarlyBinder::bind(ty).instantiate(tcx, new_args).skip_normalization();
if let Ok(old_ty) = tcx.try_normalize_erasing_regions(
Copy link
Copy Markdown
Contributor

@lcnr lcnr Apr 10, 2026

Choose a reason for hiding this comment

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

View changes since the review

I would try to change fn try_normalize_erasing_regions to take Unnormalized<T> and return T and then avoid the skip_normalization here

Copy link
Copy Markdown
Contributor

@lcnr lcnr left a comment

Choose a reason for hiding this comment

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

I am not totally sure how to best land this change, so do push back if you think any change here makes this PR worse to land instead of better.

I think all the places that do correctly normalize should not have to do skip_normalization by having normalization take an Unnormalized<T> in this PR already 🤔

I think any place where wiring the Unnormalized<T> to the normalize call isn't completely trivial can keep using skip_binder and Unnormalized::new, but having a skip_normalization call right above a call to normalize seems suboptimal 😅

View changes since this review

@adwinwhite
Copy link
Copy Markdown
Contributor Author

I think all the places that do correctly normalize should not have to do skip_normalization by having normalization take an Unnormalized in this PR already 🤔

I think any place where wiring the Unnormalized to the normalize call isn't completely trivial can keep using skip_binder and Unnormalized::new, but having a skip_normalization call right above a call to normalize seems suboptimal 😅

I didn't change normalization routines to make the initial PR trivial.
Changing all normalization routines to take Unnormalized is much more involved as you need to inspect each case.

But perhaps I could do that for the most used routines one by one, like fcx.normalize, ocx.normalize, tcx.normalize_erasing_regions and so on.

@lcnr
Copy link
Copy Markdown
Contributor

lcnr commented Apr 10, 2026

I think yeah, maybe we do want to land this PR as is, without consuming Unnormalized anywhere, only making sure the core API introducing Unnormalized makes sense.

Have separate PRs which adds Unnormalized as input to all the normalization routines and cleans stuff up this way as in one PR adds it to try_normalize_erasing_regions another one to ocx.normalize.

That way we can also split up to work over multiple people if more people want to be involved.

What else might work 🤔

we could instead do a rename of Binder.instantiate to instantiate_unnormalized, and add instantiate() -> Unnormalized, then have the normalization routines take Unnormalized and start out by just wrapping the arguments with Unnormalized::new_wip at most call-sites, and then have people migrate this over on a per-crate basis?

unsure, could try to push this PR through as is, but ideally we can split this up as much as possible without having a lot of redundant steps. This way other people can also review some of the work.

@lcnr
Copy link
Copy Markdown
Contributor

lcnr commented Apr 10, 2026

maybe doing it for some of the normalization routines is actually making the diff smaller? You could definitely try it for normalize_erasing_regions and look at how this impacts the diff 🤔 I think making the Unnormalized

genuinely just a big change :3

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

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. PG-exploit-mitigations Project group: Exploit mitigations S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-rustdoc-frontend Relevant to the rustdoc-frontend team, which will review and decide on the web UI/UX output. 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.

6 participants