-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
trait_selection: Keep type-op region constraints in borrowck #161423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2a56108
dc2e6c6
38a8b95
69745c2
231cb46
96e94dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,13 +76,21 @@ pub struct QueryResponse<'tcx, R> { | |
| pub value: R, | ||
| } | ||
|
|
||
| #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] | ||
| #[derive(Clone, Debug, Default, PartialEq, Hash)] | ||
| #[derive(StableHash, TypeFoldable, TypeVisitable)] | ||
| pub struct QueryRegionConstraints<'tcx> { | ||
| pub constraints: Vec<QueryRegionConstraint<'tcx>>, | ||
| pub assumptions: Vec<ty::ArgOutlivesClause<'tcx>>, | ||
| /// Region constraints emitted by the next solver under | ||
| /// `-Zassumptions-on-binders`. | ||
| /// | ||
| /// These stay unspanned while passing through a canonical query. The type-op | ||
| /// caller attaches its origin span when consuming the response. | ||
| pub solver_constraints: ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>, | ||
| } | ||
|
|
||
| impl Eq for QueryRegionConstraints<'_> {} | ||
|
|
||
| impl QueryRegionConstraints<'_> { | ||
| /// Represents an empty (trivially true) set of region constraints. | ||
| /// | ||
|
|
@@ -91,8 +99,21 @@ impl QueryRegionConstraints<'_> { | |
| /// discharge a requirement from another query, which is a potential problem if we did throw | ||
| /// away these assumptions because there were no constraints. | ||
| pub fn is_empty(&self) -> bool { | ||
| let QueryRegionConstraints { constraints, assumptions } = self; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the destructuring here is intentional. it means that adding new fields doesn't silently keep compiling and doing the wrong thing. please keep the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, put the full destructuring back in |
||
| constraints.is_empty() && assumptions.is_empty() | ||
| let QueryRegionConstraints { constraints, assumptions, solver_constraints } = self; | ||
| constraints.is_empty() && assumptions.is_empty() && solver_constraints.is_true() | ||
| } | ||
|
|
||
| pub fn extend(&mut self, other: &Self) { | ||
| let QueryRegionConstraints { constraints, assumptions, solver_constraints } = self; | ||
| let QueryRegionConstraints { | ||
| constraints: other_constraints, | ||
| assumptions: other_assumptions, | ||
| solver_constraints: other_solver_constraints, | ||
| } = other; | ||
| constraints.extend(other_constraints.iter().cloned()); | ||
| assumptions.extend(other_assumptions.iter().cloned()); | ||
| *solver_constraints = | ||
| std::mem::take(solver_constraints).and(other_solver_constraints.clone()); | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this necessary for new style constraints but not old style?
View changes since the review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The difference is that the old obligations and assumptions are taken before the op and checked to be empty, so everything collected afterward belongs to that op. We cannot make that same check for the solver tree. Borrowck may already have constraints from an earlier type op in the same
InferCtxt, and those stay there until the end of typeck. If we took the full tree afterward, this response would also contain the caller's older constraints. Clearing it first would lose them. The helper parks the old tree, captures what this op made, then restores the old one.I do not love the extra swap, but I think this part is a real difference in how the constraints are stored and when they are consumed.