8193367: Annotated type variable bounds crash javac
Reviewed-by: mcimadamore, vromero
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Fri Jan 25 18:43:02 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Sat Jan 26 15:50:59 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -896,7 +896,7 @@
if (moreInfo && bound != null && !isPrintingBound)
try {
isPrintingBound = true;
- s.append("{:").append(bound.bound).append(":}");
+ s.append("{:").append(bound.getUpperBound()).append(":}");
} finally {
isPrintingBound = false;
}
@@ -1607,7 +1607,7 @@
* itself. Furthermore, the erasure_field of the class
* points to the first class or interface bound.
*/
- public Type bound = null;
+ private Type _bound = null;
/** The lower bound of this type variable.
* TypeVars don't normally have a lower bound, so it is normally set
@@ -1620,7 +1620,7 @@
super(null, TypeMetadata.EMPTY);
Assert.checkNonNull(lower);
tsym = new TypeVariableSymbol(0, name, this, owner);
- this.bound = null;
+ this.setUpperBound(null);
this.lower = lower;
}
@@ -1632,15 +1632,20 @@
TypeMetadata metadata) {
super(tsym, metadata);
Assert.checkNonNull(lower);
- this.bound = bound;
+ this.setUpperBound(bound);
this.lower = lower;
}
@Override
public TypeVar cloneWithMetadata(TypeMetadata md) {
- return new TypeVar(tsym, bound, lower, md) {
+ return new TypeVar(tsym, getUpperBound(), lower, md) {
@Override
public Type baseType() { return TypeVar.this.baseType(); }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public Type getUpperBound() { return TypeVar.this.getUpperBound(); }
+
+ public void setUpperBound(Type bound) { TypeVar.this.setUpperBound(bound); }
};
}
@@ -1655,12 +1660,9 @@
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
- public Type getUpperBound() {
- if ((bound == null || bound.hasTag(NONE)) && this != tsym.type) {
- bound = tsym.type.getUpperBound();
- }
- return bound;
- }
+ public Type getUpperBound() { return _bound; }
+
+ public void setUpperBound(Type bound) { this._bound = bound; }
int rank_field = -1;
@@ -1709,7 +1711,7 @@
WildcardType wildcard) {
super(name, owner, lower);
this.lower = Assert.checkNonNull(lower);
- this.bound = upper;
+ this.setUpperBound(upper);
this.wildcard = wildcard;
}
@@ -1725,9 +1727,14 @@
@Override
public CapturedType cloneWithMetadata(TypeMetadata md) {
- return new CapturedType(tsym, bound, bound, lower, wildcard, md) {
+ return new CapturedType(tsym, getUpperBound(), getUpperBound(), lower, wildcard, md) {
@Override
public Type baseType() { return CapturedType.this.baseType(); }
+
+ @Override @DefinedBy(Api.LANGUAGE_MODEL)
+ public Type getUpperBound() { return CapturedType.this.getUpperBound(); }
+
+ public void setUpperBound(Type bound) { CapturedType.this.setUpperBound(bound); }
};
}
@@ -1832,7 +1839,7 @@
public void complete() {
for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) {
- ((TypeVar)l.head).bound.complete();
+ ((TypeVar)l.head).getUpperBound().complete();
}
qtype.complete();
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Jan 25 18:43:02 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Sat Jan 26 15:50:59 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -132,7 +132,7 @@
if (t.hasTag(WILDCARD)) {
WildcardType w = (WildcardType) t;
if (w.isSuperBound())
- return w.bound == null ? syms.objectType : w.bound.bound;
+ return w.bound == null ? syms.objectType : w.bound.getUpperBound();
else
return wildUpperBound(w.type);
}
@@ -146,7 +146,7 @@
public Type cvarUpperBound(Type t) {
if (t.hasTag(TYPEVAR)) {
TypeVar v = (TypeVar) t;
- return v.isCaptured() ? cvarUpperBound(v.bound) : v;
+ return v.isCaptured() ? cvarUpperBound(v.getUpperBound()) : v;
}
else return t;
}
@@ -1821,14 +1821,14 @@
case TYPEVAR:
if (isSubtype(t, s)) {
return true;
- } else if (isCastable(t.bound, s, noWarnings)) {
+ } else if (isCastable(t.getUpperBound(), s, noWarnings)) {
warnStack.head.warn(LintCategory.UNCHECKED);
return true;
} else {
return false;
}
default:
- return isCastable(t.bound, s, warnStack.head);
+ return isCastable(t.getUpperBound(), s, warnStack.head);
}
}
@@ -1954,7 +1954,7 @@
if (t == s) return false;
if (t.hasTag(TYPEVAR)) {
TypeVar tv = (TypeVar) t;
- return !isCastable(tv.bound,
+ return !isCastable(tv.getUpperBound(),
relaxBound(s),
noWarnings);
}
@@ -2150,7 +2150,7 @@
if (t.tsym == sym)
return t;
else
- return asSuper(t.bound, sym);
+ return asSuper(t.getUpperBound(), sym);
}
@Override
@@ -2269,7 +2269,7 @@
@Override
public Type visitTypeVar(TypeVar t, Symbol sym) {
- return memberType(t.bound, sym);
+ return memberType(t.getUpperBound(), sym);
}
@Override
@@ -2392,7 +2392,7 @@
@Override
public Type visitTypeVar(TypeVar t, Boolean recurse) {
- Type erased = erasure(t.bound, recurse);
+ Type erased = erasure(t.getUpperBound(), recurse);
return combineMetadata(erased, t);
}
};
@@ -2498,11 +2498,11 @@
*/
@Override
public Type visitTypeVar(TypeVar t, Void ignored) {
- if (t.bound.hasTag(TYPEVAR) ||
- (!t.bound.isCompound() && !t.bound.isInterface())) {
- return t.bound;
+ if (t.getUpperBound().hasTag(TYPEVAR) ||
+ (!t.getUpperBound().isCompound() && !t.getUpperBound().isInterface())) {
+ return t.getUpperBound();
} else {
- return supertype(t.bound);
+ return supertype(t.getUpperBound());
}
}
@@ -2573,11 +2573,11 @@
@Override
public List<Type> visitTypeVar(TypeVar t, Void ignored) {
- if (t.bound.isCompound())
- return interfaces(t.bound);
-
- if (t.bound.isInterface())
- return List.of(t.bound);
+ if (t.getUpperBound().isCompound())
+ return interfaces(t.getUpperBound());
+
+ if (t.getUpperBound().isInterface())
+ return List.of(t.getUpperBound());
return List.nil();
}
@@ -2662,9 +2662,9 @@
* @param allInterfaces are all bounds interface types?
*/
public void setBounds(TypeVar t, List<Type> bounds, boolean allInterfaces) {
- t.bound = bounds.tail.isEmpty() ?
+ t.setUpperBound( bounds.tail.isEmpty() ?
bounds.head :
- makeIntersectionType(bounds, allInterfaces);
+ makeIntersectionType(bounds, allInterfaces) );
t.rank_field = -1;
}
// </editor-fold>
@@ -2674,10 +2674,10 @@
* Return list of bounds of the given type variable.
*/
public List<Type> getBounds(TypeVar t) {
- if (t.bound.hasTag(NONE))
+ if (t.getUpperBound().hasTag(NONE))
return List.nil();
- else if (t.bound.isErroneous() || !t.bound.isCompound())
- return List.of(t.bound);
+ else if (t.getUpperBound().isErroneous() || !t.getUpperBound().isCompound())
+ return List.of(t.getUpperBound());
else if ((erasure(t).tsym.flags() & INTERFACE) == 0)
return interfaces(t).prepend(supertype(t));
else
@@ -3361,8 +3361,8 @@
// calculate new bounds
for (Type t : tvars) {
TypeVar tv = (TypeVar) t;
- Type bound = subst(tv.bound, from, to);
- if (bound != tv.bound)
+ Type bound = subst(tv.getUpperBound(), from, to);
+ if (bound != tv.getUpperBound())
changed = true;
newBoundsBuf.append(bound);
}
@@ -3386,15 +3386,15 @@
// set the bounds of new type variables to the new bounds
for (Type t : newTvars.toList()) {
TypeVar tv = (TypeVar) t;
- tv.bound = newBounds.head;
+ tv.setUpperBound( newBounds.head );
newBounds = newBounds.tail;
}
return newTvars.toList();
}
public TypeVar substBound(TypeVar t, List<Type> from, List<Type> to) {
- Type bound1 = subst(t.bound, from, to);
- if (bound1 == t.bound)
+ Type bound1 = subst(t.getUpperBound(), from, to);
+ if (bound1 == t.getUpperBound())
return t;
else {
// create new type variable without bounds
@@ -3402,7 +3402,7 @@
t.getMetadata());
// the new bound should use the new type variable in place
// of the old
- tv.bound = subst(bound1, List.of(t), List.of(tv));
+ tv.setUpperBound( subst(bound1, List.of(t), List.of(tv)) );
return tv;
}
}
@@ -3435,7 +3435,7 @@
List<Type> tvars1 = tvars.map(newInstanceFun);
for (List<Type> l = tvars1; l.nonEmpty(); l = l.tail) {
TypeVar tv = (TypeVar) l.head;
- tv.bound = subst(tv.bound, tvars, tvars1);
+ tv.setUpperBound( subst(tv.getUpperBound(), tvars, tvars1) );
}
return tvars1;
}
@@ -3614,11 +3614,11 @@
}
private void appendTyparamString(TypeVar t, StringBuilder buf) {
buf.append(t);
- if (t.bound == null ||
- t.bound.tsym.getQualifiedName() == names.java_lang_Object)
+ if (t.getUpperBound() == null ||
+ t.getUpperBound().tsym.getQualifiedName() == names.java_lang_Object)
return;
buf.append(" extends "); // Java syntax; no need for i18n
- Type bound = t.bound;
+ Type bound = t.getUpperBound();
if (!bound.isCompound()) {
buf.append(bound);
} else if ((erasure(t).tsym.flags() & INTERFACE) == 0) {
@@ -4375,24 +4375,24 @@
Ui = syms.objectType;
switch (Ti.kind) {
case UNBOUND:
- Si.bound = subst(Ui, A, S);
+ Si.setUpperBound( subst(Ui, A, S) );
Si.lower = syms.botType;
break;
case EXTENDS:
- Si.bound = glb(Ti.getExtendsBound(), subst(Ui, A, S));
+ Si.setUpperBound( glb(Ti.getExtendsBound(), subst(Ui, A, S)) );
Si.lower = syms.botType;
break;
case SUPER:
- Si.bound = subst(Ui, A, S);
+ Si.setUpperBound( subst(Ui, A, S) );
Si.lower = Ti.getSuperBound();
break;
}
- Type tmpBound = Si.bound.hasTag(UNDETVAR) ? ((UndetVar)Si.bound).qtype : Si.bound;
+ Type tmpBound = Si.getUpperBound().hasTag(UNDETVAR) ? ((UndetVar)Si.getUpperBound()).qtype : Si.getUpperBound();
Type tmpLower = Si.lower.hasTag(UNDETVAR) ? ((UndetVar)Si.lower).qtype : Si.lower;
- if (!Si.bound.hasTag(ERROR) &&
+ if (!Si.getUpperBound().hasTag(ERROR) &&
!Si.lower.hasTag(ERROR) &&
isSameType(tmpBound, tmpLower)) {
- currentS.head = Si.bound;
+ currentS.head = Si.getUpperBound();
}
}
currentA = currentA.tail;
@@ -4720,9 +4720,9 @@
@Override
public Type visitTypeVar(TypeVar t, Void s) {
if (rewriteTypeVars) {
- Type bound = t.bound.contains(t) ?
- erasure(t.bound) :
- visit(t.bound);
+ Type bound = t.getUpperBound().contains(t) ?
+ erasure(t.getUpperBound()) :
+ visit(t.getUpperBound());
return rewriteAsWildcardType(bound, t, EXTENDS);
} else {
return t;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Fri Jan 25 18:43:02 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Sat Jan 26 15:50:59 2019 +0100
@@ -798,7 +798,7 @@
for (JCTypeParameter tvar : typarams) {
TypeVar a = (TypeVar)tvar.type;
a.tsym.flags_field |= UNATTRIBUTED;
- a.bound = Type.noType;
+ a.setUpperBound(Type.noType);
if (!tvar.bounds.isEmpty()) {
List<Type> bounds = List.of(attribType(tvar.bounds.head, env));
for (JCExpression bound : tvar.bounds.tail)
@@ -4520,9 +4520,9 @@
annotate.annotateTypeParameterSecondStage(tree, tree.annotations);
}
- if (!typeVar.bound.isErroneous()) {
+ if (!typeVar.getUpperBound().isErroneous()) {
//fixup type-parameter bound computed in 'attribTypeVariables'
- typeVar.bound = checkIntersection(tree, tree.bounds);
+ typeVar.setUpperBound(checkIntersection(tree, tree.bounds));
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Fri Jan 25 18:43:02 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Sat Jan 26 15:50:59 2019 +0100
@@ -2285,7 +2285,7 @@
return;
if (seen.contains(t)) {
tv = (TypeVar)t;
- tv.bound = types.createErrorType(t);
+ tv.setUpperBound(types.createErrorType(t));
log.error(pos, Errors.CyclicInheritance(t));
} else if (t.hasTag(TYPEVAR)) {
tv = (TypeVar)t;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Fri Jan 25 18:43:02 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Sat Jan 26 15:50:59 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -537,8 +537,8 @@
for (Type t : todo) {
UndetVar uv = (UndetVar)t;
TypeVar ct = (TypeVar)uv.getInst();
- ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct)));
- if (ct.bound.isErroneous()) {
+ ct.setUpperBound( types.glb(inferenceContext.asInstTypes(types.getBounds(ct))) );
+ if (ct.getUpperBound().isErroneous()) {
//report inference error if glb fails
reportBoundError(uv, InferenceBound.UPPER);
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Fri Jan 25 18:43:02 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Sat Jan 26 15:50:59 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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
@@ -989,7 +989,7 @@
// use the SAM parameter type
if (checkForIntersection && descPTypes.head.getKind() == TypeKind.TYPEVAR) {
TypeVar tv = (TypeVar) descPTypes.head;
- if (tv.bound.getKind() == TypeKind.INTERSECTION) {
+ if (tv.getUpperBound().getKind() == TypeKind.INTERSECTION) {
parmType = samPTypes.head;
}
}
@@ -2375,7 +2375,7 @@
return true;
case TYPEVAR:
TypeVar tv = (TypeVar) t;
- return isIntersectionOrUnionType(tv.bound);
+ return isIntersectionOrUnionType(tv.getUpperBound());
}
return false;
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Fri Jan 25 18:43:02 2019 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Sat Jan 26 15:50:59 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, 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
@@ -506,11 +506,11 @@
public Void visitCapturedType(CapturedType t, Void ignored) {
if (indexOf(t, WhereClauseKind.CAPTURED) == -1) {
String suffix = t.lower == syms.botType ? ".1" : "";
- JCDiagnostic d = diags.fragment("where.captured"+ suffix, t, t.bound, t.lower, t.wildcard);
+ JCDiagnostic d = diags.fragment("where.captured"+ suffix, t, t.getUpperBound(), t.lower, t.wildcard);
whereClauses.get(WhereClauseKind.CAPTURED).put(t, d);
visit(t.wildcard);
visit(t.lower);
- visit(t.bound);
+ visit(t.getUpperBound());
}
return null;
}
@@ -555,7 +555,7 @@
t = (TypeVar)t.stripMetadataIfNeeded();
if (indexOf(t, WhereClauseKind.TYPEVAR) == -1) {
//access the bound type and skip error types
- Type bound = t.bound;
+ Type bound = t.getUpperBound();
while ((bound instanceof ErrorType))
bound = ((ErrorType)bound).getOriginalType();
//retrieve the bound list - if the type variable
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/generics/typevars/AnnoTypeVarBounds.java Sat Jan 26 15:50:59 2019 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019, 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 8193367
+ * @summary Annotated type variable bounds crash javac
+ * @compile AnnoTypeVarBounds.java
+ */
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+class AnnoTypeVarBounds {
+ @Target(value = {ElementType.TYPE_USE})
+ @interface A{}
+ class Sup<X, Y> { }
+ class Sub<U extends @A V, @A V extends String> extends Sup<U, V> { }
+}
--- a/test/langtools/tools/javac/lib/DPrinter.java Fri Jan 25 18:43:02 2019 -0800
+++ b/test/langtools/tools/javac/lib/DPrinter.java Sat Jan 26 15:50:59 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -1336,8 +1336,8 @@
// null or bot. So, only print the bound for subtypes of TypeVar,
// or if the bound is (erroneously) not null or bot.
if (!type.hasTag(TypeTag.TYPEVAR)
- || !(type.bound == null || type.bound.hasTag(TypeTag.BOT))) {
- printType("bound", type.bound, Details.FULL);
+ || !(type.getUpperBound() == null || type.getUpperBound().hasTag(TypeTag.BOT))) {
+ printType("bound", type.getUpperBound(), Details.FULL);
}
printType("lower", type.lower, Details.FULL);
return visitType(type, null);
--- a/test/langtools/tools/javac/types/GenericTypeWellFormednessTest.java Fri Jan 25 18:43:02 2019 -0800
+++ b/test/langtools/tools/javac/types/GenericTypeWellFormednessTest.java Sat Jan 26 15:50:59 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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
@@ -144,7 +144,7 @@
typeVars[typeVars.length - 1] = new InstantiableType(null) {
Type inst(Type clazz) {
TypeVar tvar = fac.TypeVariable();
- tvar.bound = subst(clazz, Mapping(clazz.getTypeArguments().head, tvar));
+ tvar.setUpperBound( subst(clazz, Mapping(clazz.getTypeArguments().head, tvar)) );
return tvar;
}
};
@@ -204,20 +204,20 @@
TypeVar tv4 = fac.TypeVariable();
Type decl4 = fac.Class(tv4);
- tv4.bound = decl4;
+ tv4.setUpperBound(decl4);
tv4.tsym.name = predef.exceptionType.tsym.name;
TypeVar tv5 = fac.TypeVariable();
Type decl5 = fac.Class(tv5);
- tv5.bound = subst(decl5, Mapping(tv5, fac.Wildcard(BoundKind.EXTENDS, tv5)));
+ tv5.setUpperBound( subst(decl5, Mapping(tv5, fac.Wildcard(BoundKind.EXTENDS, tv5))) );
TypeVar tv6 = fac.TypeVariable();
Type decl6 = fac.Class(tv6);
- tv6.bound = subst(decl6, Mapping(tv6, fac.Wildcard(BoundKind.SUPER, tv6)));
+ tv6.setUpperBound( subst(decl6, Mapping(tv6, fac.Wildcard(BoundKind.SUPER, tv6))) );
TypeVar tv7 = fac.TypeVariable();
Type decl7 = fac.Class(tv7);
- tv7.bound = subst(decl7, Mapping(tv7, fac.Wildcard(BoundKind.UNBOUND, predef.objectType)));
+ tv7.setUpperBound( subst(decl7, Mapping(tv7, fac.Wildcard(BoundKind.UNBOUND, predef.objectType))) );
columns = new Type[] {
decl1, decl2, decl3, decl4, decl5, decl6, decl7