-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Move placeholder handling to a proper preprocessing step #140466
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: master
Are you sure you want to change the base?
Move placeholder handling to a proper preprocessing step #140466
Conversation
r? lcnr |
This commit breaks out the logic of placheolder rewriting into its own preprocessing step. It's one of the more boring parts of rust-lang#130227. The only functional change from this is that the preprocessing step (where extra `r: 'static` constraints are added) is performed upstream of Polonius legacy, finally affecting Polonius. That is mostly a by-product, though.
8b2cab2
to
af75e13
Compare
Ok; revised SCC annotations have landed and I think I addressed all of your concerns so far @lcnr? |
af75e13
to
ef9cb23
Compare
@lcnr Fixed all the code review stuff now, I think! I amended it into the second commit. |
sup: annotation.representative.rvid(), | ||
sub: fr_static, | ||
category: ConstraintCategory::IllegalUniverse, | ||
locations: Locations::All(rustc_span::DUMMY_SP), |
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.
could we track a span related to the placeholder in the scc annotation and use that here?
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.
Sure, I guess. That might be useful for error reporting in #140737, but this PR still relies on the old error reporting machinery.
I'm also not sure what would be a good span. Where the constraint is added? Where it's defined?
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.
There is a cool variant of #140737 where we essentially run the blame search to find a blame span, put that in here, and then later stop constraint search at the outlives-static constraint and just report its span.
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.
This requires quite a lot more refactoring though.
ef9cb23
to
b1e4ca5
Compare
This comment has been minimized.
This comment has been minimized.
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.
a few more comment nits, and then finally r=me ☠️ sry
//! This logic is provisional and should be removed once the trait | ||
//! solver can handle this kind of constraint. |
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.
not really too relevant for this PR itself. With my current information I think that this will actually be really unlikely 😅 handling opaque types will need to propagate placeholders to the end of typeck
Might make sense to have a few meetings to discuss the longterm plan here again to make sure we're working towards a reachable goal 😅 forgot to talk about that part during the AllHands :<
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.
I’d say ”was too busy” but yes! More! Meetings!!!!
/// The smallest universe nameable from this SCC. | ||
/// It is the smallest of all the largest nameable universes | ||
/// of any region reachable from it. |
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 smallest universe nameable from this SCC. | |
/// It is the smallest of all the largest nameable universes | |
/// of any region reachable from it. | |
/// The largest universe nameable from this SCC. | |
/// It is the smallest nameable universes of all | |
/// existential regions reachable from it. |
} | ||
|
||
/// Returns `true` if during the annotated SCC reaches a placeholder | ||
/// with a universe larger than the smallest reachable one, `false` otherwise. |
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.
/// with a universe larger than the smallest reachable one, `false` otherwise. | |
/// with a universe larger than the smallest nameable universe of any | |
/// reachable existential region. |
} | ||
|
||
/// Determine if the tracked universes of the two SCCs are compatible. | ||
pub(crate) fn universe_compatible_with(&self, other: Self) -> bool { |
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.
what does this check? self.max_nameable_universe().can_name(other.max_nameable_universe())
seems like a very weird check 🤔
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.
okay, so it's used in eval_outlives
and... just silences errors if the other
itself already has a placeholder error?
what is the impact of only checking self.max_nameable_universe().can_name(other.max_placeholder_universe_reached)
?
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.
This logic is carefully written to precisely mirror what was there previously. It at some point made sense to me but no longer does. It seemed fine until I renamed the functions to better descriptions at which point it, as you say, sounds preposterous.
I’ll spend some time with the thinking cap about this and get back to you.
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.
But IIRC the impact is ”you get very few spurious errors, for some reason”
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.
Ah yes, this is the logic on current master:
/// Returns `true` if all the elements in the value of `scc_b` are nameable
/// in `scc_a`. Used during constraint propagation, and only once
/// the value of `scc_b` has been computed.
fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool {
let a_annotation = self.scc_annotations[scc_a];
let b_annotation = self.scc_annotations[scc_b];
let a_universe = a_annotation.min_universe();
// If scc_b's declared universe is a subset of
// scc_a's declared universe (typically, both are ROOT), then
// it cannot contain any problematic universe elements.
if a_universe.can_name(b_annotation.min_universe()) {
return true;
}
// Otherwise, there can be no placeholder in `b` with a too high
// universe index to name from `a`.
a_universe.can_name(b_annotation.max_placeholder_universe_reached)
}
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.
I mean, I wrote that, but that in turn was similarly a reconstruction of something horribly complicated IIRC
/// This code is a stop-gap measure in preparation for the future trait solver. | ||
/// | ||
/// Every constraint added by this method is an internal `IllegalUniverse` constraint. | ||
pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>( |
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.
vibe: a very specific method name for a method that actually just computes the scc, maybe
pub(crate) fn rewrite_higher_kinded_outlives_as_constraints<'tcx>( | |
pub(crate) fn compute_scc_applying_placeholder_outlives_constraints<'tcx>( |
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.
See, this is why someone who’s been living inside her own head for a year needs code review
RegionVariableOrigin::Nll(origin) => origin, | ||
_ => NllRegionVariableOrigin::Existential { from_forall: false }, | ||
}; | ||
|
||
Self { origin, universe, external_name: None } | ||
Self { origin, universe: rv_info.universe, external_name: None } |
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.
vibe: we now immediately set the external_name
in the function which creates the definitions. It's probably a lot clearer to just inline RegionDefinition::new
in that fn
Co-authored-by: lcnr <rust@lcnr.de>
|
This commit breaks out the logic of placheolder rewriting into its own preprocessing step. It's one of the more boring
parts of #130227.
The only functional change from this is that the preprocessing step (where extra
r: 'static
constraints are added) is performed upstream of Polonius legacy, finally affecting Polonius. That is mostly a by-product, though.This should be reviewable by anyone in the compiler team, so
r? rust-lang/compiler