From vicente.romero at oracle.com Thu Nov 1 11:37:03 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 1 Nov 2018 07:37:03 -0400 Subject: RFR: JDK-8213103: RoundEnvironment.getElementsAnnotatedWith(Class) crashes with -source 8 In-Reply-To: <5BD988EB.8020304@oracle.com> References: <5BD988EB.8020304@oracle.com> Message-ID: <67a6a9ec-6bea-9cc8-69ee-4ca43efb03d8@oracle.com> the change looks good to me, just the copy year should be 2018 Vicente On 10/31/18 6:50 AM, Jan Lahoda wrote: > Hi, > > When RoundEnvironment.getElementsAnnotatedWith(Class) converts the > Class to TypeElement, it uses: > eltUtils.getTypeElement(eltUtils.getModuleElement(), > ) > > But this fails with -source 8, as there are no module (so > getModuleElement returns null, and getTypeElement checks the module > parameter is non-null). The proposed fix is to avoid this code. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8213103 > Webrev: http://cr.openjdk.java.net/~jlahoda/8213103/webrev.00/index.html > > Any feedback is welcome, > ??? Jan From jan.lahoda at oracle.com Thu Nov 1 12:34:10 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Thu, 1 Nov 2018 13:34:10 +0100 Subject: RFR: JDK-8213103: RoundEnvironment.getElementsAnnotatedWith(Class) crashes with -source 8 In-Reply-To: References: <5BD988EB.8020304@oracle.com> Message-ID: <5BDAF2C2.8010101@oracle.com> Hi Joe, Thanks for the comments. An updated webrev that uses Feature.MODULES instead of Elements.getAllModules, and also updates the copyright year as noted by Vicente, is here: http://cr.openjdk.java.net/~jlahoda/8213103/webrev.01/ (As a side note, Elements.getAllModules() should be OK performance-wise for this purpose, it basically reads an existing/pre-filed field.) For changing the method to throw IAE, while I agree this situation may point out an unintended difference between the compile- and run-time environments, sometimes the difference may be intentional (runtime dependencies need to be transitive, while compile time don't need to be) and may be benign, as is in the case where I've noticed this problem. So given the method didn't throw the exception in such cases before, I'd rather keep the behavior compatible. Thanks, Jan On 31.10.2018 18:27, joe darcy wrote: > Hi Jan, > > > On 10/31/2018 3:50 AM, Jan Lahoda wrote: >> Hi, >> >> When RoundEnvironment.getElementsAnnotatedWith(Class) converts the >> Class to TypeElement, it uses: >> eltUtils.getTypeElement(eltUtils.getModuleElement(), ) >> >> >> But this fails with -source 8, as there are no module (so >> getModuleElement returns null, and getTypeElement checks the module >> parameter is non-null). The proposed fix is to avoid this code. >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-8213103 >> Webrev: http://cr.openjdk.java.net/~jlahoda/8213103/webrev.00/index.html >> >> Any feedback is welcome, >> > > Thanks for looking at this issue. > > Stepping back a bit, the API functionality being supported is > > RoundEnvironment.getElementsAnnotatedWith?(Class Annotation> a) > > and related methods which take in annotation types indicated using Class > objects (a runtime core reflection representation) and convert them > internally to TypeElement's (a compile-time representation) by > extracting the name of the annotation type and then doing various look-ups. > > If the compile-time and runtime environments and configured to be > consistent with each other, then a runtime annotation type should be > able to get back a corresponding compile-time representation. However, > it is possible for the environments to not be consistent, leading to > this bug and the earlier change 8190886: "package-info handling in > RoundEnvironment.getElementsAnnotatedWith" which this proposed fix amends. > > The proposed "return null" arm in > > @@ -285,13 +285,15 @@ > // differ from the single module being compiled. > String name = annotation.getCanonicalName(); > TypeElement annotationElement = eltUtils.getTypeElement(name); > if (annotationElement != null) > return annotationElement; > - else { > + else if (!eltUtils.getAllModuleElements().isEmpty()) { > String moduleName = > Objects.requireNonNullElse(annotation.getModule().getName(), ""); > return > eltUtils.getTypeElement(eltUtils.getModuleElement(moduleName), name); > + } else { > + return null; > } > } > > private Element mirrorAsElement(AnnotationMirror annotationMirror) { > return annotationMirror.getAnnotationType().asElement(); > > is basically the handling for an inconsistent environment pre-modules. > The preceding lines are an, in retrospect, incomplete handling of an > inconsistent state with modules. > > I recommend the check for "if modules are supported" be implemented > using a Source-based predicate so that any future dead code will get > removed once modules are in all supported source levels. In that route > is not chosen, is getAllModuleElements() a good-performing predicate for > this purpose? Would something like "if (getModuleElement?("java.base") > != null )" be better? > > If the annotation type indicated by the Class object *cannot* be turned > into an compile-time annotation type, arguably that is an erroneous > situation that should cause an exception. The IllegalArgumentException > clauses of > > RoundEnvironment.getElementsAnnotatedWith?(Class a) > RoundEnvironment.getElementsAnnotatedWithAny?(Set Annotation>> annotations) > > could be expanded to cover this situation and, in the implementation, > return null replaced by throwing an informative exception. > > What do you think? > > Cheers, > > -Joe > From joe.darcy at oracle.com Thu Nov 1 17:20:13 2018 From: joe.darcy at oracle.com (joe darcy) Date: Thu, 1 Nov 2018 10:20:13 -0700 Subject: RFR: JDK-8213103: RoundEnvironment.getElementsAnnotatedWith(Class) crashes with -source 8 In-Reply-To: <5BDAF2C2.8010101@oracle.com> References: <5BD988EB.8020304@oracle.com> <5BDAF2C2.8010101@oracle.com> Message-ID: <96c5ac74-dce6-0f07-fa5f-793e972bb859@oracle.com> Hi Jan, If we had considered this situation more careful during JSR 269, we might have specified this condition to be an error. However, as you point out, the long-standing behavior has been to return null so it is probably best to preserve that. I've filed a follow-up spec bug, JDK-8213256: "Clarify runtime vs compile time annotations for RoundEnvironment.getElementsAnnotatedWith(Class)", to make the possibility of the Class -> TypeElement failing explicit. For the annotation processor in the test file, consider subclassing test/langtools/tools/javac/lib/JavacTestingAbstractProcessor. Looks good to me to push as-is or with a possible test update. Thanks, -Joe On 11/1/2018 5:34 AM, Jan Lahoda wrote: > Hi Joe, > > Thanks for the comments. An updated webrev that uses Feature.MODULES > instead of Elements.getAllModules, and also updates the copyright year > as noted by Vicente, is here: > http://cr.openjdk.java.net/~jlahoda/8213103/webrev.01/ > > (As a side note, Elements.getAllModules() should be OK > performance-wise for this purpose, it basically reads an > existing/pre-filed field.) > > For changing the method to throw IAE, while I agree this situation may > point out an unintended difference between the compile- and run-time > environments, sometimes the difference may be intentional (runtime > dependencies need to be transitive, while compile time don't need to > be) and may be benign, as is in the case where I've noticed this > problem. So given the method didn't throw the exception in such cases > before, I'd rather keep the behavior compatible. > > Thanks, > ??? Jan > From jonathan.gibbons at oracle.com Thu Nov 1 21:20:53 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 1 Nov 2018 14:20:53 -0700 Subject: RFR: JDK-8213263: fix legal headers in test/langtools Message-ID: Please review a tedious but conceptually simple update to fix the legal headers in a lot of test/langtools files. The change is to remove the '"Classpath" exception' from the header, which should not be used in test files. The change was made by executing the following script: grep -rl '"Classpath" exception' test/langtools | xargs sed --in-place \ ??? -e 's/? Oracle designates this//' \ ??? -e '/particular file as subject to the "Classpath" exception as provided/d' \ ??? -e '/by Oracle in the LICENSE file that accompanied this code./d' After applying the script and running the tests, two tests failed. These two tests were golden-file tests and were internally inconsistent: they had a full legal header, in addition to the special token "/nodynamiccopyright/" to justify that they should not have a full legal header.? These tests, and their golden files, were manually updated.? The affected files were: test/langtools/tools/javac/lvti/T8200199.java test/langtools/tools/javac/lvti/T8200199.out test/langtools/tools/javac/lvti/badTypeReference/BadTypeReference.java test/langtools/tools/javac/lvti/badTypeReference/BadTypeReference.out JBS: https://bugs.openjdk.java.net/browse/JDK-8213263 Webrev: http://cr.openjdk.java.net/~jjg/8213263/webrev.00/ With the exception of the 4 files listed above, it may be easiest to scan through the patch file directly. -- Jon From joe.darcy at oracle.com Thu Nov 1 21:24:32 2018 From: joe.darcy at oracle.com (Joseph D. Darcy) Date: Thu, 01 Nov 2018 14:24:32 -0700 Subject: RFR: JDK-8213263: fix legal headers in test/langtools In-Reply-To: References: Message-ID: <5BDB6F10.6050200@oracle.com> Looks fine Jon; thanks, -Joe On 11/1/2018 2:20 PM, Jonathan Gibbons wrote: > Please review a tedious but conceptually simple update to fix the > legal headers in a lot of test/langtools files. > > The change is to remove the '"Classpath" exception' from the header, > which should not be used in test files. > > The change was made by executing the following script: > > grep -rl '"Classpath" exception' test/langtools | xargs sed --in-place \ > -e 's/ Oracle designates this//' \ > -e '/particular file as subject to the "Classpath" exception as > provided/d' \ > -e '/by Oracle in the LICENSE file that accompanied this code./d' > > After applying the script and running the tests, two tests failed. > These two tests were golden-file tests and were internally > inconsistent: they had a full legal header, in addition to the special > token "/nodynamiccopyright/" to justify that they should not have a > full legal header. These tests, and their golden files, were manually > updated. The affected files were: > > test/langtools/tools/javac/lvti/T8200199.java > test/langtools/tools/javac/lvti/T8200199.out > test/langtools/tools/javac/lvti/badTypeReference/BadTypeReference.java > test/langtools/tools/javac/lvti/badTypeReference/BadTypeReference.out > > JBS: https://bugs.openjdk.java.net/browse/JDK-8213263 > Webrev: http://cr.openjdk.java.net/~jjg/8213263/webrev.00/ > > With the exception of the 4 files listed above, it may be easiest to > scan through the patch file directly. > > -- Jon > From jonathan.gibbons at oracle.com Thu Nov 1 22:04:51 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 1 Nov 2018 15:04:51 -0700 Subject: RFR: XXS: JDK-8213265: fix missing newlines at end of files Message-ID: <35c695ae-556a-cbe4-31cd-ad389545225a@oracle.com> Please review a simple fix which fixes some files which did not end with a newline character. The changes were performed automagically by the following command: ?for i in $(find test/langtools -name \*.html | xargs pcregrep -LM '\n$' ) ; do echo >> $i ; done The webrev shows no changes for the individual files; the patch shows the changes to the last line. JBS: https://bugs.openjdk.java.net/browse/JDK-8213265 Webrev: http://cr.openjdk.java.net/~jjg/8213265/webrev.00/index.html -- Jon From joe.darcy at oracle.com Fri Nov 2 17:02:42 2018 From: joe.darcy at oracle.com (joe darcy) Date: Fri, 2 Nov 2018 10:02:42 -0700 Subject: JDK 12 RFR of JDK-8213256: Clarify runtime vs ,compile time annotations for ,RoundEnvironment.getElementsAnnotatedWith(Class) Message-ID: <39448ea5-a3f4-01e6-793c-87c8dc98f791@oracle.com> Hello, As a follow-up to recent discussions, please review the proposed changes and CSR for ??? JDK-8213256: Clarify runtime vs ,compile time annotations for ,RoundEnvironment.getElementsAnnotatedWith(Class) ??? CSR:? https://bugs.openjdk.java.net/browse/JDK-8213310 ??? webrev: http://cr.openjdk.java.net/~darcy/8213256.0/ Patch below. Thanks, -Joe --- old/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java 2018-11-02 09:55:44.074001000 -0700 +++ new/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java 2018-11-02 09:55:43.902001000 -0700 @@ -143,11 +143,26 @@ ????? * simply because a {@code module-info} file for that module was ????? * created. ????? * +???? *

Note: An implementation of this method typically performs +???? * an internal conversion from the runtime reflective +???? * representation of an annotation type as a {@code Class} object +???? * to a different representation used for annotation +???? * processing. The set of annotation types present in the runtime +???? * context may differ from the set of annotation types present in +???? * the context of annotation processing in a particular +???? * environmental configuration. If an runtime annotation type is +???? * not present in the annotation processing context, the situation +???? * is not treated as an error and no elements are found for that +???? * annotation type. +???? * ????? * @param a? annotation type being requested ????? * @return the elements annotated with the given annotation type, ????? * or an empty set if there are none ????? * @throws IllegalArgumentException if the argument does not ????? * represent an annotation type +???? * +???? * @see AnnotatedConstruct.getAnnotation(Class) +???? * @see AnnotatedConstruct.getAnnotationsByType(Class) ????? */ ???? Set getElementsAnnotatedWith(Class a); @@ -155,6 +170,18 @@ ????? * Returns the elements annotated with one or more of the given ????? * annotation types. ????? * +???? *

Note: An implementation of this method typically performs +???? * an internal conversion from the runtime reflective +???? * representation of an annotation type as a {@code Class} object +???? * to a different representation used for annotation +???? * processing. The set of annotation types present in the runtime +???? * context may differ from the set of annotation types present in +???? * the context of annotation processing in a particular +???? * environmental configuration. If an runtime annotation type is +???? * not present in the annotation processing context, the situation +???? * is not treated as an error and no elements are found for that +???? * annotation type. +???? * ????? * @apiNote This method may be useful when processing repeating ????? * annotations by looking for an annotation type and its ????? * containing annotation type at the same time. @@ -172,6 +199,10 @@ ????? * @throws IllegalArgumentException if the any elements of the ????? * argument set do not represent an annotation type ????? * @jls 9.6.3 Repeatable Annotation Types +???? * +???? * @see AnnotatedConstruct.getAnnotation(Class) +???? * @see AnnotatedConstruct.getAnnotationsByType(Class) +???? * ????? * @since 9 ????? */ ???? default Set getElementsAnnotatedWithAny(Set> annotations){ From jonathan.gibbons at oracle.com Fri Nov 2 18:29:56 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 2 Nov 2018 11:29:56 -0700 Subject: JDK 12 RFR of JDK-8213256: Clarify runtime vs ,compile time annotations for ,RoundEnvironment.getElementsAnnotatedWith(Class) In-Reply-To: <39448ea5-a3f4-01e6-793c-87c8dc98f791@oracle.com> References: <39448ea5-a3f4-01e6-793c-87c8dc98f791@oracle.com> Message-ID: <363c97ef-2841-cf34-1d98-020b3678a565@oracle.com> Looks OK to me. -- Jon On 11/02/2018 10:02 AM, joe darcy wrote: > Hello, > > As a follow-up to recent discussions, please review the proposed > changes and CSR for > > ??? JDK-8213256: Clarify runtime vs ,compile time annotations for > ,RoundEnvironment.getElementsAnnotatedWith(Class) > ??? CSR:? https://bugs.openjdk.java.net/browse/JDK-8213310 > ??? webrev: http://cr.openjdk.java.net/~darcy/8213256.0/ > > Patch below. > > Thanks, > > -Joe > > --- > old/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java > 2018-11-02 09:55:44.074001000 -0700 > +++ > new/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java > 2018-11-02 09:55:43.902001000 -0700 > @@ -143,11 +143,26 @@ > ????? * simply because a {@code module-info} file for that module was > ????? * created. > ????? * > +???? *

Note: An implementation of this method typically performs > +???? * an internal conversion from the runtime reflective > +???? * representation of an annotation type as a {@code Class} object > +???? * to a different representation used for annotation > +???? * processing. The set of annotation types present in the runtime > +???? * context may differ from the set of annotation types present in > +???? * the context of annotation processing in a particular > +???? * environmental configuration. If an runtime annotation type is > +???? * not present in the annotation processing context, the situation > +???? * is not treated as an error and no elements are found for that > +???? * annotation type. > +???? * > ????? * @param a? annotation type being requested > ????? * @return the elements annotated with the given annotation type, > ????? * or an empty set if there are none > ????? * @throws IllegalArgumentException if the argument does not > ????? * represent an annotation type > +???? * > +???? * @see AnnotatedConstruct.getAnnotation(Class) > +???? * @see AnnotatedConstruct.getAnnotationsByType(Class) > ????? */ > ???? Set getElementsAnnotatedWith(Class Annotation> a); > > @@ -155,6 +170,18 @@ > ????? * Returns the elements annotated with one or more of the given > ????? * annotation types. > ????? * > +???? *

Note: An implementation of this method typically performs > +???? * an internal conversion from the runtime reflective > +???? * representation of an annotation type as a {@code Class} object > +???? * to a different representation used for annotation > +???? * processing. The set of annotation types present in the runtime > +???? * context may differ from the set of annotation types present in > +???? * the context of annotation processing in a particular > +???? * environmental configuration. If an runtime annotation type is > +???? * not present in the annotation processing context, the situation > +???? * is not treated as an error and no elements are found for that > +???? * annotation type. > +???? * > ????? * @apiNote This method may be useful when processing repeating > ????? * annotations by looking for an annotation type and its > ????? * containing annotation type at the same time. > @@ -172,6 +199,10 @@ > ????? * @throws IllegalArgumentException if the any elements of the > ????? * argument set do not represent an annotation type > ????? * @jls 9.6.3 Repeatable Annotation Types > +???? * > +???? * @see AnnotatedConstruct.getAnnotation(Class) > +???? * @see AnnotatedConstruct.getAnnotationsByType(Class) > +???? * > ????? * @since 9 > ????? */ > ???? default Set > getElementsAnnotatedWithAny(Set> > annotations){ > From jan.lahoda at oracle.com Fri Nov 2 19:36:18 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Fri, 2 Nov 2018 20:36:18 +0100 Subject: JDK 12 RFR of JDK-8213256: Clarify runtime vs ,compile time annotations for ,RoundEnvironment.getElementsAnnotatedWith(Class) In-Reply-To: <39448ea5-a3f4-01e6-793c-87c8dc98f791@oracle.com> References: <39448ea5-a3f4-01e6-793c-87c8dc98f791@oracle.com> Message-ID: <5BDCA732.3040408@oracle.com> Looks good to me. Jan On 2.11.2018 18:02, joe darcy wrote: > Hello, > > As a follow-up to recent discussions, please review the proposed changes > and CSR for > > JDK-8213256: Clarify runtime vs ,compile time annotations for > ,RoundEnvironment.getElementsAnnotatedWith(Class) > CSR: https://bugs.openjdk.java.net/browse/JDK-8213310 > webrev: http://cr.openjdk.java.net/~darcy/8213256.0/ > > Patch below. > > Thanks, > > -Joe > > --- > old/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java > 2018-11-02 09:55:44.074001000 -0700 > +++ > new/src/java.compiler/share/classes/javax/annotation/processing/RoundEnvironment.java > 2018-11-02 09:55:43.902001000 -0700 > @@ -143,11 +143,26 @@ > * simply because a {@code module-info} file for that module was > * created. > * > + *

Note: An implementation of this method typically performs > + * an internal conversion from the runtime reflective > + * representation of an annotation type as a {@code Class} object > + * to a different representation used for annotation > + * processing. The set of annotation types present in the runtime > + * context may differ from the set of annotation types present in > + * the context of annotation processing in a particular > + * environmental configuration. If an runtime annotation type is > + * not present in the annotation processing context, the situation > + * is not treated as an error and no elements are found for that > + * annotation type. > + * > * @param a annotation type being requested > * @return the elements annotated with the given annotation type, > * or an empty set if there are none > * @throws IllegalArgumentException if the argument does not > * represent an annotation type > + * > + * @see AnnotatedConstruct.getAnnotation(Class) > + * @see AnnotatedConstruct.getAnnotationsByType(Class) > */ > Set getElementsAnnotatedWith(Class Annotation> a); > > @@ -155,6 +170,18 @@ > * Returns the elements annotated with one or more of the given > * annotation types. > * > + *

Note: An implementation of this method typically performs > + * an internal conversion from the runtime reflective > + * representation of an annotation type as a {@code Class} object > + * to a different representation used for annotation > + * processing. The set of annotation types present in the runtime > + * context may differ from the set of annotation types present in > + * the context of annotation processing in a particular > + * environmental configuration. If an runtime annotation type is > + * not present in the annotation processing context, the situation > + * is not treated as an error and no elements are found for that > + * annotation type. > + * > * @apiNote This method may be useful when processing repeating > * annotations by looking for an annotation type and its > * containing annotation type at the same time. > @@ -172,6 +199,10 @@ > * @throws IllegalArgumentException if the any elements of the > * argument set do not represent an annotation type > * @jls 9.6.3 Repeatable Annotation Types > + * > + * @see AnnotatedConstruct.getAnnotation(Class) > + * @see AnnotatedConstruct.getAnnotationsByType(Class) > + * > * @since 9 > */ > default Set > getElementsAnnotatedWithAny(Set> annotations){ > From vicente.romero at oracle.com Fri Nov 2 21:10:56 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 2 Nov 2018 17:10:56 -0400 Subject: RFR: XXS: JDK-8213265: fix missing newlines at end of files In-Reply-To: <35c695ae-556a-cbe4-31cd-ad389545225a@oracle.com> References: <35c695ae-556a-cbe4-31cd-ad389545225a@oracle.com> Message-ID: <094c4929-742e-d119-a155-f1e0d9ad5c3e@oracle.com> looks good, Vicente On 11/1/18 6:04 PM, Jonathan Gibbons wrote: > Please review a simple fix which fixes some files which did not end > with a newline character. > > The changes were performed automagically by the following command: > > ?for i in $(find test/langtools -name \*.html | xargs pcregrep -LM > '\n$' ) ; do echo >> $i ; done > > The webrev shows no changes for the individual files; the patch shows > the changes to the last line. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8213265 > Webrev: http://cr.openjdk.java.net/~jjg/8213265/webrev.00/index.html > > -- Jon From fey at apiomat.com Mon Nov 5 14:24:16 2018 From: fey at apiomat.com (Andreas Fey) Date: Mon, 5 Nov 2018 14:24:16 +0000 Subject: Possible open file leak in com.sun.tools.javac.file.JavacFileManager Message-ID: <92415a9981670e5a653c9d5155d6dee4fa0cfaff.camel@apiomat.com> Hi all, we maybe found a bug in the com.sun.tools.javac.file.JavacFileManager; our tool makes heavy use of compiling classes during runtime, and after switching from JDK 8 to 11, we noticed hundreds of open files being created during list() and only closed when JVM exists. The concerning lines of code are: @Override @DefinedBy(Api.COMPILER) public Iterable list(Location location, String packageName, Set kinds, boolean recurse) throws IOException { checkNotModuleOrientedLocation(location); // validatePackageName(packageName); nullCheck(packageName); nullCheck(kinds); Iterable path = getLocationAsPaths(location); if (path == null) return List.nil(); RelativeDirectory subdirectory = RelativeDirectory.forPackage(packageName); ListBuffer results = new ListBuffer<>(); for (Path directory : path) { Container container = getContainer(directory); container.list(directory, subdirectory, kinds, recurse, results); } return results.toList(); } We think, a container.close() is missing in the for loop. Without this, a filehandle is created for every container/directiry found here. To test this, the following code snipped can be used, but the location must be set property to find a valid path != null: @Test public void testFileManager( ) throws IOException { countOpenFiles( ); final Set kinds = new HashSet<>( ); kinds.add( javax.tools.JavaFileObject.Kind.OTHER ); kinds.add( javax.tools.JavaFileObject.Kind.SOURCE ); kinds.add( javax.tools.JavaFileObject.Kind.CLASS ); kinds.add( javax.tools.JavaFileObject.Kind.HTML ); final StandardJavaFileManager sfm = ToolProvider.getSystemJavaCompiler( ).getStandardFileManager( null, null, null ); sfm.list( new JavaFileManager.Location( ) { @Override public boolean isOutputLocation( ) { return false; } @Override public String getName( ) { return "CLASS_NAME"; } }, "com", kinds, true ); countOpenFiles( ); } private void countOpenFiles( ) { final String processName = java.lang.management.ManagementFactory.getRuntimeMXBean( ).getName( ); final long pid = Long.parseLong( processName.split( "@" )[ 0 ] ); try { final Runtime rt = Runtime.getRuntime( ); final Process pr = rt.exec( "lsof -p " + pid ); int ctr = 0; final BufferedReader br = new BufferedReader( new InputStreamReader( pr.getInputStream( ) ) ); while ( ( br.readLine( ) ) != null ) ctr++; pr.waitFor( ); pr.destroy( ); System.out.println( "Open files: " + ctr ); } catch ( final Exception e ) { e.printStackTrace( ); } } Can anybody confirm this? Best, Andreas -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Mon Nov 5 15:55:08 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Mon, 5 Nov 2018 07:55:08 -0800 Subject: Possible open file leak in com.sun.tools.javac.file.JavacFileManager In-Reply-To: <92415a9981670e5a653c9d5155d6dee4fa0cfaff.camel@apiomat.com> References: <92415a9981670e5a653c9d5155d6dee4fa0cfaff.camel@apiomat.com> Message-ID: Andreas, We'll take a look. -- Jon On 11/5/18 6:24 AM, Andreas Fey wrote: > Hi all, > > we maybe found a bug in the com.sun.tools.javac.file.JavacFileManager; > our tool makes heavy use of compiling classes during runtime, and > after switching from JDK 8 to 11, we noticed hundreds of open files > being created during list() and only closed when JVM exists. The > concerning lines of code are: > > ?@Override @DefinedBy(Api.COMPILER) > ????public Iterable list(Location location, > ?????????????????????????????????????????String packageName, > ?????????????????????????????????????????Set kinds, > ?????????????????????????????????????????boolean recurse) > ????????throws IOException > ????{ > ????????checkNotModuleOrientedLocation(location); > ????????// validatePackageName(packageName); > ????????nullCheck(packageName); > ????????nullCheck(kinds); > > ????????Iterable path = getLocationAsPaths(location); > ????????if (path == null) > ????????????return List.nil(); > ????????RelativeDirectory subdirectory = > RelativeDirectory.forPackage(packageName); > ????????ListBuffer results = new ListBuffer<>(); > > ????????for (Path directory : path) { > ????????????Container container = getContainer(directory); > > ????????????container.list(directory, subdirectory, kinds, recurse, > results); > ????????} > > ????????return results.toList(); > ????} > > We think, a container.close() is missing in the for loop. Without > this, a filehandle is created for every container/directiry found > here. To test this, the following code snipped can be used, but the > location must be set property to find a valid path != null: > > @Test > public void testFileManager( ) throws IOException > { > countOpenFiles( ); > > final Set kinds = new HashSet<>( ); > kinds.add( javax.tools.JavaFileObject.Kind.OTHER ); > kinds.add( javax.tools.JavaFileObject.Kind.SOURCE ); > kinds.add( javax.tools.JavaFileObject.Kind.CLASS ); > kinds.add( javax.tools.JavaFileObject.Kind.HTML ); > > final StandardJavaFileManager sfm = > ToolProvider.getSystemJavaCompiler( ).getStandardFileManager( null, > null, null ); > sfm.list( new JavaFileManager.Location( ) > { > @Override > public boolean isOutputLocation( ) > { > return false; > } > > @Override > public String getName( ) > { > return "CLASS_NAME"; > } > }, "com", kinds, true ); > > countOpenFiles( ); > } > > private void countOpenFiles( ) > { > final String processName = > java.lang.management.ManagementFactory.getRuntimeMXBean( ).getName( ); > final long pid = Long.parseLong( processName.split( "@" )[ 0 ] ); > try > { > final Runtime rt = Runtime.getRuntime( ); > final Process pr = rt.exec( "lsof -p " + pid ); > > int ctr = 0; > final BufferedReader br = new BufferedReader( > new InputStreamReader( pr.getInputStream( ) ) ); > while ( ( br.readLine( ) ) != null ) > ctr++; > pr.waitFor( ); > pr.destroy( ); > > System.out.println( "Open files: " + ctr ); > } > catch ( final Exception e ) > { > e.printStackTrace( ); > } > } > > Can anybody confirm this? > Best, > Andreas From bsrbnd at gmail.com Mon Nov 5 21:21:02 2018 From: bsrbnd at gmail.com (B. Blaser) Date: Mon, 5 Nov 2018 22:21:02 +0100 Subject: Bit set intrinsic In-Reply-To: References: <9891ee55-7114-5b71-7a90-0c4e97deda2a@redhat.com> <05e00e85-046a-cdcb-7323-9e40f8a8fc86@redhat.com> <62d7984a-78dc-82a4-15aa-6deeebf95342@redhat.com> Message-ID: On Wed, 31 Oct 2018 at 15:51, B. Blaser wrote: > > The last but not least, I implemented the c2 part (using the 8-bit > AND/OR variant) to do sharper comparisons also on non-concurrent > execution: > > http://cr.openjdk.java.net/~bsrbnd/boolpack/webrev.02/ > > With 10e6 iterations the lock latency seems to be more or less > negligible and removing it would make the intrinsic about 10% faster > than BitSet without synchronization. Which actually seems to be due to the following missing ANDB/ORB patterns in x86_64.ad: instruct andB_mem_rReg(memory dst, rRegI src, rFlagsReg cr) %{ match(Set dst (StoreB dst (AndI (LoadB dst) src))); effect(KILL cr); ins_cost(150); format %{ "andb $dst, $src\t# byte" %} opcode(0x20); ins_encode(REX_breg_mem(src, dst), OpcP, reg_mem(src, dst)); ins_pipe(ialu_mem_reg); %} instruct orB_mem_rReg(memory dst, rRegI src, rFlagsReg cr) %{ match(Set dst (StoreB dst (OrI (LoadB dst) src))); effect(KILL cr); ins_cost(150); format %{ "orb $dst, $src\t# byte" %} opcode(0x08); ins_encode(REX_breg_mem(src, dst), OpcP, reg_mem(src, dst)); ins_pipe(ialu_mem_reg); %} The next two lines: 1) bits[index>>>3] |= (byte)(1 << (index & 7)); 2) bits[index>>>3] &= (byte)~(1 << (index & 7)); where assembled as: 1) 024 movsbl R8, [RSI + #16 + R10] # byte 02a movl R11, #1 # int 030 sall R11, RCX 033 movsbl R11, R11 # i2b 037 orl R11, R8 # int 03a movb [RSI + #16 + R10], R11 # byte 2) 024 movsbl R8, [RSI + #16 + R10] # byte 02a movl R11, #1 # int 030 sall R11, RCX 033 not R11 036 movsbl R11, R11 # i2b 03a andl R8, R11 # int 03d movb [RSI + #16 + R10], R8 # byte instead of: 1) 024 movl R11, #1 # int 02a sall R11, RCX 02d movsbl R11, R11 # i2b 031 orb [RSI + #16 + R10], R11 # byte 2) 024 movl R11, #1 # int 02a sall R11, RCX 02d not R11 030 movsbl R11, R11 # i2b 034 andb [RSI + #16 + R10], R11 # byte So, as first step, I would probably create a JBS issue and send out a RFR on hotspot-dev for this simple enhancement if there are no objections? Any opinion is welcome. Thanks, Bernard From vicente.romero at oracle.com Wed Nov 7 01:45:15 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Tue, 6 Nov 2018 20:45:15 -0500 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions Message-ID: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> Hi, Please review patch for [1] at [2]. The issue was can be explained with these two simple classes: ------------------------------------------------------------------------------------------------------ package pkg1; public class MyClass { ??? protected MyClass() {}??????????????? // (i) ??? protected MyClass(String s) {}??? // (ii) } ------------------------------------------------------------------------------------------------------ package pkg2; import pkg1.*; class Client { ??? void foo(MyClass m) {} ??? void bar() { ??????? foo(new MyClass<>(){}); ??? } } ------------------------------------------------------------------------------------------------------ both constructors are protected and given that we are dealing with a diamond expression, speculative attribution is used. During speculative attribution, javac removes the class definition from the equation meaning that: new MyClass<>(){} is rewritten as: new MyClass<>() the first expression has access to the protected constructors, the other one not.? So as both are protected, they are considered not accessible during overload resolution. Still constructor (i) is applicable but constructor (ii) is not applicable. So my proposal is to create an access error at Resolve::selectBest also for this case. Right now an access error is created only if no other method is found. When an access error is returned during overload resolution, the inaccessible symbol is still used and attached to the AST till the check phase can double check and issue an error or not. As during the check phase the diamond expression is attributed without rewriting, the compiler can then find out that constructor (i) is both applicable and accessible. Thanks, Vicente [1] https://bugs.openjdk.java.net/browse/JDK-8210197 [2] http://cr.openjdk.java.net/~vromero/8210197/webrev.00/ From joe.darcy at oracle.com Wed Nov 7 05:59:48 2018 From: joe.darcy at oracle.com (joe darcy) Date: Tue, 6 Nov 2018 21:59:48 -0800 Subject: JDK 12 RFR of JDK-8213444: Missing emphasis for term being defined Message-ID: Hello, Please review the small change to address ??? JDK-8213444: Missing emphasis for term being defined ??? http://cr.openjdk.java.net/~darcy/8213444.0/ Patch below. The emphasis markup is added to the "present" term in symmetry with the other terms being defined. Additionally, the formatting of some text in a {@code } structure is improved. The analogous list of definitions in javax.lang.model.AnnotatedConstruct already use emphasis for all the defined terms. Thanks, -Joe --- old/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java 2018-11-06 21:55:58.195000000 -0800 +++ new/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java 2018-11-06 21:55:58.027000000 -0800 @@ -74,7 +74,7 @@ ? * exactly one annotation whose value element contains A and whose ? * type is the containing annotation type of A 's type. ? * - *

  • An annotation A is present on an element E if either: + *
  • An annotation A is present on an element E if either: ? * ? *
      ? * @@ -145,8 +145,8 @@ ? * ? * ? * - *

      For an invocation of {@code get[Declared]AnnotationsByType( Class < - * T >)}, the order of annotations which are directly or indirectly + *

      For an invocation of {@code get[Declared]AnnotationsByType(Class )}, + * the order of annotations which are directly or indirectly ? * present on an element E is computed as if indirectly present ? * annotations on E are directly present on E in place ? * of their container annotation, in the order in which they appear in From mandy.chung at oracle.com Wed Nov 7 06:06:48 2018 From: mandy.chung at oracle.com (Mandy Chung) Date: Tue, 6 Nov 2018 22:06:48 -0800 Subject: JDK 12 RFR of JDK-8213444: Missing emphasis for term being defined In-Reply-To: References: Message-ID: <537eb6c2-192b-fa41-c0bc-a7cc880e0ac2@oracle.com> Looks good. Mandy On 11/6/18 9:59 PM, joe darcy wrote: > Hello, > > Please review the small change to address > > ??? JDK-8213444: Missing emphasis for term being defined > ??? http://cr.openjdk.java.net/~darcy/8213444.0/ > > Patch below. > > The emphasis markup is added to the "present" term in symmetry with > the other terms being defined. Additionally, the formatting of some > text in a {@code } structure is improved. > > The analogous list of definitions in > javax.lang.model.AnnotatedConstruct already use emphasis for all the > defined terms. > > Thanks, > > -Joe > > --- > old/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java > 2018-11-06 21:55:58.195000000 -0800 > +++ > new/src/java.base/share/classes/java/lang/reflect/AnnotatedElement.java > 2018-11-06 21:55:58.027000000 -0800 > @@ -74,7 +74,7 @@ > ? * exactly one annotation whose value element contains A and > whose > ? * type is the containing annotation type of A 's type. > ? * > - *

    • An annotation A is present on an element E if > either: > + *
    • An annotation A is present on an element > E if either: > ? * > ? *
        > ? * > @@ -145,8 +145,8 @@ > ? * > ? * > ? * > - *

        For an invocation of {@code get[Declared]AnnotationsByType( > Class < > - * T >)}, the order of annotations which are directly or indirectly > + *

        For an invocation of {@code > get[Declared]AnnotationsByType(Class )}, > + * the order of annotations which are directly or indirectly > ? * present on an element E is computed as if indirectly present > ? * annotations on E are directly present on E in place > ? * of their container annotation, in the order in which they appear in > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Wed Nov 7 08:59:06 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Nov 2018 08:59:06 +0000 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions In-Reply-To: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> References: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> Message-ID: Hi Vicente, I have some reservation about the fix; the idea behind the code in Resolve is that there exist some 'ordering' of error messages (by usefulness) - typically if you have something that is NOT APPLICABLE and ACCESSIBLE you'd want that to be reported instead of some inaccessible symbol found somewhere else. This logic makes a lot of sense given that javac scans supertypes from the bottom up - meaning that if you reported every single access error, you'd get a lot of spurious hits. So this patch has the problem of altering that behavior: now accessibility errors can 'trump' applicability ones. Another problem in the fix (maybe latent) is that you only create the access error if the bestSoFar is WRONG_MTH - but not if it's WRONG_MTHS, meaning that if the arity of the inapplicable symbols > 1 your patch is not effective. That said, instead of going down this route, I think it's worth asking a deeper (and JLS-related) question: what should be the modifiers of the synthetic constructor symbols that are used to resolve an anonymous class expression as per 15.9.3; that section says that the new constructors to be checked must be defined in the supertype of C (in this case MyClass itself) and that they must retain same modifiers (protected in this case): "If the class instance creation expression uses <>, then: [...]If C is an anonymous class, let D be the superclass or superinterface of C named by the class instance creation expression. If D is a class, let c1...cn be the constructors of class D. [...] A list of methods m1...mn is defined for the purpose of overload resolution and type argument inference. For all j (1 ? j ? n), mj is defined in terms of cj as follows: ... The modifiers of |m_j | are those of |c_j |" Under those rules, it is not clear to me how could the logic described in the spec succeed in finding the right method - they should both appear as non accessible (they are defined in D and in a different package, but with 'protected' modifier), so this should apply: "To choose a constructor, we temporarily consider m1...mn to be members of D. One of m1...mn is chosen, as determined by the class instance creation expression's argument expressions, using the process specified in ?15.12.2. If there is no unique most specific method that is both applicable and accessible, then a compile-time error occurs." For what is worth, even the non-diamond path of the spec text seems to suffer from this problem: it delegates blindly to 15.12.2 w/o saying what should happen if one of the constructors has protected access, but for some reason, javac doesn't seem to have a problem with that - to show that, simply remove all generic arguments for the instance creation expressions in the test case (e.g. create raw instances of MyClass) and see that it works w/o issues. There are a bunch of possible fixes here - if we are checking a diamond anon class we could either run 15.12.2 _pretending we are in D_, or we could drop any protected modifier. Both changes, I think, seem to imply some spec update. Maurizio On 07/11/2018 01:45, Vicente Romero wrote: > Hi, > > Please review patch for [1] at [2]. The issue was can be explained > with these two simple classes: > > ------------------------------------------------------------------------------------------------------ > > package pkg1; > > public class MyClass { > ??? protected MyClass() {}??????????????? // (i) > ??? protected MyClass(String s) {}??? // (ii) > } > > ------------------------------------------------------------------------------------------------------ > > > package pkg2; > > import pkg1.*; > > class Client { > ??? void foo(MyClass m) {} > > ??? void bar() { > ??????? foo(new MyClass<>(){}); > ??? } > } > > ------------------------------------------------------------------------------------------------------ > > > both constructors are protected and given that we are dealing with a > diamond expression, speculative attribution is used. During > speculative attribution, javac removes the class definition from the > equation meaning that: > new MyClass<>(){} is rewritten as: > new MyClass<>() > > the first expression has access to the protected constructors, the > other one not.? So as both are protected, they are considered not > accessible during overload resolution. Still constructor (i) is > applicable but constructor (ii) is not applicable. So my proposal is > to create an access error at Resolve::selectBest also for this case. > Right now an access error is created only if no other method is found. > When an access error is returned during overload resolution, the > inaccessible symbol is still used and attached to the AST till the > check phase can double check and issue an error or not. As during the > check phase the diamond expression is attributed without rewriting, > the compiler can then find out that constructor (i) is both applicable > and accessible. > > Thanks, > Vicente > > [1] https://bugs.openjdk.java.net/browse/JDK-8210197 > [2] http://cr.openjdk.java.net/~vromero/8210197/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Wed Nov 7 12:03:02 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Nov 2018 12:03:02 +0000 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions In-Reply-To: References: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> Message-ID: Btw, I think where javac is really tripping up is that it's not setting up the env.info.selectSuper parameter ahead of performing the resolution step. This parameter is setup like this: diamondEnv.info.selectSuper = cdef != null; I wonder, is speculative attribution completely messing this up (since it is removing bodies from anon classes using diamond) ? If so, then that is your issue (but it would still be nice if the spec text would be made clearer). Maurizio On 07/11/2018 08:59, Maurizio Cimadamore wrote: > > Hi Vicente, > I have some reservation about the fix; the idea behind the code in > Resolve is that there exist some 'ordering' of error messages (by > usefulness) - typically if you have something that is NOT APPLICABLE > and ACCESSIBLE you'd want that to be reported instead of some > inaccessible symbol found somewhere else. This logic makes a lot of > sense given that javac scans supertypes from the bottom up - meaning > that if you reported every single access error, you'd get a lot of > spurious hits. So this patch has the problem of altering that > behavior: now accessibility errors can 'trump' applicability ones. > > Another problem in the fix (maybe latent) is that you only create the > access error if the bestSoFar is WRONG_MTH - but not if it's > WRONG_MTHS, meaning that if the arity of the inapplicable symbols > 1 > your patch is not effective. > > That said, instead of going down this route, I think it's worth asking > a deeper (and JLS-related) question: what should be the modifiers of > the synthetic constructor symbols that are used to resolve an > anonymous class expression as per 15.9.3; that section says that the > new constructors to be checked must be defined in the supertype of C > (in this case MyClass itself) and that they must retain same modifiers > (protected in this case): > > "If the class instance creation expression uses <>, then: > > [...]If C is an anonymous class, let D be the superclass or > superinterface of C named by the class instance creation expression. > > If D is a class, let c1...cn be the constructors of class D. [...] > > A list of methods m1...mn is defined for the purpose of overload > resolution and type argument inference. For all j (1 ? j ? n), mj is > defined in terms of cj as follows: > > ... > > The modifiers of |m_j | are those of |c_j |" > > > Under those rules, it is not clear to me how could the logic described > in the spec succeed in finding the right method - they should both > appear as non accessible (they are defined in D and in a different > package, but with 'protected' modifier), so this should apply: > > "To choose a constructor, we temporarily consider m1...mn to be > members of D. One of m1...mn is chosen, as determined by the class > instance creation expression's argument expressions, using the process > specified in ?15.12.2. > > If there is no unique most specific method that is both applicable and > accessible, then a compile-time error occurs." > > > For what is worth, even the non-diamond path of the spec text seems to > suffer from this problem: it delegates blindly to 15.12.2 w/o saying > what should happen if one of the constructors has protected access, > but for some reason, javac doesn't seem to have a problem with that - > to show that, simply remove all generic arguments for the instance > creation expressions in the test case (e.g. create raw instances of > MyClass) and see that it works w/o issues. > > > There are a bunch of possible fixes here - if we are checking a > diamond anon class we could either run 15.12.2 _pretending we are in > D_, or we could drop any protected modifier. Both changes, I think, > seem to imply some spec update. > > > Maurizio > > > > > On 07/11/2018 01:45, Vicente Romero wrote: >> Hi, >> >> Please review patch for [1] at [2]. The issue was can be explained >> with these two simple classes: >> >> ------------------------------------------------------------------------------------------------------ >> >> package pkg1; >> >> public class MyClass { >> ??? protected MyClass() {}??????????????? // (i) >> ??? protected MyClass(String s) {}??? // (ii) >> } >> >> ------------------------------------------------------------------------------------------------------ >> >> >> package pkg2; >> >> import pkg1.*; >> >> class Client { >> ??? void foo(MyClass m) {} >> >> ??? void bar() { >> ??????? foo(new MyClass<>(){}); >> ??? } >> } >> >> ------------------------------------------------------------------------------------------------------ >> >> >> both constructors are protected and given that we are dealing with a >> diamond expression, speculative attribution is used. During >> speculative attribution, javac removes the class definition from the >> equation meaning that: >> new MyClass<>(){} is rewritten as: >> new MyClass<>() >> >> the first expression has access to the protected constructors, the >> other one not.? So as both are protected, they are considered not >> accessible during overload resolution. Still constructor (i) is >> applicable but constructor (ii) is not applicable. So my proposal is >> to create an access error at Resolve::selectBest also for this case. >> Right now an access error is created only if no other method is >> found. When an access error is returned during overload resolution, >> the inaccessible symbol is still used and attached to the AST till >> the check phase can double check and issue an error or not. As during >> the check phase the diamond expression is attributed without >> rewriting, the compiler can then find out that constructor (i) is >> both applicable and accessible. >> >> Thanks, >> Vicente >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8210197 >> [2] http://cr.openjdk.java.net/~vromero/8210197/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Wed Nov 7 13:40:23 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 7 Nov 2018 08:40:23 -0500 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions In-Reply-To: References: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> Message-ID: <2dee357c-77b9-fa87-c72c-65a01a0cf11e@oracle.com> Hi Maurizio, Thanks for the feedback. On 11/7/18 7:03 AM, Maurizio Cimadamore wrote: > > Btw, > I think where javac is really tripping up is that it's not setting up > the env.info.selectSuper parameter ahead of performing the resolution > step. This parameter is setup like this: > > diamondEnv.info.selectSuper = cdef != null; > right I had the initial idea of going for this alternative first and wrote a patch see [3], but later convinced myself that the patch I sent in the original mail was the way to go :(. So [3] is a fix on the lines of setting diamondEnv.info.selectSuper to true for diamonds that had a class definition attached even during speculative attribution. But the patch seemed a bit hacky to me. I guess that we should probably just add a field to JCNewClass to indicate if the ClassDef part has been removed just during speculative attribution as a cleaner solution, what do you think? > I wonder, is speculative attribution completely messing this up (since > it is removing bodies from anon classes using diamond) ? If so, then > that is your issue (but it would still be nice if the spec text would > be made clearer). > > Maurizio > [3] http://cr.openjdk.java.net/~vromero/8210197/webrev.01/ > On 07/11/2018 08:59, Maurizio Cimadamore wrote: >> >> Hi Vicente, >> I have some reservation about the fix; the idea behind the code in >> Resolve is that there exist some 'ordering' of error messages (by >> usefulness) - typically if you have something that is NOT APPLICABLE >> and ACCESSIBLE you'd want that to be reported instead of some >> inaccessible symbol found somewhere else. This logic makes a lot of >> sense given that javac scans supertypes from the bottom up - meaning >> that if you reported every single access error, you'd get a lot of >> spurious hits. So this patch has the problem of altering that >> behavior: now accessibility errors can 'trump' applicability ones. >> >> Another problem in the fix (maybe latent) is that you only create the >> access error if the bestSoFar is WRONG_MTH - but not if it's >> WRONG_MTHS, meaning that if the arity of the inapplicable symbols > 1 >> your patch is not effective. >> >> That said, instead of going down this route, I think it's worth >> asking a deeper (and JLS-related) question: what should be the >> modifiers of the synthetic constructor symbols that are used to >> resolve an anonymous class expression as per 15.9.3; that section >> says that the new constructors to be checked must be defined in the >> supertype of C (in this case MyClass itself) and that they must >> retain same modifiers (protected in this case): >> >> "If the class instance creation expression uses <>, then: >> >> [...]If C is an anonymous class, let D be the superclass or >> superinterface of C named by the class instance creation expression. >> >> If D is a class, let c1...cn be the constructors of class D. [...] >> >> A list of methods m1...mn is defined for the purpose of overload >> resolution and type argument inference. For all j (1 ? j ? n), mj is >> defined in terms of cj as follows: >> >> ... >> >> The modifiers of |m_j | are those of |c_j |" >> >> >> Under those rules, it is not clear to me how could the logic >> described in the spec succeed in finding the right method - they >> should both appear as non accessible (they are defined in D and in a >> different package, but with 'protected' modifier), so this should apply: >> >> "To choose a constructor, we temporarily consider m1...mn to be >> members of D. One of m1...mn is chosen, as determined by the class >> instance creation expression's argument expressions, using the >> process specified in ?15.12.2. >> >> If there is no unique most specific method that is both applicable >> and accessible, then a compile-time error occurs." >> >> >> For what is worth, even the non-diamond path of the spec text seems >> to suffer from this problem: it delegates blindly to 15.12.2 w/o >> saying what should happen if one of the constructors has protected >> access, but for some reason, javac doesn't seem to have a problem >> with that - to show that, simply remove all generic arguments for the >> instance creation expressions in the test case (e.g. create raw >> instances of MyClass) and see that it works w/o issues. >> >> >> There are a bunch of possible fixes here - if we are checking a >> diamond anon class we could either run 15.12.2 _pretending we are in >> D_, or we could drop any protected modifier. Both changes, I think, >> seem to imply some spec update. >> >> >> Maurizio >> >> >> >> >> On 07/11/2018 01:45, Vicente Romero wrote: >>> Hi, >>> >>> Please review patch for [1] at [2]. The issue was can be explained >>> with these two simple classes: >>> >>> ------------------------------------------------------------------------------------------------------ >>> >>> package pkg1; >>> >>> public class MyClass { >>> ??? protected MyClass() {}??????????????? // (i) >>> ??? protected MyClass(String s) {}??? // (ii) >>> } >>> >>> ------------------------------------------------------------------------------------------------------ >>> >>> >>> package pkg2; >>> >>> import pkg1.*; >>> >>> class Client { >>> ??? void foo(MyClass m) {} >>> >>> ??? void bar() { >>> ??????? foo(new MyClass<>(){}); >>> ??? } >>> } >>> >>> ------------------------------------------------------------------------------------------------------ >>> >>> >>> both constructors are protected and given that we are dealing with a >>> diamond expression, speculative attribution is used. During >>> speculative attribution, javac removes the class definition from the >>> equation meaning that: >>> new MyClass<>(){} is rewritten as: >>> new MyClass<>() >>> >>> the first expression has access to the protected constructors, the >>> other one not.? So as both are protected, they are considered not >>> accessible during overload resolution. Still constructor (i) is >>> applicable but constructor (ii) is not applicable. So my proposal is >>> to create an access error at Resolve::selectBest also for this case. >>> Right now an access error is created only if no other method is >>> found. When an access error is returned during overload resolution, >>> the inaccessible symbol is still used and attached to the AST till >>> the check phase can double check and issue an error or not. As >>> during the check phase the diamond expression is attributed without >>> rewriting, the compiler can then find out that constructor (i) is >>> both applicable and accessible. >>> >>> Thanks, >>> Vicente >>> >>> [1] https://bugs.openjdk.java.net/browse/JDK-8210197 >>> [2] http://cr.openjdk.java.net/~vromero/8210197/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Wed Nov 7 21:34:39 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Wed, 7 Nov 2018 13:34:39 -0800 Subject: RFR: JDK-8209055: c.s.t.javac.code.DeferredCompletionFailureHandler seems to use WeakHashMap incorrectly In-Reply-To: <5BD9C345.7090106@oracle.com> References: <5BD9C345.7090106@oracle.com> Message-ID: <4c98ad46-a9a7-28ba-aeee-ffc9cdaa8e69@oracle.com> Jan, You don't need to @build JavacTestingAbstractProcessor, since it is not used. Otherwise OK. -- Jon On 10/31/18 7:59 AM, Jan Lahoda wrote: > Hi, > > After JDK-8187950, when a Symbol is completed in "user"/external mode > (as opposed to "javac internal" mode), and the completion fails, the > failed Symbol is "split", so that the user's code and javac may see a > different version of the Symbol (e.g. completed/not completed). This > helps to prevent throwing CompletionFailures to user's code. > > But the issue is that ClassFinder.loadClass may create "speculative" > ClassSymbols, which are subsequently removed if they turn out to be > non-existent. But when this happens in the "user" mode (like inside > Elements.getTypeElement), even these non-existent ClassSymbols are > still retained, and the number of ClassSymbols retained this way may > be fairly high. The proposed patch is to clear these speculative > Symbols even from the "user" mode cache. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8209055 > Webrev: http://cr.openjdk.java.net/~jlahoda/8209055/webrev.00/ > > Any feedback is welcome. > > Thanks, > ??? Jan From maurizio.cimadamore at oracle.com Wed Nov 7 23:44:52 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Nov 2018 23:44:52 +0000 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions In-Reply-To: <2dee357c-77b9-fa87-c72c-65a01a0cf11e@oracle.com> References: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> <2dee357c-77b9-fa87-c72c-65a01a0cf11e@oracle.com> Message-ID: On 07/11/2018 13:40, Vicente Romero wrote: > right I had the initial idea of going for this alternative first and > wrote a patch see [3], but later convinced myself that the patch I > sent in the original mail was the way to go :(. So [3] is a fix on the > lines of setting diamondEnv.info.selectSuper to true for diamonds that > had a class definition attached even during speculative attribution. > But the patch seemed a bit hacky to me. I guess that we should > probably just add a field to JCNewClass to indicate if the ClassDef > part has been removed just during speculative attribution as a cleaner > solution, what do you think? Yep that would indeed be a good solution. As usual, if you want to avoid having a field, I guess you could also have a predicate method on JCNewClass which always return 'false' but which the deferred copier overrides to return 'true' so that you can piggy back on that? Maurizio From vicente.romero at oracle.com Thu Nov 8 00:24:31 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 7 Nov 2018 19:24:31 -0500 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body Message-ID: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> Please review the fix for [1] at [2]. The bug can be illustrated with this test case: import java.util.List; import java.util.function.Function; class DiamondInsideLambdaTest { ??? void build() { ??????? List> list = transform(null, ??????????????? builder -> new Function<>() { ??????????????????? public Double apply(String params) { return null; } ??????????????? }); ??? } ??? static List transform(List fromList, Function function) { return null; } } During lambda attribution, there is a preflow visitor that fill some holes, missing types / symbols, before doing an special flow analysis on the lambda. This flow analysis skip inner classes defined inside the lambda body. The preflow visitor is anyway visiting inner classes and filling, with garbage, some of the wholes. In most cases as the preflow step happens after the lambda body has been attributed, it should be a no-op. But if the lambda body contains a diamond as in this case, then it could be that the attribution can't be done previous to the preflow step. Simply because some types in the diamond could be waiting for type inference to come to a resolution. In that case preflow will modify the diamond expression and later on during completion, as some symbols and types are filled with erroneous types, they will keep that erroneous type. [1] https://bugs.openjdk.java.net/browse/JDK-8203277 [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Thu Nov 8 00:37:00 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 7 Nov 2018 19:37:00 -0500 Subject: RFR: JDK-8209055: c.s.t.javac.code.DeferredCompletionFailureHandler seems to use WeakHashMap incorrectly In-Reply-To: <5BD9C345.7090106@oracle.com> References: <5BD9C345.7090106@oracle.com> Message-ID: I'm OK with the patch, Thanks, Vicente On 10/31/18 10:59 AM, Jan Lahoda wrote: > Hi, > > After JDK-8187950, when a Symbol is completed in "user"/external mode > (as opposed to "javac internal" mode), and the completion fails, the > failed Symbol is "split", so that the user's code and javac may see a > different version of the Symbol (e.g. completed/not completed). This > helps to prevent throwing CompletionFailures to user's code. > > But the issue is that ClassFinder.loadClass may create "speculative" > ClassSymbols, which are subsequently removed if they turn out to be > non-existent. But when this happens in the "user" mode (like inside > Elements.getTypeElement), even these non-existent ClassSymbols are > still retained, and the number of ClassSymbols retained this way may > be fairly high. The proposed patch is to clear these speculative > Symbols even from the "user" mode cache. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8209055 > Webrev: http://cr.openjdk.java.net/~jlahoda/8209055/webrev.00/ > > Any feedback is welcome. > > Thanks, > ??? Jan From vicente.romero at oracle.com Thu Nov 8 01:56:24 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 7 Nov 2018 20:56:24 -0500 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions In-Reply-To: References: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> <2dee357c-77b9-fa87-c72c-65a01a0cf11e@oracle.com> Message-ID: I liked your suggestion thanks: http://cr.openjdk.java.net/~vromero/8210197/webrev.02/ On 11/7/18 6:44 PM, Maurizio Cimadamore wrote: > > On 07/11/2018 13:40, Vicente Romero wrote: >> right I had the initial idea of going for this alternative first and >> wrote a patch see [3], but later convinced myself that the patch I >> sent in the original mail was the way to go :(. So [3] is a fix on >> the lines of setting diamondEnv.info.selectSuper to true for diamonds >> that had a class definition attached even during speculative >> attribution. But the patch seemed a bit hacky to me. I guess that we >> should probably just add a field to JCNewClass to indicate if the >> ClassDef part has been removed just during speculative attribution as >> a cleaner solution, what do you think? > > Yep that would indeed be a good solution. As usual, if you want to > avoid having a field, I guess you could also have a predicate method > on JCNewClass which always return 'false' but which the deferred > copier overrides to return 'true' so that you can piggy back on that? > > Maurizio > > From maurizio.cimadamore at oracle.com Thu Nov 8 15:00:23 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 8 Nov 2018 15:00:23 +0000 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions In-Reply-To: References: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> <2dee357c-77b9-fa87-c72c-65a01a0cf11e@oracle.com> Message-ID: Looks good, I would only change the name of the TreeMaker factory so that it's clear that it's used by deferred attribution - e.g. SpeculativeNewClass Maurizio On 08/11/2018 01:56, Vicente Romero wrote: > I liked your suggestion thanks: > > http://cr.openjdk.java.net/~vromero/8210197/webrev.02/ > > On 11/7/18 6:44 PM, Maurizio Cimadamore wrote: >> >> On 07/11/2018 13:40, Vicente Romero wrote: >>> right I had the initial idea of going for this alternative first and >>> wrote a patch see [3], but later convinced myself that the patch I >>> sent in the original mail was the way to go :(. So [3] is a fix on >>> the lines of setting diamondEnv.info.selectSuper to true for >>> diamonds that had a class definition attached even during >>> speculative attribution. But the patch seemed a bit hacky to me. I >>> guess that we should probably just add a field to JCNewClass to >>> indicate if the ClassDef part has been removed just during >>> speculative attribution as a cleaner solution, what do you think? >> >> Yep that would indeed be a good solution. As usual, if you want to >> avoid having a field, I guess you could also have a predicate method >> on JCNewClass which always return 'false' but which the deferred >> copier overrides to return 'true' so that you can piggy back on that? >> >> Maurizio >> >> > From vicente.romero at oracle.com Thu Nov 8 15:15:54 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 8 Nov 2018 10:15:54 -0500 Subject: RFR: JDK-8210197: candidate selection during overload resolution can lead to unexpected results for diamond expressions In-Reply-To: References: <01f9ec94-7df0-ee1d-3779-65631acf79ff@oracle.com> <2dee357c-77b9-fa87-c72c-65a01a0cf11e@oracle.com> Message-ID: <9025d3d9-3e06-be93-127a-e38fecf68525@oracle.com> On 11/8/18 10:00 AM, Maurizio Cimadamore wrote: > Looks good, I would only change the name of the TreeMaker factory so > that it's clear that it's used by deferred attribution - e.g. > SpeculativeNewClass ok I will do that locally and push it > > Maurizio thanks, Vicente > > On 08/11/2018 01:56, Vicente Romero wrote: >> I liked your suggestion thanks: >> >> http://cr.openjdk.java.net/~vromero/8210197/webrev.02/ >> >> On 11/7/18 6:44 PM, Maurizio Cimadamore wrote: >>> >>> On 07/11/2018 13:40, Vicente Romero wrote: >>>> right I had the initial idea of going for this alternative first >>>> and wrote a patch see [3], but later convinced myself that the >>>> patch I sent in the original mail was the way to go :(. So [3] is a >>>> fix on the lines of setting diamondEnv.info.selectSuper to true for >>>> diamonds that had a class definition attached even during >>>> speculative attribution. But the patch seemed a bit hacky to me. I >>>> guess that we should probably just add a field to JCNewClass to >>>> indicate if the ClassDef part has been removed just during >>>> speculative attribution as a cleaner solution, what do you think? >>> >>> Yep that would indeed be a good solution. As usual, if you want to >>> avoid having a field, I guess you could also have a predicate method >>> on JCNewClass which always return 'false' but which the deferred >>> copier overrides to return 'true' so that you can piggy back on that? >>> >>> Maurizio >>> >>> >> From vicente.romero at oracle.com Thu Nov 8 22:16:06 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 8 Nov 2018 17:16:06 -0500 Subject: RFR: 8211450: UndetVar::dup is not copying the kind field to the duplicated instance Message-ID: Please review the fix for [1] at [2]. The issue boiled down to UndetVar::dup not copying all the fields to the new instance. In this case the kind field. This provoked that the special logic that applies to thrown type variables was not kicking in and thus thrown variables were not being instantiated to RuntimeException. This was provoking flow analysis to complain later on. Thanks, Vicente [1] https://bugs.openjdk.java.net/browse/JDK-8211450 [2] http://cr.openjdk.java.net/~vromero/8211450/webrev.00/ From maurizio.cimadamore at oracle.com Thu Nov 8 23:02:21 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 8 Nov 2018 23:02:21 +0000 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body In-Reply-To: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> References: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> Message-ID: Hi, I agree that preflow shouldn't care about nested constructs; but I wonder - is diamond anon class the only case we need to worry about here? What about a nested lambda expression? Maurizio On 08/11/2018 00:24, Vicente Romero wrote: > Please review the fix for [1] at [2]. The bug can be illustrated with > this test case: > > import java.util.List; > import java.util.function.Function; > > class DiamondInsideLambdaTest { > ??? void build() { > ??????? List> list = transform(null, > ??????????????? builder -> new Function<>() { > ??????????????????? public Double apply(String params) { return null; } > ??????????????? }); > ??? } > > ??? static List transform(List > fromList, Function function) { > return null; } > } > > During lambda attribution, there is a preflow visitor that fill some > holes, missing types / symbols, before doing an special flow analysis > on the lambda. This flow analysis skip inner classes defined inside > the lambda body. The preflow visitor is anyway visiting inner classes > and filling, with garbage, some of the wholes. In most cases as the > preflow step happens after the lambda body has been attributed, it > should be a no-op. But if the lambda body contains a diamond as in > this case, then it could be that the attribution can't be done > previous to the preflow step. Simply because some types in the diamond > could be waiting for type inference to come to a resolution. In that > case preflow will modify the diamond expression and later on during > completion, as some symbols and types are filled with erroneous types, > they will keep that erroneous type. > > [1] https://bugs.openjdk.java.net/browse/JDK-8203277 > [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Thu Nov 8 23:03:25 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 8 Nov 2018 23:03:25 +0000 Subject: RFR: 8211450: UndetVar::dup is not copying the kind field to the duplicated instance In-Reply-To: References: Message-ID: Whoops! Looks good. Maurizio On 08/11/2018 22:16, Vicente Romero wrote: > Please review the fix for [1] at [2]. The issue boiled down to > UndetVar::dup not copying all the fields to the new instance. In this > case the kind field. This provoked that the special logic that applies > to thrown type variables was not kicking in and thus thrown variables > were not being instantiated to RuntimeException. This was provoking > flow analysis to complain later on. > > Thanks, > Vicente > > [1] https://bugs.openjdk.java.net/browse/JDK-8211450 > [2] http://cr.openjdk.java.net/~vromero/8211450/webrev.00/ From vicente.romero at oracle.com Fri Nov 9 00:12:09 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 8 Nov 2018 19:12:09 -0500 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body In-Reply-To: References: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> Message-ID: <55121cfa-2b40-0f59-089c-cce57235eb91@oracle.com> On 11/8/18 6:02 PM, Maurizio Cimadamore wrote: > > Hi, > I agree that preflow shouldn't care about nested constructs; but I > wonder - is diamond anon class the only case we need to worry about > here? What about a nested lambda expression? > right I agree with you, what about [3]? > Maurizio > Vicente [3] http://cr.openjdk.java.net/~vromero/8203277/webrev.01/ > > On 08/11/2018 00:24, Vicente Romero wrote: >> Please review the fix for [1] at [2]. The bug can be illustrated with >> this test case: >> >> import java.util.List; >> import java.util.function.Function; >> >> class DiamondInsideLambdaTest { >> ??? void build() { >> ??????? List> list = transform(null, >> ??????????????? builder -> new Function<>() { >> ??????????????????? public Double apply(String params) { return null; } >> ??????????????? }); >> ??? } >> >> ??? static List transform(List >> fromList, Function function) { >> return null; } >> } >> >> During lambda attribution, there is a preflow visitor that fill some >> holes, missing types / symbols, before doing an special flow analysis >> on the lambda. This flow analysis skip inner classes defined inside >> the lambda body. The preflow visitor is anyway visiting inner classes >> and filling, with garbage, some of the wholes. In most cases as the >> preflow step happens after the lambda body has been attributed, it >> should be a no-op. But if the lambda body contains a diamond as in >> this case, then it could be that the attribution can't be done >> previous to the preflow step. Simply because some types in the >> diamond could be waiting for type inference to come to a resolution. >> In that case preflow will modify the diamond expression and later on >> during completion, as some symbols and types are filled with >> erroneous types, they will keep that erroneous type. >> >> [1] https://bugs.openjdk.java.net/browse/JDK-8203277 >> [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Fri Nov 9 10:57:03 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 9 Nov 2018 10:57:03 +0000 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body In-Reply-To: <55121cfa-2b40-0f59-089c-cce57235eb91@oracle.com> References: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> <55121cfa-2b40-0f59-089c-cce57235eb91@oracle.com> Message-ID: Looks good - can we cook up a test that is also stressing the other new code path? Maurizio On 09/11/2018 00:12, Vicente Romero wrote: > > > On 11/8/18 6:02 PM, Maurizio Cimadamore wrote: >> >> Hi, >> I agree that preflow shouldn't care about nested constructs; but I >> wonder - is diamond anon class the only case we need to worry about >> here? What about a nested lambda expression? >> > > right I agree with you, what about [3]? > >> Maurizio >> > Vicente > > [3] http://cr.openjdk.java.net/~vromero/8203277/webrev.01/ >> >> On 08/11/2018 00:24, Vicente Romero wrote: >>> Please review the fix for [1] at [2]. The bug can be illustrated >>> with this test case: >>> >>> import java.util.List; >>> import java.util.function.Function; >>> >>> class DiamondInsideLambdaTest { >>> ??? void build() { >>> ??????? List> list = transform(null, >>> ??????????????? builder -> new Function<>() { >>> ??????????????????? public Double apply(String params) { return null; } >>> ??????????????? }); >>> ??? } >>> >>> ??? static List transform(List >>> fromList, Function function) { >>> return null; } >>> } >>> >>> During lambda attribution, there is a preflow visitor that fill some >>> holes, missing types / symbols, before doing an special flow >>> analysis on the lambda. This flow analysis skip inner classes >>> defined inside the lambda body. The preflow visitor is anyway >>> visiting inner classes and filling, with garbage, some of the >>> wholes. In most cases as the preflow step happens after the lambda >>> body has been attributed, it should be a no-op. But if the lambda >>> body contains a diamond as in this case, then it could be that the >>> attribution can't be done previous to the preflow step. Simply >>> because some types in the diamond could be waiting for type >>> inference to come to a resolution. In that case preflow will modify >>> the diamond expression and later on during completion, as some >>> symbols and types are filled with erroneous types, they will keep >>> that erroneous type. >>> >>> [1] https://bugs.openjdk.java.net/browse/JDK-8203277 >>> [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From mlists at juma.me.uk Fri Nov 9 15:22:29 2018 From: mlists at juma.me.uk (Ismael Juma) Date: Fri, 9 Nov 2018 07:22:29 -0800 Subject: spotBugs and JDK-8194978: Javac produces dead code for try-with-resource In-Reply-To: References: Message-ID: Any comments on this? Many people are disabling spotBugs when compiling with Java 11 due to this issue: https://github.com/spotbugs/spotbugs/issues/756 Ismael On Thu, Sep 13, 2018 at 10:05 PM Ismael Juma wrote: > Hi all, > > JDK-8194978 introduced some changes to the bytecode generated by javac for > the try with resource construct. In the following code, it seems to > generate a null check on a reference after invoking a method on it: > > public static void readFileAsString(String path) throws IOException { > try (FileChannel fc = FileChannel.open(Paths.get(path))) { > fc.size(); > } > > } > > In line 16 to 22 of the bytecode, it looks like we check for null after > calling a method on the fc reference: > > 16: aload_1 > 17: invokevirtual #6 // Method > java/nio/channels/FileChannel.size:()J > 20: pop2 > 21: aload_1 > 22: ifnull 52 > 25: aload_1 > 26: invokevirtual #7 // Method > java/nio/channels/FileChannel.close:()V > > Is this intentional? I ask because this pattern triggers a spotBugs > warning since it often implies a bug in user's code: > > RCN | Nullcheck of fc at line 10 of value previously dereferenced in > TryTest.readFileAsString(String, Charset) > > Note that this works fine in Java versions older than Java 11. Since this > spotBugs warning is generally useful, it would be handy if javac did not > trigger it. Alternatively, if there's a good way to detect the code that > was generated by javac, spotBugs could be updated to ignore it. For > reference, this was discussed in the spotBugs issue tracker: > > https://github.com/spotbugs/spotbugs/issues/756 > > And method bytecode in full: > > public static void readFileAsString(java.lang.String) throws > java.io.IOException; > Code: > 0: aload_0 > 1: iconst_0 > 2: anewarray #2 // class java/lang/String > 5: invokestatic #3 // Method > java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path; > 8: iconst_0 > 9: anewarray #4 // class > java/nio/file/OpenOption > 12: invokestatic #5 // Method > java/nio/channels/FileChannel.open:(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/FileChannel; > 15: astore_1 > 16: aload_1 > 17: invokevirtual #6 // Method > java/nio/channels/FileChannel.size:()J > 20: pop2 > 21: aload_1 > 22: ifnull 52 > 25: aload_1 > 26: invokevirtual #7 // Method > java/nio/channels/FileChannel.close:()V > 29: goto 52 > 32: astore_2 > 33: aload_1 > 34: ifnull 50 > 37: aload_1 > 38: invokevirtual #7 // Method > java/nio/channels/FileChannel.close:()V > 41: goto 50 > 44: astore_3 > 45: aload_2 > 46: aload_3 > 47: invokevirtual #9 // Method > java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V > 50: aload_2 > 51: athrow > 52: return > Exception table: > from to target type > 16 21 32 Class java/lang/Throwable > 37 41 44 Class java/lang/Throwable > > Thanks, > Ismael > -------------- next part -------------- An HTML attachment was scrubbed... URL: From eolivelli at gmail.com Fri Nov 9 16:16:15 2018 From: eolivelli at gmail.com (Enrico Olivelli) Date: Fri, 9 Nov 2018 17:16:15 +0100 Subject: spotBugs and JDK-8194978: Javac produces dead code for try-with-resource In-Reply-To: References: Message-ID: Hi, I am in the same situation, I should add that from JDK9 the try-with-resources block added a $closeResource method, which I can't find in the example from Ismael see for reference another know problem with Spotbugs https://github.com/spotbugs/spotbugs/issues/493 Any help or clarification will be appreciated Thanks Enrico Il giorno ven 9 nov 2018 alle ore 16:24 Ismael Juma ha scritto: > > Any comments on this? Many people are disabling spotBugs when compiling with Java 11 due to this issue: > > https://github.com/spotbugs/spotbugs/issues/756 > > Ismael > > On Thu, Sep 13, 2018 at 10:05 PM Ismael Juma wrote: >> >> Hi all, >> >> JDK-8194978 introduced some changes to the bytecode generated by javac for the try with resource construct. In the following code, it seems to generate a null check on a reference after invoking a method on it: >> >> public static void readFileAsString(String path) throws IOException { >> try (FileChannel fc = FileChannel.open(Paths.get(path))) { >> fc.size(); >> } >> >> } >> >> In line 16 to 22 of the bytecode, it looks like we check for null after calling a method on the fc reference: >> >> 16: aload_1 >> 17: invokevirtual #6 // Method java/nio/channels/FileChannel.size:()J >> 20: pop2 >> 21: aload_1 >> 22: ifnull 52 >> 25: aload_1 >> 26: invokevirtual #7 // Method java/nio/channels/FileChannel.close:()V >> >> Is this intentional? I ask because this pattern triggers a spotBugs warning since it often implies a bug in user's code: >> >> RCN | Nullcheck of fc at line 10 of value previously dereferenced in TryTest.readFileAsString(String, Charset) >> >> Note that this works fine in Java versions older than Java 11. Since this spotBugs warning is generally useful, it would be handy if javac did not trigger it. Alternatively, if there's a good way to detect the code that was generated by javac, spotBugs could be updated to ignore it. For reference, this was discussed in the spotBugs issue tracker: >> >> https://github.com/spotbugs/spotbugs/issues/756 >> >> And method bytecode in full: >> >> public static void readFileAsString(java.lang.String) throws java.io.IOException; >> Code: >> 0: aload_0 >> 1: iconst_0 >> 2: anewarray #2 // class java/lang/String >> 5: invokestatic #3 // Method java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path; >> 8: iconst_0 >> 9: anewarray #4 // class java/nio/file/OpenOption >> 12: invokestatic #5 // Method java/nio/channels/FileChannel.open:(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/FileChannel; >> 15: astore_1 >> 16: aload_1 >> 17: invokevirtual #6 // Method java/nio/channels/FileChannel.size:()J >> 20: pop2 >> 21: aload_1 >> 22: ifnull 52 >> 25: aload_1 >> 26: invokevirtual #7 // Method java/nio/channels/FileChannel.close:()V >> 29: goto 52 >> 32: astore_2 >> 33: aload_1 >> 34: ifnull 50 >> 37: aload_1 >> 38: invokevirtual #7 // Method java/nio/channels/FileChannel.close:()V >> 41: goto 50 >> 44: astore_3 >> 45: aload_2 >> 46: aload_3 >> 47: invokevirtual #9 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V >> 50: aload_2 >> 51: athrow >> 52: return >> Exception table: >> from to target type >> 16 21 32 Class java/lang/Throwable >> 37 41 44 Class java/lang/Throwable >> >> Thanks, >> Ismael From vicente.romero at oracle.com Fri Nov 9 20:31:36 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 9 Nov 2018 15:31:36 -0500 Subject: spotBugs and JDK-8194978: Javac produces dead code for try-with-resource In-Reply-To: References: Message-ID: <25e5d853-e4d4-41aa-8221-00462389fc67@oracle.com> Hi, Sorry for the late reply. My evaluation on this issue is that javac is generating code according to the spec, see JLS11 14.20.3.1 [1]. There is an explicit check for null on the resource before invoking the close() method. This is the null check javac is generating. Fix for JDK-8194978 went a bit further trying to eliminate dead code for some cases for which javac could statically determine that the resource would be different from null. In particular if the resource was initialized with a new class expression. It could be argued that we could try to analyze the body and if we find out that a NPE must be thrown in the body of the try, then the null check on the resource would be deemed unnecessary. But then we can get to an implementation that will be out of sync with the spec plus it probably won't cover all cases. Thanks, Vicente [1] https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.20.3.1 On 11/9/18 10:22 AM, Ismael Juma wrote: > Any comments on this? Many people are disabling spotBugs when > compiling with Java 11 due to this issue: > > https://github.com/spotbugs/spotbugs/issues/756 > > Ismael > > On Thu, Sep 13, 2018 at 10:05 PM Ismael Juma > wrote: > > Hi all, > > JDK-8194978 introduced some changes to the bytecode generated by > javac for the try with resource construct. In the following code, > it seems to generate a null check on a reference after invoking a > method on it: > > ? ? public static void readFileAsString(String path) throws > IOException { > ? ? ? ? try (FileChannel fc = FileChannel.open(Paths.get(path))) { > ? ? ? ? ? ? fc.size(); > ? ? ? ? } > > ? ? } > > In line 16 to 22 of the bytecode, it looks like we check for null > after calling a method on the fc reference: > > ? ? ? 16: aload_1 > ? ? ? 17: invokevirtual #6? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.size:()J > ? ? ? 20: pop2 > ? ? ? 21: aload_1 > ? ? ? 22: ifnull? ? ? ? 52 > ? ? ? 25: aload_1 > ? ? ? 26: invokevirtual #7? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.close:()V > > Is this intentional? I ask because this pattern triggers a > spotBugs warning since it often implies a bug in user's code: > > RCN | Nullcheck of fc at line 10 of value previously dereferenced > in TryTest.readFileAsString(String, Charset) > > Note that this works fine in Java versions older than Java 11. > Since this spotBugs warning is generally useful, it would be handy > if javac did not trigger it. Alternatively, if there's a good way > to detect the?code that was generated by javac, spotBugs could be > updated to ignore it. For reference, this was discussed in the > spotBugs issue tracker: > > https://github.com/spotbugs/spotbugs/issues/756 > > And method bytecode in full: > > ? public static void readFileAsString(java.lang.String) throws > java.io.IOException; > ? ? Code: > ? ? ? ?0: aload_0 > ? ? ? ?1: iconst_0 > ? ? ? ?2: anewarray? ? ?#2? ? ? ? ? ? ? ? ? // class java/lang/String > ? ? ? ?5: invokestatic? #3? ? ? ? ? ? ? ? ? // Method > java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path; > ? ? ? ?8: iconst_0 > ? ? ? ?9: anewarray? ? ?#4? ? ? ? ? ? ? ? ? // class > java/nio/file/OpenOption > ? ? ? 12: invokestatic? #5? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.open:(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/FileChannel; > ? ? ? 15: astore_1 > ? ? ? 16: aload_1 > ? ? ? 17: invokevirtual #6? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.size:()J > ? ? ? 20: pop2 > ? ? ? 21: aload_1 > ? ? ? 22: ifnull? ? ? ? 52 > ? ? ? 25: aload_1 > ? ? ? 26: invokevirtual #7? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.close:()V > ? ? ? 29: goto? ? ? ? ? 52 > ? ? ? 32: astore_2 > ? ? ? 33: aload_1 > ? ? ? 34: ifnull? ? ? ? 50 > ? ? ? 37: aload_1 > ? ? ? 38: invokevirtual #7? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.close:()V > ? ? ? 41: goto? ? ? ? ? 50 > ? ? ? 44: astore_3 > ? ? ? 45: aload_2 > ? ? ? 46: aload_3 > ? ? ? 47: invokevirtual #9? ? ? ? ? ? ? ? ? // Method > java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V > ? ? ? 50: aload_2 > ? ? ? 51: athrow > ? ? ? 52: return > ? ? Exception table: > ? ? ? ?from? ? to? target type > ? ? ? ? ? 16? ? 21? ? 32? ?Class java/lang/Throwable > ? ? ? ? ? 37? ? 41? ? 44? ?Class java/lang/Throwable > > Thanks, > Ismael > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Fri Nov 9 21:49:08 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 9 Nov 2018 13:49:08 -0800 Subject: spotBugs and JDK-8194978: Javac produces dead code for try-with-resource In-Reply-To: References: Message-ID: <711f8524-5ed6-1876-9a22-7ae046b117be@oracle.com> Ismael, What about the case where the initialization of the variable unexpectedly returns null? Yes, you'll get an NPE when you invoke a method, but the finally block will still get executed (JLS11 14.20.2) The null check in the finally block protects against trying to call close on a variable whose value is null. -- Jon On 09/13/2018 10:05 PM, Ismael Juma wrote: > Hi all, > > JDK-8194978 introduced some changes to the bytecode generated by javac > for the try with resource construct. In the following code, it seems > to generate a null check on a reference after invoking a method on it: > > ? ? public static void readFileAsString(String path) throws IOException { > ? ? ? ? try (FileChannel fc = FileChannel.open(Paths.get(path))) { > ? ? ? ? ? ? fc.size(); > ? ? ? ? } > > ? ? } > > In line 16 to 22 of the bytecode, it looks like we check for null > after calling a method on the fc reference: > > ? ? ? 16: aload_1 > ? ? ? 17: invokevirtual #6? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.size:()J > ? ? ? 20: pop2 > ? ? ? 21: aload_1 > ? ? ? 22: ifnull? ? ? ? 52 > ? ? ? 25: aload_1 > ? ? ? 26: invokevirtual #7? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.close:()V > > Is this intentional? I ask because this pattern triggers a spotBugs > warning since it often implies a bug in user's code: > > RCN | Nullcheck of fc at line 10 of value previously dereferenced in > TryTest.readFileAsString(String, Charset) > > Note that this works fine in Java versions older than Java 11. Since > this spotBugs warning is generally useful, it would be handy if javac > did not trigger it. Alternatively, if there's a good way to detect > the?code that was generated by javac, spotBugs could be updated to > ignore it. For reference, this was discussed in the spotBugs issue > tracker: > > https://github.com/spotbugs/spotbugs/issues/756 > > And method bytecode in full: > > ? public static void readFileAsString(java.lang.String) throws > java.io.IOException; > ? ? Code: > ? ? ? ?0: aload_0 > ? ? ? ?1: iconst_0 > ? ? ? ?2: anewarray? ? ?#2? ? ? ? ? ? ? ? ? // class java/lang/String > ? ? ? ?5: invokestatic? #3? ? ? ? ? ? ? ? ? // Method > java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path; > ? ? ? ?8: iconst_0 > ? ? ? ?9: anewarray? ? ?#4? ? ? ? ? ? ? ? ? // class > java/nio/file/OpenOption > ? ? ? 12: invokestatic? #5? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.open:(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/FileChannel; > ? ? ? 15: astore_1 > ? ? ? 16: aload_1 > ? ? ? 17: invokevirtual #6? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.size:()J > ? ? ? 20: pop2 > ? ? ? 21: aload_1 > ? ? ? 22: ifnull? ? ? ? 52 > ? ? ? 25: aload_1 > ? ? ? 26: invokevirtual #7? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.close:()V > ? ? ? 29: goto? ? ? ? ? 52 > ? ? ? 32: astore_2 > ? ? ? 33: aload_1 > ? ? ? 34: ifnull? ? ? ? 50 > ? ? ? 37: aload_1 > ? ? ? 38: invokevirtual #7? ? ? ? ? ? ? ? ? // Method > java/nio/channels/FileChannel.close:()V > ? ? ? 41: goto? ? ? ? ? 50 > ? ? ? 44: astore_3 > ? ? ? 45: aload_2 > ? ? ? 46: aload_3 > ? ? ? 47: invokevirtual #9? ? ? ? ? ? ? ? ? // Method > java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V > ? ? ? 50: aload_2 > ? ? ? 51: athrow > ? ? ? 52: return > ? ? Exception table: > ? ? ? ?from? ? to? target type > ? ? ? ? ? 16? ? 21? ? 32? ?Class java/lang/Throwable > ? ? ? ? ? 37? ? 41? ? 44? ?Class java/lang/Throwable > > Thanks, > Ismael From alex.buckley at oracle.com Fri Nov 9 21:59:02 2018 From: alex.buckley at oracle.com (Alex Buckley) Date: Fri, 09 Nov 2018 13:59:02 -0800 Subject: spotBugs and JDK-8194978: Javac produces dead code for try-with-resource In-Reply-To: <25e5d853-e4d4-41aa-8221-00462389fc67@oracle.com> References: <25e5d853-e4d4-41aa-8221-00462389fc67@oracle.com> Message-ID: <5BE60326.4090202@oracle.com> On 11/9/2018 12:31 PM, Vicente Romero wrote: > My evaluation on this issue is that javac is generating code > according to the spec, see JLS11 14.20.3.1 [1]. There is an explicit > check for null on the resource before invoking the close() method. > This is the null check javac is generating. I confirm that the explicit null check on the resource variable is required, per the translation in https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.20.3.1-140 -- it has been specified that way since JLS7. > Fix for JDK-8194978 went a bit further trying to eliminate dead code > for some cases for which javac could statically determine that the > resource would be different from null. In particular if the resource > was initialized with a new class expression. I confirm it's acceptable to not perform the null check in generated code if you can prove the resource variable is non-null. Frankly, though, there is so much that can occur in a "new class expression" -- `new Outer(a(b(c)))<>.new Inner(d(e(f)))` -- that I would be wary of trying to prove anything. > It could be argued that we could try to analyze the body and if we > find out that a NPE must be thrown in the body of the try, then the > null check on the resource would be deemed unnecessary. But then we > can get to an implementation that will be out of sync with the spec > plus it probably won't cover all cases. Right, let's not be too clever. Alex > Thanks, > Vicente > > [1] > https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.20.3.1 > > On 11/9/18 10:22 AM, Ismael Juma wrote: >> Any comments on this? Many people are disabling spotBugs when >> compiling with Java 11 due to this issue: >> >> https://github.com/spotbugs/spotbugs/issues/756 >> >> Ismael >> >> On Thu, Sep 13, 2018 at 10:05 PM Ismael Juma > > wrote: >> >> Hi all, >> >> JDK-8194978 introduced some changes to the bytecode generated by >> javac for the try with resource construct. In the following code, >> it seems to generate a null check on a reference after invoking a >> method on it: >> >> public static void readFileAsString(String path) throws >> IOException { >> try (FileChannel fc = FileChannel.open(Paths.get(path))) { >> fc.size(); >> } >> >> } >> >> In line 16 to 22 of the bytecode, it looks like we check for null >> after calling a method on the fc reference: >> >> 16: aload_1 >> 17: invokevirtual #6 // Method >> java/nio/channels/FileChannel.size:()J >> 20: pop2 >> 21: aload_1 >> 22: ifnull 52 >> 25: aload_1 >> 26: invokevirtual #7 // Method >> java/nio/channels/FileChannel.close:()V >> >> Is this intentional? I ask because this pattern triggers a >> spotBugs warning since it often implies a bug in user's code: >> >> RCN | Nullcheck of fc at line 10 of value previously dereferenced >> in TryTest.readFileAsString(String, Charset) >> >> Note that this works fine in Java versions older than Java 11. >> Since this spotBugs warning is generally useful, it would be handy >> if javac did not trigger it. Alternatively, if there's a good way >> to detect the code that was generated by javac, spotBugs could be >> updated to ignore it. For reference, this was discussed in the >> spotBugs issue tracker: >> >> https://github.com/spotbugs/spotbugs/issues/756 >> >> And method bytecode in full: >> >> public static void readFileAsString(java.lang.String) throws >> java.io.IOException; >> Code: >> 0: aload_0 >> 1: iconst_0 >> 2: anewarray #2 // class java/lang/String >> 5: invokestatic #3 // Method >> java/nio/file/Paths.get:(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path; >> 8: iconst_0 >> 9: anewarray #4 // class >> java/nio/file/OpenOption >> 12: invokestatic #5 // Method >> java/nio/channels/FileChannel.open:(Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/nio/channels/FileChannel; >> 15: astore_1 >> 16: aload_1 >> 17: invokevirtual #6 // Method >> java/nio/channels/FileChannel.size:()J >> 20: pop2 >> 21: aload_1 >> 22: ifnull 52 >> 25: aload_1 >> 26: invokevirtual #7 // Method >> java/nio/channels/FileChannel.close:()V >> 29: goto 52 >> 32: astore_2 >> 33: aload_1 >> 34: ifnull 50 >> 37: aload_1 >> 38: invokevirtual #7 // Method >> java/nio/channels/FileChannel.close:()V >> 41: goto 50 >> 44: astore_3 >> 45: aload_2 >> 46: aload_3 >> 47: invokevirtual #9 // Method >> java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V >> 50: aload_2 >> 51: athrow >> 52: return >> Exception table: >> from to target type >> 16 21 32 Class java/lang/Throwable >> 37 41 44 Class java/lang/Throwable >> >> Thanks, >> Ismael >> > From dmitry.batkovich at jetbrains.com Mon Nov 12 15:10:57 2018 From: dmitry.batkovich at jetbrains.com (Dmitry Batkovich) Date: Mon, 12 Nov 2018 18:10:57 +0300 Subject: Strange behaviour in DeferredCompletionFailureHandler Message-ID: Hi all, I've faced with javac 11 performance problem in DeferredCompletionFailureHandler. I have a project with google dagger dependency injection and with some javac task listener (You may see https://youtrack.jetbrains.com/issue/IDEA-201978). In this case I see lots FlipSymbolDescription#flip() traces in compiler profile snapshot. I've tried to investigate the problem by myself and found next things: 1) Map com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip produces memory leaks because keys of the map are present as a part of value object. So, keys are always strongly referenced. And usage of WeakHashMap is useless here. 2) com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip does nothing. Any information inside FlipSymbolDescription is never used (DefferedCompleter is never used). 3) Handler.install/uninstall method usages (see setHandler() usages in MultiTaskListener) produces lots of odd cycles where we have only field reassignment. Sure we need at least one TaskListener here. So, I've found that fix for https://bugs.openjdk.java.net/browse/JDK-8187950 is very dirty in point view of compiler performance. And I don't understand what's the purpose of class2Flip map introduction. Could you clarify, help me, please? Cheers, Dmitrii Batkovich -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Mon Nov 12 15:57:22 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Mon, 12 Nov 2018 16:57:22 +0100 Subject: Strange behaviour in DeferredCompletionFailureHandler In-Reply-To: References: Message-ID: <5BE9A2E2.6070005@oracle.com> Hi Dmitry, The overall goal is to avoid CompletionFailures to be thrown to the user code. This requires to "spit" a Symbol into user code version and an javac internal version and to use the user-code version while in user code, and javac internal version while in javac. (Because javac needs the CompletionFailures for correctness.) There was an issue that even "hypothetical" Symbol were kept in the maps, which should be fixed now. Please see: https://bugs.openjdk.java.net/browse/JDK-8209055 Please let me know how it works in your usecase. Thanks, Jan On 12.11.2018 16:10, Dmitry Batkovich wrote: > Hi all, > > I've faced with javac 11 performance problem > in DeferredCompletionFailureHandler. I have a project with google dagger > dependency injection and with some javac task listener (You may see > https://youtrack.jetbrains.com/issue/IDEA-201978). In this case I see > lots FlipSymbolDescription#flip() traces in compiler profile snapshot. > I've tried to investigate the problem by myself and found next things: > > 1) > Map com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > produces memory leaks because keys of the map are present as a part of > value object. So, keys are always strongly referenced. And usage of > WeakHashMap is useless here. > > 2) com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > does nothing. Any information inside FlipSymbolDescription is never used > (DefferedCompleter is never used). > > 3) Handler.install/uninstall method usages (see setHandler() usages in > MultiTaskListener) produces lots of odd cycles where we have only field > reassignment. Sure we need at least one TaskListener here. > > So, I've found that fix for > https://bugs.openjdk.java.net/browse/JDK-8187950 is very dirty in point > view of compiler performance. And I don't understand what's the purpose > of class2Flip map introduction. Could you clarify, help me, please? > > Cheers, > Dmitrii Batkovich From dmitry.batkovich at jetbrains.com Tue Nov 13 09:29:35 2018 From: dmitry.batkovich at jetbrains.com (Dmitry Batkovich) Date: Tue, 13 Nov 2018 12:29:35 +0300 Subject: Strange behaviour in DeferredCompletionFailureHandler In-Reply-To: <5BE9A2E2.6070005@oracle.com> References: <5BE9A2E2.6070005@oracle.com> Message-ID: ok, but what's about WeakHashMap? I've lots of stale keys which should be collected but they are not because they had strong references in values. On Mon, Nov 12, 2018 at 6:57 PM Jan Lahoda wrote: > Hi Dmitry, > > The overall goal is to avoid CompletionFailures to be thrown to the user > code. This requires to "spit" a Symbol into user code version and an > javac internal version and to use the user-code version while in user > code, and javac internal version while in javac. (Because javac needs > the CompletionFailures for correctness.) > > There was an issue that even "hypothetical" Symbol were kept in the > maps, which should be fixed now. Please see: > https://bugs.openjdk.java.net/browse/JDK-8209055 > > Please let me know how it works in your usecase. > > Thanks, > Jan > > On 12.11.2018 16:10, Dmitry Batkovich wrote: > > Hi all, > > > > I've faced with javac 11 performance problem > > in DeferredCompletionFailureHandler. I have a project with google dagger > > dependency injection and with some javac task listener (You may see > > https://youtrack.jetbrains.com/issue/IDEA-201978). In this case I see > > lots FlipSymbolDescription#flip() traces in compiler profile snapshot. > > I've tried to investigate the problem by myself and found next things: > > > > 1) > > Map > com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > > produces memory leaks because keys of the map are present as a part of > > value object. So, keys are always strongly referenced. And usage of > > WeakHashMap is useless here. > > > > 2) > com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > > does nothing. Any information inside FlipSymbolDescription is never used > > (DefferedCompleter is never used). > > > > 3) Handler.install/uninstall method usages (see setHandler() usages in > > MultiTaskListener) produces lots of odd cycles where we have only field > > reassignment. Sure we need at least one TaskListener here. > > > > So, I've found that fix for > > https://bugs.openjdk.java.net/browse/JDK-8187950 is very dirty in point > > view of compiler performance. And I don't understand what's the purpose > > of class2Flip map introduction. Could you clarify, help me, please? > > > > Cheers, > > Dmitrii Batkovich > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Tue Nov 13 09:44:41 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 13 Nov 2018 10:44:41 +0100 Subject: Strange behaviour in DeferredCompletionFailureHandler In-Reply-To: References: <5BE9A2E2.6070005@oracle.com> Message-ID: <5BEA9D09.5070204@oracle.com> On 13.11.2018 10:29, Dmitry Batkovich wrote: > ok, but what's about WeakHashMap? I've lots of stale keys which should > be collected but they are not because they had strong references in values. There is no WeakHashMap after JDK-8209055. The idea is that "real" ClassSymbols are permanent anyway (held from Symtab) and "hypothetical" ClassSymbols are removed from the DeferredCompletionFailureHandler when they are removed from the Symtab. Does the patch fix your usecase? Thanks, Jan > > On Mon, Nov 12, 2018 at 6:57 PM Jan Lahoda > wrote: > > Hi Dmitry, > > The overall goal is to avoid CompletionFailures to be thrown to the > user > code. This requires to "spit" a Symbol into user code version and an > javac internal version and to use the user-code version while in user > code, and javac internal version while in javac. (Because javac needs > the CompletionFailures for correctness.) > > There was an issue that even "hypothetical" Symbol were kept in the > maps, which should be fixed now. Please see: > https://bugs.openjdk.java.net/browse/JDK-8209055 > > Please let me know how it works in your usecase. > > Thanks, > Jan > > On 12.11.2018 16:10, Dmitry Batkovich wrote: > > Hi all, > > > > I've faced with javac 11 performance problem > > in DeferredCompletionFailureHandler. I have a project with google > dagger > > dependency injection and with some javac task listener (You may see > > https://youtrack.jetbrains.com/issue/IDEA-201978). In this case I see > > lots FlipSymbolDescription#flip() traces in compiler profile > snapshot. > > I've tried to investigate the problem by myself and found next > things: > > > > 1) > > Map > com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > > produces memory leaks because keys of the map are present as a > part of > > value object. So, keys are always strongly referenced. And usage of > > WeakHashMap is useless here. > > > > 2) > com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > > does nothing. Any information inside FlipSymbolDescription is > never used > > (DefferedCompleter is never used). > > > > 3) Handler.install/uninstall method usages (see setHandler() > usages in > > MultiTaskListener) produces lots of odd cycles where we have only > field > > reassignment. Sure we need at least one TaskListener here. > > > > So, I've found that fix for > > https://bugs.openjdk.java.net/browse/JDK-8187950 is very dirty in > point > > view of compiler performance. And I don't understand what's the > purpose > > of class2Flip map introduction. Could you clarify, help me, please? > > > > Cheers, > > Dmitrii Batkovich > From dmitry.batkovich at jetbrains.com Tue Nov 13 10:28:48 2018 From: dmitry.batkovich at jetbrains.com (Dmitry Batkovich) Date: Tue, 13 Nov 2018 13:28:48 +0300 Subject: Strange behaviour in DeferredCompletionFailureHandler In-Reply-To: <5BEA9D09.5070204@oracle.com> References: <5BE9A2E2.6070005@oracle.com> <5BEA9D09.5070204@oracle.com> Message-ID: Thank you, the patch from JDK-8209055 fixes my case. Could you please backport it to JDK 11? On Tue, Nov 13, 2018 at 12:44 PM Jan Lahoda wrote: > On 13.11.2018 10:29, Dmitry Batkovich wrote: > > ok, but what's about WeakHashMap? I've lots of stale keys which should > > be collected but they are not because they had strong references in > values. > > There is no WeakHashMap after JDK-8209055. The idea is that "real" > ClassSymbols are permanent anyway (held from Symtab) and "hypothetical" > ClassSymbols are removed from the DeferredCompletionFailureHandler when > they are removed from the Symtab. > > Does the patch fix your usecase? > > Thanks, > Jan > > > > > On Mon, Nov 12, 2018 at 6:57 PM Jan Lahoda > > wrote: > > > > Hi Dmitry, > > > > The overall goal is to avoid CompletionFailures to be thrown to the > > user > > code. This requires to "spit" a Symbol into user code version and an > > javac internal version and to use the user-code version while in user > > code, and javac internal version while in javac. (Because javac needs > > the CompletionFailures for correctness.) > > > > There was an issue that even "hypothetical" Symbol were kept in the > > maps, which should be fixed now. Please see: > > https://bugs.openjdk.java.net/browse/JDK-8209055 > > > > Please let me know how it works in your usecase. > > > > Thanks, > > Jan > > > > On 12.11.2018 16:10, Dmitry Batkovich wrote: > > > Hi all, > > > > > > I've faced with javac 11 performance problem > > > in DeferredCompletionFailureHandler. I have a project with google > > dagger > > > dependency injection and with some javac task listener (You may > see > > > https://youtrack.jetbrains.com/issue/IDEA-201978). In this case > I see > > > lots FlipSymbolDescription#flip() traces in compiler profile > > snapshot. > > > I've tried to investigate the problem by myself and found next > > things: > > > > > > 1) > > > Map > > > com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > > > produces memory leaks because keys of the map are present as a > > part of > > > value object. So, keys are always strongly referenced. And usage > of > > > WeakHashMap is useless here. > > > > > > 2) > > > com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler#class2Flip > > > does nothing. Any information inside FlipSymbolDescription is > > never used > > > (DefferedCompleter is never used). > > > > > > 3) Handler.install/uninstall method usages (see setHandler() > > usages in > > > MultiTaskListener) produces lots of odd cycles where we have only > > field > > > reassignment. Sure we need at least one TaskListener here. > > > > > > So, I've found that fix for > > > https://bugs.openjdk.java.net/browse/JDK-8187950 is very dirty in > > point > > > view of compiler performance. And I don't understand what's the > > purpose > > > of class2Flip map introduction. Could you clarify, help me, > please? > > > > > > Cheers, > > > Dmitrii Batkovich > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From fey at apiomat.com Mon Nov 12 07:13:57 2018 From: fey at apiomat.com (Andreas Fey) Date: Mon, 12 Nov 2018 07:13:57 +0000 Subject: Possible open file leak in com.sun.tools.javac.file.JavacFileManager Message-ID: Jon, is there an Andreas, > > We'll take a look. > > -- Jon > > > On 11/5/18 6:24 AM, Andreas Fey wrote: > Hi all, > > we maybe found a bug in the com.sun.tools.javac.file.JavacFileManager; > our tool makes heavy use of compiling classes during runtime, and > after switching from JDK 8 to 11, we noticed hundreds of open files > being created during list() and only closed when JVM exists. The > concerning lines of code are: > > @Override @DefinedBy(Api.COMPILER) > public Iterable list(Location location, > String packageName, > Set kinds, > boolean recurse) > throws IOException > { > checkNotModuleOrientedLocation(location); > // validatePackageName(packageName); > nullCheck(packageName); > nullCheck(kinds); > > Iterable path = getLocationAsPaths(location); > if (path == null) > return List.nil(); > RelativeDirectory subdirectory = > RelativeDirectory.forPackage(packageName); > ListBuffer results = new ListBuffer<>(); > > for (Path directory : path) { > Container container = getContainer(directory); > > container.list(directory, subdirectory, kinds, recurse, > results); > } > > return results.toList(); > } > > We think, a container.close() is missing in the for loop. Without > this, a filehandle is created for every container/directiry found > here. To test this, the following code snipped can be used, but the > location must be set property to find a valid path != null: > > @Test > public void testFileManager( ) throws IOException > { > countOpenFiles( ); > > final Set kinds = new HashSet<>( ); > kinds.add( javax.tools.JavaFileObject.Kind.OTHER ); > kinds.add( javax.tools.JavaFileObject.Kind.SOURCE ); > kinds.add( javax.tools.JavaFileObject.Kind.CLASS ); > kinds.add( javax.tools.JavaFileObject.Kind.HTML ); > > final StandardJavaFileManager sfm = > ToolProvider.getSystemJavaCompiler( ).getStandardFileManager( null, > null, null ); > sfm.list( new JavaFileManager.Location( ) > { > @Override > public boolean isOutputLocation( ) > { > return false; > } > > @Override > public String getName( ) > { > return "CLASS_NAME"; > } > }, "com", kinds, true ); > > countOpenFiles( ); > } > > private void countOpenFiles( ) > { > final String processName = > java.lang.management.ManagementFactory.getRuntimeMXBean( ).getName( ); > final long pid = Long.parseLong( processName.split( "@" )[ 0 ] ); > try > { > final Runtime rt = Runtime.getRuntime( ); > final Process pr = rt.exec( "lsof -p " + pid ); > > int ctr = 0; > final BufferedReader br = new BufferedReader( > new InputStreamReader( pr.getInputStream( ) ) ); > while ( ( br.readLine( ) ) != null ) > ctr++; > pr.waitFor( ); > pr.destroy( ); > > System.out.println( "Open files: " + ctr ); > } > catch ( final Exception e ) > { > e.printStackTrace( ); > } > } > > Can anybody confirm this? > Best, > Andreas -------------- next part -------------- An HTML attachment was scrubbed... URL: From rkennke at redhat.com Mon Nov 5 21:24:12 2018 From: rkennke at redhat.com (Roman Kennke) Date: Mon, 5 Nov 2018 22:24:12 +0100 Subject: Bit set intrinsic In-Reply-To: References: <9891ee55-7114-5b71-7a90-0c4e97deda2a@redhat.com> <05e00e85-046a-cdcb-7323-9e40f8a8fc86@redhat.com> <62d7984a-78dc-82a4-15aa-6deeebf95342@redhat.com> Message-ID: Just want to say that I like this effort. Please go ahead and create an issue and send it out for review. Roman > On Wed, 31 Oct 2018 at 15:51, B. Blaser wrote: >> >> The last but not least, I implemented the c2 part (using the 8-bit >> AND/OR variant) to do sharper comparisons also on non-concurrent >> execution: >> >> http://cr.openjdk.java.net/~bsrbnd/boolpack/webrev.02/ >> >> With 10e6 iterations the lock latency seems to be more or less >> negligible and removing it would make the intrinsic about 10% faster >> than BitSet without synchronization. > > Which actually seems to be due to the following missing ANDB/ORB > patterns in x86_64.ad: > > instruct andB_mem_rReg(memory dst, rRegI src, rFlagsReg cr) > %{ > match(Set dst (StoreB dst (AndI (LoadB dst) src))); > effect(KILL cr); > > ins_cost(150); > format %{ "andb $dst, $src\t# byte" %} > opcode(0x20); > ins_encode(REX_breg_mem(src, dst), OpcP, reg_mem(src, dst)); > ins_pipe(ialu_mem_reg); > %} > > instruct orB_mem_rReg(memory dst, rRegI src, rFlagsReg cr) > %{ > match(Set dst (StoreB dst (OrI (LoadB dst) src))); > effect(KILL cr); > > ins_cost(150); > format %{ "orb $dst, $src\t# byte" %} > opcode(0x08); > ins_encode(REX_breg_mem(src, dst), OpcP, reg_mem(src, dst)); > ins_pipe(ialu_mem_reg); > %} > > The next two lines: > 1) bits[index>>>3] |= (byte)(1 << (index & 7)); > 2) bits[index>>>3] &= (byte)~(1 << (index & 7)); > > where assembled as: > 1) > 024 movsbl R8, [RSI + #16 + R10] # byte > 02a movl R11, #1 # int > 030 sall R11, RCX > 033 movsbl R11, R11 # i2b > 037 orl R11, R8 # int > 03a movb [RSI + #16 + R10], R11 # byte > 2) > 024 movsbl R8, [RSI + #16 + R10] # byte > 02a movl R11, #1 # int > 030 sall R11, RCX > 033 not R11 > 036 movsbl R11, R11 # i2b > 03a andl R8, R11 # int > 03d movb [RSI + #16 + R10], R8 # byte > > instead of: > 1) > 024 movl R11, #1 # int > 02a sall R11, RCX > 02d movsbl R11, R11 # i2b > 031 orb [RSI + #16 + R10], R11 # byte > 2) > 024 movl R11, #1 # int > 02a sall R11, RCX > 02d not R11 > 030 movsbl R11, R11 # i2b > 034 andb [RSI + #16 + R10], R11 # byte > > So, as first step, I would probably create a JBS issue and send out a > RFR on hotspot-dev for this simple enhancement if there are no > objections? > > Any opinion is welcome. > > Thanks, > Bernard > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: OpenPGP digital signature URL: From erik.joelsson at oracle.com Tue Nov 13 21:08:08 2018 From: erik.joelsson at oracle.com (Erik Joelsson) Date: Tue, 13 Nov 2018 13:08:08 -0800 Subject: RFR: JDK-8213709: jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java missing modules declaration Message-ID: <96de00ac-36f7-3fef-cb17-375a3903e9f7@oracle.com> Please review this simple fix for the test jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java which adds modules declarations necessary to properly compile the @library declarations. Bug: https://bugs.openjdk.java.net/browse/JDK-8213709 Webrev: http://cr.openjdk.java.net/~erikj/8213709/webrev.01/ /Erik From jonathan.gibbons at oracle.com Tue Nov 13 21:18:44 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 13 Nov 2018 13:18:44 -0800 Subject: Possible open file leak in com.sun.tools.javac.file.JavacFileManager In-Reply-To: <92415a9981670e5a653c9d5155d6dee4fa0cfaff.camel@apiomat.com> References: <92415a9981670e5a653c9d5155d6dee4fa0cfaff.camel@apiomat.com> Message-ID: Andreas, I investigated this using your test code, changing the location to use a search path given on the command line. I see the effect are describing when the search path contains JAR files. There does not seem to be an issue when listing directories or system files. You are right in that there is a missing 'close()', but I don't think it is in the list() method, as you suggested.? You don't give any significant amount of detail about the environment in which you are seeing this, although you do say "heavy use of compiling classes during runtime". That suggests to me that you are using the javax.tools API to run the compiler (as compared to command-line javac), which suggests that you may be setting up a file manager, as in your code example. If that is the case, a likely cause of your problems is that you are not closing any file managers created and used in your application.? When I modified my version of your code sample to close the file manager and run countOpenFiles() again, the number of open files reverted to the number at the beginning of the test. You also note the change in behavior between JDK 8 and JDK 11. In JDK 9, javac was changed to use the new NIO-based APIs (java.nio.file.*) instead of the old File-based APIs (java.io.*). As part of this work, JAR files are now opened as NIO filesystems, and for performance reasons, they are held open until the file manager itself is closed. (Previously, javac had a custom implementation for handling ZIP files which did not rely on holding the JAR file open, meaning that you could get away with not bothering to close the file manager.) So, you might try checking your code to ensure you are either reusing file managers, or else closing them when they are no longer required. -- Jon On 11/05/2018 06:24 AM, Andreas Fey wrote: > Hi all, > > we maybe found a bug in the com.sun.tools.javac.file.JavacFileManager; > our tool makes heavy use of compiling classes during runtime, and > after switching from JDK 8 to 11, we noticed hundreds of open files > being created during list() and only closed when JVM exists. The > concerning lines of code are: > > ?@Override @DefinedBy(Api.COMPILER) > ????public Iterable list(Location location, > ?????????????????????????????????????????String packageName, > ?????????????????????????????????????????Set kinds, > ?????????????????????????????????????????boolean recurse) > ????????throws IOException > ????{ > ????????checkNotModuleOrientedLocation(location); > ????????// validatePackageName(packageName); > ????????nullCheck(packageName); > ????????nullCheck(kinds); > > ????????Iterable path = getLocationAsPaths(location); > ????????if (path == null) > ????????????return List.nil(); > ????????RelativeDirectory subdirectory = > RelativeDirectory.forPackage(packageName); > ????????ListBuffer results = new ListBuffer<>(); > > ????????for (Path directory : path) { > ????????????Container container = getContainer(directory); > > ????????????container.list(directory, subdirectory, kinds, recurse, > results); > ????????} > > ????????return results.toList(); > ????} > > We think, a container.close() is missing in the for loop. Without > this, a filehandle is created for every container/directiry found > here. To test this, the following code snipped can be used, but the > location must be set property to find a valid path != null: > > @Test > public void testFileManager( ) throws IOException > { > countOpenFiles( ); > > final Set kinds = new HashSet<>( ); > kinds.add( javax.tools.JavaFileObject.Kind.OTHER ); > kinds.add( javax.tools.JavaFileObject.Kind.SOURCE ); > kinds.add( javax.tools.JavaFileObject.Kind.CLASS ); > kinds.add( javax.tools.JavaFileObject.Kind.HTML ); > > final StandardJavaFileManager sfm = > ToolProvider.getSystemJavaCompiler( ).getStandardFileManager( null, > null, null ); > sfm.list( new JavaFileManager.Location( ) > { > @Override > public boolean isOutputLocation( ) > { > return false; > } > > @Override > public String getName( ) > { > return "CLASS_NAME"; > } > }, "com", kinds, true ); > > countOpenFiles( ); > } > > private void countOpenFiles( ) > { > final String processName = > java.lang.management.ManagementFactory.getRuntimeMXBean( ).getName( ); > final long pid = Long.parseLong( processName.split( "@" )[ 0 ] ); > try > { > final Runtime rt = Runtime.getRuntime( ); > final Process pr = rt.exec( "lsof -p " + pid ); > > int ctr = 0; > final BufferedReader br = new BufferedReader( > new InputStreamReader( pr.getInputStream( ) ) ); > while ( ( br.readLine( ) ) != null ) > ctr++; > pr.waitFor( ); > pr.destroy( ); > > System.out.println( "Open files: " + ctr ); > } > catch ( final Exception e ) > { > e.printStackTrace( ); > } > } > > Can anybody confirm this? > Best, > Andreas From jonathan.gibbons at oracle.com Tue Nov 13 22:35:16 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 13 Nov 2018 14:35:16 -0800 Subject: RFR: JDK-8213709: jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java missing modules declaration In-Reply-To: <96de00ac-36f7-3fef-cb17-375a3903e9f7@oracle.com> References: <96de00ac-36f7-3fef-cb17-375a3903e9f7@oracle.com> Message-ID: <5320d2bd-881c-614e-c7b0-48a8a841f5ea@oracle.com> javadoc-dev (cc:-ed) is a more appropriate list. But yes; thanks for fixing. -- Jon On 11/13/2018 01:08 PM, Erik Joelsson wrote: > Please review this simple fix for the test > jdk/javadoc/doclet/testValueTag/TestValueTagInModule.java which adds > modules declarations necessary to properly compile the @library > declarations. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8213709 > > Webrev: http://cr.openjdk.java.net/~erikj/8213709/webrev.01/ > > /Erik > From srinivas.dama at oracle.com Thu Nov 15 09:31:19 2018 From: srinivas.dama at oracle.com (srinivas) Date: Thu, 15 Nov 2018 15:01:19 +0530 Subject: RFR: 8210742: Compound var declaration splitting seems broken Message-ID: <2eae8c99-9fea-a9e8-c432-97f507d1695c@oracle.com> Hi, Please review http://cr.openjdk.java.net/~sdama/8210742/webrev.00/ for https://bugs.openjdk.java.net/browse/JDK-8210742. Regards, Srinivas From maurizio.cimadamore at oracle.com Thu Nov 15 11:43:40 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 15 Nov 2018 12:43:40 +0100 Subject: RFR: 8210742: Compound var declaration splitting seems broken In-Reply-To: <2eae8c99-9fea-a9e8-c432-97f507d1695c@oracle.com> References: <2eae8c99-9fea-a9e8-c432-97f507d1695c@oracle.com> Message-ID: <964bc1c0-0d5d-d540-c489-91e8c97ef716@oracle.com> Hi, I think what you are doing is ok, but I have some comments: 1) it seems like this code: startPos = TreeInfo.getStartPos(mods); if (startPos == Position.NOPOS) ?? startPos = TreeInfo.getStartPos(type); should probably be lifted outside the 'if' - e.g. should apply to all cases after the check for "isRestrictedLocalVarTypeName" 2) A similar argument applies, kind of, to setting type to 'null'. With your patch we do that in 2/3 branches; the branch that is left out is when you have a var declaration like this: var foo[] = ... In this case the parser will still attempt to create a var tree with 'var' as its type. If we are worried about how the AST would look in erroneous cases, then I think this is a problem too. Cheers Maurizio On 15/11/2018 10:31, srinivas wrote: > Hi, > > Please review http://cr.openjdk.java.net/~sdama/8210742/webrev.00/ > > for https://bugs.openjdk.java.net/browse/JDK-8210742. > > Regards, > > Srinivas -------------- next part -------------- An HTML attachment was scrubbed... URL: From srinivas.dama at oracle.com Thu Nov 15 14:22:55 2018 From: srinivas.dama at oracle.com (srinivas) Date: Thu, 15 Nov 2018 19:52:55 +0530 Subject: RFR: 8210742: Compound var declaration splitting seems broken In-Reply-To: <964bc1c0-0d5d-d540-c489-91e8c97ef716@oracle.com> References: <2eae8c99-9fea-a9e8-c432-97f507d1695c@oracle.com> <964bc1c0-0d5d-d540-c489-91e8c97ef716@oracle.com> Message-ID: Hi Maurizio, Thanks for the review. Yes - Initially I thought of making this code common to all branches. Below are the reasons for not doing that. 1) the reported issue from NB team is for simple 'var x' types but not for arrays. 2) I don't have enough data to preserve the type for arrays or not and I want to avoid breaking any assumption related to arrays error cases both from NB team and javac tests. Please let me know if I should include array case as well and refactor the fix. Regards, Srinivas On 15/11/18 5:13 PM, Maurizio Cimadamore wrote: > > Hi, > I think what you are doing is ok, but I have some comments: > > 1) it seems like this code: > > > startPos = TreeInfo.getStartPos(mods); > if (startPos == Position.NOPOS) > ?? startPos = TreeInfo.getStartPos(type); > > should probably be lifted outside the 'if' - e.g. should apply to all > cases after the check for "isRestrictedLocalVarTypeName" > > 2) A similar argument applies, kind of, to setting type to 'null'. > With your patch we do that in 2/3 branches; the branch that is left > out is when you have a var declaration like this: > > var foo[] = ... > > In this case the parser will still attempt to create a var tree with > 'var' as its type. If we are worried about how the AST would look in > erroneous cases, then I think this is a problem too. > > Cheers > Maurizio > > On 15/11/2018 10:31, srinivas wrote: >> Hi, >> >> Please review http://cr.openjdk.java.net/~sdama/8210742/webrev.00/ >> >> for https://bugs.openjdk.java.net/browse/JDK-8210742. >> >> Regards, >> >> Srinivas -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Fri Nov 16 19:48:23 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 16 Nov 2018 20:48:23 +0100 Subject: RFR: 8210742: Compound var declaration splitting seems broken In-Reply-To: References: <2eae8c99-9fea-a9e8-c432-97f507d1695c@oracle.com> <964bc1c0-0d5d-d540-c489-91e8c97ef716@oracle.com> Message-ID: I understand. One thing that I don't 100% get is what is the set of requirements we need to preserve; in this case we have a parser error, meaning that the input source file is wrong according to the grammar; javac ends up creating a variable tree node anyway, and then this node gets eventually type-checked, and what we are talking about here is that, when this type-checking happens (on this tree that is the result of a javac error recovery step), we are observing a type checking difference from 10 to 11. Now, it seems like NB would like to have 'var' be applied in all branches of the compound assignment, and have all types be inferred. But, as you said, for a variable type such as 'var x[]' we can't do much, so we will report an error and we will, I think, create an AST of type 'var[]' which will be left untouched, I believe, by type-checking. So, I guess what I'm really asking for is some explanation of what the desired behavior should be, and why - so that we can make sure that, moving forward, we create the right kind of synthetic recovery trees in all cases. (of course none of this is an issue for javac which will shut down immediately after discovering a parser error w/o even attempting attribution). Maurizio On 15/11/2018 15:22, srinivas wrote: > > Hi Maurizio, > > Thanks for the review. > > Yes - Initially I thought of making this code common to all branches. > > Below are the reasons for not doing that. > > 1) the reported issue from NB team is for simple 'var x' types but not > for arrays. > > 2) I don't have enough data to preserve the type for arrays or not and > I want to avoid breaking any assumption related to arrays error cases > > both from NB team and javac tests. > > Please let me know if I should include array case as well and refactor > the fix. > > Regards, > > Srinivas > > > > On 15/11/18 5:13 PM, Maurizio Cimadamore wrote: >> >> Hi, >> I think what you are doing is ok, but I have some comments: >> >> 1) it seems like this code: >> >> >> startPos = TreeInfo.getStartPos(mods); >> if (startPos == Position.NOPOS) >> ?? startPos = TreeInfo.getStartPos(type); >> >> should probably be lifted outside the 'if' - e.g. should apply to all >> cases after the check for "isRestrictedLocalVarTypeName" >> >> 2) A similar argument applies, kind of, to setting type to 'null'. >> With your patch we do that in 2/3 branches; the branch that is left >> out is when you have a var declaration like this: >> >> var foo[] = ... >> >> In this case the parser will still attempt to create a var tree with >> 'var' as its type. If we are worried about how the AST would look in >> erroneous cases, then I think this is a problem too. >> >> Cheers >> Maurizio >> >> On 15/11/2018 10:31, srinivas wrote: >>> Hi, >>> >>> Please review http://cr.openjdk.java.net/~sdama/8210742/webrev.00/ >>> >>> for https://bugs.openjdk.java.net/browse/JDK-8210742. >>> >>> Regards, >>> >>> Srinivas -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Mon Nov 19 16:12:41 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Mon, 19 Nov 2018 17:12:41 +0100 Subject: RFR: JDK-8212006: javac --release 8 should allow -endorseddirs and -extdirs to be specified Message-ID: <5BF2E0F9.3020004@oracle.com> Hi, The issue here is that -endorseddirs (and -extdirs) is disallowed when --release 8 is specified. When there is a user-provided file manager, the option handling is more complicated, as currently, at the time we are processing the file manager options, it is not yet clear with --release is specified, and if -endorseddirs should be passed to the file manager that handles the platform classes for --release (or if --endorseddirs is even a valid option). So the idea is to do a pass through the options, looking for --release, install the --release file manager if needed, and then actually process the options, passing them to the appropriate file manager(s). Webrev: http://cr.openjdk.java.net/~jlahoda/8212006/webrev.00/ JBS: https://bugs.openjdk.java.net/browse/JDK-8212006 How does this look? Thanks, Jan From srinivas.dama at oracle.com Mon Nov 19 17:26:16 2018 From: srinivas.dama at oracle.com (srinivas) Date: Mon, 19 Nov 2018 22:56:16 +0530 Subject: RFR: 8210742: Compound var declaration splitting seems broken In-Reply-To: References: <2eae8c99-9fea-a9e8-c432-97f507d1695c@oracle.com> <964bc1c0-0d5d-d540-c489-91e8c97ef716@oracle.com> Message-ID: <5dd8d0ee-1454-5f6c-121b-fc6d8eae8ddd@oracle.com> Hi Maurizio, After checking with NB team about the expected behaviour for array types, below are the conclusions. 1. They provide some series hints for the error cases for the user. for ex: var v = {1,2}, w = 2;? will have hint as convert to var v={1,2}; var w=2; For this they will reconstruct the tree structure with inferred types from error messages . After having debugging session with them, I found the expected behavior of the tree structure from javac is same for both jdk10 and jdk11(for which they reported issue for var x; types earlier) So In summary: As discussed we don't need to alter array types behavior from javac. Please review revised patch with code refactored with error message order and array AST behaviour preserved. webrev: http://cr.openjdk.java.net/~sdama/8210742/webrev.01/ Bug: https://bugs.openjdk.java.net/browse/JDK-8210742 Regards, Srinivas On 17/11/18 1:18 AM, Maurizio Cimadamore wrote: > > I understand. > > One thing that I don't 100% get is what is the set of requirements we > need to preserve; in this case we have a parser error, meaning that > the input source file is wrong according to the grammar; javac ends up > creating a variable tree node anyway, and then this node gets > eventually type-checked, and what we are talking about here is that, > when this type-checking happens (on this tree that is the result of a > javac error recovery step), we are observing a type checking > difference from 10 to 11. > > Now, it seems like NB would like to have 'var' be applied in all > branches of the compound assignment, and have all types be inferred. > > But, as you said, for a variable type such as 'var x[]' we can't do > much, so we will report an error and we will, I think, create an AST > of type 'var[]' which will be left untouched, I believe, by type-checking. > > So, I guess what I'm really asking for is some explanation of what the > desired behavior should be, and why - so that we can make sure that, > moving forward, we create the right kind of synthetic recovery trees > in all cases. > > (of course none of this is an issue for javac which will shut down > immediately after discovering a parser error w/o even attempting > attribution). > > Maurizio > > On 15/11/2018 15:22, srinivas wrote: >> >> Hi Maurizio, >> >> Thanks for the review. >> >> Yes - Initially I thought of making this code common to all branches. >> >> Below are the reasons for not doing that. >> >> 1) the reported issue from NB team is for simple 'var x' types but >> not for arrays. >> >> 2) I don't have enough data to preserve the type for arrays or not >> and I want to avoid breaking any assumption related to arrays error cases >> >> both from NB team and javac tests. >> >> Please let me know if I should include array case as well and >> refactor the fix. >> >> Regards, >> >> Srinivas >> >> >> >> On 15/11/18 5:13 PM, Maurizio Cimadamore wrote: >>> >>> Hi, >>> I think what you are doing is ok, but I have some comments: >>> >>> 1) it seems like this code: >>> >>> >>> startPos = TreeInfo.getStartPos(mods); >>> if (startPos == Position.NOPOS) >>> ?? startPos = TreeInfo.getStartPos(type); >>> >>> should probably be lifted outside the 'if' - e.g. should apply to >>> all cases after the check for "isRestrictedLocalVarTypeName" >>> >>> 2) A similar argument applies, kind of, to setting type to 'null'. >>> With your patch we do that in 2/3 branches; the branch that is left >>> out is when you have a var declaration like this: >>> >>> var foo[] = ... >>> >>> In this case the parser will still attempt to create a var tree with >>> 'var' as its type. If we are worried about how the AST would look in >>> erroneous cases, then I think this is a problem too. >>> >>> Cheers >>> Maurizio >>> >>> On 15/11/2018 10:31, srinivas wrote: >>>> Hi, >>>> >>>> Please review http://cr.openjdk.java.net/~sdama/8210742/webrev.00/ >>>> >>>> for https://bugs.openjdk.java.net/browse/JDK-8210742. >>>> >>>> Regards, >>>> >>>> Srinivas -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Mon Nov 19 18:54:31 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 19 Nov 2018 10:54:31 -0800 Subject: RFR: 8214071: Broken msg.bug diagnostics when using the compiler API Message-ID: Hi, Please review this trivial fix for msg.bug diagnostics reported by the compiler API. webrev: http://cr.openjdk.java.net/~cushon/8214071/webrev.00/ bug: https://bugs.openjdk.java.net/browse/JDK-8214071 -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Mon Nov 19 18:55:26 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Mon, 19 Nov 2018 10:55:26 -0800 Subject: RFR: 8214071: Broken msg.bug diagnostics when using the compiler API In-Reply-To: References: Message-ID: <4e705dd0-d493-ea3a-20b4-90bda93fc3f6@oracle.com> +1 On 11/19/2018 10:54 AM, Liam Miller-Cushon wrote: > Hi, > > Please review this trivial fix for msg.bug diagnostics reported by the > compiler API. > > webrev: http://cr.openjdk.java.net/~cushon/8214071/webrev.00/ > > bug: https://bugs.openjdk.java.net/browse/JDK-8214071 -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Mon Nov 19 20:57:11 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Mon, 19 Nov 2018 15:57:11 -0500 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body In-Reply-To: References: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> <55121cfa-2b40-0f59-089c-cce57235eb91@oracle.com> Message-ID: <5a8f97e4-8eb2-d24e-8241-d6d57d36ff3d@oracle.com> Hi Maurizio, On 11/9/18 5:57 AM, Maurizio Cimadamore wrote: > > Looks good - can we cook up a test that is also stressing the other > new code path? > what about: http://cr.openjdk.java.net/~vromero/8203277/webrev.02/? > Maurizio > Thanks, Vicente > On 09/11/2018 00:12, Vicente Romero wrote: >> >> >> On 11/8/18 6:02 PM, Maurizio Cimadamore wrote: >>> >>> Hi, >>> I agree that preflow shouldn't care about nested constructs; but I >>> wonder - is diamond anon class the only case we need to worry about >>> here? What about a nested lambda expression? >>> >> >> right I agree with you, what about [3]? >> >>> Maurizio >>> >> Vicente >> >> [3] http://cr.openjdk.java.net/~vromero/8203277/webrev.01/ >>> >>> On 08/11/2018 00:24, Vicente Romero wrote: >>>> Please review the fix for [1] at [2]. The bug can be illustrated >>>> with this test case: >>>> >>>> import java.util.List; >>>> import java.util.function.Function; >>>> >>>> class DiamondInsideLambdaTest { >>>> ??? void build() { >>>> ??????? List> list = transform(null, >>>> ??????????????? builder -> new Function<>() { >>>> ??????????????????? public Double apply(String params) { return null; } >>>> ??????????????? }); >>>> ??? } >>>> >>>> ??? static List transform(List >>>> fromList, Function function) { >>>> return null; } >>>> } >>>> >>>> During lambda attribution, there is a preflow visitor that fill >>>> some holes, missing types / symbols, before doing an special flow >>>> analysis on the lambda. This flow analysis skip inner classes >>>> defined inside the lambda body. The preflow visitor is anyway >>>> visiting inner classes and filling, with garbage, some of the >>>> wholes. In most cases as the preflow step happens after the lambda >>>> body has been attributed, it should be a no-op. But if the lambda >>>> body contains a diamond as in this case, then it could be that the >>>> attribution can't be done previous to the preflow step. Simply >>>> because some types in the diamond could be waiting for type >>>> inference to come to a resolution. In that case preflow will modify >>>> the diamond expression and later on during completion, as some >>>> symbols and types are filled with erroneous types, they will keep >>>> that erroneous type. >>>> >>>> [1] https://bugs.openjdk.java.net/browse/JDK-8203277 >>>> [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Mon Nov 19 21:39:13 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 19 Nov 2018 13:39:13 -0800 Subject: RFR: 8213908: AssertionError in DeferredAttr at setOverloadKind Message-ID: Hi, Please review this follow-up to JDK-8203679 and JDK-8210483, which relaxes an assertion that was added by the earlier fixes. The intent of the assertion was to ensure that separate attribution steps don't both succeed but determine different overload kinds for a method reference, but the assertion was also failing if an earlier attribution step succeeded and a later attribution step failed. webrev: http://cr.openjdk.java.net/~cushon/8213908/webrev.00/ bug: https://bugs.openjdk.java.net/browse/JDK-8213908 -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Tue Nov 20 01:49:48 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 19 Nov 2018 17:49:48 -0800 Subject: RFR: 8214026: Canonicalized archive paths appearing in diagnostics Message-ID: Hi, Please consider this fix for JDK-8214026, which ensures that jar archive paths in diagnostics (e.g. for 'bad class file' errors) are not canonicalized, for consistency with the JDK 8 javac behaviour and the precedent set by JDK-8181897 and JDK-8178017. bug: https://bugs.openjdk.java.net/browse/JDK-8214026 webrev: http://cr.openjdk.java.net/~cushon/8214026/webrev.00/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at google.com Tue Nov 20 02:21:37 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Mon, 19 Nov 2018 18:21:37 -0800 Subject: spec clarification: type annotations on static nested types In-Reply-To: References: <5A53D7C6.1070809@oracle.com> <5A8DF60F.7040002@oracle.com> Message-ID: On Thu, Feb 22, 2018 at 11:23 AM Liam Miller-Cushon wrote: > On Wed, Feb 21, 2018 at 2:43 PM, Alex Buckley > wrote: > >> On 2/21/2018 2:34 PM, Liam Miller-Cushon wrote: >> >>> I'm now reading "nested type" as meaning a type that is nested inside an >>> *annotatable* type. >>> i.e. in A.B where B is a non-static inner class, A is an annotatable >>> enclosing instance type, so a type path is needed to indicate that in >>> `A. at Foo B` the annotation is on B. >>> However in A.B where B is a static member class, A is a 'scoping >>> construct' rather than an annotatable type, so no type path is needed >>> for `A. at Foo B` since B is the only annotatable type. >>> >> >> That sounds plausible -- the "scoping construct" concept tunneled itself >> fairly deeply into the JLS -- but I don't especially recall that "nested >> type" in JVMS 4.7.20.2 meant to represent only non-static members. I can >> only suggest more digging on type-annotations-spec-experts, sorry. > > >From some offline discussion with Mike and Werner, the original intent was for "nested type" in JVMS 4.7.20.2 to only apply to non-static members. I couldn't find related discussions in type-annotations-spec-experts. However there's some language in the jsr308 draft about locations where type annotations may appear, which mentions 'scoping mechanisms' and which rules out annotations on qualifiers of static members [1]. The draft section on type_path mentions it distinguishes among locations where "an annotation may appear" [2], which as defined doesn't include qualifiers of static members. I see at least two options to reconcile the JVMS, javac, and core reflection. (a) Update JVMS 4.7.20.2 to mention non-static members, update core reflection to match, and leave javac's current behaviour as-is. (b) Change javac's behaviour to emit type path entries for both static and non-static member classes. I think there are a couple of reasons to prefer (a). * It results in slightly more efficient class files, with more compact type_path structures. * it avoids breaking compatibility with the code javac and ecj have been generating since JDK 8. Changing getAnnotatedOwnerType seems lower-risk since it was added more recently, and (due to the issue we're discussing) doesn't work reliably. [1] https://checkerframework.org/jsr308/specification/java-annotation-design.html#type-names [2] https://checkerframework.org/jsr308/specification/java-annotation-design.html#class-file%3Aext%3Atype_path -------------- next part -------------- An HTML attachment was scrubbed... URL: From amaembo at gmail.com Tue Nov 20 09:40:28 2018 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 20 Nov 2018 16:40:28 +0700 Subject: Switch expression with string concatenation Message-ID: Hello! Seems that switch expression behaves badly with string concatenation. Example: public class Java12Test { public static void main(String[] args) { String s = "foo"; System.out.println(s + switch(0) { default -> { s = "bar"; break 1; } }); System.out.println(s); } } >"C:\Program Files\Java\jdk-12\bin\java.exe" -version openjdk version "12-ea" 2019-03-19 OpenJDK Runtime Environment (build 12-ea+20) OpenJDK 64-Bit Server VM (build 12-ea+20, mixed mode, sharing) >"C:\Program Files\Java\jdk-12\bin\javac.exe" --enable-preview --release=12 Java12Test.java Note: Java12Test.java uses preview language features. Note: Recompile with -Xlint:preview for details. >"C:\Program Files\Java\jdk-12\bin\java.exe" --enable-preview Java12Test foo1 foo As you can see, `s = "bar"` assignment was not executed. With best regards, Tagir Valeev From amaembo at gmail.com Tue Nov 20 09:49:02 2018 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 20 Nov 2018 16:49:02 +0700 Subject: Switch-expression with nested try Message-ID: Hello! Switch expression with nested try is a weird beast. I was wondering how you managed to compile it. Seems it's still problematic. Code: public class Java12Test { public static void main(String[] args) { System.out.println(switch(0) { default -> { try { throw new Exception(); } catch(Exception ex) { break 1; } } }); } } >"C:\Program Files\Java\jdk-12\bin\java.exe" -version openjdk version "12-ea" 2019-03-19 OpenJDK Runtime Environment (build 12-ea+20) OpenJDK 64-Bit Server VM (build 12-ea+20, mixed mode, sharing) >"C:\Program Files\Java\jdk-12\bin\javac.exe" --enable-preview --release=12 Java12Test.java Note: Java12Test.java uses preview language features. Note: Recompile with -Xlint:preview for details. >"C:\Program Files\Java\jdk-12\bin\java.exe" --enable-preview Java12Test Error: Unable to initialize main class Java12Test Caused by: java.lang.VerifyError: Stack map does not match the one at exception handler 24 Exception Details: Location: Java12Test.main([Ljava/lang/String;)V @16: new Reason: Current frame's stack size doesn't match stackmap. Current Frame: bci: @16 flags: { } locals: { '[Ljava/lang/String;' } stack: { 'java/lang/Exception' } Stackmap Frame: bci: @24 flags: { } locals: { '[Ljava/lang/String;' } stack: { 'java/io/PrintStream', 'java/lang/Exception' } Bytecode: 0000000: b200 0203 ab00 0000 0000 000c 0000 0000 0000010: bb00 0359 b700 04bf 4d04 3ca7 0003 1bb6 0000020: 0005 b1 Exception Handler Table: bci [16, 24] => handler: 24 Stackmap Table: same_locals_1_stack_item_frame(@16,Object[#15]) full_frame(@24,{Object[#16]},{Object[#15],Object[#3]}) full_frame(@30,{Object[#16],Integer},{Object[#15]}) With best regards, Tagir Valeev From maurizio.cimadamore at oracle.com Tue Nov 20 11:54:14 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 20 Nov 2018 11:54:14 +0000 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body In-Reply-To: <5a8f97e4-8eb2-d24e-8241-d6d57d36ff3d@oracle.com> References: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> <55121cfa-2b40-0f59-089c-cce57235eb91@oracle.com> <5a8f97e4-8eb2-d24e-8241-d6d57d36ff3d@oracle.com> Message-ID: <4b501147-6f9b-fe3c-3607-dcc312c5c09a@oracle.com> Looks good - why is there a new change in the test? Maurizio On 19/11/2018 20:57, Vicente Romero wrote: > Hi Maurizio, > > On 11/9/18 5:57 AM, Maurizio Cimadamore wrote: >> >> Looks good - can we cook up a test that is also stressing the other >> new code path? >> > > what about: http://cr.openjdk.java.net/~vromero/8203277/webrev.02/? > >> Maurizio >> > > Thanks, > Vicente > >> On 09/11/2018 00:12, Vicente Romero wrote: >>> >>> >>> On 11/8/18 6:02 PM, Maurizio Cimadamore wrote: >>>> >>>> Hi, >>>> I agree that preflow shouldn't care about nested constructs; but I >>>> wonder - is diamond anon class the only case we need to worry about >>>> here? What about a nested lambda expression? >>>> >>> >>> right I agree with you, what about [3]? >>> >>>> Maurizio >>>> >>> Vicente >>> >>> [3] http://cr.openjdk.java.net/~vromero/8203277/webrev.01/ >>>> >>>> On 08/11/2018 00:24, Vicente Romero wrote: >>>>> Please review the fix for [1] at [2]. The bug can be illustrated >>>>> with this test case: >>>>> >>>>> import java.util.List; >>>>> import java.util.function.Function; >>>>> >>>>> class DiamondInsideLambdaTest { >>>>> ??? void build() { >>>>> ??????? List> list = transform(null, >>>>> ??????????????? builder -> new Function<>() { >>>>> ??????????????????? public Double apply(String params) { return >>>>> null; } >>>>> ??????????????? }); >>>>> ??? } >>>>> >>>>> ??? static List >>>>> transform(List fromList, Function>>>> extends Result> function) { return null; } >>>>> } >>>>> >>>>> During lambda attribution, there is a preflow visitor that fill >>>>> some holes, missing types / symbols, before doing an special flow >>>>> analysis on the lambda. This flow analysis skip inner classes >>>>> defined inside the lambda body. The preflow visitor is anyway >>>>> visiting inner classes and filling, with garbage, some of the >>>>> wholes. In most cases as the preflow step happens after the lambda >>>>> body has been attributed, it should be a no-op. But if the lambda >>>>> body contains a diamond as in this case, then it could be that the >>>>> attribution can't be done previous to the preflow step. Simply >>>>> because some types in the diamond could be waiting for type >>>>> inference to come to a resolution. In that case preflow will >>>>> modify the diamond expression and later on during completion, as >>>>> some symbols and types are filled with erroneous types, they will >>>>> keep that erroneous type. >>>>> >>>>> [1] https://bugs.openjdk.java.net/browse/JDK-8203277 >>>>> [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Tue Nov 20 11:55:41 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 20 Nov 2018 11:55:41 +0000 Subject: RFR: 8213908: AssertionError in DeferredAttr at setOverloadKind In-Reply-To: References: Message-ID: <07d58541-7a68-ca35-1ec7-f778b7a9e7cb@oracle.com> Looks good; I also wonder if it should be relaxed in the other direction too - e.g. Assert.check(previous == ERROR || overloadKInd == ERROR || previous == overloadKind) Maurizio On 19/11/2018 21:39, Liam Miller-Cushon wrote: > Hi, > > Please review this follow-up to?JDK-8203679 and JDK-8210483, which > relaxes an assertion that was added by the earlier fixes. > > The intent of the assertion was to ensure that separate attribution > steps don't both succeed but determine different overload kinds for a > method reference, but the assertion was also failing if an earlier > attribution step succeeded and a later attribution step failed. > > webrev: http://cr.openjdk.java.net/~cushon/8213908/webrev.00/ > bug: https://bugs.openjdk.java.net/browse/JDK-8213908 From jan.lahoda at oracle.com Tue Nov 20 12:10:12 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 20 Nov 2018 13:10:12 +0100 Subject: Switch expression with string concatenation In-Reply-To: References: Message-ID: <5BF3F9A4.1040404@oracle.com> Hi Tagir, Thanks for the report, I've filled it here: https://bugs.openjdk.java.net/browse/JDK-8214113 Jan On 20.11.2018 10:40, Tagir Valeev wrote: > Hello! > > Seems that switch expression behaves badly with string concatenation. Example: > > public class Java12Test { > public static void main(String[] args) { > String s = "foo"; > System.out.println(s + switch(0) { > default -> { > s = "bar"; > break 1; > } > }); > System.out.println(s); > } > } > >> "C:\Program Files\Java\jdk-12\bin\java.exe" -version > openjdk version "12-ea" 2019-03-19 > OpenJDK Runtime Environment (build 12-ea+20) > OpenJDK 64-Bit Server VM (build 12-ea+20, mixed mode, sharing) > >> "C:\Program Files\Java\jdk-12\bin\javac.exe" --enable-preview --release=12 Java12Test.java > Note: Java12Test.java uses preview language features. > Note: Recompile with -Xlint:preview for details. > >> "C:\Program Files\Java\jdk-12\bin\java.exe" --enable-preview Java12Test > foo1 > foo > > As you can see, `s = "bar"` assignment was not executed. > > With best regards, > Tagir Valeev > From jan.lahoda at oracle.com Tue Nov 20 12:13:40 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 20 Nov 2018 13:13:40 +0100 Subject: Switch-expression with nested try In-Reply-To: References: Message-ID: <5BF3FA74.7080200@oracle.com> Hi Tagir, Thanks for the report, I've filled it here: https://bugs.openjdk.java.net/browse/JDK-8214114 Jan On 20.11.2018 10:49, Tagir Valeev wrote: > Hello! > > Switch expression with nested try is a weird beast. I was wondering > how you managed to compile it. Seems it's still problematic. Code: > > public class Java12Test { > public static void main(String[] args) { > System.out.println(switch(0) { > default -> { > try { throw new Exception(); } > catch(Exception ex) { > break 1; > } > } > }); > } > } > >> "C:\Program Files\Java\jdk-12\bin\java.exe" -version > openjdk version "12-ea" 2019-03-19 > OpenJDK Runtime Environment (build 12-ea+20) > OpenJDK 64-Bit Server VM (build 12-ea+20, mixed mode, sharing) > >> "C:\Program Files\Java\jdk-12\bin\javac.exe" --enable-preview --release=12 Java12Test.java > Note: Java12Test.java uses preview language features. > Note: Recompile with -Xlint:preview for details. > >> "C:\Program Files\Java\jdk-12\bin\java.exe" --enable-preview Java12Test > Error: Unable to initialize main class Java12Test > Caused by: java.lang.VerifyError: Stack map does not match the one at > exception handler 24 > Exception Details: > Location: > Java12Test.main([Ljava/lang/String;)V @16: new > Reason: > Current frame's stack size doesn't match stackmap. > Current Frame: > bci: @16 > flags: { } > locals: { '[Ljava/lang/String;' } > stack: { 'java/lang/Exception' } > Stackmap Frame: > bci: @24 > flags: { } > locals: { '[Ljava/lang/String;' } > stack: { 'java/io/PrintStream', 'java/lang/Exception' } > Bytecode: > 0000000: b200 0203 ab00 0000 0000 000c 0000 0000 > 0000010: bb00 0359 b700 04bf 4d04 3ca7 0003 1bb6 > 0000020: 0005 b1 > Exception Handler Table: > bci [16, 24] => handler: 24 > Stackmap Table: > same_locals_1_stack_item_frame(@16,Object[#15]) > full_frame(@24,{Object[#16]},{Object[#15],Object[#3]}) > full_frame(@30,{Object[#16],Integer},{Object[#15]}) > > With best regards, > Tagir Valeev > From maurizio.cimadamore at oracle.com Tue Nov 20 14:09:24 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 20 Nov 2018 14:09:24 +0000 Subject: RFR: 8210742: Compound var declaration splitting seems broken In-Reply-To: <5dd8d0ee-1454-5f6c-121b-fc6d8eae8ddd@oracle.com> References: <2eae8c99-9fea-a9e8-c432-97f507d1695c@oracle.com> <964bc1c0-0d5d-d540-c489-91e8c97ef716@oracle.com> <5dd8d0ee-1454-5f6c-121b-fc6d8eae8ddd@oracle.com> Message-ID: Looks good. Seems like Netbeans needs to type check erroneous tree to later suggest possible refactoring that would be able to get rid of the error, which is why they are sensitive to what is the result of type analysis. Cheers Maurizio On 19/11/2018 17:26, srinivas wrote: > > Hi Maurizio, > > After checking with NB team about the expected behaviour for array > types, below are the conclusions. > > 1. They provide some series hints for the error cases for the user. > > for ex: var v = {1,2}, w = 2;? will have hint as convert to var > v={1,2}; var w=2; > > For this they will reconstruct the tree structure with inferred types > from error messages . > > After having debugging session with them, I found the expected > behavior of the tree structure from javac is same for both jdk10 and > jdk11(for which > > they reported issue for var x; types earlier) > > So In summary: As discussed we don't need to alter array types > behavior from javac. > > Please review revised patch with code refactored with error message > order and array AST behaviour preserved. > > webrev: http://cr.openjdk.java.net/~sdama/8210742/webrev.01/ > > Bug: https://bugs.openjdk.java.net/browse/JDK-8210742 > > Regards, > > Srinivas > > On 17/11/18 1:18 AM, Maurizio Cimadamore wrote: >> >> I understand. >> >> One thing that I don't 100% get is what is the set of requirements we >> need to preserve; in this case we have a parser error, meaning that >> the input source file is wrong according to the grammar; javac ends >> up creating a variable tree node anyway, and then this node gets >> eventually type-checked, and what we are talking about here is that, >> when this type-checking happens (on this tree that is the result of a >> javac error recovery step), we are observing a type checking >> difference from 10 to 11. >> >> Now, it seems like NB would like to have 'var' be applied in all >> branches of the compound assignment, and have all types be inferred. >> >> But, as you said, for a variable type such as 'var x[]' we can't do >> much, so we will report an error and we will, I think, create an AST >> of type 'var[]' which will be left untouched, I believe, by >> type-checking. >> >> So, I guess what I'm really asking for is some explanation of what >> the desired behavior should be, and why - so that we can make sure >> that, moving forward, we create the right kind of synthetic recovery >> trees in all cases. >> >> (of course none of this is an issue for javac which will shut down >> immediately after discovering a parser error w/o even attempting >> attribution). >> >> Maurizio >> >> On 15/11/2018 15:22, srinivas wrote: >>> >>> Hi Maurizio, >>> >>> Thanks for the review. >>> >>> Yes - Initially I thought of making this code common to all branches. >>> >>> Below are the reasons for not doing that. >>> >>> 1) the reported issue from NB team is for simple 'var x' types but >>> not for arrays. >>> >>> 2) I don't have enough data to preserve the type for arrays or not >>> and I want to avoid breaking any assumption related to arrays error >>> cases >>> >>> both from NB team and javac tests. >>> >>> Please let me know if I should include array case as well and >>> refactor the fix. >>> >>> Regards, >>> >>> Srinivas >>> >>> >>> >>> On 15/11/18 5:13 PM, Maurizio Cimadamore wrote: >>>> >>>> Hi, >>>> I think what you are doing is ok, but I have some comments: >>>> >>>> 1) it seems like this code: >>>> >>>> >>>> startPos = TreeInfo.getStartPos(mods); >>>> if (startPos == Position.NOPOS) >>>> ?? startPos = TreeInfo.getStartPos(type); >>>> >>>> should probably be lifted outside the 'if' - e.g. should apply to >>>> all cases after the check for "isRestrictedLocalVarTypeName" >>>> >>>> 2) A similar argument applies, kind of, to setting type to 'null'. >>>> With your patch we do that in 2/3 branches; the branch that is left >>>> out is when you have a var declaration like this: >>>> >>>> var foo[] = ... >>>> >>>> In this case the parser will still attempt to create a var tree >>>> with 'var' as its type. If we are worried about how the AST would >>>> look in erroneous cases, then I think this is a problem too. >>>> >>>> Cheers >>>> Maurizio >>>> >>>> On 15/11/2018 10:31, srinivas wrote: >>>>> Hi, >>>>> >>>>> Please review http://cr.openjdk.java.net/~sdama/8210742/webrev.00/ >>>>> >>>>> for https://bugs.openjdk.java.net/browse/JDK-8210742. >>>>> >>>>> Regards, >>>>> >>>>> Srinivas -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Tue Nov 20 17:14:35 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 20 Nov 2018 18:14:35 +0100 Subject: JDK-8212982: Rule cases in switch expression accepted even if complete normally Message-ID: <5BF440FB.9040401@oracle.com> Hi, Bug: https://bugs.openjdk.java.net/browse/JDK-8212982 The issue here is that javac accepts switch expressions that complete normally without providing a value, which is not correct. A (simpler) fix is to enhance Flow with the necessary checks + enhancements to place the errors at a good place. Webrev: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00/ This patch has a problem in cases like: --- public class SE { private String t(int i) { return switch (i) { default: break ""; System.err.println(0); }; } } --- This produces: --- $ javac --enable-preview --source 12 SE.java SE.java:6: error: unreachable statement System.err.println(0); ^ SE.java:7: error: switch expression completes without providing a value }; ^ (switch expressions must either provide a value or throw for all possible input values) --- The second error is caused by the first one (Flow will reset "alive" to "true" when reporting the "unreachable statement" error as an error recovery). A patch that changes the "alive" field to be tri-state (ALIVE, NOT_ALIVE, RECOVERY) so that it can suppress the second error in case of this recovery is here: Webrev 2: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00b/ (The only differences between the patches are in the Flow.java and ExpressionSwitchUnreachable.out.) This is longer, but I think it provides better errors, so I'd prefer this patch, but I am also fine with the first one. Any feedback is welcome! Thanks, Jan From cushon at google.com Tue Nov 20 17:47:58 2018 From: cushon at google.com (Liam Miller-Cushon) Date: Tue, 20 Nov 2018 09:47:58 -0800 Subject: RFR: 8213908: AssertionError in DeferredAttr at setOverloadKind In-Reply-To: <07d58541-7a68-ca35-1ec7-f778b7a9e7cb@oracle.com> References: <07d58541-7a68-ca35-1ec7-f778b7a9e7cb@oracle.com> Message-ID: On Tue, Nov 20, 2018 at 3:55 AM Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > Looks good; I also wonder if it should be relaxed in the other direction > too - e.g. > > Assert.check(previous == ERROR || overloadKInd == ERROR || previous == > overloadKind) > I think that's covered by the other branch of the if/else, we should only get to the assertion if previous != ERROR. -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Tue Nov 20 17:52:14 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 20 Nov 2018 17:52:14 +0000 Subject: RFR: 8213908: AssertionError in DeferredAttr at setOverloadKind In-Reply-To: References: <07d58541-7a68-ca35-1ec7-f778b7a9e7cb@oracle.com> Message-ID: Ah right; approved Maurizio On 20/11/2018 17:47, Liam Miller-Cushon wrote: > On Tue, Nov 20, 2018 at 3:55 AM Maurizio Cimadamore > > wrote: > > Looks good; I also wonder if it should be relaxed in the other > direction > too - e.g. > > Assert.check(previous == ERROR || overloadKInd == ERROR || > previous == > overloadKind) > > > I think that's covered by the other branch of the if/else, we should > only get to the assertion if previous != ERROR. -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Tue Nov 20 18:17:19 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 20 Nov 2018 18:17:19 +0000 Subject: JDK-8212982: Rule cases in switch expression accepted even if complete normally In-Reply-To: <5BF440FB.9040401@oracle.com> References: <5BF440FB.9040401@oracle.com> Message-ID: I like the tri-state fix; there is however something that leaves me perplexed. I see often idioms such as if (alive.alive ... Now, it seems like the Liveliness enum has a dual nature; on the one hand it's a tri-state (alive, dead, recovery). But there are cases in which you want to project it down to a two-state. The use of an hidden boolean here makes the code less readable, because a reader might ask - how is that different from alive == Liveliness.ALIVE? I think we should try to think as to what is the condition that we want to capture with the alive.alive and then have a method on the enum which returns 'true' for certain constants and false for others. I think what the code is doing is checking whether the liveliness *is not* dead. So perhaps, conditions such as alive.alive might better be rewritten as alive != Liveliness.NOT_ALIVE (btw, probably better to call NOT_ALIVE just DEAD and avoid all the double negations). Maurizio On 20/11/2018 17:14, Jan Lahoda wrote: > Hi, > > Bug: https://bugs.openjdk.java.net/browse/JDK-8212982 > > The issue here is that javac accepts switch expressions that complete > normally without providing a value, which is not correct. A (simpler) > fix is to enhance Flow with the necessary checks + enhancements to > place the errors at a good place. > > Webrev: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00/ > > This patch has a problem in cases like: > --- > public class SE { > ???? private String t(int i) { > ???????? return switch (i) { > ???????????? default: > ???????????????? break ""; > ???????????????? System.err.println(0); > ???????? }; > ???? } > } > --- > > This produces: > --- > $ javac --enable-preview --source 12 SE.java > SE.java:6: error: unreachable statement > ???????????????? System.err.println(0); > ???????????????? ^ > SE.java:7: error: switch expression completes without providing a value > ???????? }; > ???????? ^ > ? (switch expressions must either provide a value or throw for all > possible input values) > --- > > The second error is caused by the first one (Flow will reset "alive" > to "true" when reporting the "unreachable statement" error as an error > recovery). A patch that changes the "alive" field to be tri-state > (ALIVE, NOT_ALIVE, RECOVERY) so that it can suppress the second error > in case of this recovery is here: > > Webrev 2: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00b/ > > (The only differences between the patches are in the Flow.java and > ExpressionSwitchUnreachable.out.) > > This is longer, but I think it provides better errors, so I'd prefer > this patch, but I am also fine with the first one. > > Any feedback is welcome! > > Thanks, > ??? Jan From alex.buckley at oracle.com Tue Nov 20 19:47:43 2018 From: alex.buckley at oracle.com (Alex Buckley) Date: Tue, 20 Nov 2018 11:47:43 -0800 Subject: spec clarification: type annotations on static nested types In-Reply-To: References: <5A53D7C6.1070809@oracle.com> <5A8DF60F.7040002@oracle.com> Message-ID: <5BF464DF.3090405@oracle.com> On 11/19/2018 6:21 PM, Liam Miller-Cushon wrote: > From some offline discussion with Mike and Werner, the original intent > was for "nested type" in JVMS 4.7.20.2 to only apply to non-static members. > > I couldn't find related discussions in type-annotations-spec-experts. > However there's some language in the jsr308 draft about locations where > type annotations may appear, which mentions 'scoping mechanisms' and > which rules out annotations on qualifiers of static members [1]. The > draft section on type_path mentions it distinguishes among locations > where "an annotation may appear" [2], which as defined doesn't include > qualifiers of static members. > > I see at least two options to reconcile the JVMS, javac, and core > reflection. > > (a) Update JVMS 4.7.20.2 to mention non-static members, update core > reflection to match, and leave javac's current behaviour as-is. > (b) Change javac's behaviour to emit type path entries for both static > and non-static member classes. > > I think there are a couple of reasons to prefer (a). > * It results in slightly more efficient class files, with more compact > type_path structures. > * it avoids breaking compatibility with the code javac and ecj have been > generating since JDK 8. Changing getAnnotatedOwnerType seems lower-risk > since it was added more recently, and (due to the issue we're > discussing) doesn't work reliably. Thanks for investigating. Now that the original intent is clear, we could indeed adopt option (2). That involves thinking about how to narrate the change in the JVMS -- we need more color than simply adding "non-static" to a sentence in 4.7.20.2 and moving on. It appears the original intent was to have the class file structure follow the Java language constructs precisely, rather than to let the class file express more than the language (say, by tracking annotations on uses of static nested types). This intent is unusual in the broader picture, where class files are often more expressive than language constructs, but it's in line with how type_path is already able to express annotations on language-only constructs such as wildcards. "Scoping mechanism" is an informal concept that is not present in the JLS. It was formalized into the concept of "type contexts" in the Public Review of JSR 308. (For the details, read chapter 1 of the spec in that Public Review -- https://jcp.org/aboutJava/communityprocess/pr/jsr308/index.html -- to see how the oft-quoted declarative spec in java-annotation-design.html turned into a precise operational spec.) In addition, the ability to write `@Foo A.B` or `A. at Foo B` or neither was defined in terms of the qualified-this construct -- see JLS 9.7.4 and the definition of "admissible" (https://docs.oracle.com/javase/specs/jls/se11/html/jls-9.html#jls-9.7.4-400). So, 4.7.20.2 should describe how type_path in the class file matches up with "admissible" annotations on type uses with qualified names. I see that JDK-8198526 describes the problem (though with a critical typo in the second code sample) -- please file a corresponding specification/vm bug that: 1. Explains the problem using the JLS concepts I mentioned above (rather than appealing to an undefined "annotatable type" concept). 2. Proposes normative text for 4.7.20.2. 3. Expands the existing Outer.Middle.Inner example to say when @Foo could appear on each name (because it counts as admissible) and thus what the type_path would be. Alex From alex.buckley at oracle.com Tue Nov 20 20:06:43 2018 From: alex.buckley at oracle.com (Alex Buckley) Date: Tue, 20 Nov 2018 12:06:43 -0800 Subject: spec clarification: type annotations on static nested types In-Reply-To: References: <5A53D7C6.1070809@oracle.com> <5A8DF60F.7040002@oracle.com> Message-ID: <5BF46953.8060101@oracle.com> // Please disregard my prior mail as it had a typo for the option. On 11/19/2018 6:21 PM, Liam Miller-Cushon wrote: > From some offline discussion with Mike and Werner, the original intent > was for "nested type" in JVMS 4.7.20.2 to only apply to non-static members. > > I couldn't find related discussions in type-annotations-spec-experts. > However there's some language in the jsr308 draft about locations where > type annotations may appear, which mentions 'scoping mechanisms' and > which rules out annotations on qualifiers of static members [1]. The > draft section on type_path mentions it distinguishes among locations > where "an annotation may appear" [2], which as defined doesn't include > qualifiers of static members. > > I see at least two options to reconcile the JVMS, javac, and core > reflection. > > (a) Update JVMS 4.7.20.2 to mention non-static members, update core > reflection to match, and leave javac's current behaviour as-is. > (b) Change javac's behaviour to emit type path entries for both static > and non-static member classes. > > I think there are a couple of reasons to prefer (a). > * It results in slightly more efficient class files, with more compact > type_path structures. > * it avoids breaking compatibility with the code javac and ecj have been > generating since JDK 8. Changing getAnnotatedOwnerType seems lower-risk > since it was added more recently, and (due to the issue we're > discussing) doesn't work reliably. Thanks for investigating. Now that the original intent is clear, we could adopt option (a). That involves thinking about how to narrate the change in the JVMS -- we need more color than simply adding "non-static" to a sentence in 4.7.20.2 and moving on. It appears the original intent was to have the class file structure follow the Java language constructs precisely, rather than to let the class file express more than the language (say, by tracking annotations on uses of static nested types). This intent is unusual in the broader picture, where class files are often more expressive than language constructs, but it's in line with how type_path is already able to express annotations on language-only constructs such as wildcards. "Scoping mechanism" is an informal concept that is not present in the JLS. It was formalized into the concept of "type contexts" in the Public Review of JSR 308. (For the details, read chapter 1 of the spec in that Public Review -- https://jcp.org/aboutJava/communityprocess/pr/jsr308/index.html -- to see how the oft-quoted declarative spec in java-annotation-design.html turned into a precise operational spec.) In addition, the ability to write `@Foo A.B` or `A. at Foo B` or neither was defined in terms of the qualified-this construct -- see JLS 9.7.4 and the definition of "admissible" (https://docs.oracle.com/javase/specs/jls/se11/html/jls-9.html#jls-9.7.4-400). So, 4.7.20.2 should seek to capture the original intent by describing how type_path in the class file matches up with "admissible" annotations on type uses with qualified names. I see that JDK-8198526 describes the problem (though with a critical typo in the second code sample) -- please file a corresponding specification/vm bug that: 1. Explains the problem using the JLS concepts I mentioned above (rather than appealing to an undefined "annotatable type" concept). 2. Proposes normative text for 4.7.20.2. 3. Expands the existing Outer.Middle.Inner example to say when @Foo could appear on each name (because it counts as admissible) and thus what the type_path would be. Alex From jan.lahoda at oracle.com Wed Nov 21 10:31:13 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Wed, 21 Nov 2018 11:31:13 +0100 Subject: JDK-8212982: Rule cases in switch expression accepted even if complete normally In-Reply-To: References: <5BF440FB.9040401@oracle.com> Message-ID: <5BF533F1.5050605@oracle.com> Hi Maurizio, Thanks for the comments. I've renamed NOT_ALIVE to DEAD, as suggested, and replace "alive.alive" with appropriate tests (usually either == Liveness.DEAD or != Liveness.DEAD). I was first afraid this would look too bad, but seems to be quite reasonable to me in the end. Updated webrev is here: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.01/ Any further feedback is welcome! Thanks, Jan On 20.11.2018 19:17, Maurizio Cimadamore wrote: > I like the tri-state fix; there is however something that leaves me > perplexed. I see often idioms such as > > if (alive.alive ... > > Now, it seems like the Liveliness enum has a dual nature; on the one > hand it's a tri-state (alive, dead, recovery). But there are cases in > which you want to project it down to a two-state. The use of an hidden > boolean here makes the code less readable, because a reader might ask - > how is that different from alive == Liveliness.ALIVE? > > I think we should try to think as to what is the condition that we want > to capture with the alive.alive and then have a method on the enum which > returns 'true' for certain constants and false for others. > > I think what the code is doing is checking whether the liveliness *is > not* dead. > > So perhaps, conditions such as alive.alive might better be rewritten as > alive != Liveliness.NOT_ALIVE > > (btw, probably better to call NOT_ALIVE just DEAD and avoid all the > double negations). > > Maurizio > > > On 20/11/2018 17:14, Jan Lahoda wrote: >> Hi, >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-8212982 >> >> The issue here is that javac accepts switch expressions that complete >> normally without providing a value, which is not correct. A (simpler) >> fix is to enhance Flow with the necessary checks + enhancements to >> place the errors at a good place. >> >> Webrev: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00/ >> >> This patch has a problem in cases like: >> --- >> public class SE { >> private String t(int i) { >> return switch (i) { >> default: >> break ""; >> System.err.println(0); >> }; >> } >> } >> --- >> >> This produces: >> --- >> $ javac --enable-preview --source 12 SE.java >> SE.java:6: error: unreachable statement >> System.err.println(0); >> ^ >> SE.java:7: error: switch expression completes without providing a value >> }; >> ^ >> (switch expressions must either provide a value or throw for all >> possible input values) >> --- >> >> The second error is caused by the first one (Flow will reset "alive" >> to "true" when reporting the "unreachable statement" error as an error >> recovery). A patch that changes the "alive" field to be tri-state >> (ALIVE, NOT_ALIVE, RECOVERY) so that it can suppress the second error >> in case of this recovery is here: >> >> Webrev 2: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00b/ >> >> (The only differences between the patches are in the Flow.java and >> ExpressionSwitchUnreachable.out.) >> >> This is longer, but I think it provides better errors, so I'd prefer >> this patch, but I am also fine with the first one. >> >> Any feedback is welcome! >> >> Thanks, >> Jan From maurizio.cimadamore at oracle.com Wed Nov 21 11:02:54 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 21 Nov 2018 11:02:54 +0000 Subject: JDK-8212982: Rule cases in switch expression accepted even if complete normally In-Reply-To: <5BF533F1.5050605@oracle.com> References: <5BF440FB.9040401@oracle.com> <5BF533F1.5050605@oracle.com> Message-ID: <648e7633-74de-1c5b-c4a5-da52915da2d8@oracle.com> Looks great. One minor nit that I had not notice yesterday on the error messages; I think this message: switch expression completes without providing a value\n\ + (switch expressions must either provide a value or throw for all possible input values) Works better than this switch rule completes normally\n\ + (switch rules in switch expressions must either provide a value or throw) The reason being that "switch rule completes normally", the first line of the message, is kind of vague, and does not give many indications of what's wrong. I'd prefer something like this: switch rule completes without providing a value\n\ + (switch rules in switch expressions must either provide a value or throw) There is a bit of repetition, yes, but I think it's a better message. I'll leave this to your consideration. No need for another review. Thanks! Maurizio On 21/11/2018 10:31, Jan Lahoda wrote: > Hi Maurizio, > > Thanks for the comments. I've renamed NOT_ALIVE to DEAD, as suggested, > and replace "alive.alive" with appropriate tests (usually either == > Liveness.DEAD or != Liveness.DEAD). I was first afraid this would look > too bad, but seems to be quite reasonable to me in the end. > > Updated webrev is here: > http://cr.openjdk.java.net/~jlahoda/8212982/webrev.01/ > > Any further feedback is welcome! > > Thanks, > ??? Jan > > On 20.11.2018 19:17, Maurizio Cimadamore wrote: >> I like the tri-state fix; there is however something that leaves me >> perplexed. I see often idioms such as >> >> if (alive.alive ... >> >> Now, it seems like the Liveliness enum has a dual nature; on the one >> hand it's a tri-state (alive, dead, recovery). But there are cases in >> which you want to project it down to a two-state. The use of an hidden >> boolean here makes the code less readable, because a reader might ask - >> how is that different from alive == Liveliness.ALIVE? >> >> I think we should try to think as to what is the condition that we want >> to capture with the alive.alive and then have a method on the enum which >> returns 'true' for certain constants and false for others. >> >> I think what the code is doing is checking whether the liveliness *is >> not* dead. >> >> So perhaps, conditions such as alive.alive might better be rewritten as >> alive != Liveliness.NOT_ALIVE >> >> (btw, probably better to call NOT_ALIVE just DEAD and avoid all the >> double negations). >> >> Maurizio >> >> >> On 20/11/2018 17:14, Jan Lahoda wrote: >>> Hi, >>> >>> Bug: https://bugs.openjdk.java.net/browse/JDK-8212982 >>> >>> The issue here is that javac accepts switch expressions that complete >>> normally without providing a value, which is not correct. A (simpler) >>> fix is to enhance Flow with the necessary checks + enhancements to >>> place the errors at a good place. >>> >>> Webrev: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00/ >>> >>> This patch has a problem in cases like: >>> --- >>> public class SE { >>> ???? private String t(int i) { >>> ???????? return switch (i) { >>> ???????????? default: >>> ???????????????? break ""; >>> ???????????????? System.err.println(0); >>> ???????? }; >>> ???? } >>> } >>> --- >>> >>> This produces: >>> --- >>> $ javac --enable-preview --source 12 SE.java >>> SE.java:6: error: unreachable statement >>> ???????????????? System.err.println(0); >>> ???????????????? ^ >>> SE.java:7: error: switch expression completes without providing a value >>> ???????? }; >>> ???????? ^ >>> ? (switch expressions must either provide a value or throw for all >>> possible input values) >>> --- >>> >>> The second error is caused by the first one (Flow will reset "alive" >>> to "true" when reporting the "unreachable statement" error as an error >>> recovery). A patch that changes the "alive" field to be tri-state >>> (ALIVE, NOT_ALIVE, RECOVERY) so that it can suppress the second error >>> in case of this recovery is here: >>> >>> Webrev 2: http://cr.openjdk.java.net/~jlahoda/8212982/webrev.00b/ >>> >>> (The only differences between the patches are in the Flow.java and >>> ExpressionSwitchUnreachable.out.) >>> >>> This is longer, but I think it provides better errors, so I'd prefer >>> this patch, but I am also fine with the first one. >>> >>> Any feedback is welcome! >>> >>> Thanks, >>> ??? Jan -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Wed Nov 21 12:41:27 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Wed, 21 Nov 2018 13:41:27 +0100 Subject: RFR: JDK-8214113: Switch expressions may have constant type and may be skipped during write Message-ID: <5BF55277.1040705@oracle.com> Hi, Consider switch expression produces only a single constant value, like: switch (expr) { default: counter++; break 1; } Then Attr.condType returns the type of the given constant value, and if that is a constant type, the type of the whole switch expression is a constant type. And Gen may then elide the whole switch expression, which is wrong, as it may contain side-effects, or all the other arms may the throwing an exception. The solution would be to simply call .baseType() on the result, but simply deleting the special case for a single output value should work as well, as the following condition should handle the single output value case well. Bug: https://bugs.openjdk.java.net/browse/JDK-8214113 Webrev: http://cr.openjdk.java.net/~jlahoda/8214113/webrev.00/ How does this look? Thanks, Jan From anna.kozlova at jetbrains.com Wed Nov 21 13:45:26 2018 From: anna.kozlova at jetbrains.com (Anna Kozlova) Date: Wed, 21 Nov 2018 14:45:26 +0100 Subject: switch expression without value Message-ID: Hi all, looks like the code should not compile public class MyTest { public static void main(String[] args) { Supplier stringSupplier = switch (args.length) { default -> { } }; } } At least running the class I get verify error: Exception in thread "main" java.lang.VerifyError: Bad local variable type Exception Details: Location: org/jetbrains/MyTest.main([Ljava/lang/String;)V @12: aload_2 Reason: Type top (current frame, locals[2]) is not assignable to reference type Current Frame: bci: @12 flags: { } locals: { '[Ljava/lang/String;' } stack: { } Bytecode: 0000000: 2abe ab00 0000 000a 0000 0000 2c4c b1 Stackmap Table: same_frame(@12) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:325) at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:107) Thanks, Anna -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Wed Nov 21 14:48:57 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Wed, 21 Nov 2018 15:48:57 +0100 Subject: switch expression without value In-Reply-To: References: Message-ID: <5BF57059.9000207@oracle.com> Hi Anna, I believe this is the same as https://bugs.openjdk.java.net/browse/JDK-8212982 (which has just been fixed.) Jan On 21.11.2018 14:45, Anna Kozlova wrote: > Hi all, > > looks like the code should not compile > public class MyTest { > public static void main(String[] args) { > Supplier stringSupplier = switch (args.length) { > default -> { > } > }; > } > } > > At least running the class I get verify error: > > Exception in thread "main" java.lang.VerifyError: Bad local variable type > Exception Details: > Location: > org/jetbrains/MyTest.main([Ljava/lang/String;)V @12: aload_2 > Reason: > Type top (current frame, locals[2]) is not assignable to reference type > Current Frame: > bci: @12 > flags: { } > locals: { '[Ljava/lang/String;' } > stack: { } > Bytecode: > 0000000: 2abe ab00 0000 000a 0000 0000 2c4c b1 > Stackmap Table: > same_frame(@12) > > at java.base/java.lang.Class.forName0(Native Method) > at java.base/java.lang.Class.forName(Class.java:325) > at > com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:107) > > Thanks, > Anna From maurizio.cimadamore at oracle.com Wed Nov 21 17:39:12 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 21 Nov 2018 17:39:12 +0000 Subject: RFR: JDK-8214113: Switch expressions may have constant type and may be skipped during write In-Reply-To: <5BF55277.1040705@oracle.com> References: <5BF55277.1040705@oracle.com> Message-ID: <7e00e5d0-194d-d714-6a96-d75123599690@oracle.com> Looks good Maurizio On 21/11/2018 12:41, Jan Lahoda wrote: > Hi, > > Consider switch expression produces only a single constant value, like: > switch (expr) { > ??? default: > ??????? counter++; > ??????? break 1; > } > > Then Attr.condType returns the type of the given constant value, and > if that is a constant type, the type of the whole switch expression is > a constant type. And Gen may then elide the whole switch expression, > which is wrong, as it may contain side-effects, or all the other arms > may the throwing an exception. > > The solution would be to simply call .baseType() on the result, but > simply deleting the special case for a single output value should work > as well, as the following condition should handle the single output > value case well. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8214113 > Webrev: http://cr.openjdk.java.net/~jlahoda/8214113/webrev.00/ > > How does this look? > > Thanks, > ??? Jan From attila.kelemen85 at gmail.com Sat Nov 24 12:55:01 2018 From: attila.kelemen85 at gmail.com (Attila Kelemen) Date: Sat, 24 Nov 2018 13:55:01 +0100 Subject: Raw strings starting/ending with backtick Message-ID: Hi, Reading the JEP on raw string literals, I saw no mentions of the case when a string starts (or ends) with backtick. I guessed, that maybe the compiler will close the literal when it finds more than half the number of backticks than the beginning (nothing implied this behaviour just tried it and I know that it might be very suprising in other cases). I have tried with the latest early access compiler and (not too suprisingly) it didn't behave this way and simply failed when starting the literal with a backtick. My question is, of course: What is the strategy for this case? Or is it explicitly ignored as too much of an edge case (and left to the developer to deal with)? Thanks, Attila Kelemen -------------- next part -------------- An HTML attachment was scrubbed... URL: From james.laskey at oracle.com Sat Nov 24 13:11:54 2018 From: james.laskey at oracle.com (Jim Laskey) Date: Sat, 24 Nov 2018 09:11:54 -0400 Subject: Raw strings starting/ending with backtick In-Reply-To: References: Message-ID: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> There are several approaches but the simplest is using strip(). Example, `` `abc` ``.strip() Concat is another approach, ?`? + `abc` + ?`? Not perfect but other delimiter choices also have these edge cases. Cheers, ? Jim Sent from my iPad > On Nov 24, 2018, at 8:55 AM, Attila Kelemen wrote: > > Hi, > > Reading the JEP on raw string literals, I saw no mentions of the case when a string starts (or ends) with backtick. I guessed, that maybe the compiler will close the literal when it finds more than half the number of backticks than the beginning (nothing implied this behaviour just tried it and I know that it might be very suprising in other cases). I have tried with the latest early access compiler and (not too suprisingly) it didn't behave this way and simply failed when starting the literal with a backtick. > > My question is, of course: What is the strategy for this case? Or is it explicitly ignored as too much of an edge case (and left to the developer to deal with)? > > Thanks, > Attila Kelemen From weijun.wang at oracle.com Sat Nov 24 15:34:39 2018 From: weijun.wang at oracle.com (Weijun Wang) Date: Sat, 24 Nov 2018 23:34:39 +0800 Subject: Raw strings starting/ending with backtick In-Reply-To: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> Message-ID: <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> > On Nov 24, 2018, at 9:11 PM, Jim Laskey wrote: > > There are several approaches but the simplest is using strip(). Example, > > `` `abc` ``.strip() > > Concat is another approach, > > ?`? + `abc` + ?`? But this means the literal inside the constant pool of the class will be "`abc` ", right? This is a little uncomfortable to me. > > Not perfect but other delimiter choices also have these edge cases. How about the Rust r###"..."### style? Thanks Max > > Cheers, > > ? Jim > > > Sent from my iPad > >> On Nov 24, 2018, at 8:55 AM, Attila Kelemen wrote: >> >> Hi, >> >> Reading the JEP on raw string literals, I saw no mentions of the case when a string starts (or ends) with backtick. I guessed, that maybe the compiler will close the literal when it finds more than half the number of backticks than the beginning (nothing implied this behaviour just tried it and I know that it might be very suprising in other cases). I have tried with the latest early access compiler and (not too suprisingly) it didn't behave this way and simply failed when starting the literal with a backtick. >> >> My question is, of course: What is the strategy for this case? Or is it explicitly ignored as too much of an edge case (and left to the developer to deal with)? >> >> Thanks, >> Attila Kelemen > From brian.goetz at oracle.com Sat Nov 24 16:22:01 2018 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 24 Nov 2018 11:22:01 -0500 Subject: Raw strings starting/ending with backtick In-Reply-To: <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> Message-ID: No. The compiler can do constant folding of such expressions. Sent from my iPad > On Nov 24, 2018, at 10:34 AM, Weijun Wang wrote: > > > >> On Nov 24, 2018, at 9:11 PM, Jim Laskey wrote: >> >> There are several approaches but the simplest is using strip(). Example, >> >> `` `abc` ``.strip() >> >> Concat is another approach, >> >> ?`? + `abc` + ?`? > > But this means the literal inside the constant pool of the class will be "`abc` ", right? This is a little uncomfortable to me. > >> >> Not perfect but other delimiter choices also have these edge cases. > > How about the Rust r###"..."### style? > > Thanks > Max > >> >> Cheers, >> >> ? Jim >> >> >> Sent from my iPad >> >>> On Nov 24, 2018, at 8:55 AM, Attila Kelemen wrote: >>> >>> Hi, >>> >>> Reading the JEP on raw string literals, I saw no mentions of the case when a string starts (or ends) with backtick. I guessed, that maybe the compiler will close the literal when it finds more than half the number of backticks than the beginning (nothing implied this behaviour just tried it and I know that it might be very suprising in other cases). I have tried with the latest early access compiler and (not too suprisingly) it didn't behave this way and simply failed when starting the literal with a backtick. >>> >>> My question is, of course: What is the strategy for this case? Or is it explicitly ignored as too much of an edge case (and left to the developer to deal with)? >>> >>> Thanks, >>> Attila Kelemen >> > From james.laskey at oracle.com Sat Nov 24 17:30:12 2018 From: james.laskey at oracle.com (James Laskey) Date: Sat, 24 Nov 2018 13:30:12 -0400 Subject: Raw strings starting/ending with backtick In-Reply-To: <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> Message-ID: Sent from my iPhone > On Nov 24, 2018, at 11:34 AM, Weijun Wang wrote: > > > >> On Nov 24, 2018, at 9:11 PM, Jim Laskey wrote: >> >> There are several approaches but the simplest is using strip(). Example, >> >> `` `abc` ``.strip() >> >> Concat is another approach, >> >> ?`? + `abc` + ?`? > > But this means the literal inside the constant pool of the class will be "`abc` ", right? This is a little uncomfortable to me. > That?s the plan. >> >> Not perfect but other delimiter choices also have these edge cases. > > How about the Rust r###"..."### style? > > Thanks > Max > >> >> Cheers, >> >> ? Jim >> >> >> Sent from my iPad >> >>> On Nov 24, 2018, at 8:55 AM, Attila Kelemen wrote: >>> >>> Hi, >>> >>> Reading the JEP on raw string literals, I saw no mentions of the case when a string starts (or ends) with backtick. I guessed, that maybe the compiler will close the literal when it finds more than half the number of backticks than the beginning (nothing implied this behaviour just tried it and I know that it might be very suprising in other cases). I have tried with the latest early access compiler and (not too suprisingly) it didn't behave this way and simply failed when starting the literal with a backtick. >>> >>> My question is, of course: What is the strategy for this case? Or is it explicitly ignored as too much of an edge case (and left to the developer to deal with)? >>> >>> Thanks, >>> Attila Kelemen >> > From attila.kelemen85 at gmail.com Sat Nov 24 17:57:58 2018 From: attila.kelemen85 at gmail.com (Attila Kelemen) Date: Sat, 24 Nov 2018 18:57:58 +0100 Subject: Raw strings starting/ending with backtick In-Reply-To: References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> Message-ID: Thanks for all the answers. I was just a little curious if I missed something and there is nice syntax for this as well. Not that I could come up with something brilliant, only if Java was a brand new language, then 3 "quote" types would solve all the issues (and escaping would be completely useless). Obviously, this is not really an option here. James Laskey ezt ?rta (id?pont: 2018. nov. 24., Szo, 18:30): > > > Sent from my iPhone > > > On Nov 24, 2018, at 11:34 AM, Weijun Wang > wrote: > > > > > > > >> On Nov 24, 2018, at 9:11 PM, Jim Laskey > wrote: > >> > >> There are several approaches but the simplest is using strip(). > Example, > >> > >> `` `abc` ``.strip() > >> > >> Concat is another approach, > >> > >> ?`? + `abc` + ?`? > > > > But this means the literal inside the constant pool of the class will be > "`abc` ", right? This is a little uncomfortable to me. > > > That?s the plan. > > >> > >> Not perfect but other delimiter choices also have these edge cases. > > > > How about the Rust r###"..."### style? > > > > > Thanks > > Max > > > >> > >> Cheers, > >> > >> ? Jim > >> > >> > >> Sent from my iPad > >> > >>> On Nov 24, 2018, at 8:55 AM, Attila Kelemen < > attila.kelemen85 at gmail.com> wrote: > >>> > >>> Hi, > >>> > >>> Reading the JEP on raw string literals, I saw no mentions of the case > when a string starts (or ends) with backtick. I guessed, that maybe the > compiler will close the literal when it finds more than half the number of > backticks than the beginning (nothing implied this behaviour just tried it > and I know that it might be very suprising in other cases). I have tried > with the latest early access compiler and (not too suprisingly) it didn't > behave this way and simply failed when starting the literal with a backtick. > >>> > >>> My question is, of course: What is the strategy for this case? Or is > it explicitly ignored as too much of an edge case (and left to the > developer to deal with)? > >>> > >>> Thanks, > >>> Attila Kelemen > >> > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From james.laskey at oracle.com Sat Nov 24 17:40:32 2018 From: james.laskey at oracle.com (James Laskey) Date: Sat, 24 Nov 2018 13:40:32 -0400 Subject: Raw strings starting/ending with backtick In-Reply-To: References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> Message-ID: Misread - I didn?t see the spaces. The cp will contain "`abc`" (no spaces) Sent from my iPhone > On Nov 24, 2018, at 1:30 PM, James Laskey wrote: > > > > Sent from my iPhone > >> On Nov 24, 2018, at 11:34 AM, Weijun Wang wrote: >> >> >> >>> On Nov 24, 2018, at 9:11 PM, Jim Laskey wrote: >>> >>> There are several approaches but the simplest is using strip(). Example, >>> >>> `` `abc` ``.strip() >>> >>> Concat is another approach, >>> >>> ?`? + `abc` + ?`? >> >> But this means the literal inside the constant pool of the class will be "`abc` ", right? This is a little uncomfortable to me. >> > That?s the plan. > >>> >>> Not perfect but other delimiter choices also have these edge cases. >> >> How about the Rust r###"..."### style? > >> >> Thanks >> Max >> >>> >>> Cheers, >>> >>> ? Jim >>> >>> >>> Sent from my iPad >>> >>>> On Nov 24, 2018, at 8:55 AM, Attila Kelemen wrote: >>>> >>>> Hi, >>>> >>>> Reading the JEP on raw string literals, I saw no mentions of the case when a string starts (or ends) with backtick. I guessed, that maybe the compiler will close the literal when it finds more than half the number of backticks than the beginning (nothing implied this behaviour just tried it and I know that it might be very suprising in other cases). I have tried with the latest early access compiler and (not too suprisingly) it didn't behave this way and simply failed when starting the literal with a backtick. >>>> >>>> My question is, of course: What is the strategy for this case? Or is it explicitly ignored as too much of an edge case (and left to the developer to deal with)? >>>> >>>> Thanks, >>>> Attila Kelemen >>> >> From james.laskey at oracle.com Sat Nov 24 17:58:49 2018 From: james.laskey at oracle.com (James Laskey) Date: Sat, 24 Nov 2018 13:58:49 -0400 Subject: Raw strings starting/ending with backtick In-Reply-To: References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> Message-ID: <26CEAA61-D1B1-4651-A906-E1DEE96ECAEA@oracle.com> Misread- "`abc`" (no spaces) will be in the constant pool. Sent from my iPhone > On Nov 24, 2018, at 1:30 PM, James Laskey wrote: > > > > Sent from my iPhone > >> On Nov 24, 2018, at 11:34 AM, Weijun Wang wrote: >> >> >> >>> On Nov 24, 2018, at 9:11 PM, Jim Laskey wrote: >>> >>> There are several approaches but the simplest is using strip(). Example, >>> >>> `` `abc` ``.strip() >>> >>> Concat is another approach, >>> >>> ?`? + `abc` + ?`? >> >> But this means the literal inside the constant pool of the class will be "`abc` ", right? This is a little uncomfortable to me. >> > That?s the plan. > >>> >>> Not perfect but other delimiter choices also have these edge cases. >> >> How about the Rust r###"..."### style? > >> >> Thanks >> Max >> >>> >>> Cheers, >>> >>> ? Jim >>> >>> >>> Sent from my iPad >>> >>>> On Nov 24, 2018, at 8:55 AM, Attila Kelemen wrote: >>>> >>>> Hi, >>>> >>>> Reading the JEP on raw string literals, I saw no mentions of the case when a string starts (or ends) with backtick. I guessed, that maybe the compiler will close the literal when it finds more than half the number of backticks than the beginning (nothing implied this behaviour just tried it and I know that it might be very suprising in other cases). I have tried with the latest early access compiler and (not too suprisingly) it didn't behave this way and simply failed when starting the literal with a backtick. >>>> >>>> My question is, of course: What is the strategy for this case? Or is it explicitly ignored as too much of an edge case (and left to the developer to deal with)? >>>> >>>> Thanks, >>>> Attila Kelemen >>> >> From cay.horstmann at sjsu.edu Sun Nov 25 07:39:39 2018 From: cay.horstmann at sjsu.edu (Cay Horstmann) Date: Sun, 25 Nov 2018 08:39:39 +0100 Subject: Raw strings starting/ending with backtick In-Reply-To: References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> Message-ID: <8de4159c-2ac8-c6d4-9e0e-7a23fc782c4e@gmail.com> I agree that it is inelegant that there is no good syntax for raw strings starting with a backtick. Some time ago (http://horstmann.com/unblog/2018-06-01), I suggested that an initial newline after the backticks could count as part of the raw string delimiter: String myNameInABox = ``` +-----+ | Cay | +-----+```; // This string starts with + Ok, maybe it's not brilliant, but it solves two problems: (1) how to format multiline strings that should be aligned, without having to strip out the initial newline (2) how to declare strings that start with a backtick. Cheers, Cay Le 24/11/2018 ? 18:57, Attila Kelemen a ?crit?: > Thanks for all the answers. I was just a little curious if I missed > something and there is nice syntax for this as well. Not that I could > come up with something brilliant, only if Java was a brand new language, > then 3 "quote" types would solve all the issues (and escaping would be > completely useless). Obviously, this is not really an option here. > > James Laskey > > ezt ?rta (id?pont: 2018. nov. 24., Szo, 18:30): > > > > Sent from my iPhone > > > On Nov 24, 2018, at 11:34 AM, Weijun Wang > wrote: > > > > > > > >> On Nov 24, 2018, at 9:11 PM, Jim Laskey > wrote: > >> > >> There are several? approaches but the simplest is using > strip().? Example, > >> > >>? ?`` `abc` ``.strip() > >> > >> Concat is another approach, > >> > >>? ??`? + `abc` + ?`? > > > > But this means the literal inside the constant pool of the class > will be "`abc` ", right? This is a little uncomfortable to me. > > > That?s the plan. > > >> > >> Not perfect but other delimiter choices also have these edge cases. > > > > How about the Rust r###"..."### style? > > > > > Thanks > > Max > > > >> > >> Cheers, > >> > >> ? Jim > >> > >> > >> Sent from my iPad > >> > >>> On Nov 24, 2018, at 8:55 AM, Attila Kelemen > > wrote: > >>> > >>> Hi, > >>> > >>> Reading the JEP on raw string literals, I saw no mentions of > the case when a string starts (or ends) with backtick. I guessed, > that maybe the compiler will close the literal when it finds more > than half the number of backticks than the beginning (nothing > implied this behaviour just tried it and I know that it might be > very suprising in other cases). I have tried with the latest early > access compiler and (not too suprisingly) it didn't behave this way > and simply failed when starting the literal with a backtick. > >>> > >>> My question is, of course: What is the strategy for this case? > Or is it explicitly ignored as too much of an edge case (and left to > the developer to deal with)? > >>> > >>> Thanks, > >>> Attila Kelemen > >> > > > -- Cay S. Horstmann | http://horstmann.com | mailto:cay at horstmann.com From john.r.rose at oracle.com Mon Nov 26 07:28:01 2018 From: john.r.rose at oracle.com (John Rose) Date: Sun, 25 Nov 2018 23:28:01 -0800 Subject: Raw strings starting/ending with backtick In-Reply-To: <8de4159c-2ac8-c6d4-9e0e-7a23fc782c4e@gmail.com> References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> <8de4159c-2ac8-c6d4-9e0e-7a23fc782c4e@gmail.com> Message-ID: <6640C0C9-A6C4-4069-93B0-1175F67E7B67@oracle.com> On Nov 24, 2018, at 11:39 PM, Cay Horstmann wrote: > > I agree that it is inelegant that there is no good syntax for raw strings starting with a backtick. Some time ago (http://horstmann.com/unblog/2018-06-01 ), I suggested that an initial newline after the backticks could count as part of the raw string delimiter: > > String myNameInABox = ``` > +-----+ > | Cay | > +-----+```; // This string starts with + > > Ok, maybe it's not brilliant, but it solves two problems: (1) how to format multiline strings that should be aligned, without having to strip out the initial newline (2) how to declare strings that start with a backtick. The basic reality here is that we are trying to keep the quotes as simple as possible, while allowing them to quote anything at all, including their shorter siblings. A close-quote can't both appear in a string and end that string for obvious reasons. Result: There must be an infinite set of close-quotes available, so that even if a string has the first N-1 close-quotes inside it, it can be terminated with the Nth one. This also implies there must be a corresponding infinite set of open-quotes. (Opens and closes can be pairwise identical, as in the proposed feature.) Next, we have the problem of designing a set of open quotes which can be differentiated from each other before the string body proper is scanned. (You have to determine the close-quote before scanning the string body.) This really means that open-quotes must be self-delimiting, or else that there are some substrings that are forbidden to follow at least some open-quotes. If an open-quote syntax is not fully self-delimiting, there are two open-quotes Q, QR for which Q is a proper prefix of QR. In this case, a quoted string body cannot begin with R and be quoted with Q. In the present case, we allow the open-quotes to be composed of an alphabet of only one letter, the backtick, but allow any positive number of them. That's pretty good (and really, really simple) but it does have the observed defect, that none of the open-quotes are self-delimiting, because for any N>0, "`".times(N) is a proper prefix of the next open-quote, "`".times(N+1). Thus, for no open-quote (in the present scheme) can the string body begin with backtick. (There is a mirror-image problem with the end-quotes, if they are not self-delimiting. It must be possible, for any given string, to choose an end-quote which (a) isn't in the string, and (b) when appended to the string does not create an earlier instance of itself. Again, having an alphabet of one character Q for the end-quotes means that the string cannot end in Q.) Can an infinite set of strings which are repetitions of a single character be made self-delimiting? Never, since any given member of that set is the proper prefix of some longer member. Making such a set self-delimiting is simple: Add another character, and allow it to be a terminating character for the open-quote. Or, allow the open-quote to include an optional numeric count that determines the length of the rest of the quote. Or, allow the open-quote to have arbitrary (quoted) substructure. (And for each open-quote define a corresponding close-quote. Then given a string, choose the shortest close-quote that does not occur in the string, and which when appended to the string will not create an earlier instance of itself. Begin the quoted string what that close-quote's open-quote.) Supposing that Q is the main quote character and R is a helper (or two or more) which helps size the end-quote. Examples of these three approaches would be: OQ1 = { Q.times(N) + R | N > 0 } OQ2 = { R + String.valueOf(N) + Q.times(N) | N > 0 } OQ3 = { Q + S + R | S in (Universe - R).star() } Such schemes are more powerful, but much harder to describe than what we have now: OQ0 = { Q.times(N) | N > 0, Q = \" } Coming up with these schemes is simple. Coming up with a scheme that feels simple to use seems to be impossible. Tuning and tweaking these schemes is *NOT* a hill-climbing activity that ascends to better and better solutions. Creating self-delimiting string syntaxes is a frustrating exercise in pushing the complexities and corner cases into darker and darker holes. We settled on OQ0 (alphabet of one character) because it is simple and easy to understand. We looked carefully at other OQ schemes and did not find that their specification and learning complexity was paid for by removing the practical complexity of encoding a few odd-looking strings. OQ1, etc., have their own sharp edges which we think users will run into more often than they will run into the sharp edges of OQ0. Trying to "fix" OQ0 just makes it messier, like rubbing your finger over that single speck of lint on the lens of your new binoculars. ? John -------------- next part -------------- An HTML attachment was scrubbed... URL: From cay.horstmann at sjsu.edu Mon Nov 26 09:05:35 2018 From: cay.horstmann at sjsu.edu (Cay Horstmann) Date: Mon, 26 Nov 2018 10:05:35 +0100 Subject: Raw strings starting/ending with backtick In-Reply-To: <6640C0C9-A6C4-4069-93B0-1175F67E7B67@oracle.com> References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> <8de4159c-2ac8-c6d4-9e0e-7a23fc782c4e@gmail.com> <6640C0C9-A6C4-4069-93B0-1175F67E7B67@oracle.com> Message-ID: Le 26/11/2018 ? 08:28, John Rose a ?crit?: > On Nov 24, 2018, at 11:39 PM, Cay Horstmann > wrote: >> >> I agree that it is inelegant that there is no good syntax for raw >> strings starting with a backtick. Some time ago >> (http://horstmann.com/unblog/2018-06-01), I suggested that an initial >> newline after the backticks could count as part of the raw string >> delimiter: >> >> ?????String myNameInABox = ``` >> +-----+ >> | Cay | >> +-----+```; // This string starts with + >> >> Ok, maybe it's not brilliant, but it solves two problems: (1) how to >> format multiline strings that should be aligned, without having to >> strip out the initial newline (2) how to declare strings that start >> with a backtick. > > The basic reality here is that we are trying to keep the quotes as > simple as possible, > while allowing them to quote anything at all, including their shorter > siblings. > A close-quote can't both appear in a string and end that string for > obvious reasons. > > Result: ?There must be an infinite set of close-quotes available, so > that even if a > string has the first N-1 close-quotes inside it, it can be terminated > with the Nth one. > This also implies there must be a corresponding infinite set of open-quotes. > (Opens and closes can be pairwise identical, as in the proposed feature.) > > Next, we have the problem of designing a set of open quotes which can > be differentiated from each other before the string body proper is scanned. > (You have to determine the close-quote before scanning the string body.) > > This really means that open-quotes must be self-delimiting, or else that > there are some substrings that are forbidden to follow at least some > open-quotes. ?If an open-quote syntax is not fully self-delimiting, there > are two open-quotes Q, QR for which Q is a proper prefix of QR. ?In this > case, a quoted string body cannot begin with R and be quoted with Q. > > In the present case, we allow the open-quotes to be composed of an > alphabet of only one letter, the backtick, but allow any positive number > of them. ?That's pretty good (and really,?really simple) but it does have > the observed defect, that none of the open-quotes are self-delimiting, > because for any N>0, "`".times(N) is a proper prefix of the next open-quote, > "`".times(N+1). ?Thus, for no open-quote (in the present scheme) can > the string body begin with backtick. > > (There is a mirror-image problem with the end-quotes, if they are > not self-delimiting. ?It must be possible, for any given string, to > choose an end-quote which (a) isn't in the string, and (b) when > appended to the string does not create an earlier instance of itself. > Again, having an alphabet of one character Q for the end-quotes > means that the string cannot end in Q.) > > Can an infinite set of strings which are repetitions of a single character > be made self-delimiting? ?Never, since any given member of that set > is the proper prefix of some longer member. > > Making such a set self-delimiting is simple: ?Add another character, > and allow it to be a terminating character for the open-quote. > Or, allow the open-quote to include an optional numeric count > that determines the length of the rest of the quote. ?Or, allow > the open-quote to have arbitrary (quoted) substructure. > > (And for each open-quote define a corresponding close-quote. > Then given a string, choose the shortest close-quote that does not > occur in the string, and which when appended to the string will > not create an earlier instance of itself. ?Begin the quoted string > what that close-quote's open-quote.) > > Supposing that Q is the main quote character and R is a helper > (or two or more) which helps size the end-quote. ?Examples of > these three approaches would be: > > ? OQ1 = { Q.times(N) + R | N > 0 } > ? OQ2 = { R + String.valueOf(N) + Q.times(N) | N > 0 } > ? OQ3 = { Q + S + R | S in (Universe - R).star() } > > Such schemes are more powerful, but much harder to describe than > what we have now: > > ? OQ0 = { Q.times(N) | N > 0, Q = \" } > > Coming up with these schemes is simple. ?Coming up with a scheme > that feels simple to use seems to be impossible. ?Tuning and tweaking > these schemes is *NOT* a hill-climbing activity that ascends to better > and better solutions. ?Creating self-delimiting string syntaxes is a > frustrating exercise in pushing the complexities and corner cases > into darker and darker holes. > > We settled on OQ0 (alphabet of one character) because it is simple > and easy to understand. ?We looked carefully at other OQ schemes > and did not find that their specification and learning complexity > was paid for by removing the practical complexity of encoding a > few odd-looking strings. ?OQ1, etc., have their own sharp edges > which we think users will run into more often than they will run > into the sharp edges of OQ0. ?Trying to "fix" OQ0 just makes it > messier, like rubbing your finger over that single speck of lint on the > lens of your new binoculars. > > ? John Hi John, the scheme that I suggest would, in your notation be an OQ1 scheme, with Q = '\'' and R = '\n', quoting any string s as n * Q + R + s + n * Q, with sufficiently large n. Do you recall what sharp edges one would run into? It's not intuitive to me and it would be good to learn from your experience. Cheers, Cay -- Cay S. Horstmann | http://horstmann.com | mailto:cay at horstmann.com From john.r.rose at oracle.com Mon Nov 26 09:20:27 2018 From: john.r.rose at oracle.com (John Rose) Date: Mon, 26 Nov 2018 01:20:27 -0800 Subject: Raw strings starting/ending with backtick In-Reply-To: References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> <8de4159c-2ac8-c6d4-9e0e-7a23fc782c4e@gmail.com> <6640C0C9-A6C4-4069-93B0-1175F67E7B67@oracle.com> Message-ID: <6A6D6000-0358-4875-A73F-F22A93D4BEC9@oracle.com> On Nov 26, 2018, at 1:05 AM, Cay Horstmann wrote: > > the scheme that I suggest would, in your notation be an OQ1 scheme, with Q = '\'' and R = '\n', quoting any string s as n * Q + R + s + n * Q, with sufficiently large n. Do you recall what sharp edges one would run into? It's not intuitive to me and it would be good to learn from your experience. Having backtick-with-whitespace as an option besides backtick-alone basically introduces two new quoting conventions. Also, the choice of whitespace is tricky to use in syntax because whitespace displays ambiguously. I'm sympathetic to using whitespace for R since it seems to make the two quoting conventions so similar that they are seemingly just one, with an optional tweak. But the whitespace has downsides too: Making a quoting convention depend on details of whitespace is asking for puzzlers. There are joke computer languages which depend on the distinction between O and 0, or space and tab; we don't want to be like that. 1. You'd want to use R ~ /\s*\n/ since there's no visual difference between that pattern and a simple /\n/. 2. The close quote would have to contain R somewhere also, which leads to possible near-misses if the Q's are there and the R isn't. Again, having R be next to invisible (whitespace) makes it harder to find a bug if it happens. 3. After the R, you surely want the ability to strip some horizontal space also. We are adding an intrinsic "align" method to handle this. My point is that mandating a newline causes new problems: The user then is required to manage horizontal space on the new line. 4. The design of the close-quote has similar sharp edges. Making R = '|' or some other printing character, and the close-quote be RQ*, would cause fewer problems with whitespace-related format. But it would also in effect introduce a second quoting convention. -------------- next part -------------- An HTML attachment was scrubbed... URL: From cay.horstmann at sjsu.edu Mon Nov 26 09:44:50 2018 From: cay.horstmann at sjsu.edu (Cay Horstmann) Date: Mon, 26 Nov 2018 10:44:50 +0100 Subject: Raw strings starting/ending with backtick In-Reply-To: <6A6D6000-0358-4875-A73F-F22A93D4BEC9@oracle.com> References: <270196DB-4C24-49C5-982C-221FBE5BA464@oracle.com> <6C2BC051-F675-4D85-A140-2061FCAD2166@oracle.com> <8de4159c-2ac8-c6d4-9e0e-7a23fc782c4e@gmail.com> <6640C0C9-A6C4-4069-93B0-1175F67E7B67@oracle.com> <6A6D6000-0358-4875-A73F-F22A93D4BEC9@oracle.com> Message-ID: Le 26/11/2018 ? 10:20, John Rose a ?crit?: > On Nov 26, 2018, at 1:05 AM, Cay Horstmann > wrote: >> >> the scheme that I suggest would, in your notation be an OQ1 scheme, >> with Q = '\'' and R = '\n', quoting any string s as n * Q + R + s + n >> * Q, with sufficiently large n. Do you recall what sharp edges one >> would run into? It's not intuitive to me and it would be good to learn >> from your experience. > > Having backtick-with-whitespace as an option besides backtick-alone > basically introduces two new quoting conventions. > > Also, the choice of whitespace is tricky to use in syntax because whitespace > displays ambiguously. ?I'm sympathetic to using whitespace for R since it > seems to make the two quoting conventions so similar that they are seemingly > just one, with an optional tweak. ?But the whitespace has downsides too: > Making a quoting convention depend on details of whitespace is asking for > puzzlers. ?There are joke computer languages which depend on the distinction > between O and 0, or space and tab; we don't want to be like that. > > 1. You'd want to use R ~ /\s*\n/ since there's no visual difference between > that pattern and a simple /\n/. Yes. > 2. The close quote would have to contain R somewhere also, which leads > to possible near-misses if the Q's are there and the R isn't. ?Again, having > R be next to invisible (whitespace) makes it harder to find a bug if it > happens. No, that was not what I intended. Any sequence m * Q, where m ? n, would close, with (m - n) * Q belonging to s. I thought that was how it had to be. How else can you parse raw strings ending in backticks? But I just realized that is not how it works in 12-ea. I misunderstood how your closing quotes work. Would it be hard on the parser to do it my way? > 3. After the R, you surely want the ability to strip some horizontal > space also. No. > We are adding an intrinsic "align" method to handle this. ?My point is that > mandating a newline causes new problems: ?The user then is required > to manage horizontal space on the new line. I am aware of the "align" methods. Now those have sharp edges. Of course aligning problems can be avoided by placing the string at the leftmost column, like I have done in my example. This is why R = /\s*\n/ is a good choice. > 4. The design of the close-quote has similar sharp edges. > > Making R = '|' or some other printing character, and the close-quote be RQ*, > would cause fewer problems with whitespace-related format. ?But it would > also > in effect introduce a second quoting convention. See above. Cheers, Cay -- Cay S. Horstmann | http://horstmann.com | mailto:cay at horstmann.com From alex.buckley at oracle.com Mon Nov 26 21:44:01 2018 From: alex.buckley at oracle.com (Alex Buckley) Date: Mon, 26 Nov 2018 13:44:01 -0800 Subject: Where do empty compilation units belong? In-Reply-To: References: Message-ID: <5BFC6921.70102@oracle.com> // Adding compiler-dev since the parsing of files into compilation units is not a Jigsaw issue. On 11/20/2018 9:14 PM, Jayaprakash Artanareeswaran wrote: > "jigsaw-dev" wrote on 21/11/2018 > 01:56:42 AM: > > Jon points out that `OrdinaryCompilationUnit` will match an empty stream > > of tokens (I dislike the syntax-driven optionality here, but it's > > longstanding) so the file D.java could be regarded as a compilation unit > > with no package declaration, no import declarations, and no type > > declarations. > > > > Per JLS 7.4.2, such a compilation unit is in an unnamed package, and > > must be associated with an unnamed module. > > > > I would prefer 7.4.2 to say only that a compilation unit with no package > > declarations _and at least one type declaration_ is in an unnamed > > package (and must be associated with an unnamed module; 7.3 should > > enumerate that possibility). A compilation unit with no package > > declarations _and no type declarations_ would be deemed unobservable by > > 7.3, and all these questions about what to do with empty files would > > disappear. > > That would be perfect and make things unambiguous. But for now, the > paragraph above is good enough for me. Unfortunately, import declarations can have side effects (compile-time errors) so to be sure that the "no package or type decl === unobservable" rule is suitable for a file containing just an import decl, we would have to do a case analysis of how javac and ecj handle the eight combinations of the three parts allowed in an ordinary compilation unit. That's overkill for the situation involving empty files that keeps coming up and that I really want to clarify. I don't think anyone loves that an ordinary compilation unit matches the empty stream, so let's define away that scenario. As Jon said, an empty file doesn't present anything to be checked; there is no compilation unit there, so let's be unambiguous about that. We can rule out the empty stream in 7.3 with grammar or with semantics. Usually a semantic description is clearest (gives everyone the proper terminology and concepts) but in this case we don't want the description to wrestle with "consists of one, two, or three parts" when the grammar allows zero. So, a new grammatical description is appropriate, and straightforward: OrdinaryCompilationUnit: PackageDeclaration {ImportDeclaration} {TypeDeclaration} ImportDeclaration {ImportDeclaration} {TypeDeclaration} TypeDeclaration {TypeDeclaration} The "three parts, each of which is optional" description is still accurate. The package decl part is optional (as long as you have the import decls part and/or the type decls part); the import decls part is optional (as long as you have either the package decl part or ...) ... you get the picture. I would leave 7.4.2 alone; an ordinary compilation unit with no package or type decls but with import decls is part of the unnamed package (and thus unnamed module) as before, and compilers can handle that, I think. Any comments? Alex From jonathan.gibbons at oracle.com Mon Nov 26 23:22:53 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Mon, 26 Nov 2018 15:22:53 -0800 Subject: Where do empty compilation units belong? In-Reply-To: <5BFC6921.70102@oracle.com> References: <5BFC6921.70102@oracle.com> Message-ID: <8884f6e3-98c9-f84a-8e79-f719b70854b6@oracle.com> On 11/26/2018 01:44 PM, Alex Buckley wrote: > // Adding compiler-dev since the parsing of files into compilation > units is not a Jigsaw issue. > > On 11/20/2018 9:14 PM, Jayaprakash Artanareeswaran wrote: >> "jigsaw-dev" wrote on 21/11/2018 >> 01:56:42 AM: >> ?> Jon points out that `OrdinaryCompilationUnit` will match an empty >> stream >> ?> of tokens (I dislike the syntax-driven optionality here, but it's >> ?> longstanding) so the file D.java could be regarded as a >> compilation unit >> ?> with no package declaration, no import declarations, and no type >> ?> declarations. >> ?> >> ?> Per JLS 7.4.2, such a compilation unit is in an unnamed package, and >> ?> must be associated with an unnamed module. >> ?> >> ?> I would prefer 7.4.2 to say only that a compilation unit with no >> package >> ?> declarations _and at least one type declaration_ is in an unnamed >> ?> package (and must be associated with an unnamed module; 7.3 should >> ?> enumerate that possibility). A compilation unit with no package >> ?> declarations _and no type declarations_ would be deemed >> unobservable by >> ?> 7.3, and all these questions about what to do with empty files would >> ?> disappear. >> >> That would be perfect and make things unambiguous. But for now, the >> paragraph above is good enough for me. > > Unfortunately, import declarations can have side effects (compile-time > errors) so to be sure that the "no package or type decl === > unobservable" rule is suitable for a file containing just an import > decl, we would have to do a case analysis of how javac and ecj handle > the eight combinations of the three parts allowed in an ordinary > compilation unit. That's overkill for the situation involving empty > files that keeps coming up and that I really want to clarify. I don't > think anyone loves that an ordinary compilation unit matches the empty > stream, so let's define away that scenario. As Jon said, an empty file > doesn't present anything to be checked; there is no compilation unit > there, so let's be unambiguous about that. > > We can rule out the empty stream in 7.3 with grammar or with > semantics. Usually a semantic description is clearest (gives everyone > the proper terminology and concepts) but in this case we don't want > the description to wrestle with "consists of one, two, or three parts" > when the grammar allows zero. So, a new grammatical description is > appropriate, and straightforward: > > ? OrdinaryCompilationUnit: > ??? PackageDeclaration {ImportDeclaration} {TypeDeclaration} > ??? ImportDeclaration {ImportDeclaration} {TypeDeclaration} > ??? TypeDeclaration {TypeDeclaration} > > The "three parts, each of which is optional" description is still > accurate. The package decl part is optional (as long as you have the > import decls part and/or the type decls part); the import decls part > is optional (as long as you have either the package decl part or ...) > ... you get the picture. > > I would leave 7.4.2 alone; an ordinary compilation unit with no > package or type decls but with import decls is part of the unnamed > package (and thus unnamed module) as before, and compilers can handle > that, I think. > > Any comments? > > Alex That seems good to me. To summarize the javac behavior ... * javac accepts/ignores an empty file * javac treats import-only compilation units as in the unnamed package, which is not allowed in a named module * javac enforces file naming constraints when declaring a public class * javac uses file naming constraints when looking on the (module) source path for a file for a class Attached is a toy class to generate combinations of package, import and type declarations. You can use the source-launcher feature to run it. -- Jon -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Test.java Type: text/x-java Size: 1851 bytes Desc: not available URL: From vicente.romero at oracle.com Tue Nov 27 03:51:01 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Mon, 26 Nov 2018 22:51:01 -0500 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body In-Reply-To: <4b501147-6f9b-fe3c-3607-dcc312c5c09a@oracle.com> References: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> <55121cfa-2b40-0f59-089c-cce57235eb91@oracle.com> <5a8f97e4-8eb2-d24e-8241-d6d57d36ff3d@oracle.com> <4b501147-6f9b-fe3c-3607-dcc312c5c09a@oracle.com> Message-ID: On 11/20/18 6:54 AM, Maurizio Cimadamore wrote: > > Looks good - why is there a new change in the test? > good catch, I didn't think much about this but you are correct that at first glance the particular test case compiled in the test TestGetScopeResult shouldn't trigger the code in the patch. We are talking about this case: class Test { ??? void test() { ??????? cand((t, var s) -> ""); ??? } ??? void cand(I i) {} ??? interface I { ??????? public String test(String s); ??? } } which fails during the parser phase so it shouldn't exercise the new code added in this patch. But the test TestGetScopeResult forces the attribution of the test above when it does: ??? ... ??? Scope scope = Trees.instance(t).getScope(new TreePath(getCurrentPath(), node.getBody())); ??? ... and then we have the following invocation chain: JavacTrees::getScope -> JavacTrees::getAttrContext -> JavacTrees::attribStatToTree -> Attr::attribStatToTree which finally forces the attribution of the lambda and thus the execution of the new code. Thanks, Vicente > Maurizio > > On 19/11/2018 20:57, Vicente Romero wrote: >> Hi Maurizio, >> >> On 11/9/18 5:57 AM, Maurizio Cimadamore wrote: >>> >>> Looks good - can we cook up a test that is also stressing the other >>> new code path? >>> >> >> what about: http://cr.openjdk.java.net/~vromero/8203277/webrev.02/? >> >>> Maurizio >>> >> >> Thanks, >> Vicente >> >>> On 09/11/2018 00:12, Vicente Romero wrote: >>>> >>>> >>>> On 11/8/18 6:02 PM, Maurizio Cimadamore wrote: >>>>> >>>>> Hi, >>>>> I agree that preflow shouldn't care about nested constructs; but I >>>>> wonder - is diamond anon class the only case we need to worry >>>>> about here? What about a nested lambda expression? >>>>> >>>> >>>> right I agree with you, what about [3]? >>>> >>>>> Maurizio >>>>> >>>> Vicente >>>> >>>> [3] http://cr.openjdk.java.net/~vromero/8203277/webrev.01/ >>>>> >>>>> On 08/11/2018 00:24, Vicente Romero wrote: >>>>>> Please review the fix for [1] at [2]. The bug can be illustrated >>>>>> with this test case: >>>>>> >>>>>> import java.util.List; >>>>>> import java.util.function.Function; >>>>>> >>>>>> class DiamondInsideLambdaTest { >>>>>> ??? void build() { >>>>>> ??????? List> list = transform(null, >>>>>> ??????????????? builder -> new Function<>() { >>>>>> ??????????????????? public Double apply(String params) { return >>>>>> null; } >>>>>> ??????????????? }); >>>>>> ??? } >>>>>> >>>>>> ??? static List >>>>>> transform(List fromList, Function>>>>> extends Result> function) { return null; } >>>>>> } >>>>>> >>>>>> During lambda attribution, there is a preflow visitor that fill >>>>>> some holes, missing types / symbols, before doing an special flow >>>>>> analysis on the lambda. This flow analysis skip inner classes >>>>>> defined inside the lambda body. The preflow visitor is anyway >>>>>> visiting inner classes and filling, with garbage, some of the >>>>>> wholes. In most cases as the preflow step happens after the >>>>>> lambda body has been attributed, it should be a no-op. But if the >>>>>> lambda body contains a diamond as in this case, then it could be >>>>>> that the attribution can't be done previous to the preflow step. >>>>>> Simply because some types in the diamond could be waiting for >>>>>> type inference to come to a resolution. In that case preflow will >>>>>> modify the diamond expression and later on during completion, as >>>>>> some symbols and types are filled with erroneous types, they will >>>>>> keep that erroneous type. >>>>>> >>>>>> [1] https://bugs.openjdk.java.net/browse/JDK-8203277 >>>>>> [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ >>>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Tue Nov 27 10:26:03 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 27 Nov 2018 10:26:03 +0000 Subject: RFR: JDK-8203277: preflow visitor used during lambda attribution shouldn't visit class definitions inside the lambda body In-Reply-To: References: <0354d9ae-fc0f-7dd2-73e5-86777eed0670@oracle.com> <55121cfa-2b40-0f59-089c-cce57235eb91@oracle.com> <5a8f97e4-8eb2-d24e-8241-d6d57d36ff3d@oracle.com> <4b501147-6f9b-fe3c-3607-dcc312c5c09a@oracle.com> Message-ID: <4dadb424-f441-e9b1-fe90-e56bedc1abb2@oracle.com> I see looks good, thanks for the explanation. Maurizio On 27/11/2018 03:51, Vicente Romero wrote: > > > On 11/20/18 6:54 AM, Maurizio Cimadamore wrote: >> >> Looks good - why is there a new change in the test? >> > > good catch, I didn't think much about this but you are correct that at > first glance the particular test case compiled in the test > TestGetScopeResult shouldn't trigger the code in the patch. We are > talking about this case: > > class Test { > ??? void test() { > ??????? cand((t, var s) -> ""); > ??? } > ??? void cand(I i) {} > > ??? interface I { > ??????? public String test(String s); > ??? } > } > > which fails during the parser phase so it shouldn't exercise the new > code added in this patch. But the test TestGetScopeResult forces the > attribution of the test above when it does: > > ??? ... > ??? Scope scope = Trees.instance(t).getScope(new > TreePath(getCurrentPath(), node.getBody())); > ??? ... > > and then we have the following invocation chain: > > JavacTrees::getScope -> JavacTrees::getAttrContext -> > JavacTrees::attribStatToTree -> Attr::attribStatToTree > > which finally forces the attribution of the lambda and thus the > execution of the new code. > > Thanks, > Vicente > >> Maurizio >> >> On 19/11/2018 20:57, Vicente Romero wrote: >>> Hi Maurizio, >>> >>> On 11/9/18 5:57 AM, Maurizio Cimadamore wrote: >>>> >>>> Looks good - can we cook up a test that is also stressing the other >>>> new code path? >>>> >>> >>> what about: http://cr.openjdk.java.net/~vromero/8203277/webrev.02/? >>> >>>> Maurizio >>>> >>> >>> Thanks, >>> Vicente >>> >>>> On 09/11/2018 00:12, Vicente Romero wrote: >>>>> >>>>> >>>>> On 11/8/18 6:02 PM, Maurizio Cimadamore wrote: >>>>>> >>>>>> Hi, >>>>>> I agree that preflow shouldn't care about nested constructs; but >>>>>> I wonder - is diamond anon class the only case we need to worry >>>>>> about here? What about a nested lambda expression? >>>>>> >>>>> >>>>> right I agree with you, what about [3]? >>>>> >>>>>> Maurizio >>>>>> >>>>> Vicente >>>>> >>>>> [3] http://cr.openjdk.java.net/~vromero/8203277/webrev.01/ >>>>>> >>>>>> On 08/11/2018 00:24, Vicente Romero wrote: >>>>>>> Please review the fix for [1] at [2]. The bug can be illustrated >>>>>>> with this test case: >>>>>>> >>>>>>> import java.util.List; >>>>>>> import java.util.function.Function; >>>>>>> >>>>>>> class DiamondInsideLambdaTest { >>>>>>> ??? void build() { >>>>>>> ??????? List> list = transform(null, >>>>>>> ??????????????? builder -> new Function<>() { >>>>>>> ??????????????????? public Double apply(String params) { return >>>>>>> null; } >>>>>>> ??????????????? }); >>>>>>> ??? } >>>>>>> >>>>>>> ??? static List >>>>>>> transform(List fromList, Function>>>>>> extends Result> function) { return null; } >>>>>>> } >>>>>>> >>>>>>> During lambda attribution, there is a preflow visitor that fill >>>>>>> some holes, missing types / symbols, before doing an special >>>>>>> flow analysis on the lambda. This flow analysis skip inner >>>>>>> classes defined inside the lambda body. The preflow visitor is >>>>>>> anyway visiting inner classes and filling, with garbage, some of >>>>>>> the wholes. In most cases as the preflow step happens after the >>>>>>> lambda body has been attributed, it should be a no-op. But if >>>>>>> the lambda body contains a diamond as in this case, then it >>>>>>> could be that the attribution can't be done previous to the >>>>>>> preflow step. Simply because some types in the diamond could be >>>>>>> waiting for type inference to come to a resolution. In that case >>>>>>> preflow will modify the diamond expression and later on during >>>>>>> completion, as some symbols and types are filled with erroneous >>>>>>> types, they will keep that erroneous type. >>>>>>> >>>>>>> [1] https://bugs.openjdk.java.net/browse/JDK-8203277 >>>>>>> [2] http://cr.openjdk.java.net/~vromero/8203277/webrev.00/ >>>>> >>> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.lahoda at oracle.com Tue Nov 27 20:21:56 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 27 Nov 2018 21:21:56 +0100 Subject: RFR; JDK-8214031: Assertion error in value break statement with conditional operator in switch expression Message-ID: <5BFDA764.2070509@oracle.com> Hi, javac does not handle switch expressions that return booleans correctly. According to the spec, javac should track definite [un]assignment when true/false for switch expressions, but fails to do so. Moreover, for more complex code, like: int v = ...; int x; boolean b = switch (v) { case 0: x = 12; break true; case 1: x = 13; break true; default: break false; } && x == 12; The current switch expression desugaring is not powerful enough to generate valid bytecode for this input. The issue is that the current desugaring will translate the switch expression into code like: ( boolean $result; switch (v) { case 0: x = 12; $result = true; break; case 1: x = 13; $result = true; break; default: $result = false; break; } $result //"return" expression ) && x == 12 But by assigning the true/false result to a variable, we are loosing track of which variables are assigned (when true/false) and which are not. The bytecode needs to ensure the "x == 12" is jumped over when the switch expression's value is false, and that, I believe, is not possible when desugaring in Lower. So, the proposed fix is to avoid desugaring in Lower, letting switch expressions go to Gen and produce bytecode for them, including handling them in Gen.genCond for true/false switch expressions. This is mostly modelled after the conditional expression handling. Some generalizations in Lower are required as well, to handle String and enum switch expressions. Handling of definite assignment in Flow is fixed as well. JBS: https://bugs.openjdk.java.net/browse/JDK-8214031 Webrev: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.00/ Any feedback is welcome! Thanks, Jan From joe.darcy at oracle.com Tue Nov 27 20:33:30 2018 From: joe.darcy at oracle.com (joe darcy) Date: Tue, 27 Nov 2018 12:33:30 -0800 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods Message-ID: Hello, Re-visiting this refactoring, please review the changes for ??? JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods ??? http://cr.openjdk.java.net/~darcy/8146726.1/ Patch below; all langtools regression tests pass with the change. Note that by the contract of AnnotatedElement, is is okay to modify the contents of a returned array. Therefore, it is acceptable to remove the array clone step. Thanks, -Joe --- old/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java 2018-11-27 12:29:00.618001000 -0800 +++ new/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java 2018-11-27 12:29:00.250001000 -0800 @@ -1,5 +1,5 @@ ?/* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. ? * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ? * ? * This code is free software; you can redistribute it and/or modify it @@ -80,10 +80,7 @@ ????? */ ???? public Set getSupportedOptions() { ???????? SupportedOptions so = this.getClass().getAnnotation(SupportedOptions.class); -??????? if? (so == null) -??????????? return Collections.emptySet(); -??????? else -??????????? return arrayToSet(so.value(), false); +??? return (so == null) ? Collections.emptySet() : Set.of(so.value()); ???? } ???? /** @@ -115,7 +112,17 @@ ???????????????? boolean stripModulePrefixes = ???????????????????????? initialized && processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0; -??????????????? return arrayToSet(sat.value(), stripModulePrefixes); + +??? ??? String[] supportedAnnotTypes = sat.value(); +??? ??? if (stripModulePrefixes) { +??? ??? ??? for (int i = 0; i < supportedAnnotTypes.length; i++) { +??? ??? ??? String s = supportedAnnotTypes[i]; +??? ??? ??? int index = s.indexOf('/'); +??? ??? ??? if (index != -1) +??? ??? ??? ??? supportedAnnotTypes[i] = s.substring(index + 1); +??? ??? ??? } +??? ??? } +??? ??? return Set.of(supportedAnnotTypes); ???????????? } ???????? } @@ -194,19 +201,4 @@ ???? protected synchronized boolean isInitialized() { ???????? return initialized; ???? } - -??? private static Set arrayToSet(String[] array, -????????????????????????????????????????? boolean stripModulePrefixes) { -??????? assert array != null; -??????? Set set = new HashSet<>(array.length); -??????? for (String s : array) { -??????????? if (stripModulePrefixes) { -??????????????? int index = s.indexOf('/'); -??????????????? if (index != -1) -??????????????????? s = s.substring(index + 1); -??????????? } -??????????? set.add(s); -??????? } -??????? return Collections.unmodifiableSet(set); -??? } ?} From jonathan.gibbons at oracle.com Tue Nov 27 20:51:57 2018 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 27 Nov 2018 12:51:57 -0800 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods In-Reply-To: References: Message-ID: Looks OK to me -- Jon On 11/27/2018 12:33 PM, joe darcy wrote: > Hello, > > Re-visiting this refactoring, please review the changes for > > ??? JDK-8146726 : Refactor AbstractProcessor to use Set.of and related > methods > ??? http://cr.openjdk.java.net/~darcy/8146726.1/ > > Patch below; all langtools regression tests pass with the change. > > Note that by the contract of AnnotatedElement, is is okay to modify > the contents of a returned array. Therefore, it is acceptable to > remove the array clone step. > > Thanks, > > -Joe > > --- > old/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java > 2018-11-27 12:29:00.618001000 -0800 > +++ > new/src/java.compiler/share/classes/javax/annotation/processing/AbstractProcessor.java > 2018-11-27 12:29:00.250001000 -0800 > @@ -1,5 +1,5 @@ > ?/* > - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights > reserved. > + * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights > reserved. > ? * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. > ? * > ? * This code is free software; you can redistribute it and/or modify it > @@ -80,10 +80,7 @@ > ????? */ > ???? public Set getSupportedOptions() { > ???????? SupportedOptions so = > this.getClass().getAnnotation(SupportedOptions.class); > -??????? if? (so == null) > -??????????? return Collections.emptySet(); > -??????? else > -??????????? return arrayToSet(so.value(), false); > +??? return (so == null) ? Collections.emptySet() : Set.of(so.value()); > ???? } > > ???? /** > @@ -115,7 +112,17 @@ > ???????????????? boolean stripModulePrefixes = > ???????????????????????? initialized && > processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0; > -??????????????? return arrayToSet(sat.value(), stripModulePrefixes); > + > +??? ??? String[] supportedAnnotTypes = sat.value(); > +??? ??? if (stripModulePrefixes) { > +??? ??? ??? for (int i = 0; i < supportedAnnotTypes.length; i++) { > +??? ??? ??? String s = supportedAnnotTypes[i]; > +??? ??? ??? int index = s.indexOf('/'); > +??? ??? ??? if (index != -1) > +??? ??? ??? ??? supportedAnnotTypes[i] = s.substring(index + 1); > +??? ??? ??? } > +??? ??? } > +??? ??? return Set.of(supportedAnnotTypes); > ???????????? } > ???????? } > > @@ -194,19 +201,4 @@ > ???? protected synchronized boolean isInitialized() { > ???????? return initialized; > ???? } > - > -??? private static Set arrayToSet(String[] array, > -????????????????????????????????????????? boolean stripModulePrefixes) { > -??????? assert array != null; > -??????? Set set = new HashSet<>(array.length); > -??????? for (String s : array) { > -??????????? if (stripModulePrefixes) { > -??????????????? int index = s.indexOf('/'); > -??????????????? if (index != -1) > -??????????????????? s = s.substring(index + 1); > -??????????? } > -??????????? set.add(s); > -??????? } > -??????? return Collections.unmodifiableSet(set); > -??? } > ?} > > From Sergey.Bylokhov at oracle.com Tue Nov 27 21:07:54 2018 From: Sergey.Bylokhov at oracle.com (Sergey Bylokhov) Date: Tue, 27 Nov 2018 13:07:54 -0800 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods In-Reply-To: References: Message-ID: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> Hi, Joe. > Collections.emptySet() : Just curious why "Collections.emptySet()" is used instead of "Set.of()"? -- Best regards, Sergey. From ronshapiro at google.com Tue Nov 27 21:23:46 2018 From: ronshapiro at google.com (Ron Shapiro) Date: Tue, 27 Nov 2018 16:23:46 -0500 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods In-Reply-To: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> References: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> Message-ID: Set.of() throws if there are duplicate elements - but arrayToSet() didn't do so. Is it intended to throw if either of these take duplicates? On Tue, Nov 27, 2018 at 4:08 PM Sergey Bylokhov wrote: > Hi, Joe. > > > Collections.emptySet() : > Just curious why "Collections.emptySet()" is used instead of "Set.of()"? > > > -- > Best regards, Sergey. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Wed Nov 28 12:12:46 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 28 Nov 2018 12:12:46 +0000 Subject: RFR; JDK-8214031: Assertion error in value break statement with conditional operator in switch expression In-Reply-To: <5BFDA764.2070509@oracle.com> References: <5BFDA764.2070509@oracle.com> Message-ID: <35c7dd4e-45f5-0ed4-37d7-cc1ce36b1bb3@oracle.com> Hi Jan, the patch looks very good and, albeit complex, I don't think there's another way to implement shortcircuiting of boolean switch expression w/o going deep in Gen (which is what this patch does). So well done. From a code perspective I have only minor comments, as the code is generally well done: 1) In Flow, since now you are making AssignAnalyzer also extends from BaseAnalyzer (used to be BaseAnalyzer), I think there is no need now for having a type parameter in BaseAnalyzer. Let all exits be PendingExit - then subclasses can come up with variants (like AssignExit) when needed. But it seems like the 1-1 relationship between analyzer type and exit type is gone and the code should probably be more upfront about that. 2) The valueBreakHandler abstraction in Gen is nice, but I wonder if the code would be clearer by encoding the desired logic directly in visitBreak. That is, visitBreak could fetch the switch expression it points to, and determine whether we are inside a 'cond' or not, and then act accordingly. I think that, with a couple of Gen instance fields (shared trueChain/falseChain), you could be able to get there. Not 100% sure it will make the code better, but I thought it could be worth a try. 3) In the test DefiniteAssignment1.java (and also, but to lesser extent, DefiniteAssignment1.java)? I guess it would also be nice to test some && condition in the break expression - e.g. true && (x = 1) Also, might be worth replacing the true with some other variable which the compiler doesn't know to be true statically (as that affects code generation). Cheers Maurizio On 27/11/2018 20:21, Jan Lahoda wrote: > Hi, > > javac does not handle switch expressions that return booleans > correctly. According to the spec, javac should track definite > [un]assignment when true/false for switch expressions, but fails to do > so. Moreover, for more complex code, like: > > int v = ...; > int x; > boolean b = switch (v) { > ???? case 0: x = 12; break true; > ???? case 1: x = 13; break true; > ???? default: break false; > } && x == 12; > > The current switch expression desugaring is not powerful enough to > generate valid bytecode for this input. The issue is that the current > desugaring will translate the switch expression into code like: > ( > ?boolean $result; > ?switch (v) { > ???? case 0: x = 12; $result = true; break; > ???? case 1: x = 13; $result = true; break; > ???? default: $result = false; break; > ?} > ?$result?? //"return" expression > ) && x == 12 > > But by assigning the true/false result to a variable, we are loosing > track of which variables are assigned (when true/false) and which are > not. The bytecode needs to ensure the "x == 12" is jumped over when > the switch expression's value is false, and that, I believe, is not > possible when desugaring in Lower. > > So, the proposed fix is to avoid desugaring in Lower, letting switch > expressions go to Gen and produce bytecode for them, including > handling them in Gen.genCond for true/false switch expressions. This > is mostly modelled after the conditional expression handling. Some > generalizations in Lower are required as well, to handle String and > enum switch expressions. Handling of definite assignment in Flow is > fixed as well. > > JBS: https://bugs.openjdk.java.net/browse/JDK-8214031 > Webrev: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.00/ > > Any feedback is welcome! > > Thanks, > ?? Jan From vicente.romero at oracle.com Wed Nov 28 16:46:03 2018 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 28 Nov 2018 11:46:03 -0500 Subject: RFR: 8214026: Canonicalized archive paths appearing in diagnostics In-Reply-To: References: Message-ID: <41d31401-3c6a-46be-f989-3b92172436f9@oracle.com> +1 On 11/19/18 8:49 PM, Liam Miller-Cushon wrote: > Hi, > > Please consider this fix for?JDK-8214026, which ensures that jar > archive paths in diagnostics (e.g. for 'bad class file' errors) are > not canonicalized, for consistency with the JDK 8 javac behaviour and > the precedent set by JDK-8181897 and JDK-8178017. > > bug: https://bugs.openjdk.java.net/browse/JDK-8214026 > webrev: http://cr.openjdk.java.net/~cushon/8214026/webrev.00/ From joe.darcy at oracle.com Wed Nov 28 20:04:43 2018 From: joe.darcy at oracle.com (joe darcy) Date: Wed, 28 Nov 2018 12:04:43 -0800 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods In-Reply-To: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> References: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> Message-ID: <4b42daaa-3a6f-6cbb-7b42-1325d5216299@oracle.com> Hi Sergey, On 11/27/2018 1:07 PM, Sergey Bylokhov wrote: > Hi, Joe. > >> Collections.emptySet() : > Just curious why "Collections.emptySet()" is used instead of "Set.of()" I was already using Collections.emptySet() for that case, so I just preserved the code. I check with Stuart and he said either of "Collections.emptySet()" is used instead of "Set.of()" would be acceptable, but thought using "Set.of()" would be more consistent in the situation. I'll revised the webrev accordingly. Thanks, -Joe From joe.darcy at oracle.com Thu Nov 29 02:09:32 2018 From: joe.darcy at oracle.com (joe darcy) Date: Wed, 28 Nov 2018 18:09:32 -0800 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods In-Reply-To: References: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> Message-ID: <2791b744-e158-3edd-e8c3-c38dfb0a6951@oracle.com> Hi Ron, Adding Stuart for a collections consult; Stuart, what is the currently recommended idiom to construct a unmodifiable collection with the same elements as a existing collection? In particular, for a set of Strings is something like ??? Set.of(stringSet(new String[0])) preferred over ??? Collections.unmodifiableSet(stringSet); Assume serialization is not a concern. On 11/27/2018 1:23 PM, Ron Shapiro wrote: > Set.of() throws if there are duplicate elements - but arrayToSet() > didn't do so. Is it intended to throw if either of these take duplicates? > Good catch. After some pondering, I think it is preferable for AbstractProcessor to not treat duplicates as an error, but to issue a warning in if duplicates are found. Arguably, it would have been reasonable to treat such condition as an error initially when the API was introduced, but adding such a check now could have some unnecessary behavioral compatibility impact. The case to add an erroneous check for options is stronger than for supported annotations because supported annotations have some additional processing if modules are not present. In more detail, with modules to fully specify an annotation type, the module name needs to be used: "mod1/foo.bar" vs "mod2/foo.bar". If such a processor is run when modules are not used, then the names are stripped to "foo.bar" in both cases and that should not be treated as an error. Revised webrev: ??? http://cr.openjdk.java.net/~darcy/8146726.3/ Will possibly update based on guidance from Stuart on the collections usage question. Thanks, -Joe From ivan.gerasimov at oracle.com Thu Nov 29 02:52:49 2018 From: ivan.gerasimov at oracle.com (Ivan Gerasimov) Date: Wed, 28 Nov 2018 18:52:49 -0800 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods In-Reply-To: <2791b744-e158-3edd-e8c3-c38dfb0a6951@oracle.com> References: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> <2791b744-e158-3edd-e8c3-c38dfb0a6951@oracle.com> Message-ID: <86d2ef09-ef02-034c-51c6-cee6daf480e0@oracle.com> Hi Joe! In two places the expected numbers of elements is used instead of the initial capacity of a new HashSet: new HashSet<>(values.length); Wouldn't the default initial capacity (i.e. `new HashSet<>()` ) be better choice here, as the number of values is likely to be small and the HashSet is temporary anyway? With kind regards, Ivan On 11/28/18 6:09 PM, joe darcy wrote: > Hi Ron, > > Adding Stuart for a collections consult; Stuart, what is the currently > recommended idiom to construct a unmodifiable collection with the same > elements as a existing collection? In particular, for a set of Strings > is something like > > Set.of(stringSet(new String[0])) > > preferred over > > Collections.unmodifiableSet(stringSet); > > Assume serialization is not a concern. > > On 11/27/2018 1:23 PM, Ron Shapiro wrote: >> Set.of() throws if there are duplicate elements - but arrayToSet() >> didn't do so. Is it intended to throw if either of these take >> duplicates? >> > > Good catch. > > After some pondering, I think it is preferable for AbstractProcessor > to not treat duplicates as an error, but to issue a warning in if > duplicates are found. Arguably, it would have been reasonable to treat > such condition as an error initially when the API was introduced, but > adding such a check now could have some unnecessary behavioral > compatibility impact. The case to add an erroneous check for options > is stronger than for supported annotations because supported > annotations have some additional processing if modules are not > present. In more detail, with modules to fully specify an annotation > type, the module name needs to be used: "mod1/foo.bar" vs > "mod2/foo.bar". If such a processor is run when modules are not used, > then the names are stripped to "foo.bar" in both cases and that should > not be treated as an error. > > Revised webrev: > > http://cr.openjdk.java.net/~darcy/8146726.3/ > > Will possibly update based on guidance from Stuart on the collections > usage question. > > Thanks, > > -Joe > -- With kind regards, Ivan Gerasimov From srikanth.adayapalam at oracle.com Thu Nov 29 05:13:29 2018 From: srikanth.adayapalam at oracle.com (Srikanth) Date: Thu, 29 Nov 2018 10:43:29 +0530 Subject: RFR: JDK-8206325: AssertionError in TypeSymbol.getAnnotationTypeMetadata Message-ID: Hello!, Please review the proposed fix for ??? https://bugs.openjdk.java.net/browse/JDK-8206325 posted at: ??? http://cr.openjdk.java.net/~sadayapalam/JDK-8206325/webrev.00/ Basically various parts of the compiler are ill prepared to handle the scenario where a non-annotation type is treated erroneously as an annotation. The present fix does two things: (a) "drops" the bogus annotation (after suitable errors have been reported) rather than persist in symbols. (b) since (a) is not enough to avoid trouble in all cases, proactive checks to avoid tripping the land mines are also put in place. In the normal course of things, this crash would never be reported to users, since the compiler "swallows" crashes when an error has already been reported - except when annotation processing is on (or when -XDdev is used) Thanks! Srikanth From maurizio.cimadamore at oracle.com Thu Nov 29 10:56:25 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 29 Nov 2018 10:56:25 +0000 Subject: RFR: JDK-8206325: AssertionError in TypeSymbol.getAnnotationTypeMetadata In-Reply-To: References: Message-ID: Looks sensible. Thanks Maurizio On 29/11/2018 05:13, Srikanth wrote: > > Hello!, > > Please review the proposed fix for > > ??? https://bugs.openjdk.java.net/browse/JDK-8206325 > > posted at: > > ??? http://cr.openjdk.java.net/~sadayapalam/JDK-8206325/webrev.00/ > > Basically various parts of the compiler are ill prepared to handle the > scenario where a non-annotation type is treated erroneously as an > annotation. The present fix does two things: (a) "drops" the bogus > annotation (after suitable errors have been reported) rather than > persist in symbols. (b) since (a) is not enough to avoid trouble in > all cases, proactive checks to avoid tripping the land mines are also > put in place. > > In the normal course of things, this crash would never be reported to > users, since the compiler "swallows" crashes when an error has already > been reported - except when annotation processing is on (or when > -XDdev is used) > > Thanks! > Srikanth From jan.lahoda at oracle.com Thu Nov 29 12:42:30 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Thu, 29 Nov 2018 13:42:30 +0100 Subject: RFR; JDK-8214031: Assertion error in value break statement with conditional operator in switch expression In-Reply-To: <35c7dd4e-45f5-0ed4-37d7-cc1ce36b1bb3@oracle.com> References: <5BFDA764.2070509@oracle.com> <35c7dd4e-45f5-0ed4-37d7-cc1ce36b1bb3@oracle.com> Message-ID: <5BFFDEB6.8060603@oracle.com> Hi Maurizio, Thanks for the comments. I'll work on these. Jan On 28.11.2018 13:12, Maurizio Cimadamore wrote: > Hi Jan, > the patch looks very good and, albeit complex, I don't think there's > another way to implement shortcircuiting of boolean switch expression > w/o going deep in Gen (which is what this patch does). So well done. > > From a code perspective I have only minor comments, as the code is > generally well done: > > 1) In Flow, since now you are making AssignAnalyzer also extends from > BaseAnalyzer (used to be BaseAnalyzer), I think > there is no need now for having a type parameter in BaseAnalyzer. Let > all exits be PendingExit - then subclasses can come up with variants > (like AssignExit) when needed. But it seems like the 1-1 relationship > between analyzer type and exit type is gone and the code should probably > be more upfront about that. > > 2) The valueBreakHandler abstraction in Gen is nice, but I wonder if the > code would be clearer by encoding the desired logic directly in > visitBreak. That is, visitBreak could fetch the switch expression it > points to, and determine whether we are inside a 'cond' or not, and then > act accordingly. I think that, with a couple of Gen instance fields > (shared trueChain/falseChain), you could be able to get there. Not 100% > sure it will make the code better, but I thought it could be worth a try. > > 3) In the test DefiniteAssignment1.java (and also, but to lesser extent, > DefiniteAssignment1.java) I guess it would also be nice to test some && > condition in the break expression - e.g. > > true && (x = 1) > > Also, might be worth replacing the true with some other variable which > the compiler doesn't know to be true statically (as that affects code > generation). > > Cheers > Maurizio > > On 27/11/2018 20:21, Jan Lahoda wrote: >> Hi, >> >> javac does not handle switch expressions that return booleans >> correctly. According to the spec, javac should track definite >> [un]assignment when true/false for switch expressions, but fails to do >> so. Moreover, for more complex code, like: >> >> int v = ...; >> int x; >> boolean b = switch (v) { >> case 0: x = 12; break true; >> case 1: x = 13; break true; >> default: break false; >> } && x == 12; >> >> The current switch expression desugaring is not powerful enough to >> generate valid bytecode for this input. The issue is that the current >> desugaring will translate the switch expression into code like: >> ( >> boolean $result; >> switch (v) { >> case 0: x = 12; $result = true; break; >> case 1: x = 13; $result = true; break; >> default: $result = false; break; >> } >> $result //"return" expression >> ) && x == 12 >> >> But by assigning the true/false result to a variable, we are loosing >> track of which variables are assigned (when true/false) and which are >> not. The bytecode needs to ensure the "x == 12" is jumped over when >> the switch expression's value is false, and that, I believe, is not >> possible when desugaring in Lower. >> >> So, the proposed fix is to avoid desugaring in Lower, letting switch >> expressions go to Gen and produce bytecode for them, including >> handling them in Gen.genCond for true/false switch expressions. This >> is mostly modelled after the conditional expression handling. Some >> generalizations in Lower are required as well, to handle String and >> enum switch expressions. Handling of definite assignment in Flow is >> fixed as well. >> >> JBS: https://bugs.openjdk.java.net/browse/JDK-8214031 >> Webrev: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.00/ >> >> Any feedback is welcome! >> >> Thanks, >> Jan From stuart.marks at oracle.com Thu Nov 29 23:05:50 2018 From: stuart.marks at oracle.com (Stuart Marks) Date: Thu, 29 Nov 2018 15:05:50 -0800 Subject: JDK 12 RFR of JDK-8146726 : Refactor AbstractProcessor to use Set.of and related methods In-Reply-To: <2791b744-e158-3edd-e8c3-c38dfb0a6951@oracle.com> References: <3c84d320-278a-87fb-9500-c0bb796419b1@oracle.com> <2791b744-e158-3edd-e8c3-c38dfb0a6951@oracle.com> Message-ID: <61cccc13-fecf-f407-f703-c3c3d2a68618@oracle.com> On 11/28/18 6:09 PM, joe darcy wrote: > Adding Stuart for a collections consult; Stuart, what is the currently > recommended idiom to construct a unmodifiable collection with the same elements > as a existing collection? In particular, for a set of Strings is something like > > ??? Set.of(stringSet(new String[0])) > > preferred over > > ??? Collections.unmodifiableSet(stringSet); > > Assume serialization is not a concern. If the resulting set is intended to be long-lived, then Set.of(...) or Set.copyOf(coll) will make an unmodifiable copy of the source elements. Note that Set.copyOf() [new in JDK 10] will make a set by copying the elements from the source collection, silently compressing out duplicates. This differs from Set.of(...) which as Ron noted will throw if it encounters duplicates. So, a simple way to do what you want is to get the value as a String[], wrap it in a List, and then call Set.copyOf(): return Set.copyOf(Arrays.asList(so.value())); But, see below. > On 11/27/2018 1:23 PM, Ron Shapiro wrote: >> Set.of() throws if there are duplicate elements - but arrayToSet() didn't do >> so. Is it intended to throw if either of these take duplicates? >> > > Good catch. > > After some pondering, I think it is preferable for AbstractProcessor to not > treat duplicates as an error, but to issue a warning in if duplicates are found. > Arguably, it would have been reasonable to treat such condition as an error > initially when the API was introduced, but adding such a check now could have > some unnecessary behavioral compatibility impact. The case to add an erroneous > check for options is stronger than for supported annotations because supported > annotations have some additional processing if modules are not present. In more > detail, with modules to fully specify an annotation type, the module name needs > to be used: "mod1/foo.bar" vs "mod2/foo.bar". If such a processor is run when > modules are not used, then the names are stripped to "foo.bar" in both cases and > that should not be treated as an error. > > Revised webrev: > > ??? http://cr.openjdk.java.net/~darcy/8146726.3/ > > Will possibly update based on guidance from Stuart on the collections usage > question. One question is how explicit you want the error message to be. If you're willing to live with a nonspecific "warning: there are duplicates" you can do Set.copyOf() as I suggested above and then compare the set's size() to the length of the array. If they differ, you know there were duplicates. But you don't know which elements were duplicated. If you want to print the specific options that were duplicated, building up a HashSet and printing a warning whenever add() returns false is a reasonable approach. (There ways to do this using streams but they aren't significantly better for a problem this simple.) Note IvanG's comment about proper sizing of the HashSet. Now, if you're going to be creating a HashSet anyway, as part of deduplicating the options and issuing warnings, and if the caller is going to do something simple (like iterating over it, or just doing a contains check) and throwing it away, then it might not be worth copying the HashSet into a separate unmodifiable set. So maybe just wrapping it in Collections.unmodifiableSet() would be reasonable. Sorry not be conclusive. :-) s'marks From jan.lahoda at oracle.com Fri Nov 30 17:11:52 2018 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Fri, 30 Nov 2018 18:11:52 +0100 Subject: RFR; JDK-8214031: Assertion error in value break statement with conditional operator in switch expression In-Reply-To: <5BFFDEB6.8060603@oracle.com> References: <5BFDA764.2070509@oracle.com> <35c7dd4e-45f5-0ed4-37d7-cc1ce36b1bb3@oracle.com> <5BFFDEB6.8060603@oracle.com> Message-ID: <5C016F58.3060909@oracle.com> Hi, A patch updated according to the comments is here: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.01/ A delta patch from the previous patch is here: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.delta.00.01/ How does this look? Thanks, Jan On 29.11.2018 13:42, Jan Lahoda wrote: > Hi Maurizio, > > Thanks for the comments. I'll work on these. > > Jan > > On 28.11.2018 13:12, Maurizio Cimadamore wrote: >> Hi Jan, >> the patch looks very good and, albeit complex, I don't think there's >> another way to implement shortcircuiting of boolean switch expression >> w/o going deep in Gen (which is what this patch does). So well done. >> >> From a code perspective I have only minor comments, as the code is >> generally well done: >> >> 1) In Flow, since now you are making AssignAnalyzer also extends from >> BaseAnalyzer (used to be BaseAnalyzer), I think >> there is no need now for having a type parameter in BaseAnalyzer. Let >> all exits be PendingExit - then subclasses can come up with variants >> (like AssignExit) when needed. But it seems like the 1-1 relationship >> between analyzer type and exit type is gone and the code should probably >> be more upfront about that. >> >> 2) The valueBreakHandler abstraction in Gen is nice, but I wonder if the >> code would be clearer by encoding the desired logic directly in >> visitBreak. That is, visitBreak could fetch the switch expression it >> points to, and determine whether we are inside a 'cond' or not, and then >> act accordingly. I think that, with a couple of Gen instance fields >> (shared trueChain/falseChain), you could be able to get there. Not 100% >> sure it will make the code better, but I thought it could be worth a try. >> >> 3) In the test DefiniteAssignment1.java (and also, but to lesser extent, >> DefiniteAssignment1.java) I guess it would also be nice to test some && >> condition in the break expression - e.g. >> >> true && (x = 1) >> >> Also, might be worth replacing the true with some other variable which >> the compiler doesn't know to be true statically (as that affects code >> generation). >> >> Cheers >> Maurizio >> >> On 27/11/2018 20:21, Jan Lahoda wrote: >>> Hi, >>> >>> javac does not handle switch expressions that return booleans >>> correctly. According to the spec, javac should track definite >>> [un]assignment when true/false for switch expressions, but fails to do >>> so. Moreover, for more complex code, like: >>> >>> int v = ...; >>> int x; >>> boolean b = switch (v) { >>> case 0: x = 12; break true; >>> case 1: x = 13; break true; >>> default: break false; >>> } && x == 12; >>> >>> The current switch expression desugaring is not powerful enough to >>> generate valid bytecode for this input. The issue is that the current >>> desugaring will translate the switch expression into code like: >>> ( >>> boolean $result; >>> switch (v) { >>> case 0: x = 12; $result = true; break; >>> case 1: x = 13; $result = true; break; >>> default: $result = false; break; >>> } >>> $result //"return" expression >>> ) && x == 12 >>> >>> But by assigning the true/false result to a variable, we are loosing >>> track of which variables are assigned (when true/false) and which are >>> not. The bytecode needs to ensure the "x == 12" is jumped over when >>> the switch expression's value is false, and that, I believe, is not >>> possible when desugaring in Lower. >>> >>> So, the proposed fix is to avoid desugaring in Lower, letting switch >>> expressions go to Gen and produce bytecode for them, including >>> handling them in Gen.genCond for true/false switch expressions. This >>> is mostly modelled after the conditional expression handling. Some >>> generalizations in Lower are required as well, to handle String and >>> enum switch expressions. Handling of definite assignment in Flow is >>> fixed as well. >>> >>> JBS: https://bugs.openjdk.java.net/browse/JDK-8214031 >>> Webrev: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.00/ >>> >>> Any feedback is welcome! >>> >>> Thanks, >>> Jan From maurizio.cimadamore at oracle.com Fri Nov 30 17:53:25 2018 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Fri, 30 Nov 2018 17:53:25 +0000 Subject: RFR; JDK-8214031: Assertion error in value break statement with conditional operator in switch expression In-Reply-To: <5C016F58.3060909@oracle.com> References: <5BFDA764.2070509@oracle.com> <35c7dd4e-45f5-0ed4-37d7-cc1ce36b1bb3@oracle.com> <5BFFDEB6.8060603@oracle.com> <5C016F58.3060909@oracle.com> Message-ID: <16e04970-23b9-3e8c-0f30-652db36af816@oracle.com> Looks great! Thanks Maurizio On 30/11/2018 17:11, Jan Lahoda wrote: > Hi, > > A patch updated according to the comments is here: > http://cr.openjdk.java.net/~jlahoda/8214031/webrev.01/ > > A delta patch from the previous patch is here: > http://cr.openjdk.java.net/~jlahoda/8214031/webrev.delta.00.01/ > > How does this look? > > Thanks, > ?? Jan > > On 29.11.2018 13:42, Jan Lahoda wrote: >> Hi Maurizio, >> >> Thanks for the comments. I'll work on these. >> >> Jan >> >> On 28.11.2018 13:12, Maurizio Cimadamore wrote: >>> Hi Jan, >>> the patch looks very good and, albeit complex, I don't think there's >>> another way to implement shortcircuiting of boolean switch expression >>> w/o going deep in Gen (which is what this patch does). So well done. >>> >>> ?From a code perspective I have only minor comments, as the code is >>> generally well done: >>> >>> 1) In Flow, since now you are making AssignAnalyzer also extends from >>> BaseAnalyzer (used to be BaseAnalyzer), I >>> think >>> there is no need now for having a type parameter in BaseAnalyzer. Let >>> all exits be PendingExit - then subclasses can come up with variants >>> (like AssignExit) when needed. But it seems like the 1-1 relationship >>> between analyzer type and exit type is gone and the code should >>> probably >>> be more upfront about that. >>> >>> 2) The valueBreakHandler abstraction in Gen is nice, but I wonder if >>> the >>> code would be clearer by encoding the desired logic directly in >>> visitBreak. That is, visitBreak could fetch the switch expression it >>> points to, and determine whether we are inside a 'cond' or not, and >>> then >>> act accordingly. I think that, with a couple of Gen instance fields >>> (shared trueChain/falseChain), you could be able to get there. Not 100% >>> sure it will make the code better, but I thought it could be worth a >>> try. >>> >>> 3) In the test DefiniteAssignment1.java (and also, but to lesser >>> extent, >>> DefiniteAssignment1.java)? I guess it would also be nice to test >>> some && >>> condition in the break expression - e.g. >>> >>> true && (x = 1) >>> >>> Also, might be worth replacing the true with some other variable which >>> the compiler doesn't know to be true statically (as that affects code >>> generation). >>> >>> Cheers >>> Maurizio >>> >>> On 27/11/2018 20:21, Jan Lahoda wrote: >>>> Hi, >>>> >>>> javac does not handle switch expressions that return booleans >>>> correctly. According to the spec, javac should track definite >>>> [un]assignment when true/false for switch expressions, but fails to do >>>> so. Moreover, for more complex code, like: >>>> >>>> int v = ...; >>>> int x; >>>> boolean b = switch (v) { >>>> ???? case 0: x = 12; break true; >>>> ???? case 1: x = 13; break true; >>>> ???? default: break false; >>>> } && x == 12; >>>> >>>> The current switch expression desugaring is not powerful enough to >>>> generate valid bytecode for this input. The issue is that the current >>>> desugaring will translate the switch expression into code like: >>>> ( >>>> ?boolean $result; >>>> ?switch (v) { >>>> ???? case 0: x = 12; $result = true; break; >>>> ???? case 1: x = 13; $result = true; break; >>>> ???? default: $result = false; break; >>>> ?} >>>> ?$result?? //"return" expression >>>> ) && x == 12 >>>> >>>> But by assigning the true/false result to a variable, we are loosing >>>> track of which variables are assigned (when true/false) and which are >>>> not. The bytecode needs to ensure the "x == 12" is jumped over when >>>> the switch expression's value is false, and that, I believe, is not >>>> possible when desugaring in Lower. >>>> >>>> So, the proposed fix is to avoid desugaring in Lower, letting switch >>>> expressions go to Gen and produce bytecode for them, including >>>> handling them in Gen.genCond for true/false switch expressions. This >>>> is mostly modelled after the conditional expression handling. Some >>>> generalizations in Lower are required as well, to handle String and >>>> enum switch expressions. Handling of definite assignment in Flow is >>>> fixed as well. >>>> >>>> JBS: https://bugs.openjdk.java.net/browse/JDK-8214031 >>>> Webrev: http://cr.openjdk.java.net/~jlahoda/8214031/webrev.00/ >>>> >>>> Any feedback is welcome! >>>> >>>> Thanks, >>>> ?? Jan From joe.darcy at oracle.com Fri Nov 30 19:16:07 2018 From: joe.darcy at oracle.com (joe darcy) Date: Fri, 30 Nov 2018 11:16:07 -0800 Subject: Start of JDK 13 langtools CSRs to review Message-ID: <6da06ab3-019c-baaa-bf3e-e4b48c953941@oracle.com> Hello, The fork date for JDK 13 is coming in about two weeks (http://openjdk.java.net/projects/jdk/12/) and preparations are underway for start-of-release groundbreaking. Please review these two langtools CSRs as part of that effort: ??? JDK-8214550: Add source 13 and target 13 to javac ??? https://bugs.openjdk.java.net/browse/JDK-8214550 ??? JDK-8205395: Add SourceVersion.RELEASE_13 ??? https://bugs.openjdk.java.net/browse/JDK-8205395 Code reviews will follow in the context of the larger set of release updating changes. Thanks, -Joe