From jlahoda at openjdk.org Wed Oct 1 05:47:23 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 1 Oct 2025 05:47:23 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v2] In-Reply-To: References: Message-ID: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Simplifying the code as suggested. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27247/files - new: https://git.openjdk.org/jdk/pull/27247/files/bed37c4f..0ee60862 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=00-01 Stats: 6 lines in 1 file changed: 0 ins; 4 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From jlahoda at openjdk.org Wed Oct 1 11:19:18 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 1 Oct 2025 11:19:18 GMT Subject: Integrated: 8367279: Test tools/javac/tree/TreePosTest.java timed out In-Reply-To: References: Message-ID: On Wed, 17 Sep 2025 08:20:09 GMT, Jan Lahoda wrote: > The `test/langtools/tools/javac/tree/TreePosTest.java` tries to parse all langtools tests, and started to time out recently in some cases. In the case of this test, we can try to use the `JavacTaskPool`, which pools and reuses javac instances, rather than creating (and initializing) a javac instance for each file. Given this test only parses the file, and even attributes them, this should be relatively safe. > > Locally, I can't confirm too significant time improvements (before this change ~6s, after this change ~4s), but it might help on CI. This pull request has now been integrated. Changeset: 3607e998 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/3607e9986f1582ebdae1b6ad2a13c1a9c239e0d6 Stats: 29 lines in 1 file changed: 6 ins; 8 del; 15 mod 8367279: Test tools/javac/tree/TreePosTest.java timed out Reviewed-by: asotona ------------- PR: https://git.openjdk.org/jdk/pull/27334 From jlahoda at openjdk.org Thu Oct 2 06:55:57 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 2 Oct 2025 06:55:57 GMT Subject: Integrated: 8368848: JShell's code completion not always working for multi-snippet inputs In-Reply-To: References: Message-ID: On Mon, 29 Sep 2025 16:16:39 GMT, Jan Lahoda wrote: > Having a JShell input like: > > jshell> String s() { return "";} s(). > > > the code completion is not working for it. The reason is that the input is two snippets, but the code completion will interpret it as only one snippet, and a method declaration and method invocation cannot coexist inside one snippet (as one is a declaration that must appear outside of a method, and the invocation must be inside a method body or field initializer). > > The proposal herein is for the JShell's code completion to split the input into snippets, and create a wrapper/compilation unit based on all the snippets. This pull request has now been integrated. Changeset: 5251405c Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/5251405ce9ab1cbd84b798a538cb3865ea4675e9 Stats: 140 lines in 4 files changed: 114 ins; 15 del; 11 mod 8368848: JShell's code completion not always working for multi-snippet inputs Reviewed-by: asotona ------------- PR: https://git.openjdk.org/jdk/pull/27552 From jlahoda at openjdk.org Thu Oct 2 09:10:08 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 2 Oct 2025 09:10:08 GMT Subject: RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v2] In-Reply-To: References: Message-ID: > Consider case like (from the bug): > > class Demo { > > sealed interface Base permits Special, Value {} > > non-sealed interface Value extends Base {} > > sealed interface Special extends Base permits SpecialValue {} > > non-sealed interface SpecialValue extends Value, Special {} > > static int demo(final Base base) { > return switch (base) { > case final Value value -> 0; > // Uncommenting the following line will make javac accept this program > //case final Special value -> throw new AssertionError(); > }; > > } > > } > > > This fails to compile: > > /tmp/Demo.java:12: error: the switch expression does not cover all possible input values > return switch (base) { > ^ > 1 error > > > Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input. > > Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code: > > case final Value value -> 0; > => > case final SpecialValue value -> 0; > > $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java > $ > > > Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac). > > javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive. > > The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes. Jan Lahoda has updated the pull request incrementally with two additional commits since the last revision: - Removing trailing whitespace. - There are no relevant permitted subtypes of a non-abstract class, not even the class itself. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27547/files - new: https://git.openjdk.org/jdk/pull/27547/files/4cf49874..64df6f43 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=00-01 Stats: 27 lines in 2 files changed: 25 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27547.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27547/head:pull/27547 PR: https://git.openjdk.org/jdk/pull/27547 From sherman at openjdk.org Fri Oct 3 19:10:20 2025 From: sherman at openjdk.org (Xueming Shen) Date: Fri, 3 Oct 2025 19:10:20 GMT Subject: RFR: 8365675: Add String Unicode Case-Folding Support Message-ID: ### Summary Case folding is a key operation for case-insensitive matching (e.g., string equality, regex matching), where the goal is to eliminate case distinctions without applying locale or language specific conversions. Currently, the JDK does not expose a direct API for Unicode-compliant case folding. Developers now rely on methods such as: **String.equalsIgnoreCase(String)** - Unicode-aware, locale-independent. - Implementation uses Character.toLowerCase(Character.toUpperCase(int)) per code point. - Limited: does not support 1:M mapping defined in Unicode case folding. **Character.toLowerCase(int) / Character.toUpperCase(int)** - Locale-independent, single code point only. - No support for 1:M mappings. **String.toLowerCase(Locale.ROOT) / String.toUpperCase(Locale.ROOT)** - Based on Unicode SpecialCasing.txt, supports 1:M mappings. - Intended primarily for presentation/display, not structural case-insensitive matching. - Requires full string conversion before comparison, which is less efficient and not intended for structural matching. **1:M mapping example, U+00DF (?)** - String.toUpperCase(Locale.ROOT, "?") ? "SS" - Case folding produces "ss", matching Unicode caseless comparison rules. jshell> "\u00df".equalsIgnoreCase("ss") $22 ==> false jshell> "\u00df".toUpperCase(Locale.ROOT).toLowerCase(Locale.ROOT).equals("ss") $24 ==> true ### Motivation & Direction Add Unicode standard-compliant case-less comparison methods to the String class, enabling & improving reliable and efficient Unicode-aware/compliant case-insensitive matching. - Unicode-compliant **full** case folding. - Simpler, stable and more efficient case-less matching without workarounds. - Brings Java's string comparison handling in line with other programming languages/libraries. This PR proposes to introduce the following comparison methods in `String` class - boolean equalsFoldCase(String anotherString) - int compareToFoldCase(String anotherString) - Comparator UNICODE_CASEFOLD_ORDER These methods are intended to be the preferred choice when Unicode-compliant case-less matching is required. *Note: An early draft also proposed a String.toCaseFold() method returning a new case-folded string. However, during review this was considered error-prone, as the resulting string could easily be mistaken for a general transformation like toLowerCase() and then passed into APIs where case-folding semantics are not appropriate. ### The New API /** * Compares this {@code String} to another {@code String} for equality, * using Unicode case folding. Two strings are considered equal * by this method if their case-folded forms are identical. *

* Case folding is defined by the Unicode Standard in * CaseFolding.txt, * including 1:M mappings. For example, {@code "Ma?e".equalsFoldCase("MASSE")} * returns {@code true}, since the character {@code U+00DF} (sharp s) folds * to {@code "ss"}. *

* Case folding is locale-independent and language-neutral, unlike * locale-sensitive transformations such as {@link #toLowerCase()} or * {@link #toUpperCase()}. It is intended for caseless matching, * searching, and indexing. * * @apiNote * This method is the Unicode-compliant alternative to * {@link #equalsIgnoreCase(String)}. It implements full case folding as * defined by the Unicode Standard, which may differ from the simpler * per-character mapping performed by {@code equalsIgnoreCase}. * For example: *

{@snippet lang=java :
     * String a = "Ma?e";
     * String b = "MASSE";
     * boolean equalsFoldCase = a.equalsFoldCase(b);       // returns true
     * boolean equalsIgnoreCase = a.equalsIgnoreCase(b);   // returns false
     * }
* * @param anotherString * The {@code String} to compare this {@code String} against * * @return {@code true} if the given object is not {@code null} and represents * the same sequence of characters as this string under Unicode case * folding; {@code false} otherwise. * * @see #compareToFoldCase(String) * @see #equalsIgnoreCase(String) * @since 26 */ public boolean equalsFoldCase(String anotherString) /** * Compares two strings lexicographically using Unicode case folding. * This method returns an integer whose sign is that of calling {@code compareTo} * on the Unicode case folded version of the strings. Unicode Case folding * eliminates differences in case according to the Unicode Standard, using the * mappings defined in * CaseFolding.txt, * including 1:M mappings, such as {@code"?"} ? {@code }"ss"}. *

* Case folding is a locale-independent, language-neutral form of case mapping, * primarily intended for caseless matching. Unlike {@link #compareToIgnoreCase(String)}, * which applies a simpler locale-insensitive uppercase mapping. This method * follows the Unicode full case folding, providing stable and * consistent results across all environments. *

* Note that this method does not take locale into account, and may * produce results that differ from locale-sensitive ordering. Use * {@link java.text.Collator} for locale-sensitive comparison. * * @apiNote * This method is the Unicode-compliant alternative to * {@link #compareToIgnoreCase(String)}. It implements the full case folding * as defined by the Unicode Standard, which may differ from the simpler * per-character mapping performed by {@code compareToIgnoreCase}. * For example: *

{@snippet lang=java :
     * String a = "Ma?e";
     * String b = "MASSE";
     * int cmpFoldCase = a.compareToFoldCase(b);     // returns 0
     * int cmpIgnoreCase = a.compareToIgnoreCase(b); // returns > 0
     * }
* * @param str the {@code String} to be compared. * @return a negative integer, zero, or a positive integer as the specified * String is greater than, equal to, or less than this String, * ignoring case considerations by case folding. * @see #equalsFoldCase(String) * @see #compareToIgnoreCase(String) * @see java.text.Collator * @since 26 */ public int compareToFoldCase(String str) /** * A Comparator that orders {@code String} objects as by * {@link #compareToFoldCase(String) compareToFoldCase()}. * * @see #compareToFoldCase(String) * @since 26 */ public static final Comparator UNICODE_CASEFOLD_ORDER; ### Usage Examples Sharp s (U+00DF) case-folds to "ss" "stra?e".equalsIgnoreCase("strasse"); // false "stra?e".compareToIgnoreCase("strasse"); // != 0 "stra?e".equalsFoldCase("strasse"); // true ### Performance The JMH microbenchmark StringCompareToIgnoreCase has been updated to compare performance of compareToFoldCase with the existing compareToIgnoreCase(). Benchmark Mode Cnt Score Error Units StringCompareToIgnoreCase.asciiGreekLower avgt 15 20.195 ? 0.300 ns/op StringCompareToIgnoreCase.asciiGreekLowerCF avgt 15 11.051 ? 0.254 ns/op StringCompareToIgnoreCase.asciiGreekUpperLower avgt 15 6.035 ? 0.047 ns/op StringCompareToIgnoreCase.asciiGreekUpperLowerCF avgt 15 14.786 ? 0.382 ns/op StringCompareToIgnoreCase.asciiLower avgt 15 17.688 ? 1.396 ns/op StringCompareToIgnoreCase.asciiLowerCF avgt 15 44.552 ? 0.155 ns/op StringCompareToIgnoreCase.asciiUpperLower avgt 15 13.069 ? 0.487 ns/op StringCompareToIgnoreCase.asciiUpperLowerCF avgt 15 58.684 ? 0.274 ns/op StringCompareToIgnoreCase.greekLower avgt 15 20.642 ? 0.082 ns/op StringCompareToIgnoreCase.greekLowerCF avgt 15 7.255 ? 0.271 ns/op StringCompareToIgnoreCase.greekUpperLower avgt 15 5.737 ? 0.013 ns/op StringCompareToIgnoreCase.greekUpperLowerCF avgt 15 11.100 ? 1.147 ns/op StringCompareToIgnoreCase.lower avgt 15 20.192 ? 0.044 ns/op StringCompareToIgnoreCase.lowerrCF avgt 15 11.257 ? 0.259 ns/op StringCompareToIgnoreCase.supLower avgt 15 54.801 ? 0.415 ns/op StringCompareToIgnoreCase.supLowerCF avgt 15 15.207 ? 0.418 ns/op StringCompareToIgnoreCase.supUpperLower avgt 15 14.431 ? 0.188 ns/op StringCompareToIgnoreCase.supUpperLowerCF avgt 15 19.149 ? 0.985 ns/op StringCompareToIgnoreCase.upperLower avgt 15 5.650 ? 0.051 ns/op StringCompareToIgnoreCase.upperLowerCF avgt 15 14.338 ? 0.352 ns/op StringCompareToIgnoreCase.utf16SubLower avgt 15 14.774 ? 0.200 ns/op StringCompareToIgnoreCase.utf16SubLowerCF avgt 15 2.669 ? 0.041 ns/op StringCompareToIgnoreCase.utf16SupUpperLower avgt 15 16.250 ? 0.099 ns/op StringCompareToIgnoreCase.utf16SupUpperLowerCF avgt 15 11.524 ? 0.327 ns/op ### Refs [Unicode Standard 5.18.4 Caseless Matching](https://www.unicode.org/versions/latest/core-spec/chapter-5/#G21790) [Unicode? Standard Annex #44: 5.6 Case and Case Mapping](https://www.unicode.org/reports/tr44/#Casemapping) [Unicode Technical Standard #18: Unicode Regular Expressions RL1.5: Simple Loose Matches](https://www.unicode.org/reports/tr18/#Simple_Loose_Matches) [Unicode SpecialCasing.txt](https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt) [Unicode CaseFolding.txt](https://www.unicode.org/Public/UCD/latest/ucd/CaseFolding.txt) ### Other Languages **Python string.casefold()** The str.casefold() method in Python returns a casefolded version of a string. Casefolding is a more aggressive form of lowercasing, designed to remove all case distinctions in a string, particularly for the purpose of caseless string comparisons. **Perl?s fc()** Returns the casefolded version of EXPR. This is the internal function implementing the \F escape in double-quoted strings. Casefolding is the process of mapping strings to a form where case differences are erased; comparing two strings in their casefolded form is effectively a way of asking if two strings are equal, regardless of case. Perl only implements the full form of casefolding, but you can access the simple folds using "casefold()" in Unicode::UCD] ad "prop_invmap()" in Unicode::UCD]. **ICU4J UCharacter.foldCase (Java)** Purpose: Provides extensions to the standard Java Character class, including support for more Unicode properties and handling of supplementary characters (code points beyond U+FFFF). Method Signature (String based): public static String foldCase(String str, int options) Method Signature (CharSequence & Appendable based): public static A foldCase(CharSequence src, A dest, int options, Edits edits) Key Features: Case Folding: Converts a string to its case-folded equivalent. Locale Independent: Case folding in UCharacter.foldCase is generally not dependent on locale settings. Context Insensitive: The mapping of a character is not affected by surrounding characters. Turkic Option: An option exists to include or exclude special mappings for Turkish/Azerbaijani text. Result Length: The resulting string can be longer or shorter than the original. Edits Recording: Allows for recording of edits for index mapping, styled text, and getting only changes. **u_strFoldCase (C/C++)** A lower-level C API function for case folding a string. Case Folding Options: Similar options as UCharacter.foldCase for controlling case folding behavior. Availability: Found in the ustring.h and unistr.h headers in the ICU4C library. ------------- Commit messages: - 8365675: Add String Unicode Case-Folding Support Changes: https://git.openjdk.org/jdk/pull/26892/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=26892&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8365675 Stats: 1279 lines in 12 files changed: 1116 ins; 137 del; 26 mod Patch: https://git.openjdk.org/jdk/pull/26892.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26892/head:pull/26892 PR: https://git.openjdk.org/jdk/pull/26892 From acobbs at openjdk.org Mon Oct 6 16:10:57 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 6 Oct 2025 16:10:57 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate Message-ID: The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. ------------- Commit messages: - Remove drive-by tweaks that aren\t the real issue. - Avoid using LintMapper when knowing rootLint suffices. - Avoid unnecessary recursion in LintMapper. Changes: https://git.openjdk.org/jdk/pull/27651/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27651&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369039 Stats: 11 lines in 2 files changed: 11 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27651.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27651/head:pull/27651 PR: https://git.openjdk.org/jdk/pull/27651 From jlahoda at openjdk.org Mon Oct 6 17:27:35 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 6 Oct 2025 17:27:35 GMT Subject: RFR: 8357809: Test jdk/jshell/JdiListeningExecutionControlTest.java failed with com.sun.jdi.connect.TransportTimeoutException Message-ID: The test timed-out while connecting to the remote agent over JDI. This PR proposes to try to increase the JDI connection timeout. ------------- Commit messages: - Adding missing comma. - 8357809: Test jdk/jshell/JdiListeningExecutionControlTest.java failed with com.sun.jdi.connect.TransportTimeoutException Changes: https://git.openjdk.org/jdk/pull/27653/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27653&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8357809 Stats: 11 lines in 3 files changed: 7 ins; 0 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/27653.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27653/head:pull/27653 PR: https://git.openjdk.org/jdk/pull/27653 From jlahoda at openjdk.org Tue Oct 7 07:23:23 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 7 Oct 2025 07:23:23 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static Message-ID: Consider a JShell interaction like: jshell> class O { class I {} } | created class O jshell> var i = new O().new I(); i ==> O$I at 77caeb3e jshell> class O { static class I {} } Exception in thread "main" java.lang.ClassFormatError: class not in class file format at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:1222) at jdk.jshell/jdk.internal.jshell.tool.JShellTool.start(JShellTool.java:1005) at jdk.jshell/jdk.internal.jshell.tool.JShellToolBuilder.start(JShellToolBuilder.java:261) at jdk.jshell/jdk.internal.jshell.tool.JShellToolProvider.main(JShellToolProvider.java:120) There are two problems here (although the stack trace immediately only shows one of them): Redefining Classes --- When a snippet is redefined, JShell first tries to redefine it using JDI (`VirtualMachine.redefineClasses). This usually throws `UnsupportedOperationException` is the redefine cannot happen, and `JdiExecutionControl` handles that gracefully. JShell will recompile and reload the given snippet, and dependent snippets, under different names. But the `redefineClasses` method can also throw various `LinkageError`s. These are properly documented for the method: https://docs.oracle.com/en/java/javase/25/docs/api/jdk.jdi/com/sun/jdi/VirtualMachine.html#redefineClasses(java.util.Map) But `JdiExecutionControl` is not handling these `LinkageError`s. The proposed solution herein is to simply catch and handle the `LinkageError`s in the same way as the `UnsupportedOperationException` (and other exceptions). InnerClasses attribute data overriding information from sources --- Consider situation when compiling the third input: `class O { static class I {} }`. When this is being compiled, a classfile for `var i = new O().new I();` exists, and its `InnerClasses` attribute records `O.I` to be a non-`static` inner class. While compiling the code for `class O { static class I {} }`, the classfile for `var i` is also read from the classfile, and its `InnerClasses` attribute is read as well. And as a consequence, the `O.I` class will be marked as non-`static`, which conflicts with what is in the source file. This is not related to JShell as such, it can be reproduced with javac. Please see the `test/langtools/tools/javac/recovery/SourceAndInnerClassInconsistency.java` test. The proposal herein is to not use the information from the `InnerClasses` classfile attribute to manipulate classes that originate in a source file. More generally, I think the information from the source should always prevail over information from other/unrelated classfiles. Note the `InnerClasses` attribute is in a classfile that has no real relation to the source code that is being compiled, it is simply an classfile on the classpath. ------------- Commit messages: - Updating copyright year. - Fixing test. - 8340840: jshell ClassFormatError when making inner class static Changes: https://git.openjdk.org/jdk/pull/27665/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8340840 Stats: 141 lines in 4 files changed: 130 ins; 0 del; 11 mod Patch: https://git.openjdk.org/jdk/pull/27665.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27665/head:pull/27665 PR: https://git.openjdk.org/jdk/pull/27665 From redestad at openjdk.org Tue Oct 7 14:13:09 2025 From: redestad at openjdk.org (Claes Redestad) Date: Tue, 7 Oct 2025 14:13:09 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate In-Reply-To: References: Message-ID: On Mon, 6 Oct 2025 16:03:11 GMT, Archie Cobbs wrote: > The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. I haven't been able to run this through our wider performance lab yet due to some issues on my end, but in local testing I'm not seeing that much of an improvement in my diagnostic tests (the tests are a bit noisy). Running the benchmark with `-prof gc` shows that the regression correlates with a 17% increase in allocation pressure. This PR only reduces allocation pressure by about from the elevated state 1%: 26-b11: 15.06 GB/op 26-b12: 17.61 GB/op pr/27651: 17.46 GB/op Looking at hot methods I see one of the lambdas in `LintMapper$FileInfo` (allocated in the constructor) being relatively hot and I think the abundant use of capturing lambdas in JDK-8348611 might be cause for some unexpected allocation overheads. For example desugaring the stream in the `FileInfo` constructor (which was the only thing I saw on `jfr view hot-methods` that seemed related to JDK-8348611): tree.defs.stream() .filter(this::isTopLevelDecl) .map(decl -> new Span(decl, tree.endPositions)) .forEach(unmappedDecls::add); to this: for (JCTree decl : tree.defs) { if (isTopLevelDecl(decl)) { unmappedDecls.add(new Span(decl, tree.endPositions)); } } .. reduces allocation to 16.68GB/op (reducing the relative increase in allocations by about 1/3 compared to pr/27651) ------------- PR Comment: https://git.openjdk.org/jdk/pull/27651#issuecomment-3377077619 From liach at openjdk.org Tue Oct 7 15:41:05 2025 From: liach at openjdk.org (Chen Liang) Date: Tue, 7 Oct 2025 15:41:05 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 07:15:50 GMT, Jan Lahoda wrote: > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... src/jdk.jshell/share/classes/jdk/jshell/execution/JdiExecutionControl.java line 93: > 91: } catch (EngineTerminationException ex) { > 92: throw ex; > 93: } catch (Exception | LinkageError ex) { How was ClassFormatError previously thrown here? Was it wrapped in some exception? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27665#discussion_r2411069586 From amaembo at gmail.com Tue Oct 7 16:12:22 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 7 Oct 2025 18:12:22 +0200 Subject: Lambda and wildcard Message-ID: Hello! I'm investigating a seemingly weird compilation case. Consider the following Java interface: import java.util.function.Supplier; interface Main { interface X { X self(); } static X makeX() {return null;} static X create(Supplier supplier) {return null;} static X> methodRef() { return create(Main::makeX).self(); } static X> lambda() { return create(() -> makeX()).self(); } } I expect that either both methods 'methodRef' and 'lambda' should be compilable or both should be non-compilable. However, while 'methodRef' compiles, 'lambda' is rejected by compiler (using javac build 25+36-3489): Main.java:17: error: incompatible types: X> cannot be converted to X> return create(() -> makeX()).self(); ^ where CAP#1 is a fresh type-variable: CAP#1 extends Object from capture of ? 1 error error: compilation failed Could you please help me and clarify whether this is an expected behavior or not? With best regards, Tagir Valeev -------------- next part -------------- An HTML attachment was scrubbed... URL: From zjx001202 at gmail.com Tue Oct 7 16:40:22 2025 From: zjx001202 at gmail.com (Glavo) Date: Wed, 8 Oct 2025 00:40:22 +0800 Subject: Lambda and wildcard In-Reply-To: References: Message-ID: Hi Tagir, This is expected behavior. See Chapter 15 of the Java Language Specification (Java SE 25 Edition) [1]: Unlike a lambda expression, a method reference can be congruent with a generic function type (that is, a function type that has type parameters). This is because the lambda expression would need to be able to declare type parameters, and no syntax supports this; while for a method reference, no such declaration is necessary. For example, the following program is legal: interface ListFactory { List make(); } ListFactory lf = ArrayList::new; List ls = lf.make(); List ln = lf.make(); Glavo [1]: https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.27 On Wed, Oct 8, 2025 at 12:12?AM Tagir Valeev wrote: > Hello! > > I'm investigating a seemingly weird compilation case. Consider the > following Java interface: > > import java.util.function.Supplier; > > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > return create(Main::makeX).self(); > } > > static X> lambda() { > return create(() -> makeX()).self(); > } > } > > I expect that either both methods 'methodRef' and 'lambda' should be > compilable or both should be non-compilable. However, while 'methodRef' > compiles, 'lambda' is rejected by compiler (using javac build 25+36-3489): > > Main.java:17: error: incompatible types: X> cannot be converted > to X> > return create(() -> makeX()).self(); > ^ > where CAP#1 is a fresh type-variable: > CAP#1 extends Object from capture of ? > 1 error > error: compilation failed > > Could you please help me and clarify whether this is an expected behavior > or not? > > With best regards, > Tagir Valeev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From acobbs at openjdk.org Tue Oct 7 17:42:32 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 17:42:32 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v2] In-Reply-To: References: Message-ID: > The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. Archie Cobbs has updated the pull request incrementally with two additional commits since the last revision: - Unstream loops. - Put back the drive-by tweaks; they seem to matter. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27651/files - new: https://git.openjdk.org/jdk/pull/27651/files/02d2e73f..816162e0 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27651&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27651&range=00-01 Stats: 21 lines in 1 file changed: 6 ins; 2 del; 13 mod Patch: https://git.openjdk.org/jdk/pull/27651.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27651/head:pull/27651 PR: https://git.openjdk.org/jdk/pull/27651 From acobbs at openjdk.org Tue Oct 7 17:42:33 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 17:42:33 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 14:09:49 GMT, Claes Redestad wrote: >> The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. > > I haven't been able to run this through our wider performance lab yet due to some issues on my end, but in local testing I'm not seeing that much of an improvement in my diagnostic tests (the tests are a bit noisy). > > Running the benchmark with `-prof gc` shows that the regression correlates with a 17% increase in allocation pressure. This PR only reduces allocation pressure by about 1% from the regressed state: > > > 26-b11: 15.06 GB/op > 26-b12: 17.61 GB/op > pr/27651: 17.46 GB/op > > > Looking at hot methods I see one of the lambdas in `LintMapper$FileInfo` (allocated in the constructor) being relatively hot and I think the abundant use of capturing lambdas in JDK-8348611 might be cause for some unexpected allocation overheads. > > For example desugaring the stream in the `FileInfo` constructor (which was the only thing I saw on `jfr view hot-methods` that seemed related to JDK-8348611): > > tree.defs.stream() > .filter(this::isTopLevelDecl) > .map(decl -> new Span(decl, tree.endPositions)) > .forEach(unmappedDecls::add); > > to this: > > for (JCTree decl : tree.defs) { > if (isTopLevelDecl(decl)) { > unmappedDecls.add(new Span(decl, tree.endPositions)); > } > } > > .. reduces allocation to 16.68GB/op (reducing the relative increase in allocations by about 1/3 compared to pr/27651) Hi @cl4es, > This PR only reduces allocation pressure by about 1% from the regressed state: Now you're moving the goalposts :) I was looking at the performance benchmark, not allocation pressure... FWIW this is what I saw on my laptop: JDK 25 Benchmark (stopStage) Mode Cnt Score Error Units SingleJavacBenchmark.compileHot Generate ss 10 14.566 ? 0.868 s/op JDK 26 Benchmark (stopStage) Mode Cnt Score Error Units SingleJavacBenchmark.compileHot Generate ss 10 16.403 ? 0.214 s/op JDK 26 + [this patch](https://github.com/openjdk/jdk/compare/master...archiecobbs:d098d010e8c8948bf728dcd3b95eb56f97268871) Benchmark (stopStage) Mode Cnt Score Error Units SingleJavacBenchmark.compileHot Generate ss 10 14.807 ? 0.381 s/op So that patch did seem to help resolve most of the benchmark difference. Are you not seeing the same thing? But also that patch differs from the one currently committed, in that it includes the `ArrayList` to `LinkedList` changes that were later taken out. Without those changes, things get slower again: Benchmark (stopStage) Mode Cnt Score Error Units SingleJavacBenchmark.compileHot Generate ss 10 15.832 ? 0.135 s/op So surprisingly, they have an effect. So I've put them back into the PR. > For example desugaring the stream in the FileInfo constructor ... reduces allocation `` Argh, this is frustrating. _Are we supposed to use the `Stream` API to help improve code clarity, or avoid it to prevent slowdowns?_ I've seen it argued both ways... `` Anyway, unstreaming the loop you suggested plus another one, plus the other stuff, yeilds this on my laptop: Benchmark (stopStage) Mode Cnt Score Error Units SingleJavacBenchmark.compileHot Generate ss 10 14.932 ? 0.370 s/op That is with [this patch](https://github.com/openjdk/jdk/compare/master...archiecobbs:816162e08f036d2c1613746d70481807dc8266ed). Let me know what you see on the allocation pressure front... thanks. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27651#issuecomment-3377914846 From redestad at openjdk.org Tue Oct 7 18:10:14 2025 From: redestad at openjdk.org (Claes Redestad) Date: Tue, 7 Oct 2025 18:10:14 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v2] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 17:42:32 GMT, Archie Cobbs wrote: >> The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. > > Archie Cobbs has updated the pull request incrementally with two additional commits since the last revision: > > - Unstream loops. > - Put back the drive-by tweaks; they seem to matter. FYI I'm not a core maintainer/reviewer of javac but specialize on isolating and figuring out causes of performance regressions; you're free to keep the streams in in favor of perceived code clarity if you make the case that impact on performance is negligible. Transient allocation pressure can be a non-issue on one system but cause a lot of GC pauses and slowdown on another, so it's one of those things I like to keep tabs on when diagnosing a regression. Ideally we shouldn't increase allocation pressure too much. On one system I was looking at the Score was way worse after 26-b12 and didn't improve that much with this PR. On your system it seems the allocation pressure isn't a large contributor to Score. YMMV. I'll look at the numbers on your latest version. (FWIW I ran an experiment baselined on an earlier state of this PR and posted it here https://github.com/archiecobbs/jdk/pull/1 -- that showed that desugaring all the streams in LintMapper got allocation pressure down below 26-b11 levels) ------------- PR Comment: https://git.openjdk.org/jdk/pull/27651#issuecomment-3378011583 From acobbs at openjdk.org Tue Oct 7 18:22:43 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 18:22:43 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: > The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: Do more desugaring of Stream and Optional. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27651/files - new: https://git.openjdk.org/jdk/pull/27651/files/816162e0..c7d5d300 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27651&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27651&range=01-02 Stats: 12 lines in 1 file changed: 4 ins; 3 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/27651.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27651/head:pull/27651 PR: https://git.openjdk.org/jdk/pull/27651 From acobbs at openjdk.org Tue Oct 7 18:22:43 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 18:22:43 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v2] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 18:07:42 GMT, Claes Redestad wrote: > I ran an experiment baselined on an earlier state of this PR Thanks, I'll include that as well. See c7d5d300237. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27651#issuecomment-3378044779 From vromero at openjdk.org Tue Oct 7 18:54:41 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 7 Oct 2025 18:54:41 GMT Subject: RFR: 8349847: Support configuring individual lint categories as errors [v13] In-Reply-To: References: Message-ID: <1LFOwekcsWprX441eYIJPnrrthwZ_3b3axeGG8C4MBg=.c716ec78-cea1-4359-8fa1-0e4df2e60082@github.com> On Sun, 28 Sep 2025 18:53:35 GMT, Archie Cobbs wrote: >> This PR enhances the `-Werror` flag to support lint categories just like `-Xlint` does. For example `-Werror:all,-preview` would cause an error if any warning not in the `preview` lint category occurred. >> >> The existing `-Xlint` flag has a particular behavior when conflicting flags are combined (e.g., `-Xlint:all -Xlint:none -Xlint:foo -Xlint:-foo` is equivalent to `-Xlint:all`). This behavior has been factored out and Javadocumented so that both `-Xlint` and `-Werror` can have this same "parsing" logic. >> >> See the CSR [JDK-8350044](https://bugs.openjdk.org/browse/JDK-8350044) for details on how the new flag behaves in certain corner cases. > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 21 commits: > > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - Reword the "--help-lint" trailing blurb to make it sound more friendly. > - Add trailing "--help-lint" blurb to clarify how category aliases are handled. > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - Improve documentation per CSR review comments. > - Address review comments. > - Merge branch 'master' into JDK-8349847 > - Merge branch 'master' into JDK-8349847 to fix cross-compiling build problem. > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - ... and 11 more: https://git.openjdk.org/jdk/compare/9093d3a0...0599ab08 looks good ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/23622#pullrequestreview-3311466789 From amaembo at gmail.com Tue Oct 7 19:05:13 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 7 Oct 2025 21:05:13 +0200 Subject: Lambda and wildcard In-Reply-To: References: Message-ID: Hello! The 'makeX' method in my example is not generic, so this part of the specification looks unrelated. With best regards, Tagir Valeev On Tue, Oct 7, 2025, 18:41 Glavo wrote: > Hi Tagir, > > This is expected behavior. See Chapter 15 of the Java Language > Specification (Java SE 25 Edition) [1]: > > Unlike a lambda expression, a method reference can be congruent with a > generic function type (that is, a function type that has type parameters). > This is because the lambda expression would need to be able to declare > type parameters, and no syntax supports this; while for a method reference, > no such declaration is necessary. For example, the following program is > legal: > > interface ListFactory { > List make(); > } > > ListFactory lf = ArrayList::new; > List ls = lf.make(); > List ln = lf.make(); > > > Glavo > > [1]: > https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.27 > > On Wed, Oct 8, 2025 at 12:12?AM Tagir Valeev wrote: > >> Hello! >> >> I'm investigating a seemingly weird compilation case. Consider the >> following Java interface: >> >> import java.util.function.Supplier; >> >> interface Main { >> interface X { >> X self(); >> } >> >> static X makeX() {return null;} >> >> static X create(Supplier supplier) {return null;} >> >> static X> methodRef() { >> return create(Main::makeX).self(); >> } >> >> static X> lambda() { >> return create(() -> makeX()).self(); >> } >> } >> >> I expect that either both methods 'methodRef' and 'lambda' should be >> compilable or both should be non-compilable. However, while 'methodRef' >> compiles, 'lambda' is rejected by compiler (using javac build 25+36-3489): >> >> Main.java:17: error: incompatible types: X> cannot be converted >> to X> >> return create(() -> makeX()).self(); >> ^ >> where CAP#1 is a fresh type-variable: >> CAP#1 extends Object from capture of ? >> 1 error >> error: compilation failed >> >> Could you please help me and clarify whether this is an expected behavior >> or not? >> >> With best regards, >> Tagir Valeev >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From acobbs at openjdk.org Tue Oct 7 19:35:01 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 19:35:01 GMT Subject: RFR: 8349847: Support configuring individual lint categories as errors [v13] In-Reply-To: References: Message-ID: On Sun, 28 Sep 2025 18:53:35 GMT, Archie Cobbs wrote: >> This PR enhances the `-Werror` flag to support lint categories just like `-Xlint` does. For example `-Werror:all,-preview` would cause an error if any warning not in the `preview` lint category occurred. >> >> The existing `-Xlint` flag has a particular behavior when conflicting flags are combined (e.g., `-Xlint:all -Xlint:none -Xlint:foo -Xlint:-foo` is equivalent to `-Xlint:all`). This behavior has been factored out and Javadocumented so that both `-Xlint` and `-Werror` can have this same "parsing" logic. >> >> See the CSR [JDK-8350044](https://bugs.openjdk.org/browse/JDK-8350044) for details on how the new flag behaves in certain corner cases. > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 21 commits: > > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - Reword the "--help-lint" trailing blurb to make it sound more friendly. > - Add trailing "--help-lint" blurb to clarify how category aliases are handled. > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - Improve documentation per CSR review comments. > - Address review comments. > - Merge branch 'master' into JDK-8349847 > - Merge branch 'master' into JDK-8349847 to fix cross-compiling build problem. > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - Merge branch 'master' into JDK-8349847 to fix conflicts. > - ... and 11 more: https://git.openjdk.org/jdk/compare/9093d3a0...0599ab08 Thanks for the review! ------------- PR Comment: https://git.openjdk.org/jdk/pull/23622#issuecomment-3378423464 From acobbs at openjdk.org Tue Oct 7 19:35:04 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 19:35:04 GMT Subject: Integrated: 8349847: Support configuring individual lint categories as errors In-Reply-To: References: Message-ID: On Thu, 13 Feb 2025 20:52:49 GMT, Archie Cobbs wrote: > This PR enhances the `-Werror` flag to support lint categories just like `-Xlint` does. For example `-Werror:all,-preview` would cause an error if any warning not in the `preview` lint category occurred. > > The existing `-Xlint` flag has a particular behavior when conflicting flags are combined (e.g., `-Xlint:all -Xlint:none -Xlint:foo -Xlint:-foo` is equivalent to `-Xlint:all`). This behavior has been factored out and Javadocumented so that both `-Xlint` and `-Werror` can have this same "parsing" logic. > > See the CSR [JDK-8350044](https://bugs.openjdk.org/browse/JDK-8350044) for details on how the new flag behaves in certain corner cases. This pull request has now been integrated. Changeset: 910bb68e Author: Archie Cobbs URL: https://git.openjdk.org/jdk/commit/910bb68e5191f830ff6f3dff5753e4e5f6214a7b Stats: 241 lines in 13 files changed: 180 ins; 27 del; 34 mod 8349847: Support configuring individual lint categories as errors Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/23622 From jlahoda at openjdk.org Tue Oct 7 19:38:25 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 7 Oct 2025 19:38:25 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 18:22:43 GMT, Archie Cobbs wrote: >> The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Do more desugaring of Stream and Optional. I did a quick pass through the code, and looks sensible so far. Assuming it helps with resolving the problem. I'll go through the change in more detail tomorrow. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27651#issuecomment-3378444727 From acobbs at openjdk.org Tue Oct 7 19:40:35 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 19:40:35 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain Message-ID: When bit shifting an `int` or `long` value by an amount `X`, all but the last 5 or 6 (respectively) bits of `X` are ignored. This can create a trap for the unwary, as in this example: public long readLongBigEndian(byte[] buf, int offset) { return ((buf[offset + 0] & 0xff) << 56) // BUG HERE | ((buf[offset + 1] & 0xff) << 48) // BUG HERE | ((buf[offset + 2] & 0xff) << 40) // BUG HERE | ((buf[offset + 3] & 0xff) << 32) // BUG HERE | ((buf[offset + 4] & 0xff) << 24) | ((buf[offset + 5] & 0xff) << 16) | ((buf[offset + 6] & 0xff) << 8) | ((buf[offset + 7] & 0xff); } This PR adds a new warning when the compiler detects an out-of-range bit shift, i.e., an `int` bit shift not in the range `[0...31]` or a `long` bit shift not in the range `[0...63]`. ------------- Commit messages: - Merge branch 'master' into JDK-5038439 to fix conflict. - Add "long" as a supported message parameter type. - Use "bit(s)" instead of "bits" where value could be 1. - Merge branch 'master' into JDK-5038439 - Sprinkle more variety into the regression test. - Minor diff cleanup. - Update "lossy-conversions" description in compiler module Javadoc. - Warn for bit shifts using an out-of-range shift amount. Changes: https://git.openjdk.org/jdk/pull/27102/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27102&range=00 Issue: https://bugs.openjdk.org/browse/JDK-5038439 Stats: 194 lines in 14 files changed: 184 ins; 0 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/27102.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27102/head:pull/27102 PR: https://git.openjdk.org/jdk/pull/27102 From amaembo at gmail.com Tue Oct 7 19:52:57 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Tue, 7 Oct 2025 21:52:57 +0200 Subject: Lambda and wildcard In-Reply-To: References: Message-ID: On Tue, Oct 7, 2025, 21:05 Tagir Valeev wrote: > Hello! > > The 'makeX' method in my example is not generic, so this part of the > specification looks unrelated. > A correction: I meant that the method 'get' of the 'Supplier' functional interface is not generic. > With best regards, > Tagir Valeev > > On Tue, Oct 7, 2025, 18:41 Glavo wrote: > >> Hi Tagir, >> >> This is expected behavior. See Chapter 15 of the Java Language >> Specification (Java SE 25 Edition) [1]: >> >> Unlike a lambda expression, a method reference can be congruent with a >> generic function type (that is, a function type that has type parameters). >> This is because the lambda expression would need to be able to declare >> type parameters, and no syntax supports this; while for a method reference, >> no such declaration is necessary. For example, the following program is >> legal: >> >> interface ListFactory { >> List make(); >> } >> >> ListFactory lf = ArrayList::new; >> List ls = lf.make(); >> List ln = lf.make(); >> >> >> Glavo >> >> [1]: >> https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.27 >> >> On Wed, Oct 8, 2025 at 12:12?AM Tagir Valeev wrote: >> >>> Hello! >>> >>> I'm investigating a seemingly weird compilation case. Consider the >>> following Java interface: >>> >>> import java.util.function.Supplier; >>> >>> interface Main { >>> interface X { >>> X self(); >>> } >>> >>> static X makeX() {return null;} >>> >>> static X create(Supplier supplier) {return null;} >>> >>> static X> methodRef() { >>> return create(Main::makeX).self(); >>> } >>> >>> static X> lambda() { >>> return create(() -> makeX()).self(); >>> } >>> } >>> >>> I expect that either both methods 'methodRef' and 'lambda' should be >>> compilable or both should be non-compilable. However, while 'methodRef' >>> compiles, 'lambda' is rejected by compiler (using javac build 25+36-3489): >>> >>> Main.java:17: error: incompatible types: X> cannot be converted >>> to X> >>> return create(() -> makeX()).self(); >>> ^ >>> where CAP#1 is a fresh type-variable: >>> CAP#1 extends Object from capture of ? >>> 1 error >>> error: compilation failed >>> >>> Could you please help me and clarify whether this is an expected >>> behavior or not? >>> >>> With best regards, >>> Tagir Valeev >>> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From acobbs at openjdk.org Tue Oct 7 20:03:25 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 7 Oct 2025 20:03:25 GMT Subject: RFR: 8344159: Add lint warnings for unnecessary warning suppression [v3] In-Reply-To: References: Message-ID: > This PR adds a new compiler warning for `@SuppressWarnings` annotations that don't actually suppress any warnings. > > Summary of code changes: > > * Add new warning and associated lint category `"suppression"` > * Update `LintMapper` to keep track of which `@SuppressWarnings` suppressions have been validated ? > * Update `Log.warning()` so it validates any current suppression of the warning's lint category in effect. > * Add a new `validate` parameter to `Lint.isEnabled()` and `Lint.isSuppressed()` that specifies whether to also validate any current suppression. > * Add `Lint.isActive()` to check whether a category is enabled _or_ suppression of the category is being tracked - in other words, whether the warning calculation needs to be performed. Used for non-trivial warning calculations. > * Add `-Xlint:-suppression` flags to `*.gmk` build files so the build doesn't break > > ? The suppression of a lint category is "validated" as soon as it suppresses some warning in that category Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 132 commits: - Merge branch 'master' into JDK-8344159 to fix conflict. - Merge branch 'master' into JDK-8344159 to fix conflicts. - Add clarifying comment. - Merge branch 'master' into JDK-8344159 - Change inner class name to avoid shadowing superclass name. - Add a couple of code clarification comments. - Refactor test to avoid requiring changes to TestRunner. - Remove unnecessary -Xlint:-suppression flags. - Minor cleanups. - Add OPTIONS, PATH, and SUPPRESSION to the regression test. - ... and 122 more: https://git.openjdk.org/jdk/compare/910bb68e...3542625c ------------- Changes: https://git.openjdk.org/jdk/pull/25167/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=25167&range=02 Stats: 1659 lines in 34 files changed: 1486 ins; 49 del; 124 mod Patch: https://git.openjdk.org/jdk/pull/25167.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/25167/head:pull/25167 PR: https://git.openjdk.org/jdk/pull/25167 From zjx001202 at gmail.com Wed Oct 8 04:01:17 2025 From: zjx001202 at gmail.com (Glavo) Date: Wed, 8 Oct 2025 12:01:17 +0800 Subject: Lambda and wildcard In-Reply-To: References: Message-ID: Hi Tagir, My bad, I didn't look at the original code carefully. :( I re-read your email and I think this is still the expected behavior. In fact, the type of create(() -> makeX()) will be inferred to be X>. You can capture its return value in a variable in jshell and then verify it through /vars. jshell> var x = create(() -> A.makeX()) x ==> null jshell> /vars | X> x = null Unfortunately, X> and X> are not compatible, so the compilation fails. Glavo On Wed, Oct 8, 2025 at 3:53?AM Tagir Valeev wrote: > > > On Tue, Oct 7, 2025, 21:05 Tagir Valeev wrote: > >> Hello! >> >> The 'makeX' method in my example is not generic, so this part of the >> specification looks unrelated. >> > > A correction: I meant that the method 'get' of the 'Supplier' functional > interface is not generic. > > >> With best regards, >> Tagir Valeev >> >> On Tue, Oct 7, 2025, 18:41 Glavo wrote: >> >>> Hi Tagir, >>> >>> This is expected behavior. See Chapter 15 of the Java Language >>> Specification (Java SE 25 Edition) [1]: >>> >>> Unlike a lambda expression, a method reference can be congruent with a >>> generic function type (that is, a function type that has type parameters). >>> This is because the lambda expression would need to be able to declare >>> type parameters, and no syntax supports this; while for a method reference, >>> no such declaration is necessary. For example, the following program is >>> legal: >>> >>> interface ListFactory { >>> List make(); >>> } >>> >>> ListFactory lf = ArrayList::new; >>> List ls = lf.make(); >>> List ln = lf.make(); >>> >>> >>> Glavo >>> >>> [1]: >>> https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.27 >>> >>> On Wed, Oct 8, 2025 at 12:12?AM Tagir Valeev wrote: >>> >>>> Hello! >>>> >>>> I'm investigating a seemingly weird compilation case. Consider the >>>> following Java interface: >>>> >>>> import java.util.function.Supplier; >>>> >>>> interface Main { >>>> interface X { >>>> X self(); >>>> } >>>> >>>> static X makeX() {return null;} >>>> >>>> static X create(Supplier supplier) {return >>>> null;} >>>> >>>> static X> methodRef() { >>>> return create(Main::makeX).self(); >>>> } >>>> >>>> static X> lambda() { >>>> return create(() -> makeX()).self(); >>>> } >>>> } >>>> >>>> I expect that either both methods 'methodRef' and 'lambda' should be >>>> compilable or both should be non-compilable. However, while 'methodRef' >>>> compiles, 'lambda' is rejected by compiler (using javac build 25+36-3489): >>>> >>>> Main.java:17: error: incompatible types: X> cannot be >>>> converted to X> >>>> return create(() -> makeX()).self(); >>>> ^ >>>> where CAP#1 is a fresh type-variable: >>>> CAP#1 extends Object from capture of ? >>>> 1 error >>>> error: compilation failed >>>> >>>> Could you please help me and clarify whether this is an expected >>>> behavior or not? >>>> >>>> With best regards, >>>> Tagir Valeev >>>> >>> -------------- next part -------------- An HTML attachment was scrubbed... URL: From redestad at openjdk.org Wed Oct 8 08:53:06 2025 From: redestad at openjdk.org (Claes Redestad) Date: Wed, 8 Oct 2025 08:53:06 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 18:22:43 GMT, Archie Cobbs wrote: >> The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Do more desugaring of Stream and Optional. Latest look good on both score and allocation pressure, e.g., on my M1 MacBook: Name Cnt Base Error Test Error Unit Change compileHot 10 15.915 ? 0.094 14.463 ? 0.235 s/op 1.10x (p = 0.000*) * = significant Allocations: 16.9GB/op -> 13.95GB/op 26-b11 for reference on the same system: 14,285 ? 0,379 s/op Allocations 14.2GB/op So more or less recuperated on score and with slightly less allocation pressure to boot ? ------------- PR Comment: https://git.openjdk.org/jdk/pull/27651#issuecomment-3380473533 From liach at openjdk.org Wed Oct 8 12:36:03 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 8 Oct 2025 12:36:03 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 18:22:43 GMT, Archie Cobbs wrote: >> The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Do more desugaring of Stream and Optional. src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 180: > 178: > 179: final LintRange rootRange; // the root LintRange (covering the entire source file) > 180: final List unmappedDecls = new LinkedList<>(); // unmapped top-level declarations awaiting attribution LinkedList has a ton of nodes, which translate to extra object headers, forward/backward pointers, and worse cache locality. To add N items, it requires O(N) allocations. In contrast, ArrayList requires O(log(N)) allocations (resizing) and is almost always better. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2412374882 From redestad at openjdk.org Wed Oct 8 13:26:00 2025 From: redestad at openjdk.org (Claes Redestad) Date: Wed, 8 Oct 2025 13:26:00 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Wed, 8 Oct 2025 02:53:35 GMT, Chen Liang wrote: >> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: >> >> Do more desugaring of Stream and Optional. > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 180: > >> 178: >> 179: final LintRange rootRange; // the root LintRange (covering the entire source file) >> 180: final List unmappedDecls = new LinkedList<>(); // unmapped top-level declarations awaiting attribution > > LinkedList has a ton of nodes, which translate to extra object headers, forward/backward pointers, and worse cache locality. To add N items, it requires O(N) allocations. In contrast, ArrayList requires O(log(N)) allocations (resizing) and is almost always better. @archiecobbs measured a win. I haven't seen it in profiles but it could be that the code in `afterAttr` contribute to the case for `LinkedList` as it is set up to remove matching item from the list, likely at an early index. Which is one of the few things a `LinkedList` actually does better than an `ArrayList`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2413851059 From jlahoda at openjdk.org Wed Oct 8 13:55:07 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 8 Oct 2025 13:55:07 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 18:22:43 GMT, Archie Cobbs wrote: >> The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Do more desugaring of Stream and Optional. Looks reasonable to me. (I didn't run tests, though, so far.) Thanks! ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27651#pullrequestreview-3314932186 From jlahoda at openjdk.org Wed Oct 8 13:55:10 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 8 Oct 2025 13:55:10 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Wed, 8 Oct 2025 13:23:18 GMT, Claes Redestad wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 180: >> >>> 178: >>> 179: final LintRange rootRange; // the root LintRange (covering the entire source file) >>> 180: final List unmappedDecls = new LinkedList<>(); // unmapped top-level declarations awaiting attribution >> >> LinkedList has a ton of nodes, which translate to extra object headers, forward/backward pointers, and worse cache locality. To add N items, it requires O(N) allocations. In contrast, ArrayList requires O(log(N)) allocations (resizing) and is almost always better. > > @archiecobbs measured a win. I haven't seen it in profiles but it could be that the code in `afterAttr` contribute to the case for `LinkedList` as it is set up to remove matching item from the list, likely at an early index. Which is one of the few things a `LinkedList` actually does better than an `ArrayList`. While I agree `ArrayList`s are often better, @archiecobbs measured the `LinkedList`s perform better here, as @cl4es says. I am not quite clear why linked lists are faster, but it might be many of the lists are either empty (all the `children` of the leaf `LintRange` instances will be empty lists, I think, and an empty `LinkedList` is, I think, cheaper than an empty `ArrayList`), and some of them will have only a few entries (like the `unmappedDecls` list here: AFAIK, this has one entry for each top-level declaration, and hence is highly unlikely to have more than 2 entries - one for the package clause, and one for the top-level class). If `ArrayList`s with substantial number of entries are only a small minority, it might explain why the use of `LinkedList`s leads to better results. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2413937369 From liach at openjdk.org Wed Oct 8 14:11:03 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 8 Oct 2025 14:11:03 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Wed, 8 Oct 2025 13:50:55 GMT, Jan Lahoda wrote: >> @archiecobbs measured a win. I haven't seen it in profiles but it could be that the code in `afterAttr` contribute to the case for `LinkedList` as it is set up to remove matching item from the list, likely at an early index. Which is one of the few things a `LinkedList` actually does better than an `ArrayList`. > > While I agree `ArrayList`s are often better, @archiecobbs measured the `LinkedList`s perform better here, as @cl4es says. > > I am not quite clear why linked lists are faster, but it might be many of the lists are either empty (all the `children` of the leaf `LintRange` instances will be empty lists, I think, and an empty `LinkedList` is, I think, cheaper than an empty `ArrayList`), and some of them will have only a few entries (like the `unmappedDecls` list here: AFAIK, this has one entry for each top-level declaration, and hence is highly unlikely to have more than 2 entries - one for the package clause, and one for the top-level class). If `ArrayList`s with substantial number of entries are only a small minority, it might explain why the use of `LinkedList`s leads to better results. I think the right way to fix is not to use LinkedList, but to update afterAttr to use List.removeIf - this was added back in 8 to avoid the overhead of shifting from multiple removals. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2413990365 From cushon at openjdk.org Wed Oct 8 14:21:13 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 8 Oct 2025 14:21:13 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics Message-ID: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Hi, Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. Before: T.java:2: error: method does not override or implement a method from a supertype @Override ^ After: T.java:2: error: f() does not override or implement a method from a supertype @Override ^ 1 error ------------- Commit messages: - 8369428: Include method name in 'does not override or implement' diagnostics Changes: https://git.openjdk.org/jdk/pull/27692/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27692&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369428 Stats: 6 lines in 5 files changed: 1 ins; 0 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/27692.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27692/head:pull/27692 PR: https://git.openjdk.org/jdk/pull/27692 From cushon at openjdk.org Wed Oct 8 14:24:56 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 8 Oct 2025 14:24:56 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 14:12:57 GMT, Liam Miller-Cushon wrote: > Hi, > > Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. > > Before: > > > T.java:2: error: method does not override or implement a method from a supertype > @Override > ^ > > > After: > > > T.java:2: error: f() does not override or implement a method from a supertype > @Override > ^ > 1 error There are a few other diagnostics that might also benefit from this approach, like `static methods cannot be annotated with @Override` and `missing method body, or declare abstract`. If this change makes sense overall I'm happy to update them too, either here or as a follow-up. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27692#issuecomment-3381789373 From liach at openjdk.org Wed Oct 8 14:31:12 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 8 Oct 2025 14:31:12 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 14:12:57 GMT, Liam Miller-Cushon wrote: > Hi, > > Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. > > Before: > > > T.java:2: error: method does not override or implement a method from a supertype > @Override > ^ > > > After: > > > T.java:2: error: f() does not override or implement a method from a supertype > @Override > ^ > 1 error A similar diagnostic `compiler.err.does.not.override.abstract` reports both the method and the problematic class without the method. Should `compiler.err.method.does.not.override.superclass` also report both the method and the current class of the current method? ------------- PR Comment: https://git.openjdk.org/jdk/pull/27692#issuecomment-3381825267 From liach at openjdk.org Wed Oct 8 14:41:35 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 8 Oct 2025 14:41:35 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Wed, 8 Oct 2025 14:07:46 GMT, Chen Liang wrote: >> While I agree `ArrayList`s are often better, @archiecobbs measured the `LinkedList`s perform better here, as @cl4es says. >> >> I am not quite clear why linked lists are faster, but it might be many of the lists are either empty (all the `children` of the leaf `LintRange` instances will be empty lists, I think, and an empty `LinkedList` is, I think, cheaper than an empty `ArrayList`), and some of them will have only a few entries (like the `unmappedDecls` list here: AFAIK, this has one entry for each top-level declaration, and hence is highly unlikely to have more than 2 entries - one for the package clause, and one for the top-level class). If `ArrayList`s with substantial number of entries are only a small minority, it might explain why the use of `LinkedList`s leads to better results. > > I think the right way to fix is not to use LinkedList, but to update afterAttr to use List.removeIf - this was added back in 8 to avoid the overhead of shifting from multiple removals. On second look my last analysis was wrong. This is removing one element which is probably better done as an operation on a TreeSet, which is okay. However, I don't find why we would use a LinkedList for LintRange. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2414093460 From acobbs at openjdk.org Wed Oct 8 14:52:51 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 8 Oct 2025 14:52:51 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: <6Pi3kIaiJnITLG10fsfLqFkJOGN_IJMqH7ybngt5m_o=.462928b4-b4dd-40c4-babf-2a42f9b9768e@github.com> On Wed, 8 Oct 2025 14:38:58 GMT, Chen Liang wrote: >> I think the right way to fix is not to use LinkedList, but to update afterAttr to use List.removeIf - this was added back in 8 to avoid the overhead of shifting from multiple removals. > > On second look my last analysis was wrong. This is removing one element which is probably better done as an operation on a TreeSet, which is okay. However, I don't find why we would use a LinkedList for LintRange. > AFAIK, this has one entry for each top-level declaration, and hence is highly unlikely to have more than 2 entries - one for the package clause, and one for the top-level class Actually it will most likely only have one entry - package declarations are not included because they can never contain `@SuppressWarnings` annotations. This may explain why `LinkedList` is faster on average. > I don't find why we would use a LinkedList for LintRange. The same answer may apply here, but honestly I'm just guessing at this. I was also surprised that `LinkedList` was faster than `ArrayList`, but the numbers seem to be saying that. In fact, as you point out, `unmappedDecls` could be a `Set` instead of a `List`. But whether that would actually help is not clear. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2414129265 From acobbs at openjdk.org Wed Oct 8 14:58:08 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 8 Oct 2025 14:58:08 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: <6Pi3kIaiJnITLG10fsfLqFkJOGN_IJMqH7ybngt5m_o=.462928b4-b4dd-40c4-babf-2a42f9b9768e@github.com> References: <6Pi3kIaiJnITLG10fsfLqFkJOGN_IJMqH7ybngt5m_o=.462928b4-b4dd-40c4-babf-2a42f9b9768e@github.com> Message-ID: On Wed, 8 Oct 2025 14:49:53 GMT, Archie Cobbs wrote: > Actually it will most likely only have one entry - package declarations are not included because they can never contain `@SuppressWarnings` annotations. This may explain why `LinkedList` is faster on average. Argh, ignore that, I was looking at something else. So "2" is the right number on average. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2414154075 From acobbs at openjdk.org Wed Oct 8 15:34:30 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 8 Oct 2025 15:34:30 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: <6Pi3kIaiJnITLG10fsfLqFkJOGN_IJMqH7ybngt5m_o=.462928b4-b4dd-40c4-babf-2a42f9b9768e@github.com> Message-ID: On Wed, 8 Oct 2025 14:55:20 GMT, Archie Cobbs wrote: > Argh, ignore that, I was looking at something else. So "2" is the right number on average. But there's no reason for that! 99.99% of package declarations have no annotations and therefore do not need to wait for attribution. So we can get this number down to "1". I was curious if that would make any difference (using [this additional patch](https://github.com/archiecobbs/jdk/compare/JDK-8369039...archiecobbs:jdk:JDK-8369039-opt1)). When I try it on my laptop I get a slight improvement: Benchmark (stopStage) Mode Cnt Score Error Units SingleJavacBenchmark.compileHot Generate ss 10 14.841 ? 0.618 s/op ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2414270544 From acobbs at openjdk.org Wed Oct 8 16:53:29 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 8 Oct 2025 16:53:29 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 19:35:59 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: >> >> Do more desugaring of Stream and Optional. > > I did a quick pass through the code, and looks sensible so far. Assuming it helps with resolving the problem. I'll go through the change in more detail tomorrow. @lahodaj thanks for the review! Since the current version seems to address the performance issue as reported in the bug, I'll plan to integrate later this evening unless there are objections. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27651#issuecomment-3382430233 From cushon at openjdk.org Wed Oct 8 17:21:22 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 8 Oct 2025 17:21:22 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 14:28:51 GMT, Chen Liang wrote: > A similar diagnostic `compiler.err.does.not.override.abstract` reports both the method and the problematic class without the method. Should `compiler.err.method.does.not.override.superclass` also report both the method and the current class of the current method? For `compiler.err.does.not.override.abstract`, the problematic code in the current compilation unit is a class, which is shown, and javac also shows the method that isn't being overridden and its enclosing class. For `compiler.err.method.does.not.override.superclass` the problematic code in the current compilation unit is a method, which is now shown. (We don't know which superclass or supermethod would be relevant, since we couldn't resolve a supermethod.) So I do see a bit of a distinction whether the element is in the current source file or not. If it's in the current source file I think it's still valuable to have some context, but maybe just the method and not the method and also it's containing class is sufficient? What do you think? ------------- PR Comment: https://git.openjdk.org/jdk/pull/27692#issuecomment-3382518361 From liach at openjdk.org Wed Oct 8 18:38:34 2025 From: liach at openjdk.org (Chen Liang) Date: Wed, 8 Oct 2025 18:38:34 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 14:12:57 GMT, Liam Miller-Cushon wrote: > Hi, > > Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. > > Before: > > > T.java:2: error: method does not override or implement a method from a supertype > @Override > ^ > > > After: > > > T.java:2: error: f() does not override or implement a method from a supertype > @Override > ^ > 1 error I think a better analogy would be `compiler.err.default.overrides.object.member`: it is also a problematic method overriding. It reports the method, the declaring class's kind (class or interface), and the declaring class in the current source file. I think we can just emulate that message here. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27692#issuecomment-3382758741 From cushon at openjdk.org Wed Oct 8 20:58:30 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 8 Oct 2025 20:58:30 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 18:35:23 GMT, Chen Liang wrote: > I think a better analogy would be `compiler.err.default.overrides.object.member`: it is also a problematic method overriding. It reports the method, the declaring class's kind (class or interface), and the declaring class in the current source file. I think we can just emulate that message here. Ok, thanks! I can take a look at converging on showing both the method and declaring class. Another thing I notice about `compiler.err.default.overrides.object.member` is that it takes the method name, not the type (which would result in formatting the method signature). Other method diagnostics take a type. Do you have thoughts on when to make the distinction? One more weird thing about `compiler.err.default.overrides.object.member` is that it takes a kind, but as far as I can tell will only ever be reported for interfaces, `default` methods in non-interface types would be rejected earlier. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27692#issuecomment-3383210315 From redestad at openjdk.org Wed Oct 8 23:37:08 2025 From: redestad at openjdk.org (Claes Redestad) Date: Wed, 8 Oct 2025 23:37:08 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 18:22:43 GMT, Archie Cobbs wrote: >> The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Do more desugaring of Stream and Optional. This appears to resolve most or all of the regression - thanks! ------------- Marked as reviewed by redestad (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27651#pullrequestreview-3316806781 From redestad at openjdk.org Wed Oct 8 23:37:10 2025 From: redestad at openjdk.org (Claes Redestad) Date: Wed, 8 Oct 2025 23:37:10 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: <6Pi3kIaiJnITLG10fsfLqFkJOGN_IJMqH7ybngt5m_o=.462928b4-b4dd-40c4-babf-2a42f9b9768e@github.com> Message-ID: On Wed, 8 Oct 2025 15:31:21 GMT, Archie Cobbs wrote: > I was curious if that would make any difference (using [this additional patch](https://github.com/archiecobbs/jdk/compare/JDK-8369039...archiecobbs:jdk:JDK-8369039-opt1)). When I try it on my laptop I get a slight improvement: Can't reallt establish any statistically significant difference either way here, neither on score or allocations. So just to understand this a bit better I instrumented to see how common that condition is and it seems that when `tree.getTag() == Tree.PACKAGEDEF` then `tree.annotations` is never empty. At least in this benchmark. Perhaps the case when there are no annotations are skipped earlier? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2415235378 From acobbs at openjdk.org Thu Oct 9 01:35:15 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 9 Oct 2025 01:35:15 GMT Subject: RFR: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate [v3] In-Reply-To: References: <6Pi3kIaiJnITLG10fsfLqFkJOGN_IJMqH7ybngt5m_o=.462928b4-b4dd-40c4-babf-2a42f9b9768e@github.com> Message-ID: <2DInPnyFXxBtKG1K2iivzRMNQ8ps-5DJ0kU_Vd2EcUw=.4fa7fa46-3e9f-472b-bd64-6cbfe8ad1ede@github.com> On Wed, 8 Oct 2025 23:33:48 GMT, Claes Redestad wrote: > So just to understand this a bit better I instrumented to see how common that condition is and it seems that when `tree.getTag() == Tree.PACKAGEDEF` then `tree.annotations` is never empty. At least in this benchmark. Perhaps the case when there are no annotations are skipped earlier? Really? I'm not seeing that. When I apply this patch, I see `size=0` unless there's actually an annotation there: --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java @@ -179,6 +179,7 @@ private static class FileInfo { FileInfo(Lint rootLint, JCCompilationUnit tree) { rootRange = new LintRange(rootLint); for (JCTree decl : tree.defs) { +if (decl instanceof JCPackageDecl p) System.out.println("package "+p.pid+": annotations.size="+p.annotations.size()); if (isTopLevelDecl(decl)) unmappedDecls.add(new Span(decl, tree.endPositions)); } } ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27651#discussion_r2415348184 From acobbs at openjdk.org Thu Oct 9 01:35:16 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 9 Oct 2025 01:35:16 GMT Subject: Integrated: 8369039: JDK-8348611 caused regression in Javac-Hot-Generate In-Reply-To: References: Message-ID: On Mon, 6 Oct 2025 16:03:11 GMT, Archie Cobbs wrote: > The refactoring in [JDK-8348611](https://bugs.openjdk.org/browse/JDK-8348611) caused a regression in compiler performance. In the the refactoring there were a couple of simple optimizations that were missed. When put in place, these seem to (mostly) address the performance issue. This pull request has now been integrated. Changeset: 5873c4b5 Author: Archie Cobbs URL: https://git.openjdk.org/jdk/commit/5873c4b5d61844b6b34a46e8955bd94bdd3d7610 Stats: 43 lines in 2 files changed: 21 ins; 5 del; 17 mod 8369039: JDK-8348611 caused regression in Javac-Hot-Generate Co-authored-by: Claes Redestad Reviewed-by: jlahoda, redestad ------------- PR: https://git.openjdk.org/jdk/pull/27651 From maurizio.cimadamore at oracle.com Thu Oct 9 09:00:01 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 9 Oct 2025 10:00:01 +0100 Subject: Lambda and wildcard In-Reply-To: References: Message-ID: Hi Tagir! Nice cacth. Here's a slightly different example which reveals a bit more of what's happening: ``` interface Main { ??? interface X { ??????? X self(); ??? } ??? static X makeX() {return null;} ??? static X create(Supplier supplier) {return null;} ??? static X> methodRef() { ??????? var s = (String)create(Main::makeX); ??? } ??? static X> lambda() { ??????? var s = (String)create(() -> makeX()); ??? } } ``` This prints: ``` error: incompatible types: X> cannot be converted to String ??????? var s = (String)create(Main::makeX); ????????????????????????????? ^ error: incompatible types: X> cannot be converted to String ??????? var s = (String)create(() -> makeX()); ????????????????????????????? ^ ? where CAP#1 is a fresh type-variable: ??? CAP#1 extends Object from capture of ? ``` So, the main difference between the two examples is that in the lambda case, the return type of the makeX call is captured. But in the method refreene case no capture occurs. I believe the lambda case works as expected, but the method reference case does not. The JLS mandates a capture of the resolved method return type (JLS 15.13.2, emphasis mine): > A method reference expression is /congruent/ with a function type if > both of the following are true: > > * > > The function type identifies a single compile-time declaration > corresponding to the reference. > > * > > ?One of the following is true: > > o > > The result of the function type is |void|. > > o > > ?The result of the function type is R, *and the result of > applying capture conversion (?5.1.10 > ) > to the return type of the invocation type (?15.12.2.6 > ) > of the chosen compile-time declaration is R'* (where R is the > target type that may be used to infer R'), and neither R nor > R' is |void|, and R' is compatible with R in an assignment > context. > It seems like javac is missing this capture conversion and, because of that, the behavior of the two examples diverge. Cheers Maurizio On 07/10/2025 17:12, Tagir Valeev wrote: > Hello! > > I'm investigating a seemingly weird compilation case. Consider the > following Java interface: > > import java.util.function.Supplier; > > interface Main { > ? ? interface X { > ? ? ? ? X self(); > ? ? } > > ? ? static X makeX() {return null;} > > ? ? static X create(Supplier supplier) {return null;} > > ? ? static X> methodRef() { > ? ? ? ? return create(Main::makeX).self(); > ? ? } > > ? ? static X> lambda() { > ? ? ? ? return create(() -> makeX()).self(); > ? ? } > } > > I expect that either both methods 'methodRef' and 'lambda' should be > compilable or both should be non-compilable. However, while > 'methodRef' compiles, 'lambda' is rejected by compiler (using > javac?build 25+36-3489): > > Main.java:17: error: incompatible types: X> cannot be > converted to X> > ? ? ? ? return create(() -> makeX()).self(); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^ > ? where CAP#1 is a fresh type-variable: > ? ? CAP#1 extends Object from capture of ? > 1 error > error: compilation failed > > Could you please help me and clarify whether this is an expected > behavior or not? > > With best regards, > Tagir Valeev -------------- next part -------------- An HTML attachment was scrubbed... URL: From amaembo at gmail.com Thu Oct 9 09:18:03 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Thu, 9 Oct 2025 11:18:03 +0200 Subject: Lambda and wildcard In-Reply-To: References: Message-ID: Hello, Maurizio! Thank you for clarifying this. Should I file an issue? With best regards, Tagir Valeev On Thu, Oct 9, 2025 at 11:00?AM Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > Hi Tagir! > > Nice cacth. > > Here's a slightly different example which reveals a bit more of what's > happening: > > ``` > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > var s = (String)create(Main::makeX); > } > > static X> lambda() { > var s = (String)create(() -> makeX()); > } > } > ``` > > This prints: > > ``` > error: incompatible types: X> cannot be converted to String > var s = (String)create(Main::makeX); > ^ > error: incompatible types: X> cannot be converted to String > var s = (String)create(() -> makeX()); > ^ > where CAP#1 is a fresh type-variable: > CAP#1 extends Object from capture of ? > ``` > > So, the main difference between the two examples is that in the lambda > case, the return type of the makeX call is captured. But in the method > refreene case no capture occurs. > > I believe the lambda case works as expected, but the method reference case > does not. > > The JLS mandates a capture of the resolved method return type (JLS > 15.13.2, emphasis mine): > > A method reference expression is *congruent* with a function type if both > of the following are true: > > - > > The function type identifies a single compile-time declaration > corresponding to the reference. > - > > One of the following is true: > - > > The result of the function type is void. > - > > The result of the function type is R, *and the result of applying > capture conversion (?5.1.10 > ) > to the return type of the invocation type (?15.12.2.6 > ) > of the chosen compile-time declaration is R'* (where R is the > target type that may be used to infer R'), and neither R nor R' is > void, and R' is compatible with R in an assignment context. > > It seems like javac is missing this capture conversion and, because of > that, the behavior of the two examples diverge. > > Cheers > Maurizio > > > > > > On 07/10/2025 17:12, Tagir Valeev wrote: > > Hello! > > I'm investigating a seemingly weird compilation case. Consider the > following Java interface: > > import java.util.function.Supplier; > > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > return create(Main::makeX).self(); > } > > static X> lambda() { > return create(() -> makeX()).self(); > } > } > > I expect that either both methods 'methodRef' and 'lambda' should be > compilable or both should be non-compilable. However, while 'methodRef' > compiles, 'lambda' is rejected by compiler (using javac build 25+36-3489): > > Main.java:17: error: incompatible types: X> cannot be converted > to X> > return create(() -> makeX()).self(); > ^ > where CAP#1 is a fresh type-variable: > CAP#1 extends Object from capture of ? > 1 error > error: compilation failed > > Could you please help me and clarify whether this is an expected behavior > or not? > > With best regards, > Tagir Valeev > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Thu Oct 9 11:46:03 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 9 Oct 2025 12:46:03 +0100 Subject: Lambda and wildcard In-Reply-To: References: Message-ID: <041daebf-411b-4e75-a595-5127a97dc612@oracle.com> Yes, please! Thanks Maurizio On 09/10/2025 10:18, Tagir Valeev wrote: > Hello,?Maurizio! > > Thank you for clarifying this. Should I file an issue? > > With best regards, > Tagir Valeev > > On Thu, Oct 9, 2025 at 11:00?AM Maurizio Cimadamore > wrote: > > Hi Tagir! > > Nice cacth. > > Here's a slightly different example which reveals a bit more of > what's happening: > > ``` > interface Main { > ??? interface X { > ??????? X self(); > ??? } > > ??? static X makeX() {return null;} > > ??? static X create(Supplier supplier) {return > null;} > > ??? static X> methodRef() { > ??????? var s = (String)create(Main::makeX); > ??? } > > ??? static X> lambda() { > ??????? var s = (String)create(() -> makeX()); > ??? } > } > ``` > > This prints: > > ``` > error: incompatible types: X> cannot be converted to String > ??????? var s = (String)create(Main::makeX); > ????????????????????????????? ^ > error: incompatible types: X> cannot be converted to String > ??????? var s = (String)create(() -> makeX()); > ????????????????????????????? ^ > ? where CAP#1 is a fresh type-variable: > ??? CAP#1 extends Object from capture of ? > ``` > > So, the main difference between the two examples is that in the > lambda case, the return type of the makeX call is captured. But in > the method refreene case no capture occurs. > > I believe the lambda case works as expected, but the method > reference case does not. > > The JLS mandates a capture of the resolved method return type (JLS > 15.13.2, emphasis mine): > >> A method reference expression is /congruent/ with a function type >> if both of the following are true: >> >> * >> >> The function type identifies a single compile-time >> declaration corresponding to the reference. >> >> * >> >> ?One of the following is true: >> >> o >> >> The result of the function type is |void|. >> >> o >> >> ?The result of the function type is R, *and the result of >> applying capture conversion (?5.1.10 >> ) >> to the return type of the invocation type (?15.12.2.6 >> ) >> of the chosen compile-time declaration is R'* (where R is >> the target type that may be used to infer R'), and >> neither R nor R' is |void|, and R' is compatible with R >> in an assignment context. >> > It seems like javac is missing this capture conversion and, > because of that, the behavior of the two examples diverge. > > Cheers > Maurizio > > > > > > On 07/10/2025 17:12, Tagir Valeev wrote: >> Hello! >> >> I'm investigating a seemingly weird compilation case. Consider >> the following Java interface: >> >> import java.util.function.Supplier; >> >> interface Main { >> ? ? interface X { >> ? ? ? ? X self(); >> ? ? } >> >> ? ? static X makeX() {return null;} >> >> ? ? static X create(Supplier supplier) >> {return null;} >> >> ? ? static X> methodRef() { >> ? ? ? ? return create(Main::makeX).self(); >> ? ? } >> >> ? ? static X> lambda() { >> ? ? ? ? return create(() -> makeX()).self(); >> ? ? } >> } >> >> I expect that either both methods 'methodRef' and 'lambda' should >> be compilable or both should be non-compilable. However, while >> 'methodRef' compiles, 'lambda' is rejected by compiler (using >> javac?build 25+36-3489): >> >> Main.java:17: error: incompatible types: X> cannot be >> converted to X> >> ? ? ? ? return create(() -> makeX()).self(); >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^ >> ? where CAP#1 is a fresh type-variable: >> ? ? CAP#1 extends Object from capture of ? >> 1 error >> error: compilation failed >> >> Could you please help me and clarify whether this is an expected >> behavior or not? >> >> With best regards, >> Tagir Valeev > ​ -------------- next part -------------- An HTML attachment was scrubbed... URL: From cushon at openjdk.org Thu Oct 9 12:20:08 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 9 Oct 2025 12:20:08 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics [v2] In-Reply-To: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: > Hi, > > Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. > > Before: > > > T.java:2: error: method does not override or implement a method from a supertype > @Override > ^ > > > After: > > > T.java:2: error: f() does not override or implement a method from a supertype > @Override > ^ > 1 error Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Update more diagnostics ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27692/files - new: https://git.openjdk.org/jdk/pull/27692/files/75eb2794..fc64a0b4 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27692&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27692&range=00-01 Stats: 15 lines in 10 files changed: 2 ins; 0 del; 13 mod Patch: https://git.openjdk.org/jdk/pull/27692.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27692/head:pull/27692 PR: https://git.openjdk.org/jdk/pull/27692 From cushon at openjdk.org Thu Oct 9 12:20:09 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 9 Oct 2025 12:20:09 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 14:12:57 GMT, Liam Miller-Cushon wrote: > Hi, > > Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. > > Before: > > > T.java:2: error: method does not override or implement a method from a supertype > @Override > ^ > > > After: > > > T.java:2: error: f() does not override or implement a method from a supertype > @Override > ^ > 1 error I updated the PR to add the method and declaring class to: * `compiler.err.method.does.not.override.superclass` * `compiler.err.static.methods.cannot.be.annotated.with.override` * `compiler.err.missing.meth.body.or.decl.abstract` ------------- PR Comment: https://git.openjdk.org/jdk/pull/27692#issuecomment-3385602186 From cstein at openjdk.org Thu Oct 9 14:22:44 2025 From: cstein at openjdk.org (Christian Stein) Date: Thu, 9 Oct 2025 14:22:44 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 Message-ID: Please review the change to update to using jtreg `8.1`. The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. ------------- Commit messages: - 8369488: Update to use jtreg 8.1 Changes: https://git.openjdk.org/jdk/pull/27719/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27719&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369488 Stats: 11 lines in 9 files changed: 0 ins; 0 del; 11 mod Patch: https://git.openjdk.org/jdk/pull/27719.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27719/head:pull/27719 PR: https://git.openjdk.org/jdk/pull/27719 From jlahoda at openjdk.org Thu Oct 9 15:31:26 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 9 Oct 2025 15:31:26 GMT Subject: RFR: 8367499: Refactor exhaustiveness computation from Flow into a separate class [v3] In-Reply-To: References: Message-ID: > Currently the switch exhaustiveness computation code is part of `Flow`. And while conceptually the check is part of the `Flow` phase, the code is >500 lines of code currently, and likely to get bigger/more complicated in the future. Among other reasons due to enhancements like https://bugs.openjdk.org/browse/JDK-8367530. > > The proposal herein is to move the exhaustiveness computation to a separate class `ExhastivenessComputer`. There's no functional change, only move of the code. This is intentional, to aid the review process. > > One possibility to inspect what is happening is: > > git show upstream/pr/27247:src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/Flow-original.java > diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java >/tmp/exhaustivenesscomputer-comparison.diff > diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/flow-comparison.diff > > and inspecting `/tmp/exhaustivenesscomputer-comparison.diff`, `/tmp/flow-comparison.diff`. Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains three commits: - Merge branch 'JDK-8364991' into JDK-8367499 - Adding doc comment. - 8367499: Refactor exhaustiveness computation from Flow into a separate class ------------- Changes: https://git.openjdk.org/jdk/pull/27253/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27253&range=02 Stats: 1210 lines in 2 files changed: 637 ins; 570 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/27253.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27253/head:pull/27253 PR: https://git.openjdk.org/jdk/pull/27253 From jlahoda at openjdk.org Thu Oct 9 15:45:02 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 9 Oct 2025 15:45:02 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved Message-ID: Consider code like: package test; public class Test { private int test(Root r) { return switch (r) { case Root(R2(R1 _), R2(R1 _)) -> 0; case Root(R2(R1 _), R2(R2 _)) -> 0; case Root(R2(R2 _), R2(R1 _)) -> 0; }; } sealed interface Base {} record R1() implements Base {} record R2(Base b1) implements Base {} record Root(R2 b2, R2 b3) {} } ``` This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: $ javac test/Test.java .../test/Test.java:4: error: the switch expression does not cover all possible input values return switch (r) { ^ 1 error The goal of this PR is to improve the error, at least in some cases to something along these lines: $ javac test/Test.java .../test/Test.java:4: error: the switch expression does not cover all possible input values return switch (r) { ^ missing patterns: test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) 1 error The (very simplified) way it works in a recursive (or induction) way: - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. - for a current missing pattern, try to enhance it: - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and evaluated. ------------- Depends on: https://git.openjdk.org/jdk/pull/27253 Commit messages: - Better visualisation. - Merge branch 'JDK-8367499' into JDK-8367530 - Fixing tests. - Cleanup. - Cleanup. - Cleanup. - Enabling disabled test. - Cleanup, making timeout work. - Merge branch 'JDK-8367499' into JDK-8367530 - Fixing the exhaustiveness search. - ... and 7 more: https://git.openjdk.org/jdk/compare/e69c20e7...38089d18 Changes: https://git.openjdk.org/jdk/pull/27256/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8367530 Stats: 1316 lines in 14 files changed: 1234 ins; 42 del; 40 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From iris at openjdk.org Thu Oct 9 15:54:33 2025 From: iris at openjdk.org (Iris Clark) Date: Thu, 9 Oct 2025 15:54:33 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. Marked as reviewed by iris (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27719#pullrequestreview-3319601046 From erikj at openjdk.org Thu Oct 9 17:31:20 2025 From: erikj at openjdk.org (Erik Joelsson) Date: Thu, 9 Oct 2025 17:31:20 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. Marked as reviewed by erikj (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27719#pullrequestreview-3319953574 From vromero at openjdk.org Thu Oct 9 19:34:02 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 9 Oct 2025 19:34:02 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference Message-ID: Given the following test case: import java.util.function.Supplier; interface Main { interface X { X self(); } static X makeX() {return null;} static X create(Supplier supplier) {return null;} static X> methodRef() { return create(Main::makeX).self(); } static X> lambda() { return create(() -> makeX()).self(); } } javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) ------------- Commit messages: - 8369517: Compilation mismatch for equivalent lambda and method reference Changes: https://git.openjdk.org/jdk/pull/27737/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27737&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369517 Stats: 53 lines in 3 files changed: 52 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27737.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27737/head:pull/27737 PR: https://git.openjdk.org/jdk/pull/27737 From liach at openjdk.org Thu Oct 9 22:17:03 2025 From: liach at openjdk.org (Chen Liang) Date: Thu, 9 Oct 2025 22:17:03 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 19:26:36 GMT, Vicente Romero wrote: > Given the following test case: > > > import java.util.function.Supplier; > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > return create(Main::makeX).self(); > } > > static X> lambda() { > return create(() -> makeX()).self(); > } > } > > > javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) Changes requested by liach (Reviewer). test/langtools/tools/javac/lambda/methodReference/ResultTypeNotBeingCapturedTest.java line 43: > 41: > 42: static X> methodRef() { > 43: var s = (String)create(Main::makeX); Suggestion: var s = (String)create(ResultTypeNotBeingCapturedTest::makeX); Please also update the .out output, which should be more consistent after this fix. ------------- PR Review: https://git.openjdk.org/jdk/pull/27737#pullrequestreview-3320789875 PR Review Comment: https://git.openjdk.org/jdk/pull/27737#discussion_r2418071341 From vromero at openjdk.org Thu Oct 9 23:33:43 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 9 Oct 2025 23:33:43 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference [v2] In-Reply-To: References: Message-ID: > Given the following test case: > > > import java.util.function.Supplier; > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > return create(Main::makeX).self(); > } > > static X> lambda() { > return create(() -> makeX()).self(); > } > } > > > javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: fixing issues ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27737/files - new: https://git.openjdk.org/jdk/pull/27737/files/8005b675..41783b0f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27737&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27737&range=00-01 Stats: 8 lines in 4 files changed: 4 ins; 0 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/27737.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27737/head:pull/27737 PR: https://git.openjdk.org/jdk/pull/27737 From vromero at openjdk.org Fri Oct 10 01:02:03 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 10 Oct 2025 01:02:03 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference [v2] In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 22:14:37 GMT, Chen Liang wrote: >> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: >> >> fixing issues > > test/langtools/tools/javac/lambda/methodReference/ResultTypeNotBeingCapturedTest.java line 43: > >> 41: >> 42: static X> methodRef() { >> 43: var s = (String)create(Main::makeX); > > Suggestion: > > var s = (String)create(ResultTypeNotBeingCapturedTest::makeX); > > Please also update the .out output, which should be more consistent after this fix. yep thanks I saw that too, copy paste bug :) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27737#discussion_r2418273459 From cushon at openjdk.org Fri Oct 10 07:25:36 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Fri, 10 Oct 2025 07:25:36 GMT Subject: RFR: 8369508: Type annotations on anonymous new class creation expressions can't be retrieved Message-ID: Hi, Please consider this fix for [JDK-8369508: Type annotations on anonymous new class creation expressions can't be retrieved](https://bugs.openjdk.org/browse/JDK-8369508). When visiting a type annotation on an anonymous class instantiation expression, javac currently skips attribution of the annotated type when visiting it as part of the `new` expression, to prevent them from being incorrectly attached to the enclosing method instead of the synthetic declaration of the anonymous class (see [JDK-8198945](https://bugs.openjdk.org/browse/JDK-8198945)). However because this logic happens early, and results in skipping attribution of these annotations, they aren't available on the type model elements for the new class creation expression, which means they can't be retrieved by clients of the compiler tree API. This fix shifts the handling of these annotations later, to allow them to get attributed, but then to still prevent them from being attached to the enclosing method symbol of the anonymous class declaration. ------------- Commit messages: - Cleanup - 8369508: Type annotations on anonymous new class creation expressions can't be retrieved Changes: https://git.openjdk.org/jdk/pull/27730/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27730&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369508 Stats: 32 lines in 3 files changed: 11 ins; 13 del; 8 mod Patch: https://git.openjdk.org/jdk/pull/27730.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27730/head:pull/27730 PR: https://git.openjdk.org/jdk/pull/27730 From syan at openjdk.org Fri Oct 10 11:55:08 2025 From: syan at openjdk.org (SendaoYan) Date: Fri, 10 Oct 2025 11:55:08 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. Hi, is there a way to get the jtreg8.1 binary, except build from source. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27719#issuecomment-3389686651 From syan at openjdk.org Fri Oct 10 12:00:06 2025 From: syan at openjdk.org (SendaoYan) Date: Fri, 10 Oct 2025 12:00:06 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: <4WET954Oj6nVqTC0d9fTAAFyjWoUnu0EsGy7VM-V9do=.b4957a46-6b4e-4e74-bfde-33291622fde4@github.com> On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. Hi, is there a way to get the jtreg8.1 binary, except build from source. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27719#issuecomment-3389704303 From mcimadamore at openjdk.org Fri Oct 10 13:19:35 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 10 Oct 2025 13:19:35 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference [v2] In-Reply-To: References: Message-ID: <5v9YXTLLwryY5LKbQDH9D_BIVbeMM_HpROHz6MTYG4I=.00a714b6-b42e-4a61-812d-94a25e3211d6@github.com> On Thu, 9 Oct 2025 23:33:43 GMT, Vicente Romero wrote: >> Given the following test case: >> >> >> import java.util.function.Supplier; >> interface Main { >> interface X { >> X self(); >> } >> >> static X makeX() {return null;} >> >> static X create(Supplier supplier) {return null;} >> >> static X> methodRef() { >> return create(Main::makeX).self(); >> } >> >> static X> lambda() { >> return create(() -> makeX()).self(); >> } >> } >> >> >> javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > fixing issues The fix looks good! test/langtools/tools/javac/lambda/methodReference/ResultTypeNotBeingCapturedTest.java line 43: > 41: > 42: static X> methodRef() { > 43: var s = (String)create(ResultTypeNotBeingCapturedTest::makeX); The original test from Tagir was slightly different -- maybe we want to use that one instead? I think it was `return create(...).self()` ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27737#pullrequestreview-3323428306 PR Review Comment: https://git.openjdk.org/jdk/pull/27737#discussion_r2420141247 From amaembo at gmail.com Fri Oct 10 13:26:54 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Fri, 10 Oct 2025 15:26:54 +0200 Subject: Lambda and wildcard In-Reply-To: <041daebf-411b-4e75-a595-5127a97dc612@oracle.com> References: <041daebf-411b-4e75-a595-5127a97dc612@oracle.com> Message-ID: Here it is: https://bugs.openjdk.org/browse/JDK-8369565 I checked a few random OpenJDK builds I have on my machine, and it looks like the behavior was like this since Java 8. With best regards, Tagir Valeev On Thu, Oct 9, 2025 at 1:46?PM Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > Yes, please! > > Thanks > Maurizio > > On 09/10/2025 10:18, Tagir Valeev wrote: > > Hello, Maurizio! > > Thank you for clarifying this. Should I file an issue? > > With best regards, > Tagir Valeev > > On Thu, Oct 9, 2025 at 11:00?AM Maurizio Cimadamore < > maurizio.cimadamore at oracle.com> wrote: > >> Hi Tagir! >> >> Nice cacth. >> >> Here's a slightly different example which reveals a bit more of what's >> happening: >> >> ``` >> interface Main { >> interface X { >> X self(); >> } >> >> static X makeX() {return null;} >> >> static X create(Supplier supplier) {return null;} >> >> static X> methodRef() { >> var s = (String)create(Main::makeX); >> } >> >> static X> lambda() { >> var s = (String)create(() -> makeX()); >> } >> } >> ``` >> >> This prints: >> >> ``` >> error: incompatible types: X> cannot be converted to String >> var s = (String)create(Main::makeX); >> ^ >> error: incompatible types: X> cannot be converted to String >> var s = (String)create(() -> makeX()); >> ^ >> where CAP#1 is a fresh type-variable: >> CAP#1 extends Object from capture of ? >> ``` >> >> So, the main difference between the two examples is that in the lambda >> case, the return type of the makeX call is captured. But in the method >> refreene case no capture occurs. >> >> I believe the lambda case works as expected, but the method reference >> case does not. >> >> The JLS mandates a capture of the resolved method return type (JLS >> 15.13.2, emphasis mine): >> >> A method reference expression is *congruent* with a function type if >> both of the following are true: >> >> - >> >> The function type identifies a single compile-time declaration >> corresponding to the reference. >> - >> >> One of the following is true: >> - >> >> The result of the function type is void. >> - >> >> The result of the function type is R, *and the result of applying >> capture conversion (?5.1.10 >> ) >> to the return type of the invocation type (?15.12.2.6 >> ) >> of the chosen compile-time declaration is R'* (where R is the >> target type that may be used to infer R'), and neither R nor R' is >> void, and R' is compatible with R in an assignment context. >> >> It seems like javac is missing this capture conversion and, because of >> that, the behavior of the two examples diverge. >> >> Cheers >> Maurizio >> >> >> >> >> >> On 07/10/2025 17:12, Tagir Valeev wrote: >> >> Hello! >> >> I'm investigating a seemingly weird compilation case. Consider the >> following Java interface: >> >> import java.util.function.Supplier; >> >> interface Main { >> interface X { >> X self(); >> } >> >> static X makeX() {return null;} >> >> static X create(Supplier supplier) {return null;} >> >> static X> methodRef() { >> return create(Main::makeX).self(); >> } >> >> static X> lambda() { >> return create(() -> makeX()).self(); >> } >> } >> >> I expect that either both methods 'methodRef' and 'lambda' should be >> compilable or both should be non-compilable. However, while 'methodRef' >> compiles, 'lambda' is rejected by compiler (using javac build 25+36-3489): >> >> Main.java:17: error: incompatible types: X> cannot be converted >> to X> >> return create(() -> makeX()).self(); >> ^ >> where CAP#1 is a fresh type-variable: >> CAP#1 extends Object from capture of ? >> 1 error >> error: compilation failed >> >> Could you please help me and clarify whether this is an expected behavior >> or not? >> >> With best regards, >> Tagir Valeev >> >> ​ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Fri Oct 10 15:05:03 2025 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 10 Oct 2025 11:05:03 -0400 Subject: Lambda and wildcard In-Reply-To: References: <041daebf-411b-4e75-a595-5127a97dc612@oracle.com> Message-ID: <8ca23759-3a23-42e6-a59b-ca3fca7c457f@oracle.com> Hi Tagir, I had already created [1]. Sorry for not sending an update yesterday, Thanks, Vicente [1] https://bugs.openjdk.org/browse/JDK-8369517 On 10/10/25 09:26, Tagir Valeev wrote: > Here it is: > > https://bugs.openjdk.org/browse/JDK-8369565 > > I checked a few random OpenJDK builds I have on my machine, and it > looks like the behavior was like this since Java 8. > > With best regards, > Tagir Valeev > > On Thu, Oct 9, 2025 at 1:46?PM Maurizio Cimadamore > wrote: > > Yes, please! > > Thanks > Maurizio > > On 09/10/2025 10:18, Tagir Valeev wrote: > >> Hello,?Maurizio! >> >> Thank you for clarifying this. Should I file an issue? >> >> With best regards, >> Tagir Valeev >> >> On Thu, Oct 9, 2025 at 11:00?AM Maurizio Cimadamore >> wrote: >> >> Hi Tagir! >> >> Nice cacth. >> >> Here's a slightly different example which reveals a bit more >> of what's happening: >> >> ``` >> interface Main { >> ??? interface X { >> ??????? X self(); >> ??? } >> >> ??? static X makeX() {return null;} >> >> ??? static X create(Supplier supplier) >> {return null;} >> >> ??? static X> methodRef() { >> ??????? var s = (String)create(Main::makeX); >> ??? } >> >> ??? static X> lambda() { >> ??????? var s = (String)create(() -> makeX()); >> ??? } >> } >> ``` >> >> This prints: >> >> ``` >> error: incompatible types: X> cannot be converted to String >> ??????? var s = (String)create(Main::makeX); >> ????????????????????????????? ^ >> error: incompatible types: X> cannot be converted to >> String >> ??????? var s = (String)create(() -> makeX()); >> ????????????????????????????? ^ >> ? where CAP#1 is a fresh type-variable: >> ??? CAP#1 extends Object from capture of ? >> ``` >> >> So, the main difference between the two examples is that in >> the lambda case, the return type of the makeX call is >> captured. But in the method refreene case no capture occurs. >> >> I believe the lambda case works as expected, but the method >> reference case does not. >> >> The JLS mandates a capture of the resolved method return type >> (JLS 15.13.2, emphasis mine): >> >>> A method reference expression is /congruent/ with a function >>> type if both of the following are true: >>> >>> * >>> >>> The function type identifies a single compile-time >>> declaration corresponding to the reference. >>> >>> * >>> >>> ?One of the following is true: >>> >>> o >>> >>> The result of the function type is |void|. >>> >>> o >>> >>> ?The result of the function type is R, *and the >>> result of applying capture conversion (?5.1.10 >>> ) >>> to the return type of the invocation type >>> (?15.12.2.6 >>> ) >>> of the chosen compile-time declaration is R'* (where >>> R is the target type that may be used to infer R'), >>> and neither R nor R' is |void|, and R' is compatible >>> with R in an assignment context. >>> >> It seems like javac is missing this capture conversion and, >> because of that, the behavior of the two examples diverge. >> >> Cheers >> Maurizio >> >> >> >> >> >> On 07/10/2025 17:12, Tagir Valeev wrote: >>> Hello! >>> >>> I'm investigating a seemingly weird compilation case. >>> Consider the following Java interface: >>> >>> import java.util.function.Supplier; >>> >>> interface Main { >>> ? ? interface X { >>> ? ? ? ? X self(); >>> ? ? } >>> >>> ? ? static X makeX() {return null;} >>> >>> ? ? static X create(Supplier supplier) >>> {return null;} >>> >>> ? ? static X> methodRef() { >>> ? ? ? ? return create(Main::makeX).self(); >>> ? ? } >>> >>> ? ? static X> lambda() { >>> ? ? ? ? return create(() -> makeX()).self(); >>> ? ? } >>> } >>> >>> I expect that either both methods 'methodRef' and 'lambda' >>> should be compilable or both should be non-compilable. >>> However, while 'methodRef' compiles, 'lambda' is rejected by >>> compiler (using javac?build 25+36-3489): >>> >>> Main.java:17: error: incompatible types: X> cannot >>> be converted to X> >>> ? ? ? ? return create(() -> makeX()).self(); >>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^ >>> ? where CAP#1 is a fresh type-variable: >>> ? ? CAP#1 extends Object from capture of ? >>> 1 error >>> error: compilation failed >>> >>> Could you please help me and clarify whether this is an >>> expected behavior or not? >>> >>> With best regards, >>> Tagir Valeev >> > ​ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From cstein at openjdk.org Fri Oct 10 15:13:56 2025 From: cstein at openjdk.org (Christian Stein) Date: Fri, 10 Oct 2025 15:13:56 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. Usually @shipilev is kind and quick to provide them here: https://builds.shipilev.net/jtreg/ Mind his warning and motto, though: > WARNING: These artifacts are not well-tested, not virus-checked, may contain horrible bugs that could lead to data corruption, engulfing machines in flames, sharing your financial data, selling your pets on eBay, etc. etc. etc. everything that applies for binaries^W code^W anything downloaded from the Internet. Be cautious. If in doubt, build from the source yourself, and/or run on staging environment that is not painful to restore. > > Our motto: "[builds.shipilev.net](https://builds.shipilev.net/) ? still more secure than npm install" ------------- PR Comment: https://git.openjdk.org/jdk/pull/27719#issuecomment-3390690779 From cushon at openjdk.org Fri Oct 10 15:26:29 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Fri, 10 Oct 2025 15:26:29 GMT Subject: RFR: 8369508: Type annotations on anonymous new class creation expressions can't be retrieved [v2] In-Reply-To: References: Message-ID: <_ESmaroFK9q4FrDFTEJQNa_DhdJm1U3vZrmXZ-zKE80=.cd6e1dd3-21f2-4c02-99ac-e88686bbf649@github.com> > Hi, > > Please consider this fix for [JDK-8369508: Type annotations on anonymous new class creation expressions can't be retrieved](https://bugs.openjdk.org/browse/JDK-8369508). > > When visiting a type annotation on an anonymous class instantiation expression, javac currently skips attribution of the annotated type when visiting it as part of the `new` expression, to prevent them from being incorrectly attached to the enclosing method instead of the synthetic declaration of the anonymous class (see [JDK-8198945](https://bugs.openjdk.org/browse/JDK-8198945)). However because this logic happens early, and results in skipping attribution of these annotations, they aren't available on the type model elements for the new class creation expression, which means they can't be retrieved by clients of the compiler tree API. > > This fix shifts the handling of these annotations later, to allow them to get attributed, but then to still prevent them from being attached to the enclosing method symbol of the anonymous class declaration. Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Reorder an assertion ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27730/files - new: https://git.openjdk.org/jdk/pull/27730/files/27785441..bc796344 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27730&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27730&range=00-01 Stats: 4 lines in 1 file changed: 2 ins; 2 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27730.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27730/head:pull/27730 PR: https://git.openjdk.org/jdk/pull/27730 From vromero at openjdk.org Fri Oct 10 15:43:18 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 10 Oct 2025 15:43:18 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference [v3] In-Reply-To: References: Message-ID: > Given the following test case: > > > import java.util.function.Supplier; > interface Main { > interface X { > X self(); > } > > static X makeX() {return null;} > > static X create(Supplier supplier) {return null;} > > static X> methodRef() { > return create(Main::makeX).self(); > } > > static X> lambda() { > return create(() -> makeX()).self(); > } > } > > > javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: updating test ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27737/files - new: https://git.openjdk.org/jdk/pull/27737/files/41783b0f..53f7d475 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27737&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27737&range=01-02 Stats: 4 lines in 2 files changed: 0 ins; 0 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/27737.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27737/head:pull/27737 PR: https://git.openjdk.org/jdk/pull/27737 From vromero at openjdk.org Fri Oct 10 17:26:33 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 10 Oct 2025 17:26:33 GMT Subject: RFR: 8367499: Refactor exhaustiveness computation from Flow into a separate class [v3] In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 15:31:26 GMT, Jan Lahoda wrote: >> Currently the switch exhaustiveness computation code is part of `Flow`. And while conceptually the check is part of the `Flow` phase, the code is >500 lines of code currently, and likely to get bigger/more complicated in the future. Among other reasons due to enhancements like https://bugs.openjdk.org/browse/JDK-8367530. >> >> The proposal herein is to move the exhaustiveness computation to a separate class `ExhastivenessComputer`. There's no functional change, only move of the code. This is intentional, to aid the review process. >> >> One possibility to inspect what is happening is: >> >> git show upstream/pr/27247:src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/Flow-original.java >> diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java >/tmp/exhaustivenesscomputer-comparison.diff >> diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/flow-comparison.diff >> >> and inspecting `/tmp/exhaustivenesscomputer-comparison.diff`, `/tmp/flow-comparison.diff`. > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains three commits: > > - Merge branch 'JDK-8364991' into JDK-8367499 > - Adding doc comment. > - 8367499: Refactor exhaustiveness computation from Flow into a separate class lgtm, looks clean ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27253#pullrequestreview-3324919291 From mcimadamore at openjdk.org Fri Oct 10 18:40:02 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 10 Oct 2025 18:40:02 GMT Subject: RFR: 8369517: Compilation mismatch for equivalent lambda and method reference [v3] In-Reply-To: References: Message-ID: On Fri, 10 Oct 2025 15:43:18 GMT, Vicente Romero wrote: >> Given the following test case: >> >> >> import java.util.function.Supplier; >> interface Main { >> interface X { >> X self(); >> } >> >> static X makeX() {return null;} >> >> static X create(Supplier supplier) {return null;} >> >> static X> methodRef() { >> return create(Main::makeX).self(); >> } >> >> static X> lambda() { >> return create(() -> makeX()).self(); >> } >> } >> >> >> javac reports an error for the method reference but not for the lambda. There should be no difference here (error in both cases) > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > updating test Marked as reviewed by mcimadamore (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27737#pullrequestreview-3325361885 From vromero at openjdk.org Sat Oct 11 01:54:08 2025 From: vromero at openjdk.org (Vicente Romero) Date: Sat, 11 Oct 2025 01:54:08 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v2] In-Reply-To: References: Message-ID: On Wed, 1 Oct 2025 05:47:23 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Simplifying the code as suggested. test/langtools/tools/javac/patterns/Exhaustiveness.java line 2195: > 2193: private int test(Root r) { > 2194: return switch (r) { > 2195: case Root(R1 _, _, _) -> 0; should we add a similar test with generic records? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2422367499 From ascarpino at openjdk.org Sat Oct 11 01:54:52 2025 From: ascarpino at openjdk.org (Anthony Scarpino) Date: Sat, 11 Oct 2025 01:54:52 GMT Subject: RFR: 8360564: Implement JEP 524: PEM Encodings of Cryptographic Objects (Second Preview) [v5] In-Reply-To: References: Message-ID: > Hi > > Please review the [Second Preview](https://openjdk.org/jeps/8360563) for the PEM API. The most significant changes from [JEP 470](https://openjdk.org/jeps/470) are: > > - Renamed the name of `PEMRecord` class to `PEM`. > - Revised the new `encryptKey` methods of the `EncryptedPrivateKeyInfo` class to accept `DEREncodable` objects rather than just `PrivateKey` objects so that cryptographic objects with public keys, i.e., `KeyPair` and `PKCS8EncodedKeySpec`, can also be encrypted. > - Enhanced the `PEMEncoder` and `PEMDecoder` classes to support the encryption and decryption of `KeyPair` and `PKCS8EncodedKeySpec` objects. > > thanks > > Tony Anthony Scarpino has updated the pull request incrementally with two additional commits since the last revision: - major doc update, change to encrypt() - update preview ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27147/files - new: https://git.openjdk.org/jdk/pull/27147/files/e13bff47..db913c3c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27147&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27147&range=03-04 Stats: 566 lines in 11 files changed: 177 ins; 154 del; 235 mod Patch: https://git.openjdk.org/jdk/pull/27147.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27147/head:pull/27147 PR: https://git.openjdk.org/jdk/pull/27147 From jpai at openjdk.org Mon Oct 13 11:14:08 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Mon, 13 Oct 2025 11:14:08 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. Marked as reviewed by jpai (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27719#pullrequestreview-3331114106 From pminborg at openjdk.org Mon Oct 13 11:51:02 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 11:51:02 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) Message-ID: Implement JEP 526: Lazy Constants (Second Preview) The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. The old benchmarks are not moved/renamed to allow comparison with previous releases. `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. ------------- Commit messages: - Add optimization where the computing function is returned directly - Add benchmark of Optionals - Merge branch 'master' into lazy-constants - Update src/java.base/share/classes/java/lang/LazyConstant.java - Update src/java.base/share/classes/java/util/LazyCollections.java - Fix failing test - Clean up - Merge branch 'master' into lazy-constants - Update JEP number - Fix doc issues - ... and 76 more: https://git.openjdk.org/jdk/compare/1605e839...3e287031 Changes: https://git.openjdk.org/jdk/pull/27605/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8366178 Stats: 8721 lines in 60 files changed: 4112 ins; 4490 del; 119 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From duke at openjdk.org Mon Oct 13 11:51:02 2025 From: duke at openjdk.org (ExE Boss) Date: Mon, 13 Oct 2025 11:51:02 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <8VsjXECvVSYRtKpK4PId8s_8RM0T00n4BzmfO6RTinM=.e1bb59c4-8a85-4d3c-8980-249cd529b50b@github.com> On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. I?m?gonna?miss **Stable?Values**, as?it?has some?use?cases which?aren?t?served by?**Lazy?Constants**, and?on?which I?depend?on in?some of?my?code, so?I?m stuck?with using?regular non?`final`?fields. -------------------------------------------------------------------------------- Also, in the [JEP?526]?table under ?[Flexible?initialization with?lazy?constants]?: > | | Update count | Update location | Constant folding? | Concurrent updates? > | -------------- | ------------ | --------------- | ----------------- | ------------------- > | `final` field | 1 | Constructor or static initializer | Yes | No > | `LazyConstant` | [0, 1] | Anywhere | Yes, after initialization | Yes, by winner > | Non-`final` field | [0, ?) | Anywhere | No | Yes The??Update?location? of?`LazyConstant` shouldn?t?be??Anywhere?, as?that?was only?accurate for?`StableValue`, but?not for?`LazyConstant`, which?is?updated by?calling the?passed `Supplier`. Similarly, concurrent?updates are?prevented for?`LazyConstant`s by?using `synchronized?(this)`. [JEP?526]: https://openjdk.org/jeps/526 [Flexible?initialization with?lazy?constants]: https://openjdk.org/jeps/526#Flexible-initialization-with-lazy-constants Getting?access to?the?underlying `StableValue`?API with?**Lazy?Constants** is?way?too?hacky and?convoluted (but?doable):
StableVar.java /* * Any copyright is dedicated to the Public Domain. * https://creativecommons.org/publicdomain/zero/1.0/ */ import java.util.NoSuchElementException; import java.util.function.Supplier; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; import static java.lang.System.identityHashCode; import static java.util.Objects.requireNonNull; /// Horrible awful hack to get access to raw stable values in JDK 26+. @NullMarked public sealed interface StableVar permits StableHacks.StableVarImpl { boolean trySet(final T contents) throws NullPointerException, IllegalStateException; @Nullable T orNull(); T orElse(final T other) throws NullPointerException; T orElseThrow() throws NoSuchElementException; boolean isSet(); T orElseSet(final Supplier supplier) throws NullPointerException, IllegalStateException; void setOrThrow(final T contents) throws NullPointerException, IllegalStateException; static StableVar of() { return StableHacks.newInstance(); } } /// Encapsulates the actual implementation of `StableValue` on `LazyConstant` /// /// @author ExE Boss @NullMarked /*package*/ final @Namespace class StableHacks { private StableHacks() throws InstantiationException { throw new InstantiationException(StableHacks.class.getName()); } private static final String UNSET_SUFFIX = ".unset"; private static final Object UNSET = new Object() { @Override public int hashCode() { return 0; } @Override public String toString() { return "unset"; } }; private static final ScopedValue SCOPE = ScopedValue.newInstance(); private static final Supplier SCOPE_GETTER = SCOPE::get; /*package*/ static final StableVarImpl newInstance() { return new StableValue<>(); } /*package*/ sealed interface StableVarImpl extends StableVar { } private record StableValue( // Implemented as a record so that the JVM treats this as a trusted final field // even when `-XX:+TrustFinalNonStaticFields` is not set LazyConstant contents ) implements StableVarImpl { @SuppressWarnings("unchecked") private StableValue() { this(LazyConstant.of((Supplier) SCOPE_GETTER)); } private StableValue { if (contents.isInitialized()) throw new InternalError(); } @SuppressWarnings("unchecked") private final ScopedValue scope() { return (ScopedValue) SCOPE; } private final void preventReentry() throws IllegalStateException { if (Thread.holdsLock(this)) { throw new IllegalStateException("Recursive initialization of a stable value is illegal"); } } @Override public boolean trySet(final T contents) throws NullPointerException, IllegalStateException { requireNonNull(contents); if (this.contents.isInitialized()) return false; preventReentry(); synchronized (this) { return this.setImpl(contents); } } @Override @SuppressWarnings("unchecked") public final @Nullable T orNull() { return unwrapUnset(((LazyConstant) this.contents).orElse(UNSET)); } @Override public T orElse(T other) throws NullPointerException { return this.contents.orElse(other); } @Override public T orElseThrow() throws NoSuchElementException { { final T contents; if ((contents = this.orNull()) != null) { return contents; } } throw new NoSuchElementException(); } @Override public boolean isSet() { return this.contents.isInitialized(); } @Override public T orElseSet(final Supplier supplier) throws NullPointerException, IllegalStateException { requireNonNull(supplier); { final T contents; if ((contents = this.orNull()) != null) { return contents; } } return orElseSetSlowPath(supplier); } @Override public void setOrThrow(final T contents) throws NullPointerException, IllegalStateException { if (!trySet(contents)) { throw new IllegalStateException(); } } private final T orElseSetSlowPath( final Supplier supplier ) throws NullPointerException, IllegalStateException { preventReentry(); synchronized (this) { { final T contents; if ((contents = this.orNull()) != null) { return contents; } } final T newValue; this.setImpl(newValue = requireNonNull(supplier.get())); return newValue; } } private final boolean setImpl(final T contents) { assert Thread.holdsLock(this); if (this.contents.isInitialized()) { return false; } ScopedValue.where(this.scope(), contents).run(this.contents::get); return true; } @Override public final boolean equals(final Object obj) { return this == obj; } @Override public final int hashCode() { return identityHashCode(this); } @Override public String toString() { final Object contents; return renderValue( "StableValue", (contents = this.orNull()) != this ? contents : "(this StableValue)" ); } } @SuppressWarnings("unchecked") private static final @Nullable T unwrapUnset(final @Nullable Object obj) { return (obj == UNSET) ? null : (T) obj; } private static final String renderValue( final String type, final @Nullable Object value ) throws NullPointerException { return (value == null) ? type.concat(UNSET_SUFFIX) : (type + '[' + value + ']'); } }
------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3367784825 PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3368298279 From liach at openjdk.org Mon Oct 13 11:51:04 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:04 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: <8VsjXECvVSYRtKpK4PId8s_8RM0T00n4BzmfO6RTinM=.e1bb59c4-8a85-4d3c-8980-249cd529b50b@github.com> References: <8VsjXECvVSYRtKpK4PId8s_8RM0T00n4BzmfO6RTinM=.e1bb59c4-8a85-4d3c-8980-249cd529b50b@github.com> Message-ID: On Sat, 4 Oct 2025 14:29:08 GMT, ExE Boss wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Getting?access to?the?underlying `StableValue`?API with?**Lazy?Constants** is?way?too?hacky and?convoluted (but?doable): >
> StableVar.java > > > /* > * Any copyright is dedicated to the Public Domain. > * https://creativecommons.org/publicdomain/zero/1.0/ > */ > > import java.util.NoSuchElementException; > import java.util.function.Supplier; > > import org.jspecify.annotations.NullMarked; > import org.jspecify.annotations.Nullable; > > import static java.lang.System.identityHashCode; > import static java.util.Objects.requireNonNull; > > /// Horrible awful hack to get access to raw stable values in JDK 26+. > @NullMarked > public sealed interface StableVar permits StableHacks.StableVarImpl { > boolean trySet(final T contents) throws NullPointerException, IllegalStateException; > @Nullable T orNull(); > T orElse(final T other) throws NullPointerException; > T orElseThrow() throws NoSuchElementException; > boolean isSet(); > T orElseSet(final Supplier supplier) throws NullPointerException, IllegalStateException; > void setOrThrow(final T contents) throws NullPointerException, IllegalStateException; > > static StableVar of() { > return StableHacks.newInstance(); > } > } > > /// Encapsulates the actual implementation of `StableValue` on `LazyConstant` > /// > /// @author ExE Boss > @NullMarked > /*package*/ final @Namespace class StableHacks { > private StableHacks() throws InstantiationException { throw new InstantiationException(StableHacks.class.getName()); } > > private static final String UNSET_SUFFIX = ".unset"; > private static final Object UNSET = new Object() { > @Override > public int hashCode() { > return 0; > } > > @Override > public String toString() { > return "unset"; > } > }; > > private static final ScopedValue SCOPE = ScopedValue.newInstance(); > private static final Supplier SCOPE_GETTER = SCOPE::get; > > /*package*/ static final StableVarImpl newInstance() { > return new StableValue<>(); > } > > /*package*/ sealed interface StableVarImpl extends StableVar { > } > > private record StableValue( > // Implemented as a record so that the JVM treats this as a trusted final field > // even when `-XX:+TrustFinalNonStaticFields` is not set > LazyConstant contents > ) implements StableVarImpl { > @SuppressWarnings("unchecked") > private StableValue() { > this(LazyConstant.of((Supplier) SCOPE_GETTER)); > } > > private StableValue { > if (contents.isInitialized()) throw new InternalError(); > } > > @SuppressWarnings("unchecked") > private fi... Hi @ExE-Boss, this new JEP describes how this functionality will be provided in the future: > Lazy constants cover the common, high-level use cases for lazy initialization. In the future we might consider providing stable access semantics directly, at a lower level, for reference, array, and primitive fields. This would address, for example, use cases where the computing function associated with a lazy constant is not known at construction. This would be necessary, as there are usage patterns (such as nominal descriptors in ClassFile API) that would benefit from multiple assignment and a stable promoted read. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3368317631 From duke at openjdk.org Mon Oct 13 11:51:05 2025 From: duke at openjdk.org (Burning_TNT) Date: Mon, 13 Oct 2025 11:51:05 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. It's essential to provide a low-level API as those in StableValue. Completely migrating to factory pattern may forcing users to build their own LazyConstant wrapper as ExeBoss has down above. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3369054838 From pminborg at openjdk.org Mon Oct 13 11:51:05 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 11:51:05 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <5N4q67er51rXJ8E1oqNY4gCowyJ_K4x1SCeWncz1dFY=.2fe20197-fffe-467f-a1af-5816594c7e78@github.com> On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > I?m?gonna?miss **Stable?Values**, as?it?has some?use?cases which?aren?t?served by?**Lazy?Constants**, and?on?which I?depend?on in?some of?my?code, so?I?m stuck?with using?regular non?`final`?fields. > > Also, in the [JEP?526](https://openjdk.org/jeps/526)?table under ?[Flexible?initialization with?lazy?constants](https://openjdk.org/jeps/526#Flexible-initialization-with-lazy-constants)?: > > > Update count > > Update location > > Constant folding? > > Concurrent updates? > > > > > > > > > > `final` field > > 1 > > Constructor or static initializer > > Yes > > No > > > > > > `LazyConstant` > > [0, 1] > > Anywhere > > Yes, after initialization > > Yes, by winner > > > > > > Non-`final` field > > [0, ?) > > Anywhere > > No > > Yes > > The??Update?location? of?`LazyConstant` shouldn?t?be??Anywhere?, as?that?was only?accurate for?`StableValue`, but?not for?`LazyConstant`, which?is?updated by?calling the?passed `Supplier`. > > Similarly, concurrent?updates are?prevented for?`LazyConstant`s by?using `synchronized?(this)`. I've updated the JEP. Thanks for pointing out this. Let me know what you think about the new text. We are exploring better ways to provide low-level, imperative, lazy constant/stable value fields. This work will be done outside the current JEP. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3396693041 PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3397160926 From duke at openjdk.org Mon Oct 13 11:51:06 2025 From: duke at openjdk.org (ExE Boss) Date: Mon, 13 Oct 2025 11:51:06 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: <5N4q67er51rXJ8E1oqNY4gCowyJ_K4x1SCeWncz1dFY=.2fe20197-fffe-467f-a1af-5816594c7e78@github.com> References: <5N4q67er51rXJ8E1oqNY4gCowyJ_K4x1SCeWncz1dFY=.2fe20197-fffe-467f-a1af-5816594c7e78@github.com> Message-ID: On Mon, 13 Oct 2025 09:49:16 GMT, Per Minborg wrote: > I've updated the JEP. Thanks for pointing out this. Let me know what you think about the new text. The?change was?made to?the?wrong?row (?Non?`final`?field? instead of??`LazyConstant`?). ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3396866550 From fandreuzzi at openjdk.org Mon Oct 13 11:51:09 2025 From: fandreuzzi at openjdk.org (Francesco Andreuzzi) Date: Mon, 13 Oct 2025 11:51:09 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <9oTBJDVY4LhEXsE4tVJAItdEvmaA3YcZ0BbUrw7M9uk=.86f99b3a-fbb2-4ce4-916d-e0487fce4211@github.com> On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/lang/LazyConstant.java line 166: > 164: * > 165: *

Performance

> 166: * As a lazy constant can never change after it has been initialized. Therefore, Suggestion: * A lazy constant can never change after it has been initialized. Therefore, src/java.base/share/classes/java/util/LazyCollections.java line 80: > 78: } > 79: > 80: @Override public boolean isEmpty() { return size == 0;} Suggestion: @Override public boolean isEmpty() { return size == 0; } ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399059426 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399074220 From duke at openjdk.org Mon Oct 13 11:51:10 2025 From: duke at openjdk.org (Kerman) Date: Mon, 13 Oct 2025 11:51:10 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/util/Optional.java line 74: > 72: * If non-null, the value; if null, indicates no value is present > 73: */ > 74: @Stable Shouldn?t this also add a null sentinel to allow the folding of the empty case? Or is that irrelevant because empty would be the terminator of a chain. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399352909 From liach at openjdk.org Mon Oct 13 11:51:11 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:11 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> On Thu, 2 Oct 2025 16:16:44 GMT, Kerman wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > src/java.base/share/classes/java/util/Optional.java line 74: > >> 72: * If non-null, the value; if null, indicates no value is present >> 73: */ >> 74: @Stable > > Shouldn?t this also add a null sentinel to allow the folding of the empty case? Or is that irrelevant because empty would be the terminator of a chain. Usually a null sentinel is used when null indicates something different. I think maybe to allow folding the empty case, we should probably add a new annotation or a new element-value to indicate this status and properly handle it in C1/C2 (similar to the field trusting in ciField) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2403729792 From pminborg at openjdk.org Mon Oct 13 11:51:11 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 11:51:11 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> References: <-lErHk2PzyJCaPQGrEwCt3nObTrTHs7_p53eBXspUGE=.50dc2375-8769-49a5-9308-ab40132bbd19@github.com> Message-ID: On Sat, 4 Oct 2025 04:13:05 GMT, Chen Liang wrote: >> src/java.base/share/classes/java/util/Optional.java line 74: >> >>> 72: * If non-null, the value; if null, indicates no value is present >>> 73: */ >>> 74: @Stable >> >> Shouldn?t this also add a null sentinel to allow the folding of the empty case? Or is that irrelevant because empty would be the terminator of a chain. > > Usually a null sentinel is used when null indicates something different. I think maybe to allow folding the empty case, we should probably add a new annotation or a new element-value to indicate this status and properly handle it in C1/C2 (similar to the field trusting in ciField) I've added two new benchmarks: private static final LazyConstant> OPTIONAL_42 = LazyConstant.of(() -> Optional.of(42)); private static final LazyConstant> OPTIONAL_42_2 = LazyConstant.of(() -> Optional.of(42)); private static final LazyConstant> OPTIONAL_EMPTY = LazyConstant.of(Optional::empty); private static final LazyConstant> OPTIONAL_EMPTY2 = LazyConstant.of(Optional::empty); ... @Benchmark public int staticOptional42() { return OPTIONAL_42.get().orElseThrow() + OPTIONAL_42_2.get().orElseThrow(); } @Benchmark public boolean staticOptionalEmpty() { return OPTIONAL_EMPTY.get().isEmpty() ^ OPTIONAL_EMPTY2.get().isEmpty(); } Which gives: Benchmark Mode Cnt Score Error Units StableValueBenchmark.staticOptional42 avgt 10 0.354 ? 0.045 ns/op Benchmark Mode Cnt Score Error Units StableValueBenchmark.staticOptionalEmpty avgt 10 0.370 ? 0.030 ns/op So, both `Optional` variants appears to support constant folding. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426044826 From liach at openjdk.org Mon Oct 13 11:51:13 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:13 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/jdk/internal/lang/LazyConstantImpl.java line 171: > 169: > 170: public static LazyConstantImpl ofLazy(Supplier computingFunction) { > 171: return new LazyConstantImpl<>(computingFunction); We might return the function if it is already a LazyConstantImpl. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399678324 From duke at openjdk.org Mon Oct 13 11:51:14 2025 From: duke at openjdk.org (Jefferson Quesado) Date: Mon, 13 Oct 2025 11:51:14 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/sun/nio/ch/Net.java line 99: > 97: } > 98: > 99: private static final LazyConstant SHUTDOWN_WRITE_BEFORE_CLOSE = LazyConstant.of(new Supplier() { I wonder if there is a reason for not using `BooleanSupplier`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2399205774 From liach at openjdk.org Mon Oct 13 11:51:15 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 13 Oct 2025 11:51:15 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 15:21:37 GMT, Jefferson Quesado wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > src/java.base/share/classes/sun/nio/ch/Net.java line 99: > >> 97: } >> 98: >> 99: private static final LazyConstant SHUTDOWN_WRITE_BEFORE_CLOSE = LazyConstant.of(new Supplier() { > > I wonder if there is a reason for not using `BooleanSupplier`. Unfortunately, BooleanSupplier does not extend Supplier. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2403730001 From jlahoda at openjdk.org Mon Oct 13 12:00:55 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 13 Oct 2025 12:00:55 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v3] In-Reply-To: References: Message-ID: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Adding tests with generic records. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27247/files - new: https://git.openjdk.org/jdk/pull/27247/files/0ee60862..026dc4c8 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=01-02 Stats: 81 lines in 1 file changed: 81 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From mcimadamore at openjdk.org Mon Oct 13 13:08:03 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:08:03 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. test/jdk/java/lang/LazyConstant/DemoImperativeTest.java line 25: > 23: > 24: /* @test > 25: * @summary Demo of an imperative stable value based on a lazy constant Should this summary be updated (and. some of the classes defined here) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426297364 From mcimadamore at openjdk.org Mon Oct 13 13:20:38 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:20:38 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/util/LazyCollections.java line 255: > 253: } > 254: > 255: interface LenientList extends List { Ok, this seems needed to give access to `getAcquire` from sublists created from other sublists... src/java.base/share/classes/java/util/LazyCollections.java line 360: > 358: > 359: @Stable > 360: private final Set keySet; I believe putting the field in here might cause some redundancies -- for instance LazyMap extends this class and addss a `Map`, from which you can clearly derive the key set... ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426326166 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426329562 From mcimadamore at openjdk.org Mon Oct 13 13:30:34 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:30:34 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/lang/LazyConstant.java line 42: > 40: > 41: /** > 42: * A lazy constant is a deferred, shallowly immutable constant to be computed at It seems like the javadoc is a snapshot of an earlier version of the JEP where the word "content" was replaced with "constant". I think we should go back to "content" and say (as we did for stable values) that a "A lazy constant is a holder of contents that can be set at most once." ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426358262 From mcimadamore at openjdk.org Mon Oct 13 13:34:33 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:34:33 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: <56kNzRwD6WRl9bHJUKb-YU1TuN6Tha_crXrwvfb-EmU=.c601a0b2-a66f-4d7f-9952-d235ee935fb1@github.com> On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/lang/LazyConstant.java line 98: > 96: * constant is not initialized. > 97: *

> 98: * If the computing function throws any unchecked exception or Error, that Throwable add some code blocks around `Error` and `Throwable` ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426369216 From mcimadamore at openjdk.org Mon Oct 13 13:40:56 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:40:56 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:35:21 GMT, Maurizio Cimadamore wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > src/java.base/share/classes/java/lang/LazyConstant.java line 157: > >> 155: * The computing function runs on the caller?s thread. >> 156: *

>> 157: * If a thread that is blocked by another computing thread is interrupted, this is not > > I'm not sure I understand what you mean in this para E.g. "thread that is blocked by another computing thread". Did you mean to say "if the thread running the computing function is interrupted"? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426381677 From mcimadamore at openjdk.org Mon Oct 13 13:40:54 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:40:54 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/lang/LazyConstant.java line 155: > 153: * {@code final} fields of any newly created objects, are safely published. > 154: *

> 155: * The computing function runs on the caller?s thread. Here you might define "we call that thread the computing thread" -- this might be useful when defining other concepts in this section (maybe) src/java.base/share/classes/java/lang/LazyConstant.java line 157: > 155: * The computing function runs on the caller?s thread. > 156: *

> 157: * If a thread that is blocked by another computing thread is interrupted, this is not I'm not sure I understand what you mean in this para src/java.base/share/classes/java/lang/LazyConstant.java line 172: > 170: * (e.g. in cases where the lazy constant itself is stored in a > 171: * {@code static final} field) or forms a trusted chain to such a VM constant via > 172: * one or more layers of a {@linkplain Record record} fields or final fields one or more layers of "trusted" fields -- then in parenthesis you say what these "trusted" fields are. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426383095 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426379186 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426387301 From mcimadamore at openjdk.org Mon Oct 13 13:46:48 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:46:48 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/lang/LazyConstant.java line 188: > 186: * arbitrary depth can be used, which provides constant components. > 187: * More generally, a lazy constant can hold other lazy constants of > 188: * arbitrary depth and still provide transitive constancy. I'm not sure the term "constancy" is common to mean constant-ness. I think it might be better to use the term "constant-folding" -- and then define "constant-folding" in the above "performance" section: > A lazy constant can never change after it has been initialized. Therefore, > a JVM implementation may, for an initialized lazy constant, elide all future reads > of that lazy constant, and instead directly use any constant that it has previously > observed Then you can add "we call this optimization constant-folding". src/java.base/share/classes/java/lang/LazyConstant.java line 192: > 190: * The {@code LazyConstant} type is not {@link Serializable}. > 191: *

> 192: * It is not recommended putting lazy constants into equality-based collections Not sure what you mean here. It seems like the javadoc for `equals` says that it triggers initialization, so it should be ok? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426397976 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426402669 From pminborg at openjdk.org Mon Oct 13 13:46:51 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 13:46:51 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:17:37 GMT, Maurizio Cimadamore wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > src/java.base/share/classes/java/util/LazyCollections.java line 360: > >> 358: >> 359: @Stable >> 360: private final Set keySet; > > I believe putting the field in here might cause some redundancies -- for instance LazyMap extends this class and addss a `Map`, from which you can clearly derive the key set... It is true that `AbstractMap` already contains a `keySet` field. If we annotate `AbstractMap.keySet` with `@Stable` (which seems ok to do), we can get rid of this field. A note here is that eventually, we would like to get rid of all the fields in `AbstractMap`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426399337 From mcimadamore at openjdk.org Mon Oct 13 13:50:07 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 13:50:07 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) In-Reply-To: References: Message-ID: On Thu, 2 Oct 2025 10:51:08 GMT, Per Minborg wrote: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. src/java.base/share/classes/java/lang/LazyConstant.java line 276: > 274: * this method might block or throw. > 275: * > 276: * @implSpec The order of potential initialization triggering is specified as: Do we really need to specify this? src/java.base/share/classes/java/lang/LazyConstant.java line 312: > 310: String toString(); > 311: > 312: // Factories Suggestion: // Factory ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426409576 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426412926 From pminborg at openjdk.org Mon Oct 13 13:54:44 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 13:54:44 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: References: Message-ID: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Remove redundant field ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/3e287031..0978179a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=00-01 Stats: 7 lines in 2 files changed: 3 ins; 3 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Oct 13 14:03:37 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:03:37 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v3] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Add links around Error and Throwable ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/0978179a..5770e033 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=01-02 Stats: 5 lines in 1 file changed: 0 ins; 0 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Oct 13 14:03:41 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:03:41 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v3] In-Reply-To: References: Message-ID: <0kU7XwB4vVkXnZLTj79Gen7puX7sPTKNfZwkf3I1wpM=.840e45e2-87bb-41ad-a4be-8d474458559d@github.com> On Mon, 13 Oct 2025 13:36:19 GMT, Maurizio Cimadamore wrote: >> src/java.base/share/classes/java/lang/LazyConstant.java line 157: >> >>> 155: * The computing function runs on the caller?s thread. >>> 156: *

>>> 157: * If a thread that is blocked by another computing thread is interrupted, this is not >> >> I'm not sure I understand what you mean in this para > > E.g. "thread that is blocked by another computing thread". Did you mean to say "if the thread running the computing function is interrupted"? If a thread `A` won the race and invokes the computing function, and another thread `B` comes along while computation takes place by `A`, then interrupting thread `B` will not have any effect. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426445641 From syan at openjdk.org Mon Oct 13 14:07:56 2025 From: syan at openjdk.org (SendaoYan) Date: Mon, 13 Oct 2025 14:07:56 GMT Subject: RFR: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. I have run the tests with jtreg8.1, and there is no new failure. ------------- Marked as reviewed by syan (Committer). PR Review: https://git.openjdk.org/jdk/pull/27719#pullrequestreview-3331786495 From pminborg at openjdk.org Mon Oct 13 14:13:42 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:13:42 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v4] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Reprhase text around the computing thread ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/5770e033..47af4307 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=02-03 Stats: 13 lines in 1 file changed: 1 ins; 2 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Oct 13 14:18:53 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:18:53 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v5] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Rephrase trusted field text ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/47af4307..ea14b8f9 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=03-04 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Oct 13 14:22:13 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:22:13 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v6] In-Reply-To: References: Message-ID: <5EAP5ubicOh_odm_aPlWJZbDQTuV0AIRs-fHlW7jTlc=.86692372-8a21-49dc-a453-4dbeef84d242@github.com> > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Define constant folding ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/ea14b8f9..e25eeb9b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=04-05 Stats: 7 lines in 1 file changed: 1 ins; 0 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Mon Oct 13 14:33:06 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:33:06 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Update src/java.base/share/classes/java/lang/LazyConstant.java Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/e25eeb9b..5845a7a5 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=05-06 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From mcimadamore at openjdk.org Mon Oct 13 14:33:08 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:33:08 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v6] In-Reply-To: <5EAP5ubicOh_odm_aPlWJZbDQTuV0AIRs-fHlW7jTlc=.86692372-8a21-49dc-a453-4dbeef84d242@github.com> References: <5EAP5ubicOh_odm_aPlWJZbDQTuV0AIRs-fHlW7jTlc=.86692372-8a21-49dc-a453-4dbeef84d242@github.com> Message-ID: On Mon, 13 Oct 2025 14:22:13 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Define constant folding src/java.base/share/classes/java/lang/LazyConstant.java line 156: > 154: * {@code final} fields of any newly created objects, are safely published. > 155: *

> 156: * If the computing thread or any thread that is blocked by the computing thread My worry here is that when we say "any thread that is blocked" we really meany "any thread". But in reality this javadoc only refers to threads that are trying to call `get` and end up blocked because some other thread won the race. E.g. if a thread is blocked by the computing thread for any other reason, we don't know whether interrupting that thread will result in an `InterruptedException` ? I think it might be worth simplifying this a bit, starting with the property you want to assert: > Thread interruption does not cancel initialization of a lazy constant. In other words, if the computing thread is > interrupted, `LazyConstant::get` doesn't clear the interrupted thread?s status is not cleared, nor does it throw > an `InterruptedException`. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426515394 From pminborg at openjdk.org Mon Oct 13 14:33:10 2025 From: pminborg at openjdk.org (Per Minborg) Date: Mon, 13 Oct 2025 14:33:10 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 13:44:07 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Update src/java.base/share/classes/java/lang/LazyConstant.java >> >> Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> > > src/java.base/share/classes/java/lang/LazyConstant.java line 192: > >> 190: * The {@code LazyConstant} type is not {@link Serializable}. >> 191: *

>> 192: * It is not recommended putting lazy constants into equality-based collections > > Not sure what you mean here. It seems like the javadoc for `equals` says that it triggers initialization, so it should be ok? Formally, it is ok, but may result in strange side effects if we, for example, put a key of type LazyConstant in a map. It will then be initialized immediately (upon `map.put()`), and the put operation can therefore have non-obvious side effects. > src/java.base/share/classes/java/lang/LazyConstant.java line 276: > >> 274: * this method might block or throw. >> 275: * >> 276: * @implSpec The order of potential initialization triggering is specified as: > > Do we really need to specify this? This is a corner case, but we might have two uninitialized LCs. The order in which they get computed might be significant (e.g., they operate on shared data structures). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426507366 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426513556 From mcimadamore at openjdk.org Mon Oct 13 14:33:13 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:33:13 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:25:58 GMT, Per Minborg wrote: >> src/java.base/share/classes/java/lang/LazyConstant.java line 276: >> >>> 274: * this method might block or throw. >>> 275: * >>> 276: * @implSpec The order of potential initialization triggering is specified as: >> >> Do we really need to specify this? > > This is a corner case, but we might have two uninitialized LCs. The order in which they get computed might be significant (e.g., they operate on shared data structures). I understand that the order might be significant -- but I still wonder if we should specify that order. This seems to add constraints to the implementation. Do we really want clients to rely on the order in which lazy constants are initialized when calling `equals` ? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426522315 From mcimadamore at openjdk.org Mon Oct 13 14:37:27 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:37:27 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:23:40 GMT, Per Minborg wrote: >> src/java.base/share/classes/java/lang/LazyConstant.java line 192: >> >>> 190: * The {@code LazyConstant} type is not {@link Serializable}. >>> 191: *

>>> 192: * It is not recommended putting lazy constants into equality-based collections >> >> Not sure what you mean here. It seems like the javadoc for `equals` says that it triggers initialization, so it should be ok? > > Formally, it is ok, but may result in strange side effects if we, for example, put a key of type LazyConstant in a map. It will then be initialized immediately (upon `map.put()`), and the put operation can therefore have non-obvious side effects. I think it would be better to link to `equals` more explicitly -- e.g. "As equals and hashCode might trigger the initialization of a lazy constant, it is recommended to avoid storing lazy constants into equality-based collections (or similar constructs) as their addition (e.g. via `Map::put`, or `Set::add`) might result in subtle side-effects). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426535831 From mcimadamore at openjdk.org Mon Oct 13 14:44:09 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 13 Oct 2025 14:44:09 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:33:06 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update src/java.base/share/classes/java/lang/LazyConstant.java > > Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> src/java.base/share/classes/java/lang/LazyConstant.java line 287: > 285: */ > 286: @Override > 287: boolean equals(Object obj); There is a tension here (same for hashCode). A lazy constant is a mutable cell that can be updated only once, given some computing function. When you compare two lazy constants, you can either compare the mutable cell (e.g. the pointer to the memory location where the constant will be eventually stored), or you can compare the constants. Here, the javadoc decides to opt for comparing the constants -- but this might be problematic, as now `equals` can throw exceptions too (and/or result in blocking, as you say in the javadoc). So, I'm not too sure what's the best option here -- do we have an idea of how frequent it is to want to compare two lazy constants "by value" ? (for reference, we have no precedent for this: `ClassValue`, `ScopedValue` and `ThreadLocal` do not redefine equals/hashCode). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426553275 From vromero at openjdk.org Mon Oct 13 15:05:31 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 13 Oct 2025 15:05:31 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v3] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 12:00:55 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Adding tests with generic records. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1070: > 1068: if (!rpOne.nested[i].equals(rpOther.nested[i])) { > 1069: if (useHashes) { > 1070: continue NEXT_PATTERN; I guess the code would be more readable if these labels and jumps could be (re)factored out. Another improvement in this sense could be using explicit types instead of `var` ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2426609372 From duke at openjdk.org Mon Oct 13 16:52:00 2025 From: duke at openjdk.org (ExE Boss) Date: Mon, 13 Oct 2025 16:52:00 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> References: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> Message-ID: On Mon, 13 Oct 2025 13:54:44 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Remove redundant field src/java.base/share/classes/java/util/AbstractMap.java line 335: > 333: */ > 334: @Stable > 335: transient Set keySet; Are?all?uses of?this?field in?`java.util` able?to?handle the?`@Stable`ness of?this?field correctly? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2426844190 From vromero at openjdk.org Mon Oct 13 17:14:04 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 13 Oct 2025 17:14:04 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v3] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 12:00:55 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Adding tests with generic records. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1079: > 1077: } > 1078: if (rpOne.nested[i] instanceof BindingPattern bpOne) { > 1079: if (!types.isSubtype(types.erasure(bpOne.type), types.erasure(bpOther.type))) { it seems from the description that the subtyping test is in the critical path when no hashes are being used. Would it make sense to use a cache and probably reduce the number of times we need to do the full fledged subtyping? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2426892058 From ascarpino at openjdk.org Mon Oct 13 17:22:25 2025 From: ascarpino at openjdk.org (Anthony Scarpino) Date: Mon, 13 Oct 2025 17:22:25 GMT Subject: RFR: 8360564: Implement JEP 524: PEM Encodings of Cryptographic Objects (Second Preview) [v6] In-Reply-To: References: Message-ID: > Hi > > Please review the [Second Preview](https://openjdk.org/jeps/8360563) for the PEM API. The most significant changes from [JEP 470](https://openjdk.org/jeps/470) are: > > - Renamed the name of `PEMRecord` class to `PEM`. > - Revised the new `encryptKey` methods of the `EncryptedPrivateKeyInfo` class to accept `DEREncodable` objects rather than just `PrivateKey` objects so that cryptographic objects with public keys, i.e., `KeyPair` and `PKCS8EncodedKeySpec`, can also be encrypted. > - Enhanced the `PEMEncoder` and `PEMDecoder` classes to support the encryption and decryption of `KeyPair` and `PKCS8EncodedKeySpec` objects. > > thanks > > Tony Anthony Scarpino has updated the pull request incrementally with one additional commit since the last revision: updates ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27147/files - new: https://git.openjdk.org/jdk/pull/27147/files/db913c3c..3e183c5a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27147&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27147&range=04-05 Stats: 21 lines in 3 files changed: 14 ins; 2 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/27147.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27147/head:pull/27147 PR: https://git.openjdk.org/jdk/pull/27147 From vromero at openjdk.org Tue Oct 14 00:20:07 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 14 Oct 2025 00:20:07 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v3] In-Reply-To: References: Message-ID: <1ai6gNBx5AWfUYsRK9kQG0YtvY_AefvZtgQ8rJ7cjAY=.19418379-6e5b-42c0-832f-1ce29fc14e72@github.com> On Mon, 13 Oct 2025 12:00:55 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Adding tests with generic records. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 805: > 803: } > 804: Set patterns = patternSet; > 805: Map> replaces = new IdentityHashMap<>(); why using IdentityHashMap here? won't this imply, potentially, having duplicated info in this map? I'm sure there is a good reason for this but not clear to me at first glance. Also if the implementation depends on this DS we should probably document it ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2427601654 From cstein at openjdk.org Tue Oct 14 08:57:51 2025 From: cstein at openjdk.org (Christian Stein) Date: Tue, 14 Oct 2025 08:57:51 GMT Subject: Integrated: 8369488: Update to use jtreg 8.1 In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 09:34:11 GMT, Christian Stein wrote: > Please review the change to update to using jtreg `8.1`. > > The primary change is to the `jib-profiles.js` file, which specifies the version of jtreg to use, for those systems that rely on this file. In addition, the `requiredVersion` has been updated in the various `TEST.ROOT` files. This pull request has now been integrated. Changeset: 702179e7 Author: Christian Stein URL: https://git.openjdk.org/jdk/commit/702179e7858bae1c7c13ad6eda3c4fbffdbb15db Stats: 11 lines in 9 files changed: 0 ins; 0 del; 11 mod 8369488: Update to use jtreg 8.1 Reviewed-by: iris, erikj, jpai, syan ------------- PR: https://git.openjdk.org/jdk/pull/27719 From asotona at openjdk.org Tue Oct 14 11:59:08 2025 From: asotona at openjdk.org (Adam Sotona) Date: Tue, 14 Oct 2025 11:59:08 GMT Subject: RFR: 8357809: Test jdk/jshell/JdiListeningExecutionControlTest.java failed with com.sun.jdi.connect.TransportTimeoutException In-Reply-To: References: Message-ID: On Mon, 6 Oct 2025 17:21:23 GMT, Jan Lahoda wrote: > The test timed-out while connecting to the remote agent over JDI. This PR proposes to try to increase the JDI connection timeout. Looks good to me. ------------- Marked as reviewed by asotona (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27653#pullrequestreview-3335208179 From darcy at openjdk.org Tue Oct 14 20:05:24 2025 From: darcy at openjdk.org (Joe Darcy) Date: Tue, 14 Oct 2025 20:05:24 GMT Subject: RFR: 8369851: Remove darcy author tags from langtools tests Message-ID: A little test cleanup to conform to current conventions of not using author tags. ------------- Commit messages: - JDK-8369851: Remove darcy author tags from langtools tests Changes: https://git.openjdk.org/jdk/pull/27808/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27808&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369851 Stats: 135 lines in 87 files changed: 1 ins; 67 del; 67 mod Patch: https://git.openjdk.org/jdk/pull/27808.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27808/head:pull/27808 PR: https://git.openjdk.org/jdk/pull/27808 From darcy at openjdk.org Tue Oct 14 20:40:42 2025 From: darcy at openjdk.org (Joe Darcy) Date: Tue, 14 Oct 2025 20:40:42 GMT Subject: RFR: 8369851: Remove darcy author tags from langtools tests [v2] In-Reply-To: References: Message-ID: > A little test cleanup to conform to current conventions of not using author tags. Joe Darcy has updated the pull request incrementally with one additional commit since the last revision: Fix copyright updates. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27808/files - new: https://git.openjdk.org/jdk/pull/27808/files/6fd9e8b3..9e5d98d8 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27808&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27808&range=00-01 Stats: 2 lines in 2 files changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27808.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27808/head:pull/27808 PR: https://git.openjdk.org/jdk/pull/27808 From vromero at openjdk.org Tue Oct 14 20:58:07 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 14 Oct 2025 20:58:07 GMT Subject: RFR: 8369851: Remove darcy author tags from langtools tests [v2] In-Reply-To: References: Message-ID: On Tue, 14 Oct 2025 20:40:42 GMT, Joe Darcy wrote: >> A little test cleanup to conform to current conventions of not using author tags. > > Joe Darcy has updated the pull request incrementally with one additional commit since the last revision: > > Fix copyright updates. lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27808#pullrequestreview-3337455686 From iris at openjdk.org Tue Oct 14 21:28:02 2025 From: iris at openjdk.org (Iris Clark) Date: Tue, 14 Oct 2025 21:28:02 GMT Subject: RFR: 8369851: Remove darcy author tags from langtools tests [v2] In-Reply-To: References: Message-ID: On Tue, 14 Oct 2025 20:40:42 GMT, Joe Darcy wrote: >> A little test cleanup to conform to current conventions of not using author tags. > > Joe Darcy has updated the pull request incrementally with one additional commit since the last revision: > > Fix copyright updates. Marked as reviewed by iris (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27808#pullrequestreview-3337556569 From darcy at openjdk.org Tue Oct 14 21:32:10 2025 From: darcy at openjdk.org (Joe Darcy) Date: Tue, 14 Oct 2025 21:32:10 GMT Subject: Integrated: 8369851: Remove darcy author tags from langtools tests In-Reply-To: References: Message-ID: On Tue, 14 Oct 2025 19:59:07 GMT, Joe Darcy wrote: > A little test cleanup to conform to current conventions of not using author tags. This pull request has now been integrated. Changeset: 70528bd3 Author: Joe Darcy URL: https://git.openjdk.org/jdk/commit/70528bd39925fabf23aad25f0a58a61f746ca9d8 Stats: 136 lines in 87 files changed: 1 ins; 67 del; 68 mod 8369851: Remove darcy author tags from langtools tests Reviewed-by: vromero, iris ------------- PR: https://git.openjdk.org/jdk/pull/27808 From jlahoda at openjdk.org Wed Oct 15 11:45:57 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 15 Oct 2025 11:45:57 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v4] In-Reply-To: References: Message-ID: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request incrementally with three additional commits since the last revision: - Caching isSubtype, as suggested. - Adding explanation to the replaces map. - Factoring out the 'substitutable' check, as suggested. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27247/files - new: https://git.openjdk.org/jdk/pull/27247/files/026dc4c8..11ee4dfa Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=02-03 Stats: 125 lines in 1 file changed: 76 ins; 39 del; 10 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From jlahoda at openjdk.org Wed Oct 15 13:32:05 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 15 Oct 2025 13:32:05 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v3] In-Reply-To: <1ai6gNBx5AWfUYsRK9kQG0YtvY_AefvZtgQ8rJ7cjAY=.19418379-6e5b-42c0-832f-1ce29fc14e72@github.com> References: <1ai6gNBx5AWfUYsRK9kQG0YtvY_AefvZtgQ8rJ7cjAY=.19418379-6e5b-42c0-832f-1ce29fc14e72@github.com> Message-ID: On Tue, 14 Oct 2025 00:17:38 GMT, Vicente Romero wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Adding tests with generic records. > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 805: > >> 803: } >> 804: Set patterns = patternSet; >> 805: Map> replaces = new IdentityHashMap<>(); > > why using IdentityHashMap here? won't this imply, potentially, having duplicated info in this map? I'm sure there is a good reason for this but not clear to me at first glance. It seems like we need to preserve like the `position` of the element being replaced. > > Also if the implementation depends on this DS we should probably document it. Yes, the identity map is intentional. It is entirely possible two equivalent types are produced from two different originating pattern sets, and when backtracking, we want to use the correct set. That is achieve by using the identity search. I've added a comment: https://github.com/openjdk/jdk/pull/27247/commits/51b7fc283e88ac5947cfebfce6609704c360e235 Thanks! > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1070: > >> 1068: if (!rpOne.nested[i].equals(rpOther.nested[i])) { >> 1069: if (useHashes) { >> 1070: continue NEXT_PATTERN; > > I guess the code would be more readable if these labels and jumps could be (re)factored out. Another improvement in this sense could be using explicit types instead of `var` I've moved this check into a separate method (https://github.com/openjdk/jdk/pull/27247/commits/9138ef6bbba63787796bb964b29d273a3d6c76b9), and added some comments. Looks much better, thanks! > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1079: > >> 1077: } >> 1078: if (rpOne.nested[i] instanceof BindingPattern bpOne) { >> 1079: if (!types.isSubtype(types.erasure(bpOne.type), types.erasure(bpOther.type))) { > > it seems from the description that the subtyping test is in the critical path when no hashes are being used. Would it make sense to use a cache and probably reduce the number of times we need to do the full fledged subtyping? I've added caching (https://github.com/openjdk/jdk/pull/27247/commits/11ee4dfaa7ddef03ecdb410df5cf0f39857b12c9), let's see how that will work. Thanks! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2432572924 PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2432564345 PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2432566198 From vromero at openjdk.org Wed Oct 15 17:16:27 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 15 Oct 2025 17:16:27 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v4] In-Reply-To: References: Message-ID: <5-oesAV_GaMFF1TMRE89XMjKHoxhbQUdZwqz4Fg1DmM=.b0d16486-fa47-4ef0-a818-6f4bc3f22466@github.com> On Wed, 15 Oct 2025 11:45:57 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with three additional commits since the last revision: > > - Caching isSubtype, as suggested. > - Adding explanation to the replaces map. > - Factoring out the 'substitutable' check, as suggested. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 763: > 761: } > 762: > 763: private final Map, Boolean> isSubtypeCache = new HashMap<>(); I think that you want to compare a type using Types::isSameType instead of Type::equals method. There is one cache that does this: Infer::incorporationCache. Although it could be that type identity comparison is enough for this application, dunno src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1123: > 1121: * the existing pattern > 1122: */ > 1123: private boolean nestedComponentsEquivalent(RecordPattern existing, yep looks better now, thanks! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2433301144 PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2433333979 From vromero at openjdk.org Wed Oct 15 17:16:29 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 15 Oct 2025 17:16:29 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v3] In-Reply-To: References: <1ai6gNBx5AWfUYsRK9kQG0YtvY_AefvZtgQ8rJ7cjAY=.19418379-6e5b-42c0-832f-1ce29fc14e72@github.com> Message-ID: On Wed, 15 Oct 2025 13:28:58 GMT, Jan Lahoda wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 805: >> >>> 803: } >>> 804: Set patterns = patternSet; >>> 805: Map> replaces = new IdentityHashMap<>(); >> >> why using IdentityHashMap here? won't this imply, potentially, having duplicated info in this map? I'm sure there is a good reason for this but not clear to me at first glance. It seems like we need to preserve like the `position` of the element being replaced. >> >> Also if the implementation depends on this DS we should probably document it. > > Yes, the identity map is intentional. It is entirely possible two equivalent types are produced from two different originating pattern sets, and when backtracking, we want to use the correct set. That is achieve by using the identity search. I've added a comment: > https://github.com/openjdk/jdk/pull/27247/commits/51b7fc283e88ac5947cfebfce6609704c360e235 > > Thanks! thanks for adding the comment! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2433326470 From vromero at openjdk.org Wed Oct 15 17:16:30 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 15 Oct 2025 17:16:30 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v3] In-Reply-To: References: <1ai6gNBx5AWfUYsRK9kQG0YtvY_AefvZtgQ8rJ7cjAY=.19418379-6e5b-42c0-832f-1ce29fc14e72@github.com> Message-ID: On Wed, 15 Oct 2025 16:50:52 GMT, Vicente Romero wrote: >> Yes, the identity map is intentional. It is entirely possible two equivalent types are produced from two different originating pattern sets, and when backtracking, we want to use the correct set. That is achieve by using the identity search. I've added a comment: >> https://github.com/openjdk/jdk/pull/27247/commits/51b7fc283e88ac5947cfebfce6609704c360e235 >> >> Thanks! > > thanks for adding the comment! to be honest, the problem I have with IdentityHashMap is that it has a lot of misses, at least that's that I saw while debugging some examples. What I saw was that in order to make sure that a given PatternDescription was not in the map, several keys in the table were visited. This somehow can kill the benefit of using a map as it can degenerate in some cases. So I wonder if it could be possible to define a key that takes into consideration the position of the JCRecordPattern we got the record pattern from, in order to make them "unique". Of course this is in the performance side and could be done in a follow-up patch ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2433383853 From jlahoda at openjdk.org Thu Oct 16 06:24:16 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 16 Oct 2025 06:24:16 GMT Subject: Integrated: 8357809: Test jdk/jshell/JdiListeningExecutionControlTest.java failed with com.sun.jdi.connect.TransportTimeoutException In-Reply-To: References: Message-ID: On Mon, 6 Oct 2025 17:21:23 GMT, Jan Lahoda wrote: > The test timed-out while connecting to the remote agent over JDI. This PR proposes to try to increase the JDI connection timeout. This pull request has now been integrated. Changeset: 5696d606 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/5696d60663f1bb917728808118fab3b346ed0341 Stats: 11 lines in 3 files changed: 7 ins; 0 del; 4 mod 8357809: Test jdk/jshell/JdiListeningExecutionControlTest.java failed with com.sun.jdi.connect.TransportTimeoutException Reviewed-by: asotona ------------- PR: https://git.openjdk.org/jdk/pull/27653 From pminborg at openjdk.org Thu Oct 16 12:10:32 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:10:32 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v7] In-Reply-To: References: Message-ID: On Mon, 13 Oct 2025 14:41:11 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Update src/java.base/share/classes/java/lang/LazyConstant.java >> >> Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> > > src/java.base/share/classes/java/lang/LazyConstant.java line 287: > >> 285: */ >> 286: @Override >> 287: boolean equals(Object obj); > > There is a tension here (same for hashCode). A lazy constant is a mutable cell that can be updated only once, given some computing function. When you compare two lazy constants, you can either compare the mutable cell (e.g. the pointer to the memory location where the constant will be eventually stored), or you can compare the constants. Here, the javadoc decides to opt for comparing the constants -- but this might be problematic, as now `equals` can throw exceptions too (and/or result in blocking, as you say in the javadoc). So, I'm not too sure what's the best option here -- do we have an idea of how frequent it is to want to compare two lazy constants "by value" ? > > (for reference, we have no precedent for this: `ClassValue`, `ScopedValue` and `ThreadLocal` do not redefine equals/hashCode). I have reverted back to the default Object::hashCode and Object::equals methods ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2435655625 From pminborg at openjdk.org Thu Oct 16 12:13:46 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:13:46 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: References: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> Message-ID: On Mon, 13 Oct 2025 16:48:07 GMT, ExE Boss wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Remove redundant field > > src/java.base/share/classes/java/util/AbstractMap.java line 335: > >> 333: */ >> 334: @Stable >> 335: transient Set keySet; > > Are?all?uses of?this?field in?`java.util` able?to?handle the?`@Stable`ness of?this?field correctly? That is a good question. The potentially different keySet values should be freely substitutable or else there seams to be something wrong. If they are FS, then the VM should be able to pick any. But it is a big assumption to say that *all* maps that extend AM behave in such a way. We could go back to the previous version and shadow the field. That seems safest. Note: there is work in progress to remove these fields. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2435668562 From pminborg at openjdk.org Thu Oct 16 12:23:26 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:23:26 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v8] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 94 additional commits since the last revision: - Revert back to Object::(hashCode/equals) - Merge branch 'master' into lazy-constants - Update src/java.base/share/classes/java/lang/LazyConstant.java Co-authored-by: Maurizio Cimadamore <54672762+mcimadamore at users.noreply.github.com> - Define constant folding - Rephrase trusted field text - Reprhase text around the computing thread - Add links around Error and Throwable - Remove redundant field - Add optimization where the computing function is returned directly - Add benchmark of Optionals - ... and 84 more: https://git.openjdk.org/jdk/compare/6cbed094...8fa4a4ca ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/5845a7a5..8fa4a4ca Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=06-07 Stats: 10612 lines in 265 files changed: 5868 ins; 4190 del; 554 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Thu Oct 16 12:33:31 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:33:31 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v9] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Rephrase docs on interrupt ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/8fa4a4ca..e6268f3d Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=07-08 Stats: 4 lines in 1 file changed: 0 ins; 1 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Thu Oct 16 12:37:35 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:37:35 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v10] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Update first javadoc sentence ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/e6268f3d..f5493909 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=09 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=08-09 Stats: 2 lines in 1 file changed: 0 ins; 1 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Thu Oct 16 12:41:56 2025 From: pminborg at openjdk.org (Per Minborg) Date: Thu, 16 Oct 2025 12:41:56 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v11] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Fix test descriptions ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/f5493909..a51f221a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=10 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=09-10 Stats: 2 lines in 2 files changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From vromero at openjdk.org Thu Oct 16 20:26:20 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 16 Oct 2025 20:26:20 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v4] In-Reply-To: References: Message-ID: On Wed, 15 Oct 2025 11:45:57 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with three additional commits since the last revision: > > - Caching isSubtype, as suggested. > - Adding explanation to the replaces map. > - Factoring out the 'substitutable' check, as suggested. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1066: > 1064: join.append(rpOne); > 1065: > 1066: for (int nextCandidate = 0; nextCandidate < candidatesArr.length; nextCandidate++) { can't the initializer be: `int nextCandidate = firstCandidate + 1`? probably saving some cycles ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27247#discussion_r2437373610 From pminborg at openjdk.org Fri Oct 17 09:25:01 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 09:25:01 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Update javadocs ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/a51f221a..6a6e804e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=11 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=10-11 Stats: 59 lines in 1 file changed: 7 ins; 3 del; 49 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From mcimadamore at openjdk.org Fri Oct 17 09:51:21 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 09:51:21 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 46: > 44: * A lazy constant is created using the factory method > 45: * {@linkplain LazyConstant#of(Supplier) LazyConstant.of({@code })}. > 46: * When created, the contents (and hence the lazy constant itself) is not initialized. "When created, the lazy constant is not initialized, meaning it has no contents." E.g. it's the lazy constant that is initialized/not initialized. The content "just is". (or "is not", if not initialized). src/java.base/share/classes/java/lang/LazyConstant.java line 47: > 45: * {@linkplain LazyConstant#of(Supplier) LazyConstant.of({@code })}. > 46: * When created, the contents (and hence the lazy constant itself) is not initialized. > 47: * The contents (of type {@code T}) can then be initialized Again, "a lazy constant can be initialized, and its content retrieved, by calling get" src/java.base/share/classes/java/lang/LazyConstant.java line 50: > 48: * (and retrieved) by calling {@linkplain #get()}. The first time {@linkplain #get()} > 49: * is called, the underlying computing function (provided at construction) will > 50: * be invoked and the result will be used to initialize the contents. Once initialized, "and the result will be used to initialize the lazy constant. Once a lazy constant is initialized, its contents can never change..." ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439058429 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439060624 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439064085 From mcimadamore at openjdk.org Fri Oct 17 09:56:18 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 09:56:18 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 54: > 52: * again upon subsequent {@linkplain #get() get} invocations. > 53: *

> 54: * A lazy constant is shallowly immutable, meaning the reference to the contents This para here seems a bit redundant. In part it repeats something already said (when initialized, contents will never change). I'd drop this from here, and maybe push it down to an API note (e.g. note: the contents of a lazy constant can be mutable -- e.g. an ArrayList). src/java.base/share/classes/java/lang/LazyConstant.java line 60: > 58: *

> 59: * Consider the following example where a lazy constant field "{@code logger}" is a > 60: * shallowly immutable holder of an object of type {@code Logger}: "where the lazy constant field "logger" holds an object of type Logger" src/java.base/share/classes/java/lang/LazyConstant.java line 77: > 75: *} > 76: *

> 77: * Initially, the lazy constant (and its contents) is not initialized. Suggestion: * Initially, the lazy constant is not initialized. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439072055 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439073774 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439075865 From mcimadamore at openjdk.org Fri Oct 17 10:08:22 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 10:08:22 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 101: > 99: * {@linkplain Error}, that {@linkplain Throwable} is propagated to the caller, and the > 100: * lazy constant remains uninitialized. In other words, upon an unsuccessful invocation of > 101: * the computing function, neither a constant, the exception, nor the fact that "In other words" I don't think this sentence adds much. I think it's better to just drop it. The main thing to say is that if computing function is unsuccessful, the lazy constant stays uninitialized (which we already said). src/java.base/share/classes/java/lang/LazyConstant.java line 111: > 109: * which are held by lazy constants: > 110: * > 111: * {@snippet lang = java: If you wanted, you could reuse the `Component` class -- that one already has a lazy constant field, so if you put the component itself in another lazy constant field you have your composition example. src/java.base/share/classes/java/lang/LazyConstant.java line 144: > 142: * > 143: *

Thread Safety

> 144: * A lazy constant is guaranteed to be initialized atomically and at most once. If We already mention some of these above: "Furthermore, {@linkplain #get()} guarantees that, out of several threads trying to * invoke the computing function simultaneously, only one is ever selected for * computation" Maybe add a reference form that text to this section? src/java.base/share/classes/java/lang/LazyConstant.java line 152: > 150: *

> 151: * The invocation of the computing function and the resulting initialization of > 152: * the constant {@linkplain java.util.concurrent##MemoryVisibility happens-before} Do you mean constant or content? I think the latter? E.g. when you initialize a lazy constant, you safely publish its contents? (the lazy constant itself is already published) src/java.base/share/classes/java/lang/LazyConstant.java line 158: > 156: * Thread interruption does not cancel the initialization of a lazy constant. In other > 157: * words, if the computing thread is interrupted, {@code LazyConstant::get} doesn't clear > 158: * the interrupted thread?s status, nor does it throw an InterruptedException. Suggestion: * the interrupted thread?s status, nor does it throw an {@code InterruptedException}. src/java.base/share/classes/java/lang/LazyConstant.java line 164: > 162: * > 163: *

Performance

> 164: * A lazy constant can never change after it has been initialized. Therefore, The contents of a lazy constant can never change after the lazy constant has been initialized (again, spell out things clearly) src/java.base/share/classes/java/lang/LazyConstant.java line 166: > 164: * A lazy constant can never change after it has been initialized. Therefore, > 165: * a JVM implementation may, for an initialized lazy constant, elide all future reads > 166: * of that lazy constant and instead directly use any constant that it has previously "elide all future reads of that lazy constant's contents and instead use the contents that has been previously observed" ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439091644 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439096445 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439102301 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439110166 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439114804 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439119542 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439124386 From mcimadamore at openjdk.org Fri Oct 17 10:20:09 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 10:20:09 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: <2V6nUv7mUoPV7kx6uQXMTM9D4Xdm-1xEK7ErgbEAdds=.0bc05925-08b5-4799-903c-04b9bfa4760d@github.com> On Fri, 17 Oct 2025 09:25:01 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update javadocs src/java.base/share/classes/java/lang/LazyConstant.java line 168: > 166: * of that lazy constant and instead directly use any constant that it has previously > 167: * observed. We call this optimization constant folding. This is only possible if > 168: * the reference to the lazy constant is a VM constant (e.g. in cases where Not sure talking about VM constant is good. We could alternatively say: "if the lazy constant is stored in a static final field, either directly, or indirectly, via one or more trusted fields (i.e. any combination...)" src/java.base/share/classes/java/lang/LazyConstant.java line 179: > 177: * must be non-null, or a {@link NullPointerException} will be thrown. > 178: * > 179: * @apiNote Once a lazy constant is initialized with an object, the object cannot ever be Once a lazy constant is initialized, its contents can never be removed... src/java.base/share/classes/java/lang/LazyConstant.java line 182: > 180: * removed. This can be a source of an unintended memory leak. More specifically, > 181: * a lazy constant {@linkplain java.lang.ref##reachability strongly references} > 182: * the object it was initialized with. Hence, a lazy constant will hold s/the object it was initialized with/its contents (here and below) src/java.base/share/classes/java/lang/LazyConstant.java line 186: > 184: * is collected (if ever). > 185: *

> 186: * A {@code LazyConstant} that has a type parameter {@code T} that is an "A lazy constant whose contents is an array will not optimize access to the the elements of such array. Instead, ..." src/java.base/share/classes/java/lang/LazyConstant.java line 191: > 189: * Instead, a {@linkplain List#ofLazy(int, IntFunction) lazy list} of > 190: * arbitrary depth can be used, which provides constant components. > 191: * More generally, a lazy constant can hold other lazy constants of More generally... you said that in the composition section? src/java.base/share/classes/java/lang/LazyConstant.java line 233: > 231: > 232: /** > 233: * {@return the initialized contents. If not initialized, first computes and "initialized contents" is not a term you have defined in this javadoc. `get` returns the contents of this lazy constant. If the lazy constant is not initialized... src/java.base/share/classes/java/lang/LazyConstant.java line 267: > 265: */ > 266: @Override > 267: String toString(); I think it might be worth also defining a javadoc for equals/hashCode, to say explicitly that they will also not trigger initialization src/java.base/share/classes/java/lang/LazyConstant.java line 284: > 282: * directly. > 283: * > 284: * @param computingFunction in the form of a Supplier to be used to compute Suggestion: * @param computingFunction a {@code Supplier} used to initialize ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439138229 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439141653 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439144255 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439156012 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439150170 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439161143 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439169909 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439174349 From mcimadamore at openjdk.org Fri Oct 17 10:25:47 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 10:25:47 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v12] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 09:25:01 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update javadocs src/java.base/share/classes/java/util/List.java line 1231: > 1229: * will be thrown. > 1230: *

> 1231: * The returned lazy list strongly references its computing We should say that hashCode/equals trigger computation src/java.base/share/classes/java/util/Map.java line 1784: > 1782: * will be thrown. > 1783: *

> 1784: * The returned lazy map strongly references its underlying Again, we should say that equals/hashCode triggers computation ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439200027 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2439207782 From pminborg at openjdk.org Fri Oct 17 11:43:47 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 11:43:47 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v13] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Update wording on List/Map Object methods ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/6a6e804e..8cde6974 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=12 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=11-12 Stats: 12 lines in 2 files changed: 12 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From jlahoda at openjdk.org Fri Oct 17 11:45:52 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 17 Oct 2025 11:45:52 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v5] In-Reply-To: References: Message-ID: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Avoiding the use of IdentityHashMap. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27247/files - new: https://git.openjdk.org/jdk/pull/27247/files/11ee4dfa..25d1b956 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=03-04 Stats: 42 lines in 1 file changed: 12 ins; 12 del; 18 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From jlahoda at openjdk.org Fri Oct 17 11:56:50 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 17 Oct 2025 11:56:50 GMT Subject: RFR: 8369489: Marker annotation on inner class access crashes javac compiler Message-ID: Consider code like: I i = @Ann Object[]::new; the initializer is a method reference over an array type, whose component is annotated - that follows from the grammar in JLS 4.3, and also matches what is parsed for code like: I i = (@Ann Object[]) null; But, the javac's parser will create a method reference, whose type is an annotated type - which is wrong. And also fails if the array type as such is also annotated. The proposal herein is to simply use `insertAnnotationsToMostInner` to put the annotation at the correct place, as is done on other similar places. This one attaches the annotation at the correct nesting level. Sadly, the code may be something very broken like: I i = @Ann foobar()::new; and `insertAnnotationsToMostInner` would fail for this code/AST. Hence if the method reference is not over a type, we'll create an `AnnotatedType` (to keep the info in the AST as before) + an error + an error AST node. ------------- Commit messages: - Fixing error recovery. - Adjusting member ref position to sensible values. - 8369489: Marker annotation on inner class access crashes javac compiler Changes: https://git.openjdk.org/jdk/pull/27864/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27864&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369489 Stats: 249 lines in 4 files changed: 240 ins; 5 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/27864.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27864/head:pull/27864 PR: https://git.openjdk.org/jdk/pull/27864 From pminborg at openjdk.org Fri Oct 17 12:13:48 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 12:13:48 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v14] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Improve equals/hashCode document ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/8cde6974..77ae3fe1 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=13 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=12-13 Stats: 19 lines in 1 file changed: 16 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Fri Oct 17 12:28:15 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 12:28:15 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v15] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Improve method docs ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/77ae3fe1..e2c24f5c Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=14 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=13-14 Stats: 10 lines in 1 file changed: 1 ins; 0 del; 9 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Fri Oct 17 13:13:45 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 13:13:45 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Update docs after comments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/e2c24f5c..d961426d Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=15 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=14-15 Stats: 58 lines in 1 file changed: 3 ins; 16 del; 39 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Fri Oct 17 14:06:44 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:06:44 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v17] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Revert the AbstractMap.keySet @Stable annotation ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/d961426d..698b4125 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=16 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=15-16 Stats: 5 lines in 2 files changed: 4 ins; 1 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Fri Oct 17 14:10:39 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:10:39 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v2] In-Reply-To: References: <90jKH5-Bb3vf27uhLPOUtgmYmZRFdH1voVYr8kIR__I=.2aff8cb2-38be-4dd3-a1df-e3f8a7a90542@github.com> Message-ID: On Thu, 16 Oct 2025 12:10:51 GMT, Per Minborg wrote: >> src/java.base/share/classes/java/util/AbstractMap.java line 335: >> >>> 333: */ >>> 334: @Stable >>> 335: transient Set keySet; >> >> Are?all?uses of?this?field in?`java.util` able?to?handle the?`@Stable`ness of?this?field correctly? > > That is a good question. The potentially different keySet values should be freely substitutable or else there seams to be something wrong. If they are FS, then the VM should be able to pick any. But it is a big assumption to say that *all* maps that extend AM behave in such a way. We could go back to the previous version and shadow the field. That seems safest. > > Note: there is work in progress to remove these fields. I've reverted the @Stable annotation on AM.keySet. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440164233 From mcimadamore at openjdk.org Fri Oct 17 14:17:54 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 14:17:54 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] In-Reply-To: References: Message-ID: <_kXdqyWalfyZNF_Bhnuw9NQh-9x3cutCQEB-r72fLR4=.aaadf47e-46d7-43d2-99dc-c6e0da1f8ad6@github.com> On Fri, 17 Oct 2025 13:13:45 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update docs after comments src/java.base/share/classes/java/lang/LazyConstant.java line 154: > 152: * > 153: *

Performance

> 154: * The contents of lazy constant can never change after it has been initialized. Therefore, Suggestion: * The contents of a lazy constant can never change after it has been initialized. Therefore, ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440185045 From mcimadamore at openjdk.org Fri Oct 17 14:30:06 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 14:30:06 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 14:23:28 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Update docs after comments > > src/java.base/share/classes/java/util/List.java line 1235: > >> 1233: * or more lazy elements. The returned list's {@linkplain Object#toString() toString()} >> 1234: * method never triggers initialization of elements. Instead, an >> 1235: * implementation-dependant string is returned for uninitialized elements. > > Suggestion: > > * implementation-dependent string is returned for uninitialized elements. Design comment: I note some internal discomfort at the fact that equals/hashCode trigger initialization, but toString does not... effectively this would make replacing a regular immutable list with a lazy list not possible in all cases. Not saying we should do anything now -- but something to monitor ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440214527 From mcimadamore at openjdk.org Fri Oct 17 14:30:05 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 14:30:05 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v16] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 13:13:45 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update docs after comments src/java.base/share/classes/java/lang/LazyConstant.java line 157: > 155: * a JVM implementation may, for an initialized lazy constant, elide all future reads of > 156: * that lazy constant's contents and instead use the contents that has been previously > 157: * observed. We call this optimization constant folding. This is only possible This is still not ok. First, there seems to be some typo ("if the reference to the lazy constant in a static final field or..."). Secondly, trusted chain _to_ such field. I think it's the other way around, the trusted chain starts at a static final field, and then eventually gets to the lazy constant, possibly traversing one or more trusted fields. src/java.base/share/classes/java/lang/LazyConstant.java line 174: > 172: * the lazy constant itself is collected (if ever). > 173: *

> 174: * A lazy constant whose contents is an array will not optimize access to "While it's possible to store an array inside a lazy constant, doing so will not result in improved access to the array elements. Instead ..." src/java.base/share/classes/java/lang/LazyConstant.java line 289: > 287: * > 288: * @param computingFunction in the form of a {@linkplain Supplier} to be used > 289: * to compute the constant s/compute/initialize (e.g. the term "compute the constant" is not defined anywhere) src/java.base/share/classes/java/util/List.java line 1235: > 1233: * or more lazy elements. The returned list's {@linkplain Object#toString() toString()} > 1234: * method never triggers initialization of elements. Instead, an > 1235: * implementation-dependant string is returned for uninitialized elements. Suggestion: * implementation-dependent string is returned for uninitialized elements. src/java.base/share/classes/java/util/Map.java line 1788: > 1786: * or more lazy values. The returned maps's {@linkplain Object#toString() toString()} > 1787: * method never triggers initialization of values. Instead, an > 1788: * implementation-dependant string is returned for uninitialized values. Suggestion: * implementation-dependent string is returned for uninitialized values. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440193622 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440203445 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440207743 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440209019 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2440216157 From pminborg at openjdk.org Fri Oct 17 14:29:55 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:29:55 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v18] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 104 additional commits since the last revision: - Merge branch 'master' into lazy-constants - Revert the AbstractMap.keySet @Stable annotation - Update docs after comments - Improve method docs - Improve equals/hashCode document - Update wording on List/Map Object methods - Update javadocs - Fix test descriptions - Update first javadoc sentence - Rephrase docs on interrupt - ... and 94 more: https://git.openjdk.org/jdk/compare/e2f6db0f...fc064e47 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/698b4125..fc064e47 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=17 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=16-17 Stats: 8176 lines in 211 files changed: 4888 ins; 2457 del; 831 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From pminborg at openjdk.org Fri Oct 17 14:58:44 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 17 Oct 2025 14:58:44 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v19] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Update after doc comments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/fc064e47..6721ca4a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=18 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=17-18 Stats: 14 lines in 3 files changed: 1 ins; 0 del; 13 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From jlahoda at openjdk.org Fri Oct 17 16:19:11 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 17 Oct 2025 16:19:11 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static In-Reply-To: References: Message-ID: <0VQamQ6Lcz3nkvVmvWAo_ip6qO_AuR7gx9oxTIUHV20=.cd6d67b1-d39b-492b-9ecf-04ea82c78667@github.com> On Tue, 7 Oct 2025 15:37:46 GMT, Chen Liang wrote: >> Consider a JShell interaction like: >> >> jshell> class O { class I {} } >> | created class O >> >> jshell> var i = new O().new I(); >> i ==> O$I at 77caeb3e >> >> jshell> class O { static class I {} } >> Exception in thread "main" java.lang.ClassFormatError: class not in class file format >> at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) >> at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) >> at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) >> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) >> at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) >> at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) >> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) >> at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) >> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) >> at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) >> at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) >> at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) >> at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) >> at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) >> at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) >> at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) >> at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) >> at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) >> ... > > src/jdk.jshell/share/classes/jdk/jshell/execution/JdiExecutionControl.java line 93: > >> 91: } catch (EngineTerminationException ex) { >> 92: throw ex; >> 93: } catch (Exception | LinkageError ex) { > > How was ClassFormatError previously thrown here? Was it wrapped in some exception? It was simply thrown out of the redefine method, as the stacktrace in the summary suggests. Note that the javadoc for `redefineClasses` is very clear it may throw `ClassFormatError`: https://docs.oracle.com/en/java/javase/25/docs/api/jdk.jdi/com/sun/jdi/VirtualMachine.html#redefineClasses(java.util.Map) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27665#discussion_r2440518160 From mcimadamore at openjdk.org Fri Oct 17 16:35:20 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 16:35:20 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static In-Reply-To: References: Message-ID: On Tue, 7 Oct 2025 07:15:50 GMT, Jan Lahoda wrote: > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... javac changes look good (did not look at the jshell part) src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java line 3155: > 3153: name = names.one; > 3154: ClassSymbol member = enterClass(name, outer); > 3155: if ((member.flags_field & FROM_SOURCE) == 0) { I agree with the fix -- I guess I'd slightly prefer to see a warning if a mismatch is detected, but I'll leave that to you. ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27665#pullrequestreview-3351081584 PR Review Comment: https://git.openjdk.org/jdk/pull/27665#discussion_r2440559516 From vromero at openjdk.org Fri Oct 17 17:29:05 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 17 Oct 2025 17:29:05 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v5] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 11:45:52 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Avoiding the use of IdentityHashMap. last changes look good, thanks. I will take another look after the rebasement ------------- PR Comment: https://git.openjdk.org/jdk/pull/27247#issuecomment-3416450723 From mcimadamore at openjdk.org Fri Oct 17 19:58:08 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 17 Oct 2025 19:58:08 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v19] In-Reply-To: References: Message-ID: <2Ow8e38mfpHtFTbD5kUe4BKOaWACguUWAfKwerScgMg=.228371ce-d23d-4dc2-816c-ce80c7da7771@github.com> On Fri, 17 Oct 2025 14:58:44 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update after doc comments src/java.base/share/classes/java/lang/LazyConstant.java line 161: > 159: * to a lazy constant or if there is a chain from a {@code static final} field -- via one > 160: * or more trusted fields (i.e., {@code static final} fields, > 161: * {@linkplain Record record} fields, lazy constants, lazy lists, lazy maps, lazy constants and lazy lists/maps are not themselves "trusted final fields" (at least not yet), so not sure they belong here? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2441086058 From duke at openjdk.org Sat Oct 18 01:07:11 2025 From: duke at openjdk.org (ExE Boss) Date: Sat, 18 Oct 2025 01:07:11 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v19] In-Reply-To: <2Ow8e38mfpHtFTbD5kUe4BKOaWACguUWAfKwerScgMg=.228371ce-d23d-4dc2-816c-ce80c7da7771@github.com> References: <2Ow8e38mfpHtFTbD5kUe4BKOaWACguUWAfKwerScgMg=.228371ce-d23d-4dc2-816c-ce80c7da7771@github.com> Message-ID: <7R8km2ZfztfyDcrUvjd_5P85J7pBMsxAIY-tP76jnTc=.d4311603-0098-4f89-84b3-f073bec00a4d@github.com> On Fri, 17 Oct 2025 19:55:42 GMT, Maurizio Cimadamore wrote: >> Per Minborg has updated the pull request incrementally with one additional commit since the last revision: >> >> Update after doc comments > > src/java.base/share/classes/java/lang/LazyConstant.java line 161: > >> 159: * to a lazy constant or if there is a chain from a {@code static final} field -- via one >> 160: * or more trusted fields (i.e., {@code static final} fields, >> 161: * {@linkplain Record record} fields, lazy constants, lazy lists, lazy maps, > > lazy constants and lazy lists/maps are not themselves "trusted final fields" (at least not yet), so not sure they belong here? The?`@Stable`?annotation makes?fields with?non?`null`?values into?trusted?fields when?the?class is?loaded by?a?platform class?loader. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2441495949 From jlahoda at openjdk.org Mon Oct 20 05:45:53 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 20 Oct 2025 05:45:53 GMT Subject: RFR: 8367499: Refactor exhaustiveness computation from Flow into a separate class [v4] In-Reply-To: References: Message-ID: > Currently the switch exhaustiveness computation code is part of `Flow`. And while conceptually the check is part of the `Flow` phase, the code is >500 lines of code currently, and likely to get bigger/more complicated in the future. Among other reasons due to enhancements like https://bugs.openjdk.org/browse/JDK-8367530. > > The proposal herein is to move the exhaustiveness computation to a separate class `ExhastivenessComputer`. There's no functional change, only move of the code. This is intentional, to aid the review process. > > One possibility to inspect what is happening is: > > git show upstream/pr/27247:src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/Flow-original.java > diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java >/tmp/exhaustivenesscomputer-comparison.diff > diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/flow-comparison.diff > > and inspecting `/tmp/exhaustivenesscomputer-comparison.diff`, `/tmp/flow-comparison.diff`. Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits: - Cleanup. - 8367499: Refactor exhaustiveness computation from Flow into a separate class ------------- Changes: https://git.openjdk.org/jdk/pull/27253/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27253&range=03 Stats: 1146 lines in 2 files changed: 605 ins; 538 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/27253.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27253/head:pull/27253 PR: https://git.openjdk.org/jdk/pull/27253 From jlahoda at openjdk.org Mon Oct 20 05:47:41 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 20 Oct 2025 05:47:41 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v2] In-Reply-To: References: Message-ID: > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 26 commits: - Better visualisation. - Merge branch 'JDK-8367499' into JDK-8367530 - Merge branch 'JDK-8364991' into JDK-8367499 - Simplifying the code as suggested. - Fixing tests. - Cleanup. - Cleanup. - Cleanup. - Enabling disabled test. - Cleanup, making timeout work. - ... and 16 more: https://git.openjdk.org/jdk/compare/3355a9d3...38089d18 ------------- Changes: https://git.openjdk.org/jdk/pull/27256/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=01 Stats: 2457 lines in 14 files changed: 1906 ins; 521 del; 30 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From jlahoda at openjdk.org Mon Oct 20 05:49:59 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 20 Oct 2025 05:49:59 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v6] In-Reply-To: References: Message-ID: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 557 additional commits since the last revision: - Merge branch 'JDK-8367499-2' into JDK-8364991 - 8367499: Refactor exhaustiveness computation from Flow into a separate class - 8369685: RISC-V: refactor code related to RVFeatureValue::enabled Reviewed-by: fyang, rehn - 8369814: G1: Relax card mark and store ordering Reviewed-by: tschatzl, fandreuzzi - 8342659: Test vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java failed: Class nsk.share.jdi.TestClass1 was not unloaded Co-authored-by: Chris Plummer Reviewed-by: sspitsyn, cjplummer - 8369979: Flag UsePopCountInstruction was accidentally disabled on PPC64 Reviewed-by: aph, mdoerr - 8369924: Remove test/jdk/javax/management/remote/mandatory/loading/MissingClassTest.java from problemlist Reviewed-by: sspitsyn - 8341381: Random lines appear in graphic causing by the fix of JDK-8297230 Reviewed-by: prr - 8068310: [TEST_BUG] Test javax/swing/JColorChooser/Test4234761.java fails with GTKL&F Reviewed-by: serb - 8342401: [TESTBUG] javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java test fails in ubuntu 22.04 on SBR Hosts Reviewed-by: honkar, serb - ... and 547 more: https://git.openjdk.org/jdk/compare/25d1b956...0290ecb0 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27247/files - new: https://git.openjdk.org/jdk/pull/27247/files/25d1b956..0290ecb0 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=04-05 Stats: 205929 lines in 2817 files changed: 158796 ins; 30484 del; 16649 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From jlahoda at openjdk.org Mon Oct 20 05:50:39 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 20 Oct 2025 05:50:39 GMT Subject: RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v3] In-Reply-To: References: Message-ID: > Consider case like (from the bug): > > class Demo { > > sealed interface Base permits Special, Value {} > > non-sealed interface Value extends Base {} > > sealed interface Special extends Base permits SpecialValue {} > > non-sealed interface SpecialValue extends Value, Special {} > > static int demo(final Base base) { > return switch (base) { > case final Value value -> 0; > // Uncommenting the following line will make javac accept this program > //case final Special value -> throw new AssertionError(); > }; > > } > > } > > > This fails to compile: > > /tmp/Demo.java:12: error: the switch expression does not cover all possible input values > return switch (base) { > ^ > 1 error > > > Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input. > > Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code: > > case final Value value -> 0; > => > case final SpecialValue value -> 0; > > $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java > $ > > > Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac). > > javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive. > > The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes. Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 14 commits: - Merge branch 'JDK-8367499-2' into JDK-8366968-2 - Cleanup. - Cleanup. - Merge branch 'JDK-8367499-2' into JDK-8366968-2 - Removing trailing whitespace. - There are no relevant permitted subtypes of a non-abstract class, not even the class itself. - 8366968: Exhaustive switch expression rejected by for not covering all possible values - Adding doc comment. - 8367499: Refactor exhaustiveness computation from Flow into a separate class - Adding test. - ... and 4 more: https://git.openjdk.org/jdk/compare/5bec3156...ef63b5cc ------------- Changes: https://git.openjdk.org/jdk/pull/27547/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=02 Stats: 70 lines in 2 files changed: 62 ins; 2 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/27547.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27547/head:pull/27547 PR: https://git.openjdk.org/jdk/pull/27547 From jlahoda at openjdk.org Mon Oct 20 05:54:31 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 20 Oct 2025 05:54:31 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v3] In-Reply-To: References: Message-ID: <4haXoYHh46riqTQdh7-vQQTpyjZcT4p9kItvAyZUcbI=.adb64c2c-635e-4493-bb41-36b7e77e08b6@github.com> > Consider code like: > > package test; > public class Test { > private int test(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > ``` > > This is missing a case for `Root(R2(R2 _), R2(R2 _))`. javac will produce an error correctly, but the error is not very helpful: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > The goal of this PR is to improve the error, at least in some cases to something along these lines: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > missing patterns: > test.Test.Root(test.Test.R2(test.Test.R2 _), test.Test.R2(test.Test.R2 _)) > 1 error > > > The (very simplified) way it works in a recursive (or induction) way: > - start with defining the missing pattern as the binding pattern for the selector type. This would certainly exhaust the switch. > - for a current missing pattern, try to enhance it: > - if the current type is a sealed type, try to expand to its (direct) permitted subtypes. Remove those that are not needed. > - if the current (binding pattern) type is a record type, expand it to a record type, generate all possible combinations of its component types based on sealed hierarchies. Remove those that are not needed. > > This approach relies heavily on our ability to compute exhaustiveness, which is evaluated repeatedly in the process. > > There are some cases where the algorithm does not produce ideal results (see the tests), but overall seems much better than what we have now. > > Another significant limitation is the speed of the process. Evaluating exhaustiveness is not a fast process, and this algorithm evaluates exhaustiveness repeatedly, potentially for many combinations of patterns (esp. for record patterns). So part of the proposal here is to have a time deadline for the computation. The default is 5s, and can be changed by `-XDexhaustivityTimeout=`. > > There's also an open possibility for select tools to delay the more detailed computation to some later time, although that would need to be tried and eval... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 22 commits: - Fixing tests - Merge branch 'JDK-8364991-2' into JDK-8367530-2 - Better visualisation. - Merge branch 'JDK-8367499' into JDK-8367530 - Merge branch 'JDK-8364991' into JDK-8367499 - Fixing tests. - Cleanup. - Cleanup. - Cleanup. - Enabling disabled test. - ... and 12 more: https://git.openjdk.org/jdk/compare/0290ecb0...b79bce1f ------------- Changes: https://git.openjdk.org/jdk/pull/27256/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=02 Stats: 1326 lines in 15 files changed: 1233 ins; 43 del; 50 mod Patch: https://git.openjdk.org/jdk/pull/27256.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27256/head:pull/27256 PR: https://git.openjdk.org/jdk/pull/27256 From cushon at openjdk.org Mon Oct 20 14:44:06 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Mon, 20 Oct 2025 14:44:06 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations Message-ID: Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). ------------- Commit messages: - 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations Changes: https://git.openjdk.org/jdk/pull/27901/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370237 Stats: 28 lines in 3 files changed: 28 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27901.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27901/head:pull/27901 PR: https://git.openjdk.org/jdk/pull/27901 From abimpoudis at openjdk.org Mon Oct 20 15:33:46 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Mon, 20 Oct 2025 15:33:46 GMT Subject: RFR: 8359145: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) Message-ID: Draft PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview) ------------- Commit messages: - 8359145: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) Changes: https://git.openjdk.org/jdk/pull/27637/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8359145 Stats: 788 lines in 17 files changed: 739 ins; 2 del; 47 mod Patch: https://git.openjdk.org/jdk/pull/27637.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27637/head:pull/27637 PR: https://git.openjdk.org/jdk/pull/27637 From vromero at openjdk.org Mon Oct 20 16:04:05 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 20 Oct 2025 16:04:05 GMT Subject: RFR: 8367499: Refactor exhaustiveness computation from Flow into a separate class [v4] In-Reply-To: References: Message-ID: On Mon, 20 Oct 2025 05:45:53 GMT, Jan Lahoda wrote: >> Currently the switch exhaustiveness computation code is part of `Flow`. And while conceptually the check is part of the `Flow` phase, the code is >500 lines of code currently, and likely to get bigger/more complicated in the future. Among other reasons due to enhancements like https://bugs.openjdk.org/browse/JDK-8367530. >> >> The proposal herein is to move the exhaustiveness computation to a separate class `ExhastivenessComputer`. There's no functional change, only move of the code. This is intentional, to aid the review process. >> >> One possibility to inspect what is happening is: >> >> git show upstream/pr/27247:src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/Flow-original.java >> diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java >/tmp/exhaustivenesscomputer-comparison.diff >> diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/flow-comparison.diff >> >> and inspecting `/tmp/exhaustivenesscomputer-comparison.diff`, `/tmp/flow-comparison.diff`. > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits: > > - Cleanup. > - 8367499: Refactor exhaustiveness computation from Flow into a separate class Marked as reviewed by vromero (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27253#pullrequestreview-3357056666 From vromero at openjdk.org Mon Oct 20 16:50:06 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 20 Oct 2025 16:50:06 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v6] In-Reply-To: References: Message-ID: On Mon, 20 Oct 2025 05:49:59 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 557 additional commits since the last revision: > > - Merge branch 'JDK-8367499-2' into JDK-8364991 > - 8367499: Refactor exhaustiveness computation from Flow into a separate class > - 8369685: RISC-V: refactor code related to RVFeatureValue::enabled > > Reviewed-by: fyang, rehn > - 8369814: G1: Relax card mark and store ordering > > Reviewed-by: tschatzl, fandreuzzi > - 8342659: Test vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java failed: Class nsk.share.jdi.TestClass1 was not unloaded > > Co-authored-by: Chris Plummer > Reviewed-by: sspitsyn, cjplummer > - 8369979: Flag UsePopCountInstruction was accidentally disabled on PPC64 > > Reviewed-by: aph, mdoerr > - 8369924: Remove test/jdk/javax/management/remote/mandatory/loading/MissingClassTest.java from problemlist > > Reviewed-by: sspitsyn > - 8341381: Random lines appear in graphic causing by the fix of JDK-8297230 > > Reviewed-by: prr > - 8068310: [TEST_BUG] Test javax/swing/JColorChooser/Test4234761.java fails with GTKL&F > > Reviewed-by: serb > - 8342401: [TESTBUG] javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java test fails in ubuntu 22.04 on SBR Hosts > > Reviewed-by: honkar, serb > - ... and 547 more: https://git.openjdk.org/jdk/compare/25d1b956...0290ecb0 lgtm, nice job! ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27247#pullrequestreview-3357213136 From davidalayachew at gmail.com Tue Oct 21 02:54:20 2025 From: davidalayachew at gmail.com (David Alayachew) Date: Mon, 20 Oct 2025 22:54:20 -0400 Subject: JShell should add a tab if a new line is entered after an opening parentheses. Message-ID: Hello @compiler-dev , Sometimes, when using JShell, I like to write code like this. Stream.of( some(complex(expression)), another(kind, of(complex, expression)), you(get, the, idea) ) .parallel() .map(...) .forEach(...) ; But when typing the above in JShell, the 3 expressions in the call to Stream.of() are not indented. And in fact, even if I manually indent the first expression, JShell will require me to do the same for the following lines. There's a couple of different ways to go about this. Maybe JShell could be smarter about realizing where its current indent should be. For example, it could just follow the indent of the previous line. That would let the user pick the indent of their choice. But from what little I have read of the JShell codebase, it sounds like it would just be easiest to just make open parentheses + new line = increment indent. What do you think? Thank you for your time and consideration. David Alayachew -------------- next part -------------- An HTML attachment was scrubbed... URL: From jlahoda at openjdk.org Tue Oct 21 07:25:15 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 21 Oct 2025 07:25:15 GMT Subject: Integrated: 8367499: Refactor exhaustiveness computation from Flow into a separate class In-Reply-To: References: Message-ID: <4eYDVOv9_i7Z5pgNZ23iE7rihJAcuyJgR-7aWP6oWKs=.f236ecf3-ce98-4b1c-9409-bdb16167b182@github.com> On Fri, 12 Sep 2025 09:49:14 GMT, Jan Lahoda wrote: > Currently the switch exhaustiveness computation code is part of `Flow`. And while conceptually the check is part of the `Flow` phase, the code is >500 lines of code currently, and likely to get bigger/more complicated in the future. Among other reasons due to enhancements like https://bugs.openjdk.org/browse/JDK-8367530. > > The proposal herein is to move the exhaustiveness computation to a separate class `ExhastivenessComputer`. There's no functional change, only move of the code. This is intentional, to aid the review process. > > One possibility to inspect what is happening is: > > git show upstream/master:src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/Flow-original.java > diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java >/tmp/exhaustivenesscomputer-comparison.diff > diff -d -w /tmp/Flow-original.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java >/tmp/flow-comparison.diff > > and inspecting `/tmp/exhaustivenesscomputer-comparison.diff`, `/tmp/flow-comparison.diff`. This pull request has now been integrated. Changeset: 430041d3 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/430041d366ddf450c2480c81608dde980dfa6d41 Stats: 1146 lines in 2 files changed: 605 ins; 538 del; 3 mod 8367499: Refactor exhaustiveness computation from Flow into a separate class Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/27253 From jlahoda at openjdk.org Tue Oct 21 11:15:54 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 21 Oct 2025 11:15:54 GMT Subject: RFR: 8366691: JShell should support a more convenient completion Message-ID: JShell tool has the code completion feature in the terminal, allowing to tab-complete inputs. The JShell engine also has an API to compute the completions. But, the API is more suitable for a terminal-based UI, not for a GUI. The goal in this PR is to provide an API that would allow better code completions in GUI frontends for JShell. The main idea here is that the user of the API will get information could the context and `Element` that can continue the current input, and can produce UI elements/strings out of this information as necessary. The apidiff for the current API is available here: https://cr.openjdk.org/~jlahoda/8366691/JDK-8366691.00/ ------------- Commit messages: - Fixing test - Adding test for the active parameter. - Adding parameter index. - Merge branch 'master' into JDK-8366691 - Merge branch 'JDK-8368848' into JDK-8366691 - 8368848: JShell's code completion not always working for multi-snippet inputs - Ability to get real type. - Fixing(?) anchor. - Merge branch 'master' into JDK-8366691 - Fixing tests. - ... and 22 more: https://git.openjdk.org/jdk/compare/dfd38322...084654a9 Changes: https://git.openjdk.org/jdk/pull/27049/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27049&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8366691 Stats: 954 lines in 8 files changed: 792 ins; 73 del; 89 mod Patch: https://git.openjdk.org/jdk/pull/27049.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27049/head:pull/27049 PR: https://git.openjdk.org/jdk/pull/27049 From jlahoda at openjdk.org Tue Oct 21 11:25:38 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 21 Oct 2025 11:25:38 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v7] In-Reply-To: References: Message-ID: <9tTMfRjmfWhUBHKxOSnqc_FXFhZ21HucWbcP03q09zY=.0804751a-3fd4-4570-8361-cf9ddb510c7a@github.com> > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 14 commits: - Merge branch 'master' into JDK-8364991 - Merge branch 'JDK-8367499-2' into JDK-8364991 - 8367499: Refactor exhaustiveness computation from Flow into a separate class - Avoiding the use of IdentityHashMap. - Caching isSubtype, as suggested. - Adding explanation to the replaces map. - Factoring out the 'substitutable' check, as suggested. - Adding tests with generic records. - Simplifying the code as suggested. - Adding test. - ... and 4 more: https://git.openjdk.org/jdk/compare/ea7186a8...ba70f898 ------------- Changes: https://git.openjdk.org/jdk/pull/27247/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=06 Stats: 299 lines in 2 files changed: 259 ins; 17 del; 23 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From jlahoda at openjdk.org Tue Oct 21 11:28:57 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 21 Oct 2025 11:28:57 GMT Subject: RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v4] In-Reply-To: References: Message-ID: > Consider case like (from the bug): > > class Demo { > > sealed interface Base permits Special, Value {} > > non-sealed interface Value extends Base {} > > sealed interface Special extends Base permits SpecialValue {} > > non-sealed interface SpecialValue extends Value, Special {} > > static int demo(final Base base) { > return switch (base) { > case final Value value -> 0; > // Uncommenting the following line will make javac accept this program > //case final Special value -> throw new AssertionError(); > }; > > } > > } > > > This fails to compile: > > /tmp/Demo.java:12: error: the switch expression does not cover all possible input values > return switch (base) { > ^ > 1 error > > > Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input. > > Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code: > > case final Value value -> 0; > => > case final SpecialValue value -> 0; > > $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java > $ > > > Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac). > > javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive. > > The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes. Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 17 commits: - Merge branch 'master' into JDK-8366968 - Merge branch 'JDK-8367499-2' into JDK-8366968-2 - Cleanup. - Cleanup. - Cleanup. - Merge branch 'JDK-8367499-2' into JDK-8366968-2 - 8367499: Refactor exhaustiveness computation from Flow into a separate class - Removing trailing whitespace. - There are no relevant permitted subtypes of a non-abstract class, not even the class itself. - 8366968: Exhaustive switch expression rejected by for not covering all possible values - ... and 7 more: https://git.openjdk.org/jdk/compare/ea7186a8...f75a6830 ------------- Changes: https://git.openjdk.org/jdk/pull/27547/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=03 Stats: 70 lines in 2 files changed: 62 ins; 2 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/27547.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27547/head:pull/27547 PR: https://git.openjdk.org/jdk/pull/27547 From jlahoda at openjdk.org Tue Oct 21 12:50:12 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 21 Oct 2025 12:50:12 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v2] In-Reply-To: References: Message-ID: > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Adding lint warning for inconsistent InnerClasses attribute. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27665/files - new: https://git.openjdk.org/jdk/pull/27665/files/6977a247..2b7c465b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=00-01 Stats: 187 lines in 2 files changed: 186 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27665.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27665/head:pull/27665 PR: https://git.openjdk.org/jdk/pull/27665 From vromero at openjdk.org Tue Oct 21 12:55:33 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 21 Oct 2025 12:55:33 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v7] In-Reply-To: <9tTMfRjmfWhUBHKxOSnqc_FXFhZ21HucWbcP03q09zY=.0804751a-3fd4-4570-8361-cf9ddb510c7a@github.com> References: <9tTMfRjmfWhUBHKxOSnqc_FXFhZ21HucWbcP03q09zY=.0804751a-3fd4-4570-8361-cf9ddb510c7a@github.com> Message-ID: On Tue, 21 Oct 2025 11:25:38 GMT, Jan Lahoda wrote: >> Consider this code: >> >> $ cat Test.java >> package test; >> public class Test { >> private int test1(Root r) { >> return switch (r) { >> case Root(R2(R1 _), R2(R1 _)) -> 0; >> case Root(R2(R1 _), R2(R2 _)) -> 0; >> case Root(R2(R2 _), R2(R1 _)) -> 0; >> case Root(R2(R2 _), R2 _) -> 0; >> }; >> } >> sealed interface Base {} >> record R1() implements Base {} >> record R2(Base b1) implements Base {} >> record Root(R2 b2, R2 b3) {} >> } >> >> >> javac (JDK 25) will produce a compile-time error for this code: >> >> $ javac test/Test.java >> .../test/Test.java:4: error: the switch expression does not cover all possible input values >> return switch (r) { >> ^ >> 1 error >> >> >> This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. >> >> One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. >> >> Such path exists here (every line shows a set of patterns that is being transformed): >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ >> Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) >> Root(R2 _, R2 _) >> => >> Root _ >> => >> exhaustive >> >> >> The problem here is that in the first step, javac chooses this path: >> >> Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) >> => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) >> Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) >> => dead end, as there are no two patterns that would have the same nested pattern in the same component >> >> >> If javac would do full backtracking, it could go back, and choose the other path, and find out the switch ... > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 14 commits: > > - Merge branch 'master' into JDK-8364991 > - Merge branch 'JDK-8367499-2' into JDK-8364991 > - 8367499: Refactor exhaustiveness computation from Flow into a separate class > - Avoiding the use of IdentityHashMap. > - Caching isSubtype, as suggested. > - Adding explanation to the replaces map. > - Factoring out the 'substitutable' check, as suggested. > - Adding tests with generic records. > - Simplifying the code as suggested. > - Adding test. > - ... and 4 more: https://git.openjdk.org/jdk/compare/ea7186a8...ba70f898 Marked as reviewed by vromero (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27247#pullrequestreview-3360513588 From jlahoda at openjdk.org Tue Oct 21 13:38:48 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 21 Oct 2025 13:38:48 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v3] In-Reply-To: References: Message-ID: > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Adding forgotten change. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27665/files - new: https://git.openjdk.org/jdk/pull/27665/files/2b7c465b..f9502bee Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=01-02 Stats: 5 lines in 1 file changed: 5 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27665.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27665/head:pull/27665 PR: https://git.openjdk.org/jdk/pull/27665 From jan.lahoda at oracle.com Tue Oct 21 14:13:55 2025 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 21 Oct 2025 16:13:55 +0200 Subject: JShell should add a tab if a new line is entered after an opening parentheses. In-Reply-To: References: Message-ID: Hi David, I've filled: https://bugs.openjdk.org/browse/JDK-8370338 Thanks for the report, ? ? Jan On 10/21/25 04:54, David Alayachew wrote: > Hello @compiler-dev , > > Sometimes, when using JShell, I like to write code like this. > > Stream.of( > some(complex(expression)), > another(kind, of(complex, expression)), > you(get, the, idea) > ) > .parallel() > .map(...) > .forEach(...) > ; > > But when typing the above in JShell, the 3 expressions in the call to > Stream.of() are not indented. And in fact, even if I manually indent > the first expression, JShell will require me to do the same for the > following lines. > > There's a couple of different ways to go about this. Maybe JShell > could be smarter about realizing where its current indent should be. > For example, it could just follow the indent of the previous line. > That would let the user pick the indent of their choice. > > But from what little I have read of the JShell codebase, it sounds > like it would just be easiest to just make open parentheses?+ new line > = increment indent. > > What do you think? > > Thank you for your time and consideration. > David Alayachew -------------- next part -------------- An HTML attachment was scrubbed... URL: From stephan.herrmann at berlin.de Tue Oct 21 19:26:49 2025 From: stephan.herrmann at berlin.de (Stephan Herrmann) Date: Tue, 21 Oct 2025 21:26:49 +0200 Subject: resolving several ivars to the same capture? Message-ID: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> Once more, I have a bunch of tests on my desk where javac and ecj disagree. The pending fix for one case, makes ecj accept the following program, which is rejected by javac: //--- import java.util.function.Function; public class Test { public static void main(String[] args) { C> c = null; m( _ -> new A<>(c), b -> b.intValue()); } static void m(Function, A> f1, Function f2) {} static class A { public A(C> t) {} } private record B(V t) implements C { } private interface C { W t(); } } //--- javac reports: Test.java:5: error: cannot infer type arguments for A<> _ -> new A<>((C>) null), ^ reason: cannot infer type-variable(s) U (argument mismatch; C> cannot be converted to C>) where U is a type-variable: U extends Object declared in class A Test.java:6: error: cannot find symbol b -> b.intValue()); ^ symbol: method intValue() location: variable b of type Object 2 errors With my pending fix ecj would accept, with these details: Outer inference of m() yields: T#0 : capture#1-of ? R#1 : java.lang.Integer U#3 : capture#1-of ? so m() resolves as: void m(Function,A>, Function) With target types Function,A> and Function the two lambdas complete resolution just fine. Am I missing any detail, why this inference solution is not valid? FYI, the pending fix relates to capturing while computing super types of A. While normally we ensure uniqueness of captures per source location, when type inference requests a capture for supertype computation we use the current invocation as the point of reference, i.e., repeatedly capturing the same wildcard during one invocation of type inference will share one unified capture. Is this OK? Or what are the rules for uniqueness vs. unification in this case? thanks, Stephan From pminborg at openjdk.org Wed Oct 22 07:51:30 2025 From: pminborg at openjdk.org (Per Minborg) Date: Wed, 22 Oct 2025 07:51:30 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v19] In-Reply-To: <7R8km2ZfztfyDcrUvjd_5P85J7pBMsxAIY-tP76jnTc=.d4311603-0098-4f89-84b3-f073bec00a4d@github.com> References: <2Ow8e38mfpHtFTbD5kUe4BKOaWACguUWAfKwerScgMg=.228371ce-d23d-4dc2-816c-ce80c7da7771@github.com> <7R8km2ZfztfyDcrUvjd_5P85J7pBMsxAIY-tP76jnTc=.d4311603-0098-4f89-84b3-f073bec00a4d@github.com> Message-ID: On Sat, 18 Oct 2025 01:04:37 GMT, ExE Boss wrote: >> src/java.base/share/classes/java/lang/LazyConstant.java line 161: >> >>> 159: * to a lazy constant or if there is a chain from a {@code static final} field -- via one >>> 160: * or more trusted fields (i.e., {@code static final} fields, >>> 161: * {@linkplain Record record} fields, lazy constants, lazy lists, lazy maps, >> >> lazy constants and lazy lists/maps are not themselves "trusted final fields" (at least not yet), so not sure they belong here? > > The?`@Stable`?annotation makes?fields with?non?`null`?values into?trusted?fields when?the?class is?loaded by?a?platform class?loader. There could be a chain: `static final` -> record component -> lazy list element -> record component, for example, and this would be a trusted chain. There are other constucts that could be in the chain as well and that are not mentioned (e.g. a `List.of()`) so perhaps we should do some change here. Easiest is to just remove the mention of lazy*. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2450745732 From maurizio.cimadamore at oracle.com Wed Oct 22 10:05:59 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 22 Oct 2025 11:05:59 +0100 Subject: resolving several ivars to the same capture? In-Reply-To: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> Message-ID: Hi Stephan, first, I'll note that this issue seems dangerously close to this open spec issue: https://bugs.openjdk.org/browse/JDK-8016196 Then, to the specifics of your query, the crux of the problem here is to determine how this subexpression is type checked: new A<>(c) Because that determines T, and the type of T then determines whether calling intValue in the other lambda makes sense. Now, to check the above expression we have to prove that the type of `c` is compatible with the formal parameter of the A's constructor, so, something like: C> <: C> (where U is an inference variable here) This seems to lead to: B <: C B<#CAP> <: C, where #CAP <: Number // CAPTURE HERE! U = #CAP So, the type we infer for the instance creation expression would be A<#CAP>. Note that this capture variable does have an upper bound (Number), which you didn't report in your ecj dump, but I assume it to be there (otherwise the second lambda would fail to type check). Now, the second step of the subtyping proof above requires capture, which is the spec issue I mentioned above. I think javac went back and forth a bit on whether to apply capture or not (given the open spec issue), and perhaps landed on a slightly different place than ecj. We have other examples where applying capture conversion during incorporation this way leads to issues: https://bugs.openjdk.org/browse/JDK-8206142 (That said, I would have expected javac to perform a capture there -- @Vicente, when you have time, can you please take a look and see why javac is not capturing?) Thanks Maurizio On 21/10/2025 20:26, Stephan Herrmann wrote: > Once more, I have a bunch of tests on my desk where javac and ecj > disagree. > > The pending fix for one case, makes ecj accept the following program, > which is rejected by javac: > > //--- > import java.util.function.Function; > public class Test { > ??? public static void main(String[] args) { > ??????? C> c = null; > ??????? m( > ??????????????? _ -> new A<>(c), > ??????????????? b -> b.intValue()); > ??? } > ??? static void m(Function, A> f1, Function > f2) {} > ??? static class A { > ??????? public A(C> t) {} > ??? } > ??? private record B(V t) implements C { > > ??? } > ??? private interface C { > ??????? W t(); > ??? } > } > //--- > > javac reports: > Test.java:5: error: cannot infer type arguments for A<> > ??????????????? _ -> new A<>((C>) null), > ???????????????????? ^ > ? reason: cannot infer type-variable(s) U > ??? (argument mismatch; C> cannot be converted to C>) > ? where U is a type-variable: > ??? U extends Object declared in class A > Test.java:6: error: cannot find symbol > ??????????????? b -> b.intValue()); > ????????????????????? ^ > ? symbol:?? method intValue() > ? location: variable b of type Object > 2 errors > > > With my pending fix ecj would accept, with these details: > > Outer inference of m() yields: > ????T#0??? :??? capture#1-of ? > ????R#1??? :??? java.lang.Integer > ????U#3??? :??? capture#1-of ? > so m() resolves as: > void m(Function,A>, Function ?,Integer>) > > With target types Function,A> and > Function the two lambdas complete resolution > just fine. > > > Am I missing any detail, why this inference solution is not valid? > > > FYI, the pending fix relates to capturing while computing super types > of A. While normally we ensure uniqueness of captures per source > location, when type inference requests a capture for supertype > computation we use the current invocation as the point of reference, > i.e., repeatedly capturing the same wildcard during one invocation of > type inference will share one unified capture. Is this OK? Or what are > the rules for uniqueness vs. unification in this case? > > > > thanks, > Stephan From abimpoudis at openjdk.org Wed Oct 22 10:45:04 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Wed, 22 Oct 2025 10:45:04 GMT Subject: RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v4] In-Reply-To: References: Message-ID: On Tue, 21 Oct 2025 11:28:57 GMT, Jan Lahoda wrote: >> Consider case like (from the bug): >> >> class Demo { >> >> sealed interface Base permits Special, Value {} >> >> non-sealed interface Value extends Base {} >> >> sealed interface Special extends Base permits SpecialValue {} >> >> non-sealed interface SpecialValue extends Value, Special {} >> >> static int demo(final Base base) { >> return switch (base) { >> case final Value value -> 0; >> // Uncommenting the following line will make javac accept this program >> //case final Special value -> throw new AssertionError(); >> }; >> >> } >> >> } >> >> >> This fails to compile: >> >> /tmp/Demo.java:12: error: the switch expression does not cover all possible input values >> return switch (base) { >> ^ >> 1 error >> >> >> Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input. >> >> Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code: >> >> case final Value value -> 0; >> => >> case final SpecialValue value -> 0; >> >> $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java >> $ >> >> >> Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac). >> >> javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive. >> >> The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes. > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 17 commits: > > - Merge branch 'master' into JDK-8366968 > - Merge branch 'JDK-8367499-2' into JDK-8366968-2 > - Cleanup. > - Cleanup. > - Cleanup. > - Merge branch 'JDK-8367499-2' into JDK-8366968-2 > - 8367499: Refactor exhaustiveness computation from Flow into a separate class > - Removing trailing whitespace. > - There are no relevant permitted subtypes of a non-abstract class, not even the class itself. > - 8366968: Exhaustive switch expression rejected by for not covering all possible values > - ... and 7 more: https://git.openjdk.org/jdk/compare/ea7186a8...f75a6830 Looks good ? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 231: > 229: return instantiated != null && types.isCastable(selectorType, instantiated); > 230: }); > 231: Set filteredPermitted = new HashSet<>(permitted); `permitted` is the set of transitively permitted right? e.g., SpecialValue, Value and Special. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 240: > 238: currentSubTypes = > 239: permitted.stream() > 240: .filter(perm -> types.isSubtype(types.erasure(perm.type), Can we also add a test with a generic hierarchy to witness the alternative path in the `types.erasure` part? I am sure the following would pass thought so feel free to ignore: class SomeType {} sealed interface Base permits Special, Value {} non-sealed interface Value extends Base {} sealed interface Special extends Base permits SpecialValue {} non-sealed interface SpecialValue extends Value, Special {} static int demo(final Base base) { return switch (base) { case Value value -> 0; }; } ------------- Marked as reviewed by abimpoudis (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27547#pullrequestreview-3362237250 PR Review Comment: https://git.openjdk.org/jdk/pull/27547#discussion_r2449375638 PR Review Comment: https://git.openjdk.org/jdk/pull/27547#discussion_r2451555471 From abimpoudis at openjdk.org Wed Oct 22 10:45:05 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Wed, 22 Oct 2025 10:45:05 GMT Subject: RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v4] In-Reply-To: References: Message-ID: <936VB-NsrG2Mh5x25XstXjCue4sGlrw6iBQfQQSlWLo=.18630169-7693-4b5a-ab16-79bbddf8a54a@github.com> On Wed, 22 Oct 2025 10:34:36 GMT, Aggelos Biboudis wrote: >> Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 17 commits: >> >> - Merge branch 'master' into JDK-8366968 >> - Merge branch 'JDK-8367499-2' into JDK-8366968-2 >> - Cleanup. >> - Cleanup. >> - Cleanup. >> - Merge branch 'JDK-8367499-2' into JDK-8366968-2 >> - 8367499: Refactor exhaustiveness computation from Flow into a separate class >> - Removing trailing whitespace. >> - There are no relevant permitted subtypes of a non-abstract class, not even the class itself. >> - 8366968: Exhaustive switch expression rejected by for not covering all possible values >> - ... and 7 more: https://git.openjdk.org/jdk/compare/ea7186a8...f75a6830 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 240: > >> 238: currentSubTypes = >> 239: permitted.stream() >> 240: .filter(perm -> types.isSubtype(types.erasure(perm.type), > > Can we also add a test with a generic hierarchy to witness the alternative path in the `types.erasure` part? I am sure the following would pass thought so feel free to ignore: > > > class SomeType {} > sealed interface Base permits Special, Value {} > non-sealed interface Value extends Base {} > sealed interface Special extends Base permits SpecialValue {} > non-sealed interface SpecialValue extends Value, Special {} > > static int demo(final Base base) { > return switch (base) { > case Value value -> 0; > }; > } Also, since this area of the `if` tries to detect the diamond shape does it make sense to extract it into a method so that it stands out? Otherwise a comment would be excellent here. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27547#discussion_r2451584240 From acobbs at openjdk.org Wed Oct 22 15:21:43 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 22 Oct 2025 15:21:43 GMT Subject: RFR: 8344159: Add lint warnings for unnecessary warning suppression [v4] In-Reply-To: References: Message-ID: > This PR adds a new compiler warning for `@SuppressWarnings` annotations that don't actually suppress any warnings. > > Summary of code changes: > > * Add new warning and associated lint category `"suppression"` > * Update `LintMapper` to keep track of which `@SuppressWarnings` suppressions have been validated ? > * Update `Log.warning()` so it validates any current suppression of the warning's lint category in effect. > * Add a new `validate` parameter to `Lint.isEnabled()` and `Lint.isSuppressed()` that specifies whether to also validate any current suppression. > * Add `Lint.isActive()` to check whether a category is enabled _or_ suppression of the category is being tracked - in other words, whether the warning calculation needs to be performed. Used for non-trivial warning calculations. > * Add `-Xlint:-suppression` flags to `*.gmk` build files so the build doesn't break > > ? The suppression of a lint category is "validated" as soon as it suppresses some warning in that category Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 133 commits: - Merge branch 'master' into JDK-8344159 to fix conflict. - Merge branch 'master' into JDK-8344159 to fix conflict. - Merge branch 'master' into JDK-8344159 to fix conflicts. - Add clarifying comment. - Merge branch 'master' into JDK-8344159 - Change inner class name to avoid shadowing superclass name. - Add a couple of code clarification comments. - Refactor test to avoid requiring changes to TestRunner. - Remove unnecessary -Xlint:-suppression flags. - Minor cleanups. - ... and 123 more: https://git.openjdk.org/jdk/compare/a1be2979...f2b75547 ------------- Changes: https://git.openjdk.org/jdk/pull/25167/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=25167&range=03 Stats: 1665 lines in 34 files changed: 1490 ins; 49 del; 126 mod Patch: https://git.openjdk.org/jdk/pull/25167.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/25167/head:pull/25167 PR: https://git.openjdk.org/jdk/pull/25167 From cushon at openjdk.org Wed Oct 22 18:07:37 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 22 Oct 2025 18:07:37 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v2] In-Reply-To: References: Message-ID: > Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Update another affected test ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27901/files - new: https://git.openjdk.org/jdk/pull/27901/files/2d935b43..a99313bc Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=00-01 Stats: 5 lines in 1 file changed: 0 ins; 0 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/27901.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27901/head:pull/27901 PR: https://git.openjdk.org/jdk/pull/27901 From cushon at openjdk.org Wed Oct 22 18:07:39 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 22 Oct 2025 18:07:39 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations In-Reply-To: References: Message-ID: <0kyTa-tINebXunOwoNXuVAWeflV3BIKq7-MZzN_Zsgg=.171d989f-bbc5-4aee-9751-e3544b42f2d1@github.com> On Mon, 20 Oct 2025 14:36:17 GMT, Liam Miller-Cushon wrote: > Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). The CI failures are because this improves the errors reported `for test/langtools/tools/doclint/CrashInAnnotateTest.java`, I pushed a fix ------------- PR Comment: https://git.openjdk.org/jdk/pull/27901#issuecomment-3433564694 From cushon at openjdk.org Thu Oct 23 08:28:09 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 23 Oct 2025 08:28:09 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 18:35:23 GMT, Chen Liang wrote: >> Hi, >> >> Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. >> >> Before: >> >> >> T.java:2: error: method does not override or implement a method from a supertype >> @Override >> ^ >> >> >> After: >> >> >> T.java:2: error: f() does not override or implement a method from a supertype >> @Override >> ^ >> 1 error > > I think a better analogy would be `compiler.err.default.overrides.object.member`: it is also a problematic method overriding. It reports the method, the declaring class's kind (class or interface), and the declaring class in the current source file. I think we can just emulate that message here. @liach how does the current version of this look to you? Does anyone else have feedback on the proposed diagnostic changes? ------------- PR Comment: https://git.openjdk.org/jdk/pull/27692#issuecomment-3435713502 From cushon at openjdk.org Thu Oct 23 08:30:11 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 23 Oct 2025 08:30:11 GMT Subject: RFR: 8369508: Type annotations on anonymous new class creation expressions can't be retrieved [v2] In-Reply-To: <_ESmaroFK9q4FrDFTEJQNa_DhdJm1U3vZrmXZ-zKE80=.cd6e1dd3-21f2-4c02-99ac-e88686bbf649@github.com> References: <_ESmaroFK9q4FrDFTEJQNa_DhdJm1U3vZrmXZ-zKE80=.cd6e1dd3-21f2-4c02-99ac-e88686bbf649@github.com> Message-ID: On Fri, 10 Oct 2025 15:26:29 GMT, Liam Miller-Cushon wrote: >> Hi, >> >> Please consider this fix for [JDK-8369508: Type annotations on anonymous new class creation expressions can't be retrieved](https://bugs.openjdk.org/browse/JDK-8369508). >> >> When visiting a type annotation on an anonymous class instantiation expression, javac currently skips attribution of the annotated type when visiting it as part of the `new` expression, to prevent them from being incorrectly attached to the enclosing method instead of the synthetic declaration of the anonymous class (see [JDK-8198945](https://bugs.openjdk.org/browse/JDK-8198945)). However because this logic happens early, and results in skipping attribution of these annotations, they aren't available on the type model elements for the new class creation expression, which means they can't be retrieved by clients of the compiler tree API. >> >> This fix shifts the handling of these annotations later, to allow them to get attributed, but then to still prevent them from being attached to the enclosing method symbol of the anonymous class declaration. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Reorder an assertion Hi, is there any feedback on this change? I did some of the related previous fixes in this area (JDK-8198945, JDK-8351431) and think is more robust than the current behaviour. It was tested with some tooling that uses the affected javac APIs to process type annotations, and it resolved the issues that were being seen with type annotations in new class creation expressions. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27730#issuecomment-3435720926 From stephan.herrmann at berlin.de Thu Oct 23 10:25:49 2025 From: stephan.herrmann at berlin.de (Stephan Herrmann) Date: Thu, 23 Oct 2025 12:25:49 +0200 Subject: resolving several ivars to the same capture? In-Reply-To: References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> Message-ID: <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> Hi Maurizio thanks for taking the time. Am 22.10.25 um 12:05 schrieb Maurizio Cimadamore: > first, I'll note that this issue seems dangerously close to this open spec issue: > > https://bugs.openjdk.org/browse/JDK-8016196 In this particular issue I'm puzzled by this statement: "The correct behavior is unspecified: what is the parameterization of List that is a supertype of ArrayList? How do we derive it?" Doesn't 4.10.2 clearly state that type arguments should be captured here? (in fact until recently ecj failed to apply this rule, and many of our current issues are "regressions" resulting from fixing this). Is that rule in 4.10.2 at stake, potentially to be removed or altered? > Then, to the specifics of your query, the crux of the problem here is to > determine how this subexpression is type checked: > > new A<>(c) > > Because that determines T, and the type of T then determines whether calling > intValue in the other lambda makes sense. > > Now, to check the above expression we have to prove that the type of `c` is > compatible with the formal parameter of the A's constructor, so, something like: > > C> <: C> (where U is an inference variable here) > > This seems to lead to: > > B <: C > B<#CAP> <: C, where #CAP <: Number // CAPTURE HERE! > U = #CAP > > So, the type we infer for the instance creation expression would be A<#CAP>. > Note that this capture variable does have an upper bound (Number), which you > didn't report in your ecj dump, but I assume it to be there (otherwise the > second lambda would fail to type check). So far all looks good, and yes, the capture has Number as its upper bound. > Now, the second step of the subtyping proof above requires capture, which is the > spec issue I mentioned above. I think javac went back and forth a bit on whether > to apply capture or not (given the open spec issue), and perhaps landed on a > slightly different place than ecj. > > We have other examples where applying capture conversion during incorporation > this way leads to issues: > > https://bugs.openjdk.org/browse/JDK-8206142 The issue states that rejecting the example is a regression (in 9). FWIW, ecj accepts the example ever since Java 1.8. Seeing that a fix for javac exists for many years, why is that fix not applied? Is this an indication that perhaps JLS is to be changed rather than javac? What do you recommend for the current issue? Is it OK for ecj to accept the program, and if people complain about the difference to javac, explain that this is a bug in javac? Or are there any fine points in the spec which we are missing, that justify rejecting? > (That said, I would have expected javac to perform a capture there -- @Vicente, > when you have time, can you please take a look and see why javac is not capturing?) OK, I might just wait for Vicente's answer here :) thanks, Stephan > Thanks > Maurizio > > On 21/10/2025 20:26, Stephan Herrmann wrote: >> Once more, I have a bunch of tests on my desk where javac and ecj disagree. >> >> The pending fix for one case, makes ecj accept the following program, which is >> rejected by javac: >> >> //--- >> import java.util.function.Function; >> public class Test { >> ??? public static void main(String[] args) { >> ??????? C> c = null; >> ??????? m( >> ??????????????? _ -> new A<>(c), >> ??????????????? b -> b.intValue()); >> ??? } >> ??? static void m(Function, A> f1, Function f2) {} >> ??? static class A { >> ??????? public A(C> t) {} >> ??? } >> ??? private record B(V t) implements C { >> >> ??? } >> ??? private interface C { >> ??????? W t(); >> ??? } >> } >> //--- >> >> javac reports: >> Test.java:5: error: cannot infer type arguments for A<> >> ??????????????? _ -> new A<>((C>) null), >> ???????????????????? ^ >> ? reason: cannot infer type-variable(s) U >> ??? (argument mismatch; C> cannot be converted to C>) >> ? where U is a type-variable: >> ??? U extends Object declared in class A >> Test.java:6: error: cannot find symbol >> ??????????????? b -> b.intValue()); >> ????????????????????? ^ >> ? symbol:?? method intValue() >> ? location: variable b of type Object >> 2 errors >> >> >> With my pending fix ecj would accept, with these details: >> >> Outer inference of m() yields: >> ????T#0??? :??? capture#1-of ? >> ????R#1??? :??? java.lang.Integer >> ????U#3??? :??? capture#1-of ? >> so m() resolves as: >> void m(Function,A>, Function) >> >> With target types Function,A> and >> Function the two lambdas complete resolution just fine. >> >> >> Am I missing any detail, why this inference solution is not valid? >> >> >> FYI, the pending fix relates to capturing while computing super types of A. >> While normally we ensure uniqueness of captures per source location, when type >> inference requests a capture for supertype computation we use the current >> invocation as the point of reference, i.e., repeatedly capturing the same >> wildcard during one invocation of type inference will share one unified >> capture. Is this OK? Or what are the rules for uniqueness vs. unification in >> this case? >> >> >> >> thanks, >> Stephan From maurizio.cimadamore at oracle.com Thu Oct 23 10:45:20 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 23 Oct 2025 11:45:20 +0100 Subject: resolving several ivars to the same capture? In-Reply-To: <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> Message-ID: On 23/10/2025 11:25, Stephan Herrmann wrote: > Hi Maurizio > > thanks for taking the time. > > Am 22.10.25 um 12:05 schrieb Maurizio Cimadamore: >> first, I'll note that this issue seems dangerously close to this open >> spec issue: >> >> https://bugs.openjdk.org/browse/JDK-8016196 > > In this particular issue I'm puzzled by this statement: > > "The correct behavior is unspecified: what is the parameterization of > List that is a supertype of ArrayList? How do we derive it?" > > Doesn't 4.10.2 clearly state that type arguments should be captured here? Yes, but that means that we will generate ?spurious? capture variables during inference which will end up in the result. Depending on the case, this might result in failures. Dan (CC?ed) might add more details. >> We have other examples where applying capture conversion during >> incorporation this way leads to issues: >> >> https://bugs.openjdk.org/browse/JDK-8206142 > > The issue states that rejecting the example is a regression (in 9). > FWIW, ecj accepts the example ever since Java 1.8. Seeing that a fix > for javac exists for many years, why is that fix not applied? Is this > an indication that perhaps JLS is to be changed rather than javac? IIRC, we realized that this is a case where we?re doomed no matter what we do. When running that fix through our tests we got some compatibility issues, so in general we were skeptical of applying it w/o having some kind of spec coverage. > > What do you recommend for the current issue? Is it OK for ecj to > accept the program, and if people complain about the difference to > javac, explain that this is a bug in javac? Or are there any fine > points in the spec which we are missing, that justify rejecting? If this is indeed connected to the spec issue I mentioned above, then I?d say that it?s sad but also sort of ok for the compilers to diverge, given that a ?real? fix will in reality be a lot more convoluted than just applying capture. > >> (That said, I would have expected javac to perform a capture there -- >> @Vicente, when you have time, can you please take a look and see why >> javac is not capturing?) > > OK, I might just wait for Vicente's answer here :) Ok. Thanks Maurizio > > thanks, > Stephan >> Thanks >> Maurizio >> >> On 21/10/2025 20:26, Stephan Herrmann wrote: >>> Once more, I have a bunch of tests on my desk where javac and ecj >>> disagree. >>> >>> The pending fix for one case, makes ecj accept the following >>> program, which is rejected by javac: >>> >>> //--- >>> import java.util.function.Function; >>> public class Test { >>> ??? public static void main(String[] args) { >>> ??????? C> c = null; >>> ??????? m( >>> ??????????????? _ -> new A<>(c), >>> ??????????????? b -> b.intValue()); >>> ??? } >>> ??? static void m(Function, A> f1, Function>> R> f2) {} >>> ??? static class A { >>> ??????? public A(C> t) {} >>> ??? } >>> ??? private record B(V t) implements C { >>> >>> ??? } >>> ??? private interface C { >>> ??????? W t(); >>> ??? } >>> } >>> //--- >>> >>> javac reports: >>> Test.java:5: error: cannot infer type arguments for A<> >>> ??????????????? _ -> new A<>((C>) null), >>> ???????????????????? ^ >>> ? reason: cannot infer type-variable(s) U >>> ??? (argument mismatch; C> cannot be converted to C>> C>) >>> ? where U is a type-variable: >>> ??? U extends Object declared in class A >>> Test.java:6: error: cannot find symbol >>> ??????????????? b -> b.intValue()); >>> ????????????????????? ^ >>> ? symbol:?? method intValue() >>> ? location: variable b of type Object >>> 2 errors >>> >>> >>> With my pending fix ecj would accept, with these details: >>> >>> Outer inference of m() yields: >>> ????T#0??? :??? capture#1-of ? >>> ????R#1??? :??? java.lang.Integer >>> ????U#3??? :??? capture#1-of ? >>> so m() resolves as: >>> void m(Function,A>, Function>> ?,Integer>) >>> >>> With target types Function,A> and >>> Function the two lambdas complete resolution >>> just fine. >>> >>> >>> Am I missing any detail, why this inference solution is not valid? >>> >>> >>> FYI, the pending fix relates to capturing while computing super >>> types of A. While normally we ensure uniqueness of captures per >>> source location, when type inference requests a capture for >>> supertype computation we use the current invocation as the point of >>> reference, i.e., repeatedly capturing the same wildcard during one >>> invocation of type inference will share one unified capture. Is this >>> OK? Or what are the rules for uniqueness vs. unification in this case? >>> >>> >>> >>> thanks, >>> Stephan > > > ​ -------------- next part -------------- An HTML attachment was scrubbed... URL: From stephan.herrmann at berlin.de Thu Oct 23 11:10:55 2025 From: stephan.herrmann at berlin.de (Stephan Herrmann) Date: Thu, 23 Oct 2025 13:10:55 +0200 Subject: resolving several ivars to the same capture? In-Reply-To: References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> Message-ID: Am 23.10.25 um 12:45 schrieb Maurizio Cimadamore: > On 23/10/2025 11:25, Stephan Herrmann wrote: >> Doesn't 4.10.2 clearly state that type arguments should be captured here? > > Yes, but that means that we will generate ?spurious? capture variables during > inference which will end up in the result. Depending on the case, this might > result in failures. define "spurious"! :) > If this is indeed connected to the spec issue I mentioned above, then I?d say > that it?s sad but also sort of ok for the compilers to diverge, given that a > ?real? fix will in reality be a lot more convoluted than just applying capture. I understand that changes in this area can easily have big impact, and that investigations to curb undesirable impact require a significant investment. On the other hand also continuously investigating many issues of similar nature causes tremendous efforts over time. What is the perspective for things to eventually clear up? * Will Valhalla enter a stage where the type system needs to be improved in ways that will include general clarifications of matters of wildcards and captures? * Otherwise, would it make sense to create a JEP dedicated to such clarifications in order to allocate resources required for this task? I can offer whatever insights can be gained from ecj as a second implementation, including experiments what impact certain spec changes might have. I personally don't have the full background of type systems sufficient for commenting which spec changes might be sound or bogus, but I do have private contact to someone who has this background. Perhaps for precise questions I could "mediate" some help :) best, Stephan From maurizio.cimadamore at oracle.com Thu Oct 23 14:53:05 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 23 Oct 2025 15:53:05 +0100 Subject: resolving several ivars to the same capture? In-Reply-To: References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> Message-ID: <3986cc58-ceac-4d59-920f-acb4bc872451@oracle.com> On 23/10/2025 12:10, Stephan Herrmann wrote: > Am 23.10.25 um 12:45 schrieb Maurizio Cimadamore: >> On 23/10/2025 11:25, Stephan Herrmann wrote: >>> Doesn't 4.10.2 clearly state that type arguments should be captured >>> here? >> >> Yes, but that means that we will generate ?spurious? capture >> variables during inference which will end up in the result. Depending >> on the case, this might result in failures. > > define "spurious"! :) I think Dan has explored this topic in more details and might have more examples of when the extra captures generated during incorporation might lead to bad inference results. I'll leave this with him. > > >> If this is indeed connected to the spec issue I mentioned above, then >> I?d say that it?s sad but also sort of ok for the compilers to >> diverge, given that a ?real? fix will in reality be a lot more >> convoluted than just applying capture. > > > > What is the perspective for things to eventually clear up? These issues are complex and take quite a bit of time to fix (compiler implememtation being the least concern) while, at the same time, they tend to impact a relatively low number of users. So prioritization for these things is always tricky. You can expect new features to keep cleaning up things as required. Some examples: * local variable type inference introduced a new _upward projection_ routine which I suspect can be used as a basis for some of the subtyping woes mentioned in this thread (as an upward projection is the closest upper bound of a type that is free of captured type-variables) * pattern matching is increasingly refining and polishing the story around cast conversions * flexible constructor bodies required a fair deal of cleanup in the definitions of local class well-formedness I believe this to be a good and pragmatic way to keep moving towards a place where compiler and spec are closer together, while adding interesting new features to the platform. So, no, an umbrella JEP for "type system fixes" is almost certainly not how these issues will be addressed. Maurizio From maurizio.cimadamore at oracle.com Thu Oct 23 15:10:23 2025 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 23 Oct 2025 16:10:23 +0100 Subject: resolving several ivars to the same capture? In-Reply-To: <3986cc58-ceac-4d59-920f-acb4bc872451@oracle.com> References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> <3986cc58-ceac-4d59-920f-acb4bc872451@oracle.com> Message-ID: <5a638d7f-a9cd-4397-a49b-edeadccd0491@oracle.com> On 23/10/2025 15:53, Maurizio Cimadamore wrote: >>> Yes, but that means that we will generate ?spurious? capture >>> variables during inference which will end up in the result. >>> Depending on the case, this might result in failures. >> >> define "spurious"! ? > I think Dan has explored this topic in more details and might have > more examples of when the extra captures generated during > incorporation might lead to bad inference results. I'll leave this > with him. Actually, here's a possible example: class Test { ? ? static class A { } ? ? static class B { } ? ? static class C extends B { } ? ? static void m(A> a) { } ? ? static void test(A> a) { ? ? ? ? m(a); ? ? } } Here we run the subtyping check: A> <:?A> Which leads to C <: B C<#CAP1> <: B Which leads to Z == #CAP1 Ok, so the inferred type for m's parameter is?A> But is our actual argument (A>) compatible with that? Let's check A> <:?A> Which leads again to: C <:?B<#CAP1> C<#CAP2> <: B<#CAP1> false Since we capture _again_, we end up with _two_ capture variables, incompatible with each other. So, inference was able to get to some kind of solution, but unfortunately the inferred type is not compatible with the actual argument we started with. Maurizio -------------- next part -------------- An HTML attachment was scrubbed... URL: From jlahoda at openjdk.org Thu Oct 23 15:19:16 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 23 Oct 2025 15:19:16 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v4] In-Reply-To: References: Message-ID: > Consider a JShell interaction like: > > jshell> class O { class I {} } > | created class O > > jshell> var i = new O().new I(); > i ==> O$I at 77caeb3e > > jshell> class O { static class I {} } > Exception in thread "main" java.lang.ClassFormatError: class not in class file format > at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) > at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) > at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) > at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) > at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) > at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) > at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) > at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) > at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) > at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) > at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) > at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) > at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) > at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) > at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) > at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) > at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) > at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) > at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) > at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) > at jdk.jshell/jdk.internal.jshell.tool.JShellTool.run(JShellTool.java:... Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Fixing CheckExamples ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27665/files - new: https://git.openjdk.org/jdk/pull/27665/files/f9502bee..6914c146 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27665&range=02-03 Stats: 34 lines in 3 files changed: 30 ins; 0 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/27665.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27665/head:pull/27665 PR: https://git.openjdk.org/jdk/pull/27665 From stephan.herrmann at berlin.de Thu Oct 23 16:04:05 2025 From: stephan.herrmann at berlin.de (Stephan Herrmann) Date: Thu, 23 Oct 2025 18:04:05 +0200 Subject: resolving several ivars to the same capture? In-Reply-To: <5a638d7f-a9cd-4397-a49b-edeadccd0491@oracle.com> References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> <3986cc58-ceac-4d59-920f-acb4bc872451@oracle.com> <5a638d7f-a9cd-4397-a49b-edeadccd0491@oracle.com> Message-ID: <622b1f82-3c00-4a96-bd69-1d3c81144959@berlin.de> Am 23.10.25 um 17:10 schrieb Maurizio Cimadamore: > > On 23/10/2025 15:53, Maurizio Cimadamore wrote: >>>> Yes, but that means that we will generate ?spurious? capture variables >>>> during inference which will end up in the result. Depending on the case, >>>> this might result in failures. >>> >>> define "spurious"! ? >> I think Dan has explored this topic in more details and might have more >> examples of when the extra captures generated during incorporation might lead >> to bad inference results. I'll leave this with him. > > Actually, here's a possible example: > > class Test { > ? ? static class A { } > ? ? static class B { } > ? ? static class C extends B { } > > ? ? static void m(A> a) { } > > ? ? static void test(A> a) { > ? ? ? ? m(a); > ? ? } > } ecj accepts this (since 2017). Is that a problem? It seems ecj succeeds, because repeated capture requests are detected to be asking the exact same question (same wildcard, same code location), so the same capture may be answered more than once. Stephan From vicente.romero at oracle.com Thu Oct 23 16:43:38 2025 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 23 Oct 2025 12:43:38 -0400 Subject: resolving several ivars to the same capture? In-Reply-To: References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> Message-ID: Hi, Sorry for joining late to the party :) I don't have too much to add to this discussion. My recollection is that as Maurizio mentioned, yes we tried a fix in this area but that brought in some compatibility issues and we deferred going for any change until we had clarifications from the spec side. I think the situation is still the same, Vicente On 10/23/25 07:10, Stephan Herrmann wrote: > Am 23.10.25 um 12:45 schrieb Maurizio Cimadamore: >> On 23/10/2025 11:25, Stephan Herrmann wrote: >>> Doesn't 4.10.2 clearly state that type arguments should be captured >>> here? >> >> Yes, but that means that we will generate ?spurious? capture >> variables during inference which will end up in the result. Depending >> on the case, this might result in failures. > > define "spurious"! :) > > >> If this is indeed connected to the spec issue I mentioned above, then >> I?d say that it?s sad but also sort of ok for the compilers to >> diverge, given that a ?real? fix will in reality be a lot more >> convoluted than just applying capture. > > I understand that changes in this area can easily have big impact, and > that investigations to curb undesirable impact require a significant > investment. On the other hand also continuously investigating many > issues of similar nature causes tremendous efforts over time. > > What is the perspective for things to eventually clear up? > * Will Valhalla enter a stage where the type system needs to be > improved in ways that will include general clarifications of matters > of wildcards and captures? > * Otherwise, would it make sense to create a JEP dedicated to such > clarifications in order to allocate resources required for this task? > > I can offer whatever insights can be gained from ecj as a second > implementation, including experiments what impact certain spec changes > might have. I personally don't have the full background of type > systems sufficient for commenting which spec changes might be sound or > bogus, but I do have private contact to someone who has this > background. Perhaps for precise questions I could "mediate" some help :) > > best, > Stephan From vicente.romero at oracle.com Thu Oct 23 16:48:41 2025 From: vicente.romero at oracle.com (Vicente Romero) Date: Thu, 23 Oct 2025 12:48:41 -0400 Subject: resolving several ivars to the same capture? In-Reply-To: <622b1f82-3c00-4a96-bd69-1d3c81144959@berlin.de> References: <28cb175b-ef23-4cfc-b2e2-ca74410b3af5@berlin.de> <9623629d-0714-406b-b89a-fb6ca829aa7c@berlin.de> <3986cc58-ceac-4d59-920f-acb4bc872451@oracle.com> <5a638d7f-a9cd-4397-a49b-edeadccd0491@oracle.com> <622b1f82-3c00-4a96-bd69-1d3c81144959@berlin.de> Message-ID: <69242576-d295-4309-ba9a-4b0b4a584013@oracle.com> On 10/23/25 12:04, Stephan Herrmann wrote: > Am 23.10.25 um 17:10 schrieb Maurizio Cimadamore: >> >> On 23/10/2025 15:53, Maurizio Cimadamore wrote: >>>>> Yes, but that means that we will generate ?spurious? capture >>>>> variables during inference which will end up in the result. >>>>> Depending on the case, this might result in failures. >>>> >>>> define "spurious"! ? >>> I think Dan has explored this topic in more details and might have >>> more examples of when the extra captures generated during >>> incorporation might lead to bad inference results. I'll leave this >>> with him. >> >> Actually, here's a possible example: >> >> class Test { >> ?? ? static class A { } >> ?? ? static class B { } >> ?? ? static class C extends B { } >> >> ?? ? static void m(A> a) { } >> >> ?? ? static void test(A> a) { >> ?? ? ? ? m(a); >> ?? ? } >> } > > ecj accepts this (since 2017). Is that a problem? > > It seems ecj succeeds, because repeated capture requests are detected > to be asking the exact same question (same wildcard, same code > location), so the same capture may be answered more than once. > > Stephan we also do some capture caching in javac but it is very limited, I would love to extend its reach, but still we would need some spec blessing here Vicente From pminborg at openjdk.org Fri Oct 24 08:51:06 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 24 Oct 2025 08:51:06 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v19] In-Reply-To: References: Message-ID: On Fri, 17 Oct 2025 14:58:44 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Update after doc comments After some discussion, we have concluded that we need to rework how `toString()` works for `LazyConstant`, lazy maps, and lists: #### For `LazyConstant` In order to align with other comput-later constructs like `Future`, we'd like to provide something like this: java.lang.LazyConstant at 5ed828d[computing function = $Lambda/0x00000ffe000d6550 at 4d3167f4] // Uninitialized java.lang.LazyConstant at 4ad92aa[42] // Initialized #### For lazy list, map, and all their derivatives (e.g., `subList()`, `values()`) There is a tension between the willingness to keep the `toString()` methods lazy during debugging and the compatibility with the existing `List` and `Map` implementations. It would be very surprising if a lazy list would output something different from a normal list for `toString()`. We think it is more important that lazy constructs are compatible with their corresponding eager constructs. Hence, we propose to make `toString()` trigger initialization of all elements/values. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27605#issuecomment-3441894953 From pminborg at openjdk.org Fri Oct 24 09:01:10 2025 From: pminborg at openjdk.org (Per Minborg) Date: Fri, 24 Oct 2025 09:01:10 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v20] In-Reply-To: References: Message-ID: > Implement JEP 526: Lazy Constants (Second Preview) > > The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. > > The old benchmarks are not moved/renamed to allow comparison with previous releases. > > `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. Per Minborg has updated the pull request incrementally with one additional commit since the last revision: Rework toString implementations ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27605/files - new: https://git.openjdk.org/jdk/pull/27605/files/6721ca4a..c3278e0b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=19 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27605&range=18-19 Stats: 271 lines in 5 files changed: 27 ins; 211 del; 33 mod Patch: https://git.openjdk.org/jdk/pull/27605.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27605/head:pull/27605 PR: https://git.openjdk.org/jdk/pull/27605 From jlahoda at openjdk.org Fri Oct 24 12:08:22 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 24 Oct 2025 12:08:22 GMT Subject: RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v5] In-Reply-To: References: Message-ID: <7iuAdoO-2YYBbg6MjMHT5Ylkn5Ui6F4QrLW6P-_lrXM=.71e9fbc4-f9ed-47a5-a607-83731d466a85@github.com> > Consider case like (from the bug): > > class Demo { > > sealed interface Base permits Special, Value {} > > non-sealed interface Value extends Base {} > > sealed interface Special extends Base permits SpecialValue {} > > non-sealed interface SpecialValue extends Value, Special {} > > static int demo(final Base base) { > return switch (base) { > case final Value value -> 0; > // Uncommenting the following line will make javac accept this program > //case final Special value -> throw new AssertionError(); > }; > > } > > } > > > This fails to compile: > > /tmp/Demo.java:12: error: the switch expression does not cover all possible input values > return switch (base) { > ^ > 1 error > > > Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input. > > Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code: > > case final Value value -> 0; > => > case final SpecialValue value -> 0; > > $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java > $ > > > Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac). > > javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive. > > The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes. Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Reorganizing code, adding comments. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27547/files - new: https://git.openjdk.org/jdk/pull/27547/files/f75a6830..293b6467 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27547&range=03-04 Stats: 115 lines in 2 files changed: 90 ins; 16 del; 9 mod Patch: https://git.openjdk.org/jdk/pull/27547.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27547/head:pull/27547 PR: https://git.openjdk.org/jdk/pull/27547 From jlahoda at openjdk.org Fri Oct 24 12:26:48 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 24 Oct 2025 12:26:48 GMT Subject: RFR: 8370334: javadoc NPE with "import module" statement Message-ID: `Modules.enter` completes all root modules, but in case of additional modules being added to the module graph via `Modules.addExtraAddModules` (either from javadoc, or using the `CompilationTask.addModules`, these extra modules may not be completed at this time. Normally, they are completed eventually, but if their `module-info`s contain `import module`, an NPE will appear while checking the import, before the complete happens. The proposal herein is to consistently complete all modules in the module graph when the module graphs is setup. ------------- Commit messages: - Adding javac test. - Cleanup. - 8370334: javadoc NPE with "import module" statement Changes: https://git.openjdk.org/jdk/pull/27974/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27974&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370334 Stats: 73 lines in 3 files changed: 68 ins; 0 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/27974.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27974/head:pull/27974 PR: https://git.openjdk.org/jdk/pull/27974 From duke at openjdk.org Sat Oct 25 02:53:01 2025 From: duke at openjdk.org (Josiah Noel) Date: Sat, 25 Oct 2025 02:53:01 GMT Subject: RFR: 8368695: Support 101 switching protocol in jdk.httpserver [v13] In-Reply-To: References: Message-ID: > - adds a flag to ExchangeImpl to signal whether the current request is an Upgrade request > - Adds a new `UpgradeInputStream` to ensure that the server keeps track of when the upgraded request is closed > - on 101 response codes, `sendResponseHeaders` will not immediately close the output stream > - on 101 response codes, `sendResponseHeaders` will use an `UndefLengthOutputStream` Josiah Noel has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 18 commits: - Update ExchangeImpl.java - Merge remote-tracking branch 'upstream/master' into JDK-8368695 - reduce diff - Merge remote-tracking branch 'upstream/master' into JDK-8368695 - Update SwitchingProtocolTest.java - Update SwitchingProtocolTest.java - Update SwitchingProtocolTest.java - add exception test - Create UpgradeOutputStream.java - close raw streams - ... and 8 more: https://git.openjdk.org/jdk/compare/32697bf6...ae2b1184 ------------- Changes: https://git.openjdk.org/jdk/pull/27751/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27751&range=12 Stats: 25304 lines in 632 files changed: 6529 ins; 14641 del; 4134 mod Patch: https://git.openjdk.org/jdk/pull/27751.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27751/head:pull/27751 PR: https://git.openjdk.org/jdk/pull/27751 From duke at openjdk.org Sat Oct 25 02:53:02 2025 From: duke at openjdk.org (Josiah Noel) Date: Sat, 25 Oct 2025 02:53:02 GMT Subject: Withdrawn: 8368695: Support 101 switching protocol in jdk.httpserver In-Reply-To: References: Message-ID: On Fri, 10 Oct 2025 19:45:57 GMT, Josiah Noel wrote: > - adds a flag to ExchangeImpl to signal whether the current request is an Upgrade request > - Adds a new `UpgradeInputStream` to ensure that the server keeps track of when the upgraded request is closed > - on 101 response codes, `sendResponseHeaders` will not immediately close the output stream > - on 101 response codes, `sendResponseHeaders` will use an `UndefLengthOutputStream` This pull request has been closed without being integrated. ------------- PR: https://git.openjdk.org/jdk/pull/27751 From vromero at openjdk.org Mon Oct 27 15:09:16 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 27 Oct 2025 15:09:16 GMT Subject: RFR: 8366871: (javac) legacy.properties seems to be an obsolete file Message-ID: Simple PR removing an obsolete properties file, TIA ------------- Commit messages: - Merge branch 'master' into JDK-8366871 - 8366871: (javac) legacy.properties seems to be an obsolete file Changes: https://git.openjdk.org/jdk/pull/28001/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28001&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8366871 Stats: 570 lines in 1 file changed: 0 ins; 570 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28001.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28001/head:pull/28001 PR: https://git.openjdk.org/jdk/pull/28001 From prappo at openjdk.org Mon Oct 27 17:51:36 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Mon, 27 Oct 2025 17:51:36 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently Message-ID: Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. ------------- Commit messages: - Initial commit Changes: https://git.openjdk.org/jdk/pull/27972/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27972&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370568 Stats: 207 lines in 77 files changed: 0 ins; 0 del; 207 mod Patch: https://git.openjdk.org/jdk/pull/27972.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27972/head:pull/27972 PR: https://git.openjdk.org/jdk/pull/27972 From liach at openjdk.org Mon Oct 27 19:34:40 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 27 Oct 2025 19:34:40 GMT Subject: RFR: 8370687: Improve before constructor has been called error message Message-ID: In the Valhalla EA2 preview, Value class and record constructor body is in prologue by default, as opposed to all existing constructors and all identity constructors in EA2. This causes a confusion because the error message `cant.ref.before.ctor.called` can appear in such constructors without explicit constructor invocations. After discussion with @vicente-romero-oracle, we decide to commit this change onto mainline: these two errors never happen in constructors without explicit constructor invocation (colloquially "this" or "super" calls) on mainline, so this message update would not create new confusions. This is future-proof, and is more consistent with the related `call.must.only.appear.in.ctor` message, which is "explicit constructor invocation may only appear within a constructor body". ------------- Commit messages: - 8370687: Improve before constructor has been called error message Changes: https://git.openjdk.org/jdk/pull/28007/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28007&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370687 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28007.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28007/head:pull/28007 PR: https://git.openjdk.org/jdk/pull/28007 From vromero at openjdk.org Mon Oct 27 19:46:05 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 27 Oct 2025 19:46:05 GMT Subject: RFR: 8370687: Improve before constructor has been called error message In-Reply-To: References: Message-ID: On Mon, 27 Oct 2025 19:27:43 GMT, Chen Liang wrote: > In the Valhalla EA2 preview, Value class and record constructor body is in prologue by default, as opposed to all existing constructors and all identity constructors in EA2. This causes a confusion because the error message `cant.ref.before.ctor.called` can appear in such constructors without explicit constructor invocations. > > After discussion with @vicente-romero-oracle, we decide to commit this change onto mainline: these two errors never happen in constructors without explicit constructor invocation (colloquially "this" or "super" calls) on mainline, so this message update would not create new confusions. This is future-proof, and is more consistent with the related `call.must.only.appear.in.ctor` message, which is "explicit constructor invocation may only appear within a constructor body". lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28007#pullrequestreview-3385191408 From liach at openjdk.org Mon Oct 27 20:09:01 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 27 Oct 2025 20:09:01 GMT Subject: RFR: 8366871: (javac) legacy.properties seems to be an obsolete file In-Reply-To: References: Message-ID: On Mon, 27 Oct 2025 15:02:41 GMT, Vicente Romero wrote: > Simple PR removing an obsolete properties file, > > TIA Indeed, this represents something from Java 5 or 6 and we already dropped those support. Never saw this file mentioned anywhere too. ------------- Marked as reviewed by liach (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28001#pullrequestreview-3385265410 From vromero at openjdk.org Mon Oct 27 20:15:11 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 27 Oct 2025 20:15:11 GMT Subject: Integrated: 8366871: (javac) legacy.properties seems to be an obsolete file In-Reply-To: References: Message-ID: On Mon, 27 Oct 2025 15:02:41 GMT, Vicente Romero wrote: > Simple PR removing an obsolete properties file, > > TIA This pull request has now been integrated. Changeset: e4e457f6 Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/e4e457f6966568ed93093e57c0f7cd50f2bfba95 Stats: 570 lines in 1 file changed: 0 ins; 570 del; 0 mod 8366871: (javac) legacy.properties seems to be an obsolete file Reviewed-by: liach ------------- PR: https://git.openjdk.org/jdk/pull/28001 From rriggs at openjdk.org Mon Oct 27 20:45:02 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Mon, 27 Oct 2025 20:45:02 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently In-Reply-To: References: Message-ID: On Fri, 24 Oct 2025 09:45:38 GMT, Pavel Rappo wrote: > Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. > > Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. Looks good. ------------- Marked as reviewed by rriggs (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27972#pullrequestreview-3385391439 From vromero at openjdk.org Mon Oct 27 21:19:03 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 27 Oct 2025 21:19:03 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics [v2] In-Reply-To: References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Thu, 9 Oct 2025 12:20:08 GMT, Liam Miller-Cushon wrote: >> Hi, >> >> Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. >> >> Before: >> >> >> T.java:2: error: method does not override or implement a method from a supertype >> @Override >> ^ >> >> >> After: >> >> >> T.java:2: error: f() does not override or implement a method from a supertype >> @Override >> ^ >> 1 error > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Update more diagnostics lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27692#pullrequestreview-3385498160 From cushon at openjdk.org Mon Oct 27 21:28:58 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Mon, 27 Oct 2025 21:28:58 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics [v3] In-Reply-To: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: > Hi, > > Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. > > Before: > > > T.java:2: error: method does not override or implement a method from a supertype > @Override > ^ > > > After: > > > T.java:2: error: f() does not override or implement a method from a supertype > @Override > ^ > 1 error Liam Miller-Cushon has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains three additional commits since the last revision: - Merge branch 'openjdk:master' into JDK-8369428 - Update more diagnostics - 8369428: Include method name in 'does not override or implement' diagnostics ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27692/files - new: https://git.openjdk.org/jdk/pull/27692/files/fc64a0b4..4d55ceb0 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27692&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27692&range=01-02 Stats: 58933 lines in 1501 files changed: 35159 ins; 15739 del; 8035 mod Patch: https://git.openjdk.org/jdk/pull/27692.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27692/head:pull/27692 PR: https://git.openjdk.org/jdk/pull/27692 From liach at openjdk.org Mon Oct 27 21:28:59 2025 From: liach at openjdk.org (Chen Liang) Date: Mon, 27 Oct 2025 21:28:59 GMT Subject: RFR: 8369428: Include method name in 'does not override or implement' diagnostics [v3] In-Reply-To: References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: <-Ni8sRKwt4NHwCGdbX9v4Fn-ur11ngqvnnOCSj2ydig=.b33566a6-ad23-44c0-9bf2-0a3cef3267b8@github.com> On Mon, 27 Oct 2025 21:25:26 GMT, Liam Miller-Cushon wrote: >> Hi, >> >> Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. >> >> Before: >> >> >> T.java:2: error: method does not override or implement a method from a supertype >> @Override >> ^ >> >> >> After: >> >> >> T.java:2: error: f() does not override or implement a method from a supertype >> @Override >> ^ >> 1 error > > Liam Miller-Cushon has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains three additional commits since the last revision: > > - Merge branch 'openjdk:master' into JDK-8369428 > - Update more diagnostics > - 8369428: Include method name in 'does not override or implement' diagnostics Sorry for a very late reply but this does look much more informative. ------------- Marked as reviewed by liach (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27692#pullrequestreview-3385522674 From alanb at openjdk.org Tue Oct 28 07:00:03 2025 From: alanb at openjdk.org (Alan Bateman) Date: Tue, 28 Oct 2025 07:00:03 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently In-Reply-To: References: Message-ID: On Fri, 24 Oct 2025 09:45:38 GMT, Pavel Rappo wrote: > Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. > > Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java line 1044: > 1042: * already cancelled. This interrupts the threads executing unfinished subtasks. This > 1043: * method then waits for all threads to finish. If interrupted while waiting then it > 1044: * will continue to wait until the threads finish, before completing with the interrupted Can you drop the change to this file from the PR as we have reworded this paragraph as part of the updated for JEP 525. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27972#discussion_r2468133283 From alanb at openjdk.org Tue Oct 28 07:52:03 2025 From: alanb at openjdk.org (Alan Bateman) Date: Tue, 28 Oct 2025 07:52:03 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently In-Reply-To: References: Message-ID: On Fri, 24 Oct 2025 09:45:38 GMT, Pavel Rappo wrote: > Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. > > Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. I skimmed through the replace and it looks okay. There are several places where we should be linking as "interrupted status" will look like a grammatical error with the change. We do that as needed, not this PR. This is the first update to some of these files in 2025 so you will need to update the copyright header of those files. src/java.base/share/classes/java/net/DatagramSocket.java line 614: > 612: * interrupting a thread receiving a datagram packet will close the > 613: * underlying channel and cause this method to throw {@link > 614: * java.nio.channels.ClosedByInterruptException} with the interrupted Can you change this to "the thread's interrupted status set"? src/java.base/share/classes/java/net/DatagramSocket.java line 620: > 618: * datagram packet. In that case, interrupting the virtual thread will > 619: * cause it to wakeup and close the socket. This method will then throw > 620: * {@code SocketException} with the interrupted status set. Same thing here, and in ServerSocket and Socket. test/jdk/java/lang/Thread/virtual/CustomScheduler.java line 207: > 205: > 206: /** > 207: * Test running task with the carrier interrupted status set. We can change this to "the carrier's interrupted status set". ------------- Marked as reviewed by alanb (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27972#pullrequestreview-3387081610 PR Review Comment: https://git.openjdk.org/jdk/pull/27972#discussion_r2468253205 PR Review Comment: https://git.openjdk.org/jdk/pull/27972#discussion_r2468257078 PR Review Comment: https://git.openjdk.org/jdk/pull/27972#discussion_r2468273763 From cushon at openjdk.org Tue Oct 28 08:57:11 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Tue, 28 Oct 2025 08:57:11 GMT Subject: Integrated: 8369428: Include method name in 'does not override or implement' diagnostics In-Reply-To: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> References: <6QTLwzfiTq2xXYjd42ITL9v39vqLm2ndoIfeEf-UteA=.982a5fec-805a-4ca2-ba96-2658a382d01e@github.com> Message-ID: On Wed, 8 Oct 2025 14:12:57 GMT, Liam Miller-Cushon wrote: > Hi, > > Please consider this small improvement to `compiler.err.method.does.not.override.superclass` diagnostics, to include the method name. > > Before: > > > T.java:2: error: method does not override or implement a method from a supertype > @Override > ^ > > > After: > > > T.java:2: error: f() does not override or implement a method from a supertype > @Override > ^ > 1 error This pull request has now been integrated. Changeset: f82cc22b Author: Liam Miller-Cushon URL: https://git.openjdk.org/jdk/commit/f82cc22bfe675ca263270a932f9cc12e837a7f65 Stats: 15 lines in 10 files changed: 3 ins; 0 del; 12 mod 8369428: Include method name in 'does not override or implement' diagnostics Reviewed-by: vromero, liach ------------- PR: https://git.openjdk.org/jdk/pull/27692 From prappo at openjdk.org Tue Oct 28 10:06:36 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Tue, 28 Oct 2025 10:06:36 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v2] In-Reply-To: References: Message-ID: > Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. > > Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. Pavel Rappo has updated the pull request incrementally with three additional commits since the last revision: - Update copyright years Note: any commit hashes below might be outdated due to subsequent history rewriting (e.g. git rebase). + update make/langtools/tools/javacserver/server/CompilerThreadPool.java due to a10f8b4304d + update src/java.base/share/classes/java/lang/Object.java due to a10f8b4304d + update src/java.base/share/classes/java/net/DatagramSocket.java due to a6a23d6fdaf + update src/java.base/share/classes/java/net/ServerSocket.java due to a6a23d6fdaf + update src/java.base/share/classes/java/nio/channels/DatagramChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/FileChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/InterruptibleChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ReadableByteChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ScatteringByteChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/Selector.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/SocketChannel.java due to a10f8b4304d + update src/java.base/share/classes/sun/nio/ch/Interruptible.java due to a10f8b4304d + update src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java due to a10f8b4304d + update src/java.desktop/share/classes/java/awt/Robot.java due to a10f8b4304d + update src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpChannel.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpMultiChannel.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpServerChannel.java due to a10f8b4304d + update test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/InterruptThread/intrpthrd001/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/newclass02/java.base/java/lang/Object.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP01/sp01t002/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP01/sp01t003/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllDiag.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinDiag.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/runner/MemDiag.java due to a10f8b4304d + update test/jdk/java/lang/Thread/JoinWithDuration.java due to a10f8b4304d + update test/jdk/java/lang/Thread/SleepWithDuration.java due to a10f8b4304d + update test/jdk/java/lang/Thread/virtual/CustomScheduler.java due to a6a23d6fdaf + update test/jdk/java/nio/channels/Channels/SocketChannelStreams.java due to a10f8b4304d + update test/jdk/java/nio/channels/FileChannel/CloseDuringTransfer.java due to a10f8b4304d + update test/jdk/java/nio/channels/FileChannel/ClosedByInterrupt.java due to a10f8b4304d + update test/jdk/java/nio/channels/Pipe/PipeInterrupt.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/LotsOfInterrupts.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/SelectWithConsumer.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/WakeupAfterClose.java due to a10f8b4304d + update test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java due to a10f8b4304d + update test/jdk/java/nio/file/Files/CallWithInterruptSet.java due to a10f8b4304d + update test/jdk/java/nio/file/Files/InterruptCopy.java due to a10f8b4304d + update test/jdk/java/util/concurrent/CompletableFuture/LostInterrupt.java due to a10f8b4304d + update test/jdk/java/util/concurrent/CompletableFuture/SwallowedInterruptedException.java due to a10f8b4304d + update test/jdk/java/util/concurrent/ExecutorService/CloseTest.java due to a10f8b4304d + update test/jdk/java/util/concurrent/ExecutorService/InvokeTest.java due to a10f8b4304d + update test/jdk/java/util/zip/InterruptibleZip.java due to a10f8b4304d - Reword for clarity as suggested - Drop to ease upcoming merge from loom repo ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27972/files - new: https://git.openjdk.org/jdk/pull/27972/files/a10f8b43..89dbafe0 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27972&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27972&range=00-01 Stats: 67 lines in 47 files changed: 4 ins; 0 del; 63 mod Patch: https://git.openjdk.org/jdk/pull/27972.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27972/head:pull/27972 PR: https://git.openjdk.org/jdk/pull/27972 From alanb at openjdk.org Tue Oct 28 10:10:11 2025 From: alanb at openjdk.org (Alan Bateman) Date: Tue, 28 Oct 2025 10:10:11 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v2] In-Reply-To: References: Message-ID: On Tue, 28 Oct 2025 10:06:36 GMT, Pavel Rappo wrote: >> Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. >> >> Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. > > Pavel Rappo has updated the pull request incrementally with three additional commits since the last revision: > > - Update copyright years > > Note: any commit hashes below might be outdated due to subsequent > history rewriting (e.g. git rebase). > > + update make/langtools/tools/javacserver/server/CompilerThreadPool.java due to a10f8b4304d > + update src/java.base/share/classes/java/lang/Object.java due to a10f8b4304d > + update src/java.base/share/classes/java/net/DatagramSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/net/ServerSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/nio/channels/DatagramChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/FileChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/InterruptibleChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ReadableByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ScatteringByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/Selector.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/SocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/sun/nio/ch/Interruptible.java due to a10f8b4304d > + update src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java due to a10f8b4304d > + update src/java.desktop/share/classes/java/awt/Robot.java due to a10f8b4304d > + update src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpMultiChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpServerChannel.java due to a10f8b4304d > + update test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java due to a10f8b4304d > + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/InterruptThread/intrpthrd001/TestDescription.java due to a10f8b4304d > + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/newclass02/java.base/java/lang/Object.java due to a10f8b4304d > + update test/... Marked as reviewed by alanb (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27972#pullrequestreview-3387827557 From cushon at openjdk.org Tue Oct 28 11:47:12 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Tue, 28 Oct 2025 11:47:12 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings Message-ID: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. ------------- Commit messages: - 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings Changes: https://git.openjdk.org/jdk/pull/28018/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370800 Stats: 11 lines in 3 files changed: 3 ins; 0 del; 8 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From abimpoudis at openjdk.org Tue Oct 28 12:46:30 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Tue, 28 Oct 2025 12:46:30 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v2] In-Reply-To: References: Message-ID: > Draft PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview) Aggelos Biboudis has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains one new commit since the last revision: 8359145: JEP 530: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27637/files - new: https://git.openjdk.org/jdk/pull/27637/files/d15b13e7..f1448e1b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=00-01 Stats: 0 lines in 0 files changed: 0 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/27637.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27637/head:pull/27637 PR: https://git.openjdk.org/jdk/pull/27637 From prappo at openjdk.org Tue Oct 28 14:25:06 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Tue, 28 Oct 2025 14:25:06 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v3] In-Reply-To: References: Message-ID: > Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. > > Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. Pavel Rappo has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision: - Merge remote-tracking branch 'jdk/master' into 8370568 - Update copyright years Note: any commit hashes below might be outdated due to subsequent history rewriting (e.g. git rebase). + update make/langtools/tools/javacserver/server/CompilerThreadPool.java due to a10f8b4304d + update src/java.base/share/classes/java/lang/Object.java due to a10f8b4304d + update src/java.base/share/classes/java/net/DatagramSocket.java due to a6a23d6fdaf + update src/java.base/share/classes/java/net/ServerSocket.java due to a6a23d6fdaf + update src/java.base/share/classes/java/nio/channels/DatagramChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/FileChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/InterruptibleChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ReadableByteChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ScatteringByteChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/Selector.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/SocketChannel.java due to a10f8b4304d + update src/java.base/share/classes/sun/nio/ch/Interruptible.java due to a10f8b4304d + update src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java due to a10f8b4304d + update src/java.desktop/share/classes/java/awt/Robot.java due to a10f8b4304d + update src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpChannel.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpMultiChannel.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpServerChannel.java due to a10f8b4304d + update test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/InterruptThread/intrpthrd001/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/newclass02/java.base/java/lang/Object.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP01/sp01t002/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP01/sp01t003/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllDiag.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinDiag.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/runner/MemDiag.java due to a10f8b4304d + update test/jdk/java/lang/Thread/JoinWithDuration.java due to a10f8b4304d + update test/jdk/java/lang/Thread/SleepWithDuration.java due to a10f8b4304d + update test/jdk/java/lang/Thread/virtual/CustomScheduler.java due to a6a23d6fdaf + update test/jdk/java/nio/channels/Channels/SocketChannelStreams.java due to a10f8b4304d + update test/jdk/java/nio/channels/FileChannel/CloseDuringTransfer.java due to a10f8b4304d + update test/jdk/java/nio/channels/FileChannel/ClosedByInterrupt.java due to a10f8b4304d + update test/jdk/java/nio/channels/Pipe/PipeInterrupt.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/LotsOfInterrupts.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/SelectWithConsumer.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/WakeupAfterClose.java due to a10f8b4304d + update test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java due to a10f8b4304d + update test/jdk/java/nio/file/Files/CallWithInterruptSet.java due to a10f8b4304d + update test/jdk/java/nio/file/Files/InterruptCopy.java due to a10f8b4304d + update test/jdk/java/util/concurrent/CompletableFuture/LostInterrupt.java due to a10f8b4304d + update test/jdk/java/util/concurrent/CompletableFuture/SwallowedInterruptedException.java due to a10f8b4304d + update test/jdk/java/util/concurrent/ExecutorService/CloseTest.java due to a10f8b4304d + update test/jdk/java/util/concurrent/ExecutorService/InvokeTest.java due to a10f8b4304d + update test/jdk/java/util/zip/InterruptibleZip.java due to a10f8b4304d - Reword for clarity as suggested - Drop to ease upcoming merge from loom repo - Initial commit ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27972/files - new: https://git.openjdk.org/jdk/pull/27972/files/89dbafe0..b3297337 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27972&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27972&range=01-02 Stats: 3639 lines in 160 files changed: 1891 ins; 1140 del; 608 mod Patch: https://git.openjdk.org/jdk/pull/27972.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27972/head:pull/27972 PR: https://git.openjdk.org/jdk/pull/27972 From liach at openjdk.org Tue Oct 28 17:58:33 2025 From: liach at openjdk.org (Chen Liang) Date: Tue, 28 Oct 2025 17:58:33 GMT Subject: RFR: 8370687: Improve before constructor has been called error message In-Reply-To: References: Message-ID: On Mon, 27 Oct 2025 19:27:43 GMT, Chen Liang wrote: > In the Valhalla EA2 preview, Value class and record constructor body is in prologue by default, as opposed to all existing constructors and all identity constructors in EA2. This causes a confusion because the error message `cant.ref.before.ctor.called` can appear in such constructors without explicit constructor invocations. > > After discussion with @vicente-romero-oracle, we decide to commit this change onto mainline: these two errors never happen in constructors without explicit constructor invocation (colloquially "this" or "super" calls) on mainline, so this message update would not create new confusions. This is future-proof, and is more consistent with the related `call.must.only.appear.in.ctor` message, which is "explicit constructor invocation may only appear within a constructor body". Thanks for the reviews! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28007#issuecomment-3457778801 From liach at openjdk.org Tue Oct 28 18:02:03 2025 From: liach at openjdk.org (Chen Liang) Date: Tue, 28 Oct 2025 18:02:03 GMT Subject: Integrated: 8370687: Improve before constructor has been called error message In-Reply-To: References: Message-ID: On Mon, 27 Oct 2025 19:27:43 GMT, Chen Liang wrote: > In the Valhalla EA2 preview, Value class and record constructor body is in prologue by default, as opposed to all existing constructors and all identity constructors in EA2. This causes a confusion because the error message `cant.ref.before.ctor.called` can appear in such constructors without explicit constructor invocations. > > After discussion with @vicente-romero-oracle, we decide to commit this change onto mainline: these two errors never happen in constructors without explicit constructor invocation (colloquially "this" or "super" calls) on mainline, so this message update would not create new confusions. This is future-proof, and is more consistent with the related `call.must.only.appear.in.ctor` message, which is "explicit constructor invocation may only appear within a constructor body". This pull request has now been integrated. Changeset: 20e55faf Author: Chen Liang URL: https://git.openjdk.org/jdk/commit/20e55fafb39dd74a044d7fda8a2b3409cc00bf54 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod 8370687: Improve before constructor has been called error message Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/28007 From vromero at openjdk.org Tue Oct 28 18:08:19 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 28 Oct 2025 18:08:19 GMT Subject: RFR: 8369508: Type annotations on anonymous new class creation expressions can't be retrieved [v2] In-Reply-To: <_ESmaroFK9q4FrDFTEJQNa_DhdJm1U3vZrmXZ-zKE80=.cd6e1dd3-21f2-4c02-99ac-e88686bbf649@github.com> References: <_ESmaroFK9q4FrDFTEJQNa_DhdJm1U3vZrmXZ-zKE80=.cd6e1dd3-21f2-4c02-99ac-e88686bbf649@github.com> Message-ID: On Fri, 10 Oct 2025 15:26:29 GMT, Liam Miller-Cushon wrote: >> Hi, >> >> Please consider this fix for [JDK-8369508: Type annotations on anonymous new class creation expressions can't be retrieved](https://bugs.openjdk.org/browse/JDK-8369508). >> >> When visiting a type annotation on an anonymous class instantiation expression, javac currently skips attribution of the annotated type when visiting it as part of the `new` expression, to prevent them from being incorrectly attached to the enclosing method instead of the synthetic declaration of the anonymous class (see [JDK-8198945](https://bugs.openjdk.org/browse/JDK-8198945)). However because this logic happens early, and results in skipping attribution of these annotations, they aren't available on the type model elements for the new class creation expression, which means they can't be retrieved by clients of the compiler tree API. >> >> This fix shifts the handling of these annotations later, to allow them to get attributed, but then to still prevent them from being attached to the enclosing method symbol of the anonymous class declaration. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Reorder an assertion looks sensible ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27730#pullrequestreview-3390155311 From cushon at openjdk.org Tue Oct 28 18:34:15 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Tue, 28 Oct 2025 18:34:15 GMT Subject: RFR: 8369508: Type annotations on anonymous new class creation expressions can't be retrieved [v3] In-Reply-To: References: Message-ID: <1-mzzDMc8ol5YQJEA-n8ZTI_wD-SwbLodK73z0AUJZU=.2c1b39a0-58b0-49f5-8bc2-58b9f009ff87@github.com> > Hi, > > Please consider this fix for [JDK-8369508: Type annotations on anonymous new class creation expressions can't be retrieved](https://bugs.openjdk.org/browse/JDK-8369508). > > When visiting a type annotation on an anonymous class instantiation expression, javac currently skips attribution of the annotated type when visiting it as part of the `new` expression, to prevent them from being incorrectly attached to the enclosing method instead of the synthetic declaration of the anonymous class (see [JDK-8198945](https://bugs.openjdk.org/browse/JDK-8198945)). However because this logic happens early, and results in skipping attribution of these annotations, they aren't available on the type model elements for the new class creation expression, which means they can't be retrieved by clients of the compiler tree API. > > This fix shifts the handling of these annotations later, to allow them to get attributed, but then to still prevent them from being attached to the enclosing method symbol of the anonymous class declaration. Liam Miller-Cushon has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains four additional commits since the last revision: - Merge branch 'openjdk:master' into JDK-8369508 - Reorder an assertion - Cleanup - 8369508: Type annotations on anonymous new class creation expressions can't be retrieved ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27730/files - new: https://git.openjdk.org/jdk/pull/27730/files/bc796344..fddf385e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27730&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27730&range=01-02 Stats: 60862 lines in 1565 files changed: 36489 ins; 16036 del; 8337 mod Patch: https://git.openjdk.org/jdk/pull/27730.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27730/head:pull/27730 PR: https://git.openjdk.org/jdk/pull/27730 From vromero at openjdk.org Tue Oct 28 18:59:57 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 28 Oct 2025 18:59:57 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v2] In-Reply-To: References: Message-ID: On Wed, 22 Oct 2025 18:07:37 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Update another affected test test/langtools/tools/doclint/CrashInTypeAnnotateTest.java line 18: > 16: @interface A {} > 17: > 18: /** {@link List<@Nullable String>} shouldn't this be: `{@link List<@A String>}`? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27901#discussion_r2470721961 From rriggs at openjdk.org Wed Oct 29 01:49:05 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Wed, 29 Oct 2025 01:49:05 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v3] In-Reply-To: References: Message-ID: On Tue, 28 Oct 2025 14:25:06 GMT, Pavel Rappo wrote: >> Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. >> >> Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. > > Pavel Rappo has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision: > > - Merge remote-tracking branch 'jdk/master' into 8370568 > - Update copyright years > > Note: any commit hashes below might be outdated due to subsequent > history rewriting (e.g. git rebase). > > + update make/langtools/tools/javacserver/server/CompilerThreadPool.java due to a10f8b4304d > + update src/java.base/share/classes/java/lang/Object.java due to a10f8b4304d > + update src/java.base/share/classes/java/net/DatagramSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/net/ServerSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/nio/channels/DatagramChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/FileChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/InterruptibleChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ReadableByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ScatteringByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/Selector.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/SocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/sun/nio/ch/Interruptible.java due to a10f8b4304d > + update src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java due to a10f8b4304d > + update src/java.desktop/share/classes/java/awt/Robot.java due to a10f8b4304d > + update src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpMultiChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpServerChannel.java due to a10f8b4304d > + update test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java due to a10f8b4304d > + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/InterruptThread/intrpthrd001/Test... Nice cleanup. ------------- Marked as reviewed by rriggs (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27972#pullrequestreview-3391422490 From cstein at openjdk.org Wed Oct 29 06:58:31 2025 From: cstein at openjdk.org (Christian Stein) Date: Wed, 29 Oct 2025 06:58:31 GMT Subject: RFR: 8370175: State engine terminates when throwing self-caused exception Message-ID: Please review this change to prevent an engine termination in `jshell` in a self-causation exception scenario. Prior to the fix, a non-null cause exception was unconditionally converted and used. Now, a set with identity equalitiy semantics is guarding the process, by breaking a recursive chains when a reference cycle is detected. The guard implementation is inspired by the one used in [java.base/java.lang.Throwable](https://github.com/openjdk/jdk/blob/0687f120cc324f35fe43d811b6beb4184fd854ec/src/java.base/share/classes/java/lang/Throwable.java#L689-L693) Note that a direct self-causation state is already prevented at the `Throwable::initCause` method level: jshell> var t = new Throwable() t ==> java.lang.Throwable jshell> t.initCause(t) | Exception java.lang.IllegalArgumentException: Self-causation not permitted | at Throwable.initCause (Throwable.java:492) | at (#8:1) | Caused by: java.lang.Throwable | at do_it$Aux (#7:1) | at (#7:1) ------------- Commit messages: - Compact implementation and add test - 8370175: State engine terminates when throwing self-caused exception Changes: https://git.openjdk.org/jdk/pull/28037/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28037&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370175 Stats: 30 lines in 2 files changed: 25 ins; 0 del; 5 mod Patch: https://git.openjdk.org/jdk/pull/28037.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28037/head:pull/28037 PR: https://git.openjdk.org/jdk/pull/28037 From jlahoda at openjdk.org Wed Oct 29 07:01:32 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 29 Oct 2025 07:01:32 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v2] In-Reply-To: References: Message-ID: On Wed, 22 Oct 2025 18:07:37 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Update another affected test Looks good to me, except for the test tweak as @vicente-romero-oracle suggests. Thanks! ------------- PR Comment: https://git.openjdk.org/jdk/pull/27901#issuecomment-3460103262 From cushon at openjdk.org Wed Oct 29 07:29:12 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 07:29:12 GMT Subject: Integrated: 8369508: Type annotations on anonymous new class creation expressions can't be retrieved In-Reply-To: References: Message-ID: On Thu, 9 Oct 2025 14:35:58 GMT, Liam Miller-Cushon wrote: > Hi, > > Please consider this fix for [JDK-8369508: Type annotations on anonymous new class creation expressions can't be retrieved](https://bugs.openjdk.org/browse/JDK-8369508). > > When visiting a type annotation on an anonymous class instantiation expression, javac currently skips attribution of the annotated type when visiting it as part of the `new` expression, to prevent them from being incorrectly attached to the enclosing method instead of the synthetic declaration of the anonymous class (see [JDK-8198945](https://bugs.openjdk.org/browse/JDK-8198945)). However because this logic happens early, and results in skipping attribution of these annotations, they aren't available on the type model elements for the new class creation expression, which means they can't be retrieved by clients of the compiler tree API. > > This fix shifts the handling of these annotations later, to allow them to get attributed, but then to still prevent them from being attached to the enclosing method symbol of the anonymous class declaration. This pull request has now been integrated. Changeset: c97d50d7 Author: Liam Miller-Cushon URL: https://git.openjdk.org/jdk/commit/c97d50d793df46292e38707956586dfaa4b77d32 Stats: 32 lines in 3 files changed: 11 ins; 13 del; 8 mod 8369508: Type annotations on anonymous new class creation expressions can't be retrieved Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/27730 From cushon at openjdk.org Wed Oct 29 07:39:23 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 07:39:23 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v3] In-Reply-To: References: Message-ID: > Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Fix typo in test ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27901/files - new: https://git.openjdk.org/jdk/pull/27901/files/a99313bc..6af3b250 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=01-02 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27901.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27901/head:pull/27901 PR: https://git.openjdk.org/jdk/pull/27901 From cushon at openjdk.org Wed Oct 29 07:39:25 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 07:39:25 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v2] In-Reply-To: References: Message-ID: <1r8w1AZVc9ICVqs2TiRbQ0JpRxTPu61OD5Nj7tph5IA=.922c4514-4d81-4629-a489-b52c7c6ecda9@github.com> On Tue, 28 Oct 2025 18:57:32 GMT, Vicente Romero wrote: >> Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: >> >> Update another affected test > > test/langtools/tools/doclint/CrashInTypeAnnotateTest.java line 18: > >> 16: @interface A {} >> 17: >> 18: /** {@link List<@Nullable String>} > > shouldn't this be: `{@link List<@A String>}`? Thanks, fixed. This test was reproducing the crash even with the typo to use the wrong annotation, but definitely better not to rely on that. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27901#discussion_r2471998613 From jlahoda at openjdk.org Wed Oct 29 07:55:01 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 29 Oct 2025 07:55:01 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Tue, 28 Oct 2025 11:41:01 GMT, Liam Miller-Cushon wrote: > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. So, overall, I am not convinced this is a good move. Yes, we have some existing cases where missing stuff produces just warnings in the class reader, but these are cases where annotations, or their attributes, are missing. Not when the actual field/method type is missing. I.e. in the test case, not producing an error for missing `@Anno` would seem more or less OK to me, but ignoring errors for missing type `A` makes much less sense to me. But, even if we decided to ignore the missing class error, the implementation is, sadly, wrong. We cannot just ignore the `CompletionFailure`, as that will never be thrown again for the given `ClassSymbol`. And then javac may proceed to generate a classfile for a broken input. For example, changing the test to: void testMissingEnclosingType() throws Exception { String annoSrc = """ import static java.lang.annotation.ElementType.TYPE_USE; import java.lang.annotation.Target; @Target(TYPE_USE) @interface Anno {} class A {} class B { public @Anno A a; } """; String cSrc = """ class C { B b; public void test() { b.a.toString(); } } """; Path base = Paths.get("."); Path src = base.resolve("src"); tb.createDirectories(src); tb.writeJavaFiles(src, annoSrc, cSrc); Path out = base.resolve("out"); tb.createDirectories(out); new JavacTask(tb).outdir(out).files(tb.findJavaFiles(src)).run(); // now if we remove A.class javac should not crash tb.deleteFiles(out.resolve("A.class")); List log = new JavacTask(tb) .outdir(out) .classpath(out) .options(/*"-Werror", */"-XDrawDiagnostics") .files(src.resolve("C.java")) .run(Expect.FAIL) .writeAll() .getOutputLines(Task.OutputKind.DIRECT); var expectedOutput = List.of( "B.class:-:-: compiler.warn.cant.attach.type.annotations: @Anno, B, a," + " (compiler.misc.class.file.not.found: A)", "- compiler.err.warnings.and.werror", "1 error", "1 warning"); if (!expectedOutput.equals(log)) { throw new Exception("expected output not found: " + log); } } leads to: An exception has occurred in the compiler (26-internal). Please file a bug against the Java compiler via the Java bug reporting page (https://bugreport.java.com) after checking the Bug Database (https://bugs.java.com) for duplicates. Include your program, the following diagnostic, and the parameters passed to the Java compiler in your report. Thank you. java.lang.ClassCastException: class com.sun.tools.javac.code.Symbol$ClassSymbol cannot be cast to class com.sun.tools.javac.code.Symbol$MethodSymbol (com.sun.tools.javac.code.Symbol$ClassSymbol and com.sun.tools.javac.code.Symbol$MethodSymbol are in module jdk.compiler of loader 'app') at jdk.compiler/com.sun.tools.javac.comp.TransTypes.visitApply(TransTypes.java:931) at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1869) at jdk.compiler/com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58) at jdk.compiler/com.sun.tools.javac.comp.TransTypes.translate(TransTypes.java:450) ... I think that if you really want to ignore the `CompletionFailure`s at this point, `DeferredCompletionFailureHandler` needs to be used to re-set the `ClassSymbol` for `A` to the original state. `speculativeCodeHandler` might be usable for this (look how it is used in `DeferredAttr`). `b.a.toString();` in the above testcase would then hopefully produce a compile-time error correctly. Second problem is that catching the `CompletionFailure` at this place may leave some of the annotations unassigned, leading to an inconsistent model. Like, what if the type of the field is `@Anno Triple<@Anno Integer, @Anno A, @Anno String>` (where `A` is missing) - I may get some of the types with the annotation, and some without, no? Shouldn't the annotations be applied consistently? (It is an issue even now, but now javac reports an error, so it is less of a problem if the model is sub-optimal.) ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3460238387 From jlahoda at openjdk.org Wed Oct 29 08:13:02 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 29 Oct 2025 08:13:02 GMT Subject: RFR: 8370175: State engine terminates when throwing self-caused exception In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 06:51:12 GMT, Christian Stein wrote: > Please review this change to prevent an engine termination in `jshell` in a self-causation exception scenario. > > Prior to the fix, a non-null cause exception was unconditionally converted and used. Now, a set with identity equalitiy semantics is guarding the process, by breaking a recursive chains when a reference cycle is detected. The guard implementation is inspired by the one used in [java.base/java.lang.Throwable](https://github.com/openjdk/jdk/blob/0687f120cc324f35fe43d811b6beb4184fd854ec/src/java.base/share/classes/java/lang/Throwable.java#L689-L693) > > Note that a direct self-causation state is already prevented at the `Throwable::initCause` method level: > > > jshell> var t = new Throwable() > t ==> java.lang.Throwable > > jshell> t.initCause(t) > | Exception java.lang.IllegalArgumentException: Self-causation not permitted > | at Throwable.initCause (Throwable.java:492) > | at (#8:1) > | Caused by: java.lang.Throwable > | at do_it$Aux (#7:1) > | at (#7:1) Looks reasonable to me. ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28037#pullrequestreview-3392110797 From jlahoda at openjdk.org Wed Oct 29 08:16:08 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 29 Oct 2025 08:16:08 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v3] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 07:39:23 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Fix typo in test Looks good to me. (I didn't run tests, though.) ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27901#pullrequestreview-3392123641 From cushon at openjdk.org Wed Oct 29 08:49:24 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 08:49:24 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v2] In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Use DeferredCompletionFailureHandler ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28018/files - new: https://git.openjdk.org/jdk/pull/28018/files/8a5aba58..0a6c9590 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=00-01 Stats: 14 lines in 2 files changed: 7 ins; 1 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From cushon at openjdk.org Wed Oct 29 08:54:05 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 08:54:05 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v2] In-Reply-To: References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: On Wed, 29 Oct 2025 08:49:24 GMT, Liam Miller-Cushon wrote: >> Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). >> >> As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. >> >> The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. > > Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: > > Use DeferredCompletionFailureHandler Thanks very much for the review! > So, overall, I am not convinced this is a good move. Yes, we have some existing cases where missing stuff produces just warnings in the class reader, but these are cases where annotations, or their attributes, are missing. Not when the actual field/method type is missing. I.e. in the test case, not producing an error for missing `@Anno` would seem more or less OK to me, but ignoring errors for missing type `A` makes much less sense to me. I had been thinking about it similarly, that it would be better to report and error and just add the missing transitive deps. I've heard feedback about a couple of cases where the code owners didn't want to do that, because the deps were only used for thinks like `@link` tags or for optional / provided framework dependencies. Overall it might make sense to move this back to a draft and collect more feedback in the bug. > I think that if you really want to ignore the `CompletionFailure`s at this point, `DeferredCompletionFailureHandler` needs to be used to re-set the `ClassSymbol` for `A` to the original state. `speculativeCodeHandler` might be usable for this (look how it is used in `DeferredAttr`). `b.a.toString();` in the above testcase would then hopefully produce a compile-time error correctly. Thanks! I experimented with doing that and it avoids the crash, and I have pushed those changes to the PR, but I realize that doesn't fully solve the issues you raised and this needs more thought and discussion. > Second problem is that catching the `CompletionFailure` at this place may leave some of the annotations unassigned, leading to an inconsistent model. Like, what if the type of the field is `@Anno Triple<@Anno Integer, @Anno A, @Anno String>` (where `A` is missing) - I may get some of the types with the annotation, and some without, no? Shouldn't the annotations be applied consistently? (It is an issue even now, but now javac reports an error, so it is less of a problem if the model is sub-optimal.) Yes, I guess to continue with this approach of trying to recover from the `CompletionFailure`s, we'd want to push that handling into the logic for attaching annotations, and recover and continue attaching annotations where possible instead of stopping. I do think that's a somewhat rare issue. If these diagnostics did end up getting downgraded to warnings, compilations that are relying on accurate type annotation information would likely want to promote them to errors. And the examples in the bug weren't generally trying to read the type annotations, they just wanted compilation to succeed with incomplete classpaths. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28018#issuecomment-3460423634 From fandreuzzi at openjdk.org Wed Oct 29 09:02:12 2025 From: fandreuzzi at openjdk.org (Francesco Andreuzzi) Date: Wed, 29 Oct 2025 09:02:12 GMT Subject: RFR: 8370175: State engine terminates when throwing self-caused exception In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 06:51:12 GMT, Christian Stein wrote: > Please review this change to prevent an engine termination in `jshell` in a self-causation exception scenario. > > Prior to the fix, a non-null cause exception was unconditionally converted and used. Now, a set with identity equalitiy semantics is guarding the process, by breaking a recursive chains when a reference cycle is detected. The guard implementation is inspired by the one used in [java.base/java.lang.Throwable](https://github.com/openjdk/jdk/blob/0687f120cc324f35fe43d811b6beb4184fd854ec/src/java.base/share/classes/java/lang/Throwable.java#L689-L693) > > Note that a direct self-causation state is already prevented at the `Throwable::initCause` method level: > > > jshell> var t = new Throwable() > t ==> java.lang.Throwable > > jshell> t.initCause(t) > | Exception java.lang.IllegalArgumentException: Self-causation not permitted > | at Throwable.initCause (Throwable.java:492) > | at (#8:1) > | Caused by: java.lang.Throwable > | at do_it$Aux (#7:1) > | at (#7:1) Marked as reviewed by fandreuzzi (Author). ------------- PR Review: https://git.openjdk.org/jdk/pull/28037#pullrequestreview-3392275100 From asotona at openjdk.org Wed Oct 29 09:14:44 2025 From: asotona at openjdk.org (Adam Sotona) Date: Wed, 29 Oct 2025 09:14:44 GMT Subject: RFR: 8366691: JShell should support a more convenient completion In-Reply-To: References: Message-ID: On Tue, 2 Sep 2025 13:05:01 GMT, Jan Lahoda wrote: > JShell tool has the code completion feature in the terminal, allowing to tab-complete inputs. The JShell engine also has an API to compute the completions. But, the API is more suitable for a terminal-based UI, not for a GUI. > > The goal in this PR is to provide an API that would allow better code completions in GUI frontends for JShell. > > The main idea here is that the user of the API will get information could the context and `Element` that can continue the current input, and can produce UI elements/strings out of this information as necessary. > > The apidiff for the current API is available here: > https://cr.openjdk.org/~jlahoda/8366691/JDK-8366691.00/ Looks good to me. ------------- Marked as reviewed by asotona (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27049#pullrequestreview-3392319759 From jpai at openjdk.org Wed Oct 29 09:42:22 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Wed, 29 Oct 2025 09:42:22 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v3] In-Reply-To: References: Message-ID: On Tue, 28 Oct 2025 14:25:06 GMT, Pavel Rappo wrote: >> Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. >> >> Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. > > Pavel Rappo has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains five additional commits since the last revision: > > - Merge remote-tracking branch 'jdk/master' into 8370568 > - Update copyright years > > Note: any commit hashes below might be outdated due to subsequent > history rewriting (e.g. git rebase). > > + update make/langtools/tools/javacserver/server/CompilerThreadPool.java due to a10f8b4304d > + update src/java.base/share/classes/java/lang/Object.java due to a10f8b4304d > + update src/java.base/share/classes/java/net/DatagramSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/net/ServerSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/nio/channels/DatagramChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/FileChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/InterruptibleChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ReadableByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ScatteringByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/Selector.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/SocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/sun/nio/ch/Interruptible.java due to a10f8b4304d > + update src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java due to a10f8b4304d > + update src/java.desktop/share/classes/java/awt/Robot.java due to a10f8b4304d > + update src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpMultiChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpServerChannel.java due to a10f8b4304d > + update test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java due to a10f8b4304d > + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/InterruptThread/intrpthrd001/Test... Hello Pavel, these changes look OK to me. Over time I think it will be harder to keep track or enforce this in code comments but I think it is easier to enforce for API specification text. ------------- Marked as reviewed by jpai (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27972#pullrequestreview-3392430217 From prappo at openjdk.org Wed Oct 29 10:06:23 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 29 Oct 2025 10:06:23 GMT Subject: RFR: 8370175: State engine terminates when throwing self-caused exception In-Reply-To: References: Message-ID: <9mjV8Kv0dt6Mh16Cyxq7EnOsZ-SCXJYTTgdMut-EOiw=.68036465-14c5-4428-8a25-821ef8dca4c1@github.com> On Wed, 29 Oct 2025 06:51:12 GMT, Christian Stein wrote: > Please review this change to prevent an engine termination in `jshell` in a self-causation exception scenario. > > Prior to the fix, a non-null cause exception was unconditionally converted and used. Now, a set with identity equalitiy semantics is guarding the process, by breaking a recursive chains when a reference cycle is detected. The guard implementation is inspired by the one used in [java.base/java.lang.Throwable](https://github.com/openjdk/jdk/blob/0687f120cc324f35fe43d811b6beb4184fd854ec/src/java.base/share/classes/java/lang/Throwable.java#L689-L693) > > Note that a direct self-causation state is already prevented at the `Throwable::initCause` method level: > > > jshell> var t = new Throwable() > t ==> java.lang.Throwable > > jshell> t.initCause(t) > | Exception java.lang.IllegalArgumentException: Self-causation not permitted > | at Throwable.initCause (Throwable.java:492) > | at (#8:1) > | Caused by: java.lang.Throwable > | at do_it$Aux (#7:1) > | at (#7:1) As a reporter, thanks for taking care of this. One note is that Throwable.printStackTrace also takes care of cycles in _suppressed_ trees. JShell does not seem to print suppressed exceptions, but if it ever does, we will need to treat them the same way. jshell> var e1 = new Error(); ...> var e2 = new Error(); ...> e1.addSuppressed(e2); ...> e2.addSuppressed(e1); ...> e1.printStackTrace(); e1 ==> java.lang.Error e2 ==> java.lang.Error java.lang.Error at REPL.$JShell$2.do_it$Aux($JShell$2.java:6) at REPL.$JShell$2.do_it$($JShell$2.java:11) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) at java.base/java.lang.reflect.Method.invoke(Method.java:565) at jdk.jshell/jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:227) at jdk.jshell/jdk.jshell.execution.RemoteExecutionControl.invoke(RemoteExecutionControl.java:121) at jdk.jshell/jdk.jshell.execution.DirectExecutionControl.invoke(DirectExecutionControl.java:125) at jdk.jshell/jdk.jshell.execution.ExecutionControlForwarder.processCommand(ExecutionControlForwarder.java:148) at jdk.jshell/jdk.jshell.execution.ExecutionControlForwarder.commandLoop(ExecutionControlForwarder.java:266) at jdk.jshell/jdk.jshell.execution.Util.forwardExecutionControl(Util.java:78) at jdk.jshell/jdk.jshell.execution.Util.forwardExecutionControlAndIO(Util.java:148) at jdk.jshell/jdk.jshell.execution.RemoteExecutionControl.main(RemoteExecutionControl.java:74) Suppressed: java.lang.Error at REPL.$JShell$3.do_it$Aux($JShell$3.java:6) at REPL.$JShell$3.do_it$($JShell$3.java:11) ... 10 more Suppressed: [CIRCULAR REFERENCE: java.lang.Error] jshell> throw e1 | Exception java.lang.Error | at do_it$Aux (#1:1) | at (#1:1) Btw, why doesn't JShell print suppressed exceptions? Seems helpful in try-with-resources blocks. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28037#issuecomment-3460688628 From cushon at openjdk.org Wed Oct 29 10:22:36 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 10:22:36 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v4] In-Reply-To: References: Message-ID: > Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Update examples.not-yet.txt ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27901/files - new: https://git.openjdk.org/jdk/pull/27901/files/6af3b250..152ef5fa Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=02-03 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/27901.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27901/head:pull/27901 PR: https://git.openjdk.org/jdk/pull/27901 From prappo at openjdk.org Wed Oct 29 10:25:59 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 29 Oct 2025 10:25:59 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v4] In-Reply-To: References: Message-ID: > Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. > > Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. Pavel Rappo has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision: - Fix one more occurrence - Merge remote-tracking branch 'jdk/master' into 8370568 - Merge remote-tracking branch 'jdk/master' into 8370568 - Update copyright years Note: any commit hashes below might be outdated due to subsequent history rewriting (e.g. git rebase). + update make/langtools/tools/javacserver/server/CompilerThreadPool.java due to a10f8b4304d + update src/java.base/share/classes/java/lang/Object.java due to a10f8b4304d + update src/java.base/share/classes/java/net/DatagramSocket.java due to a6a23d6fdaf + update src/java.base/share/classes/java/net/ServerSocket.java due to a6a23d6fdaf + update src/java.base/share/classes/java/nio/channels/DatagramChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/FileChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/InterruptibleChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ReadableByteChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ScatteringByteChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/Selector.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java due to a10f8b4304d + update src/java.base/share/classes/java/nio/channels/SocketChannel.java due to a10f8b4304d + update src/java.base/share/classes/sun/nio/ch/Interruptible.java due to a10f8b4304d + update src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java due to a10f8b4304d + update src/java.desktop/share/classes/java/awt/Robot.java due to a10f8b4304d + update src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpChannel.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpMultiChannel.java due to a10f8b4304d + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpServerChannel.java due to a10f8b4304d + update test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/InterruptThread/intrpthrd001/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/newclass02/java.base/java/lang/Object.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP01/sp01t002/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP01/sp01t003/TestDescription.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllDiag.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinDiag.java due to a10f8b4304d + update test/hotspot/jtreg/vmTestbase/nsk/share/runner/MemDiag.java due to a10f8b4304d + update test/jdk/java/lang/Thread/JoinWithDuration.java due to a10f8b4304d + update test/jdk/java/lang/Thread/SleepWithDuration.java due to a10f8b4304d + update test/jdk/java/lang/Thread/virtual/CustomScheduler.java due to a6a23d6fdaf + update test/jdk/java/nio/channels/Channels/SocketChannelStreams.java due to a10f8b4304d + update test/jdk/java/nio/channels/FileChannel/CloseDuringTransfer.java due to a10f8b4304d + update test/jdk/java/nio/channels/FileChannel/ClosedByInterrupt.java due to a10f8b4304d + update test/jdk/java/nio/channels/Pipe/PipeInterrupt.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/LotsOfInterrupts.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/SelectWithConsumer.java due to a10f8b4304d + update test/jdk/java/nio/channels/Selector/WakeupAfterClose.java due to a10f8b4304d + update test/jdk/java/nio/channels/SocketChannel/AdaptorStreams.java due to a10f8b4304d + update test/jdk/java/nio/file/Files/CallWithInterruptSet.java due to a10f8b4304d + update test/jdk/java/nio/file/Files/InterruptCopy.java due to a10f8b4304d + update test/jdk/java/util/concurrent/CompletableFuture/LostInterrupt.java due to a10f8b4304d + update test/jdk/java/util/concurrent/CompletableFuture/SwallowedInterruptedException.java due to a10f8b4304d + update test/jdk/java/util/concurrent/ExecutorService/CloseTest.java due to a10f8b4304d + update test/jdk/java/util/concurrent/ExecutorService/InvokeTest.java due to a10f8b4304d + update test/jdk/java/util/zip/InterruptibleZip.java due to a10f8b4304d - Reword for clarity as suggested - Drop to ease upcoming merge from loom repo - Initial commit ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27972/files - new: https://git.openjdk.org/jdk/pull/27972/files/b3297337..32e4c36a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27972&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27972&range=02-03 Stats: 2165 lines in 89 files changed: 1112 ins; 785 del; 268 mod Patch: https://git.openjdk.org/jdk/pull/27972.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27972/head:pull/27972 PR: https://git.openjdk.org/jdk/pull/27972 From prappo at openjdk.org Wed Oct 29 10:26:00 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 29 Oct 2025 10:26:00 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v3] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 09:39:55 GMT, Jaikiran Pai wrote: > Hello Pavel, these changes look OK to me. > > Over time I think it will be harder to keep track or enforce this in code comments but I think it is easier to enforce for API specification text. Moving from "interrupted" to "interrupt" was a slow drift rather than a landslide. I think it's okay to repair it once. _Loom_ is already in and once _structured concurrency_ is in, I don't expect many new occurrences of "interrupt" in the foreseeable future. But you are right, the important bit is the specification, not the code comments. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27972#issuecomment-3460767516 From cushon at openjdk.org Wed Oct 29 10:27:07 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 10:27:07 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v5] In-Reply-To: References: Message-ID: > Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). Liam Miller-Cushon has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains six additional commits since the last revision: - Merge remote-tracking branch 'origin/master' into JDK-8370237 - Undo accidental update of examples.not-yet.txt - Update examples.not-yet.txt - Fix typo in test - Update another affected test - 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27901/files - new: https://git.openjdk.org/jdk/pull/27901/files/152ef5fa..a05973c6 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=03-04 Stats: 21830 lines in 532 files changed: 13148 ins; 5780 del; 2902 mod Patch: https://git.openjdk.org/jdk/pull/27901.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27901/head:pull/27901 PR: https://git.openjdk.org/jdk/pull/27901 From jpai at openjdk.org Wed Oct 29 10:29:34 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Wed, 29 Oct 2025 10:29:34 GMT Subject: RFR: 8370568: Refer to Thread.interrupted as "interrupted status" consistently [v4] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 10:25:59 GMT, Pavel Rappo wrote: >> Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. >> >> Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. > > Pavel Rappo has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision: > > - Fix one more occurrence > - Merge remote-tracking branch 'jdk/master' into 8370568 > - Merge remote-tracking branch 'jdk/master' into 8370568 > - Update copyright years > > Note: any commit hashes below might be outdated due to subsequent > history rewriting (e.g. git rebase). > > + update make/langtools/tools/javacserver/server/CompilerThreadPool.java due to a10f8b4304d > + update src/java.base/share/classes/java/lang/Object.java due to a10f8b4304d > + update src/java.base/share/classes/java/net/DatagramSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/net/ServerSocket.java due to a6a23d6fdaf > + update src/java.base/share/classes/java/nio/channels/DatagramChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/FileChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/InterruptibleChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ReadableByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ScatteringByteChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/Selector.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/ServerSocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/java/nio/channels/SocketChannel.java due to a10f8b4304d > + update src/java.base/share/classes/sun/nio/ch/Interruptible.java due to a10f8b4304d > + update src/java.base/share/classes/sun/security/ssl/StatusResponseManager.java due to a10f8b4304d > + update src/java.desktop/share/classes/java/awt/Robot.java due to a10f8b4304d > + update src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/DOMParserImpl.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpMultiChannel.java due to a10f8b4304d > + update src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpServerChannel.java due to a10f8b4304d > + update test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java due to a10f8b4304d > ... Marked as reviewed by jpai (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27972#pullrequestreview-3392609024 From abimpoudis at openjdk.org Wed Oct 29 11:46:10 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Wed, 29 Oct 2025 11:46:10 GMT Subject: RFR: 8366968: Exhaustive switch expression rejected by for not covering all possible values [v5] In-Reply-To: <7iuAdoO-2YYBbg6MjMHT5Ylkn5Ui6F4QrLW6P-_lrXM=.71e9fbc4-f9ed-47a5-a607-83731d466a85@github.com> References: <7iuAdoO-2YYBbg6MjMHT5Ylkn5Ui6F4QrLW6P-_lrXM=.71e9fbc4-f9ed-47a5-a607-83731d466a85@github.com> Message-ID: <0ifEBzgoPi3RxK-RtXaJZgYOpW5sEP3oDtuU3ulymo8=.75675840-0550-4057-9cd0-60cb2183e45e@github.com> On Fri, 24 Oct 2025 12:08:22 GMT, Jan Lahoda wrote: >> Consider case like (from the bug): >> >> class Demo { >> >> sealed interface Base permits Special, Value {} >> >> non-sealed interface Value extends Base {} >> >> sealed interface Special extends Base permits SpecialValue {} >> >> non-sealed interface SpecialValue extends Value, Special {} >> >> static int demo(final Base base) { >> return switch (base) { >> case final Value value -> 0; >> // Uncommenting the following line will make javac accept this program >> //case final Special value -> throw new AssertionError(); >> }; >> >> } >> >> } >> >> >> This fails to compile: >> >> /tmp/Demo.java:12: error: the switch expression does not cover all possible input values >> return switch (base) { >> ^ >> 1 error >> >> >> Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input. >> >> Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code: >> >> case final Value value -> 0; >> => >> case final SpecialValue value -> 0; >> >> $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java >> $ >> >> >> Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac). >> >> javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive. >> >> The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes. > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Reorganizing code, adding comments. Looks good! ------------- Marked as reviewed by abimpoudis (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27547#pullrequestreview-3392899901 From jlahoda at openjdk.org Wed Oct 29 13:51:31 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 29 Oct 2025 13:51:31 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v2] In-Reply-To: References: Message-ID: On Tue, 28 Oct 2025 12:46:30 GMT, Aggelos Biboudis wrote: >> PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). >> >> spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ > > Aggelos Biboudis has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains one new commit since the last revision: > > 8359145: JEP 530: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) I think the direction is good, there are some comments inline. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 5099: > 5097: } > 5098: } > 5099: // where Nit: Suggestion: src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4743: > 4741: boolean dominated = false; > 4742: > 4743: if (unconditionalCaseLabel == testCaseLabel) unconditionalFound = true; I think the code here is correct, but it is very hard to read (to me, at least). I wonder if there's a chance to try to tweak the code so that it is more readable. At least: do `{}` around `unconditionalFound`, and move the `dominatedCandidate` into the `if (!currentType.hasTag(ERROR) && !testType.hasTag(ERROR)) {`. I suspect it might be possible to replace `dominatedCandidate` with `continue` in `if (currentType.constValue() instanceof Number) {` (would need to `if (allowPrimitivePatterns && unconditionalFound && unconditionalCaseLabel != label) {` check upfront, so not sure if that would improve things). test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInAssignability.java line 93: > 91: } > 92: void assertOriginalAssignmentNarrowingAndUnconditionality() { > 93: // byte b = vs ExactConversionsSupport::isIntToByteExact If I understand it correctly, the updated and original isAssignable should give the same results, right? I think it would be better to have one invocation, like `assertOriginaAndUpdatedAssignable`, that would check that for the given input, both methods return the same value, and the expected value. Having to lists of cases is likely to lead to omissions/mistakes, I suspect. ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27637#pullrequestreview-3393466239 PR Review Comment: https://git.openjdk.org/jdk/pull/27637#discussion_r2473119289 PR Review Comment: https://git.openjdk.org/jdk/pull/27637#discussion_r2473182215 PR Review Comment: https://git.openjdk.org/jdk/pull/27637#discussion_r2473117111 From jlahoda at openjdk.org Wed Oct 29 13:57:29 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Wed, 29 Oct 2025 13:57:29 GMT Subject: RFR: 8370865: Incorrect parser error for compact source files and multi-variable declarations Message-ID: Consider code like: int f1, f2; void main() {} When javac's parser accepts `f1`, it sees `,`, but it won't parse this as top-level field declarations, failing with: /tmp/F.java:1: error: class, interface, annotation type, enum, record, method or field expected int f1, f2; ^ 1 error This PR changes the parser to also accept the `,` as the next token when parsing top-level fields. ------------- Commit messages: - 8370865: Incorrect parser error for compact source files and multi-variable declarations Changes: https://git.openjdk.org/jdk/pull/28044/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28044&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370865 Stats: 155 lines in 3 files changed: 153 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28044.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28044/head:pull/28044 PR: https://git.openjdk.org/jdk/pull/28044 From cushon at openjdk.org Wed Oct 29 14:17:13 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Wed, 29 Oct 2025 14:17:13 GMT Subject: RFR: 8370800: Downgrade cant.attach.type.annotations diagnostics to warnings [v3] In-Reply-To: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> References: <-ml93dDR1Xpnk6kMW1VVNP3vJQL0inYhS5QPAdlNukk=.3027b692-a069-43f3-8c0a-0216022ebea4@github.com> Message-ID: <_Pmfnuh7YT1oYG_mVTZXAuZ-dPIr1-m0YjKGMMI3-lg=.7cab1b2f-9385-4fa2-9141-02f748f30ab6@github.com> > Hi, please consider this fix for [JDK-8370800: Downgrade cant.attach.type.annotations diagnostics to warnings](https://bugs.openjdk.org/browse/JDK-8370800). > > As discussed in the, this reduces the compatibility impact of these diagnostics for builds that deliberately omit transitive annotation dependencies, for example if they are only referenced through javadoc `@link` tags, or by frameworks that conditionally load the classes. > > The PR changes the existing error diagnostic to an unconditional warning. Another alternative would be to make it an optional xlint diagnostic, perhaps as part of `-Xlint:classfile`, or as another category. Liam Miller-Cushon has updated the pull request incrementally with one additional commit since the last revision: Update examples.not-yet.txt ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28018/files - new: https://git.openjdk.org/jdk/pull/28018/files/0a6c9590..c65a7ac5 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28018&range=01-02 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28018.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28018/head:pull/28018 PR: https://git.openjdk.org/jdk/pull/28018 From prappo at openjdk.org Wed Oct 29 15:39:31 2025 From: prappo at openjdk.org (Pavel Rappo) Date: Wed, 29 Oct 2025 15:39:31 GMT Subject: Integrated: 8370568: Refer to Thread.interrupted as "interrupted status" consistently In-Reply-To: References: Message-ID: On Fri, 24 Oct 2025 09:45:38 GMT, Pavel Rappo wrote: > Throughout documentation and source code, the `Thread.interrupted` flag is referred to as either "interrupt**ed** status" or "interrupt status". It might be good to be consistent. > > Historically, it seems to have initially been "interrupted status". This is how the flag is called in `java.lang.Thread` and the "Java Concurrency in Practice" book. ("The Java Programming Language" calls it "interrupted **state**".) However, over the years "interrupt status" appeared in documentation and source code through networking and NIO classes. This pull request has now been integrated. Changeset: 28f2591b Author: Pavel Rappo URL: https://git.openjdk.org/jdk/commit/28f2591bad49c4d1590325c3d315d850ab6bcc7d Stats: 260 lines in 77 files changed: 4 ins; 0 del; 256 mod 8370568: Refer to Thread.interrupted as "interrupted status" consistently Reviewed-by: jpai, rriggs, alanb ------------- PR: https://git.openjdk.org/jdk/pull/27972 From cstein at openjdk.org Wed Oct 29 16:54:03 2025 From: cstein at openjdk.org (Christian Stein) Date: Wed, 29 Oct 2025 16:54:03 GMT Subject: RFR: 8370175: State engine terminates when throwing self-caused exception In-Reply-To: <9mjV8Kv0dt6Mh16Cyxq7EnOsZ-SCXJYTTgdMut-EOiw=.68036465-14c5-4428-8a25-821ef8dca4c1@github.com> References: <9mjV8Kv0dt6Mh16Cyxq7EnOsZ-SCXJYTTgdMut-EOiw=.68036465-14c5-4428-8a25-821ef8dca4c1@github.com> Message-ID: <0HzIP4xQsC1gqVYCgw-2KYYmqjhbLENeWuJaLB3Cn9U=.5569a94b-1dda-48fe-a6bf-eadc3a4375a2@github.com> On Wed, 29 Oct 2025 10:03:28 GMT, Pavel Rappo wrote: > As a reporter, thanks for taking care of this. Welcome, Pavel! > [...] > Btw, why doesn't JShell print suppressed exceptions? Seems helpful in try-with-resources blocks. Should be discussed in a dedicated JBS issue or thread on the appropriated mailing list. As `kulla-dev` is archived, please send a mail to [compiler-dev](https://mail.openjdk.org/mailman/listinfo/compiler-dev) instead. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28037#issuecomment-3462668945 From acobbs at openjdk.org Wed Oct 29 20:54:19 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 29 Oct 2025 20:54:19 GMT Subject: RFR: 8344159: Add lint warnings for unnecessary warning suppression In-Reply-To: <81JqWQPRbafWl22IItWNL52faigZS1l31SXsD9Zq1EE=.b6d84001-edd9-443a-8ca7-555a81ae6af0@github.com> References: <81JqWQPRbafWl22IItWNL52faigZS1l31SXsD9Zq1EE=.b6d84001-edd9-443a-8ca7-555a81ae6af0@github.com> Message-ID: <4Vtxklt1aGLbaZHO8bzuV1ZgR5YCmzvvQB1kdxxZvHw=.1ce1039c-d4df-4bd6-be04-c3c359b3de09@github.com> On Tue, 16 Sep 2025 13:32:15 GMT, Erik Joelsson wrote: >> This PR adds a new compiler warning for `@SuppressWarnings` annotations that don't actually suppress any warnings. >> >> Summary of code changes: >> >> * Add new warning and associated lint category `"suppression"` >> * Update `LintMapper` to keep track of which `@SuppressWarnings` suppressions have been validated ? >> * Update `Log.warning()` so it validates any current suppression of the warning's lint category in effect. >> * Add a new `validate` parameter to `Lint.isEnabled()` and `Lint.isSuppressed()` that specifies whether to also validate any current suppression. >> * Add `Lint.isActive()` to check whether a category is enabled _or_ suppression of the category is being tracked - in other words, whether the warning calculation needs to be performed. Used for non-trivial warning calculations. >> * Add `-Xlint:-suppression` flags to `*.gmk` build files so the build doesn't break >> >> ? The suppression of a lint category is "validated" as soon as it suppresses some warning in that category > >> /label remove kulla > > I have removed kulla-dev from the bot configuration so the stuck label is now benign. @erikj79, @magicus - Would you mind updating your review since the recent changes that addressed merge conflicts? Thanks! ------------- PR Comment: https://git.openjdk.org/jdk/pull/25167#issuecomment-3463955731 From erikj at openjdk.org Wed Oct 29 21:10:33 2025 From: erikj at openjdk.org (Erik Joelsson) Date: Wed, 29 Oct 2025 21:10:33 GMT Subject: RFR: 8344159: Add lint warnings for unnecessary warning suppression [v4] In-Reply-To: References: Message-ID: <3TYbuRwZvS0UJxfI1fFZN4HXZwbsX6fHFbkgndH6cNU=.adcd31f8-12c8-4087-be78-b679f6f9e275@github.com> On Wed, 22 Oct 2025 15:21:43 GMT, Archie Cobbs wrote: >> This PR adds a new compiler warning for `@SuppressWarnings` annotations that don't actually suppress any warnings. >> >> Summary of code changes: >> >> * Add new warning and associated lint category `"suppression"` >> * Update `LintMapper` to keep track of which `@SuppressWarnings` suppressions have been validated ? >> * Update `Log.warning()` so it validates any current suppression of the warning's lint category in effect. >> * Add a new `validate` parameter to `Lint.isEnabled()` and `Lint.isSuppressed()` that specifies whether to also validate any current suppression. >> * Add `Lint.isActive()` to check whether a category is enabled _or_ suppression of the category is being tracked - in other words, whether the warning calculation needs to be performed. Used for non-trivial warning calculations. >> * Add `-Xlint:-suppression` flags to `*.gmk` build files so the build doesn't break >> >> ? The suppression of a lint category is "validated" as soon as it suppresses some warning in that category > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 133 commits: > > - Merge branch 'master' into JDK-8344159 to fix conflict. > - Merge branch 'master' into JDK-8344159 to fix conflict. > - Merge branch 'master' into JDK-8344159 to fix conflicts. > - Add clarifying comment. > - Merge branch 'master' into JDK-8344159 > - Change inner class name to avoid shadowing superclass name. > - Add a couple of code clarification comments. > - Refactor test to avoid requiring changes to TestRunner. > - Remove unnecessary -Xlint:-suppression flags. > - Minor cleanups. > - ... and 123 more: https://git.openjdk.org/jdk/compare/a1be2979...f2b75547 Build changes still look good. ------------- Marked as reviewed by erikj (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/25167#pullrequestreview-3396264627 From vromero at openjdk.org Wed Oct 29 22:25:19 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 29 Oct 2025 22:25:19 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type Message-ID: Javac is throwing an OOME for the code like: class Test { interface WithMixin01 {} // ... // 20 interfaces here interface WithMixin20 {} interface ClientA extends WithMixin02, WithMixin01, WithMixin03, WithMixin04, WithMixin05, WithMixin06, WithMixin07, WithMixin08, WithMixin09, WithMixin10, WithMixin11, WithMixin12, WithMixin13, WithMixin14, WithMixin15, WithMixin16, WithMixin17, WithMixin18, WithMixin19, WithMixin20 { } interface ClientB extends WithMixin01, WithMixin02, WithMixin03, WithMixin04, WithMixin05, WithMixin06, WithMixin07, WithMixin08, WithMixin09, WithMixin10, WithMixin11, WithMixin12, WithMixin13, WithMixin14, WithMixin15, WithMixin16, WithMixin17, WithMixin18, WithMixin19, WithMixin20 { } public static void main(String... args) { ClientA a = null; ClientB b = null; String selector = "a"; Object o = switch (selector) { case "a" -> a; case "b" -> b; default -> null; }; } } the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. TIA ------------- Commit messages: - editing parameter name - 8369654: javac OutOfMemoryError for complex intersection type Changes: https://git.openjdk.org/jdk/pull/28050/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8369654 Stats: 140 lines in 3 files changed: 123 ins; 0 del; 17 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Wed Oct 29 22:34:58 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 29 Oct 2025 22:34:58 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v2] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: minor changes ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/fbb09774..3af5be4b Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=00-01 Stats: 13 lines in 1 file changed: 0 ins; 0 del; 13 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Wed Oct 29 22:35:00 2025 From: vromero at openjdk.org (Vicente Romero) Date: Wed, 29 Oct 2025 22:35:00 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v2] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 22:32:01 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > minor changes src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 4077: > 4075: List mec = null; > 4076: if (lubWillBeErased && !cl.isEmpty()) { > 4077: cl = List.of(cl.head); we don't need to deal with the whole list of types from here as it will be erased ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28050#discussion_r2475778300 From jlahoda at openjdk.org Thu Oct 30 07:11:12 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 30 Oct 2025 07:11:12 GMT Subject: Integrated: 8366968: Exhaustive switch expression rejected by for not covering all possible values In-Reply-To: References: Message-ID: On Mon, 29 Sep 2025 13:10:59 GMT, Jan Lahoda wrote: > Consider case like (from the bug): > > class Demo { > > sealed interface Base permits Special, Value {} > > non-sealed interface Value extends Base {} > > sealed interface Special extends Base permits SpecialValue {} > > non-sealed interface SpecialValue extends Value, Special {} > > static int demo(final Base base) { > return switch (base) { > case final Value value -> 0; > // Uncommenting the following line will make javac accept this program > //case final Special value -> throw new AssertionError(); > }; > > } > > } > > > This fails to compile: > > /tmp/Demo.java:12: error: the switch expression does not cover all possible input values > return switch (base) { > ^ > 1 error > > > Note there is no instance of `Special` that would not be an instance of `Value` as well. I.e. covering `Value` will catch all input. > > Also, note that if `case Value` is replaced with `case SpecialValue`, javac also compile the code: > > case final Value value -> 0; > => > case final SpecialValue value -> 0; > > $ ~/tools/jdk/jdk-25/bin/javac /tmp/Demo.java > $ > > > Which shows the problem: replacing a type with a super type should not cause the switch to stop to be exhaustive (i.e. the switch is exhaustive for `SpecialValue`, but replacing it with its super type `Value`, the switch is no longer exhaustive for javac). > > javac contains a piece of code that searches through subtypes to handle diamond class hierarchies like the one above. But, when it searches for subtypes, it does a search through permitted subtypes of the type. And since `Value` is not sealed, this search will not find `SpecialValue`, and javac won't see the switch to be exhaustive. > > The proposal herein is to broaden the search, and consider all transitive permitted subtypes of the selector type, and filter subtypes of the current type from this set (if the current type is abstract, if it is not abstract, we can't do the subtype search at all). This should, I think, include all relevant subtypes. This pull request has now been integrated. Changeset: 87a47721 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/87a47721981bb84b1e22b5b2d8d24bc60c8b7223 Stats: 164 lines in 2 files changed: 145 ins; 11 del; 8 mod 8366968: Exhaustive switch expression rejected by for not covering all possible values Reviewed-by: abimpoudis ------------- PR: https://git.openjdk.org/jdk/pull/27547 From aturbanov at openjdk.org Thu Oct 30 09:05:20 2025 From: aturbanov at openjdk.org (Andrey Turbanov) Date: Thu, 30 Oct 2025 09:05:20 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v2] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 22:34:58 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > minor changes src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 3854: > 3852: cl1.head.hasTag(CLASS) && cl2.head.hasTag(CLASS)) { > 3853: if (cl1.head.isParameterized() && cl2.head.isParameterized()) { > 3854: Type merge = merge(lubWillBeErased, cl1.head,cl2.head); Suggestion: Type merge = merge(lubWillBeErased, cl1.head, cl2.head); ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28050#discussion_r2476961771 From abimpoudis at openjdk.org Thu Oct 30 10:08:55 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Thu, 30 Oct 2025 10:08:55 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v3] In-Reply-To: References: Message-ID: > PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). > > spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ Aggelos Biboudis has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains three additional commits since the last revision: - Merge branch 'master' into JDK-8359145 # Conflicts: # src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java - Address review - 8359145: JEP 530: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27637/files - new: https://git.openjdk.org/jdk/pull/27637/files/f1448e1b..8a17c55a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=01-02 Stats: 36486 lines in 973 files changed: 21635 ins; 9436 del; 5415 mod Patch: https://git.openjdk.org/jdk/pull/27637.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27637/head:pull/27637 PR: https://git.openjdk.org/jdk/pull/27637 From jlahoda at openjdk.org Thu Oct 30 10:54:03 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 30 Oct 2025 10:54:03 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v2] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 22:34:58 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > minor changes I am not the expert on types, and leveraging the fact that we will erase the type later is clever. But, when I was trying to debug this, it seemed the reason is that we are repeatedly and recursively asking `lub(ClientB, ClientA)`, from different paths (e.g. from `WithMixin02, WithMixin01`, which will then ask the same question based on different mixins one level deeper in the recursion). Caching the results helps in this case[1], and I wonder if that could be a viable solution (i.e. is this mostly about the recursion?). I also tried `var v = java.util.List.of(a, b);` - that takes a long time as well, and without the cache, it takes a long time in `lub`. But the cache is not enough for that case, as with the cache, it still spends a lot of time elsewhere. [1] diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index 0c155caa56d..3da5c0703bd 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -3984,6 +3984,45 @@ public Type lub(List ts) { * does not exist return the type of null (bottom). */ public Type lub(Type... ts) { + TypeListKey key = new TypeListKey(this, ts); + Type result = lubCache.get(key); + + if (result == null) { + lubCache.put(key, result = computeLub(ts)); + } + + return result; + } + private record TypeListKey(Types thisTypes, Type... types) { + @Override + public int hashCode() { + int hashCode = 0; + for (Type t : types) { + hashCode = 127 * hashCode + thisTypes.hashCode(t); + } + return hashCode; + } + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TypeListKey other)) { + return false; + } + if (thisTypes != other.thisTypes) { + return false; + } + if (types.length != other.types.length) { + return false; + } + for (int i = 0; i < types.length; i++) { + if (!thisTypes.isSameType(types[i], other.types[i])) { + return false; + } + } + return true; + } + } + private Map lubCache = new HashMap<>(); + private Type computeLub(Type... ts) { final int UNKNOWN_BOUND = 0; final int ARRAY_BOUND = 1; final int CLASS_BOUND = 2; ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3467331832 From jlahoda at openjdk.org Thu Oct 30 11:35:31 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 30 Oct 2025 11:35:31 GMT Subject: RFR: 8364991: Incorrect not-exhaustive error [v8] In-Reply-To: References: Message-ID: > Consider this code: > > $ cat Test.java > package test; > public class Test { > private int test1(Root r) { > return switch (r) { > case Root(R2(R1 _), R2(R1 _)) -> 0; > case Root(R2(R1 _), R2(R2 _)) -> 0; > case Root(R2(R2 _), R2(R1 _)) -> 0; > case Root(R2(R2 _), R2 _) -> 0; > }; > } > sealed interface Base {} > record R1() implements Base {} > record R2(Base b1) implements Base {} > record Root(R2 b2, R2 b3) {} > } > > > javac (JDK 25) will produce a compile-time error for this code: > > $ javac test/Test.java > .../test/Test.java:4: error: the switch expression does not cover all possible input values > return switch (r) { > ^ > 1 error > > > This error is not correct according to the JLS. JLS defines a set of possible reductions of pattern sets, and if there exists a series of reductions from the pattern set into a pattern set that covers the selector type, the switch is exhaustive. > > One such reduction is that if there's a sub-set of (record) patterns that only differ in one component ("the mismatching component"), we can replace them with a (set of) patterns where this component is reduced, and the other components are unmodified. > > Such path exists here (every line shows a set of patterns that is being transformed): > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the second component as the mismatching component, then we can reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)) => Root(R2(R1 _), R2 _); as we can reduce R2(R1 _), R2(R2 _) to R2 _ > Root(R2(R1 _), R2 _), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => choosing the first component as the mismatching component, we can reduce Root(R2(R1 _), R2 _), Root(R2(R2 _), R2 _) => Root(R2 _, R2 _) > Root(R2 _, R2 _) > => > Root _ > => > exhaustive > > > The problem here is that in the first step, javac chooses this path: > > Root(R2(R1 _), R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2(R1 _)), Root(R2(R2 _), R2 _) > => reduce Root(R2(R1 _), R2(R1 _)), Root(R2(R2 _), R2(R1 _)) => Root(R2 _, R2(R1 _)) > Root(R2 _, R2(R1 _)), Root(R2(R1 _), R2(R2 _)), Root(R2(R2 _), R2 _) > => dead end, as there are no two patterns that would have the same nested pattern in the same component > > > If javac would do full backtracking, it could go back, and choose the other path, and find out the switch is exhaustive. But, full naive backtracking is, I think, prohibitively too slow for even relatively small swit... Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 15 commits: - Merge branch 'master' into JDK-8364991 - Merge branch 'master' into JDK-8364991 - Merge branch 'JDK-8367499-2' into JDK-8364991 - 8367499: Refactor exhaustiveness computation from Flow into a separate class - Avoiding the use of IdentityHashMap. - Caching isSubtype, as suggested. - Adding explanation to the replaces map. - Factoring out the 'substitutable' check, as suggested. - Adding tests with generic records. - Simplifying the code as suggested. - ... and 5 more: https://git.openjdk.org/jdk/compare/80fcfaf4...e6a3f0da ------------- Changes: https://git.openjdk.org/jdk/pull/27247/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27247&range=07 Stats: 299 lines in 2 files changed: 259 ins; 16 del; 24 mod Patch: https://git.openjdk.org/jdk/pull/27247.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27247/head:pull/27247 PR: https://git.openjdk.org/jdk/pull/27247 From abimpoudis at openjdk.org Thu Oct 30 12:50:14 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Thu, 30 Oct 2025 12:50:14 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v4] In-Reply-To: References: Message-ID: > PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). > > spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ Aggelos Biboudis has updated the pull request incrementally with one additional commit since the last revision: Fix regression in Check ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27637/files - new: https://git.openjdk.org/jdk/pull/27637/files/8a17c55a..abe53647 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27637&range=02-03 Stats: 14 lines in 1 file changed: 4 ins; 4 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/27637.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27637/head:pull/27637 PR: https://git.openjdk.org/jdk/pull/27637 From vromero at openjdk.org Thu Oct 30 12:57:09 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 30 Oct 2025 12:57:09 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v3] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: Update src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Co-authored-by: Andrey Turbanov ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/3af5be4b..c6b19b2f Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=01-02 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From mcimadamore at openjdk.org Thu Oct 30 13:45:31 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Thu, 30 Oct 2025 13:45:31 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v2] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 22:30:22 GMT, Vicente Romero wrote: >> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: >> >> minor changes > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 4077: > >> 4075: List mec = null; >> 4076: if (lubWillBeErased && !cl.isEmpty()) { >> 4077: cl = List.of(cl.head); > > we don't need to deal with the whole list of types from here as it will be erased This seems a bit unsound because we're just picking the first erased supertype. Maybe it's ok because all closures are sorted by subtyping (so all supertypes come _after_ subtypes). Another possible approach would be not to bother with lub, and to have a simpler routine in Code that: * obtains all the erased supers of both types * "minimize" them, to find the smallest set of common erased supertypes * pick randomly one element in the minimized set (because lub is a bit of an overkill is then we're going to erase the result anyway). Perhaps it would be good to write both versions, and then decide on which one seems minimally invasive. Of course it's a tricky trade off -- on the one hand by doubling down on lub, we can reuse some of the machinery there, but we also pull in more than we should. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28050#discussion_r2478170340 From abimpoudis at openjdk.org Thu Oct 30 16:45:51 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Thu, 30 Oct 2025 16:45:51 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v2] In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 13:48:04 GMT, Jan Lahoda wrote: >> Aggelos Biboudis has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains one new commit since the last revision: >> >> 8359145: JEP 530: Implement Primitive Types in Patterns, instanceof, and switch (Fourth Preview) > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4743: > >> 4741: boolean dominated = false; >> 4742: >> 4743: if (unconditionalCaseLabel == testCaseLabel) unconditionalFound = true; > > I think the code here is correct, but it is very hard to read (to me, at least). I wonder if there's a chance to try to tweak the code so that it is more readable. > > At least: do `{}` around `unconditionalFound`, and move the `dominatedCandidate` into the `if (!currentType.hasTag(ERROR) && !testType.hasTag(ERROR)) {`. I suspect it might be possible to replace `dominatedCandidate` with `continue` in `if (currentType.constValue() instanceof Number) {` (would need to `if (allowPrimitivePatterns && unconditionalFound && unconditionalCaseLabel != label) {` check upfront, so not sure if that would improve things). I simplified the code (abstained from using `continue`). Do you still think it is necessary? > test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInAssignability.java line 93: > >> 91: } >> 92: void assertOriginalAssignmentNarrowingAndUnconditionality() { >> 93: // byte b = vs ExactConversionsSupport::isIntToByteExact > > If I understand it correctly, the updated and original isAssignable should give the same results, right? I think it would be better to have one invocation, like `assertOriginaAndUpdatedAssignable`, that would check that for the given input, both methods return the same value, and the expected value. Having to lists of cases is likely to lead to omissions/mistakes, I suspect. Addressed! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27637#discussion_r2478811104 PR Review Comment: https://git.openjdk.org/jdk/pull/27637#discussion_r2478812442 From abimpoudis at openjdk.org Thu Oct 30 16:45:55 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Thu, 30 Oct 2025 16:45:55 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v4] In-Reply-To: References: Message-ID: <_qw7Y4M5qZJn9-oIES_aUWMH0B3A-37Jzhd4qQgncto=.4fd227da-3352-42df-b2ad-10b6dde44597@github.com> On Thu, 30 Oct 2025 12:50:14 GMT, Aggelos Biboudis wrote: >> PR for Primitive Types in Patterns, instanceof, and switch (Fourth Preview). >> >> spec: https://cr.openjdk.org/~abimpoudis/instanceof/latest/ > > Aggelos Biboudis has updated the pull request incrementally with one additional commit since the last revision: > > Fix regression in Check src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4752: > 4750: if (types.isUnconditionallyExactCombined(currentType, testType) && > 4751: label instanceof JCConstantCaseLabel) { > 4752: dominated = !(testCaseLabel instanceof JCConstantCaseLabel) && Note that I turned `|=` into `=` @lahodaj ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27637#discussion_r2478807035 From jlahoda at openjdk.org Thu Oct 30 16:56:04 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Thu, 30 Oct 2025 16:56:04 GMT Subject: RFR: 8366196: Crash in AbstractMethodCheck.getMethodCheckFailure Message-ID: `AttrRecover` invokes `Attr.checkMethod` with a cached `CheckContext`. `checkMethod` may be calling `report` on the `CheckContext`: https://github.com/openjdk/jdk/blob/ed36b9bb6f3d429db6accfb3b096e50e7f2217ff/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L4986 This fails if the cached `CheckContext` is a `MethodCheckContext`, whose `report` method throws. The proposal herein is to not delegate to the cached `CheckContext`'s `report` method, but rather always report the error using `Check.basicHandler`. ------------- Commit messages: - 8366196: Crash in AbstractMethodCheck.getMethodCheckFailure Changes: https://git.openjdk.org/jdk/pull/28066/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28066&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8366196 Stats: 66 lines in 2 files changed: 64 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28066.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28066/head:pull/28066 PR: https://git.openjdk.org/jdk/pull/28066 From alanb at openjdk.org Thu Oct 30 18:48:23 2025 From: alanb at openjdk.org (Alan Bateman) Date: Thu, 30 Oct 2025 18:48:23 GMT Subject: RFR: 8366178: Implement JEP 526: Lazy Constants (Second Preview) [v20] In-Reply-To: References: Message-ID: On Fri, 24 Oct 2025 09:01:10 GMT, Per Minborg wrote: >> Implement JEP 526: Lazy Constants (Second Preview) >> >> The lazy list/map implementations are broken out from `ImmutableCollections` to a separate class. >> >> The old benchmarks are not moved/renamed to allow comparison with previous releases. >> >> `java.util.Optional` is updated so that its field is annotated with `@Stable`. This is to allow `Optional` instances to be held in lazy constants and still provide constant folding. > > Per Minborg has updated the pull request incrementally with one additional commit since the last revision: > > Rework toString implementations src/java.base/share/classes/java/util/List.java line 1200: > 1198: > 1199: /** > 1200: * {@return a new lazily computed list with the provided {@code size}} A minor comment here is that "of the given size" might be a bit clearer than "with the provided size". src/java.base/share/classes/java/util/List.java line 1240: > 1238: * function used to compute elements only so long as there are uncomputed elements > 1239: * after which the computing function is not strongly referenced > 1240: * anymore and may be collected. I think it's okay to say that the computing function is kept strongly reachable until at least all elements have been computed. I'm less sure about the second part being normative text and wonder if it would be better to move that part to an implNote. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2479172995 PR Review Comment: https://git.openjdk.org/jdk/pull/27605#discussion_r2479168408 From vromero at openjdk.org Thu Oct 30 19:07:05 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 30 Oct 2025 19:07:05 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v3] In-Reply-To: References: Message-ID: <28d4YDH459p-hCV1LNKkSjHt4NxVI9KzU4M9KmkXJO8=.004204f8-5092-45f2-8dbc-18e575e1b963@github.com> On Thu, 30 Oct 2025 12:57:09 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > Update src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > > Co-authored-by: Andrey Turbanov > I am not the expert on types, and leveraging the fact that we will erase the type later is clever. > > But, when I was trying to debug this, it seemed the reason is that we are repeatedly and recursively asking `lub(ClientB, ClientA)`, from different paths (e.g. from `WithMixin02, WithMixin01`, which will then ask the same question based on different mixins one level deeper in the recursion). Caching the results helps in this case[1], and I wonder if that could be a viable solution (i.e. is this mostly about the recursion?). > > I also tried `var v = java.util.List.of(a, b);` - that takes a long time as well, and without the cache, it takes a long time in `lub`. But the cache is not enough for that case, as with the cache, it still spends a lot of time elsewhere. > > [1] > > ```diff > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > index 0c155caa56d..3da5c0703bd 100644 > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > @@ -3984,6 +3984,45 @@ public Type lub(List ts) { > * does not exist return the type of null (bottom). > */ > public Type lub(Type... ts) { > + TypeListKey key = new TypeListKey(this, ts); > + Type result = lubCache.get(key); > + > + if (result == null) { > + lubCache.put(key, result = computeLub(ts)); > + } > + > + return result; > + } > + private record TypeListKey(Types thisTypes, Type... types) { > + @Override > + public int hashCode() { > + int hashCode = 0; > + for (Type t : types) { > + hashCode = 127 * hashCode + thisTypes.hashCode(t); > + } > + return hashCode; > + } > + @Override > + public boolean equals(Object obj) { > + if (!(obj instanceof TypeListKey other)) { > + return false; > + } > + if (thisTypes != other.thisTypes) { > + return false; > + } > + if (types.length != other.types.length) { > + return false; > + } > + for (int i = 0; i < types.length; i++) { > + if (!thisTypes.isSameType(types[i], other.types[i])) { > + return false; > + } > + } > + return true; > + } > + } > + private Map lubCache = new HashMap<>(); > + private Type computeLub(Type... ts) { > final int UNKNOWN_BOUND = 0; > final int ARRAY_BOUND = 1; > final int CLASS_BOUND = 2; > ``` correct, that's the reason, but in general I don't think that you can cache the lub results based on the input. As the output will depend not only on the input. See the cache already existing for the Types::merge method. That method is invoked by Types::lub and it itself invokes lub or not. So if merge finds that it itself called lub for the current input, then it will refrain to call lub again for the same input as this would be a deadlock. So depending on what is on this merge cache the output of lub could change for the same input ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3469647906 From vromero at openjdk.org Thu Oct 30 19:49:30 2025 From: vromero at openjdk.org (Vicente Romero) Date: Thu, 30 Oct 2025 19:49:30 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v3] In-Reply-To: References: Message-ID: On Thu, 30 Oct 2025 12:57:09 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > Update src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java > > Co-authored-by: Andrey Turbanov some data points to have an idea of the number of times we are invoking lub for the test case included in the description above. Assuming that we run it with different definitions of ClientA and ClientB changing the number of super types so for `# of SuperTypes == 1` we would have: interface ClientA extends WithMixin01 {} interface ClientB extends WithMixin01 {} for 2 supertypes we would have: interface ClientA extends WithMixin01, WithMixin02 {} interface ClientB extends WithMixin01, WithMixin02 {} and so on. I got the table below: | # of SuperTypes | # of Lub Invocations | |---|---| | 1| 1 | 2 | 5 | 3 | 16 | 4 | 65 | 5 | 326 | 6 | 1957 | 7 | 13700 | 8 | 109601 | 9 | 986410 | 10 | which is exponential on `# of SuperTypes` and steeper that `e^x` for `# of SuperTypes` > 3 ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3469791849 From cushon at openjdk.org Thu Oct 30 21:56:27 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Thu, 30 Oct 2025 21:56:27 GMT Subject: RFR: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations [v6] In-Reply-To: References: Message-ID: > Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). Liam Miller-Cushon has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains seven additional commits since the last revision: - Merge branch 'openjdk:master' into JDK-8370237 - Merge remote-tracking branch 'origin/master' into JDK-8370237 - Undo accidental update of examples.not-yet.txt - Update examples.not-yet.txt - Fix typo in test - Update another affected test - 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27901/files - new: https://git.openjdk.org/jdk/pull/27901/files/a05973c6..7236dd54 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27901&range=04-05 Stats: 36100 lines in 228 files changed: 17971 ins; 16637 del; 1492 mod Patch: https://git.openjdk.org/jdk/pull/27901.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/27901/head:pull/27901 PR: https://git.openjdk.org/jdk/pull/27901 From pavel.rappo at gmail.com Thu Oct 30 22:06:31 2025 From: pavel.rappo at gmail.com (Pavel Rappo) Date: Thu, 30 Oct 2025 22:06:31 +0000 Subject: Print suppressed exceptions in JShell Message-ID: Is there any reason why JShell does not print out suppressed exceptions? I think it would be good to print them. jshell> new Throwable() $1 ==> java.lang.Throwable jshell> new Error() $2 ==> java.lang.Error jshell> $1.addSuppressed($2) jshell> throw $1 | Exception java.lang.Throwable | at (#1:1) -Pavel From chen.l.liang at oracle.com Thu Oct 30 23:35:26 2025 From: chen.l.liang at oracle.com (Chen Liang) Date: Thu, 30 Oct 2025 23:35:26 +0000 Subject: Print suppressed exceptions in JShell In-Reply-To: References: Message-ID: I think it is probably just an oversight. This seems to be printed by JShellTool::displayEvalException, which shouldn't be too hard to add printing for suppressed exceptions. -Chen Confidential ? Oracle Internal ________________________________ From: compiler-dev on behalf of Pavel Rappo Sent: Thursday, October 30, 2025 5:06 PM To: compiler-dev at openjdk.org Subject: Print suppressed exceptions in JShell Is there any reason why JShell does not print out suppressed exceptions? I think it would be good to print them. jshell> new Throwable() $1 ==> java.lang.Throwable jshell> new Error() $2 ==> java.lang.Error jshell> $1.addSuppressed($2) jshell> throw $1 | Exception java.lang.Throwable | at (#1:1) -Pavel -------------- next part -------------- An HTML attachment was scrubbed... URL: From chen.l.liang at oracle.com Thu Oct 30 23:41:24 2025 From: chen.l.liang at oracle.com (Chen Liang) Date: Thu, 30 Oct 2025 23:41:24 +0000 Subject: Print suppressed exceptions in JShell In-Reply-To: References: Message-ID: On a second look, this is a bit more complex - the exception has to be transported. So UserException does not handle suppressed exceptions at all; ExecutionControlForwarder, LocalExecutionControl, StreamingExecutionControl all need to update for suppressed exception handling. In particular, changing the forwarder's protocol might be a bit risky; I wonder if we want to dig into this. ________________________________ From: compiler-dev on behalf of Chen Liang Sent: Thursday, October 30, 2025 6:35 PM To: Pavel Rappo ; compiler-dev at openjdk.org Subject: Re: Print suppressed exceptions in JShell I think it is probably just an oversight. This seems to be printed by JShellTool::displayEvalException, which shouldn't be too hard to add printing for suppressed exceptions. -Chen Confidential ? Oracle Internal ________________________________ From: compiler-dev on behalf of Pavel Rappo Sent: Thursday, October 30, 2025 5:06 PM To: compiler-dev at openjdk.org Subject: Print suppressed exceptions in JShell Is there any reason why JShell does not print out suppressed exceptions? I think it would be good to print them. jshell> new Throwable() $1 ==> java.lang.Throwable jshell> new Error() $2 ==> java.lang.Error jshell> $1.addSuppressed($2) jshell> throw $1 | Exception java.lang.Throwable | at (#1:1) -Pavel -------------- next part -------------- An HTML attachment was scrubbed... URL: From vromero at openjdk.org Fri Oct 31 03:52:57 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 03:52:57 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v4] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with four additional commits since the last revision: - another fix - minor fixes - addressing review comments - experiments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/c6b19b2f..e893d095 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=02-03 Stats: 42 lines in 3 files changed: 7 ins; 14 del; 21 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Fri Oct 31 04:17:53 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 04:17:53 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v5] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: another change ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/e893d095..10acd428 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=03-04 Stats: 7 lines in 1 file changed: 6 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Fri Oct 31 05:14:45 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 05:14:45 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v6] In-Reply-To: References: Message-ID: <8LPKsH5J8pL0jZeKUIizm25Hbigxy0DzyKvq828xG5A=.d7a78414-b680-474e-9c46-ecfa5323c418@github.com> > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: missing supertype ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/10acd428..2fba3e7e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=04-05 Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Fri Oct 31 05:45:02 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 05:45:02 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v6] In-Reply-To: <8LPKsH5J8pL0jZeKUIizm25Hbigxy0DzyKvq828xG5A=.d7a78414-b680-474e-9c46-ecfa5323c418@github.com> References: <8LPKsH5J8pL0jZeKUIizm25Hbigxy0DzyKvq828xG5A=.d7a78414-b680-474e-9c46-ecfa5323c418@github.com> Message-ID: <6ajTzGFyHSCW3sS9MkLM4N_53CRMe4JRqJ-syyzEo4E=.4ac7b227-11a4-4374-96fb-3dd35fe9bb09@github.com> On Fri, 31 Oct 2025 05:14:45 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > missing supertype Note for reviewers: I think that the current solution is incomplete and still incorrect. We need something more complex for the case when both types are non primitive arrays ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3471421512 From cushon at openjdk.org Fri Oct 31 09:55:23 2025 From: cushon at openjdk.org (Liam Miller-Cushon) Date: Fri, 31 Oct 2025 09:55:23 GMT Subject: Integrated: 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations In-Reply-To: References: Message-ID: On Mon, 20 Oct 2025 14:36:17 GMT, Liam Miller-Cushon wrote: > Hi, please consider this fix for a crash with `-Xdoclint` and type annotations. It is a generalization of a previous fix for [JDK-8266082](https://bugs.openjdk.org/browse/JDK-8266082). This pull request has now been integrated. Changeset: 8e3620a3 Author: Liam Miller-Cushon URL: https://git.openjdk.org/jdk/commit/8e3620a344f83a21191bb70cf2af24e9ae1952ce Stats: 33 lines in 4 files changed: 28 ins; 0 del; 5 mod 8370237: AssertionError in Annotate.fromAnnotations with -Xdoclint and type annotations Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/27901 From mcimadamore at openjdk.org Fri Oct 31 10:10:07 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 31 Oct 2025 10:10:07 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v4] In-Reply-To: References: Message-ID: On Thu, 23 Oct 2025 15:19:16 GMT, Jan Lahoda wrote: >> Consider a JShell interaction like: >> >> jshell> class O { class I {} } >> | created class O >> >> jshell> var i = new O().new I(); >> i ==> O$I at 77caeb3e >> >> jshell> class O { static class I {} } >> Exception in thread "main" java.lang.ClassFormatError: class not in class file format >> at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) >> at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) >> at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) >> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) >> at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) >> at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) >> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) >> at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) >> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) >> at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) >> at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) >> at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) >> at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) >> at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) >> at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) >> at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) >> at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) >> at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) >> ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing CheckExamples Thanks for adding the warning -- javac code looks good. ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27665#pullrequestreview-3403478831 From mcimadamore at openjdk.org Fri Oct 31 10:57:14 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 31 Oct 2025 10:57:14 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v6] In-Reply-To: <6ajTzGFyHSCW3sS9MkLM4N_53CRMe4JRqJ-syyzEo4E=.4ac7b227-11a4-4374-96fb-3dd35fe9bb09@github.com> References: <8LPKsH5J8pL0jZeKUIizm25Hbigxy0DzyKvq828xG5A=.d7a78414-b680-474e-9c46-ecfa5323c418@github.com> <6ajTzGFyHSCW3sS9MkLM4N_53CRMe4JRqJ-syyzEo4E=.4ac7b227-11a4-4374-96fb-3dd35fe9bb09@github.com> Message-ID: <1rwcDj2-5VjlymajucdKn_mtIG9jw9UYz_JV5d0FASY=.317984fc-ddc8-4df9-b79f-dbf4bc5c6f0f@github.com> On Fri, 31 Oct 2025 05:42:15 GMT, Vicente Romero wrote: > Note for reviewers: I think that the current solution is incomplete and still incorrect. We need something more complex for the case when both types are non primitive arrays Also, for context -- yesterday @vicente-romero-oracle and I explored a possible solution that doesn't need go through lub -- after all here we're after finding a common erased supertype between the two types under test. While finding common erased super types is a part of lub (see JLS), lub also does a lot more stuff. In principle the code we need might be as simple as: List ec = intersect(erasedSupertypes(t1), erasedSupertypes(t2)); return ec.head But this simple solution seems to have issues, so additional investigation is required. @lahodaj am I correct in assuming that the types to be merged in Code are always either class types or array types? E.g. no type variables, intersection types, or other "weird" stuff? ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3472502969 From vromero at openjdk.org Fri Oct 31 14:31:57 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 14:31:57 GMT Subject: RFR: 8370865: Incorrect parser error for compact source files and multi-variable declarations In-Reply-To: References: Message-ID: <_7kxCQmBAusMSqfUEMs8F1pAVFK15pkdG-tKvJfnors=.8472faa9-73ce-4998-96aa-d35f1083593f@github.com> On Wed, 29 Oct 2025 13:51:09 GMT, Jan Lahoda wrote: > Consider code like: > > int f1, f2; > void main() {} > > > When javac's parser accepts `f1`, it sees `,`, but it won't parse this as top-level field declarations, failing with: > > /tmp/F.java:1: error: class, interface, annotation type, enum, record, method or field expected > int f1, f2; > ^ > 1 error > > > This PR changes the parser to also accept the `,` as the next token when parsing top-level fields. lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28044#pullrequestreview-3404569563 From asotona at openjdk.org Fri Oct 31 15:12:42 2025 From: asotona at openjdk.org (Adam Sotona) Date: Fri, 31 Oct 2025 15:12:42 GMT Subject: RFR: 8340840: jshell ClassFormatError when making inner class static [v4] In-Reply-To: References: Message-ID: On Thu, 23 Oct 2025 15:19:16 GMT, Jan Lahoda wrote: >> Consider a JShell interaction like: >> >> jshell> class O { class I {} } >> | created class O >> >> jshell> var i = new O().new I(); >> i ==> O$I at 77caeb3e >> >> jshell> class O { static class I {} } >> Exception in thread "main" java.lang.ClassFormatError: class not in class file format >> at jdk.jdi/com.sun.tools.jdi.VirtualMachineImpl.redefineClasses(VirtualMachineImpl.java:396) >> at jdk.jshell/jdk.jshell.execution.JdiExecutionControl.redefine(JdiExecutionControl.java:90) >> at jdk.jshell/jdk.jshell.Unit.doRedefines(Unit.java:312) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$27(Eval.java:1120) >> at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178) >> at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:722) >> at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) >> at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) >> at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) >> at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) >> at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) >> at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) >> at jdk.jshell/jdk.jshell.Eval.lambda$compileAndLoad$29(Eval.java:1121) >> at jdk.jshell/jdk.jshell.TaskFactory.lambda$runTask$4(TaskFactory.java:213) >> at jdk.compiler/com.sun.tools.javac.api.JavacTaskPool.getTask(JavacTaskPool.java:193) >> at jdk.jshell/jdk.jshell.TaskFactory.runTask(TaskFactory.java:206) >> at jdk.jshell/jdk.jshell.TaskFactory.compile(TaskFactory.java:186) >> at jdk.jshell/jdk.jshell.Eval.compileAndLoad(Eval.java:1100) >> at jdk.jshell/jdk.jshell.Eval.declare(Eval.java:901) >> at jdk.jshell/jdk.jshell.Eval.eval(Eval.java:140) >> at jdk.jshell/jdk.jshell.JShell.eval(JShell.java:513) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSource(JShellTool.java:3633) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processSourceCatchingReset(JShellTool.java:1353) >> at jdk.jshell/jdk.internal.jshell.tool.JShellTool.processInput(JShellTool.java:1251) >> ... > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Fixing CheckExamples Marked as reviewed by asotona (Reviewer). ------------- PR Review: https://git.openjdk.org/jdk/pull/27665#pullrequestreview-3404736517 From jlahoda at openjdk.org Fri Oct 31 16:55:38 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 31 Oct 2025 16:55:38 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v6] In-Reply-To: <8LPKsH5J8pL0jZeKUIizm25Hbigxy0DzyKvq828xG5A=.d7a78414-b680-474e-9c46-ecfa5323c418@github.com> References: <8LPKsH5J8pL0jZeKUIizm25Hbigxy0DzyKvq828xG5A=.d7a78414-b680-474e-9c46-ecfa5323c418@github.com> Message-ID: On Fri, 31 Oct 2025 05:14:45 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > missing supertype Yes, I think the types here should not be weird (even primitive types are probably handled by the `isSubtype` before going to `lub`). If needed, the types could be passed through erasure, to be sure. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3473992227 From vromero at openjdk.org Fri Oct 31 17:28:48 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 17:28:48 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v7] In-Reply-To: References: Message-ID: <2oL1AgEvZ2vfSsU2BNhSJelot7Cr6oKQTX8Tq8Epm8M=.0cbcc824-014e-4675-8548-42a69b71f951@github.com> > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: adding more array support ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/2fba3e7e..cff29576 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=05-06 Stats: 73 lines in 3 files changed: 38 ins; 5 del; 30 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Fri Oct 31 17:28:49 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 17:28:49 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v7] In-Reply-To: <2oL1AgEvZ2vfSsU2BNhSJelot7Cr6oKQTX8Tq8Epm8M=.0cbcc824-014e-4675-8548-42a69b71f951@github.com> References: <2oL1AgEvZ2vfSsU2BNhSJelot7Cr6oKQTX8Tq8Epm8M=.0cbcc824-014e-4675-8548-42a69b71f951@github.com> Message-ID: On Fri, 31 Oct 2025 17:24:54 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > adding more array support src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 4094: > 4092: } > 4093: > 4094: public List erasedSupertypes(Type t) { no code changes just made it public plus indentation change src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 4107: > 4105: > 4106: private Type arraySuperType; > 4107: public Type arraySuperType() { no code changes just made it public plus indentation change src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java line 1847: > 1845: } > 1846: > 1847: private Type allArray(Type... ts) { this code has been extracted from lub so there will be some duplicity here ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28050#discussion_r2482183876 PR Review Comment: https://git.openjdk.org/jdk/pull/28050#discussion_r2482184228 PR Review Comment: https://git.openjdk.org/jdk/pull/28050#discussion_r2482186344 From vromero at openjdk.org Fri Oct 31 17:32:03 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 17:32:03 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v7] In-Reply-To: <2oL1AgEvZ2vfSsU2BNhSJelot7Cr6oKQTX8Tq8Epm8M=.0cbcc824-014e-4675-8548-42a69b71f951@github.com> References: <2oL1AgEvZ2vfSsU2BNhSJelot7Cr6oKQTX8Tq8Epm8M=.0cbcc824-014e-4675-8548-42a69b71f951@github.com> Message-ID: <1HAlt7hNBd_fY6k-MFujkHh1Af-JOZfKz9AGdQn7H6Q=.83644814-1bb1-4143-8097-c7865008f5af@github.com> On Fri, 31 Oct 2025 17:28:48 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > adding more array support I have updated the PR improving the array support, basically the previous approach was arriving to a wrong supertype for the case of two reference arrays. There is now some code that is common to a portion of lub which we could probably extract to a common method in Types and just reuse it in Code but not without some massage anyways that could slow the general lub a bit so probably not worthy as lub is a very established code that I don't think will change in the near future. Thanks for all the comments so far ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3474119310 From mcimadamore at openjdk.org Fri Oct 31 17:57:12 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Fri, 31 Oct 2025 17:57:12 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v7] In-Reply-To: <2oL1AgEvZ2vfSsU2BNhSJelot7Cr6oKQTX8Tq8Epm8M=.0cbcc824-014e-4675-8548-42a69b71f951@github.com> References: <2oL1AgEvZ2vfSsU2BNhSJelot7Cr6oKQTX8Tq8Epm8M=.0cbcc824-014e-4675-8548-42a69b71f951@github.com> Message-ID: On Fri, 31 Oct 2025 17:28:48 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > adding more array support src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java line 1869: > 1867: > 1868: private List getErasedSuperTypes(Type t) { > 1869: if (t.hasTag(TYPEVAR)) { this can use Types.skipTypeVars? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28050#discussion_r2482263098 From vromero at openjdk.org Fri Oct 31 19:00:28 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 19:00:28 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v8] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: simplifying code ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/cff29576..dd862d62 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=06-07 Stats: 51 lines in 1 file changed: 11 ins; 29 del; 11 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Fri Oct 31 19:30:41 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 19:30:41 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v9] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: delta changes ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/dd862d62..d78558eb Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=07-08 Stats: 13 lines in 1 file changed: 3 ins; 2 del; 8 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Fri Oct 31 19:48:54 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 19:48:54 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v10] In-Reply-To: References: Message-ID: <_7mDQDHicBjwPftsOlWqBq0KIuGff9GzMR-upKJx8_c=.363687ca-e059-419e-8a51-52d6fae0af0b@github.com> > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: adding some doc ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/d78558eb..bd0bfa6a Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=09 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=08-09 Stats: 7 lines in 1 file changed: 7 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Fri Oct 31 21:49:23 2025 From: vromero at openjdk.org (Vicente Romero) Date: Fri, 31 Oct 2025 21:49:23 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v11] In-Reply-To: References: Message-ID: > Javac is throwing an OOME for the code like: > > class Test { > interface WithMixin01 {} > // ... > // 20 interfaces here > interface WithMixin20 {} > > interface ClientA extends > WithMixin02, > WithMixin01, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > interface ClientB extends > WithMixin01, > WithMixin02, > WithMixin03, > WithMixin04, > WithMixin05, > WithMixin06, > WithMixin07, > WithMixin08, > WithMixin09, > WithMixin10, > WithMixin11, > WithMixin12, > WithMixin13, > WithMixin14, > WithMixin15, > WithMixin16, > WithMixin17, > WithMixin18, > WithMixin19, > WithMixin20 { > } > > public static void main(String... args) { > ClientA a = null; > ClientB b = null; > String selector = "a"; > Object o = switch (selector) { > case "a" -> a; > case "b" -> b; > default -> null; > }; > } > } > > the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very slooooow. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: fixing comment ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/bd0bfa6a..e5bfcfd1 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=10 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=09-10 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28050.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28050/head:pull/28050 PR: https://git.openjdk.org/jdk/pull/28050 From liach at openjdk.org Fri Oct 31 23:22:01 2025 From: liach at openjdk.org (Chen Liang) Date: Fri, 31 Oct 2025 23:22:01 GMT Subject: RFR: 8366196: Crash in AbstractMethodCheck.getMethodCheckFailure In-Reply-To: References: Message-ID: On Thu, 30 Oct 2025 16:47:56 GMT, Jan Lahoda wrote: > `AttrRecover` invokes `Attr.checkMethod` with a cached `CheckContext`. `checkMethod` may be calling `report` on the `CheckContext`: > https://github.com/openjdk/jdk/blob/ed36b9bb6f3d429db6accfb3b096e50e7f2217ff/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java#L4986 > > This fails if the cached `CheckContext` is a `MethodCheckContext`, whose `report` method throws. > > The proposal herein is to not delegate to the cached `CheckContext`'s `report` method, but rather always report the error using `Check.basicHandler`. Looks okay ------------- Marked as reviewed by liach (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28066#pullrequestreview-3406555210 From liach at openjdk.org Fri Oct 31 23:37:04 2025 From: liach at openjdk.org (Chen Liang) Date: Fri, 31 Oct 2025 23:37:04 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v11] In-Reply-To: References: Message-ID: On Fri, 31 Oct 2025 21:49:23 GMT, Vicente Romero wrote: >> Javac is throwing an OOME for the code like: >> >> class Test { >> interface WithMixin01 {} >> // ... >> // 20 interfaces here >> interface WithMixin20 {} >> >> interface ClientA extends >> WithMixin02, >> WithMixin01, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> interface ClientB extends >> WithMixin01, >> WithMixin02, >> WithMixin03, >> WithMixin04, >> WithMixin05, >> WithMixin06, >> WithMixin07, >> WithMixin08, >> WithMixin09, >> WithMixin10, >> WithMixin11, >> WithMixin12, >> WithMixin13, >> WithMixin14, >> WithMixin15, >> WithMixin16, >> WithMixin17, >> WithMixin18, >> WithMixin19, >> WithMixin20 { >> } >> >> public static void main(String... args) { >> ClientA a = null; >> ClientB b = null; >> String selector = "a"; >> Object o = switch (selector) { >> case "a" -> a; >> case "b" -> b; >> default -> null; >> }; >> } >> } >> >> the reason is that after [JDK-8353565](https://bugs.openjdk.org/browse/JDK-8353565) we are using Types::lub when joining jump chains in Code. The result of the lub will be erased anyways so the proposal here is to cut in the result given by lub types that will be erased anyways. The reason for the slow lub invocation here is that in order to obtain the lub in this case, the lub method is invoked several times. Each invocation, minus the first one, with very complex types which makes them very ... > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > fixing comment This iteration is much cleaner and more sensible than the initial version. ------------- Marked as reviewed by liach (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28050#pullrequestreview-3406587439