Skip to content

abby: always store nextgen region constraints in canonical form - #161306

Open
BoxyUwU wants to merge 24 commits into
rust-lang:mainfrom
BoxyUwU:abby_canonical_form_always
Open

abby: always store nextgen region constraints in canonical form#161306
BoxyUwU wants to merge 24 commits into
rust-lang:mainfrom
BoxyUwU:abby_canonical_form_always

Conversation

@BoxyUwU

@BoxyUwU BoxyUwU commented Aug 18, 2026

Copy link
Copy Markdown
Member

View all comments

title. introduce an And/Or/LeafConstraint/ types to reason about the structure of our region constraints. Never produce arbitrarily nested or/ands and always have constraints in an evaluated form.

I kinda mucked up this PR and accidentally did two things at the same time. Not only do we immediately put everything into canonical form, we also change what it means for a region constraint to be in canonical form. Whoops :>

Rough overview of what a RegionConstraint is:

  • RegionConstraint contains two things: an AND of LEAFs and an OR of AND of LEAFs. Another way of thinking about it would be to say its an AND consisting of arbitrarily many LEAFs and a single OR of AND of LEAFs
  • There are never any region constraints shared between all ANDs of the OR, instead they're moved into the top level AND
  • If the OR constraint is false then we wipe the top level AND as it doesn't matter what they are, the constraint is always going to be false
  • ORs never have two equivalent ANDs within them. Similarly, ANDs never have two equivalent LEAFs within them

this simplifies a lot of things conceptually as we now no longer need to worry about what state our region constraints are in. and our algorithms also don't need to handle arbitrary nesting of ors/ands :) and its a lot easier to read the debug logs 😅

I also wound up needing to do this while trying to compile std/core with -Zassumptions-on-binders as we would otherwise OOM from having both:

  • Lots of duplicate region constraints (e.g. And('a: 'b, 'a: 'b))
  • Lots of region constraints shared across all elements of an OR (e.g. Or(And('a: 'b, 'b: 'c), And('a: 'b, 'b: 'd)))

Some future work:

  • Remove RegionConstraint::splatted_and_constraints it's kind of weird to even need it and probably encourages bad-for-perf patterns
  • we Probably want some kind of fast path for pushing new leaf constraints to the region constraint storage. slash have a way to register a leaf constraint directly rather than having to make a RegionConstraint. Perf stuff :3

In theory this PR should mostly not have functional changes. In practice it might affect some things due to changing the exact repr of things affecting query responses. There's probably also some behaviour differences here due to us falling on our face more or less in WIP parts of abby now that we have different region constraints. I don't think any of this should be meaningful though. This PR is intended to not fundamentally change the abby algorithm :3

This PR should be reviewed commit-by-commit. There are a bunch of commits restructuring existing logic to assume their input is in canonical form as it will be by the end of the PR.

Then there's the core change in always canonical form which actually replaces RegionConstraint with all the new types and updates all the locations using them.

Finally there's propagate ambiguity not evaluate which deals with the leftover evaluate_solver_constraint which was mostly unnecessary now due to moving its main logic into construction of RegionConstraint and friends. I didn't want to make actual bug fixes in this PR so I just left some FIXMEs about some of the issues that propagate_ambiguity has instead of fixing them here.

Fixes rust-lang/project-assumptions-on-binders#14

@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 Aug 18, 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.

@BoxyUwU
BoxyUwU force-pushed the abby_canonical_form_always branch 5 times, most recently from d860264 to c64bf00 Compare August 21, 2026 13:36
@rust-log-analyzer

This comment has been minimized.

@BoxyUwU
BoxyUwU force-pushed the abby_canonical_form_always branch from c64bf00 to 57b2d5e Compare August 21, 2026 14:12
@rust-log-analyzer

This comment has been minimized.

@BoxyUwU
BoxyUwU force-pushed the abby_canonical_form_always branch from 57b2d5e to c17800a Compare August 21, 2026 14:38
@rust-log-analyzer

This comment has been minimized.

@BoxyUwU
BoxyUwU force-pushed the abby_canonical_form_always branch 2 times, most recently from aba4012 to 56320f9 Compare August 21, 2026 14:52
@rust-log-analyzer

This comment has been minimized.

@BoxyUwU
BoxyUwU force-pushed the abby_canonical_form_always branch 2 times, most recently from 5bedfe3 to 65f3b73 Compare August 21, 2026 15:07
@rust-log-analyzer

This comment has been minimized.

@BoxyUwU
BoxyUwU force-pushed the abby_canonical_form_always branch from a10cd16 to 930ca67 Compare August 21, 2026 16:15
@rust-log-analyzer

This comment has been minimized.

@BoxyUwU

BoxyUwU commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

r? @lcnr @khyperia

@rust-log-analyzer

This comment has been minimized.

@BoxyUwU
BoxyUwU marked this pull request as ready for review August 21, 2026 16:42
@rustbot

rustbot commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

This comment has been minimized.

@BoxyUwU

BoxyUwU commented Aug 27, 2026

Copy link
Copy Markdown
Member Author

did it take me too long to rebase and I need to rebase again lolsob

@khyperia khyperia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

looks good to me! didn't rereview region_constraint.rs suuuper closely, mostly just assuming you haven't committed terrible crimes in the rebase ✨

View changes since this review

Comment thread compiler/rustc_infer/src/infer/outlives/obligations.rs Outdated
Comment thread compiler/rustc_hir_analysis/src/check/wfcheck.rs Outdated
.into_iter()
.map(|item| self.lower_test_binder_constraint(item))
.reduce(SolverRegionConstraint::new_or)
.unwrap_or(SolverRegionConstraint::new_true()),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this took me a moment, aaah, the SolverRegionConstraint::new_{and,or} auto-canonicalize as they're constructing. neat! (if I did this myself I might have rejected noncanonical syntax as invalid, but canonicalizing it makes sense too~)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

an empty OR should be false, should it not?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It is not if you implement it wrong like I did

@BoxyUwU

BoxyUwU commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

Should move the trait bounds on the span generic parameter into a new trait with a blanket impl to avoid the boilerplate everywhere actually

}

Or(candidates.into_boxed_slice())
rewrite_placeholder_ty_outlives_constraints_in_universe_for_eager_placeholder_handling(

@lcnr lcnr Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

consider moving these functions into an eager_placeholder_handling module and removing the for_X from their name :> horribly long name

View changes since the review

/// Converts the region constraint into an ORs of ANDs of "leaf" constraints. Where
/// a leaf constraint is a non-or/and constraint.
#[instrument(level = "debug", ret)]
pub fn canonical_form(self) -> Self {

@lcnr lcnr Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

removing canonical_form in this commit feels wrong :>

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hmm should just rename the commit. this was mostly intended as a "delete a bunch of junk to make the diff nicer"

Comment thread compiler/rustc_infer/src/infer/outlives/obligations.rs
Comment thread compiler/rustc_hir_analysis/src/check/wfcheck.rs Outdated
Comment thread compiler/rustc_hir_analysis/src/check/wfcheck.rs Outdated
Comment thread compiler/rustc_hir_analysis/src/check/wfcheck.rs Outdated
// The alias is either rigid or ambiguous in which case we'll return with ambiguity.
Alias(_, alias) => self.destructure_alias_outlives(*alias, r),
UnresolvedInferenceVariable(_) => RegionConstraint::Ambiguity(()),
UnresolvedInferenceVariable(_) => Or::new_ambig(()),

@lcnr lcnr Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

vibe for future PR, have a NoSpans type instead of using () as () here is slightly confusing.

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Comment thread compiler/rustc_type_ir/src/region_constraint.rs Outdated

@lcnr lcnr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

none of this is blocking this PR itself

View changes since this review

}

pub fn new_and(a: Or<I, S>, b: Or<I, S>) -> Self {
// I think this returns false if either a or b is false?

@lcnr lcnr Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

horrible comment 🤣

yes, this returns Empty if one of the two is empty. We're building the cartesian product here.

This function also doesn't return something in canonical form, does it? if you have

[[A, B], [A]] and [[C], [B, C]] you end up with [A, B, C], [A, B, C] (deduped by And::new 🤔), [A, C], and another [A, B, C]

might be good to have a new_raw with a debug_assert that we're in canonical form?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Or::new does all the actual canonicalizing which is I guess the equivalent to your new_raw 🤔 having a debug assert would be nice though

Comment thread compiler/rustc_type_ir/src/region_constraint.rs
Comment thread compiler/rustc_type_ir/src/region_constraint.rs
Comment thread compiler/rustc_type_ir/src/region_constraint.rs
@BoxyUwU

BoxyUwU commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

going to make canonical form be span insensitive

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

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

Click to see the possible cause of the failure (guessed by this bot)
 Documenting rustc_middle v0.0.0 (/checkout/compiler/rustc_middle)
[RUSTC-TIMING] rustc_next_trait_solver test:false 1.740
 Documenting rustc_llvm v0.0.0 (/checkout/compiler/rustc_llvm)
 Documenting rustc_ast_passes v0.0.0 (/checkout/compiler/rustc_ast_passes)
warning: unresolved link to `RegionConstraint::AliasTyOutlivesViaEnv`
   --> compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs:191:52
    |
191 |     ///     when exiting the current binder. See [`RegionConstraint::AliasTyOutlivesViaEnv`].
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `RegionConstraint` in scope
    |
    = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default

 Documenting rustc_windows_rc v0.0.0 (/checkout/compiler/rustc_windows_rc)
error: `rustc_next_trait_solver` (lib doc) generated 1 warning
error: warnings are denied by `build.warnings` configuration
warning: build failed, waiting for other jobs to finish...
[RUSTC-TIMING] rustc_middle test:false 13.522
Bootstrap failed while executing `doc compiler --stage 1`
Currently active steps:
doc::Rustc { build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, crates: ["rustc-main", "rustc_abi", "rustc_arena", "rustc_ast", "rustc_ast_ir", "rustc_ast_lowering", "rustc_ast_passes", "rustc_ast_pretty", "rustc_attr_ir", "rustc_attr_parsing", "rustc_baked_icu_data", "rustc_borrowck", "rustc_builtin_macros", "rustc_codegen_llvm", "rustc_codegen_ssa", "rustc_const_eval", "rustc_crate_store", "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_structures", "rustc_symbol_mangling", "rustc_target", "rustc_thread_pool", "rustc_trait_selection", "rustc_traits", "rustc_transmute", "rustc_ty_utils", "rustc_ty_walk", "rustc_type_ir", "rustc_type_ir_macros", "rustc_windows_rc"] } at src/bootstrap/src/core/build_steps/doc.rs:916
Command `/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo doc --target x86_64-unknown-linux-gnu -Zbinary-dep-depinfo -j 4 -Zroot-dir=/checkout -Zembed-metadata=no --locked --color=always --profile=release --features 'llvm rustc' --manifest-path /checkout/compiler/rustc/Cargo.toml -Zskip-rustdoc-fingerprint --no-deps -Zrustdoc-map -p rustc-main -p rustc_abi -p rustc_arena -p rustc_ast -p rustc_ast_ir -p rustc_ast_lowering -p rustc_ast_passes -p rustc_ast_pretty -p rustc_attr_ir -p rustc_attr_parsing -p rustc_baked_icu_data -p rustc_borrowck -p rustc_builtin_macros -p rustc_codegen_llvm -p rustc_codegen_ssa -p rustc_const_eval -p rustc_crate_store -p rustc_data_structures -p rustc_driver -p rustc_driver_impl -p rustc_error_codes -p rustc_error_messages -p rustc_errors -p rustc_expand -p rustc_feature -p rustc_fs_util -p rustc_graphviz -p rustc_hashes -p rustc_hir -p rustc_hir_analysis -p rustc_hir_id -p rustc_hir_pretty -p rustc_hir_typeck -p rustc_incremental -p rustc_index -p rustc_index_macros -p rustc_infer -p rustc_interface -p rustc_lexer -p rustc_lint -p rustc_lint_defs -p rustc_llvm -p rustc_log -p rustc_macros -p rustc_metadata -p rustc_middle -p rustc_mir_build -p rustc_mir_dataflow -p rustc_mir_transform -p rustc_monomorphize -p rustc_next_trait_solver -p rustc_parse -p rustc_parse_format -p rustc_passes -p rustc_pattern_analysis -p rustc_privacy -p rustc_proc_macro -p rustc_public -p rustc_public_bridge -p rustc_query_impl -p rustc_resolve -p rustc_sanitizers -p rustc_serialize -p rustc_session -p rustc_span -p rustc_structures -p rustc_symbol_mangling -p rustc_target -p rustc_thread_pool -p rustc_trait_selection -p rustc_traits -p rustc_transmute -p rustc_ty_utils -p rustc_ty_walk -p rustc_type_ir -p rustc_type_ir_macros -p rustc_windows_rc [workdir=/checkout]` failed with exit code 101
Created at: src/bootstrap/src/core/build_steps/doc.rs:946:25
Executed at: src/bootstrap/src/core/build_steps/doc.rs:1007:26

Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:00:37
  local time: Fri Aug 28 14:36:53 UTC 2026
  network time: Fri, 28 Aug 2026 14:36:53 GMT
##[error]Process completed with exit code 1.
##[group]Run echo "disk usage:"

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

Labels

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.

[Work Item]: Only have canonical form region constraints

5 participants