Repository navigation
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
| T: TypeFoldable<TyCtxt<'tcx>>, | ||
| { | ||
| self.tcx.anonymize_bound_vars(t) | ||
| self.tcx.anonymize_bound_vars(t.super_fold_with(self)) |
There was a problem hiding this comment.
This implementation is obviously correct but it's doing a lot unnecessary walking & work. Of course, this part of the code isn't performance critical & I don't think we have any benchmarks containing RPITITs. Still, IMO we should simplify this, it won't take that much more code.
As you know, anonymize_bound_vars only anonymizes bound vars bound by the current binder & under the hood it's also a TypeFolder (with some TypeFlags and other early returns) meaning in total we rewalk the type a lot if there are several binders.
Moreover, the BoundVarReplacer (a folder) inside anonymize_bound_vars performs a lot of checks to ensure it only replaces bound vars that are bound at the correct level & it has to shift the de-Bruijn indices & re-intern the shifted regions etc. produced by anonymize_bound_vars's BoundVarReplacerDelegate.
However, since the idea of our Anonymize here is to fully anonymize the type, most of these things don't need to be done. Fundamentally we simply we want to replace any Bound{Region,Ty,Const}Kind with Anon keeping the de Bruijn index & the BoundVar (index) fully intact.
So this whole operation could just be a TypeFolder that impls fold_{region,type,const}, returns the argument unchanged if it !_.has_bound_vars() otherwise if it's a ty::{,Re,ConstKind::}Bound return a *Bound with *Kind::Anon.
There was a problem hiding this comment.
E.g., for code like
#![deny(refining_impl_trait)]
trait A {
fn f() -> impl B<for<'a> fn(for<'b> fn(&'a (), &'b ()))>;
}
impl A for () {
fn f() -> impl B<for<'a> fn(for<'b> fn(&'a (), &'b ()))> {
0
}
}
trait B<T: ?Sized> {}
impl<T: ?Sized, U: ?Sized> B<T> for U {}the execution trace under your PR looks something like
fold_binder()
# arg: Binder { value: TraitClause(<Opaque(DefId(0:10 ~ b[656a]::{impl#0}::f::{opaque#0}), []) as B<for<Region(BrNamed(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)))> fn(for<Region(BrNamed(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)))> fn(&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) ()))>>, polarity:Positive), bound_vars: [] }
# arg has bound vars; calling super_fold_with()...
fold_ty()
# arg: Alias(Yes, Alias { kind: Opaque { def_id: DefId(0:10 ~ b[656a]::{impl#0}::f::{opaque#0}) }, args: [], .. })
# arg has no bound vars; ret arg as is...
fold_ty()
# arg: Binder { value: fn(Binder { value: fn(&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) ()), bound_vars: [Region(BrNamed(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)))] }), bound_vars: [Region(BrNamed(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)))] }
# arg has bound vars; calling super_fold_with()...
fold_binder()
# arg: Binder { value: FnSigTys { inputs_and_output: [Binder { value: fn(&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) ()), bound_vars: [Region(BrNamed(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)))] }, ()] }, bound_vars: [Region(BrNamed(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)))] }
# arg has bound vars; calling super_fold_with()...
fold_ty()
# arg: Binder { value: fn(&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) ()), bound_vars: [Region(BrNamed(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)))] }
# arg has bound vars; calling super_fold_with()...
fold_binder()
# arg: Binder { value: FnSigTys { inputs_and_output: [&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) (), ()] }, bound_vars: [Region(BrNamed(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)))] }
# arg has bound vars; calling super_fold_with()...
fold_ty()
# arg: &'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) ()
# arg has bound vars; calling super_fold_with()...
fold_ty()
# arg: ()
# arg has no bound vars; ret arg as is...
fold_ty()
# arg: &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) ()
# arg has bound vars; calling super_fold_with()...
fold_ty()
# arg: ()
# arg has no bound vars; ret arg as is...
fold_ty()
# arg: ()
# arg has no bound vars; ret arg as is...
anonymize_bound_vars()
# arg: Binder { value: FnSigTys { inputs_and_output: [&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) (), ()] }, bound_vars: [Region(BrNamed(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)))] }
# has esc bound vars; calling arg.fold_with(BVR)...
BVR::fold_ty()
# arg: &'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) ()
# has vars bound at/above current index
# calling super_fold_with()...
BVR::fold_region()
# arg: '^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a))
# not ReBound with matching index; returning arg as is...
BVR::fold_ty()
# arg: ()
# no vars bound at/above current index; ret arg as is...
BVR::fold_ty()
# arg: &'^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)) ()
# has vars bound at/above current index
# calling super_fold_with()...
BVR::fold_region()
# arg: '^0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b))
# is ReBound with matching index
# calling delegate.replace_region(0.Named(DefId(0:7 ~ b[656a]::A::f::{opaque#0}::'b)))...
# ...which yielded '^0
# adjusting the de Bruijn index...
# ...giving us '^0
BVR::fold_ty()
# arg: ()
# no vars bound at/above current index; ret arg as is...
BVR::fold_ty()
# arg: ()
# no vars bound at/above current index; ret arg as is...
fold_ty()
# arg: ()
# arg has no bound vars; ret arg as is...
anonymize_bound_vars()
# arg: Binder { value: FnSigTys { inputs_and_output: [Binder { value: fn(&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0 ()), bound_vars: [Region(BrAnon)] }, ()] }, bound_vars: [Region(BrNamed(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)))] }
# has esc bound vars; calling arg.fold_with(BVR)...
BVR::fold_ty()
# arg: Binder { value: fn(&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0 ()), bound_vars: [Region(BrAnon)] }
# has vars bound at/above current index
# calling super_fold_with()...
BVR::fold_binder()
# arg: Binder { value: FnSigTys { inputs_and_output: [&'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) (), &'^0 (), ()] }, bound_vars: [Region(BrAnon)] }
# calling super_fold_with()...
BVR::fold_ty()
# arg: &'^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)) ()
# has vars bound at/above current index
# calling super_fold_with()...
BVR::fold_region()
# arg: '^1_0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a))
# is ReBound with matching index
# calling delegate.replace_region(0.Named(DefId(0:6 ~ b[656a]::A::f::{opaque#0}::'a)))...
# ...which yielded '^0
# adjusting the de Bruijn index...
# ...giving us '^1_0
BVR::fold_ty()
# arg: ()
# no vars bound at/above current index; ret arg as is...
BVR::fold_ty()
# arg: &'^0 ()
# no vars bound at/above current index; ret arg as is...
BVR::fold_ty()
# arg: ()
# no vars bound at/above current index; ret arg as is...
BVR::fold_ty()
# arg: ()
# no vars bound at/above current index; ret arg as is...
anonymize_bound_vars()
# arg: Binder { value: TraitClause(<Opaque(DefId(0:10 ~ b[656a]::{impl#0}::f::{opaque#0}), []) as B<for<Region(BrAnon)> fn(for<Region(BrAnon)> fn(&'^1_0 (), &'^0 ()))>>, polarity:Positive), bound_vars: [] }
# no esc bound vars; ret arg...See how it walks into parts of the type just to walk out and reenter parts it's already visited & partially anonymized (but now under different Binder.bound_vars / at a different binder depth)?
|
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. |
Fix #165091
The inner binder is missed.