abby: always store nextgen region constraints in canonical form - #161306
abby: always store nextgen region constraints in canonical form#161306BoxyUwU wants to merge 24 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
d860264 to
c64bf00
Compare
This comment has been minimized.
This comment has been minimized.
c64bf00 to
57b2d5e
Compare
This comment has been minimized.
This comment has been minimized.
57b2d5e to
c17800a
Compare
This comment has been minimized.
This comment has been minimized.
aba4012 to
56320f9
Compare
This comment has been minimized.
This comment has been minimized.
5bedfe3 to
65f3b73
Compare
This comment has been minimized.
This comment has been minimized.
a10cd16 to
930ca67
Compare
This comment has been minimized.
This comment has been minimized.
930ca67 to
1bead00
Compare
This comment has been minimized.
This comment has been minimized.
|
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. |
5555820 to
7748294
Compare
This comment has been minimized.
This comment has been minimized.
|
did it take me too long to rebase and I need to rebase again lolsob |
| .into_iter() | ||
| .map(|item| self.lower_test_binder_constraint(item)) | ||
| .reduce(SolverRegionConstraint::new_or) | ||
| .unwrap_or(SolverRegionConstraint::new_true()), |
There was a problem hiding this comment.
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~)
There was a problem hiding this comment.
an empty OR should be false, should it not?
There was a problem hiding this comment.
It is not if you implement it wrong like I did
|
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( |
There was a problem hiding this comment.
consider moving these functions into an eager_placeholder_handling module and removing the for_X from their name :> horribly long name
| /// 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 { |
There was a problem hiding this comment.
removing canonical_form in this commit feels wrong :>
There was a problem hiding this comment.
hmm should just rename the commit. this was mostly intended as a "delete a bunch of junk to make the diff nicer"
| // 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(()), |
There was a problem hiding this comment.
vibe for future PR, have a NoSpans type instead of using () as () here is slightly confusing.
There was a problem hiding this comment.
| } | ||
|
|
||
| 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? |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
|
going to make canonical form be span insensitive |
|
The job Click to see the possible cause of the failure (guessed by this bot) |
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
RegionConstraintis:RegionConstraintcontains two things: anAND of LEAFsand anOR of AND of LEAFs. Another way of thinking about it would be to say its anANDconsisting of arbitrarily many LEAFs and a singleOR of AND of LEAFsfalsethen we wipe the top levelANDas it doesn't matter what they are, the constraint is always going to be falsethis 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/corewith-Zassumptions-on-bindersas we would otherwise OOM from having both:And('a: 'b, 'a: 'b))OR(e.g.Or(And('a: 'b, 'b: 'c), And('a: 'b, 'b: 'd)))Some future work:
RegionConstraint::splatted_and_constraintsit's kind of weird to even need it and probably encourages bad-for-perf patternsRegionConstraint. Perf stuff :3In 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 formwhich actually replacesRegionConstraintwith all the new types and updates all the locations using them.Finally there's
propagate ambiguity not evaluatewhich deals with the leftoverevaluate_solver_constraintwhich was mostly unnecessary now due to moving its main logic into construction ofRegionConstraintand friends. I didn't want to make actual bug fixes in this PR so I just left some FIXMEs about some of the issues thatpropagate_ambiguityhas instead of fixing them here.Fixes rust-lang/project-assumptions-on-binders#14