-
Notifications
You must be signed in to change notification settings - Fork 254
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
Feat.rewrite.lifetime #915
Conversation
cf7eacc
to
3f7bea0
Compare
590a3dd
to
1199a8f
Compare
3f14512
to
a97d979
Compare
c5e4266
to
7bbfc3d
Compare
c2rust-analyze/src/rewrite/ty.rs
Outdated
if let Some(adt_metadata) = &self.acx.gacx.adt_metadata.table.get(&adt_def.did()) { | ||
self.hir_rewrites.push(( | ||
hir_ty.span, | ||
adt_ty_rw(adt_def, &adt_metadata.lifetime_params, substs), |
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.
adt_metadata.lifetime_params
tells you what lifetimes are declared on the type, not what lifetimes should be passed at this particular use of it. Due to the way we infer hypothetical lifetimes in ADTs, it happens to be the case that the names match up within struct fields (given struct Foo<'h0> { ... }
, all uses will look like struct Bar<'h0, 'h1> { foo: &'h1 Foo<'h0> }
, with the same name 'h0
in both places), but this isn't true in general.
struct Foo<'h0> { ... }
fn foo1<'a>(x: Foo<'a>, y: Foo<'a>) { ... }
fn foo2<'a, 'b>(x: Foo<'a>, y: Foo<'b>) { ... }
Given Foo
, both the foo1
and foo2
signatures are valid, and they mean different things, so we need a way to express both of them.
RewriteLabel
probably needs a field like &'tcx [OriginArg<'tcx>]
representing the lifetime arguments of a particular Ty
, with similar meaning to the labels of FieldMetadata
's origin_args
field. That will allow for distinctions like the above foo1
/foo2
example.
For struct field types, the lifetime arguments can be set from the existing FieldMetadata::origin_args
labels. For types in function signatures, we'll eventually need a similar setup to generate hypothetical parameters and so on, but for now that doesn't exist, so any region arguments should either be elided or left as 'static
. Inside function bodies, the regions can always be elided.
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.
Thanks for the catch, the tests were wrong and didn't complain about this. I've addressed it in 37e14bc and took out the test for the function lifetime rewriting for the time being; I'll create an issue for 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.
Issue created #921
7bbfc3d
to
8d61604
Compare
@spernsteiner would you mind taking another look at this? |
961c23e
to
c114df6
Compare
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 generally looks okay, but I have questions about a couple specific rewrite cases
if let TyKind::Adt(adt_def, substs) = rw_lty.ty.kind() { | ||
if !rw_lty.label.lifetime.is_empty() { | ||
self.hir_rewrites.push(( |
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 was expecting this to generate a rewrite on every ADT with at least one lifetime, which would lead to unnecessary unfolding of type aliases. But I didn't see that effect when I ran it on this code:
struct Test<'a>(&'a u8);
type Alias<'a> = Test<'a>;
fn f<'a>(x: Alias<'a>) {}
I was expecting a rewrite from x: Alias<'a>
to x: Test<'a>
, but no such rewrite occurred. Under what conditions is label.lifetime
non-empty? I was expecting it to be set to the original lifetime args ['a]
in this case. Is it empty for structs that have no hypothetical lifetimes?
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.
Alias
doesn't get rewritten because it doesn't appear in the ADT metadata table, and that's because it's DefKind
is a TyAlias
and not one of Struct | Enum | Union
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.
Is support for TyAlias
for structs
something that can be done in a follow-up PR?
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.
Issue created in #926
))) | ||
} | ||
_ => { | ||
other_params.push(Rewrite::PrintTy(gp.name.ident().to_string())) |
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.
Will this swallow constraints, rewriting struct Foo<T: Clone>(...)
into struct Foo<T>(...)
?
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.
Issue created in #927. Would you mind elaborating on that issue as to how fresh hypothetical lifetimes would be spliced in?
I think ideally we would be able to either insert additional lifetime arguments before/after some existing argument ( |
Co-authored-by: Khyber Sen <kkysen@gmail.com>
Co-authored-by: Khyber Sen <kkysen@gmail.com>
Co-authored-by: Khyber Sen <kkysen@gmail.com>
Co-authored-by: Khyber Sen <kkysen@gmail.com>
Co-authored-by: Khyber Sen <kkysen@gmail.com>
Co-authored-by: Khyber Sen <kkysen@gmail.com>
c114df6
to
b61367a
Compare
Co-authored-by: spernsteiner <spernsteiner@galois.com>
Rewrites structs to reflect hypothetical lifetimes accepted by polonius.
e.g.
gets rewritten to