RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution

Archie Cobbs acobbs at openjdk.org
Thu Jul 3 19:02:27 UTC 2025


On Thu, 10 Apr 2025 20:23:15 GMT, Archie Cobbs <acobbs at openjdk.org> 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


More information about the compiler-dev mailing list