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't call isSuptype on types whose Java types are not subtypes #772

Merged
merged 5 commits into from
Jun 22, 2016

Conversation

smillst
Copy link
Member

@smillst smillst commented Jun 3, 2016

No description provided.

@smillst smillst mentioned this pull request Jun 3, 2016
@mernst
Copy link
Member

mernst commented Jun 14, 2016

This looks OK to me.

return visitUnionSupertype(subtype, supertype, visited);
Types types = checker.getTypeUtils();
for (AnnotatedDeclaredType supertypeAltern : supertype.getAlternatives()) {
if (TypesUtils.isErasedSubtype(types, subtype.getUnderlyingType(), supertypeAltern.getUnderlyingType())
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't it be more concise to add the check for subtyping of the underlying type to isSubtype?
Is there ever a reason for not including this check? It looks like it is always occurring together. The only exception I saw was in visitIntersection_Intersection which could keep the additional check.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is there ever a reason for not including this check?

Yes, for example isSubtype of Integer and int are not erased Java subtypes, so the check can't be added to isSubtype.

Copy link
Member

Choose a reason for hiding this comment

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

It would seem much simpler to add that special casing into isSubtype.
An int is never a subtype of Integer, because boxing/unboxing would apply first.
Making many invocations of isSubtype simpler and documenting the boxing special case in isSubtype seems beneficial and clearer to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

As documented, the Java types of the arguments to isSubtype are not always in a subtype relationship.

It would seem much simpler to add that special casing into isSubtype.

It would not be correct to do so. For example, isSubtype(@C Cloneable & @A List<@B String, @A List<@B String>) if the isErasedSubtype is moved to isSubtype, then isSubtype called recursively on @C Cloneable and @A List<@B String> would return false which would cause isSubtype(@C Cloneable & @A List<@B String, @A List<@B String>) to return false as well.

Copy link
Member

Choose a reason for hiding this comment

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

I don't understand your example. At the moment the code is

for (alternatives) {
  if (isErasedSubtype(A, B) && isSubtype(A, B) {
    return true;
  }
}
return false;

How is it not semantically equivalent to write:

for (alternatives) {
  if (isSubytpe(A, B)) {
    return true;
  }
}
return false;

and strengthen isSubtype:

boolean isSubtype(A, B) {
   if (!isErasedSubtype(A, B) {
     return false;
   }
}

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 would probably be good to do this, but it is not as simple as adding isErasedSubtype to isSubtype. Aside from primitives, isErasedSubtype fails for the following combinations to isSubtype (and there are probably more):

int[], Object[]
U extends Object & Iterable<Object>, Iterable<Object>
Throwable&Cloneable&Unions.MyInterface<String>,  Object&Cloneable&Unions.MyInterface<String>

So, if we would like to add this functionality, it should be done in a separate pull request.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, if you think that is easier.
Did you have a test case for this pull request?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a refactoring, so there are already some test cases. More complex ones require asSuper to work correctly. See tests in all-systems with Union or Intersection in name.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, so I'm not sure why splitting this up into two refactorings makes it easier, but if you prefer, let's do that. Please file an issue for the remaining work.
(The PR title made it sound like something doesn't work without this change.)

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 have more test cases in asSuper that crash on master because of asSuper bugs that also crash on asSuper because of this issue.

@wmdietl
Copy link
Member

wmdietl commented Jun 14, 2016

Is there a test case that fails without this change?

@wmdietl wmdietl assigned smillst and unassigned wmdietl Jun 14, 2016
@smillst smillst assigned wmdietl and unassigned smillst Jun 17, 2016
@wmdietl wmdietl assigned smillst and unassigned wmdietl Jun 20, 2016
@smillst smillst assigned wmdietl and unassigned smillst Jun 20, 2016
@smillst smillst merged commit f9fa7b8 into master Jun 22, 2016
@smillst smillst deleted the subtype branch June 22, 2016 21:14
Ao-senXiong added a commit to opprop/checker-framework that referenced this pull request Jul 18, 2024
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