mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-02 06:28:23 +00:00
8341901: Using 'var' keyword switch pattern matching causes compiler error
Reviewed-by: vromero, abimpoudis
This commit is contained in:
parent
76a55c3cb6
commit
8bd080bcc9
@ -4198,6 +4198,7 @@ public class Attr extends JCTree.Visitor {
|
||||
if (chk.checkUnique(tree.var.pos(), v, env.info.scope)) {
|
||||
chk.checkTransparentVar(tree.var.pos(), v, env.info.scope);
|
||||
}
|
||||
chk.validate(tree.var.vartype, env, true);
|
||||
if (tree.var.isImplicitlyTyped()) {
|
||||
setSyntheticVariableType(tree.var, type == Type.noType ? syms.errType
|
||||
: type);
|
||||
@ -4207,7 +4208,6 @@ public class Attr extends JCTree.Visitor {
|
||||
annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v, tree.var.pos());
|
||||
}
|
||||
annotate.flush();
|
||||
chk.validate(tree.var.vartype, env, true);
|
||||
result = tree.type;
|
||||
if (v.isUnnamedVariable()) {
|
||||
matchBindings = MatchBindingsComputer.EMPTY;
|
||||
|
||||
@ -738,12 +738,18 @@ public class TreeMaker implements JCTree.Factory {
|
||||
}
|
||||
|
||||
/** Create a qualified identifier from a symbol, adding enough qualifications
|
||||
* to make the reference unique.
|
||||
* to make the reference unique. The types in the AST nodes will be erased.
|
||||
*/
|
||||
public JCExpression QualIdent(Symbol sym) {
|
||||
return isUnqualifiable(sym)
|
||||
JCExpression result = isUnqualifiable(sym)
|
||||
? Ident(sym)
|
||||
: Select(QualIdent(sym.owner), sym);
|
||||
|
||||
if (sym.kind == TYP) {
|
||||
result.setType(types.erasure(sym.type));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Create an identifier that refers to the variable declared in given variable
|
||||
|
||||
@ -23,18 +23,28 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8332725
|
||||
* @bug 8332725 8341901
|
||||
* @summary Verify the AST model works correctly for binding patterns with var
|
||||
*/
|
||||
|
||||
import com.sun.source.tree.BindingPatternTree;
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.IdentifierTree;
|
||||
import com.sun.source.tree.MemberSelectTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.tree.VariableTree;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.TreePathScanner;
|
||||
import com.sun.source.util.TreeScanner;
|
||||
import com.sun.source.util.Trees;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.lang.model.type.DeclaredType;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.DiagnosticListener;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
@ -45,6 +55,7 @@ public class BindingPatternVarTypeModel {
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
new BindingPatternVarTypeModel().run();
|
||||
new BindingPatternVarTypeModel().runVarParameterized();
|
||||
}
|
||||
|
||||
private void run() throws Exception {
|
||||
@ -86,4 +97,85 @@ public class BindingPatternVarTypeModel {
|
||||
throw new AssertionError("Didn't find the binding pattern!");
|
||||
}
|
||||
}
|
||||
|
||||
private void runVarParameterized() throws Exception {
|
||||
JavaFileObject input =
|
||||
SimpleJavaFileObject.forSource(URI.create("mem:///Test.java"),
|
||||
"""
|
||||
package test;
|
||||
public class Test {
|
||||
record R(N.I i) {}
|
||||
int test(Object o) {
|
||||
Test.N.I checkType0 = null;
|
||||
var checkType1 = checkType0;
|
||||
return switch (o) {
|
||||
case R(var checkType2) -> 0;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
static class N<T> {
|
||||
interface I {}
|
||||
}
|
||||
}
|
||||
""");
|
||||
DiagnosticListener<JavaFileObject> noErrors = d -> {
|
||||
if (d.getKind() == Diagnostic.Kind.ERROR) {
|
||||
throw new IllegalStateException(d.toString());
|
||||
}
|
||||
};
|
||||
JavacTask task =
|
||||
(JavacTask) compiler.getTask(null, null, noErrors, null, null, List.of(input));
|
||||
CompilationUnitTree cut = task.parse().iterator().next();
|
||||
Trees trees = Trees.instance(task);
|
||||
|
||||
task.analyze();
|
||||
|
||||
new TreePathScanner<Void, Void>() {
|
||||
private boolean checkAttributes;
|
||||
@Override
|
||||
public Void visitVariable(VariableTree node, Void p) {
|
||||
boolean prevCheckAttributes = checkAttributes;
|
||||
try {
|
||||
checkAttributes |=
|
||||
node.getName().toString().startsWith("checkType");
|
||||
return super.visitVariable(node, p);
|
||||
} finally {
|
||||
checkAttributes = prevCheckAttributes;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitIdentifier(IdentifierTree node, Void p) {
|
||||
checkType();
|
||||
return super.visitIdentifier(node, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitMemberSelect(MemberSelectTree node, Void p) {
|
||||
checkType();
|
||||
return super.visitMemberSelect(node, p);
|
||||
}
|
||||
|
||||
private void checkType() {
|
||||
if (!checkAttributes) {
|
||||
return ;
|
||||
}
|
||||
|
||||
TypeMirror type = trees.getTypeMirror(getCurrentPath());
|
||||
|
||||
if (type.getKind() == TypeKind.PACKAGE) {
|
||||
return ; //OK
|
||||
}
|
||||
if (type.getKind() != TypeKind.DECLARED) {
|
||||
throw new AssertionError("Expected a declared type, but got: " +
|
||||
type.getKind());
|
||||
}
|
||||
|
||||
if (!((DeclaredType) type).getTypeArguments().isEmpty()) {
|
||||
throw new AssertionError("Unexpected type arguments: " +
|
||||
((DeclaredType) type).getTypeArguments());
|
||||
}
|
||||
}
|
||||
}.scan(cut, null);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user