Skip to content

Commit 8bd080b

Browse files
committedNov 19, 2024
8341901: Using 'var' keyword switch pattern matching causes compiler error
Reviewed-by: vromero, abimpoudis
1 parent 76a55c3 commit 8bd080b

File tree

3 files changed

+102
-4
lines changed

3 files changed

+102
-4
lines changed
 

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -4198,6 +4198,7 @@ public void visitBindingPattern(JCBindingPattern tree) {
41984198
if (chk.checkUnique(tree.var.pos(), v, env.info.scope)) {
41994199
chk.checkTransparentVar(tree.var.pos(), v, env.info.scope);
42004200
}
4201+
chk.validate(tree.var.vartype, env, true);
42014202
if (tree.var.isImplicitlyTyped()) {
42024203
setSyntheticVariableType(tree.var, type == Type.noType ? syms.errType
42034204
: type);
@@ -4207,7 +4208,6 @@ public void visitBindingPattern(JCBindingPattern tree) {
42074208
annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v, tree.var.pos());
42084209
}
42094210
annotate.flush();
4210-
chk.validate(tree.var.vartype, env, true);
42114211
result = tree.type;
42124212
if (v.isUnnamedVariable()) {
42134213
matchBindings = MatchBindingsComputer.EMPTY;

‎src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -738,12 +738,18 @@ public JCFieldAccess Select(JCExpression base, Symbol sym) {
738738
}
739739

740740
/** Create a qualified identifier from a symbol, adding enough qualifications
741-
* to make the reference unique.
741+
* to make the reference unique. The types in the AST nodes will be erased.
742742
*/
743743
public JCExpression QualIdent(Symbol sym) {
744-
return isUnqualifiable(sym)
744+
JCExpression result = isUnqualifiable(sym)
745745
? Ident(sym)
746746
: Select(QualIdent(sym.owner), sym);
747+
748+
if (sym.kind == TYP) {
749+
result.setType(types.erasure(sym.type));
750+
}
751+
752+
return result;
747753
}
748754

749755
/** Create an identifier that refers to the variable declared in given variable

‎test/langtools/tools/javac/patterns/BindingPatternVarTypeModel.java

+93-1
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,28 @@
2323

2424
/*
2525
* @test
26-
* @bug 8332725
26+
* @bug 8332725 8341901
2727
* @summary Verify the AST model works correctly for binding patterns with var
2828
*/
2929

3030
import com.sun.source.tree.BindingPatternTree;
3131
import com.sun.source.tree.CompilationUnitTree;
32+
import com.sun.source.tree.IdentifierTree;
33+
import com.sun.source.tree.MemberSelectTree;
3234
import com.sun.source.tree.Tree;
35+
import com.sun.source.tree.VariableTree;
3336
import com.sun.source.util.JavacTask;
37+
import com.sun.source.util.TreePathScanner;
3438
import com.sun.source.util.TreeScanner;
39+
import com.sun.source.util.Trees;
3540
import java.net.URI;
3641
import java.util.List;
3742
import java.util.concurrent.atomic.AtomicBoolean;
43+
import javax.lang.model.type.DeclaredType;
44+
import javax.lang.model.type.TypeKind;
45+
import javax.lang.model.type.TypeMirror;
46+
import javax.tools.Diagnostic;
47+
import javax.tools.DiagnosticListener;
3848
import javax.tools.JavaCompiler;
3949
import javax.tools.JavaFileObject;
4050
import javax.tools.SimpleJavaFileObject;
@@ -45,6 +55,7 @@ public class BindingPatternVarTypeModel {
4555

4656
public static void main(String... args) throws Exception {
4757
new BindingPatternVarTypeModel().run();
58+
new BindingPatternVarTypeModel().runVarParameterized();
4859
}
4960

5061
private void run() throws Exception {
@@ -86,4 +97,85 @@ public Void visitBindingPattern(BindingPatternTree node, Void p) {
8697
throw new AssertionError("Didn't find the binding pattern!");
8798
}
8899
}
100+
101+
private void runVarParameterized() throws Exception {
102+
JavaFileObject input =
103+
SimpleJavaFileObject.forSource(URI.create("mem:///Test.java"),
104+
"""
105+
package test;
106+
public class Test {
107+
record R(N.I i) {}
108+
int test(Object o) {
109+
Test.N.I checkType0 = null;
110+
var checkType1 = checkType0;
111+
return switch (o) {
112+
case R(var checkType2) -> 0;
113+
default -> 0;
114+
};
115+
}
116+
static class N<T> {
117+
interface I {}
118+
}
119+
}
120+
""");
121+
DiagnosticListener<JavaFileObject> noErrors = d -> {
122+
if (d.getKind() == Diagnostic.Kind.ERROR) {
123+
throw new IllegalStateException(d.toString());
124+
}
125+
};
126+
JavacTask task =
127+
(JavacTask) compiler.getTask(null, null, noErrors, null, null, List.of(input));
128+
CompilationUnitTree cut = task.parse().iterator().next();
129+
Trees trees = Trees.instance(task);
130+
131+
task.analyze();
132+
133+
new TreePathScanner<Void, Void>() {
134+
private boolean checkAttributes;
135+
@Override
136+
public Void visitVariable(VariableTree node, Void p) {
137+
boolean prevCheckAttributes = checkAttributes;
138+
try {
139+
checkAttributes |=
140+
node.getName().toString().startsWith("checkType");
141+
return super.visitVariable(node, p);
142+
} finally {
143+
checkAttributes = prevCheckAttributes;
144+
}
145+
}
146+
147+
@Override
148+
public Void visitIdentifier(IdentifierTree node, Void p) {
149+
checkType();
150+
return super.visitIdentifier(node, p);
151+
}
152+
153+
@Override
154+
public Void visitMemberSelect(MemberSelectTree node, Void p) {
155+
checkType();
156+
return super.visitMemberSelect(node, p);
157+
}
158+
159+
private void checkType() {
160+
if (!checkAttributes) {
161+
return ;
162+
}
163+
164+
TypeMirror type = trees.getTypeMirror(getCurrentPath());
165+
166+
if (type.getKind() == TypeKind.PACKAGE) {
167+
return ; //OK
168+
}
169+
if (type.getKind() != TypeKind.DECLARED) {
170+
throw new AssertionError("Expected a declared type, but got: " +
171+
type.getKind());
172+
}
173+
174+
if (!((DeclaredType) type).getTypeArguments().isEmpty()) {
175+
throw new AssertionError("Unexpected type arguments: " +
176+
((DeclaredType) type).getTypeArguments());
177+
}
178+
}
179+
}.scan(cut, null);
180+
}
89181
}

0 commit comments

Comments
 (0)
Please sign in to comment.