--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Thu Mar 19 16:13:40 2015 -0700
@@ -31,10 +31,12 @@
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
+import java.util.function.Function;
import javax.lang.model.type.*;
import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.code.Types.MapVisitor;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
import static com.sun.tools.javac.code.BoundKind.*;
@@ -218,33 +220,81 @@
/** An abstract class for mappings from types to types
*/
- public static abstract class Mapping {
- private String name;
- public Mapping(String name) {
- this.name = name;
+ public static abstract class TypeMapping<S> extends Types.MapVisitor<S> implements Function<Type, Type> {
+
+ @Override
+ public Type apply(Type type) {
+ return visit(type);
+ }
+
+ List<Type> visit(List<Type> ts, S s) {
+ return ts.map(t -> visit(t, s));
+ }
+
+ @Override
+ public Type visitClassType(ClassType t, S s) {
+ Type outer = t.getEnclosingType();
+ Type outer1 = visit(outer, s);
+ List<Type> typarams = t.getTypeArguments();
+ List<Type> typarams1 = visit(typarams, s);
+ if (outer1 == outer && typarams1 == typarams) return t;
+ else return new ClassType(outer1, typarams1, t.tsym, t.metadata);
+ }
+
+ @Override
+ public Type visitWildcardType(WildcardType wt, S s) {
+ Type t = wt.type;
+ if (t != null)
+ t = visit(t, s);
+ if (t == wt.type)
+ return wt;
+ else
+ return new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.metadata);
}
- public abstract Type apply(Type t);
- public String toString() {
- return name;
+
+ @Override
+ public Type visitArrayType(ArrayType t, S s) {
+ Type elemtype = t.elemtype;
+ Type elemtype1 = visit(elemtype, s);
+ if (elemtype1 == elemtype) return t;
+ else return new ArrayType(elemtype1, t.tsym, t.metadata);
+ }
+
+ @Override
+ public Type visitMethodType(MethodType t, S s) {
+ List<Type> argtypes = t.argtypes;
+ Type restype = t.restype;
+ List<Type> thrown = t.thrown;
+ List<Type> argtypes1 = visit(argtypes, s);
+ Type restype1 = visit(restype, s);
+ List<Type> thrown1 = visit(thrown, s);
+ if (argtypes1 == argtypes &&
+ restype1 == restype &&
+ thrown1 == thrown) return t;
+ else return new MethodType(argtypes1, restype1, thrown1, t.tsym);
+ }
+
+ @Override
+ public Type visitCapturedType(CapturedType t, S s) {
+ return visitTypeVar(t, s);
+ }
+
+ @Override
+ public Type visitForAll(ForAll t, S s) {
+ return visit(t.qtype, s);
}
}
/** map a type function over all immediate descendants of this type
*/
- public Type map(Mapping f) {
- return this;
+ public <Z> Type map(TypeMapping<Z> mapping, Z arg) {
+ return mapping.visit(this, arg);
}
- /** map a type function over a list of types
+ /** map a type function over all immediate descendants of this type (no arg version)
*/
- public static List<Type> map(List<Type> ts, Mapping f) {
- if (ts.nonEmpty()) {
- List<Type> tail1 = map(ts.tail, f);
- Type t = f.apply(ts.head);
- if (tail1 != ts.tail || t != ts.head)
- return tail1.prepend(t);
- }
- return ts;
+ public <Z> Type map(TypeMapping<Z> mapping) {
+ return mapping.visit(this, null);
}
/** Define a constant type, of the same kind as this type
@@ -775,17 +825,6 @@
return s.toString();
}
- public Type map(Mapping f) {
- //- System.err.println(" (" + this + ").map(" + f + ")");//DEBUG
- Type t = type;
- if (t != null)
- t = f.apply(t);
- if (t == type)
- return this;
- else
- return new WildcardType(t, kind, tsym, bound, metadata);
- }
-
@DefinedBy(Api.LANGUAGE_MODEL)
public Type getExtendsBound() {
if (kind == EXTENDS)
@@ -1009,15 +1048,6 @@
allparams().isEmpty();
}
- public Type map(Mapping f) {
- Type outer = getEnclosingType();
- Type outer1 = f.apply(outer);
- List<Type> typarams = getTypeArguments();
- List<Type> typarams1 = map(typarams, f);
- if (outer1 == outer && typarams1 == typarams) return this;
- else return new ClassType(outer1, typarams1, tsym, metadata);
- }
-
public boolean contains(Type elem) {
return
elem == this
@@ -1248,12 +1278,6 @@
};
}
- public Type map(Mapping f) {
- Type elemtype1 = f.apply(elemtype);
- if (elemtype1 == elemtype) return this;
- else return new ArrayType(elemtype1, tsym, metadata);
- }
-
public boolean contains(Type elem) {
return elem == this || elemtype.contains(elem);
}
@@ -1345,16 +1369,6 @@
restype != null && restype.isErroneous();
}
- public Type map(Mapping f) {
- List<Type> argtypes1 = map(argtypes, f);
- Type restype1 = f.apply(restype);
- List<Type> thrown1 = map(thrown, f);
- if (argtypes1 == argtypes &&
- restype1 == restype &&
- thrown1 == thrown) return this;
- else return new MethodType(argtypes1, restype1, thrown1, tsym);
- }
-
public boolean contains(Type elem) {
return elem == this || contains(argtypes, elem) || restype.contains(elem) || contains(thrown, elem);
}
@@ -1647,10 +1661,6 @@
return qtype.isErroneous();
}
- public Type map(Mapping f) {
- return f.apply(qtype);
- }
-
public boolean contains(Type elem) {
return qtype.contains(elem);
}
@@ -1820,7 +1830,7 @@
}
protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
- Type bound2 = toTypeVarMap.apply(bound).baseType();
+ Type bound2 = bound.map(toTypeVarMap).baseType();
List<Type> prevBounds = bounds.get(ib);
for (Type b : prevBounds) {
//check for redundancy - use strict version of isSameType on tvars
@@ -1831,15 +1841,10 @@
notifyChange(EnumSet.of(ib));
}
//where
- Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") {
+ TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
@Override
- public Type apply(Type t) {
- if (t.hasTag(UNDETVAR)) {
- UndetVar uv = (UndetVar)t;
- return uv.inst != null ? uv.inst : uv.qtype;
- } else {
- return t.map(this);
- }
+ public Type visitUndetVar(UndetVar uv, Void _unused) {
+ return uv.inst != null ? uv.inst : uv.qtype;
}
};
@@ -2110,7 +2115,6 @@
public Type getEnclosingType() { return this; }
public Type getReturnType() { return this; }
public Type asSub(Symbol sym) { return this; }
- public Type map(Mapping f) { return this; }
public boolean isGenType(Type t) { return true; }
public boolean isErroneous() { return true; }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Mar 19 16:13:40 2015 -0700
@@ -32,6 +32,8 @@
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
+import java.util.function.BiPredicate;
+import java.util.stream.Collector;
import javax.tools.JavaFileObject;
@@ -1766,10 +1768,11 @@
// <editor-fold defaultstate="collapsed" desc="cvarLowerBounds">
public List<Type> cvarLowerBounds(List<Type> ts) {
- return map(ts, cvarLowerBoundMapping);
+ return ts.map(cvarLowerBoundMapping);
}
- private final Mapping cvarLowerBoundMapping = new Mapping("cvarLowerBound") {
- public Type apply(Type t) {
+ private final TypeMapping<Void> cvarLowerBoundMapping = new TypeMapping<Void>() {
+ @Override
+ public Type visitCapturedType(CapturedType t, Void _unused) {
return cvarLowerBound(t);
}
};
@@ -1879,9 +1882,15 @@
/**
* Mapping to take element type of an arraytype
*/
- private Mapping elemTypeFun = new Mapping ("elemTypeFun") {
- public Type apply(Type t) {
- return elemtype(skipTypeVars(t, false));
+ private TypeMapping<Void> elemTypeFun = new TypeMapping<Void>() {
+ @Override
+ public Type visitArrayType(ArrayType t, Void _unused) {
+ return t.elemtype;
+ }
+
+ @Override
+ public Type visitTypeVar(TypeVar t, Void _unused) {
+ return visit(skipTypeVars(t, false));
}
};
@@ -2177,7 +2186,7 @@
}
}
// where
- private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
+ private TypeMapping<Boolean> erasure = new TypeMapping<Boolean>() {
private Type combineMetadata(final Type ty,
final TypeMetadata md) {
if (!md.isEmpty()) {
@@ -2202,8 +2211,8 @@
if (t.isPrimitive())
return t; /*fast special case*/
else {
- Type erased = t.map(recurse ? erasureRecFun : erasureFun);
- return combineMetadata(erased, t.getMetadata());
+ //other cases already handled
+ return combineMetadata(t, t.getMetadata());
}
}
@@ -2223,23 +2232,10 @@
Type erased = erasure(t.bound, recurse);
return combineMetadata(erased, t.getMetadata());
}
-
- @Override
- public Type visitErrorType(ErrorType t, Boolean recurse) {
- return t;
- }
};
- private Mapping erasureFun = new Mapping ("erasure") {
- public Type apply(Type t) { return erasure(t); }
- };
-
- private Mapping erasureRecFun = new Mapping ("erasureRecursive") {
- public Type apply(Type t) { return erasureRecursive(t); }
- };
-
public List<Type> erasure(List<Type> ts) {
- return Type.map(ts, erasureFun);
+ return erasure.visit(ts, false);
}
public Type erasureRecursive(Type t) {
@@ -2247,7 +2243,7 @@
}
public List<Type> erasureRecursive(List<Type> ts) {
- return Type.map(ts, erasureRecFun);
+ return erasure.visit(ts, true);
}
// </editor-fold>
@@ -3177,15 +3173,18 @@
* changing all recursive bounds from old to new list.
*/
public List<Type> newInstances(List<Type> tvars) {
- List<Type> tvars1 = Type.map(tvars, newInstanceFun);
+ 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);
}
return tvars1;
}
- private static final Mapping newInstanceFun = new Mapping("newInstanceFun") {
- public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); }
+ private static final TypeMapping<Void> newInstanceFun = new TypeMapping<Void>() {
+ @Override
+ public TypeVar visitTypeVar(TypeVar t, Void _unused) {
+ return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata());
+ }
};
// </editor-fold>
@@ -3409,41 +3408,86 @@
}
/**
+ * Collect types into a new closure (using a @code{ClosureHolder})
+ */
+ public Collector<Type, ClosureHolder, List<Type>> closureCollector(boolean minClosure, BiPredicate<Type, Type> shouldSkip) {
+ return Collector.of(() -> new ClosureHolder(minClosure, shouldSkip),
+ ClosureHolder::add,
+ ClosureHolder::merge,
+ ClosureHolder::closure);
+ }
+ //where
+ class ClosureHolder {
+ List<Type> closure;
+ final boolean minClosure;
+ final BiPredicate<Type, Type> shouldSkip;
+
+ ClosureHolder(boolean minClosure, BiPredicate<Type, Type> shouldSkip) {
+ this.closure = List.nil();
+ this.minClosure = minClosure;
+ this.shouldSkip = shouldSkip;
+ }
+
+ void add(Type type) {
+ closure = insert(closure, type, shouldSkip);
+ }
+
+ ClosureHolder merge(ClosureHolder other) {
+ closure = union(closure, other.closure, shouldSkip);
+ return this;
+ }
+
+ List<Type> closure() {
+ return minClosure ? closureMin(closure) : closure;
+ }
+ }
+
+ BiPredicate<Type, Type> basicClosureSkip = (t1, t2) -> t1.tsym == t2.tsym;
+
+ /**
* Insert a type in a closure
*/
- public List<Type> insert(List<Type> cl, Type t) {
+ public List<Type> insert(List<Type> cl, Type t, BiPredicate<Type, Type> shouldSkip) {
if (cl.isEmpty()) {
return cl.prepend(t);
- } else if (t.tsym == cl.head.tsym) {
+ } else if (shouldSkip.test(t, cl.head)) {
return cl;
} else if (t.tsym.precedes(cl.head.tsym, this)) {
return cl.prepend(t);
} else {
// t comes after head, or the two are unrelated
- return insert(cl.tail, t).prepend(cl.head);
+ return insert(cl.tail, t, shouldSkip).prepend(cl.head);
}
}
+ public List<Type> insert(List<Type> cl, Type t) {
+ return insert(cl, t, basicClosureSkip);
+ }
+
/**
* Form the union of two closures
*/
- public List<Type> union(List<Type> cl1, List<Type> cl2) {
+ public List<Type> union(List<Type> cl1, List<Type> cl2, BiPredicate<Type, Type> shouldSkip) {
if (cl1.isEmpty()) {
return cl2;
} else if (cl2.isEmpty()) {
return cl1;
- } else if (cl1.head.tsym == cl2.head.tsym) {
- return union(cl1.tail, cl2.tail).prepend(cl1.head);
+ } else if (shouldSkip.test(cl1.head, cl2.head)) {
+ return union(cl1.tail, cl2.tail, shouldSkip).prepend(cl1.head);
} else if (cl1.head.tsym.precedes(cl2.head.tsym, this)) {
- return union(cl1.tail, cl2).prepend(cl1.head);
+ return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
} else if (cl2.head.tsym.precedes(cl1.head.tsym, this)) {
- return union(cl1, cl2.tail).prepend(cl2.head);
+ return union(cl1, cl2.tail, shouldSkip).prepend(cl2.head);
} else {
// unrelated types
- return union(cl1.tail, cl2).prepend(cl1.head);
+ return union(cl1.tail, cl2, shouldSkip).prepend(cl1.head);
}
}
+ public List<Type> union(List<Type> cl1, List<Type> cl2) {
+ return union(cl1, cl2, basicClosureSkip);
+ }
+
/**
* Intersect two closures
*/
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Mar 19 16:13:40 2015 -0700
@@ -40,11 +40,13 @@
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
import com.sun.tools.javac.comp.Check.CheckContext;
import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.FreeTypeListener;
import com.sun.tools.javac.jvm.*;
+import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
@@ -2871,6 +2873,16 @@
names.empty, List.of(fExpr.targets.head), ABSTRACT);
if (csym != null) {
chk.checkImplementations(env.tree, csym, csym);
+ try {
+ //perform an additional functional interface check on the synthetic class,
+ //as there may be spurious errors for raw targets - because of existing issues
+ //with membership and inheritance (see JDK-8074570).
+ csym.flags_field |= INTERFACE;
+ types.findDescriptorType(csym.type);
+ } catch (FunctionDescriptorLookupError err) {
+ resultInfo.checkContext.report(fExpr,
+ diags.fragment(Fragments.NoSuitableFunctionalIntfInst(fExpr.targets.head)));
+ }
}
} catch (Types.FunctionDescriptorLookupError ex) {
JCDiagnostic cause = ex.getDiagnostic();
@@ -2942,7 +2954,7 @@
public void visitBinary(JCBinary tree) {
// Attribute arguments.
Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env));
- Type right = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.rhs, env));
+ Type right = chk.checkNonVoid(tree.rhs.pos(), attribExpr(tree.rhs, env));
// Find operator.
Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right);
Type owntype = types.createErrorType(tree.type);
@@ -3722,7 +3734,7 @@
DeferredAttr.DeferredTypeMap checkDeferredMap =
deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
- argtypes = Type.map(argtypes, checkDeferredMap);
+ argtypes = argtypes.map(checkDeferredMap);
if (noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
chk.warnUnchecked(env.tree.pos(),
@@ -3730,7 +3742,7 @@
kindName(sym),
sym.name,
rs.methodArguments(sym.type.getParameterTypes()),
- rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
+ rs.methodArguments(argtypes.map(checkDeferredMap)),
kindName(sym.location()),
sym.location());
owntype = new MethodType(owntype.getParameterTypes(),
@@ -3754,7 +3766,7 @@
return new Pair<>(sym, diag);
}
};
- List<Type> argtypes2 = Type.map(argtypes,
+ List<Type> argtypes2 = argtypes.map(
rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase));
JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
env.tree, sym, site, sym.name, argtypes2, typeargtypes);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Mar 19 16:13:40 2015 -0700
@@ -27,6 +27,7 @@
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Type.TypeMapping;
import com.sun.tools.javac.comp.Resolve.ResolveError;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.tree.*;
@@ -44,7 +45,6 @@
import java.util.ArrayList;
import java.util.Collections;
-import java.util.EnumMap;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -300,13 +300,6 @@
}
};
- DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
- public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
- Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
- return dt.tree.type = Type.stuckType;
- }
- };
-
/**
* Policy for detecting stuck expressions. Different criteria might cause
* an expression to be judged as stuck, depending on whether the check
@@ -849,33 +842,24 @@
/** an empty deferred attribution context - all methods throw exceptions */
final DeferredAttrContext emptyDeferredAttrContext;
- /** The AttrMode to descriptive name mapping */
- private static final EnumMap<AttrMode, String> deferredTypeMapDescriptions;
- static {
- deferredTypeMapDescriptions = new EnumMap<>(AttrMode.class);
- deferredTypeMapDescriptions.put(AttrMode.CHECK, "deferredTypeMap[CHECK]");
- deferredTypeMapDescriptions.put(AttrMode.SPECULATIVE, "deferredTypeMap[SPECULATIVE]");
- }
-
/**
* Map a list of types possibly containing one or more deferred types
* into a list of ordinary types. Each deferred type D is mapped into a type T,
* where T is computed by retrieving the type that has already been
* computed for D during a previous deferred attribution round of the given kind.
*/
- class DeferredTypeMap extends Type.Mapping {
+ class DeferredTypeMap extends TypeMapping<Void> {
DeferredAttrContext deferredAttrContext;
protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
- super(deferredTypeMapDescriptions.get(mode));
this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase,
infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
}
@Override
- public Type apply(Type t) {
+ public Type visitType(Type t, Void _unused) {
if (!t.hasTag(DEFERRED)) {
- return t.map(this);
+ return super.visitType(t, null);
} else {
DeferredType dt = (DeferredType)t;
return typeOf(dt);
@@ -928,7 +912,7 @@
return chk.checkNonVoid(pos, super.check(pos, found));
}
});
- return super.apply(dt);
+ return super.visit(dt);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu Mar 19 16:13:40 2015 -0700
@@ -25,6 +25,7 @@
package com.sun.tools.javac.comp;
+import com.sun.tools.javac.code.Type.TypeMapping;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
import com.sun.tools.javac.tree.TreeInfo;
@@ -477,7 +478,7 @@
restype = syms.objectType;
}
- List<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step));
+ List<Type> paramtypes = argtypes.map(new ImplicitArgType(spMethod, resolveContext.step));
List<Type> exType = spMethod != null ?
spMethod.getThrownTypes() :
List.of(syms.throwableType); // make it throw all exceptions
@@ -495,9 +496,16 @@
(rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase);
}
- public Type apply(Type t) {
- t = types.erasure(super.apply(t));
- if (t.hasTag(BOT))
+ @Override
+ public Type visitClassType(ClassType t, Void aVoid) {
+ return types.erasure(t);
+ }
+
+ @Override
+ public Type visitType(Type t, Void _unused) {
+ if (t.hasTag(DEFERRED)) {
+ return visit(super.visitType(t, null));
+ } else if (t.hasTag(BOT))
// nulls type as the marker type Null (which has no instances)
// infer as java.lang.Void for now
t = types.boxedClass(syms.voidType).type;
@@ -865,7 +873,8 @@
@Override
public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
Infer infer = inferenceContext.infer();
- List<Type> boundList = uv.getBounds(InferenceBound.UPPER);
+ List<Type> boundList = uv.getBounds(InferenceBound.UPPER).stream()
+ .collect(infer.types.closureCollector(true, infer.types::isSameType));
List<Type> boundListTail = boundList.tail;
while (boundList.nonEmpty()) {
List<Type> tmpTail = boundListTail;
@@ -2046,23 +2055,19 @@
List<FreeTypeListener> freetypeListeners = List.nil();
public InferenceContext(List<Type> inferencevars) {
- this.undetvars = Type.map(inferencevars, fromTypeVarFun);
+ this.undetvars = inferencevars.map(fromTypeVarFun);
this.inferencevars = inferencevars;
}
//where
- Mapping fromTypeVarFun = new Mapping("fromTypeVarFunWithBounds") {
- // mapping that turns inference variables into undet vars
- public Type apply(Type t) {
- if (t.hasTag(TYPEVAR)) {
- TypeVar tv = (TypeVar)t;
- if (tv.isCaptured()) {
- return new CapturedUndetVar((CapturedType)tv, types);
- } else {
- return new UndetVar(tv, types);
- }
- } else {
- return t.map(this);
- }
+ TypeMapping<Void> fromTypeVarFun = new TypeMapping<Void>() {
+ @Override
+ public Type visitTypeVar(TypeVar tv, Void aVoid) {
+ return new UndetVar(tv, types);
+ }
+
+ @Override
+ public Type visitCapturedType(CapturedType t, Void aVoid) {
+ return new CapturedUndetVar(t, types);
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Mar 19 16:13:40 2015 -0700
@@ -232,8 +232,7 @@
}
}
String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
- List<Type> argtypes2 = Type.map(argtypes,
- deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
+ List<Type> argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name,
site.tsym, mostSpecificPos, currentResolutionContext.step,
methodArguments(argtypes2),
@@ -2259,7 +2258,7 @@
(typeargtypes == null || !Type.isErroneous(typeargtypes));
}
public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
- return Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
+ return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Mar 19 16:13:40 2015 -0700
@@ -56,6 +56,7 @@
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
+import static com.sun.tools.javac.code.TypeTag.ARRAY;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
import static com.sun.tools.javac.jvm.ClassFile.*;
@@ -2006,6 +2007,15 @@
}
if (saveParameterNames)
setParameterNames(m, type);
+
+ if ((flags & VARARGS) != 0) {
+ final Type last = type.getParameterTypes().last();
+ if (last == null || !last.hasTag(ARRAY)) {
+ m.flags_field &= ~VARARGS;
+ throw badClassFile("malformed.vararg.method", m);
+ }
+ }
+
return m;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Mar 19 16:13:40 2015 -0700
@@ -1847,6 +1847,9 @@
compiler.misc.undecl.type.var=\
undeclared type variable: {0}
+compiler.misc.malformed.vararg.method=\
+ class file contains malformed variable arity method: {0}
+
compiler.misc.wrong.version=\
class file has wrong version {0}.{1}, should be {2}.{3}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Thu Mar 19 16:13:40 2015 -0700
@@ -33,6 +33,7 @@
import java.util.AbstractCollection;
import java.util.ListIterator;
import java.util.NoSuchElementException;
+import java.util.function.Function;
import java.util.stream.Collector;
/** A class for generic linked lists. Links are supposed to be
@@ -417,6 +418,17 @@
}
@SuppressWarnings("unchecked")
+ public <Z> List<Z> map(Function<A, Z> mapper) {
+ if (nonEmpty()) {
+ List<Z> tail1 = tail.map(mapper);
+ Z head1 = mapper.apply(head);
+ if (tail1 != tail || head1 != head)
+ return tail1.prepend(head1);
+ }
+ return (List<Z>)this;
+ }
+
+ @SuppressWarnings("unchecked")
public static <T> List<T> convert(Class<T> klass, List<?> list) {
if (list == null)
return null;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8071847/T8071847.java Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 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 8071847
+ * @summary Verify proper termination when instance initialization method uses invalid flags
+ * @compile T8071847.java
+ * @run main T8071847
+*/
+
+
+import java.io.*;
+import java.util.*;
+
+public class T8071847 {
+ String testclass="invalidFlags.class";
+ String testclassHexString =
+ "CAFEBABE00000031000D0A0003000A07000B07000C0100063C696E69743E0100" +
+ "03282956010004436F646501000F4C696E654E756D6265725461626C6501000A" +
+ "536F7572636546696C65010009546573742E6A6176610C0004000501000C696E" +
+ "76616C6964466C6167730100106A6176612F6C616E672F4F626A656374002000" +
+ "02000300000000000100A000040005000100060000001D00010001000000052A" +
+ "B70001B10000000100070000000600010000000100010008000000020009";
+
+ String testJavaFile = "testInvalidFlags.java";
+ String testJavaSource ="public class testInvalidFlags extends invalidFlags {" +
+ "invalidFlags c = null;" +
+ "public testInvalidFlags() { c = new invalidFlags(); }" +
+ "public static void main(String... args) { " +
+ "new testInvalidFlags();}}";
+
+ public static void main(String[] args) throws Exception {
+ new T8071847().run();
+ }
+
+ public void run() throws IOException {
+ writeHexFile(testclass,testclassHexString);
+ writeTestFile(testJavaFile, testJavaSource);
+ javac(testJavaFile);
+ }
+
+ File writeTestFile(String fname, String source) throws IOException {
+ File f = new File(fname);
+ PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
+ out.println(source);
+ out.close();
+ return f;
+ }
+
+ byte[] hexToByte(String str) {
+ char[] CA = str.toCharArray();
+ byte[] byteArry = new byte[str.length()/2];
+ int bi = 0;
+ for (int i = 0; i<CA.length ; i+=2) {
+ char c1 = CA[i], c2=CA[i+1];
+ byteArry[bi++] = (byte)((Character.digit((int)c1,16)<<4) +
+ Character.digit((int)c2,16));
+ }
+ return byteArry;
+ }
+
+ File writeHexFile(String classFileName, String hexString) throws IOException {
+ File f = new File(classFileName);
+ FileOutputStream output = new FileOutputStream(f);
+ output.write(hexToByte(hexString));
+ output.close();
+ return f;
+ }
+
+ String javac(String className) {
+ StringWriter sw = new StringWriter();
+ PrintWriter out = new PrintWriter(sw);
+ int rc = 0;
+ List<String> javacArgs = new ArrayList<>();
+ javacArgs.addAll(Arrays.asList("-XDrawDiagnostics", "-cp", ".", "-d", ".", className));
+ rc = com.sun.tools.javac.Main.compile(
+ javacArgs.toArray(new String[javacArgs.size()]),out);
+ out.close();
+ if (rc > 1) {
+ System.out.println(sw.toString());
+ throw new Error("javac " + className + " failed. rc=" + rc);
+ }
+ if (rc != 1 || !sw.toString().contains("compiler.misc.malformed.vararg.method"))
+ throw new RuntimeException("Unexpected output" + sw.toString());
+ return sw.toString();
+ }
+}
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Thu Mar 19 12:59:26 2015 -0700
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Thu Mar 19 16:13:40 2015 -0700
@@ -87,6 +87,7 @@
compiler.misc.unable.to.access.file # ClassFile
compiler.misc.undecl.type.var # ClassReader
compiler.misc.unicode.str.not.supported # ClassReader
+compiler.misc.malformed.vararg.method # ClassReader
compiler.misc.verbose.retro # UNUSED
compiler.misc.verbose.retro.with # UNUSED
compiler.misc.verbose.retro.with.list # UNUSED
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/expression/BinopVoidTest.java Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8074148
+ * @summary Attr.visitBinary flags error at wrong position
+ *
+ * @compile/fail/ref=BinopVoidTest.out -XDrawDiagnostics BinopVoidTest.java
+ */
+
+class BinopVoidTest {
+ void foo() {}
+ int x = 10 + foo();
+ int y = foo() + 10;
+ int z = foo() + foo();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/expression/BinopVoidTest.out Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,5 @@
+BinopVoidTest.java:11:21: compiler.err.void.not.allowed.here
+BinopVoidTest.java:12:16: compiler.err.void.not.allowed.here
+BinopVoidTest.java:13:16: compiler.err.void.not.allowed.here
+BinopVoidTest.java:13:24: compiler.err.void.not.allowed.here
+4 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8048838/T8048838.java Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 8048838
+ * @summary type inference performance regression
+ * @compile T8048838.java
+ */
+class T8048838 {
+
+ <T1 extends T2, T2 extends T3, T3 extends T4, T4 extends T5, T5 extends T6, T6 extends T7,
+ T7 extends T8, T8 extends T9, T9 extends T10, T10 extends T11, T11 extends T12,
+ T12 extends T13, T13 extends T14, T14 extends T15, T15 extends T16, T16 extends T17,
+ T17 extends T18, T18 extends T19, T19 extends T20, T20 extends T21, T21 extends T22,
+ T22 extends T23, T23 extends T24, T24 extends T25, T25 extends T26, T26 extends T27,
+ T27 extends T28, T28 extends T29, T29 extends T30, T30 extends T31, T31 extends T32,
+ T32 extends T33, T33 extends T34, T34 extends T35, T35 extends T36, T36 extends T37,
+ T37 extends T38, T38 extends T39, T39 extends T40, T40 extends T41, T41 extends T42,
+ T42 extends T43, T43 extends T44, T44 extends T45, T45 extends T46, T46 extends T47,
+ T47 extends T48, T48 extends T49, T49 extends T50, T50 extends T51, T51 extends T52,
+ T52 extends T53, T53 extends T54, T54 extends T55, T55 extends T56, T56 extends T57,
+ T57 extends T58, T58 extends T59, T59 extends T60, T60 extends T61, T61 extends T62,
+ T62 extends T63, T63 extends T64, T64 extends T65, T65 extends T66, T66 extends T67,
+ T67 extends T68, T68 extends T69, T69 extends T70, T70 extends T71, T71 extends T72,
+ T72 extends T73, T73 extends T74, T74 extends T75, T75 extends T76, T76 extends T77,
+ T77 extends T78, T78 extends T79, T79 extends T80, T80 extends T81, T81 extends T82,
+ T82 extends T83, T83 extends T84, T84 extends T85, T85 extends T86, T86 extends T87,
+ T87 extends T88, T88 extends T89, T89 extends T90, T90 extends T91, T91 extends T92,
+ T92 extends T93, T93 extends T94, T94 extends T95, T95 extends T96, T96 extends T97,
+ T97 extends T98, T98 extends T99, T99 extends T100, T100 extends Integer>
+ T1 foo(T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8, T9 x9, T10 x10, T11 x11, T12 x12,
+ T13 x13, T14 x14, T15 x15, T16 x16, T17 x17, T18 x18, T19 x19, T20 x20, T21 x21, T22 x22,
+ T23 x23, T24 x24, T25 x25, T26 x26, T27 x27, T28 x28, T29 x29, T30 x30, T31 x31, T32 x32,
+ T33 x33, T34 x34, T35 x35, T36 x36, T37 x37, T38 x38, T39 x39, T40 x40, T41 x41, T42 x42,
+ T43 x43, T44 x44, T45 x45, T46 x46, T47 x47, T48 x48, T49 x49, T50 x50, T51 x51, T52 x52,
+ T53 x53, T54 x54, T55 x55, T56 x56, T57 x57, T58 x58, T59 x59, T60 x60, T61 x61, T62 x62,
+ T63 x63, T64 x64, T65 x65, T66 x66, T67 x67, T68 x68, T69 x69, T70 x70, T71 x71, T72 x72,
+ T73 x73, T74 x74, T75 x75, T76 x76, T77 x77, T78 x78, T79 x79, T80 x80, T81 x81, T82 x82,
+ T83 x83, T84 x84, T85 x85, T86 x86, T87 x87, T88 x88, T89 x89, T90 x90, T91 x91, T92 x92,
+ T93 x93, T94 x94, T95 x95, T96 x96, T97 x97, T98 x98, T99 x99, T100 x100) { return null; }
+
+ Object test() {
+ return foo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100); // type inference expected
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.java Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,33 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8074381
+ * @summary java.lang.AssertionError during compiling
+ * @compile/fail/ref=T8074381a.out -XDrawDiagnostics T8074381a.java
+ */
+class T8074381a {
+ interface Sup<X> {
+ boolean m(X x);
+ }
+
+ interface Sub<X> extends Sup<String> {
+ boolean m(String s);
+ }
+
+ void testRaw() {
+ Sub s1 = c -> true;
+ Sub s2 = Boolean::new;
+ Sub s3 = new Sub() {
+ @Override
+ public boolean m(String o) { return true; }
+ };
+ }
+
+ void testNonRaw() {
+ Sub<Integer> s1 = c -> true;
+ Sub<Integer> s2 = Boolean::new;
+ Sub<Integer> s3 = new Sub<Integer>() {
+ @Override
+ public boolean m(String o) { return true; }
+ };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381a.out Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,4 @@
+T8074381a.java:17:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub)
+T8074381a.java:18:18: compiler.err.prob.found.req: (compiler.misc.no.suitable.functional.intf.inst: T8074381a.Sub)
+T8074381a.java:19:28: compiler.err.does.not.override.abstract: compiler.misc.anonymous.class: T8074381a$1, m(java.lang.Object), T8074381a.Sup
+3 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.java Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,44 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8074381
+ * @summary java.lang.AssertionError during compiling
+ * @compile/fail/ref=T8074381b.out -XDrawDiagnostics T8074381b.java
+ */
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+class T8074381b {
+
+ @SuppressWarnings("unchecked")
+ public Invocation resolve(Handler handler) {
+ return new Invocation((t) -> handler.handle((String) t));
+ }
+
+ public static class Handler {
+ public void handle(String s) {
+ System.out.println(s);
+ }
+ }
+
+ public static class Invocation<T> {
+ public final ThrowingConsumer<T> consumer;
+
+ public Invocation(final ThrowingConsumer<T> consumer) {
+ this.consumer = consumer;
+ }
+ }
+
+ @FunctionalInterface
+ public interface ThrowingConsumer<T> extends BiConsumer<T,Consumer<Throwable>> {
+ @Override
+ default void accept(final T elem, final Consumer<Throwable> errorHandler) {
+ try {
+ acceptThrows(elem);
+ } catch (final Throwable e) {
+ errorHandler.accept(e);
+ }
+ }
+
+ void acceptThrows(T elem) throws Throwable;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8074381/T8074381b.out Thu Mar 19 16:13:40 2015 -0700
@@ -0,0 +1,2 @@
+T8074381b.java:14:16: compiler.err.cant.apply.symbol: kindname.constructor, Invocation, T8074381b.ThrowingConsumer, @383, kindname.class, T8074381b.Invocation<T>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: T8074381b.ThrowingConsumer))
+1 error