RFR: 8232765: NullPointerException at Types.eraseNotNeeded() when compiling a class

Guoxiong Li gli at openjdk.java.net
Fri Apr 23 13:54:25 UTC 2021


On Wed, 21 Apr 2021 14:32:48 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:

>> So, in `Attr` we check that the class implements `Iterable`. In this case it does, but there's an incompatible override. That issues an error as expected, so compiling the provided test case:
>> 
>> 
>> public class T8232765 {
>>           public void test(String[] args) {
>>               MyLinkedList<Integer> list = new MyLinkedList<>();
>>               for (int x : list)
>>                   System.out.print(x);
>>           }
>>       }
>>       class MyLinkedList<T> implements java.lang.Iterable<T> {
>>           public void iterator() {}
>>       };
>> 
>> Does not result in a crash.
>> 
>> I suspect the issue in JBS is more subtle, and involves, perhaps, separate compilation? I find this very odd - typically javac stops at a phase (e.g. Attr) if one or more files had errors in that phase. In this case we have a bad implementation of `Iterable`, so we should not be able to go past `Attr`.
>
> Ok, I see where I went wrong. I can reproduce the crash - the problem I had was related to `public` appearing in a file with wrong name.
> 
> So, the issue occurs when two classes are defined in the same source. In that case, we advance T8232765 through the compiler pipeline almost independently of MyLinkedList. The only thing happening for MyLinkedList is the typeEnter step - but no Attr is performed, so no overriding checks.
> 
> If the `simple` compile policy is used, no crash occurs:
> 
> 
> javac -XDcompilePolicy=simple -XDverboseCompilePolicy=true Test.java 
> [attribute T8232765]
> [attribute MyLinkedList]
> Test.java:8: error: MyLinkedList is not abstract and does not override abstract method iterator() in Iterable
>                 class MyLinkedList<T> implements java.lang.Iterable<T> {
>                 ^
>   where T is a type-variable:
>     T extends Object declared in class MyLinkedList
> Test.java:9: error: iterator() in MyLinkedList cannot implement iterator() in Iterable
>                     public void iterator() {}
>                                 ^
>   return type void is not compatible with Iterator<T#2>
>   where T#1,T#2 are type-variables:
>     T#1 extends Object declared in interface Iterable
>     T#2 extends Object declared in class MyLinkedList
> 2 errors
> 
> 
> This has come up again in the past: should the *simple* policy be the default?

@mcimadamore Thank you for your review.

> issuing this kind of type-checking errors in Lower is unusual. This kind of stuff should be caught in earlier (e.g. in Attr)

I agree with you about it. I will try to move the check to Attr.

> So, the issue occurs when two classes are defined in the same source. In that case, we advance T8232765 through the compiler pipeline almost independently of MyLinkedList. The only thing happening for MyLinkedList is the typeEnter step - but no Attr is performed, so no overriding checks.

Yes, your analysis is right. And this situation is common when we use the iterator. So it is neccesary to fix it.

> This has come up again in the past: should the simple policy be the default?

For this bug, if we use the `simple` policy, we can get the more correct error message. But we don't know which policy the users use. So I think it is not a issue about the default policy. We only need to comfirm that all the policies work well, which is our ultimate goal.

-------------

PR: https://git.openjdk.java.net/jdk/pull/2099


More information about the compiler-dev mailing list