}
tree.type = result = t;
}
public void visitTypeParameter(JCTypeParameter tree) {
TypeVar a = (TypeVar)tree.type;
Set<Type> boundSet = new HashSet<Type>();
if (a.bound.isErroneous())
return;
List<Type> bs = types.getBounds(a);
if (tree.bounds.nonEmpty()) {
// accept class or interface or typevar as first bound.
Type b = checkBase(bs.head, tree.bounds.head, env, false, false, false);
boundSet.add(types.erasure(b));
if (b.isErroneous()) {
a.bound = b;
}
else if (b.tag == TYPEVAR) {
// if first bound was a typevar, do not accept further bounds.
if (tree.bounds.tail.nonEmpty()) {
log.error(tree.bounds.tail.head.pos(),
"type.var.may.not.be.followed.by.other.bounds");
tree.bounds = List.of(tree.bounds.head);
a.bound = bs.head;
}
} else {
// if first bound was a class or interface, accept only interfaces
// as further bounds.
for (JCExpression bound : tree.bounds.tail) {
bs = bs.tail;
Type i = checkBase(bs.head, bound, env, false, true, false);
if (i.isErroneous())
a.bound = i;
else if (i.tag == CLASS)
chk.checkNotRepeated(bound.pos(), types.erasure(i), boundSet);
}
}
}
bs = types.getBounds(a);
// in case of multiple bounds ...
if (bs.length() > 1) {
// ... the variable's bound is a class type flagged COMPOUND
// (see comment for TypeVar.bound).
// In this case, generate a class tree that represents the
// bound class, ...
JCExpression extending;
List<JCExpression> implementing;
if ((bs.head.tsym.flags() & INTERFACE) == 0) {
extending = tree.bounds.head;
implementing = tree.bounds.tail;
} else {
extending = null;
implementing = tree.bounds;
}
JCClassDecl cd = make.at(tree.pos).ClassDef(
make.Modifiers(PUBLIC | ABSTRACT),
tree.name, List.<JCTypeParameter>nil(),
extending, implementing, List.<JCTree>nil());
ClassSymbol c = (ClassSymbol)a.getUpperBound().tsym;
Assert.check((c.flags() & COMPOUND) != 0);
cd.sym = c;
c.sourcefile = env.toplevel.sourcefile;
// ... and attribute the bound class