RFR: 8294943: Implement record patterns in enhanced for [v2]
Aggelos Biboudis
abimpoudis at openjdk.org
Mon Oct 31 13:59:38 UTC 2022
On Mon, 31 Oct 2022 08:52:45 GMT, Jan Lahoda <jlahoda at openjdk.org> wrote:
>> Aggelos Biboudis has updated the pull request incrementally with one additional commit since the last revision:
>>
>> Fix applicability bug
>
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java line 428:
>
>> 426: @Override
>> 427: boolean match(JCEnhancedForLoop tree){
>> 428: Assert.check(tree.getDeclarationKind() == EnhancedForLoopTree.DeclarationKind.VARIABLE);
>
> This assert is wrong - at the point the Analyzer is running, the enhanced for loop may use patterns Try, for example:
>
> public class ForEachTest {
> private void test(Iterable<? extends R> l) {
> for (R(Object a) : l) {
>
> }
> }
> record R(Object a) {}
> }
>
>
> And run:
>
> $ javac --enable-preview -source 20 -XDfind=all /tmp/ForEachTest.java
> Note: /tmp/ForEachTest.java uses preview features of Java SE 20.
> Note: Recompile with -Xlint:preview for details.
> An exception has occurred in the compiler (20-internal). Please file a bug against the Java compiler via the Java bug reporting page (https://bugreport.java.com) after checking the Bug Database (https://bugs.java.com) for duplicates. Include your program, the following diagnostic, and the parameters passed to the Java compiler in your report. Thank you.
> java.lang.AssertionError
> at jdk.compiler/com.sun.tools.javac.util.Assert.error(Assert.java:155)
> at jdk.compiler/com.sun.tools.javac.util.Assert.check(Assert.java:46)
> at jdk.compiler/com.sun.tools.javac.comp.Analyzer$RedundantLocalVarTypeAnalyzerForEach.match(Analyzer.java:428)
> ...
>
>
> Suggest to change the code of this method to:
>
> return tree.getDeclarationKind() == EnhancedForLoopTree.DeclarationKind.VARIABLE &&
> !isImplicitlyTyped((JCVariableDecl) tree.varOrRecordPattern);
>
>
> Note the asserts in the other methods here are OK, as those methods should not (AFAIK) be called when this method returns false.
>
> Analyzer tests are under `test/langtools/tools/javac/analyzer`.
Very good point! Added it as a stand alone test too!
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 1549:
>
>> 1547: }
>> 1548: }
>> 1549: if(tree.getDeclarationKind() == EnhancedForLoopTree.DeclarationKind.VARIABLE) {
>
> It should be possible to use `tree.varOrRecordPattern instanceof JCVariableDecl jcVariableDecl` as is done in `Flow`, right? (Dtto on other places.)
>
> Nit: we usually put a space between `if` and `(`.
I used what you propose when we need to initialise a variable, but kept the `getDeclarationKind()` method call when a variable is not needed (e.g. in assertions). Testing that way is visually clearer I think.
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java line 3463:
>
>> 3461: make.Ident(index)).setType(elemtype);
>> 3462:
>> 3463: JCBlock body = null;
>
> Offhand, it seems there are unnecessary changes in this file (like this declaration of `JCBlock body`. Please go through the patch, and undo the unnecessary changes. Keeping/adding the `Assert.check` is good, of course.
I reverted this but kept the necessary cast.
> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java line 753:
>
>> 751: make.at(tree.pos).VarDef(currentValue, null).setType(selectorType);
>> 752:
>> 753: List<JCExpression> params = List.of(makeNull(), makeNull());
>
> The specification says the exception should be `new MatchException(new NullPointerException())`, but the nested NPE seems to be missing here.
>
> FWIW, I think it is OK, for now, to create an empty NPE, but we may be able to do something better after PR 9746.
Addressed!
-------------
PR: https://git.openjdk.org/jdk/pull/10798
More information about the compiler-dev
mailing list