From vromero at openjdk.org Sat Nov 1 12:25:47 2025 From: vromero at openjdk.org (Vicente Romero) Date: Sat, 1 Nov 2025 12:25:47 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v12] 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 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 16 additional commits since the last revision: - Merge branch 'master' into JDK-8369654 - fixing comment - adding some doc - delta changes - simplifying code - adding more array support - missing supertype - another change - another fix - minor fixes - ... and 6 more: https://git.openjdk.org/jdk/compare/bc6df8bb...34e2d9d4 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28050/files - new: https://git.openjdk.org/jdk/pull/28050/files/e5bfcfd1..34e2d9d4 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=11 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28050&range=10-11 Stats: 44514 lines in 404 files changed: 23137 ins; 18965 del; 2412 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 Sun Nov 2 02:19:19 2025 From: vromero at openjdk.org (Vicente Romero) Date: Sun, 2 Nov 2025 02:19:19 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Message-ID: javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. This new visitor will compare types looking for exactness which is something desirable in a map key. TIA ------------- Commit messages: - 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Changes: https://git.openjdk.org/jdk/pull/28101/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8337142 Stats: 96 lines in 2 files changed: 90 ins; 0 del; 6 mod Patch: https://git.openjdk.org/jdk/pull/28101.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28101/head:pull/28101 PR: https://git.openjdk.org/jdk/pull/28101 From mcimadamore at openjdk.org Mon Nov 3 10:06:23 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 10:06:23 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 good! ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28066#pullrequestreview-3410277978 From mcimadamore at openjdk.org Mon Nov 3 10:07:33 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 10:07:33 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v12] In-Reply-To: References: Message-ID: On Sat, 1 Nov 2025 12:25:47 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 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 16 additional commits since the last revision: > > - Merge branch 'master' into JDK-8369654 > - fixing comment > - adding some doc > - delta changes > - simplifying code > - adding more array support > - missing supertype > - another change > - another fix > - minor fixes > - ... and 6 more: https://git.openjdk.org/jdk/compare/fc64c841...34e2d9d4 Very good -- thanks! ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28050#pullrequestreview-3410285240 From mcimadamore at openjdk.org Mon Nov 3 11:05:05 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:05:05 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> On Sun, 2 Nov 2025 02:12:40 GMT, Vicente Romero wrote: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3479961463 From mcimadamore at openjdk.org Mon Nov 3 11:20:03 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:20:03 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> References: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> Message-ID: On Mon, 3 Nov 2025 11:02:41 GMT, Maurizio Cimadamore wrote: > Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? This seems to fix the SOE -- but it introduces some spurious errors in the build... maybe worth more investigation? E.g. it almost seems as if javac kind of relies on cycles not to be detected... ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480014278 From amaembo at gmail.com Mon Nov 3 11:32:47 2025 From: amaembo at gmail.com (Tagir Valeev) Date: Mon, 3 Nov 2025 12:32:47 +0100 Subject: Type-use annotation on var lambda parameter Message-ID: Hello! I stumbled on the following issue. Let's consider this Java file: package com.example; import java.lang.annotation.Retention; import java.lang.annotation.Target; import java.util.function.Function; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Retention(value=RUNTIME) @Target(value={TYPE_USE}) @interface Anno { } public class TestClass { public static void main(String[] args) { Function f = (@Anno var val ) -> Integer.toHexString(val); System.out.println(f.apply(10)); } } As you can see, there's a TYPE_USE annotation which is applied to the lambda parameter declared with 'var' keyword. If I understand JLS 9.7.4 [1] correctly, this should not be legal: > If the annotation appears before a void method declaration or a variable declaration that uses var (?14.4, ?15.27.1), then there is no closest type. If the annotation's interface is deemed to apply only to the type which is closest to the annotation, a compile-time error occurs. However, javac accepts this code. I tried different versions between Java 11 and Java 25, and the result is the same: the file is compiled successfully. However, the TestClass.class file contains no references to the Anno annotation at all, despite it having the RUNTIME retention. So it looks like the annotation is silently ignored. One thing that confuses me is that the Eclipse compiler (ecj-4.34.jar) also accepts this code. However, it generates a RuntimeVisibleTypeAnnotations attribute for the Anno annotation. So either both compilers accept this code incorrectly, or my understanding of the specification is wrong. Could you please take a look at the javac issue? I'd be happy to be corrected if I misunderstood the specification. Thank you in advance! Tagir Valeev [1] https://docs.oracle.com/javase/specs/jls/se25/html/jls-9.html#jls-9.7.4 -------------- next part -------------- An HTML attachment was scrubbed... URL: From jlahoda at openjdk.org Mon Nov 3 11:44:12 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 11:44:12 GMT Subject: Integrated: 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`. This pull request has now been integrated. Changeset: 15fd5292 Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/15fd52925ab64a6a9e33691eed9e952a7b75da4b Stats: 66 lines in 2 files changed: 64 ins; 0 del; 2 mod 8366196: Crash in AbstractMethodCheck.getMethodCheckFailure Reviewed-by: liach, mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/28066 From mcimadamore at openjdk.org Mon Nov 3 11:47:02 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:47:02 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> Message-ID: On Mon, 3 Nov 2025 11:17:32 GMT, Maurizio Cimadamore wrote: > > Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? > > This seems to fix the SOE -- but it introduces some spurious errors in the build... maybe worth more investigation? E.g. it almost seems as if javac kind of relies on cycles not to be detected... Nah... it seems to me that `containsTypeRecursive` never sees the same type pair twice in a nested context. We keep adding newer type to the type cache, but it seems like the program is running away here... ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480108251 From mcimadamore at openjdk.org Mon Nov 3 11:50:01 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 11:50:01 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: <9K1ROatwdZUPPEA3TutMLsxam69WX-_y9HpFIjZfvbk=.7802fef6-b1ec-47c5-80da-83aae4b29ae9@github.com> Message-ID: On Mon, 3 Nov 2025 11:44:08 GMT, Maurizio Cimadamore wrote: > > > Question: what if containsTypeEquivalent is defined in terms of containsTypeRecursive? Won't the cache then prevent the SOE? > > > > > > This seems to fix the SOE -- but it introduces some spurious errors in the build... maybe worth more investigation? E.g. it almost seems as if javac kind of relies on cycles not to be detected... > > Nah... it seems to me that `containsTypeRecursive` never sees the same type pair twice in a nested context. We keep adding newer type to the type cache, but it seems like the program is running away here... Your analysis in this PR seems to imply that the cycle occurs via TypePair::equals, but when debugging I don't see this method being invoked at all (I do see the hashCode method being invoked though). I think we need to characterize the nature of the recursion more precisely. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480123502 From jlahoda at openjdk.org Mon Nov 3 12:06:30 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 12:06:30 GMT Subject: Integrated: 8370865: Incorrect parser error for compact source files and multi-variable declarations In-Reply-To: References: Message-ID: 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. This pull request has now been integrated. Changeset: abf4f3da Author: Jan Lahoda URL: https://git.openjdk.org/jdk/commit/abf4f3da76f413406de2860e4fbfacccfa15c221 Stats: 155 lines in 3 files changed: 153 ins; 0 del; 2 mod 8370865: Incorrect parser error for compact source files and multi-variable declarations Reviewed-by: vromero ------------- PR: https://git.openjdk.org/jdk/pull/28044 From mcimadamore at openjdk.org Mon Nov 3 13:09:45 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 13:09:45 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: On Sun, 2 Nov 2025 02:12:40 GMT, Vicente Romero wrote: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA I did some more analysis. It seems like inference completes correctly. But at the last step we end up with a very complex type (for the type variable in List::of): M&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>,? extends java.lang.Object&Nine&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six&Thirteen&Eleven&Thirteen&Eleven&Thirte en>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six>> (!!) In the very last step of inference we have to check if this is a subtype of Object (the upper bound of the tvar). And this crashes javac, because subtyping needs to capture and capture triggers a glb involving this huge type which then consumes the stack. Eventually this computation ends up in `containsTypeRecursive` with these two types: T = Test.Ten&Test.Thirteen&Test.Eleven&Test.Thirteen>&Test.Thirteen>> S = Test.Ten&Test.Thirteen> At which point we keep looping forever because, to check if we have already seen this type pair, we need to perform (as you said), a nested containment check which brings us back here. So, we never decide whether we can add the type pair to the cache or not... So, your fix seems to be correct -- we need a simpler way to structurally compares two types w/o calling back into containment. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 1350: > 1348: */ > 1349: SameTypeVisitor isSameTypeVisitor = new SameTypeVisitor(); > 1350: class SameTypeVisitor extends TypeRelation { I suggest to maybe make this an abstract class (with 2 abstract methods), then define `isSameTypeVisitor` as before, as an anonymous instance of our new abstract class, then define another equality visitor instance for type pair. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3480424235 PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2486430939 From vromero at openjdk.org Mon Nov 3 14:56:30 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 14:56:30 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: Message-ID: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: addressing review comments ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28101/files - new: https://git.openjdk.org/jdk/pull/28101/files/21fab4d0..ef427b38 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=00-01 Stats: 20 lines in 1 file changed: 11 ins; 5 del; 4 mod Patch: https://git.openjdk.org/jdk/pull/28101.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28101/head:pull/28101 PR: https://git.openjdk.org/jdk/pull/28101 From vromero at openjdk.org Mon Nov 3 14:56:32 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 14:56:32 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 13:06:49 GMT, Maurizio Cimadamore wrote: >> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: >> >> addressing review comments > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 1350: > >> 1348: */ >> 1349: SameTypeVisitor isSameTypeVisitor = new SameTypeVisitor(); >> 1350: class SameTypeVisitor extends TypeRelation { > > I suggest to maybe make this an abstract class (with 2 abstract methods), then define `isSameTypeVisitor` as before, as an anonymous instance of our new abstract class, then define another equality visitor instance for type pair. I updated the PR with this suggestion, thanks ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2486766423 From jlahoda at openjdk.org Mon Nov 3 14:51:36 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 14:51:36 GMT Subject: RFR: 8359145: Implement JEP 530: Primitive Types in Patterns, instanceof, and switch (Fourth Preview) [v4] In-Reply-To: References: Message-ID: 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 Looks OK to me. ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27637#pullrequestreview-3411387946 From jlahoda at openjdk.org Mon Nov 3 15:10:49 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 15:10:49 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] 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 23 commits: - Merge branch 'JDK-8364991' into JDK-8367530 - 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. - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 ------------- Changes: https://git.openjdk.org/jdk/pull/27256/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=27256&range=03 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 mcimadamore at openjdk.org Mon Nov 3 16:01:45 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 16:01:45 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> References: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> Message-ID: On Mon, 3 Nov 2025 14:56:30 GMT, Vicente Romero wrote: >> javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: >> >> - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType >> - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop >> >> The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. >> >> This new visitor will compare types looking for exactness which is something desirable in a map key. >> >> TIA > > Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: > > addressing review comments src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 3901: > 3899: boolean sameTypeArguments(List ts, List ss) { > 3900: while (ts.nonEmpty() && ss.nonEmpty() > 3901: && exactTypeVisitor.visit(ts.head, ss.head)) { You could delegate to `sameTypeComparator` here? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2487001792 From mcimadamore at openjdk.org Mon Nov 3 16:06:59 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 3 Nov 2025 16:06:59 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> Message-ID: On Mon, 3 Nov 2025 15:58:51 GMT, Maurizio Cimadamore wrote: >> Vicente Romero has updated the pull request incrementally with one additional commit since the last revision: >> >> addressing review comments > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 3901: > >> 3899: boolean sameTypeArguments(List ts, List ss) { >> 3900: while (ts.nonEmpty() && ss.nonEmpty() >> 3901: && exactTypeVisitor.visit(ts.head, ss.head)) { > > You could delegate to `sameTypeComparator` here? Another possibility would be to declare an overloaded method to `isSameType` that takes a type argument comparator function. And maybe the default type argument comparator function is `containsTypeEquivalent` but then other clients could override that. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2487016381 From jlahoda at openjdk.org Mon Nov 3 16:19:27 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 16:19:27 GMT Subject: RFR: 8370334: javadoc NPE with "import module" statement [v2] In-Reply-To: References: 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. Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Don't eagerly complete the unnamed module. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/27974/files - new: https://git.openjdk.org/jdk/pull/27974/files/ff2162ee..14ac910e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=27974&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=27974&range=00-01 Stats: 4 lines in 1 file changed: 3 ins; 0 del; 1 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 jlahoda at openjdk.org Mon Nov 3 17:06:36 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 3 Nov 2025 17:06:36 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain In-Reply-To: References: Message-ID: On Thu, 4 Sep 2025 15:22:57 GMT, Archie Cobbs wrote: > 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]`. I think overall seems sensible - some questions/nits inline. make/jdk/src/classes/build/tools/intpoly/FieldGen.java line 631: > 629: + (params.getBitsPerLimb() - 1) + ";"); > 630: if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) { > 631: result.appendLine("@SuppressWarnings(\"lossy-conversions\")"); Do you know what is the specific problematic code generated here? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4055: > 4053: int maximumShift; > 4054: switch (((OperatorSymbol)operator).opcode) { > 4055: case ByteCodes.ishl: Nit: use "modernized" switch - multiple case labels and `->`? test/langtools/tools/javac/lint/ShiftOutOfRange.java line 14: > 12: > 13: // These should generate warnings > 14: a = a << (byte)-1; Looking at the patch, I am not completely convinced disallowing `-1` is beneficial. On one hand, it looks weird. On the other hand, it makes some sense (as far as I can tell, it is universal for both `int` and `long`). And, unlike `128`, it is not clearly wrong. I am not sure if it wouldn't be better to simply permit `-1` as a special case. I see there are `<< -5` in the microbenchmark tests, but I think I am less inclined to accommodate negative values other than `-1`, as the semantics of those is much more cryptic, for me at least. Please let me know what you think. ------------- PR Review: https://git.openjdk.org/jdk/pull/27102#pullrequestreview-3411950069 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487162366 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487161036 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487176078 From pavel.rappo at gmail.com Mon Nov 3 17:41:11 2025 From: pavel.rappo at gmail.com (Pavel Rappo) Date: Mon, 3 Nov 2025 17:41:11 +0000 Subject: Print suppressed exceptions in JShell In-Reply-To: References: Message-ID: >From the user?s perspective, it would be helpful to see suppressed exceptions. Even though it?s unusual to use try-with-resources (TWR) in hand-written JShell snippets, some methods _programmatically_ add suppressed exceptions to the exception they throw, so TWR isn?t required to see them. On Thu, Oct 30, 2025 at 11:41?PM Chen Liang wrote: > > 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 From rgiulietti at openjdk.org Mon Nov 3 18:12:13 2025 From: rgiulietti at openjdk.org (Raffaello Giulietti) Date: Mon, 3 Nov 2025 18:12:13 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 16:47:56 GMT, Jan Lahoda wrote: >> 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]`. > > test/langtools/tools/javac/lint/ShiftOutOfRange.java line 14: > >> 12: >> 13: // These should generate warnings >> 14: a = a << (byte)-1; > > Looking at the patch, I am not completely convinced disallowing `-1` is beneficial. On one hand, it looks weird. On the other hand, it makes some sense (as far as I can tell, it is universal for both `int` and `long`). And, unlike `128`, it is not clearly wrong. I am not sure if it wouldn't be better to simply permit `-1` as a special case. > > I see there are `<< -5` in the microbenchmark tests, but I think I am less inclined to accommodate negative values other than `-1`, as the semantics of those is much more cryptic, for me at least. > > Please let me know what you think. One way to read `v << -n` is: "Shift out everything to the left, except for the `n` least significant bits". Analogously for `v >>> -n`: "Shift out everything to the right, except for the `n` most significant bits". To rotate `v` by `n` bits to the left, for example, one can write `v << n | v >>> -n` (regardless of the width of `v`) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487416183 From vromero at openjdk.org Mon Nov 3 18:28:43 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:28:43 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v3] In-Reply-To: References: Message-ID: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA Vicente Romero 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: - addressing review comments - Merge branch 'master' into JDK-8337142 - addressing review comments - 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28101/files - new: https://git.openjdk.org/jdk/pull/28101/files/ef427b38..da012a78 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28101&range=01-02 Stats: 7938 lines in 155 files changed: 4711 ins; 1856 del; 1371 mod Patch: https://git.openjdk.org/jdk/pull/28101.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28101/head:pull/28101 PR: https://git.openjdk.org/jdk/pull/28101 From vromero at openjdk.org Mon Nov 3 18:28:45 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:28:45 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v2] In-Reply-To: References: <3vyz4FHRvN1mJZm5wCNEtPYdczimn-ghxuoK3YxlT64=.ffa6608e-a725-4210-94d8-c6cd5693cdb2@github.com> Message-ID: On Mon, 3 Nov 2025 16:02:43 GMT, Maurizio Cimadamore wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java line 3901: >> >>> 3899: boolean sameTypeArguments(List ts, List ss) { >>> 3900: while (ts.nonEmpty() && ss.nonEmpty() >>> 3901: && exactTypeVisitor.visit(ts.head, ss.head)) { >> >> You could delegate to `sameTypeComparator` here? > > Another possibility would be to declare an overloaded method to `isSameType` that takes a type argument comparator function. And maybe the default type argument comparator function is `containsTypeEquivalent` but then other clients could override that. I went for the first option. There is a public version of `containsTypeEquivalent` that takes two lists as arguments. For the second variant I think we would need to add the lambda to that method. We can add another version of that method but I think the first option is cleaner ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28101#discussion_r2487453067 From vromero at openjdk.org Mon Nov 3 18:35:02 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:35:02 GMT Subject: Integrated: 8369654: javac OutOfMemoryError for complex intersection type In-Reply-To: References: Message-ID: On Wed, 29 Oct 2025 22:16:25 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 slooooow. > > TIA This pull request has now been integrated. Changeset: 9f972008 Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/9f972008ff2beb4b69855f4c42b8a664a6b8bc95 Stats: 161 lines in 3 files changed: 147 ins; 2 del; 12 mod 8369654: javac OutOfMemoryError for complex intersection type Reviewed-by: liach, mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/28050 From vromero at openjdk.org Mon Nov 3 18:35:01 2025 From: vromero at openjdk.org (Vicente Romero) Date: Mon, 3 Nov 2025 18:35:01 GMT Subject: RFR: 8369654: javac OutOfMemoryError for complex intersection type [v12] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 10:04:33 GMT, Maurizio Cimadamore wrote: > Very good -- thanks! thanks for the suggestions! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28050#issuecomment-3481938493 From acobbs at openjdk.org Mon Nov 3 18:36:33 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:36:33 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: 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]`. Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: - Merge branch 'master' into JDK-5038439 to fix conflict. - Address review comment (combine switch cases). - 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=01 Stats: 181 lines in 13 files changed: 173 ins; 0 del; 8 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 acobbs at openjdk.org Mon Nov 3 18:36:35 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:36:35 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: <0D_jgs9w47rAKwt5Udla_7C1bfb7Moc14-Fr4RsTq64=.27341088-069f-4208-817e-7391e1348a54@github.com> On Mon, 3 Nov 2025 16:44:13 GMT, Jan Lahoda wrote: >> Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: >> >> - Merge branch 'master' into JDK-5038439 to fix conflict. >> - Address review comment (combine switch cases). >> - 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. > > make/jdk/src/classes/build/tools/intpoly/FieldGen.java line 631: > >> 629: + (params.getBitsPerLimb() - 1) + ";"); >> 630: if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) { >> 631: result.appendLine("@SuppressWarnings(\"lossy-conversions\")"); > > Do you know what is the specific problematic code generated here? Actually this goes away after merging int the latest master. It was fixed independently by JDK-8368301. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 4055: > >> 4053: int maximumShift; >> 4054: switch (((OperatorSymbol)operator).opcode) { >> 4055: case ByteCodes.ishl: > > Nit: use "modernized" switch - multiple case labels and `->`? We can combined the labels, but since we're setting _two_ values we can't use the `->` syntax. Fixed in 8044632727d. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487476213 PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487476095 From acobbs at openjdk.org Mon Nov 3 18:36:37 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:36:37 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 18:09:01 GMT, Raffaello Giulietti wrote: >> test/langtools/tools/javac/lint/ShiftOutOfRange.java line 14: >> >>> 12: >>> 13: // These should generate warnings >>> 14: a = a << (byte)-1; >> >> Looking at the patch, I am not completely convinced disallowing `-1` is beneficial. On one hand, it looks weird. On the other hand, it makes some sense (as far as I can tell, it is universal for both `int` and `long`). And, unlike `128`, it is not clearly wrong. I am not sure if it wouldn't be better to simply permit `-1` as a special case. >> >> I see there are `<< -5` in the microbenchmark tests, but I think I am less inclined to accommodate negative values other than `-1`, as the semantics of those is much more cryptic, for me at least. >> >> Please let me know what you think. > > One way to read `v << -n` is: "Shift out everything to the left, except for the `n` least significant bits". > Analogously for `v >>> -n`: "Shift out everything to the right, except for the `n` most significant bits". > > To rotate `v` by `n` bits to the left, for example, one can write `v << n | v >>> -n` (regardless of the width of `v`) Hmm, obviously this is a judgement call and I'm curious what others think. My opinion is that I still think there should be a warning for shifts of -1. I mean, maybe to a _real_ hacker, then of course `foo << -1` makes perfect sense because it's just stating the "obvious" which is "shift the low order bit into the high order position and set all the other bits to zero", right?? :) I just don't think the average Java programmer automatically understands that. Yes, it's an idiom or "handy trick", but if hasn't attained the status of being universally recognized then it doesn't deserve a special exception. On the other hand, excluding -1 from the warning would be less disruptive (at least, to the real hackers out there), and that has its own merits. So I don't have a super strong opinion about it. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487476314 From hgreule at openjdk.org Mon Nov 3 18:36:39 2025 From: hgreule at openjdk.org (Hannes Greule) Date: Mon, 3 Nov 2025 18:36:39 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: <05yTbGH4d3Remac9l0EN0P6Li94CmDTyXvalkwb5vhI=.1a640f2e-df85-4add-88a9-e6613cfe3f4c@github.com> On Mon, 3 Nov 2025 18:32:57 GMT, Archie Cobbs wrote: >> 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]`. > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: > > - Merge branch 'master' into JDK-5038439 to fix conflict. > - Address review comment (combine switch cases). > - 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. test/langtools/tools/javac/lint/ShiftOutOfRange.java line 18: > 16: a = a >>> (short)-1; > 17: a <<= -1; > 18: a >>= -1L; // also generates "implicit cast from long to int in compound assignment is possibly lossy" I'm a bit surprised by the additional warning here. The shift still operates on int, not long; i.e., unary promotion is performed for each argument rather than binary promotion https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.19 Should this be fixed (separately, obviously)? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487472103 From acobbs at openjdk.org Mon Nov 3 18:56:27 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 3 Nov 2025 18:56:27 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: <05yTbGH4d3Remac9l0EN0P6Li94CmDTyXvalkwb5vhI=.1a640f2e-df85-4add-88a9-e6613cfe3f4c@github.com> References: <05yTbGH4d3Remac9l0EN0P6Li94CmDTyXvalkwb5vhI=.1a640f2e-df85-4add-88a9-e6613cfe3f4c@github.com> Message-ID: On Mon, 3 Nov 2025 18:30:22 GMT, Hannes Greule wrote: >> Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits: >> >> - Merge branch 'master' into JDK-5038439 to fix conflict. >> - Address review comment (combine switch cases). >> - 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. > > test/langtools/tools/javac/lint/ShiftOutOfRange.java line 18: > >> 16: a = a >>> (short)-1; >> 17: a <<= -1; >> 18: a >>= -1L; // also generates "implicit cast from long to int in compound assignment is possibly lossy" > > I'm a bit surprised by the additional warning here. The shift still operates on int, not long; i.e., unary promotion is performed for each argument rather than binary promotion https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.19 > > Should this be fixed (separately, obviously)? I agree, this is a separate compiler glitch. I've created [JDK-8371162](https://bugs.openjdk.org/browse/JDK-8371162). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487531814 From rriggs at openjdk.org Mon Nov 3 19:15:13 2025 From: rriggs at openjdk.org (Roger Riggs) Date: Mon, 3 Nov 2025 19:15:13 GMT Subject: RFR: 5038439: Warning message for literal shift amounts outside the canonical domain [v2] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 18:31:54 GMT, Archie Cobbs wrote: >> One way to read `v << -n` is: "Shift out everything to the left, except for the `n` least significant bits". >> Analogously for `v >>> -n`: "Shift out everything to the right, except for the `n` most significant bits". >> >> To rotate `v` by `n` bits to the left, for example, one can write `v << n | v >>> -n` (regardless of the width of `v`) > > Hmm, obviously this is a judgement call and I'm curious what others think. > > My opinion is that I still think there should be a warning for shifts of -1. > > I mean, maybe to a _real_ hacker, then of course `foo << -1` makes perfect sense because it's just stating the "obvious" which is "shift the low order bit into the high order position and set all the other bits to zero", right?? :) > > I just don't think the average Java programmer automatically understands that. > > Yes, it's an idiom or "handy trick", but if hasn't attained the status of being universally recognized then it doesn't deserve a special exception. > > On the other hand, excluding -1 from the warning would be less disruptive (at least, to the real hackers out there), and that has its own merits. So I don't have a super strong opinion about it. This might be worth a corpus scan to see how common it is to shift by -1 or other constants, either int or long. Someone, might interpret `v << -1` as a right shift, is it more likely to misinterpret it as using more than 5/6 bits of the shift or considering it signed. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27102#discussion_r2487576716 From vyazici at openjdk.org Tue Nov 4 09:00:17 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Tue, 4 Nov 2025 09:00:17 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" Message-ID: Document usage and purpose of `ct.properties`. ------------- Commit messages: - Document `ct.properties` Changes: https://git.openjdk.org/jdk/pull/28123/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28123&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8371133 Stats: 9 lines in 1 file changed: 8 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28123.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28123/head:pull/28123 PR: https://git.openjdk.org/jdk/pull/28123 From jlahoda at openjdk.org Tue Nov 4 10:21:28 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 10:21:28 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 08:46:50 GMT, Volkan Yazici wrote: > Document usage and purpose of `ct.properties`. src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties line 26: > 24: # > 25: > 26: # This file is used by `com.sun.tools.javac.file.JRTIndex` to generate How about phrasing like this (`JRTIndex` uses the data defined here, but does not generate the `.java` file - parts of the build system do): # This file was originally used to produce the `proprietary` warning when # accessing non-APIs, and to hide some non-APIs in JDK <= 8. This has been # superseded by the module system and `--release`. But, when compiling with # `--source 8`, it is still used for this purpose by `com.sun.tools.javac.file.JRTIndex`. # # The build generates `jdk.compiler/com/sun/tools/javac/resources/ct.java` from # this file, which is then used at runtime. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28123#discussion_r2489747244 From jpai at openjdk.org Tue Nov 4 10:42:29 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Tue, 4 Nov 2025 10:42:29 GMT Subject: RFR: 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier Message-ID: Can I please get a review of this change which cleans up the outdated enum constants in the internal `jdk.internal.javac.PreviewFeature$Feature` enum? This addresses https://bugs.openjdk.org/browse/JDK-8365699. As noted in that issue, this enum has accumulated some outdated preview feature constants which are no longer needed. The changes in this PR removes those enum constants whose preview features have been finalized in Java 25 or earlier (the current mainline bootstrap JDK is Java 25). A code comment explaining the lifetime of these enum constants has also been added. No new tests have been introduced and tier1, tier2, tier3 testing is currently in progress in the CI. ------------- Commit messages: - 8365699: Remove jdk.internal.javac.PreviewFeature.Feature enum values for features finalized in Java 25 or earlier Changes: https://git.openjdk.org/jdk/pull/28128/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28128&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8365699 Stats: 23 lines in 1 file changed: 15 ins; 6 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28128.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28128/head:pull/28128 PR: https://git.openjdk.org/jdk/pull/28128 From jlahoda at openjdk.org Tue Nov 4 10:59:11 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 10:59:11 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v2] In-Reply-To: References: Message-ID: On Tue, 23 Sep 2025 17:19:23 GMT, Archie Cobbs wrote: >> The compiler generates a warning if you declare a `close()` method that throws any supertype of `InterruptedException` in a class or interface extending `AutoCloseable`. This is because suppressed `InterruptedException`'s are likely to lead to misbehavior at runtime. >> >> However, this feature also generates a warning due to `AutoCloseable.close()` itself, if you simply inherit it. For example: >> >> $ cat MyClass.java >> public interface MyClass extends AutoCloseable { >> } >> $ javac -Xlint:try MyClass.java >> MyClass.java:1: warning: [try] auto-closeable resource MyClass has a member method close() that could throw InterruptedException >> public interface MyClass extends AutoCloseable { >> ^ >> 1 warning >> >> The warning is not useful because `AutoCloseable.close()` is abstract and so it's going to be some other class' job to deal with the throws clause. >> >> This change prevents `AutoCloseable.close()` itself from triggering the warning in a class declaration. We preserve the existing behavior in which a warning is generated at the use site (i.e., at the try-with-resources statement). > > Archie Cobbs 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 two additional commits since the last revision: > > - Merge branch 'master' into JDK-8155591 to get recent build fixes. > - Don't warn about AutoCloseable.close() itself throwing InterruptedException. Makes sense to me. I think it would be useful if the tests would be enhanced to cover the case where the `close` method declaration in non-AutoClo does actually `Exception`/`InterruptedException`. I found `InterruptedExceptionTest.java`, but as that's a combo test, it is harder to see a sensible warning is produced on a sensible place. Regarding sensible place, it would be possible to produce a warning specifically at the problematic `close` method (if it is declared in the given class, and not inherited) using `TreeInfo.diagnosticPositionFor`, but it is not so easy in this case - among other things, the warning would probably need a different wording. Up to you. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3485318048 From vyazici at openjdk.org Tue Nov 4 12:18:34 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Tue, 4 Nov 2025 12:18:34 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" [v2] In-Reply-To: References: Message-ID: > Document usage and purpose of `ct.properties`. Volkan Yazici has updated the pull request incrementally with one additional commit since the last revision: Apply review feedback ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28123/files - new: https://git.openjdk.org/jdk/pull/28123/files/9edb525a..476a98d3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28123&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28123&range=00-01 Stats: 8 lines in 1 file changed: 4 ins; 3 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/28123.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28123/head:pull/28123 PR: https://git.openjdk.org/jdk/pull/28123 From vyazici at openjdk.org Tue Nov 4 12:18:36 2025 From: vyazici at openjdk.org (Volkan Yazici) Date: Tue, 4 Nov 2025 12:18:36 GMT Subject: RFR: 8371133: Clarify the purpose of "src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties" [v2] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:18:57 GMT, Jan Lahoda wrote: >> Volkan Yazici has updated the pull request incrementally with one additional commit since the last revision: >> >> Apply review feedback > > src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties line 26: > >> 24: # >> 25: >> 26: # This file is used by `com.sun.tools.javac.file.JRTIndex` to generate > > How about phrasing like this (`JRTIndex` uses the data defined here, but does not generate the `.java` file - parts of the build system do): > > # This file was originally used to produce the `proprietary` warning when > # accessing non-APIs, and to hide some non-APIs in JDK <= 8. This has been > # superseded by the module system and `--release`. But, when compiling with > # `--source 8`, it is still used for this purpose by `com.sun.tools.javac.file.JRTIndex`. > # > # The build generates `jdk.compiler/com/sun/tools/javac/resources/ct.java` from > # this file, which is then used at runtime. Applied in 476a98d3460. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/28123#discussion_r2490274420 From nbenalla at openjdk.org Tue Nov 4 12:27:43 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 12:27:43 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 Message-ID: Get JDK 27 underway. ------------- Commit messages: - initial commit start-of-JDK-27 Changes: https://git.openjdk.org/jdk/pull/28130/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8370890 Stats: 90 lines in 34 files changed: 46 ins; 0 del; 44 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From nbenalla at openjdk.org Tue Nov 4 12:27:43 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 12:27:43 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 11:45:04 GMT, Nizar Benalla wrote: > Get JDK 27 underway. This initial version of the PR intentionally excludes the creation of the new symbol files so that the fundamental code aspects of the update are easier to see. The GA release date is accurate. The URL of the JVMLS will be updated in the next commit to be accurate. ------------- PR Comment: https://git.openjdk.org/jdk/pull/28130#issuecomment-3485695380 From jlahoda at openjdk.org Tue Nov 4 14:53:32 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 14:53:32 GMT Subject: RFR: 8369489: Marker annotation on inner class access crashes javac compiler [v2] In-Reply-To: References: Message-ID: <2MDD-eawPdZWHZl3tJ0JMbovqlYuiC7weyGrPtfrZzM=.2a87e1c1-6eb6-4e8d-b853-b415d3c03e63@github.com> > 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. Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains four commits: - Merge branch 'master' into JDK-8369489 - 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=01 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 abimpoudis at openjdk.org Tue Nov 4 16:12:46 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Tue, 4 Nov 2025 16:12:46 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 14:11:54 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 23 commits: >> >> - Merge branch 'JDK-8364991' into JDK-8367530 >> - 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. >> - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 > > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 948: > >> 946: //combine sealed subtypes into the supertype, if all is covered. >> 947: //but preserve more specific record types in positions where there are record patterns in the original patterns >> 948: //this is particularly for the case where the sealed supertype only has one permitted type, the record > > There is a word missing:"this is particularly *important* for" I think, right? Interesting. This is a property for NR-1S that shows up here too. Nice. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490694687 From abimpoudis at openjdk.org Tue Nov 4 16:12:44 2025 From: abimpoudis at openjdk.org (Aggelos Biboudis) Date: Tue, 4 Nov 2025 16:12:44 GMT Subject: RFR: 8367530: The exhaustiveness errors could be improved [v4] In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 15:10:49 GMT, Jan Lahoda wrote: >> 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... > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 23 commits: > > - Merge branch 'JDK-8364991' into JDK-8367530 > - 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. > - ... and 13 more: https://git.openjdk.org/jdk/compare/e6a3f0da...b7c33349 This is a MEGA PR. Many congratulations @lahodaj. ? This is a first pass. I will come back to it again as I am slowly progressing into understanding it better. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 157: > 155: .stream() > 156: .flatMap(pd -> { > 157: if (pd instanceof BindingPattern bp && enum2Constants.containsKey(bp.type.tsym)) { Can this be subsumed into `computeMissingPatternDescriptions` just to handle the generation of all kinds of incomplete patterns inside there? It seems to be that this client-side would be clearer, but ignore if it would be too much fuss. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 173: > 171: } > 172: > 173: private CoverageResult computeCoverage(Type selectorType, Set patterns, boolean search) { This extra boolean parameter is subtle (because previously we didn't have a new mode of execution). Can you introduce either a top-level comment at the `computeCoverage` method or something more descriptive than `search` or an enumeration with the two modes? Because now it is calculating both the coverage result and the inverse (uncovered patterns). src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 351: > 349: Type instantiated = instantiatePatternType(targetType, csym); > 350: > 351: return instantiated != null && types.isCastable(targetType, instantiated); If inference fails, does this mean that we get an exhaustiveness error with a sample generic instantiation? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 836: > 834: if (toExpand instanceof BindingPattern bp) { > 835: if (bp.type.tsym.isSealed()) { > 836: //try to replace binding patterns for sealed types with all their immediate permitted types: Can you reuse the word "viablePermittedPatterns" in this comment? That way the reader can formulate the properties of what this variable represents, faster. IIUC this is a process of minimization going from the `viablePermittedPatterns` to `reducedPermittedPatterns`. Not only that, but (I think) there is a property that reduction means that you prune the combinatorial space as long as there are no variables *and* the pattern is the most general. The actual invariants are actually coming from `isPossibleSubtypePredicate` which ensures castability and pattern inference. I wonder how can we end up here with completely incompatible classes? (final A, final B) (so that the castability check return false in `isPossibleSubtypePredicate`). Wouldn't that be an error of applicability? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 893: > 891: > 892: for (Type componentType : componentTypes) { > 893: List variants; Is this the same conceptually to `viablePermittedPatterns` for the binding patterns case? If yes, we can reuse the same name (just to match the concepts)? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 924: > 922: .collect(Collectors.toCollection(HashSet::new)); > 923: > 924: //remove unnecessary: It seems that the removal of the unnecessary patterns is common to the next step as well? If yes, would it be beneficial to extract? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java line 948: > 946: //combine sealed subtypes into the supertype, if all is covered. > 947: //but preserve more specific record types in positions where there are record patterns in the original patterns > 948: //this is particularly for the case where the sealed supertype only has one permitted type, the record There is a word missing:"this is particularly *important* for" I think, right? ------------- PR Review: https://git.openjdk.org/jdk/pull/27256#pullrequestreview-3416390483 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490487291 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490461430 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2491048541 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490585550 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490667198 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490594825 PR Review Comment: https://git.openjdk.org/jdk/pull/27256#discussion_r2490682402 From mcimadamore at openjdk.org Tue Nov 4 16:38:29 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 4 Nov 2025 16:38:29 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy [v3] In-Reply-To: References: Message-ID: <97nAwH2eW-S0h6YmGalbzJCRLioJIKPEI190360QK-w=.b0e1e371-abdd-45fc-82fd-92ae2f460490@github.com> On Mon, 3 Nov 2025 18:28:43 GMT, Vicente Romero wrote: >> javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: >> >> - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType >> - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop >> >> The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. >> >> This new visitor will compare types looking for exactness which is something desirable in a map key. >> >> TIA > > Vicente Romero 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: > > - addressing review comments > - Merge branch 'master' into JDK-8337142 > - addressing review comments > - 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Looks good, thanks. I hope the performance of the type comparison doesn't regress too much (given that there's more virtual calls in the middle). ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/28101#pullrequestreview-3417490888 From cstein at openjdk.org Tue Nov 4 16:49:31 2025 From: cstein at openjdk.org (Christian Stein) Date: Tue, 4 Nov 2025 16:49:31 GMT Subject: RFR: 8278856: javac documentation does not mention use of Manifest class-path attribute [v2] In-Reply-To: References: Message-ID: > Please review this improvement to `javac`'s manpage, section **Directory Hierarchies**. Christian Stein 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 two additional commits since the last revision: - Merge branch 'openjdk:master' into patch-2 - 8278856: javac documentation does not mention use of Manifest class-path attribute ------------- Changes: - all: https://git.openjdk.org/jdk/pull/22243/files - new: https://git.openjdk.org/jdk/pull/22243/files/5799d8a9..ec71757e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=22243&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=22243&range=00-01 Stats: 1445838 lines in 19140 files changed: 785063 ins; 536765 del; 124010 mod Patch: https://git.openjdk.org/jdk/pull/22243.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/22243/head:pull/22243 PR: https://git.openjdk.org/jdk/pull/22243 From vromero at openjdk.org Tue Nov 4 16:50:32 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 4 Nov 2025 16:50:32 GMT Subject: RFR: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: On Mon, 3 Nov 2025 13:04:53 GMT, Maurizio Cimadamore wrote: >> javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: >> >> - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType >> - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop >> >> The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. >> >> This new visitor will compare types looking for exactness which is something desirable in a map key. >> >> TIA > > I did some more analysis. It seems like inference completes correctly. But at the last step we end up with a very complex type (for the type variable in List::of): > > > M&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>,? extends java.lang.Object&Nine&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six&Thirteen&Eleven&Thirteen&Eleven&Thir teen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Thirteen&Eleven&Thirteen&Eleven&Thirteen>&Thirteen>>&Thirteen&Eleven&Thirteen>&Thirteen>>>&Six>> > > > (!!) > > In the very last step of inference we have to check if this is a subtype of Object (the upper bound of the tvar). And this crashes javac, because subtyping needs to capture and capture triggers a glb involving this huge type which then consumes the stack. > > Eventually this computation ends up in `containsTypeRecursive` with these two types: > > > T = Test.Ten&Test.Thirteen&Test.Eleven&Test.Thirteen>&Test.Thirteen>> > > S = Test.Ten&Test.Thirteen> > > > At which point we keep looping forever because, to check if we have already seen this type pair, we need to perform (as you said), a nested containment check which brings us back here. So, we never decide whether we can add the type pair to the cache or not... > > So, your fix seems to be correct -- we need a simpler way to structurally compares two types w/o calling back into containment. @mcimadamore thanks for the review! ------------- PR Comment: https://git.openjdk.org/jdk/pull/28101#issuecomment-3486976235 From vromero at openjdk.org Tue Nov 4 16:50:34 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 4 Nov 2025 16:50:34 GMT Subject: Integrated: 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy In-Reply-To: References: Message-ID: On Sun, 2 Nov 2025 02:12:40 GMT, Vicente Romero wrote: > javac can crash with SOE for some deeply nested type hierarchies. See the related JBS issue for the code example. Here we have another example of infinite recursion in the compiler. This is what is happening: > > - method Types."isSubtype"::containsTypeRecursive uses a cache, which is a Set, the elements in that cache are of type Types.TypePair. Method TypePair::equals invoke Types::isSameType > - Types::isSameType for this test case ends up invoking Types."isSubtype"::containsTypeRecursive, closing the infinite loop > > The proposed solution is to define current anonymous class isSameTypeVisitor as a named class and derive from it a visitor that will be the one used by Types.TypePair and thus invoked by TypePair::equals every time instances of TypePair are added or removed from a Map, Set, etc. > > This new visitor will compare types looking for exactness which is something desirable in a map key. > > TIA This pull request has now been integrated. Changeset: 4c6af03f Author: Vicente Romero URL: https://git.openjdk.org/jdk/commit/4c6af03f81e068a98b8f4628b96682a54f3946da Stats: 102 lines in 2 files changed: 96 ins; 0 del; 6 mod 8337142: StackOverflowError in Types.containsTypeRecursive with deeply nested type hierarchy Reviewed-by: mcimadamore ------------- PR: https://git.openjdk.org/jdk/pull/28101 From jlahoda at openjdk.org Tue Nov 4 17:03:43 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Tue, 4 Nov 2025 17:03:43 GMT Subject: RFR: 8278856: javac documentation does not mention use of Manifest class-path attribute [v2] In-Reply-To: References: Message-ID: On Tue, 19 Nov 2024 16:13:16 GMT, Christian Stein wrote: >> Christian Stein 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 two additional commits since the last revision: >> >> - Merge branch 'openjdk:master' into patch-2 >> - 8278856: javac documentation does not mention use of Manifest class-path attribute > > src/jdk.compiler/share/man/javac.md line 1291: > >> 1289: and the specified JAR file(s) exist, they are automatically inserted into the >> 1290: user class path after the JAR file. This rule also applies recursively to any >> 1291: new JAR files found. Consult the [JAR File Specification](../jar/jar.html#class-path-attribute) > > The link to the `jar.html` file using the relative path `../jar/` should lead to the JAR File Specification document. For JavaSE 23, that specification documentation is located at https://docs.oracle.com/en/java/javase/23/docs/specs/jar/jar.html > > How can I test that the online version, for 23 hosted at https://docs.oracle.com/en/java/javase/23/docs/specs/man/javac.html, contains the correct link target? I see javadoc uses a similar approach: https://github.com/openjdk/jdk/blob/4c6af03f81e068a98b8f4628b96682a54f3946da/src/jdk.javadoc/share/man/javadoc.md?plain=1#L101 So the link here is probably OK, but I don't know what is the way to check. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/22243#discussion_r2491325249 From vromero at openjdk.org Tue Nov 4 18:30:08 2025 From: vromero at openjdk.org (Vicente Romero) Date: Tue, 4 Nov 2025 18:30:08 GMT Subject: RFR: 8369489: Marker annotation on inner class access crashes javac compiler [v2] In-Reply-To: <2MDD-eawPdZWHZl3tJ0JMbovqlYuiC7weyGrPtfrZzM=.2a87e1c1-6eb6-4e8d-b853-b415d3c03e63@github.com> References: <2MDD-eawPdZWHZl3tJ0JMbovqlYuiC7weyGrPtfrZzM=.2a87e1c1-6eb6-4e8d-b853-b415d3c03e63@github.com> Message-ID: On Tue, 4 Nov 2025 14:53:32 GMT, Jan Lahoda wrote: >> 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. > > Jan Lahoda has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains four commits: > > - Merge branch 'master' into JDK-8369489 > - Fixing error recovery. > - Adjusting member ref position to sensible values. > - 8369489: Marker annotation on inner class access crashes javac compiler lgtm ------------- Marked as reviewed by vromero (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/27864#pullrequestreview-3418109245 From darcy at openjdk.org Tue Nov 4 18:47:51 2025 From: darcy at openjdk.org (Joe Darcy) Date: Tue, 4 Nov 2025 18:47:51 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 In-Reply-To: References: Message-ID: <4YP2knvpGm61PssS9EtEX4W35vd90XLOjgkevNqaBF0=.e5a34d1c-4f3d-407e-b53d-789a97682a0d@github.com> On Tue, 4 Nov 2025 11:45:04 GMT, Nizar Benalla wrote: > Get JDK 27 underway. Looks fine so far. ------------- PR Review: https://git.openjdk.org/jdk/pull/28130#pullrequestreview-3418178547 From nbenalla at openjdk.org Tue Nov 4 20:11:23 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 20:11:23 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v2] In-Reply-To: References: Message-ID: <3cZuldBvytdN_Hu0qlLhUkrCsH5EUlZJ5SEjnF8SLEU=.e76693bd-f6e1-4f8a-9dd5-699c9e4306bf@github.com> > Get JDK 27 underway. Nizar Benalla has updated the pull request incrementally with one additional commit since the last revision: add missing enum ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28130/files - new: https://git.openjdk.org/jdk/pull/28130/files/cc1a968e..647904b3 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=00-01 Stats: 1 line in 1 file changed: 1 ins; 0 del; 0 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From nbenalla at openjdk.org Tue Nov 4 20:24:52 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 4 Nov 2025 20:24:52 GMT Subject: RFR: 8370890: Start of release updates for JDK 27 [v3] In-Reply-To: References: Message-ID: > Get JDK 27 underway. Nizar Benalla has updated the pull request incrementally with one additional commit since the last revision: update links to JVMS 26 and 27 ------------- Changes: - all: https://git.openjdk.org/jdk/pull/28130/files - new: https://git.openjdk.org/jdk/pull/28130/files/647904b3..b51f2324 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=28130&range=01-02 Stats: 2 lines in 1 file changed: 0 ins; 0 del; 2 mod Patch: https://git.openjdk.org/jdk/pull/28130.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/28130/head:pull/28130 PR: https://git.openjdk.org/jdk/pull/28130 From acobbs at openjdk.org Tue Nov 4 23:56:30 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 4 Nov 2025 23:56:30 GMT Subject: RFR: 8155591: Misleading warning when not overriding close method in interface extending AutoCloseable [v2] In-Reply-To: References: Message-ID: On Tue, 4 Nov 2025 10:56:24 GMT, Jan Lahoda wrote: >> Archie Cobbs 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 two additional commits since the last revision: >> >> - Merge branch 'master' into JDK-8155591 to get recent build fixes. >> - Don't warn about AutoCloseable.close() itself throwing InterruptedException. > > Makes sense to me. I think it would be useful if the tests would be enhanced to cover the case where the `close` method declaration in non-AutoClo does actually `Exception`/`InterruptedException`. I found `InterruptedExceptionTest.java`, but as that's a combo test, it is harder to see a sensible warning is produced on a sensible place. > > Regarding sensible place, it would be possible to produce a warning specifically at the problematic `close` method (if it is declared in the given class, and not inherited) using `TreeInfo.diagnosticPositionFor`, but it is not so easy in this case - among other things, the warning would probably need a different wording. Up to you. Hi @lahodaj thanks for taking a look. I just realized there is another potential issue. Shouldn't a warning also be generated in this example? class WithClose { public void close() throws Exception { } } public class Try extends WithClose implements AutoCloseable { } Currently the compiler does not generate one; I'm not sure yet what exact logical tweak would be needed. ------------- PR Comment: https://git.openjdk.org/jdk/pull/27062#issuecomment-3488465787