Skip to content
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

Merged
merged 1 commit into from
Aug 4, 2017
Merged

Can derive copy analysis #866

merged 1 commit into from
Aug 4, 2017

Conversation

photoszzt
Copy link
Contributor

r? @fitzgen or @emilio. Fix: #766

Copy link
Member

@fitzgen fitzgen left a 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!

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) {
Copy link
Member

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.

Copy link
Contributor Author

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).

} else {
trace!(" we cannot derive Copy for the layout");
self.insert(id);
self.insert_array(id)
Copy link
Member

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.

also cannot derive Copy");
self.insert_array(id);
}
if cant_derive_copy_in_array || cant_derive_copy {
Copy link
Member

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);
}

Copy link
Member

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.

self.insert_array(id);
}
if cant_derive_copy_in_array || cant_derive_copy {
return ConstrainResult::Changed;
Copy link
Member

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?

Copy link
Contributor Author

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() {
Copy link
Member

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.

/// 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))
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

@bors-servo
Copy link

☔ The latest upstream changes (presumably #861) made this pull request unmergeable. Please resolve the merge conflicts.

@bors-servo
Copy link

☔ The latest upstream changes (presumably #873) made this pull request unmergeable. Please resolve the merge conflicts.

@bors-servo
Copy link

☔ The latest upstream changes (presumably #874) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Member

@fitzgen fitzgen left a 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 !

}

TypeKind::Comp(ref info) => {
let fields_have = info.fields()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about base members?

// 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)
Copy link
Member

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 to HasTypeParameterInArray 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 the Analysis because it should be obvious from the context: its in the ir::analysis module amd it implements the MonotonFramework trait.

  • Only compute the cannot_derive_copy set in the CannotDeriveCopy analysis. Get rid of the cannot_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.

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! 👍

@fitzgen
Copy link
Member

fitzgen commented Aug 3, 2017

@bors-servo r+

@bors-servo
Copy link

📌 Commit 89dde21 has been approved by fitzgen

@bors-servo
Copy link

⌛ Testing commit 89dde21 with merge e91d448...

bors-servo pushed a commit that referenced this pull request Aug 3, 2017
@bors-servo
Copy link

💔 Test failed - status-travis

@fitzgen
Copy link
Member

fitzgen commented Aug 3, 2017

@bors-servo r+

@bors-servo
Copy link

📌 Commit 68f6adf has been approved by fitzgen

bors-servo pushed a commit that referenced this pull request Aug 3, 2017
@bors-servo
Copy link

⌛ Testing commit 68f6adf with merge b1cfa78...

@bors-servo
Copy link

☀️ Test successful - status-travis
Approved by: fitzgen
Pushing b1cfa78 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants