RFR: 8348611: Eliminate DeferredLintHandler and emit warnings after attribution [v11]

Jan Lahoda jlahoda at openjdk.org
Mon Sep 22 06:35:37 UTC 2025


On Thu, 14 Aug 2025 04:00:12 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.
>
> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Remove unused field from "LintRange" record.

I am afraid I need to be even more strict: internal "APIs" are not supported, and are not kept stable. Any use of such "APIs" is not recommended, and it is solely up to the user to handle any updates/changes.

My wild guess here is that openrewrite tries to suppress diagnostics (so that it can attribute the template without producing anything), but that fails for some reason (although I admit I don't immediately see the reason). It is hard to say, as the code simply ignores all exceptions:
https://github.com/openrewrite/rewrite-templating/blob/02cc7b03b9ef8eea0c609866bf0788d08731deb6/src/main/java/org/openrewrite/java/template/internal/CompilerMessageSuppressor.java#L127
And since this PR moves the warning reporting a to later point, it appears to work after this PR.

Also, for completeness, code like this:
https://github.com/openrewrite/rewrite-templating/blob/02cc7b03b9ef8eea0c609866bf0788d08731deb6/src/main/java/org/openrewrite/java/template/processor/TypeAwareProcessor.java#L138
is basically guaranteed to stop working at some point:
https://openjdk.org/jeps/498

-------------

PR Comment: https://git.openjdk.org/jdk/pull/24584#issuecomment-3317172398


More information about the compiler-dev mailing list