Skip to content
Permalink
Browse files
8261205: AssertionError: Cannot add metadata to an intersection type
Reviewed-by: mcimadamore
  • Loading branch information
Vicente Romero committed May 20, 2021
1 parent 7b98400 commit 81f39ed3e0176b75dee1c8db24041545bcc68a86
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 8 deletions.
@@ -30,7 +30,6 @@
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject;

import com.sun.tools.javac.code.Attribute.Array;
import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
@@ -1224,7 +1223,9 @@ public void visitLambda(JCLambda tree) {
.methodParameter(tree, i, param.vartype.pos);
push(param);
try {
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
if (!param.declaredUsingVar()) {
separateAnnotationsKinds(param.vartype, param.sym.type, param.sym, pos);
}
} finally {
pop();
}
@@ -1262,7 +1263,7 @@ public void visitVarDef(final JCVariableDecl tree) {
final TypeAnnotationPosition pos =
TypeAnnotationPosition.localVariable(currentLambda,
tree.pos);
if (!tree.isImplicitlyTyped()) {
if (!tree.declaredUsingVar()) {
separateAnnotationsKinds(tree.vartype, tree.sym.type, tree.sym, pos);
}
} else if (tree.sym.getKind() == ElementKind.BINDING_VARIABLE) {
@@ -27,7 +27,6 @@

import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

import javax.lang.model.element.ElementKind;
import javax.tools.JavaFileObject;
@@ -44,7 +44,6 @@
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
import static com.sun.tools.javac.tree.JCTree.Tag.VARDEF;

/** Resolves field, method and constructor header, and constructs corresponding Symbols.
*
@@ -3327,6 +3327,7 @@ JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean r
*/
JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
boolean reqInit, Comment dc, boolean localDecl, boolean compound) {
boolean declaredUsingVar = false;
type = bracketsOpt(type);
JCExpression init = null;
if (token.kind == EQ) {
@@ -3345,6 +3346,7 @@ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression ty
//error - 'var' and arrays
reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedArray(typeName));
} else {
declaredUsingVar = true;
if(compound)
//error - 'var' in compound local var decl
reportSyntaxError(elemType.pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
@@ -3357,7 +3359,7 @@ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression ty
}
}
JCVariableDecl result =
toP(F.at(pos).VarDef(mods, name, type, init));
toP(F.at(pos).VarDef(mods, name, type, init, declaredUsingVar));
attach(result, dc);
result.startPos = startPos;
return result;
@@ -3469,7 +3471,8 @@ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type, boolean
}
type = bracketsOpt(type);

return toP(F.at(pos).VarDef(mods, name, type, null));
return toP(F.at(pos).VarDef(mods, name, type, null,
type != null && type.hasTag(IDENT) && ((JCIdent)type).name == names.var));
}

/** Resources = Resource { ";" Resources }
@@ -957,23 +957,35 @@ public static class JCVariableDecl extends JCStatement implements VariableTree {
public VarSymbol sym;
/** explicit start pos */
public int startPos = Position.NOPOS;
/** declared using `var` */
private boolean declaredUsingVar;

protected JCVariableDecl(JCModifiers mods,
Name name,
JCExpression vartype,
JCExpression init,
VarSymbol sym) {
this(mods, name, vartype, init, sym, false);
}

protected JCVariableDecl(JCModifiers mods,
Name name,
JCExpression vartype,
JCExpression init,
VarSymbol sym,
boolean declaredUsingVar) {
this.mods = mods;
this.name = name;
this.vartype = vartype;
this.init = init;
this.sym = sym;
this.declaredUsingVar = declaredUsingVar;
}

protected JCVariableDecl(JCModifiers mods,
JCExpression nameexpr,
JCExpression vartype) {
this(mods, null, vartype, null, null);
this(mods, null, vartype, null, null, false);
this.nameexpr = nameexpr;
if (nameexpr.hasTag(Tag.IDENT)) {
this.name = ((JCIdent)nameexpr).name;
@@ -987,6 +999,10 @@ public boolean isImplicitlyTyped() {
return vartype == null;
}

public boolean declaredUsingVar() {
return declaredUsingVar;
}

@Override
public void accept(Visitor v) { v.visitVarDef(this); }

@@ -227,6 +227,12 @@ public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype,
return tree;
}

public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init, boolean declaredUsingVar) {
JCVariableDecl tree = new JCVariableDecl(mods, name, vartype, init, null, declaredUsingVar);
tree.pos = pos;
return tree;
}

public JCVariableDecl ReceiverVarDef(JCModifiers mods, JCExpression name, JCExpression vartype) {
JCVariableDecl tree = new JCVariableDecl(mods, name, vartype);
tree.pos = pos;
@@ -0,0 +1,138 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8261205
* @summary check that potentially applicable type annotations are skip if the variable or parameter was declared with var
* @library /tools/lib
* @modules
* jdk.jdeps/com.sun.tools.classfile
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.code
* jdk.compiler/com.sun.tools.javac.util
* @build toolbox.ToolBox toolbox.JavacTask
* @run main VariablesDeclaredWithVarTest
*/

import java.util.List;
import java.util.ArrayList;

import java.io.File;
import java.nio.file.Paths;

import java.lang.annotation.*;
import java.util.Arrays;

import com.sun.tools.classfile.*;
import com.sun.tools.javac.util.Assert;

import toolbox.JavacTask;
import toolbox.ToolBox;

public class VariablesDeclaredWithVarTest {
ToolBox tb = new ToolBox();

final String src =
"""
import java.util.function.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target({ElementType.TYPE_USE, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@interface A {}

class Test {
void kaa() {
@A var c = g(1, 1L);
}

<X> X g(X a, X b) {
return a;
}

void foo() {
bar((@A var s) -> s);
}

void bar(Function<String, String> f) {}
}
""";

public static void main(String... args) throws Exception {
new VariablesDeclaredWithVarTest().run();
}

void run() throws Exception {
compileTestClass();
checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
"Test.class").toUri()), 0);
}

void compileTestClass() throws Exception {
new JavacTask(tb)
.sources(src)
.run();
}

void checkClassFile(final File cfile, int... taPositions) throws Exception {
ClassFile classFile = ClassFile.read(cfile);
List<TypeAnnotation> annos = new ArrayList<>();
for (Method method : classFile.methods) {
findAnnotations(classFile, method, annos);
String methodName = method.getName(classFile.constant_pool);
Assert.check(annos.size() == 0, "there shouldn't be any type annotations in any method, found " + annos.size() +
" type annotations at method " + methodName);
}
}

void findAnnotations(ClassFile cf, Method m, List<TypeAnnotation> annos) {
findAnnotations(cf, m, Attribute.RuntimeVisibleTypeAnnotations, annos);
findAnnotations(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, annos);
}

void findAnnotations(ClassFile cf, Method m, String name, List<TypeAnnotation> annos) {
int index = m.attributes.getIndex(cf.constant_pool, name);
if (index != -1) {
Attribute attr = m.attributes.get(index);
assert attr instanceof RuntimeTypeAnnotations_attribute;
RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
annos.addAll(Arrays.asList(tAttr.annotations));
}

int cindex = m.attributes.getIndex(cf.constant_pool, Attribute.Code);
if (cindex != -1) {
Attribute cattr = m.attributes.get(cindex);
assert cattr instanceof Code_attribute;
Code_attribute cAttr = (Code_attribute)cattr;
index = cAttr.attributes.getIndex(cf.constant_pool, name);
if (index != -1) {
Attribute attr = cAttr.attributes.get(index);
assert attr instanceof RuntimeTypeAnnotations_attribute;
RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
annos.addAll(Arrays.asList(tAttr.annotations));
}
}
}
}

1 comment on commit 81f39ed

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 81f39ed May 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.