-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
CFI: Fix encode_region: unexpected ReEarlyBound(0, 'a) #111851
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 | ||||
---|---|---|---|---|---|---|
|
@@ -272,12 +272,11 @@ fn encode_region<'tcx>( | |||||
s.push('E'); | ||||||
compress(dict, DictKey::Region(region), &mut s); | ||||||
} | ||||||
RegionKind::ReErased => { | ||||||
RegionKind::ReEarlyBound(..) | RegionKind::ReErased => { | ||||||
s.push_str("u6region"); | ||||||
compress(dict, DictKey::Region(region), &mut s); | ||||||
} | ||||||
RegionKind::ReEarlyBound(..) | ||||||
| RegionKind::ReFree(..) | ||||||
RegionKind::ReFree(..) | ||||||
| RegionKind::ReStatic | ||||||
| RegionKind::ReError(_) | ||||||
| RegionKind::ReVar(..) | ||||||
|
@@ -704,14 +703,15 @@ fn transform_predicates<'tcx>( | |||||
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> { | ||||||
let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates | ||||||
.iter() | ||||||
.map(|predicate| match predicate.skip_binder() { | ||||||
.filter_map(|predicate| match predicate.skip_binder() { | ||||||
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. Unrelated, but why are we erasing projection predicates here? Those distinguish object types in a meaningful way? 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 reason for this is when transforming the concrete self into a reference to a trait object before emitting type metadata identifiers for trait methods (in typeid_for_instance, called in predefine_fn), the trait resolved from the method is the identity trait (i.e., early bound), and this is also necessary for trait objects with generic type parameters (see Trait3 in tests). Unless there is a way to bind the traits at that time, we'll need to work with identity traits (i.e., early bound, and that is the reason why predicates are excluded from the encoding) and add support for encoding early bound types both when emitting type metadata identifiers for trait methods and when emitting type checks. It's okay to work with early bound types for CFI since we're not encoding/mangling names for linking. (Surely it'd be better if we could bind those traits when doing the method to trait resolution in typeid_for_instance so we'd get better granularity, but I haven't found a way to do that.) 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. I'm sorry, I'm not really sure if I follow. What I mean is that you should be passing this trait ref through
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. what is an "identity trait" I have never heard this terminology before. 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. Would you mind providing more information? I think that for CFI we want to know and encode that there was an (erased) region there so trait methods are properly grouped together. 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 trait (reference) returned by https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.TraitRef.html#method.identity (which is early bound). (I'm not sure if identity trait is the actual correct name/terminology, but I've been using that to refer to it.) 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. Why are you using the trait ref without substituting it?
This seems like it's accidentally throwing away the substs that are carried by the instance: 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. It's intentional--but probably due to my lack of understanding--for grouping trait methods together for CFI. It's currently grouping methods per trait identity (i.e., early bound), but it surely would be better to group them per trait implementation and specialization (i.e., bound). However, the instance has a concrete self (i.e., it was monomorphized already), and I'm transforming the concrete self into a reference to a trait object (for grouping trait methods together for CFI) by doing the method to trait resolution in typeid_for_instance. Are the subts from the instance there, the substs expected by the trait identity resolved from the method to trait resolution also there? 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. Even though this was merged, lets continue the discussion because I'm interested in finding out a way to group trait methods more granularly, and if the substs from the monomorphized instance can be used in the trait ref returned from the method to trait resolution that would be great--and I can follow up with a PR to increase the granularity for trait objects using that. |
||||||
ty::ExistentialPredicate::Trait(trait_ref) => { | ||||||
let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id); | ||||||
ty::Binder::dummy(ty::ExistentialPredicate::Trait( | ||||||
Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait( | ||||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref), | ||||||
)) | ||||||
))) | ||||||
} | ||||||
_ => predicate, | ||||||
ty::ExistentialPredicate::Projection(..) => None, | ||||||
ty::ExistentialPredicate::AutoTrait(..) => Some(predicate), | ||||||
}) | ||||||
.collect(); | ||||||
tcx.mk_poly_existential_predicates(&predicates) | ||||||
|
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 are we not just erasing regions somewhere up the callstack? I don't think we should be handing early-bound vars 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.
See below.