RFR: 8348427: DeferredLintHandler API should use JCTree instead of DiagnosticPosition [v2]
Archie Cobbs
acobbs at openjdk.org
Fri Feb 7 00:25:10 UTC 2025
On Thu, 6 Feb 2025 22:10:57 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:
>>> > learn a little bit more about this. It looks like the only time immediate mode is used explicitly (i.e., other due to `DeferredLintHandler`'s default state) is when resolving imports ([here](https://github.com/openjdk/jdk/blob/89e5e7ab73472b7d02aac5b8b0c7e9f26db6ec32/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java#L368)). In that case, of course, there can be no enclosing `@SuppressWarnings` so that makes sense.
>>>
>>> Can we use a similar "flush" strategy ? E.g. make the warnings be part of an import declaration, and then process them as part of a flush? While it's good that you knocked one of the two usages off -- it's a bit sad to have this machinery "just" for one case.
>>>
>>> Separately, I wonder if warnings issued from import statements should be suppressible as well (perhaps piggy backing on the toplevel class `@SuppressWarnings` uhmmm). It seems bad that there's some warnings that can't be suppressed programmatically.
>>
>> I think it would be useful to understand which warnings can be generated during `resolveImports`. @jddarcy pointed me at:
>>
>> https://openjdk.org/jeps/211
>>
>> See related change:
>>
>> https://hg.openjdk.org/jdk9/jdk9/langtools/rev/82384454947c
>>
>> Where we explicitly disable deprecation warnings on import since 9. Is there any other?
>
>> > > learn a little bit more about this. It looks like the only time immediate mode is used explicitly (i.e., other due to `DeferredLintHandler`'s default state) is when resolving imports ([here](https://github.com/openjdk/jdk/blob/89e5e7ab73472b7d02aac5b8b0c7e9f26db6ec32/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java#L368)). In that case, of course, there can be no enclosing `@SuppressWarnings` so that makes sense.
>> >
>> >
>> > Can we use a similar "flush" strategy ? E.g. make the warnings be part of an import declaration, and then process them as part of a flush? While it's good that you knocked one of the two usages off -- it's a bit sad to have this machinery "just" for one case.
>> > Separately, I wonder if warnings issued from import statements should be suppressible as well (perhaps piggy backing on the toplevel class `@SuppressWarnings` uhmmm). It seems bad that there's some warnings that can't be suppressed programmatically.
>>
>> I think it would be useful to understand which warnings can be generated during `resolveImports`. @jddarcy pointed me at:
>>
>> https://openjdk.org/jeps/211
>>
>> See related change:
>>
>> https://hg.openjdk.org/jdk9/jdk9/langtools/rev/82384454947c
>>
>> Where we explicitly disable deprecation warnings on import since 9. Is there any other?
>
> If this was indeed the only possible case, there is a possible silver lining, because either warnings in imports are enabled (e.g. `--source 8`) in which case we can just report them immediately, as they can't be suppressed, or they are disabled (e.g. `--source >= 9`) in which case no warning should even be generated, period.
>
> But I'm sure reality is more complex than that :-)
Hi @mcimadamore,
Thanks for the review & comments!
> Can we use a similar "flush" strategy ? E.g. make the warnings be part of an import declaration, and then process them as part of a flush? While it's good that you knocked one of the two usages off -- it's a bit sad to have this machinery "just" for one case.
Agreed - it seems to be a result of mixing the ordering of attributing things and flushing the `DeferredLintHandler`. An example is this program:
import java.security.PolicySpi;
public class A {
@SuppressWarnings("deprecation")
private PolicySpi foo;
@SuppressWarnings("deprecation")
public void m() throws Exception {
A.class.newInstance();
}
}
If you comment out the one remaining `deferredLintHandler.pushImmediate()` invocation (in `TypeEnter.java`), then watch watch happens when compiling the above program, you'll see that `checkDeprecated()` is invoked twice for `PolicySpi`, and the first time (`other` = `unnamed package`) the current `Lint` instance is correct but the deferred instance is incorrect, and the second time (`other` = `A`) the reverse is true; when it's invoked for `newInstance()` (only once), the current instance is correct but the deferred instance is incorrect. So - all still very confusing to me.
"When to flush" is indeed a key issue for other reasons too. For example, it appears that `JCTree` nodes tend to randomly disappear after attribution (well, it only seems random to me so far), so that deferring warning analysis for too long can set you up for a `NullPointerException` chasing exercise. A simple example is in `Gen.genClass()` where all of a class' declarations are discarded after the classfile is generate (whether that matters depends on the compiler execution mode), and there are others which I'm still chasing down.
> I think it would be useful to understand which warnings can be generated during resolveImports. @jddarcy pointed me at: https://openjdk.org/jeps/211
I ran across this as well and accommodated it my prototype by effectively pretending there is a `@SuppressWarnings("deprecation", "removal", "preview")` on every `import` statement if source ≥ 9. This is possible because the `@SuppressWarning` analysis is a completely separate step.
> Separately, I wonder if warnings issued from import statements should be suppressible as well (perhaps piggy backing on the toplevel class `@SuppressWarnings` uhmmm). It seems bad that there's some warnings that can't be suppressed programmatically.
It would be nice if the compiler allowed `@SuppressWarnings` in more places. If/when it ever does, the proposed refactoring would hopefully make it easier to implement.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/23281#issuecomment-2641503897
More information about the compiler-dev
mailing list