a change in javac behavior
forax at univ-mlv.fr
forax at univ-mlv.fr
Mon Dec 18 06:39:45 UTC 2023
> From: "Alan Snyder" <javalists at cbfiddle.com>
> To: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "compiler-dev" <compiler-dev at openjdk.org>
> Sent: Sunday, December 17, 2023 9:03:14 PM
> Subject: Re: a change in javac behavior
> So, that is how things are supposed to work?
Yes,
> Also, can you explain why javac does not complain about the builder.perform()
> invocation?
> That variable is declared using the disputed parameter declaration.
> If the parameter type is taken to be Thread.Builder, the call to perform should
> be rejected.
Hard to say without the whole code but if your original error comes from the same file, it may mask the error at builder.perform(), javac does several passes on the same code.
regards,
Rémi
>> On Dec 17, 2023, at 9:56 AM, Remi Forax <forax at univ-mlv.fr> wrote:
>>> From: "Alan Snyder" <javalists at cbfiddle.com>
>>> To: "compiler-dev" <compiler-dev at openjdk.org>
>>> Sent: Sunday, December 17, 2023 5:48:15 PM
>>> Subject: a change in javac behavior
>>> I’m experiencing a change in behavior compiling a particular file.
>>> The compiler is trying to match an invocation to one of two constructors for a
>>> static class defined in the same file.
>>> The second constructor has a parameter of type Builder. In the past, this was
>>> interpreted as my Builder class, which is imported into this file.
>>> That matches the invocation.
>>> Now, however, the constructor parameter type is interpreted as
>>> java.lang.Thread.Builder, presumably because the static class extends Thread.
>>> That causes a mismatch to be reported.
>>> This interpretation appears to be limited to the resolution of the constructor
>>> invocation. Within the constructor, I do not get an error when the parameter
>>> is used as an instance of my Builder class.
>>> This happens in JDK 20, JDK 21, and the latest build of JDK 22.
>>> It does not happen in JDK 17.
>> I believe this is not a behavior change, you are experiencing the "comb"
>> behavior, where javac will first start to match members declared inside the
>> class hierarchy before trying to match other members.
>> Here is the classical example
>> class Foo {
>> String name;
>> void setName(String name) {
>> this.name = name;
>> }
>> public void execute() {
>> new Thread() {
>> public void run() {
>> setName("foo");
>> }
>> }.start();
>> }
>> }
>> where the method setName() inside execute() calls Thread.setName() instead of
>> Foo.setName().
>> You code compiles with JDK 17 because Thread.Builder was introduced in 21 (19 as
>> preview).
>> If you want to avoid those kind of issues, prefer delegation to inheritance.
>>> The error message:
>>> [javac] constructor Worker.Worker(@org.jetbrains.annotations.NotNull
>>> String, at org.jetbrains.annotations.NotNull
>>> SeverityLevel, at org.jetbrains.annotations.NotNull
>>> java.lang.Thread.Builder, at org.jetbrains.annotations.Nullable
>>> TaskStatusListener, at org.jetbrains.annotations.NotNull
>>> SimpleTaskReceiver<BuildResult>) is not applicable
>>> [javac] (argument mismatch; @org.jetbrains.annotations.NotNull
>>> com.cbfiddle.releases.Builder cannot be converted to
>>> @org.jetbrains.annotations.NotNull java.lang.Thread.Builder)
>>> The constructor:
>>> public Worker ( @NotNull String taskName ,
>>> @NotNull SeverityLevel level ,
>>> @NotNull Builder builder ,
>>> @Nullable TaskStatusListener tsl ,
>>> @NotNull SimpleTaskReceiver < BuildResult > r )
>>> {
>>> this . taskName = taskName ;
>>> this . level = level ;
>>> this . r = r ;
>>> this . bl = createBuildListener( tsl ) ;
>>> this . op = () -> builder .perform( bl ) ;
>>> setPriority( Thread . MIN_PRIORITY ) ;
>>> }
>> regards,
>> Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20231218/246fd990/attachment.htm>
More information about the compiler-dev
mailing list