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

Fix assertion failure on nested tuple identity #1947

Merged
merged 1 commit into from
Jun 22, 2017

Conversation

Praetonus
Copy link
Member

@Praetonus Praetonus commented Jun 6, 2017

This fixes a bug introduced in 9b9c084 caused by the __is method of a tuple nested in another tuple not being reached.

This should only get a changelog entry if we do a new release before merging this, since the bug exists only in the unreleased version.

Copy link
Contributor

@plietar plietar left a comment

Choose a reason for hiding this comment

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

I'm not sure I get the logic of determining reachability by considering the contents of both sides.

If we determine that the TK_IS needs the __is method, (ie subtype_kind_overlap contains SUBTYPE_KIND_TUPLE), then I think we should only mark the method as reachable on the left hand side type, and all types it contains recursively. We should ignore completely the right hand side type.

The reachability logic here should match the genident one, especially the box_is_box and gen_is_tuple_fun methods


if(!is_known(l_type) && !is_known(r_type))
{
pony_assert(r_child == NULL);
Copy link
Contributor

Choose a reason for hiding this comment

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

Tuples could have different length, in which case this asserts (or segfaults)
#1946

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll fix that.

reach_type_t* sub;
size_t i = HASHMAP_BEGIN;

while((sub = reach_type_cache_next(&t->subtypes, &i)) != NULL)
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't add_rmethod already take care of adding it to all subtypes ?

Copy link
Member Author

Choose a reason for hiding this comment

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

It does, but it doesn't handle the case of a tuple subtype that should add __is to its members.

Copy link
Contributor

@plietar plietar Jun 6, 2017

Choose a reason for hiding this comment

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

Indeed, thanks

@Praetonus
Copy link
Member Author

@plietar The __is method is only needed when both the left hand side type and the right hand side type of an is expression have the same tuple type as a subtype.

For example, consider this case:

a: ((U8, U16) | (U16, U16))
b: ((U8, U16) | None)

a is b

Here, both a and b can be an (U8, U16) tuple, but only b can be an (U16, U16) tuple. This means that (U8, U16) needs the __is function but not (U16, U16) since we statically know that if a has that type, there is no need to check the contents of the tuple because b will have a different type.

If we were to determine the reachability of __is based on the left hand side type, we'd always get all needed types (since they'd also be contained in the right hand side type) but also a few unneeded types, like (U16, U16) here.

if(!is_known(type))
static void reachable_digestof_type(reach_t* r, ast_t* type, pass_opt_t* opt)
{
if(ast_id(type) == TK_TUPLETYPE)
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this case call add_rmethod as well ?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, we only need __digestof when using digestof on an abstract type (i.e. not a tuple) with boxed subtypes.

@plietar
Copy link
Contributor

plietar commented Jun 6, 2017

What I meant here is that when generating the __is method, we consider the two types to be identical (see #1950, this isn't ideal, but that's how it is right now).

Therefore we should only recurse considering the left hand side type, ignoring the right one.

Additionally right now we generate the __is on both sides, but we only need it for the left, since this is what we'll be calling during codegen.

@sylvanc sylvanc added the do not merge This PR should not be merged at this time label Jun 7, 2017
@Praetonus Praetonus force-pushed the reach-internal-recurse branch from 94c7300 to ef8f359 Compare June 11, 2017 13:11
@Praetonus
Copy link
Member Author

I do think that recursing on every subtype of the left hand side type is unnecessary and marks too many types. Recursing on types which are subtypes of both the left hand side type and the right hand side type marks every needed type and no unneeded type. I expect that we'll have to change that logic in order to fix #1950 but for now I think it's fine.

I'll fix the __is generation, generating both sides is indeed unnecessary.

@Praetonus Praetonus force-pushed the reach-internal-recurse branch from ef8f359 to 92e7b68 Compare June 11, 2017 13:52
@SeanTAllen SeanTAllen removed the do not merge This PR should not be merged at this time label Jun 21, 2017
This fixes a bug introduced in 9b9c084 caused by the `__is` method of a
tuple nested in another tuple not being reached.
@Praetonus Praetonus force-pushed the reach-internal-recurse branch from 92e7b68 to 5c7dfaa Compare June 21, 2017 22:43
@Praetonus
Copy link
Member Author

Conflicts fixed, merging.

@Praetonus Praetonus merged commit d7b23ed into ponylang:master Jun 22, 2017
@Praetonus Praetonus deleted the reach-internal-recurse branch June 22, 2017 01:31
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.

4 participants