-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
remove more trivial regions in evaluate_added_goals_and_make_canonical_response #162032
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
Changes from all commits
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 |
|---|---|---|
|
|
@@ -18,8 +18,8 @@ use rustc_type_ir::solve::{ | |
| }; | ||
| use rustc_type_ir::{ | ||
| self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased, | ||
| OpaqueTypeKey, PredicateKind, Region, TypeFoldable, TypeSuperVisitable, TypeVisitable, | ||
| TypeVisitableExt, TypeVisitor, TypingMode, eager_resolve_vars, | ||
| OpaqueTypeKey, PredicateKind, Region, RegionVid, TypeFoldable, TypeSuperVisitable, | ||
| TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, eager_resolve_vars, max_universe, | ||
| }; | ||
| use thin_vec::ThinVec; | ||
| use tracing::{Level, debug, instrument, trace, warn}; | ||
|
|
@@ -1608,6 +1608,75 @@ where | |
| r.retain(|(outlives, _)| !outlives.is_trivial() && unique.insert(*outlives)); | ||
| } | ||
|
|
||
| #[derive(Default)] | ||
| struct NonTrivialVars { | ||
| vars: HashSet<RegionVid>, | ||
| } | ||
| impl<I> TypeVisitor<I> for NonTrivialVars | ||
| where | ||
| I: Interner, | ||
| { | ||
| type Result = (); | ||
| fn visit_ty(&mut self, t: I::Ty) { | ||
| // If a nested type doesn't have any `ReVar`s, then we won't insert | ||
| // anything into `vars` anyway, so skip for better perf. | ||
| if !t.has_infer_regions() { | ||
|
ShoyuVanilla marked this conversation as resolved.
|
||
| return; | ||
| } | ||
| t.super_visit_with(self); | ||
| } | ||
| fn visit_const(&mut self, c: I::Const) { | ||
| // The same goes for consts. | ||
| if !c.has_infer_regions() { | ||
| return; | ||
| } | ||
| c.super_visit_with(self); | ||
| } | ||
| fn visit_region(&mut self, r: Region<I>) { | ||
| if let ty::ReVar(vid) = r.kind() { | ||
| self.vars.insert(vid); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // If we have a constraint like `'re: '?1`, where '?1 can name 're and '?1 appears | ||
| // only on the RHS of region constraints, then this kind of constraint is also trivial, | ||
| // since we're able to pick '?1 := 'empty, and 're: 'empty is always true for any 're. | ||
|
Contributor
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. cc https://rust-lang.zulipchat.com/#narrow/channel/618216-t-types.2Fcall-for-participation/topic/yeet.20.27empty.20in.20region.20handling/with/623092808 pls update comment in a followup PR :> |
||
| if let ExternalRegionConstraints::Old(r) = &mut external_constraints.region_constraints | ||
| && !r.is_empty() | ||
| { | ||
| let mut vis = NonTrivialVars::default(); | ||
| var_values.visit_with(&mut vis); | ||
| // We have to visit each component of `external_constraints` individually here | ||
|
Contributor
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. if you do that, pls do |
||
| // because we skip the RHS of outlives constraints, and `TypeVisitor` doesn't | ||
| // have a method we can easily override in order to do this. | ||
| external_constraints.opaque_types.visit_with(&mut vis); | ||
| external_constraints.normalization_nested_goals.visit_with(&mut vis); | ||
| for (constraint, _) in r.iter() { | ||
| match constraint { | ||
| ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, _)) => { | ||
| sup.visit_with(&mut vis) | ||
| } | ||
| ty::RegionConstraint::Eq(eq) => eq.visit_with(&mut vis), | ||
| } | ||
| } | ||
|
|
||
| r.retain(|(outlives, _)| { | ||
| if let ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, re)) = *outlives | ||
| && let Some(sup_re) = sup.as_region() | ||
| && let ty::RegionKind::ReVar(vid) = re.kind() | ||
| // This is only safe if we call `eager_resolve_vars` beforehand, | ||
| // which we do. | ||
| && self.delegate.universe_of_lt(vid).unwrap() | ||
| .can_name(max_universe(&**self.delegate, sup_re)) | ||
| { | ||
| vis.vars.contains(&vid) | ||
| } else { | ||
| true | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| let canonical = canonicalize_response( | ||
| self.delegate, | ||
| self.max_input_universe, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| //@ compile-flags: -Znext-solver -Zno-leak-check | ||
|
|
||
| //! Make sure we don't drop trivial-looking region constraints that would otherwise fail | ||
| //! leak check. | ||
|
|
||
| trait Trait {} | ||
| trait Other<'a, 'b> {} | ||
|
|
||
| struct Foo; | ||
| // We need this indirection because something direct like `for<'a> &'a (): 'b` gives us a | ||
| // TypeOutlives constraint, whereas we want to be testing how we handle RegionOutlives, and | ||
| // only `impl Other for Bar`'s where-clause can give us that. | ||
| impl<'b> Trait for Foo where for<'a> Bar: Other<'a, 'b> {} | ||
|
|
||
| struct Bar; | ||
| impl<'a, 'b> Other<'a, 'b> for Bar where 'a: 'b {} | ||
|
|
||
| fn f<T: Trait>(_: T) {} | ||
|
|
||
| fn main() { f(Foo); } | ||
| //~^ ERROR higher-ranked lifetime error |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| error: higher-ranked lifetime error | ||
| --> $DIR/no-dedup-universes.rs:20:13 | ||
| | | ||
| LL | fn main() { f(Foo); } | ||
| | ^^^^^^ | ||
| | | ||
| = note: could not prove `Foo: Trait` | ||
|
|
||
| error: aborting due to 1 previous error | ||
|
|
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.
probably nice to move this entire thing into a
filter_irrelevant_region_constraintsfunction or sth. The current function is already really long and involved