-
Notifications
You must be signed in to change notification settings - Fork 721
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
Can derive copy analysis #866
Conversation
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.
Looks good as always :)
A couple nitpicks and questions below.
Thanks!
src/ir/analysis/derive_copy.rs
Outdated
fn constrain(&mut self, id: ItemId) -> ConstrainResult { | ||
trace!("constrain: {:?}", id); | ||
|
||
if self.cannot_derive_copy.contains(&id) || self.cannot_derive_copy_in_array.contains(&id) { |
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 it always true that we insert into both sets at the same time, if we will ever insert the same item into both sets? If we would insert into one set on a first iteration, and insert into the other set on a second iteration, then this check here would prevent that second insertion from ever occurring.
If this is indeed correct (I need to think about it some more and read the rest of this code) then we should definitely have a comment here for readers to understand this subtlety.
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.
Yes. I do want to make sure they insert into both sets. Otherwise, I don't have a way to make sure the function reaches a fix-point. I can't check that they are in both sets as there're elements only belongs to the second set. From what I see in the trace if it inserts in the first set, it also needs to insert into the second set. I split it for the situation that it doesn't insert in the first set and insert into the second set (things related to Named both explicitly and transitively).
src/ir/analysis/derive_copy.rs
Outdated
} else { | ||
trace!(" we cannot derive Copy for the layout"); | ||
self.insert(id); | ||
self.insert_array(id) |
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.
Seems like having an insert_both
method could be nice; these two lines are repeated in multiple places.
src/ir/analysis/derive_copy.rs
Outdated
also cannot derive Copy"); | ||
self.insert_array(id); | ||
} | ||
if cant_derive_copy_in_array || cant_derive_copy { |
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.
Rather than checking for both conditions here and then maybe returning if either cannot derive, let's do the check-and-maybe-return dance after each lookup, so that we aren't continuing to do lookups when we already "know" we can stop considering this item.
let cannot_derive_copy = ...;
if cannot derive_copy {
...
return self.insert(id);
}
let cannot_derive_copy_in_array = ...;
if cannot_derive_copy_in_array {
...
return self.insert_array(id);
}
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 wait, is this so that we insert into both sets at the same time, if need be? (Like how I was asking in an above comment).
If so, then we really need a comment explaining this. It is pretty subtle.
src/ir/analysis/derive_copy.rs
Outdated
self.insert_array(id); | ||
} | ||
if cant_derive_copy_in_array || cant_derive_copy { | ||
return ConstrainResult::Changed; |
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.
Same deal here for making sure it goes into both sets before the return?
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.
Yes. See above.
type Extra = (); | ||
|
||
fn can_derive_copy(&self, ctx: &BindgenContext, _: ()) -> bool { | ||
if self.detect_derive_copy_cycle.get() { |
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.
We can remove the detect_derive_copy_cycle
member now, as well.
src/ir/template.rs
Outdated
/// Is this has array? | ||
fn has_array(&self, ctx: &BindgenContext) -> bool { | ||
let resolved_item = ctx.resolve_item(self.template_definition()); | ||
resolved_item.as_type().map_or(false, |ty| ty.has_array(ctx)) |
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.
Do we need to consider the template arguments here as well? The old can_derive_copy_in_array
for TemplateInstantiation
also checked that each of the args could derive copy in an array, but I'm not sure if that translates to HasArray
or not.
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.
For HasArray, I mainly checking about whether it's transitively related to a comp that has an array in it. Maybe I should also check args.
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.
Try adding args. I have a feeling that my current implementation runs into cycling recursion and the stack overflows. Maybe it would turn into an analysis.
☔ The latest upstream changes (presumably #861) made this pull request unmergeable. Please resolve the merge conflicts. |
☔ The latest upstream changes (presumably #873) made this pull request unmergeable. Please resolve the merge conflicts. |
☔ The latest upstream changes (presumably #874) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
Just caught something below; sorry I didn't notice this earlier!
Note also that #874 just landed, so this PR will need to rebase on top of its changes.
Thanks @photoszzt !
src/ir/analysis/has_array.rs
Outdated
} | ||
|
||
TypeKind::Comp(ref info) => { | ||
let fields_have = info.fields() |
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 about base members?
src/ir/context.rs
Outdated
// derive `Copy` or not. | ||
trace!("looking up id: {:?}, contains_array: {:?}", id, contains_array); | ||
if contains_array { | ||
!self.cannot_derive_copy_in_array.as_ref().unwrap().contains(&id) |
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 there ever a case where the type can have an array containing a named type parameter and it is still true that it can derive copy? As far as I know, the answer is "no", which means that this check is already unnecessary. That is, if id.has_array(ctx)
then we can return false
immediately. Which also means that we don't need the cannot_derive_copy_in_array
set, because its redundant with the HasArray
analysis's results.
So, unless I'm overlooking something, I think we should take these steps:
-
Rename
HasArrayAnalysis
toHasTypeParameterInArray
so that it is more clear what it is computing. It isn't computing if the type has any old array in it, it is computing whether it contains an array of type parameters. We can drop theAnalysis
because it should be obvious from the context: its in their::analysis
module amd it implements theMonotonFramework
trait. -
Only compute the
cannot_derive_copy
set in theCannotDeriveCopy
analysis. Get rid of thecannot_derive_copy_in_array
set. -
In this method:
assert!(... in codegen phase ...);
!id.has_type_param_in_array(self) &&
!self.cannot_derive_copy.as_ref().unwrap().contains(&id)
Sorry for not catching this earlier! I think this will be a big improvement, though, so it is worth 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.
Thanks! 👍
@bors-servo r+ |
📌 Commit 89dde21 has been approved by |
💔 Test failed - status-travis |
@bors-servo r+ |
📌 Commit 68f6adf has been approved by |
☀️ Test successful - status-travis |
r? @fitzgen or @emilio. Fix: #766