--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Nov 30 15:14:36 2012 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Nov 30 15:14:48 2012 +0000
@@ -716,21 +716,8 @@
}
a.tsym.flags_field &= ~UNATTRIBUTED;
}
- for (JCTypeParameter tvar : typarams)
+ for (JCTypeParameter tvar : typarams) {
chk.checkNonCyclic(tvar.pos(), (TypeVar)tvar.type);
- attribStats(typarams, env);
- }
-
- void attribBounds(List<JCTypeParameter> typarams) {
- for (JCTypeParameter typaram : typarams) {
- Type bound = typaram.type.getUpperBound();
- if (bound != null && bound.tsym instanceof ClassSymbol) {
- ClassSymbol c = (ClassSymbol)bound.tsym;
- if ((c.flags_field & COMPOUND) != 0) {
- Assert.check((c.flags_field & UNATTRIBUTED) != 0, c);
- attribClass(typaram.pos(), c);
- }
- }
}
}
@@ -892,7 +879,12 @@
deferredLintHandler.flush(tree.pos());
chk.checkDeprecatedAnnotation(tree.pos(), m);
- attribBounds(tree.typarams);
+ // Create a new environment with local scope
+ // for attributing the method.
+ Env<AttrContext> localEnv = memberEnter.methodEnv(tree, env);
+ localEnv.info.lint = lint;
+
+ attribStats(tree.typarams, localEnv);
// If we override any other methods, check that we do so properly.
// JLS ???
@@ -903,12 +895,6 @@
}
chk.checkOverride(tree, m);
- // Create a new environment with local scope
- // for attributing the method.
- Env<AttrContext> localEnv = memberEnter.methodEnv(tree, env);
-
- localEnv.info.lint = lint;
-
if (isDefaultMethod && types.overridesObjectMethod(m.enclClass(), m)) {
log.error(tree, "default.overrides.object.member", m.name, Kinds.kindName(m.location()), m.location());
}
@@ -2196,7 +2182,7 @@
Type target;
Type lambdaType;
if (pt() != Type.recoveryType) {
- target = infer.instantiateFunctionalInterface(that, pt(), explicitParamTypes, resultInfo.checkContext);
+ target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext);
lambdaType = types.findDescriptorType(target);
chk.checkFunctionalInterface(that, target);
} else {
@@ -2294,6 +2280,26 @@
}
}
}
+
+ private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) {
+ Type pt = resultInfo.pt;
+ if (pt != Type.recoveryType && pt.isCompound()) {
+ IntersectionClassType ict = (IntersectionClassType)pt;
+ List<Type> bounds = ict.allInterfaces ?
+ ict.getComponents().tail :
+ ict.getComponents();
+ types.findDescriptorType(bounds.head); //propagate exception outwards!
+ for (Type bound : bounds.tail) {
+ if (!types.isMarkerInterface(bound)) {
+ resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound));
+ }
+ }
+ //for now (translation doesn't support intersection types)
+ return bounds.head;
+ } else {
+ return pt;
+ }
+ }
//where
private Type fallbackDescriptorType(JCExpression tree) {
switch (tree.getTag()) {
@@ -2466,7 +2472,7 @@
Type target;
Type desc;
if (pt() != Type.recoveryType) {
- target = infer.instantiateFunctionalInterface(that, pt(), null, resultInfo.checkContext);
+ target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext);
desc = types.findDescriptorType(target);
chk.checkFunctionalInterface(that, target);
} else {
@@ -3575,63 +3581,79 @@
tree.type = result = t;
}
- public void visitTypeParameter(JCTypeParameter tree) {
- TypeVar a = (TypeVar)tree.type;
+ public void visitTypeIntersection(JCTypeIntersection tree) {
+ attribTypes(tree.bounds, env);
+ tree.type = result = checkIntersection(tree, tree.bounds);
+ }
+
+ public void visitTypeParameter(JCTypeParameter tree) {
+ TypeVar typeVar = (TypeVar)tree.type;
+ if (!typeVar.bound.isErroneous()) {
+ //fixup type-parameter bound computed in 'attribTypeVariables'
+ typeVar.bound = checkIntersection(tree, tree.bounds);
+ }
+ }
+
+ Type checkIntersection(JCTree tree, List<JCExpression> bounds) {
Set<Type> boundSet = new HashSet<Type>();
- if (a.bound.isErroneous())
- return;
- List<Type> bs = types.getBounds(a);
- if (tree.bounds.nonEmpty()) {
+ if (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;
+ bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false);
+ boundSet.add(types.erasure(bounds.head.type));
+ if (bounds.head.type.isErroneous()) {
+ return bounds.head.type;
}
- else if (b.hasTag(TYPEVAR)) {
+ else if (bounds.head.type.hasTag(TYPEVAR)) {
// if first bound was a typevar, do not accept further bounds.
- if (tree.bounds.tail.nonEmpty()) {
- log.error(tree.bounds.tail.head.pos(),
+ if (bounds.tail.nonEmpty()) {
+ log.error(bounds.tail.head.pos(),
"type.var.may.not.be.followed.by.other.bounds");
- tree.bounds = List.of(tree.bounds.head);
- a.bound = bs.head;
+ return bounds.head.type;
}
} 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.hasTag(CLASS))
- chk.checkNotRepeated(bound.pos(), types.erasure(i), boundSet);
+ for (JCExpression bound : bounds.tail) {
+ bound.type = checkBase(bound.type, bound, env, false, true, false);
+ if (bound.type.isErroneous()) {
+ bounds = List.of(bound);
+ }
+ else if (bound.type.hasTag(CLASS)) {
+ chk.checkNotRepeated(bound.pos(), types.erasure(bound.type), boundSet);
+ }
}
}
}
- bs = types.getBounds(a);
-
- // in case of multiple bounds ...
- if (bs.length() > 1) {
+
+ if (bounds.length() == 0) {
+ return syms.objectType;
+ } else if (bounds.length() == 1) {
+ return bounds.head.type;
+ } else {
+ Type owntype = types.makeCompoundType(TreeInfo.types(bounds));
+ if (tree.hasTag(TYPEINTERSECTION)) {
+ ((IntersectionClassType)owntype).intersectionKind =
+ IntersectionClassType.IntersectionKind.EXPLICIT;
+ }
// ... 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;
+ if (!bounds.head.type.isInterface()) {
+ extending = bounds.head;
+ implementing = bounds.tail;
} else {
extending = null;
- implementing = tree.bounds;
+ implementing = bounds;
}
- JCClassDecl cd = make.at(tree.pos).ClassDef(
+ JCClassDecl cd = make.at(tree).ClassDef(
make.Modifiers(PUBLIC | ABSTRACT),
- tree.name, List.<JCTypeParameter>nil(),
+ names.empty, List.<JCTypeParameter>nil(),
extending, implementing, List.<JCTree>nil());
- ClassSymbol c = (ClassSymbol)a.getUpperBound().tsym;
+ ClassSymbol c = (ClassSymbol)owntype.tsym;
Assert.check((c.flags() & COMPOUND) != 0);
cd.sym = c;
c.sourcefile = env.toplevel.sourcefile;
@@ -3640,10 +3662,11 @@
c.flags_field |= UNATTRIBUTED;
Env<AttrContext> cenv = enter.classEnv(cd, env);
enter.typeEnvs.put(c, cenv);
+ attribClass(c);
+ return owntype;
}
}
-
public void visitWildcard(JCWildcard tree) {
//- System.err.println("visitWildcard("+tree+");");//DEBUG
Type type = (tree.kind.kind == BoundKind.UNBOUND)
@@ -3797,7 +3820,7 @@
chk.validateAnnotations(tree.mods.annotations, c);
// Validate type parameters, supertype and interfaces.
- attribBounds(tree.typarams);
+ attribStats(tree.typarams, env);
if (!c.isAnonymous()) {
//already checked if anonymous
chk.validate(tree.typarams, env);