Skip to content

Commit a73d012

Browse files
author
Vicente Romero
committedFeb 7, 2023
8295019: Cannot call a method with a parameter of a local class declared in a lambda
Reviewed-by: mcimadamore
1 parent 4fe99da commit a73d012

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed
 

‎src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -464,10 +464,29 @@ JCLambda attribSpeculativeLambda(JCLambda that, Env<AttrContext> env, ResultInfo
464464
* disabled during speculative type-checking.
465465
*/
466466
JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
467+
/* When performing speculative attribution on an argument expression, we should make sure that argument type
468+
* cache does not get polluted with local types, as that leads to spurious type errors (see JDK-8295019)
469+
*/
467470
return attribSpeculative(tree, env, resultInfo, treeCopier,
468-
null, AttributionMode.SPECULATIVE, null);
471+
null, AttributionMode.SPECULATIVE, !hasTypeDeclaration(tree) ? null : argumentAttr.withLocalCacheContext());
469472
}
470473

474+
// where
475+
private boolean hasTypeDeclaration(JCTree tree) {
476+
TypeDeclVisitor typeDeclVisitor = new TypeDeclVisitor();
477+
typeDeclVisitor.scan(tree);
478+
return typeDeclVisitor.result;
479+
}
480+
481+
private static class TypeDeclVisitor extends TreeScanner {
482+
boolean result = false;
483+
484+
@Override
485+
public void visitClassDef(JCClassDecl that) {
486+
result = true;
487+
}
488+
}
489+
471490
JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo, LocalCacheContext localCache) {
472491
return attribSpeculative(tree, env, resultInfo, treeCopier,
473492
null, AttributionMode.SPECULATIVE, localCache);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8295019
27+
* @summary Cannot call a method with a parameter of a local class declared in a lambda
28+
* @compile TypeDeclarationInsideExpressionTest.java
29+
*/
30+
31+
class TypeDeclarationInsideExpressionTest {
32+
class LambdaTest {
33+
void run(Runnable r) {}
34+
35+
void m() {
36+
run(() -> {
37+
class C {
38+
static void takeC(C c) {}
39+
static C giveC() {
40+
return null;
41+
}
42+
}
43+
C.takeC(C.giveC());
44+
45+
record R() {
46+
static void takeR(R r) {}
47+
static R giveR() { return null; }
48+
}
49+
R.takeR(R.giveR());
50+
51+
interface I {
52+
static void takeI(I i) {}
53+
static I giveI() { return null; }
54+
}
55+
I.takeI(I.giveI());
56+
57+
enum E {
58+
A;
59+
static void takeE(E e) {}
60+
static E giveE() { return null; }
61+
}
62+
E.takeE(E.giveE());
63+
});
64+
}
65+
}
66+
67+
class SwitchExprTest {
68+
void run(int i) {}
69+
void m(int o) {
70+
run(switch(o) {
71+
case 1 -> {
72+
class C {
73+
static int takeC(C c) { return 0; }
74+
static C giveC() { return null; }
75+
}
76+
yield C.takeC(C.giveC());
77+
}
78+
case 2 -> {
79+
record R() {
80+
static int takeR(R r) { return 0; }
81+
static R giveR() { return null; }
82+
}
83+
yield R.takeR(R.giveR());
84+
}
85+
case 3 -> {
86+
interface I {
87+
static int takeI(I i) { return 0; }
88+
static I giveI() { return null; }
89+
}
90+
yield I.takeI(I.giveI());
91+
}
92+
case 4 -> {
93+
enum E {
94+
A;
95+
static int takeE(E e) { return 0; }
96+
static E giveE() { return null; }
97+
}
98+
yield E.takeE(E.giveE());
99+
}
100+
default -> throw new AssertionError();
101+
});
102+
}
103+
}
104+
}

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Feb 7, 2023

@openjdk-notifier[bot]
Please sign in to comment.