From nbenalla at openjdk.org Tue Jul 1 11:35:42 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Tue, 1 Jul 2025 11:35:42 GMT Subject: RFR: 8346884: Add since checker test to jdk.editpad In-Reply-To: References: Message-ID: On Tue, 3 Jun 2025 10:09:44 GMT, Nizar Benalla wrote: > Please review this patch to add a new test to check `@since` tags in the `jdk.editpad` module. > > TIA keep alive ------------- PR Comment: https://git.openjdk.org/jdk/pull/25613#issuecomment-3023556036 From acobbs at openjdk.org Thu Jul 3 19:02:27 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 3 Jul 2025 19:02:27 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution Message-ID: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. In addition, several other factors complicate things: * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. ------------- Commit messages: - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Address review suggestions. - Remove assumptions about mandatoryness from the MandatoryWarningAggregator. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Merge branch 'master' into MandatoryWarningCleanup - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Move (most) SOURCE_LEVEL flags into compiler.properties. - Add DiagnosticFlag support to compiler.properties and put AGGREGATE there. - Apply some review suggestions. - ... and 76 more: https://git.openjdk.org/jdk/compare/25ed36f3...ec02990a Changes: https://git.openjdk.org/jdk/pull/24584/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8348611 Stats: 1999 lines in 57 files changed: 1065 ins; 587 del; 347 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From acobbs at openjdk.org Thu Jul 3 19:02:27 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 3 Jul 2025 19:02:27 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Thu, 10 Apr 2025 20:23:15 GMT, Archie Cobbs wrote: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Goals: * Eliminate `DeferredLintHandler` and the requirement for code to configure and use it in order to log warnings * Allow all warnings to be logged via `log.warning()` without having to know if/how `@SuppressWarnings` might apply * Eliminate (mostly) the need for manual `Lint` instance manipulation Design overview: * Maintain mappings from source code position to `Lint` configuration in the `LintMapper` class * Notify `LintMapper` when attribution completes so `Lint` configurations can be updated * Hold/defer lint warnings in `Log.DiagnosticHandler` if the `Lint` configuration is not yet known * Notify `Log` when held/deferred warnings should be reconsidered and flushed Patch overview: * `LintMapper.java`, `Log.java` - Replacing the functionality of `DeferredLintHandler` as described above * `JavacTrees.java` - Add a couple of missing calls to `Log.useSource()` * Other `src` classes - Derivative changes and cleanups/code removal * `test` classes - Warning/error reorderings, plus a few new tests Recommend ignoring whitespace when viewing the patch. ------------- PR Comment: https://git.openjdk.org/jdk/pull/24584#issuecomment-2835563690 From cstein at openjdk.org Fri Jul 4 11:05:19 2025 From: cstein at openjdk.org (Christian Stein) Date: Fri, 4 Jul 2025 11:05:19 GMT Subject: RFR: 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell [v2] In-Reply-To: References: Message-ID: > Please review this change to handle an `EndOfFileException` while reading input from a user console in such a way, that no stacktrace is emitted. The handling of the `Ctrl+D` command is left as-is; here the following underlying core-libs should stay in control: > > - `System.in.read()` > - `System.console().reader().read()` > - `System.console().readLine()` > - `System.console().readPassword()` > - `System.in.readAllBytes()` > - `IO.readln()` Christian Stein has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits: - Attempting to tweak behavior - 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell ------------- Changes: https://git.openjdk.org/jdk/pull/25713/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=25713&range=01 Stats: 96 lines in 6 files changed: 64 ins; 5 del; 27 mod Patch: https://git.openjdk.org/jdk/pull/25713.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/25713/head:pull/25713 PR: https://git.openjdk.org/jdk/pull/25713 From cstein at openjdk.org Fri Jul 4 13:27:41 2025 From: cstein at openjdk.org (Christian Stein) Date: Fri, 4 Jul 2025 13:27:41 GMT Subject: RFR: 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell [v2] In-Reply-To: <41KLHstELyXrWp7ErJU59UIzTb2MyiKmlf0dr9mUs0U=.0d6ed7ce-9330-4a77-bf03-94515240f530@github.com> References: <41KLHstELyXrWp7ErJU59UIzTb2MyiKmlf0dr9mUs0U=.0d6ed7ce-9330-4a77-bf03-94515240f530@github.com> Message-ID: On Mon, 30 Jun 2025 07:22:34 GMT, Christian Stein wrote: >> Christian Stein has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits: >> >> - Attempting to tweak behavior >> - 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell > > test/langtools/jdk/jshell/InputUITest.java line 78: > >> 76: "System.console().readPassword()", " ==> null", >> 77: "IO.readln()", " ==> \"null\"" >> 78: // TODO , "System.in.readAllBytes()", " ==> " // ... hangs forever > > Manual testing in a JShell session with this change set applied shows the watend behaviour: breaks with Ctrl+C and no exception is printed for Ctrl+D Now also works as expected after @lahodaj's tweaks. ? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/25713#discussion_r2185374317 From jlahoda at openjdk.org Fri Jul 4 15:30:39 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 4 Jul 2025 15:30:39 GMT Subject: RFR: 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell [v2] In-Reply-To: References: Message-ID: On Fri, 4 Jul 2025 11:05:19 GMT, Christian Stein wrote: >> Please review this change to handle an `EndOfFileException` while reading input from a user console in such a way, that no stacktrace is emitted. The handling of the `Ctrl+D` command is left as-is; here the following underlying core-libs should stay in control: >> >> - `System.in.read()` >> - `System.console().reader().read()` >> - `System.console().readLine()` >> - `System.console().readPassword()` >> - `System.in.readAllBytes()` >> - `IO.readln()` > > Christian Stein has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains two commits: > > - Attempting to tweak behavior > - 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell Looks good to me, thanks! ------------- Marked as reviewed by jlahoda (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/25713#pullrequestreview-2987687147 From jlahoda at openjdk.org Fri Jul 4 17:37:58 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Fri, 4 Jul 2025 17:37:58 GMT Subject: RFR: 8177650: JShell tool: packages in classpath don't appear in completions Message-ID: JShell provides the code completion feature, where it suggests possible follow ups for a given snippet prefix. To allow completion for packages, JShell uses a background task to go through known classes and create an index for them. There are two problems with this background task: - the classpath is read from the JShell's FileManager, but the FileManager may not be configured with the compile options yet, so the classpath may not be filled yet, - the module path is not included in the list of paths to paths to search This PR proposes to: - use FileManager configured by passing the compile options through javac - include the module path in the search path ------------- Commit messages: - Correcting handling of modular paths. - Improving test reliability. - 8177650: JShell tool: packages in classpath don't appear in completions Changes: https://git.openjdk.org/jdk/pull/26137/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=26137&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8177650 Stats: 281 lines in 5 files changed: 278 ins; 0 del; 3 mod Patch: https://git.openjdk.org/jdk/pull/26137.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26137/head:pull/26137 PR: https://git.openjdk.org/jdk/pull/26137 From cstein at openjdk.org Mon Jul 7 09:02:44 2025 From: cstein at openjdk.org (Christian Stein) Date: Mon, 7 Jul 2025 09:02:44 GMT Subject: Integrated: 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell In-Reply-To: References: Message-ID: <1xdtYBf8RH0PkrVmMCy4OiUzJobC4sDCMT7p43tUvyM=.ecd8019b-7e80-4ee7-b41b-a1fd1d753310@github.com> On Tue, 10 Jun 2025 08:29:15 GMT, Christian Stein wrote: > Please review this change to handle an `EndOfFileException` while reading input from a user console in such a way, that no stacktrace is emitted. The handling of the `Ctrl+D` command is left as-is; here the following underlying core-libs should stay in control: > > - `System.in.read()` > - `System.console().reader().read()` > - `System.console().readLine()` > - `System.console().readPassword()` > - `System.in.readAllBytes()` > - `IO.readln()` This pull request has now been integrated. Changeset: 9449fea2 Author: Christian Stein URL: https://git.openjdk.org/jdk/commit/9449fea2cd7aa7375f1b127e5f0d2a36ffaa1814 Stats: 96 lines in 6 files changed: 64 ins; 5 del; 27 mod 8358552: EndOfFileException in System.in.read() and IO.readln() etc. in JShell Reviewed-by: jlahoda ------------- PR: https://git.openjdk.org/jdk/pull/25713 From cstein at openjdk.org Mon Jul 7 12:38:41 2025 From: cstein at openjdk.org (Christian Stein) Date: Mon, 7 Jul 2025 12:38:41 GMT Subject: RFR: 8177650: JShell tool: packages in classpath don't appear in completions In-Reply-To: References: Message-ID: <3W44S8GgYXgsMYUkySDQc7o5hUtiOA019iRvkaQ5R4g=.ac616bb4-16e3-4740-9d56-9e7f5e90905c@github.com> On Fri, 4 Jul 2025 17:32:38 GMT, Jan Lahoda wrote: > JShell provides the code completion feature, where it suggests possible follow ups for a given snippet prefix. To allow completion for packages, JShell uses a background task to go through known classes and create an index for them. > > There are two problems with this background task: > - the classpath is read from the JShell's FileManager, but the FileManager may not be configured with the compile options yet, so the classpath may not be filled yet, > - the module path is not included in the list of paths to paths to search > > This PR proposes to: > - use FileManager configured by passing the compile options through javac > - include the module path in the search path Marked as reviewed by cstein (Committer). ------------- PR Review: https://git.openjdk.org/jdk/pull/26137#pullrequestreview-2993653306 From cstein at openjdk.org Mon Jul 7 12:46:56 2025 From: cstein at openjdk.org (Christian Stein) Date: Mon, 7 Jul 2025 12:46:56 GMT Subject: RFR: 8177650: JShell tool: packages in classpath don't appear in completions In-Reply-To: References: Message-ID: On Fri, 4 Jul 2025 17:32:38 GMT, Jan Lahoda wrote: > JShell provides the code completion feature, where it suggests possible follow ups for a given snippet prefix. To allow completion for packages, JShell uses a background task to go through known classes and create an index for them. > > There are two problems with this background task: > - the classpath is read from the JShell's FileManager, but the FileManager may not be configured with the compile options yet, so the classpath may not be filled yet, > - the module path is not included in the list of paths to paths to search > > This PR proposes to: > - use FileManager configured by passing the compile options through javac > - include the module path in the search path Changes requested by cstein (Committer). test/langtools/jdk/jshell/ToolCompletionTest.java line 196: > 194: Files.createDirectories(lib); > 195: compiler.jar(p1, jarName, "p1/p2/Test.class", "p1/p3/Test.class"); > 196: Files.move(compiler.getPath(p1.resolve(jarName)), lib.resolve(jarName)); Suggestion: Files.copy(compiler.getPath(p1.resolve(jarName)), lib.resolve(jarName)); Prevent `java.nio.file.FileSystemException` on Windows: ToolCompletionTest.d\\tool_completion_test\\dir1\\test.jar -> tool_completion_test\\lib\\test.jar: The process cannot access the file because it is being used by another process Seems like `compiler.jar(p1, jarName, "p1/p2/Test.class", "p1/p3/Test.class");` keeps an open file handle to the created `JAR` file. ------------- PR Review: https://git.openjdk.org/jdk/pull/26137#pullrequestreview-2993683578 PR Review Comment: https://git.openjdk.org/jdk/pull/26137#discussion_r2189970293 From jlahoda at openjdk.org Mon Jul 7 13:05:28 2025 From: jlahoda at openjdk.org (Jan Lahoda) Date: Mon, 7 Jul 2025 13:05:28 GMT Subject: RFR: 8177650: JShell tool: packages in classpath don't appear in completions [v2] In-Reply-To: References: Message-ID: > JShell provides the code completion feature, where it suggests possible follow ups for a given snippet prefix. To allow completion for packages, JShell uses a background task to go through known classes and create an index for them. > > There are two problems with this background task: > - the classpath is read from the JShell's FileManager, but the FileManager may not be configured with the compile options yet, so the classpath may not be filled yet, > - the module path is not included in the list of paths to paths to search > > This PR proposes to: > - use FileManager configured by passing the compile options through javac > - include the module path in the search path Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: Avoiding problems with locked files on Windows. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/26137/files - new: https://git.openjdk.org/jdk/pull/26137/files/ec2dcb89..54eed125 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=26137&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=26137&range=00-01 Stats: 10 lines in 2 files changed: 7 ins; 2 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/26137.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26137/head:pull/26137 PR: https://git.openjdk.org/jdk/pull/26137 From cstein at openjdk.org Mon Jul 7 13:09:43 2025 From: cstein at openjdk.org (Christian Stein) Date: Mon, 7 Jul 2025 13:09:43 GMT Subject: RFR: 8177650: JShell tool: packages in classpath don't appear in completions [v2] In-Reply-To: References: Message-ID: On Mon, 7 Jul 2025 12:43:57 GMT, Christian Stein wrote: >> Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: >> >> Avoiding problems with locked files on Windows. > > test/langtools/jdk/jshell/ToolCompletionTest.java line 196: > >> 194: Files.createDirectories(lib); >> 195: compiler.jar(p1, jarName, "p1/p2/Test.class", "p1/p3/Test.class"); >> 196: Files.move(compiler.getPath(p1.resolve(jarName)), lib.resolve(jarName)); > > Suggestion: > > Files.copy(compiler.getPath(p1.resolve(jarName)), lib.resolve(jarName)); > > > Prevent `java.nio.file.FileSystemException` on Windows: > > > ToolCompletionTest.d\\tool_completion_test\\dir1\\test.jar -> tool_completion_test\\lib\\test.jar: The process cannot access the file because it is being used by another process > > > Seems like `compiler.jar(p1, jarName, "p1/p2/Test.class", "p1/p3/Test.class");` keeps an open file handle to the created `JAR` file. Superseded by https://github.com/openjdk/jdk/pull/26137/commits/54eed125f92aeb016502a8c06b2f284d4e4d4ded ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/26137#discussion_r2190028046 From duke at openjdk.org Mon Jul 7 15:40:50 2025 From: duke at openjdk.org (Khalid Boulanouare) Date: Mon, 7 Jul 2025 15:40:50 GMT Subject: RFR: 8361188: Test java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java fails on Mac OS X Message-ID: Fixed an issue where null value component is not checked in class java/awt/Mixing/AWT_Mixing/OverlappingTestBase. Also removed test java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java from problem list file. ------------- Depends on: https://git.openjdk.org/jdk/pull/25971 Commit messages: - Merge branch 'pr/25971' into jdk-8361188 - Merge branch 'pr/25971' into jdk-8361188 - Merge branch 'openjdk:master' into jdk-8361188 - Removes test from Problem List - Returns false if component is null, in the case of embedded frame Changes: https://git.openjdk.org/jdk/pull/26162/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=26162&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8361188 Stats: 3 lines in 2 files changed: 1 ins; 1 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/26162.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/26162/head:pull/26162 PR: https://git.openjdk.org/jdk/pull/26162 From jpai at openjdk.org Tue Jul 8 05:06:39 2025 From: jpai at openjdk.org (Jaikiran Pai) Date: Tue, 8 Jul 2025 05:06:39 GMT Subject: RFR: 8346884: Add since checker test to jdk.editpad In-Reply-To: References: Message-ID: On Tue, 3 Jun 2025 10:09:44 GMT, Nizar Benalla wrote: > Please review this patch to add a new test to check `@since` tags in the `jdk.editpad` module. > > TIA This looks OK to me. ------------- Marked as reviewed by jpai (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/25613#pullrequestreview-2995985317 From nbenalla at openjdk.org Wed Jul 9 13:51:49 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Wed, 9 Jul 2025 13:51:49 GMT Subject: RFR: 8346884: Add since checker test to jdk.editpad In-Reply-To: References: Message-ID: On Tue, 3 Jun 2025 10:09:44 GMT, Nizar Benalla wrote: > Please review this patch to add a new test to check `@since` tags in the `jdk.editpad` module. > > TIA Thanks for the review Jaikiran. This passes on all platforms in our CI ------------- PR Comment: https://git.openjdk.org/jdk/pull/25613#issuecomment-3052749566 From nbenalla at openjdk.org Wed Jul 9 13:51:50 2025 From: nbenalla at openjdk.org (Nizar Benalla) Date: Wed, 9 Jul 2025 13:51:50 GMT Subject: Integrated: 8346884: Add since checker test to jdk.editpad In-Reply-To: References: Message-ID: On Tue, 3 Jun 2025 10:09:44 GMT, Nizar Benalla wrote: > Please review this patch to add a new test to check `@since` tags in the `jdk.editpad` module. > > TIA This pull request has now been integrated. Changeset: 7daf9813 Author: Nizar Benalla URL: https://git.openjdk.org/jdk/commit/7daf9813c0617ea97d95bf326eac1758e40cddd6 Stats: 3 lines in 1 file changed: 0 ins; 0 del; 3 mod 8346884: Add since checker test to jdk.editpad Reviewed-by: jpai ------------- PR: https://git.openjdk.org/jdk/pull/25613 From asotona at openjdk.org Thu Jul 17 11:59:49 2025 From: asotona at openjdk.org (Adam Sotona) Date: Thu, 17 Jul 2025 11:59:49 GMT Subject: RFR: 8177650: JShell tool: packages in classpath don't appear in completions [v2] In-Reply-To: References: Message-ID: On Mon, 7 Jul 2025 13:05:28 GMT, Jan Lahoda wrote: >> JShell provides the code completion feature, where it suggests possible follow ups for a given snippet prefix. To allow completion for packages, JShell uses a background task to go through known classes and create an index for them. >> >> There are two problems with this background task: >> - the classpath is read from the JShell's FileManager, but the FileManager may not be configured with the compile options yet, so the classpath may not be filled yet, >> - the module path is not included in the list of paths to paths to search >> >> This PR proposes to: >> - use FileManager configured by passing the compile options through javac >> - include the module path in the search path > > Jan Lahoda has updated the pull request incrementally with one additional commit since the last revision: > > Avoiding problems with locked files on Windows. Looks good to me. ------------- Marked as reviewed by asotona (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/26137#pullrequestreview-3029214655 From acobbs at openjdk.org Thu Jul 17 18:42:36 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Thu, 17 Jul 2025 18:42:36 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v2] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: <4fsbORe6HMABvncq0SCmCH2if4qdoonHeR7Ny3CODWY=.fe7838da-e648-44ff-a4ca-18617d48fec3@github.com> > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 87 commits: - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Address review suggestions. - Remove assumptions about mandatoryness from the MandatoryWarningAggregator. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Merge branch 'master' into MandatoryWarningCleanup - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Move (most) SOURCE_LEVEL flags into compiler.properties. - Add DiagnosticFlag support to compiler.properties and put AGGREGATE there. - ... and 77 more: https://git.openjdk.org/jdk/compare/a65d9532...9432be0d ------------- Changes: https://git.openjdk.org/jdk/pull/24584/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=01 Stats: 2000 lines in 57 files changed: 1064 ins; 587 del; 349 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From jan.lahoda at oracle.com Fri Jul 18 12:01:49 2025 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Fri, 18 Jul 2025 14:01:49 +0200 Subject: CFV: Dissolve the Kulla project Message-ID: Hello Kulla committers, The "Kulla" project was founded to develop JShell, and bring it into the JDK. That happened in JDK 9, almost 8 years ago. Since then JShell has been an integral part of the JDK. Given the Kulla project achieved its goal and JShell is no longer any different than any other JDK component, I am hereby proposing to dissolve[1] and archive the Kulla project. Votes are due by midnight UTC on August 3rd. Only current Kulla Committers [2] are eligible to vote on this motion.? Votes must be cast in the open by replying to this mailing list. For Lazy Consensus voting instructions, see [3]. Thank you, ??? Jan [1] https://openjdk.org/bylaws#_6 [2] https://openjdk.org/census#kulla [3] https://openjdk.org/bylaws#lazy-consensus -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Fri Jul 18 12:56:48 2025 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 18 Jul 2025 12:56:48 +0000 Subject: CFV: Dissolve the Kulla project In-Reply-To: References: Message-ID: <313951C9-7D23-4641-AD88-524645FA370E@oracle.com> Vote: Yes On Jul 18, 2025, at 8:01 AM, Jan Lahoda > wrote: Hello Kulla committers, The "Kulla" project was founded to develop JShell, and bring it into the JDK. That happened in JDK 9, almost 8 years ago. Since then JShell has been an integral part of the JDK. Given the Kulla project achieved its goal and JShell is no longer any different than any other JDK component, I am hereby proposing to dissolve[1] and archive the Kulla project. Votes are due by midnight UTC on August 3rd. Only current Kulla Committers [2] are eligible to vote on this motion. Votes must be cast in the open by replying to this mailing list. For Lazy Consensus voting instructions, see [3]. Thank you, Jan [1] https://openjdk.org/bylaws#_6 [2] https://openjdk.org/census#kulla [3] https://openjdk.org/bylaws#lazy-consensus -------------- next part -------------- An HTML attachment was scrubbed... URL: From vicente.romero at oracle.com Fri Jul 18 12:58:41 2025 From: vicente.romero at oracle.com (Vicente Romero) Date: Fri, 18 Jul 2025 08:58:41 -0400 Subject: CFV: Dissolve the Kulla project In-Reply-To: References: Message-ID: <694af8e8-b322-45cc-a69b-36c57ced6797@oracle.com> vote: yes Vicente On 7/18/25 08:01, Jan Lahoda wrote: > > Hello Kulla committers, > > The "Kulla" project was founded to develop JShell, and bring it into the > JDK. That happened in JDK 9, almost 8 years ago. Since then JShell has > been an integral part of the JDK. Given the Kulla project achieved its > goal and JShell is no longer any different than any other JDK component, > I am hereby proposing to dissolve[1] and archive the Kulla project. > > Votes are due by midnight UTC on August 3rd. > > Only current Kulla Committers [2] are eligible to vote on this > motion.? Votes must be cast in the open by replying to this mailing list. > > For Lazy Consensus voting instructions, see [3]. > > Thank you, > ??? Jan > > [1] https://openjdk.org/bylaws#_6 > [2] https://openjdk.org/census#kulla > [3] https://openjdk.org/bylaws#lazy-consensus > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From joe.darcy at oracle.com Fri Jul 18 16:19:02 2025 From: joe.darcy at oracle.com (Joseph D. Darcy) Date: Fri, 18 Jul 2025 09:19:02 -0700 Subject: CFV: Dissolve the Kulla project In-Reply-To: References: Message-ID: <6ace4d3f-b0d6-449d-9319-aae2a85fde0e@oracle.com> vote:yes On 7/18/2025 5:01 AM, Jan Lahoda wrote: > > Hello Kulla committers, > > The "Kulla" project was founded to develop JShell, and bring it into the > JDK. That happened in JDK 9, almost 8 years ago. Since then JShell has > been an integral part of the JDK. Given the Kulla project achieved its > goal and JShell is no longer any different than any other JDK component, > I am hereby proposing to dissolve[1] and archive the Kulla project. > > Votes are due by midnight UTC on August 3rd. > > Only current Kulla Committers [2] are eligible to vote on this > motion.? Votes must be cast in the open by replying to this mailing list. > > For Lazy Consensus voting instructions, see [3]. > > Thank you, > ??? Jan > > [1] https://openjdk.org/bylaws#_6 > [2] https://openjdk.org/census#kulla > [3] https://openjdk.org/bylaws#lazy-consensus > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From iris.clark at oracle.com Fri Jul 18 16:47:54 2025 From: iris.clark at oracle.com (Iris Clark) Date: Fri, 18 Jul 2025 16:47:54 +0000 Subject: CFV: Dissolve the Kulla project In-Reply-To: References: Message-ID: Vote: yes Iris -------------- next part -------------- An HTML attachment was scrubbed... URL: From acobbs at openjdk.org Sun Jul 20 20:39:07 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Sun, 20 Jul 2025 20:39:07 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 89 commits: - Add DEFAULT_ENABLED flags to fix some mandatory warnings. - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Address review suggestions. - Remove assumptions about mandatoryness from the MandatoryWarningAggregator. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Merge branch 'master' into MandatoryWarningCleanup - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - ... and 79 more: https://git.openjdk.org/jdk/compare/cab51596...91202f7b ------------- Changes: https://git.openjdk.org/jdk/pull/24584/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=02 Stats: 1997 lines in 56 files changed: 1052 ins; 586 del; 359 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From mcimadamore at openjdk.org Mon Jul 28 16:58:08 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 28 Jul 2025 16:58:08 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Sun, 20 Jul 2025 20:39:07 GMT, Archie Cobbs wrote: >> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. >> >> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. >> >> In addition, several other factors complicate things: >> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any >> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) >> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) >> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled >> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings >> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags >> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. >> >> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". >> >> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. > > Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 89 commits: > > - Add DEFAULT_ENABLED flags to fix some mandatory warnings. > - Merge branch 'master' into JDK-8348611 to fix conflicts. > - Merge branch 'master' into JDK-8348611 to fix conflicts. > - Merge branch 'master' into JDK-8348611 to fix conflicts. > - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 > - Address review suggestions. > - Remove assumptions about mandatoryness from the MandatoryWarningAggregator. > - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 > - Merge branch 'master' into MandatoryWarningCleanup > - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 > - ... and 79 more: https://git.openjdk.org/jdk/compare/cab51596...91202f7b Overall, this is a great piece of work! The simplifications are evident throughout the entire codebase. I'm not sure `LintMapper` has reached its simplest possible form yet -- I've left some comments for you to consider -- I wonder if there's something we can do to capture the state transitions a little more explicitly there. src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java line 484: > 482: * @param warning key for the localized warning message > 483: */ > 484: public void logIfEnabled(LintWarning warning) { I like it a lot that now there's "just warnings". It took a while to see this more clearly, but once you see it you can't unsee it :-) src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 55: > 53: * > 54: *

> 55: * Because {@code @SuppressWarnings} is a Java symbol, in general this mapping can't be be Suggestion: * Because {@code @SuppressWarnings} is a Java symbol, in general this mapping can't be src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 178: > 176: * Instances evolve through three states: > 177: *

    > 178: *
  • Before the file has been completely parsed, {@link #topSpans} is null. Maybe we can capture all these interesting state transitions with a sealed hierarchy? E.g. at different stages it seems like we might need different info attached to this "info" note -- which might suggest using different subclasses? src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 283: > 281: * nodes representing the top-level declarations in the file, and so on. > 282: */ > 283: private static class DeclNode extends Span { This also seems to suggest that some of the spans computed after parsing are later "promoted" to decl nodes. But the code doesn't work like this, instead it tracks spans and decls separately into the same FileInfo data structure, which I find a bit odd. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java line 1079: > 1077: private final Symbol sym; > 1078: > 1079: public TypeAnnotate(Env env, Symbol sym) { All these changes are truly great, as they are sign that you were able to remove a lot of coupling from the way things were implemented. E.g. the goal of this PR is not to "make annotation processing simpler", but turns out that, by centralizing the lint mapping logic in one place, other parts of the compiler also got simpler! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 1: > 1: /* Now that `Attr` no longer depends on `Check::lint` (yayyy!) can we make that field private? src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 227: > 225: void warnDeprecated(DiagnosticPosition pos, Symbol sym) { > 226: Assert.check(!importSuppression); > 227: LintWarning warningKey = sym.isDeprecatedForRemoval() ? Another big win is the absence of all "is enabled?" checks in the new code. Meaning less potential for mistakes. src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 1: > 1: /* Another big win here -- code is much flatter! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 265: > 263: > 264: // Short circuit if this calculation is unnecessary > 265: if (!lintMapper.lintAt(env.toplevel.sourcefile, env.tree.pos()).get().isEnabled(THIS_ESCAPE)) Question -- this code does the shortcircuiting using `lintMapper` -- but I saw code in `Check` that does shortcircuiting using `lint` (e.g. `Check::checkPotentiallyAmbiguousOverloads`). If such short-circuit operation are somewhat frequent (to avoid expensive computation logic) perhaps we should have a "blessed" (and less verbose) way to do it? (Unfortunately, I'm aware that `checkPotentiallyAmbiguousOverloads` is called when `lintMapper` yet doesn't know whether lint warnings are suppressed or not -- this seems a problem?) src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java line 174: > 172: category.annotationSuppression ? // else emit if the category is not suppressed, where > 173: !lint.isSuppressed(category) : // ...suppression happens via @SuppressWarnings > 174: !options.isLintDisabled(category); // ...suppression happens via -Xlint:-category Can this be rewritten as `!rootLint().isSuppressed(category)` ? E.g. how many different ways do we have to query the same thing? src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java line 196: > 194: */ > 195: public void flushLintWaiters() { > 196: lintWaitersMap.entrySet().removeIf(entry -> { the use of `removeIf` seems to suggest that these not all warnings might be flushed at the same time? But this seems odd -- I'd expect that the `lintMapper` only gets new info in `Attr` -- after which if something doesn't have a `Lint`, well that shouldn't change? ------------- PR Review: https://git.openjdk.org/jdk/pull/24584#pullrequestreview-3063577027 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237121469 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237230153 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237237978 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237264944 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237114296 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237142388 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237132978 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237149038 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237163998 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237209441 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237227213 From acobbs at openjdk.org Mon Jul 28 17:53:19 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 28 Jul 2025 17:53:19 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Mon, 28 Jul 2025 16:41:59 GMT, Maurizio Cimadamore 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 89 commits: >> >> - Add DEFAULT_ENABLED flags to fix some mandatory warnings. >> - Merge branch 'master' into JDK-8348611 to fix conflicts. >> - Merge branch 'master' into JDK-8348611 to fix conflicts. >> - Merge branch 'master' into JDK-8348611 to fix conflicts. >> - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 >> - Address review suggestions. >> - Remove assumptions about mandatoryness from the MandatoryWarningAggregator. >> - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 >> - Merge branch 'master' into MandatoryWarningCleanup >> - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 >> - ... and 79 more: https://git.openjdk.org/jdk/compare/cab51596...91202f7b > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 55: > >> 53: * >> 54: *

    >> 55: * Because {@code @SuppressWarnings} is a Java symbol, in general this mapping can't be be > > Suggestion: > > * Because {@code @SuppressWarnings} is a Java symbol, in general this mapping can't be Oops, thanks. Fixed in d4322d92d1f. > src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 178: > >> 176: * Instances evolve through three states: >> 177: *

      >> 178: *
    • Before the file has been completely parsed, {@link #topSpans} is null. > > Maybe we can capture all these interesting state transitions with a sealed hierarchy? E.g. at different stages it seems like we might need different info attached to this "info" note -- which might suggest using different subclasses? Yes, this probably could take advantage of those newer language features. I'll take a look at this and your other comment about `FileInfo` and post an update soon. Thanks very much for the detailed review and comments so far! > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 1: > >> 1: /* > > Now that `Attr` no longer depends on `Check::lint` (yayyy!) can we make that field private? Indeed - good catch! Fixed in d4322d92d1f. > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 265: > >> 263: >> 264: // Short circuit if this calculation is unnecessary >> 265: if (!lintMapper.lintAt(env.toplevel.sourcefile, env.tree.pos()).get().isEnabled(THIS_ESCAPE)) > > Question -- this code does the shortcircuiting using `lintMapper` -- but I saw code in `Check` that does shortcircuiting using `lint` (e.g. `Check::checkPotentiallyAmbiguousOverloads`). If such short-circuit operation are somewhat frequent (to avoid expensive computation logic) perhaps we should have a "blessed" (and less verbose) way to do it? > > (Unfortunately, I'm aware that `checkPotentiallyAmbiguousOverloads` is called when `lintMapper` yet doesn't know whether lint warnings are suppressed or not -- this seems a problem?) The subtle difference between `ThisEscapeAnalyzer` and `Check::checkPotentiallyAmbiguousOverloads` is that `ThisEscapeAnalyzer` runs during the compiler's `WARN` phase, whereas `checkPotentiallyAmbiguousOverloads` runs during the `ATTR` phase, and only during the `WARN` phase it is guaranteed that `LintMapper.lintAt()` will always be able to return a non-empty value. Side note: as you may remember we had an earlier discussion about the idea of moving warnings from the `ATTR` phase to the `WARN` phase - the main "pro" being that there is no longer any concern about whether the applicable `Lint` instance has been mapped yet, so you don't need to track it manually (like `Check` does). I played with trying to do this but it was too heavy of a lift at the time (and probably still is) but it's a potential long term idea. The downside however (as you pointed out) is that during `ATTR` you have all the information you need to compute the warnings already "in front of you", whereas if you deferred that warning calculation to the `WARN` you would have to find it again (but maybe most of it is available?). Anyway, for now this is all "for future study". > src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java line 174: > >> 172: category.annotationSuppression ? // else emit if the category is not suppressed, where >> 173: !lint.isSuppressed(category) : // ...suppression happens via @SuppressWarnings >> 174: !options.isLintDisabled(category); // ...suppression happens via -Xlint:-category > > Can this be rewritten as `!rootLint().isSuppressed(category)` ? E.g. how many different ways do we have to query the same thing? There is a quirk about that: `rootLint().isSuppressed()` always returns `false` no matter what (see the last line of `Lint.initializeRootIfNeeded()`). In other words, the question that `isSuppressed()` is answering is not "Is this category suppressed somehow?" but rather "Is this category suppressed by a `@SuppressWarnings` annotation?" So in the case of a warning enabled by default: * For the root `Lint` instance, "suppression" happens via `-Xlint:-foo` * For non-root `Lint` instances, "suppression" happens via `@SuppressWarnings("foo")` Could this be simplified somehow? Probably... but that would be an independent cleanup. > the use of `removeIf` seems to suggest that these not all warnings might be flushed at the same time? Correct - "in theory" they might not all be flushed at the same time, because the entries in `lintWaitersMap` are organized on a per-source file basis, whereas lint mappings are discovered on a per-top level declaration basis. In practice they probably are.... but I didn't want to impose any implicit restrictions on when it was safe to invoke `Log.reportOutstandingWarnings()`. So, call this defensive coding :) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237441525 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237441827 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237440503 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237440802 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237441054 PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237441313 From acobbs at openjdk.org Mon Jul 28 17:53:18 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 28 Jul 2025 17:53:18 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v4] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 91 commits: - Address a couple of review comments. - Merge branch 'master' into JDK-8348611 - Add DEFAULT_ENABLED flags to fix some mandatory warnings. - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'master' into JDK-8348611 to fix conflicts. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - Address review suggestions. - Remove assumptions about mandatoryness from the MandatoryWarningAggregator. - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 - ... and 81 more: https://git.openjdk.org/jdk/compare/4189fcba...d4322d92 ------------- Changes: https://git.openjdk.org/jdk/pull/24584/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=03 Stats: 1998 lines in 56 files changed: 1052 ins; 586 del; 360 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From mcimadamore at openjdk.org Mon Jul 28 21:25:57 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Mon, 28 Jul 2025 21:25:57 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Mon, 28 Jul 2025 17:49:44 GMT, Archie Cobbs wrote: >> src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java line 265: >> >>> 263: >>> 264: // Short circuit if this calculation is unnecessary >>> 265: if (!lintMapper.lintAt(env.toplevel.sourcefile, env.tree.pos()).get().isEnabled(THIS_ESCAPE)) >> >> Question -- this code does the shortcircuiting using `lintMapper` -- but I saw code in `Check` that does shortcircuiting using `lint` (e.g. `Check::checkPotentiallyAmbiguousOverloads`). If such short-circuit operation are somewhat frequent (to avoid expensive computation logic) perhaps we should have a "blessed" (and less verbose) way to do it? >> >> (Unfortunately, I'm aware that `checkPotentiallyAmbiguousOverloads` is called when `lintMapper` yet doesn't know whether lint warnings are suppressed or not -- this seems a problem?) > > The subtle difference between `ThisEscapeAnalyzer` and `Check::checkPotentiallyAmbiguousOverloads` is that `ThisEscapeAnalyzer` runs during the compiler's `WARN` phase, whereas `checkPotentiallyAmbiguousOverloads` runs during the `ATTR` phase, and only during the `WARN` phase it is guaranteed that `LintMapper.lintAt()` will always be able to return a non-empty value. > > Side note: as you may remember we had an earlier discussion about the idea of moving warnings from the `ATTR` phase to the `WARN` phase - the main "pro" being that there is no longer any concern about whether the applicable `Lint` instance has been mapped yet, so you don't need to track it manually (like `Check` does). I played with trying to do this but it was too heavy of a lift at the time (and probably still is) but it's a potential long term idea. The downside however (as you pointed out) is that during `ATTR` you have all the information you need to compute the warnings already "in front of you", whereas if you deferred that warning calculation to the `WARN` you would have to find it again (but maybe most of it is available?). Anyway, for now this is all "for future study". One thing that might help would be to maybe use the name `rootLint` for all lint variables we use to shortcircuit -- to make it clear that these checks are not really... 100% correct. Another possibility would be to have a centralized check in LintMapper which, if the tree has been attributed does a check similar to what `ThisEscapeAnalyzer` does, otherwise we just look at the root lint (as a stop gap). At least all clients that need shortcircuiting would use same logic, and the impl could do the best it can to support that (and maybe in the future we can see if we can improve on that front). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237890423 From acobbs at openjdk.org Mon Jul 28 22:05:44 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 28 Jul 2025 22:05:44 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: Refactor LintMapper to clean up internal type hierarchy per review. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/24584/files - new: https://git.openjdk.org/jdk/pull/24584/files/d4322d92..f65e1950 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=04 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=03-04 Stats: 121 lines in 1 file changed: 24 ins; 39 del; 58 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From acobbs at openjdk.org Mon Jul 28 22:05:45 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 28 Jul 2025 22:05:45 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Mon, 28 Jul 2025 16:53:05 GMT, Maurizio Cimadamore 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 89 commits: >> >> - Add DEFAULT_ENABLED flags to fix some mandatory warnings. >> - Merge branch 'master' into JDK-8348611 to fix conflicts. >> - Merge branch 'master' into JDK-8348611 to fix conflicts. >> - Merge branch 'master' into JDK-8348611 to fix conflicts. >> - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 >> - Address review suggestions. >> - Remove assumptions about mandatoryness from the MandatoryWarningAggregator. >> - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 >> - Merge branch 'master' into MandatoryWarningCleanup >> - Merge branch 'MandatoryWarningCleanup' into JDK-8348611 >> - ... and 79 more: https://git.openjdk.org/jdk/compare/cab51596...91202f7b > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 283: > >> 281: * nodes representing the top-level declarations in the file, and so on. >> 282: */ >> 283: private static class DeclNode extends Span { > > This also seems to suggest that some of the spans computed after parsing are later "promoted" to decl nodes. But the code doesn't work like this, instead it tracks spans and decls separately into the same FileInfo data structure, which I find a bit odd. Should be improved in f65e1950467. Thanks. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237935618 From acobbs at openjdk.org Mon Jul 28 22:05:45 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Mon, 28 Jul 2025 22:05:45 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Mon, 28 Jul 2025 21:23:33 GMT, Maurizio Cimadamore wrote: > One thing that might help would be to maybe use the name `rootLint` for all lint variables we use to shortcircuit -- to make it clear that these checks are not really... 100% correct. Not sure I'm understanding you... the remaining short-circuit checks are using "local" `Lint` instances, not the root `Lint` instance; for example `checkPotentiallyAmbiguousOverloads()`... > Another possibility would be to have a centralized check in LintMapper which, if the tree has been attributed does a check similar to what `ThisEscapeAnalyzer` does, otherwise we just look at the root lint (as a stop gap). Continuing the above comment, wouldn't that cause `checkPotentiallyAmbiguousOverloads()` to start ignoring any enclosing `@SuppressWarnings("overrides")` annotations? > At least all clients that need shortcircuiting would use same logic, and the impl could do the best it can to support that (and maybe in the future we can see if we can improve on that front). Other ideas: * Add a method that basically says "Call me back when my `Lint` is ready". Echoes of `DeferredLintHandler` :) * Get rid of as much short-circuiting as we possible (i.e., where the performance impact is negligible, we can simply not short-circuit) * Move the short-circuited warnings to the `WARN` phase ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2237935426 From mcimadamore at openjdk.org Tue Jul 29 09:12:11 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 29 Jul 2025 09:12:11 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Mon, 28 Jul 2025 21:58:09 GMT, Archie Cobbs wrote: > Not sure I'm understanding you... the remaining short-circuit checks are using "local" `Lint` instances, not the root `Lint` instance; for example `checkPotentiallyAmbiguousOverloads()`... At the start of `checkPotentiallyAmbiguousOverloads()`, we check: if (!lint.isEnabled(LintCategory.OVERLOADS)) return; Now, I do not see any other code setting this lint. There are a couple of visitors elsewhere that do, but these operations seems rather local. To my eyes, this is check applied to the root lint. Then there's a more subtle check (that I missed) below: // Allow site's own declared methods (only) to apply @SuppressWarnings("overloads") methodGroups.forEach(list -> list.removeIf( m -> m.owner == site.tsym && !lint.augment(m).isEnabled(LintCategory.OVERLOADS))); This "augments" the lint with one of the symbols to check, and removes the symbol if it is annotated with `@SuppressWarnings("overloads")`. This code seems convoluted, in the sense that you don't really need to augment anything here? The toplevel check looks for enablement, whereas this loop looks for suppression. To implement the latter all you need is to check is a certain category appears suppressed in the given symbol. Note though: if we have a `@SuppressWarnings` on the enclosing class I don't think that will be considered. I will need to test a bit more. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2239087936 From mcimadamore at openjdk.org Tue Jul 29 09:20:57 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 29 Jul 2025 09:20:57 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Tue, 29 Jul 2025 09:09:45 GMT, Maurizio Cimadamore wrote: >>> One thing that might help would be to maybe use the name `rootLint` for all lint variables we use to shortcircuit -- to make it clear that these checks are not really... 100% correct. >> >> Not sure I'm understanding you... the remaining short-circuit checks are using "local" `Lint` instances, not the root `Lint` instance; for example `checkPotentiallyAmbiguousOverloads()`... >> >>> Another possibility would be to have a centralized check in LintMapper which, if the tree has been attributed does a check similar to what `ThisEscapeAnalyzer` does, otherwise we just look at the root lint (as a stop gap). >> >> Continuing the above comment, wouldn't that cause `checkPotentiallyAmbiguousOverloads()` to start ignoring any enclosing `@SuppressWarnings("overrides")` annotations? >> >>> At least all clients that need shortcircuiting would use same logic, and the impl could do the best it can to support that (and maybe in the future we can see if we can improve on that front). >> >> Other ideas: >> * Add a method that basically says "Call me back when my `Lint` is ready". Echoes of `DeferredLintHandler` :) >> * Get rid of as much short-circuiting as we possible (i.e., where the performance impact is negligible, we can simply not short-circuit) >> * Move the short-circuited warnings to the `WARN` phase > >> Not sure I'm understanding you... the remaining short-circuit checks are using "local" `Lint` instances, not the root `Lint` instance; for example `checkPotentiallyAmbiguousOverloads()`... > > At the start of `checkPotentiallyAmbiguousOverloads()`, we check: > > > if (!lint.isEnabled(LintCategory.OVERLOADS)) > return; > > > Now, I do not see any other code setting this lint. There are a couple of visitors elsewhere that do, but these operations seems rather local. To my eyes, this is check applied to the root lint. Then there's a more subtle check (that I missed) below: > > > // Allow site's own declared methods (only) to apply @SuppressWarnings("overloads") > methodGroups.forEach(list -> list.removeIf( > m -> m.owner == site.tsym && !lint.augment(m).isEnabled(LintCategory.OVERLOADS))); > > > This "augments" the lint with one of the symbols to check, and removes the symbol if it is annotated with `@SuppressWarnings("overloads")`. > > This code seems convoluted, in the sense that you don't really need to augment anything here? The toplevel check looks for enablement, whereas this loop looks for suppression. To implement the latter all you need is to check is a certain category appears suppressed in the given symbol. Note though: if we have a `@SuppressWarnings` on the enclosing class I don't think that will be considered. I will need to test a bit more. > Move the short-circuited warnings to the `WARN` phase This is probably the best, as I suspect that we only shortcircuit in a handful of cases. Another approach would be to try an augment lint earlier -- e.g. during `memberEnter`. After all, by that point we have seen the class, and we have seen a method/field symbol, so in principle we might know what suppressions these symbols have. The only thing that would be left after that is stuff inside method bodies (mostly local var declaration, and anon/local inner classes -- but I believe both go through `memberEnter` again, so we should be covered). This would ensure that the mappings are setup as early as possible -- which would allow shortcircuiting logic in `Check` to occur more naturally. That said, doing this might have some bootstrapping issues -- @lahodaj any ideas? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2239109725 From acobbs at openjdk.org Tue Jul 29 14:05:59 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 29 Jul 2025 14:05:59 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v3] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Tue, 29 Jul 2025 09:17:51 GMT, Maurizio Cimadamore wrote: >>> Not sure I'm understanding you... the remaining short-circuit checks are using "local" `Lint` instances, not the root `Lint` instance; for example `checkPotentiallyAmbiguousOverloads()`... >> >> At the start of `checkPotentiallyAmbiguousOverloads()`, we check: >> >> >> if (!lint.isEnabled(LintCategory.OVERLOADS)) >> return; >> >> >> Now, I do not see any other code setting this lint. There are a couple of visitors elsewhere that do, but these operations seems rather local. To my eyes, this is check applied to the root lint. Then there's a more subtle check (that I missed) below: >> >> >> // Allow site's own declared methods (only) to apply @SuppressWarnings("overloads") >> methodGroups.forEach(list -> list.removeIf( >> m -> m.owner == site.tsym && !lint.augment(m).isEnabled(LintCategory.OVERLOADS))); >> >> >> This "augments" the lint with one of the symbols to check, and removes the symbol if it is annotated with `@SuppressWarnings("overloads")`. >> >> This code seems convoluted, in the sense that you don't really need to augment anything here? The toplevel check looks for enablement, whereas this loop looks for suppression. To implement the latter all you need is to check is a certain category appears suppressed in the given symbol. Note though: if we have a `@SuppressWarnings` on the enclosing class I don't think that will be considered. I will need to test a bit more. > >> Move the short-circuited warnings to the `WARN` phase > > This is probably the best, as I suspect that we only shortcircuit in a handful of cases. > > Another approach would be to try an augment lint earlier -- e.g. during `memberEnter`. After all, by that point we have seen the class, and we have seen a method/field symbol, so in principle we might know what suppressions these symbols have. The only thing that would be left after that is stuff inside method bodies (mostly local var declaration, and anon/local inner classes -- but I believe both go through `memberEnter` again, so we should be covered). This would ensure that the mappings are setup as early as possible -- which would allow shortcircuiting logic in `Check` to occur more naturally. > > That said, doing this might have some bootstrapping issues -- @lahodaj any ideas? > > Not sure I'm understanding you... the remaining short-circuit checks are using "local" `Lint` instances, not the root `Lint` instance; for example `checkPotentiallyAmbiguousOverloads()`... > > At the start of `checkPotentiallyAmbiguousOverloads()`, we check... Now, I do not see any other code setting this lint. That method is invoked from `Attr.attribClassBody()`, which is invoked from `Attr.attribClass()`, which invokes `chk.setLint()`, etc. So it does appear to be using a "local" `Lint` instance, right? But I was missing your larger point - even if we replaced this local `Lint` with `rootLint`, the short circuit check would still be correct, just less precise. In other words, once a Lint category is disabled, it's never possible for it be re-enabled by a nested declaration. So if code is short-circuiting via `if (!lint.isEnabled(FOO)) skip...` then switching from a local lint to `rootLint` is a conservative (safe) change (side note: this wouldn't work for `DEFAULT_ENABLED` warnings, but the few warnings that have that flag are not involved here). > This code seems convoluted, in the sense that you don't really need to augment anything here? The toplevel check looks for enablement, whereas this loop looks for suppression. To implement the latter all you need is to check is a certain category appears suppressed in the given symbol. Note though: if we have a @SuppressWarnings on the enclosing class I don't think that will be considered. I will need to test a bit more. This check (overloads) as well as the `"this-escape"` check do "tricky" stuff because they are both examples in which whether the warning is emitted depends on non-local suppression. For some warnings, this is just inherent in what the warning means, invalidating the assumption that a `@SuppressWarnings` annotation always fully "contains" the warnings it might apply to. For example, a `"this-escape"` warning is suppressed for a _field_ if every primary _constructor_ has `@SuppressWarnings("this-escape")`. This is of course because fields are initiailized when `super()` happens, so control flow jumps around. In the `"overloads"` case, there is logic to allow "either/or" of the methods to suppress the warning: in other words, the warning is referring to two different methods at the same time, so that brings the question, Which method's `@SuppressWarnings` annotation should apply? The code applies _both_ at the same time in a conservative fashion, meaning either method (or both) may suppress the warning. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2239953767 From mcimadamore at openjdk.org Tue Jul 29 18:16:01 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 29 Jul 2025 18:16:01 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Mon, 28 Jul 2025 22:05:44 GMT, Archie Cobbs wrote: >> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. >> >> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. >> >> In addition, several other factors complicate things: >> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any >> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) >> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) >> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled >> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings >> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags >> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. >> >> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". >> >> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Refactor LintMapper to clean up internal type hierarchy per review. src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 183: > 181: private class FileInfo { > 182: > 183: final MappedDeclNode rootNode = new MappedDeclNode(rootLint); // tree of this file's "interesting" declaration nodes I still find the design a bit odd here. We create an "empty" root node here, but then in the constructor we set up all its children. Maybe we should create the full "node" from the original `JCCompilationUnit` tree (in a single shot) ? Also, I can't quite figure out if we end up adding both a `Decl` and a `MappedDecl` as children of the same parent decl? Perhaps, if the only difference between mapped and non-mapped decl is that the former have a Lint object, just having a single decl class with a mutable Lint field that is only set once might work? Meta-comment -- I also realize how a lot of this could probably be avoided if we could just stash the Lint directly in the corresponding tree? (e.g. if we could do that, then we'd just need something to "find" the most specific tree given a position and see if it has a `Lint` set. We'd probably still need a map from source files to compilation unit trees) ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2240599648 From mcimadamore at openjdk.org Tue Jul 29 18:16:01 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Tue, 29 Jul 2025 18:16:01 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Tue, 29 Jul 2025 18:10:36 GMT, Maurizio Cimadamore wrote: >> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: >> >> Refactor LintMapper to clean up internal type hierarchy per review. > > src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 183: > >> 181: private class FileInfo { >> 182: >> 183: final MappedDeclNode rootNode = new MappedDeclNode(rootLint); // tree of this file's "interesting" declaration nodes > > I still find the design a bit odd here. We create an "empty" root node here, but then in the constructor we set up all its children. Maybe we should create the full "node" from the original `JCCompilationUnit` tree (in a single shot) ? Also, I can't quite figure out if we end up adding both a `Decl` and a `MappedDecl` as children of the same parent decl? Perhaps, if the only difference between mapped and non-mapped decl is that the former have a Lint object, just having a single decl class with a mutable Lint field that is only set once might work? > > Meta-comment -- I also realize how a lot of this could probably be avoided if we could just stash the Lint directly in the corresponding tree? (e.g. if we could do that, then we'd just need something to "find" the most specific tree given a position and see if it has a `Lint` set. We'd probably still need a map from source files to compilation unit trees) What I'm trying to say here is: having things in a side-map adds costs. Because, regardless of whether warnings are enabled or not, we're still going to add things to the `LintMapper` side-map. At which point it might be "cheaper" (memory-wise) to just add a field to the tree, and not having to "replicate" a tree-like structure inside `LintMapper` ? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2240604282 From acobbs at openjdk.org Tue Jul 29 18:48:02 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 29 Jul 2025 18:48:02 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Tue, 29 Jul 2025 18:12:53 GMT, Maurizio Cimadamore wrote: > What I'm trying to say here is: having things in a side-map adds costs. Because, regardless of whether warnings are enabled or not, we're still going to add things to the `LintMapper` side-map. At which point it might be "cheaper" (memory-wise) to just add a field to the tree, and not having to "replicate" a tree-like structure inside `LintMapper` ? Remember that the tree of nodes that `LintMapper` builds is sparse - nodes are only created for (a) top-level declarations and (b) nested declarations for which the effective `Lint` is different from the parent, i.e., nested declarations that actually have a material `@SuppressWarnings` annotation. > I still find the design a bit odd here. We create an "empty" root node here, but then in the constructor we set up all its children. Maybe we should create the full "node" from the original `JCCompilationUnit` tree (in a single shot) ? Also, I can't quite figure out if we end up adding both a `Decl` and a `MappedDecl` as children of the same parent decl? This is a side-effect of the fact that we need to always create `Decl` nodes for top-level declarations, but for nested declarations we only create them when/if needed, and when we do they are already `MappedDecl` nodes. So the top-level declaration nodes just under root are "special". They are the only nodes that are ever `Decl` (not-yet-mapped) nodes before transitioning to `MappedDecl` nodes. > Perhaps, if the only difference between mapped and non-mapped decl is that the former have a Lint object, just having a single decl class with a mutable Lint field that is only set once might work? Given the above, let me know what you think is most appropriate. There are basically three types of nodes: root, non-mapped (top-level only), and mapped. The second type converts from non-mapped to mapped when the declaration is attributed. > Meta-comment -- I also realize how a lot of this could probably be avoided if we could just stash the Lint directly in the corresponding tree? (e.g. if we could do that, then we'd just need something to "find" the most specific tree given a position and see if it has a Lint set. We'd probably still need a map from source files to compilation unit trees) The difficulty in the "finding" is the problem with that idea. Also you'd have to recurse through every node in the AST tree, instead of just the `@SuppressWarnings`-annotated declarations. Right now the "finding" is fast because the tree is sparse. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2240671907 From acobbs at openjdk.org Tue Jul 29 21:39:47 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 29 Jul 2025 21:39:47 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v6] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: More refactoring to simplify LintMapper per review. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/24584/files - new: https://git.openjdk.org/jdk/pull/24584/files/f65e1950..147cb2dc Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=05 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=04-05 Stats: 86 lines in 1 file changed: 15 ins; 28 del; 43 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From acobbs at openjdk.org Tue Jul 29 21:39:48 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Tue, 29 Jul 2025 21:39:48 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Tue, 29 Jul 2025 18:45:16 GMT, Archie Cobbs wrote: >> What I'm trying to say here is: having things in a side-map adds costs. Because, regardless of whether warnings are enabled or not, we're still going to add things to the `LintMapper` side-map. At which point it might be "cheaper" (memory-wise) to just add a field to the tree, and not having to "replicate" a tree-like structure inside `LintMapper` ? > >> What I'm trying to say here is: having things in a side-map adds costs. Because, regardless of whether warnings are enabled or not, we're still going to add things to the `LintMapper` side-map. At which point it might be "cheaper" (memory-wise) to just add a field to the tree, and not having to "replicate" a tree-like structure inside `LintMapper` ? > > Remember that the tree of nodes that `LintMapper` builds is sparse - nodes are only created for (a) top-level declarations and (b) nested declarations for which the effective `Lint` is different from the parent, i.e., nested declarations that actually have a material `@SuppressWarnings` annotation. > >> I still find the design a bit odd here. We create an "empty" root node here, but then in the constructor we set up all its children. Maybe we should create the full "node" from the original `JCCompilationUnit` tree (in a single shot) ? Also, I can't quite figure out if we end up adding both a `Decl` and a `MappedDecl` as children of the same parent decl? > > This is a side-effect of the fact that we need to always create `Decl` nodes for top-level declarations, but for nested declarations we only create them when/if needed, and when we do they are already `MappedDecl` nodes. > > So the top-level declaration nodes just under root are "special". They are the only nodes that are ever `Decl` (not-yet-mapped) nodes before transitioning to `MappedDecl` nodes. > >> Perhaps, if the only difference between mapped and non-mapped decl is that the former have a Lint object, just having a single decl class with a mutable Lint field that is only set once might work? > > Given the above, let me know what you think is most appropriate. There are basically three types of nodes: root, non-mapped (top-level only), and mapped. The second type converts from non-mapped to mapped when the declaration is attributed. > >> Meta-comment -- I also realize how a lot of this could probably be avoided if we could just stash the Lint directly in the corresponding tree? (e.g. if we could do that, then we'd just need something to "find" the most specific tree given a position and see if it has a Lint set. We'd probably still need a map from source files to compilation unit trees) > > The difficulty in the "finding" is the problem with that idea. Also you'd have to recurse through every node in the AST tree, instead of just the `@SuppressWarnings`-annotated declarations. Right now the "finding" is fast because the tree is sparse. By the way, I have to agree with you that the code in `LintMapper` is still more confusing than necessary. I've done another pass to clean it up; please see if 147cb2dc30a looks better. Thanks. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2241067770 From mcimadamore at openjdk.org Wed Jul 30 11:59:57 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 30 Jul 2025 11:59:57 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Tue, 29 Jul 2025 21:36:32 GMT, Archie Cobbs wrote: >>> What I'm trying to say here is: having things in a side-map adds costs. Because, regardless of whether warnings are enabled or not, we're still going to add things to the `LintMapper` side-map. At which point it might be "cheaper" (memory-wise) to just add a field to the tree, and not having to "replicate" a tree-like structure inside `LintMapper` ? >> >> Remember that the tree of nodes that `LintMapper` builds is sparse - nodes are only created for (a) top-level declarations and (b) nested declarations for which the effective `Lint` is different from the parent, i.e., nested declarations that actually have a material `@SuppressWarnings` annotation. >> >>> I still find the design a bit odd here. We create an "empty" root node here, but then in the constructor we set up all its children. Maybe we should create the full "node" from the original `JCCompilationUnit` tree (in a single shot) ? Also, I can't quite figure out if we end up adding both a `Decl` and a `MappedDecl` as children of the same parent decl? >> >> This is a side-effect of the fact that we need to always create `Decl` nodes for top-level declarations, but for nested declarations we only create them when/if needed, and when we do they are already `MappedDecl` nodes. >> >> So the top-level declaration nodes just under root are "special". They are the only nodes that are ever `Decl` (not-yet-mapped) nodes before transitioning to `MappedDecl` nodes. >> >>> Perhaps, if the only difference between mapped and non-mapped decl is that the former have a Lint object, just having a single decl class with a mutable Lint field that is only set once might work? >> >> Given the above, let me know what you think is most appropriate. There are basically three types of nodes: root, non-mapped (top-level only), and mapped. The second type converts from non-mapped to mapped when the declaration is attributed. >> >>> Meta-comment -- I also realize how a lot of this could probably be avoided if we could just stash the Lint directly in the corresponding tree? (e.g. if we could do that, then we'd just need something to "find" the most specific tree given a position and see if it has a Lint set. We'd probably still need a map from source files to compilation unit trees) >> >> The difficulty in the "finding" is the problem with that idea. Also you'd have to recurse through every node in the AST tree, instead of just the `@SuppressWarnings`-annotated declarations. Right now the "finding" is fast because the tree is sparse. > > By the way, I have to agree with you that the code in `LintMapper` is still more confusing than necessary. > > I've done another pass to clean it up; please see if 147cb2dc30a looks better. Thanks. Thanks for the comments -- mapped declarations are indeed sparse as you point out, and this might simplify the "position matching" process. However, the unmapped declarations are not sparse. It is true that, after Attr, we will go through the list of unmapped decls and remove them as we map them. But, after parsing the list of unmapped declaration does seem a copy of an AST. Say you kept _mapped_ declaration as they are now. Can the list of _unmapped_ declaration just be replaced by the compilation unit tree? Or, maybe, a "list of declaration trees" to analyze? It is unclear to me what added value the unmapped data structure has compared to just an AST node. The only thing it adds are the "contains" methods -- which could be implemented as static methods in TreeInfo perhaps? Also, I don't get the subclassing between `Decl` and `MappedDecl`. They seem to serve quite different purposes -- the former is essentially a *flat* "todo list", whereas the latter is a proper tree-based representation, with parent/child edges. I'm not even sure any client can call methods on a `Decl` when in reality the object could be a `MappedDecl` ? My concrete suggestion here would be to: * either just remove `Decl` and use `JCTree`s instead (and put `contains` methods in `TreeInfo`, as they might be useful), or create a small record around `JCTree` (and define `contains` methods in that record). * when we create a `FileInfo`, we already know, from the start, what the list of "todo" trees/decls are * then we have mapped declarations; here you have a node that can have many children nodes, using some kind of "delta encoding" (e.g. a child is there only if its lint is different and interesting, otherwise we just use the parent). I think the current class you have (`MappedDecl`) + the builder/scanner you have works well here. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2242389055 From mcimadamore at openjdk.org Wed Jul 30 11:59:58 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 30 Jul 2025 11:59:58 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v6] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: <6B6ZvvizIU9sR8xOEJjSF_5U20vzeas9PbUtE7GPbK8=.c619d6c6-ab51-4128-87ce-f36385a1fd2f@github.com> On Tue, 29 Jul 2025 21:39:47 GMT, Archie Cobbs wrote: >> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. >> >> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. >> >> In addition, several other factors complicate things: >> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any >> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) >> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) >> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled >> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings >> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags >> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. >> >> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". >> >> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > More refactoring to simplify LintMapper per review. src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 356: > 354: > 355: // If this declaration is not "interesting", we don't need to create a MappedDecl for it > 356: if (lint == previousLint && parent.parent != null) { Does this mean we create a mapped decl for all toplevel decls in a file (even if their `lint` is not interesting) ? Why? ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2242392260 From acobbs at openjdk.org Wed Jul 30 15:54:45 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 30 Jul 2025 15:54:45 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v7] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: More simplification of LintMapper per review suggestions. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/24584/files - new: https://git.openjdk.org/jdk/pull/24584/files/147cb2dc..6a1289e9 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=06 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=05-06 Stats: 114 lines in 2 files changed: 27 ins; 35 del; 52 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From acobbs at openjdk.org Wed Jul 30 15:54:45 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 30 Jul 2025 15:54:45 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Wed, 30 Jul 2025 11:56:32 GMT, Maurizio Cimadamore wrote: > Thanks for the comments -- mapped declarations are indeed sparse as you point out, and this might simplify the "position matching" process. However, the unmapped declarations are not sparse. There number of unmapped declarations equals the number of top-level class, package, or module declarations. I'm describing this as "sparse" because it does not include any methods, variables or nested classes. But of course if you're considering only top-level declarations then it's not "sparse" with respect to just that set. > It is true that, after Attr, we will go through the list of unmapped decls and remove them as we map them. But, after parsing the list of unmapped declaration does seem a copy of an AST. It's only a copy of the AST to a depth of one... so really a list, not a tree... but regardless, I think you have a good point (see below)... > Say you kept _mapped_ declaration as they are now. Can the list of _unmapped_ declaration just be replaced by the compilation unit tree? Or, maybe, a "list of declaration trees" to analyze? To restate your question: What value does storing a list of `Decl`'s provide over just storing a list of the corresponding original `JCTree` objects? There are two reasons I did this: 1. If we just store the `JCTree`'s, then we also must retain a reference to every source file's `EndPosTable` (it's required by `MappedDeclBuilder`), which I was trying to avoid because, at least in some cases (depending on compiler configuration), those tables are (otherwise) discarded after parsing. So the new references to `EndPosTable` will increase compiler memory usage. But I may have been overreacting or misunderstanding that. 2. This is a minor detail, but the `JCTree` we see after parsing is not always the same `JCTree` we see after attribution (not sure why; it happens in test method `EdgeCases.testWrongPackageInExportedPackage()` for some reason). So even if we store the trees, we still have to compare them by position, not object equality, so in effect it's really the position we care about, not the tree... > Does this mean we create a mapped decl for all toplevel decls in a file (even if their lint is not interesting) ? Why? Yes, but! That special case is no longer required with the recent cleanups, so now we can fix this too :) > My concrete suggestion here would be to... Thanks, this makes things simpler and cleaner. Should all be done in 6a1289e9372. Thanks again for your thoughtful review and comments! ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2243146877 From mcimadamore at openjdk.org Wed Jul 30 17:01:57 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 30 Jul 2025 17:01:57 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v5] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Wed, 30 Jul 2025 15:51:27 GMT, Archie Cobbs wrote: >> Thanks for the comments -- mapped declarations are indeed sparse as you point out, and this might simplify the "position matching" process. However, the unmapped declarations are not sparse. It is true that, after Attr, we will go through the list of unmapped decls and remove them as we map them. But, after parsing the list of unmapped declaration does seem a copy of an AST. >> >> Say you kept _mapped_ declaration as they are now. Can the list of _unmapped_ declaration just be replaced by the compilation unit tree? Or, maybe, a "list of declaration trees" to analyze? It is unclear to me what added value the unmapped data structure has compared to just an AST node. The only thing it adds are the "contains" methods -- which could be implemented as static methods in TreeInfo perhaps? >> >> Also, I don't get the subclassing between `Decl` and `MappedDecl`. They seem to serve quite different purposes -- the former is essentially a *flat* "todo list", whereas the latter is a proper tree-based representation, with parent/child edges. I'm not even sure any client can call methods on a `Decl` when in reality the object could be a `MappedDecl` ? >> >> My concrete suggestion here would be to: >> >> * either just remove `Decl` and use `JCTree`s instead (and put `contains` methods in `TreeInfo`, as they might be useful), or create a small record around `JCTree` (and define `contains` methods in that record). >> * when we create a `FileInfo`, we already know, from the start, what the list of "todo" trees/decls are >> * then we have mapped declarations; here you have a node that can have many children nodes, using some kind of "delta encoding" (e.g. a child is there only if its lint is different and interesting, otherwise we just use the parent). I think the current class you have (`MappedDecl`) + the builder/scanner you have works well here. > >> Thanks for the comments -- mapped declarations are indeed sparse as you point out, and this might simplify the "position matching" process. However, the unmapped declarations are not sparse. > > There number of unmapped declarations equals the number of top-level class, package, or module declarations. I'm describing this as "sparse" because it does not include any methods, variables or nested classes. But of course if you're considering only top-level declarations then it's not "sparse" with respect to just that set. > >> It is true that, after Attr, we will go through the list of unmapped decls and remove them as we map them. But, after parsing the list of unmapped declaration does seem a copy of an AST. > > It's only a copy of the AST to a depth of one... so really a list, not a tree... but regardless, I think you have a good point (see below)... > >> Say you kept _mapped_ declaration as they are now. Can the list of _unmapped_ declaration just be replaced by the compilation unit tree? Or, maybe, a "list of declaration trees" to analyze? > > To restate your question: What value does storing a list of `Decl`'s provide over just storing a list of the corresponding original `JCTree` objects? There are two reasons I did this: > 1. If we just store the `JCTree`'s, then we also must retain a reference to every source file's `EndPosTable` (it's required by `MappedDeclBuilder`), which I was trying to avoid because, at least in some cases (depending on compiler configuration), those tables are (otherwise) discarded after parsing. So the new references to `EndPosTable` will increase compiler memory usage. But I may have been overreacting or misunderstanding that. > 2. This is a minor detail, but the `JCTree` we see after parsing is not always the same `JCTree` we see after attribution (not sure why; it happens in test method `EdgeCases.testWrongPackageInExportedPackage()` for some reason). So even if we store the trees, we still have to compare them by position, not object equality, so in effect it's really the position we care about, not the tree... > >> Does this mean we create a mapped decl for all toplevel decls in a file (even if their lint is not interesting) ? Why? > > Yes, but! That special case is no longer required with the recent cleanups, so now we can fix this too :) > >> My concrete suggestion here would be to... > > Thanks, this makes things simpler and cleaner. Should all be done in 6a1289e9372. > > Thanks again for your thoughtful review and comments! The new code looks clearer to follow. What we really want is: * first, capture only the "spans" of toplevel declarations * then, after attr, organize all these spans into some kind of tree structure that optimizes the search If you are worried about holding onto the end pos table too long (I don't have strong opinion on this), I'm ok with using some kind of "span" class to model... a span -- but that class should be completely disconnected from the `MappedDecl` class (which was really my main point). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2243339408 From mcimadamore at openjdk.org Wed Jul 30 17:06:58 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 30 Jul 2025 17:06:58 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v7] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Wed, 30 Jul 2025 15:54:45 GMT, Archie Cobbs wrote: >> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. >> >> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. >> >> In addition, several other factors complicate things: >> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any >> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) >> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) >> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled >> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings >> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags >> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. >> >> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". >> >> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > More simplification of LintMapper per review suggestions. src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 242: > 240: private static class MappedDecl { > 241: > 242: final int startPos; // declaration's lexical starting position Better idea. Have a record class called `Span` which has start/end pos. Then, in `FileInfo` we keep track of a list of these `Span`s. And, after attr, we "add" each span to the MappedDecl structure. The MappedDecl class will have itself a little Span object inside which can be used for all the positional queries. E.g. use delegation/aggregation, instead of subtyping (as, after all, a `MappedDecl` is really not a span -- but has a span). ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2243351077 From mcimadamore at openjdk.org Wed Jul 30 17:13:03 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 30 Jul 2025 17:13:03 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v7] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Wed, 30 Jul 2025 15:54:45 GMT, Archie Cobbs wrote: >> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. >> >> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. >> >> In addition, several other factors complicate things: >> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any >> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) >> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) >> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled >> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings >> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags >> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. >> >> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". >> >> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > More simplification of LintMapper per review suggestions. src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java line 299: > 297: * The tree is sparse: only declarations that differ from their parent are included. > 298: */ > 299: private static class MappedDeclBuilder extends TreeScanner { Another (maybe picky) comment: to my eyes, `MappedDeclBuilder` is really a mutable data structure. It has operations to find nodes, but it doesn't provide operation to _add_ new nodes. Instead the _add_ operation is delegated to this builder class. Now, I totally understand that the process of adding a new entry to `MappedDecl` is complex, and you need to scan a tree to get there. That's all good. But I think you do want an `add(Span, JCTree)` to `MappedDecl` which can then be used inside `FileInfo::afterAttr`. The fact that the implementation of this `add` method is defined in terms of a tree scanner is an impl detail that doesn't need to be known outside the `add` method (and you can in fact turn the scanner into a local class, and then have the visitor create a new scanner, and process the provided tree with it. This should encapsulate the data structure modelled by `MappedDecl` even more. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2243364077 From acobbs at openjdk.org Wed Jul 30 20:39:46 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 30 Jul 2025 20:39:46 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v8] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: More simplification of LintMapper per review suggestions. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/24584/files - new: https://git.openjdk.org/jdk/pull/24584/files/6a1289e9..d1adde49 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=07 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=06-07 Stats: 177 lines in 2 files changed: 40 ins; 70 del; 67 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From acobbs at openjdk.org Wed Jul 30 20:39:48 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 30 Jul 2025 20:39:48 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v7] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: <8rEIxvjnKLeh1hdXLpOYsuOijDmHp_9gkXzoHQXPdXY=.47a1091b-4899-436e-b98f-3a948447f525@github.com> On Wed, 30 Jul 2025 17:04:18 GMT, Maurizio Cimadamore wrote: > Better idea. Have a record class called `Span` which has start/end pos. Then... Yeah that's a little more correct in terms of the data model. > Another (maybe picky) comment: to my eyes... Sure, that's easy enough to do. Also allows us to eliminate a couple more fields. Should be done in d1adde49247. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24584#discussion_r2243808019 From acobbs at openjdk.org Wed Jul 30 21:03:45 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 30 Jul 2025 21:03:45 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v9] In-Reply-To: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: > This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. > > A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. > > In addition, several other factors complicate things: > * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any > * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) > * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) > * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled > * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings > * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags > * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. > > Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". > > The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: Remove an unnecessary field. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/24584/files - new: https://git.openjdk.org/jdk/pull/24584/files/d1adde49..7fca4a05 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=08 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=24584&range=07-08 Stats: 18 lines in 1 file changed: 2 ins; 7 del; 9 mod Patch: https://git.openjdk.org/jdk/pull/24584.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/24584/head:pull/24584 PR: https://git.openjdk.org/jdk/pull/24584 From mcimadamore at openjdk.org Wed Jul 30 21:18:00 2025 From: mcimadamore at openjdk.org (Maurizio Cimadamore) Date: Wed, 30 Jul 2025 21:18:00 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v9] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: <1mzpiGo4BSwuqjOfUFTT6SiwHbXohMkOkUTIfT0gVIk=.23692b9c-3aa7-4870-b5b0-4c1c1d4424e2@github.com> On Wed, 30 Jul 2025 21:03:45 GMT, Archie Cobbs wrote: >> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. >> >> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. >> >> In addition, several other factors complicate things: >> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any >> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) >> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) >> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled >> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings >> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags >> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. >> >> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". >> >> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Remove an unnecessary field. Thanks for addressing all my comments, I like the last version a lot. I consider this PR approved, but I'll bump the reviewer number to 2, so that others (@lahodaj ?) can take a look. ------------- Marked as reviewed by mcimadamore (Reviewer). PR Review: https://git.openjdk.org/jdk/pull/24584#pullrequestreview-3073360528 From acobbs at openjdk.org Wed Jul 30 21:21:58 2025 From: acobbs at openjdk.org (Archie Cobbs) Date: Wed, 30 Jul 2025 21:21:58 GMT Subject: RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v9] In-Reply-To: References: <08zj2WBmFFeEQbGegExwyGLIDLQV71_TmkqDA4lYad8=.50f5befe-7d49-4865-92e8-fcbbf1f5ea32@github.com> Message-ID: On Wed, 30 Jul 2025 21:03:45 GMT, Archie Cobbs wrote: >> This is a cleanup/refactoring of how lint warnings are logged and `@SuppressWarnings` annotations applied. >> >> A central challenge with lint warnings is that warnings can be generated during any compiler phase, but whether a particular lint warning is suppressed via `@SuppressWarnings` can't be known until after attribution. For example, the parser doesn't have enough information to interpret and apply `@SuppressWarnings("text-blocks")` to text blocks, or `@SuppressWarnings("preview")` to preview lexical features; instead, the `DeferredLintHandler` is used to workaround this limitation. >> >> In addition, several other factors complicate things: >> * Knowing the current applicable `Lint` instance requires manually tracking it with each declaration visited and applying/removing the `@SuppressWarnings` annotation there, if any >> * Some warnings are "suppressibly mandatory" (i.e., they are _emitted if not suppressed_ instead of _emitted if enabled_) >> * Some warnings are "unsuppressibly mandatory" (e.g., the "internal proprietary API" warning) >> * Some mandatory warnings are _aggregated_ into notes that are emitted at the end of compilation when not enabled >> * Some warnings are _lint_ warnings, with a corresponding lint category, while others are just "plain" warnings >> * Some lint warnings are suppressible via `@SuppressWarnings`, while others are only suppressible via `-Xlint:-foo` flags >> * Speculative compilation requires holding log messages in purgatory until the speculation resolves, after which they are then either discarded or emitted. But this creates a tricky interaction with `DeferredLintHandler` because even after speculation is complete, we may still not yet know whether a warning should be suppressed. >> >> Previously the logic to get all of this right was non-obviously woven around the code base. In particular, you needed to know somehow whether or not to use `DeferredLintHandler`, and in what "mode". >> >> The overall goal of this PR is to simplify usage so that **no matter where you are in the compiler, you can just invoke `log.warning()` to log a warning** and (mostly) forget about all of the details listed above. > > Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision: > > Remove an unnecessary field. Thanks for your review and all the help along the way :) ------------- PR Comment: https://git.openjdk.org/jdk/pull/24584#issuecomment-3137850459