This commit is contained in:
Lana Steuck 2012-10-08 15:40:27 -07:00
commit babd792880
153 changed files with 6680 additions and 1236 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2012, 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
@ -195,10 +195,7 @@ public class ClassUseWriter extends SubWriterHolderWriter {
ClassUseWriter clsgen;
String path = DirectoryManager.getDirectoryPath(classdoc.
containingPackage());
if (path.length() > 0) {
path += File.separator;
}
path += "class-use";
path += "class-use" + DirectoryManager.URL_FILE_SEPARATOR;
String filename = classdoc.name() + ".html";
String pkgname = classdoc.containingPackage().name();
pkgname += (pkgname.length() > 0)? ".class-use": "class-use";

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2012, 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
@ -302,7 +302,9 @@ public class HelpWriter extends HtmlDocletWriter {
Content constHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
getResource("doclet.Constants_Summary"));
Content liConst = HtmlTree.LI(HtmlStyle.blockList, constHead);
Content line29 = getResource("doclet.Help_line_29");
Content line29 = getResource("doclet.Help_line_29",
getHyperLinkString("constant-values.html",
configuration.getText("doclet.Constants_Summary")));
Content constPara = HtmlTree.P(line29);
liConst.addContent(constPara);
ul.addContent(liConst);

View File

@ -160,7 +160,7 @@ doclet.Help_line_25=Frames/No Frames
doclet.Help_line_26=These links show and hide the HTML frames. All pages are available with or without frames.
doclet.Help_line_27=The {0} link shows all classes and interfaces except non-static nested types.
doclet.Help_line_28=Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
doclet.Help_line_29=The <a href="constant-values.html">Constant Field Values</a> page lists the static final fields and their values.
doclet.Help_line_29=The {0} page lists the static final fields and their values.
doclet.Help_line_30=This help file applies to API documentation generated using the standard doclet.
doclet.Help_enum_line_1=Each enum has its own separate page with the following sections:
doclet.Help_enum_line_2=Enum declaration

View File

@ -488,17 +488,18 @@ public abstract class Configuration {
}
/**
* Add a traliling file separator, if not found or strip off extra trailing
* file separators if any.
* Add a trailing file separator, if not found. Remove superfluous
* file separators if any. Preserve the front double file separator for
* UNC paths.
*
* @param path Path under consideration.
* @return String Properly constructed path string.
*/
String addTrailingFileSep(String path) {
public static String addTrailingFileSep(String path) {
String fs = System.getProperty("file.separator");
String dblfs = fs + fs;
int indexDblfs;
while ((indexDblfs = path.indexOf(dblfs)) >= 0) {
while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {
path = path.substring(0, indexDblfs) +
path.substring(indexDblfs + fs.length());
}

View File

@ -262,11 +262,7 @@ public class TagletManager {
urls[count++] = url;
}
}
if (urls.length != count) {
URL[] tmp = new URL[count];
System.arraycopy(urls, 0, tmp, 0, count);
urls = tmp;
}
urls = Arrays.copyOf(urls, count);
return urls;
}

View File

@ -136,4 +136,11 @@ public class BasicJavacTask extends JavacTask {
throw new IllegalStateException();
}
/**
* For internal use only. This method will be
* removed without warning.
*/
public void updateContext(Context newContext) {
context = newContext;
}
}

View File

@ -79,10 +79,8 @@ public class MultiTaskListener implements TaskListener {
if (ccw.unwrap(l) == listener)
throw new IllegalStateException();
}
TaskListener[] newListeners = new TaskListener[listeners.length + 1];
System.arraycopy(listeners, 0, newListeners, 0, listeners.length);
newListeners[newListeners.length - 1] = ccw.wrap(listener);
listeners = newListeners;
listeners = Arrays.copyOf(listeners, listeners.length + 1);
listeners[listeners.length - 1] = ccw.wrap(listener);
}
public void remove(TaskListener listener) {

View File

@ -28,6 +28,7 @@ package com.sun.tools.javac.code;
import java.util.EnumSet;
import java.util.Locale;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.tools.javac.api.Formattable;
import com.sun.tools.javac.api.Messages;
@ -85,11 +86,12 @@ public class Kinds {
public static final int AMBIGUOUS = ERRONEOUS+1; // ambiguous reference
public static final int HIDDEN = ERRONEOUS+2; // hidden method or field
public static final int STATICERR = ERRONEOUS+3; // nonstatic member from static context
public static final int ABSENT_VAR = ERRONEOUS+4; // missing variable
public static final int WRONG_MTHS = ERRONEOUS+5; // methods with wrong arguments
public static final int WRONG_MTH = ERRONEOUS+6; // one method with wrong arguments
public static final int ABSENT_MTH = ERRONEOUS+7; // missing method
public static final int ABSENT_TYP = ERRONEOUS+8; // missing type
public static final int MISSING_ENCL = ERRONEOUS+4; // missing enclosing class
public static final int ABSENT_VAR = ERRONEOUS+5; // missing variable
public static final int WRONG_MTHS = ERRONEOUS+6; // methods with wrong arguments
public static final int WRONG_MTH = ERRONEOUS+7; // one method with wrong arguments
public static final int ABSENT_MTH = ERRONEOUS+8; // missing method
public static final int ABSENT_TYP = ERRONEOUS+9; // missing type
public enum KindName implements Formattable {
ANNOTATION("kindname.annotation"),
@ -140,6 +142,14 @@ public class Kinds {
}
}
public static KindName kindName(MemberReferenceTree.ReferenceMode mode) {
switch (mode) {
case INVOKE: return KindName.METHOD;
case NEW: return KindName.CONSTRUCTOR;
default : throw new AssertionError("Unexpected mode: "+ mode);
}
}
/** A KindName representing a given symbol
*/
public static KindName kindName(Symbol sym) {

View File

@ -30,6 +30,10 @@ import java.util.Locale;
import com.sun.tools.javac.api.Messages;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.Pretty;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
@ -51,6 +55,8 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
List<Type> seenCaptured = List.nil();
static final int PRIME = 997; // largest prime less than 1000
protected Printer() { }
/**
* This method should be overriden in order to provide proper i18n support.
*

View File

@ -194,6 +194,9 @@ public enum Source {
public boolean allowObjectToPrimitiveCast() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowPoly() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowLambda() {
return compareTo(JDK1_8) >= 0;
}

View File

@ -168,6 +168,10 @@ public abstract class Symbol implements Element {
return owner;
}
public Symbol baseSymbol() {
return this;
}
/** The symbol's erased type.
*/
public Type erasure(Types types) {
@ -918,7 +922,12 @@ public abstract class Symbol implements Element {
/** Clone this symbol with new owner.
*/
public VarSymbol clone(Symbol newOwner) {
VarSymbol v = new VarSymbol(flags_field, name, type, newOwner);
VarSymbol v = new VarSymbol(flags_field, name, type, newOwner) {
@Override
public Symbol baseSymbol() {
return VarSymbol.this;
}
};
v.pos = pos;
v.adr = adr;
v.data = data;
@ -1045,7 +1054,12 @@ public abstract class Symbol implements Element {
/** Clone this symbol with new owner.
*/
public MethodSymbol clone(Symbol newOwner) {
MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner);
MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner) {
@Override
public Symbol baseSymbol() {
return MethodSymbol.this;
}
};
m.code = code;
return m;
}
@ -1068,6 +1082,10 @@ public abstract class Symbol implements Element {
}
}
public boolean isDynamic() {
return false;
}
/** find a symbol that this (proxy method) symbol implements.
* @param c The class whose members are searched for
* implementations
@ -1356,6 +1374,27 @@ public abstract class Symbol implements Element {
}
}
/** A class for invokedynamic method calls.
*/
public static class DynamicMethodSymbol extends MethodSymbol {
public Object[] staticArgs;
public Symbol bsm;
public int bsmKind;
public DynamicMethodSymbol(Name name, Symbol owner, int bsmKind, MethodSymbol bsm, Type type, Object[] staticArgs) {
super(0, name, type, owner);
this.bsm = bsm;
this.bsmKind = bsmKind;
this.staticArgs = staticArgs;
}
@Override
public boolean isDynamic() {
return true;
}
}
/** A class for predefined operators.
*/
public static class OperatorSymbol extends MethodSymbol {

View File

@ -126,6 +126,7 @@ public class Symtab {
public final Type cloneableType;
public final Type serializableType;
public final Type methodHandleType;
public final Type methodTypeType;
public final Type nativeHeaderType;
public final Type throwableType;
public final Type errorType;
@ -182,6 +183,10 @@ public class Symtab {
*/
public final Name[] boxedName = new Name[TypeTags.TypeTagCount];
/** A set containing all operator names.
*/
public final Set<Name> operatorNames = new HashSet<Name>();
/** A hashtable containing the encountered top-level and member classes,
* indexed by flat names. The table does not contain local classes.
* It should be updated from the outside to reflect classes defined
@ -243,7 +248,7 @@ public class Symtab {
int opcode) {
predefClass.members().enter(
new OperatorSymbol(
names.fromString(name),
makeOperatorName(name),
new MethodType(List.of(left, right), res,
List.<Type>nil(), methodClass),
opcode,
@ -274,7 +279,7 @@ public class Symtab {
Type res,
int opcode) {
OperatorSymbol sym =
new OperatorSymbol(names.fromString(name),
new OperatorSymbol(makeOperatorName(name),
new MethodType(List.of(arg),
res,
List.<Type>nil(),
@ -285,6 +290,16 @@ public class Symtab {
return sym;
}
/**
* Create a new operator name from corresponding String representation
* and add the name to the set of known operator names.
*/
private Name makeOperatorName(String name) {
Name opName = names.fromString(name);
operatorNames.add(opName);
return opName;
}
/** Enter a class into symbol table.
* @param The name of the class.
*/
@ -440,6 +455,7 @@ public class Symtab {
throwableType = enterClass("java.lang.Throwable");
serializableType = enterClass("java.io.Serializable");
methodHandleType = enterClass("java.lang.invoke.MethodHandle");
methodTypeType = enterClass("java.lang.invoke.MethodType");
errorType = enterClass("java.lang.Error");
illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
interruptedExceptionType = enterClass("java.lang.InterruptedException");

View File

@ -27,14 +27,19 @@ package com.sun.tools.javac.code;
import java.util.Collections;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.util.*;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.type.*;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.TypeTags.*;
/** This class represents Java types. The class itself defines the behavior of
@ -70,6 +75,9 @@ public class Type implements PrimitiveType {
/** Constant type: no type at all. */
public static final JCNoType noType = new JCNoType(NONE);
/** Constant type: special type to be used during recovery of deferred expressions. */
public static final JCNoType recoveryType = new JCNoType(NONE);
/** If this switch is turned on, the names of type variables
* and anonymous classes are printed with hashcodes appended.
*/
@ -1168,22 +1176,59 @@ public class Type implements PrimitiveType {
}
}
/** A class for instantiatable variables, for use during type
* inference.
/** A class for inference variables, for use during method/diamond type
* inference. An inference variable has upper/lower bounds and a set
* of equality constraints. Such bounds are set during subtyping, type-containment,
* type-equality checks, when the types being tested contain inference variables.
* A change listener can be attached to an inference variable, to receive notifications
* whenever the bounds of an inference variable change.
*/
public static class UndetVar extends DelegatedType {
public List<Type> lobounds = List.nil();
public List<Type> hibounds = List.nil();
public List<Type> eq = List.nil();
/** Inference variable change listener. The listener method is called
* whenever a change to the inference variable's bounds occurs
*/
public interface UndetVarListener {
/** called when some inference variable bounds (of given kinds ibs) change */
void varChanged(UndetVar uv, Set<InferenceBound> ibs);
}
/**
* Inference variable bound kinds
*/
public enum InferenceBound {
/** upper bounds */
UPPER,
/** lower bounds */
LOWER,
/** equality constraints */
EQ;
}
/** inference variable bounds */
private Map<InferenceBound, List<Type>> bounds;
/** inference variable's inferred type (set from Infer.java) */
public Type inst = null;
/** inference variable's change listener */
public UndetVarListener listener = null;
@Override
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
return v.visitUndetVar(this, s);
}
public UndetVar(Type origin) {
public UndetVar(TypeVar origin, Types types) {
this(origin, types, true);
}
public UndetVar(TypeVar origin, Types types, boolean includeBounds) {
super(UNDETVAR, origin);
bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
bounds.put(InferenceBound.UPPER, includeBounds ? types.getBounds(origin) : List.<Type>nil());
bounds.put(InferenceBound.LOWER, List.<Type>nil());
bounds.put(InferenceBound.EQ, List.<Type>nil());
}
public String toString() {
@ -1195,6 +1240,48 @@ public class Type implements PrimitiveType {
if (inst != null) return inst.baseType();
else return this;
}
/** get all bounds of a given kind */
public List<Type> getBounds(InferenceBound ib) {
return bounds.get(ib);
}
/** add a bound of a given kind - this might trigger listener notification */
public void addBound(InferenceBound ib, Type bound, Types types) {
List<Type> prevBounds = bounds.get(ib);
for (Type b : prevBounds) {
if (types.isSameType(b, bound)) {
return;
}
}
bounds.put(ib, prevBounds.prepend(bound));
notifyChange(EnumSet.of(ib));
}
/** replace types in all bounds - this might trigger listener notification */
public void substBounds(List<Type> from, List<Type> to, Types types) {
EnumSet<InferenceBound> changed = EnumSet.noneOf(InferenceBound.class);
Map<InferenceBound, List<Type>> bounds2 = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
InferenceBound ib = _entry.getKey();
List<Type> prevBounds = _entry.getValue();
List<Type> newBounds = types.subst(prevBounds, from, to);
bounds2.put(ib, newBounds);
if (prevBounds != newBounds) {
changed.add(ib);
}
}
if (!changed.isEmpty()) {
bounds = bounds2;
notifyChange(changed);
}
}
private void notifyChange(EnumSet<InferenceBound> ibs) {
if (listener != null) {
listener.varChanged(this, ibs);
}
}
}
/** Represents VOID or NONE.

View File

@ -102,9 +102,13 @@ public class TypeTags {
*/
public static final int FORALL = WILDCARD+1;
/** The tag of deferred expression types in method context
*/
public static final int DEFERRED = FORALL+1;
/** The tag of the bottom type <null>.
*/
public static final int BOT = FORALL+1;
public static final int BOT = DEFERRED+1;
/** The tag of a missing type.
*/

View File

@ -34,6 +34,7 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.comp.Check;
import static com.sun.tools.javac.code.Scope.*;
@ -78,8 +79,10 @@ public class Types {
final boolean allowObjectToPrimitiveCast;
final ClassReader reader;
final Check chk;
JCDiagnostic.Factory diags;
List<Warner> warnStack = List.nil();
final Name capturedName;
private final FunctionDescriptorLookupError functionDescriptorLookupError;
// <editor-fold defaultstate="collapsed" desc="Instantiating">
public static Types instance(Context context) {
@ -101,6 +104,8 @@ public class Types {
chk = Check.instance(context);
capturedName = names.fromString("<captured wildcard>");
messages = JavacMessages.instance(context);
diags = JCDiagnostic.Factory.instance(context);
functionDescriptorLookupError = new FunctionDescriptorLookupError();
}
// </editor-fold>
@ -295,6 +300,294 @@ public class Types {
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="findSam">
/**
* Exception used to report a function descriptor lookup failure. The exception
* wraps a diagnostic that can be used to generate more details error
* messages.
*/
public static class FunctionDescriptorLookupError extends RuntimeException {
private static final long serialVersionUID = 0;
JCDiagnostic diagnostic;
FunctionDescriptorLookupError() {
this.diagnostic = null;
}
FunctionDescriptorLookupError setMessage(JCDiagnostic diag) {
this.diagnostic = diag;
return this;
}
public JCDiagnostic getDiagnostic() {
return diagnostic;
}
}
/**
* A cache that keeps track of function descriptors associated with given
* functional interfaces.
*/
class DescriptorCache {
private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<TypeSymbol, Entry>();
class FunctionDescriptor {
Symbol descSym;
FunctionDescriptor(Symbol descSym) {
this.descSym = descSym;
}
public Symbol getSymbol() {
return descSym;
}
public Type getType(Type origin) {
return memberType(origin, descSym);
}
}
class Entry {
final FunctionDescriptor cachedDescRes;
final int prevMark;
public Entry(FunctionDescriptor cachedDescRes,
int prevMark) {
this.cachedDescRes = cachedDescRes;
this.prevMark = prevMark;
}
boolean matches(int mark) {
return this.prevMark == mark;
}
}
FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError {
Entry e = _map.get(origin);
CompoundScope members = membersClosure(origin.type, false);
if (e == null ||
!e.matches(members.getMark())) {
FunctionDescriptor descRes = findDescriptorInternal(origin, members);
_map.put(origin, new Entry(descRes, members.getMark()));
return descRes;
}
else {
return e.cachedDescRes;
}
}
/**
* Scope filter used to skip methods that should be ignored during
* function interface conversion (such as methods overridden by
* j.l.Object)
*/
class DescriptorFilter implements Filter<Symbol> {
TypeSymbol origin;
DescriptorFilter(TypeSymbol origin) {
this.origin = origin;
}
@Override
public boolean accepts(Symbol sym) {
return sym.kind == Kinds.MTH &&
(sym.flags() & ABSTRACT) != 0 &&
!overridesObjectMethod(origin, sym) &&
notOverridden(sym);
}
private boolean notOverridden(Symbol msym) {
Symbol impl = ((MethodSymbol)msym).implementation(origin, Types.this, false);
return impl == null || (impl.flags() & ABSTRACT) != 0;
}
};
/**
* Compute the function descriptor associated with a given functional interface
*/
public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError {
if (!origin.isInterface()) {
//t must be an interface
throw failure("not.a.functional.intf");
}
final ListBuffer<Symbol> abstracts = ListBuffer.lb();
for (Symbol sym : membersCache.getElements(new DescriptorFilter(origin))) {
Type mtype = memberType(origin.type, sym);
if (abstracts.isEmpty() ||
(sym.name == abstracts.first().name &&
overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) {
abstracts.append(sym);
} else {
//the target method(s) should be the only abstract members of t
throw failure("not.a.functional.intf.1",
diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin));
}
}
if (abstracts.isEmpty()) {
//t must define a suitable non-generic method
throw failure("not.a.functional.intf.1",
diags.fragment("no.abstracts", Kinds.kindName(origin), origin));
} else if (abstracts.size() == 1) {
if (abstracts.first().type.tag == FORALL) {
throw failure("invalid.generic.desc.in.functional.intf",
abstracts.first(),
Kinds.kindName(origin),
origin);
} else {
return new FunctionDescriptor(abstracts.first());
}
} else { // size > 1
for (Symbol msym : abstracts) {
if (msym.type.tag == FORALL) {
throw failure("invalid.generic.desc.in.functional.intf",
abstracts.first(),
Kinds.kindName(origin),
origin);
}
}
FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList());
if (descRes == null) {
//we can get here if the functional interface is ill-formed
ListBuffer<JCDiagnostic> descriptors = ListBuffer.lb();
for (Symbol desc : abstracts) {
String key = desc.type.getThrownTypes().nonEmpty() ?
"descriptor.throws" : "descriptor";
descriptors.append(diags.fragment(key, desc.name,
desc.type.getParameterTypes(),
desc.type.getReturnType(),
desc.type.getThrownTypes()));
}
JCDiagnostic.MultilineDiagnostic incompatibleDescriptors =
new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf",
Kinds.kindName(origin), origin), descriptors.toList());
throw failure(incompatibleDescriptors);
}
return descRes;
}
}
/**
* Compute a synthetic type for the target descriptor given a list
* of override-equivalent methods in the functional interface type.
* The resulting method type is a method type that is override-equivalent
* and return-type substitutable with each method in the original list.
*/
private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) {
//pick argument types - simply take the signature that is a
//subsignature of all other signatures in the list (as per JLS 8.4.2)
List<Symbol> mostSpecific = List.nil();
outer: for (Symbol msym1 : methodSyms) {
Type mt1 = memberType(origin.type, msym1);
for (Symbol msym2 : methodSyms) {
Type mt2 = memberType(origin.type, msym2);
if (!isSubSignature(mt1, mt2)) {
continue outer;
}
}
mostSpecific = mostSpecific.prepend(msym1);
}
if (mostSpecific.isEmpty()) {
return null;
}
//pick return types - this is done in two phases: (i) first, the most
//specific return type is chosen using strict subtyping; if this fails,
//a second attempt is made using return type substitutability (see JLS 8.4.5)
boolean phase2 = false;
Symbol bestSoFar = null;
while (bestSoFar == null) {
outer: for (Symbol msym1 : mostSpecific) {
Type mt1 = memberType(origin.type, msym1);
for (Symbol msym2 : methodSyms) {
Type mt2 = memberType(origin.type, msym2);
if (phase2 ?
!returnTypeSubstitutable(mt1, mt2) :
!isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) {
continue outer;
}
}
bestSoFar = msym1;
}
if (phase2) {
break;
} else {
phase2 = true;
}
}
if (bestSoFar == null) return null;
//merge thrown types - form the intersection of all the thrown types in
//all the signatures in the list
List<Type> thrown = null;
for (Symbol msym1 : methodSyms) {
Type mt1 = memberType(origin.type, msym1);
thrown = (thrown == null) ?
mt1.getThrownTypes() :
chk.intersect(mt1.getThrownTypes(), thrown);
}
final List<Type> thrown1 = thrown;
return new FunctionDescriptor(bestSoFar) {
@Override
public Type getType(Type origin) {
Type mt = memberType(origin, getSymbol());
return new MethodType(mt.getParameterTypes(), mt.getReturnType(), thrown1, syms.methodClass);
}
};
}
boolean isSubtypeInternal(Type s, Type t) {
return (s.isPrimitive() && t.isPrimitive()) ?
isSameType(t, s) :
isSubtype(s, t);
}
FunctionDescriptorLookupError failure(String msg, Object... args) {
return failure(diags.fragment(msg, args));
}
FunctionDescriptorLookupError failure(JCDiagnostic diag) {
return functionDescriptorLookupError.setMessage(diag);
}
}
private DescriptorCache descCache = new DescriptorCache();
/**
* Find the method descriptor associated to this class symbol - if the
* symbol 'origin' is not a functional interface, an exception is thrown.
*/
public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError {
return descCache.get(origin).getSymbol();
}
/**
* Find the type of the method descriptor associated to this class symbol -
* if the symbol 'origin' is not a functional interface, an exception is thrown.
*/
public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError {
return descCache.get(origin.tsym).getType(origin);
}
/**
* Is given type a functional interface?
*/
public boolean isFunctionalInterface(TypeSymbol tsym) {
try {
findDescriptorSymbol(tsym);
return true;
} catch (FunctionDescriptorLookupError ex) {
return false;
}
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="isSubtype">
/**
* Is t an unchecked subtype of s?
@ -510,7 +803,7 @@ public class Types {
return false;
}
t.hibounds = t.hibounds.prepend(s);
t.addBound(InferenceBound.UPPER, s, Types.this);
return true;
}
@ -578,7 +871,7 @@ public class Types {
undet.qtype == s ||
s.tag == ERROR ||
s.tag == BOT) return true;
undet.lobounds = undet.lobounds.prepend(s);
undet.addBound(InferenceBound.LOWER, s, this);
return true;
}
default:
@ -723,7 +1016,7 @@ public class Types {
if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN)
return true;
t.eq = t.eq.prepend(s);
t.addBound(InferenceBound.EQ, s, Types.this);
return true;
}
@ -735,19 +1028,6 @@ public class Types {
};
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="fromUnknownFun">
/**
* A mapping that turns all unknown types in this type to fresh
* unknown variables.
*/
public Mapping fromUnknownFun = new Mapping("fromUnknownFun") {
public Type apply(Type t) {
if (t.tag == UNKNOWN) return new UndetVar(t);
else return t.map(this);
}
};
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Contains Type">
public boolean containedBy(Type t, Type s) {
switch (t.tag) {
@ -759,12 +1039,12 @@ public class Types {
case UNBOUND: //similar to ? extends Object
case EXTENDS: {
Type bound = upperBound(s);
undetvar.hibounds = undetvar.hibounds.prepend(bound);
undetvar.addBound(InferenceBound.UPPER, bound, this);
break;
}
case SUPER: {
Type bound = lowerBound(s);
undetvar.lobounds = undetvar.lobounds.prepend(bound);
undetvar.addBound(InferenceBound.LOWER, bound, this);
break;
}
}
@ -1227,7 +1507,10 @@ public class Types {
* Returns the lower bounds of the formals of a method.
*/
public List<Type> lowerBoundArgtypes(Type t) {
return map(t.getParameterTypes(), lowerBoundMapping);
return lowerBounds(t.getParameterTypes());
}
public List<Type> lowerBounds(List<Type> ts) {
return map(ts, lowerBoundMapping);
}
private final Mapping lowerBoundMapping = new Mapping("lowerBound") {
public Type apply(Type t) {
@ -2019,6 +2302,15 @@ public class Types {
hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
}
public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) {
for (Scope.Entry e = syms.objectType.tsym.members().lookup(msym.name) ; e.scope != null ; e = e.next()) {
if (msym.overrides(e.sym, origin, Types.this, true)) {
return true;
}
}
return false;
}
// <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
class ImplementationCache {
@ -3166,6 +3458,14 @@ public class Types {
}
return Type.noType;
}
/**
* Return the unboxed type if 't' is a boxed class, otherwise return 't' itself.
*/
public Type unboxedTypeOrType(Type t) {
Type unboxedType = unboxedType(t);
return unboxedType.tag == NONE ? t : unboxedType;
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Capture conversion">

View File

@ -514,22 +514,6 @@ public class Annotate {
expectedType);
fatalError = true;
}
// validate that all other elements of containing type has defaults
scope = targetContainerType.tsym.members();
error = false;
for(Symbol elm : scope.getElements()) {
if (elm.name != names.value &&
elm.kind == Kinds.MTH &&
((MethodSymbol)elm).defaultValue == null) {
log.error(pos,
"invalid.containedby.annotation.elem.nondefault",
targetContainerType,
elm);
containerValueSymbol = null;
error = true;
}
}
if (error) {
fatalError = true;
}

File diff suppressed because it is too large Load Diff

View File

@ -56,7 +56,7 @@ public class AttrContext {
/** Are arguments to current function applications boxed into an array for varargs?
*/
boolean varArgs = false;
Resolve.MethodResolutionPhase pendingResolutionPhase = null;
/** A record of the lint/SuppressWarnings currently in effect
*/
@ -67,6 +67,11 @@ public class AttrContext {
*/
Symbol enclVar = null;
/** ResultInfo to be used for attributing 'return' statement expressions
* (set by Attr.visitMethod and Attr.visitLambda)
*/
Attr.ResultInfo returnResult = null;
/** Duplicate this context, replacing scope field and copying all others.
*/
AttrContext dup(Scope scope) {
@ -75,9 +80,10 @@ public class AttrContext {
info.staticLevel = staticLevel;
info.isSelfCall = isSelfCall;
info.selectSuper = selectSuper;
info.varArgs = varArgs;
info.pendingResolutionPhase = pendingResolutionPhase;
info.lint = lint;
info.enclVar = enclVar;
info.returnResult = returnResult;
return info;
}
@ -93,6 +99,11 @@ public class AttrContext {
return scope.getElements();
}
boolean lastResolveVarargs() {
return pendingResolutionPhase != null &&
pendingResolutionPhase.isVarargsRequired();
}
public String toString() {
return "AttrContext[" + scope.toString() + "]";
}

View File

@ -40,6 +40,9 @@ import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.ANNOTATION;
@ -66,6 +69,7 @@ public class Check {
private final Resolve rs;
private final Symtab syms;
private final Enter enter;
private final DeferredAttr deferredAttr;
private final Infer infer;
private final Types types;
private final JCDiagnostic.Factory diags;
@ -98,6 +102,7 @@ public class Check {
rs = Resolve.instance(context);
syms = Symtab.instance(context);
enter = Enter.instance(context);
deferredAttr = DeferredAttr.instance(context);
infer = Infer.instance(context);
this.types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
@ -416,7 +421,7 @@ public class Check {
* checks - depending on the check context, meaning of 'compatibility' might
* vary significantly.
*/
interface CheckContext {
public interface CheckContext {
/**
* Is type 'found' compatible with type 'req' in given context
*/
@ -429,6 +434,12 @@ public class Check {
* Obtain a warner for this check context
*/
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
public Infer.InferenceContext inferenceContext();
public DeferredAttr.DeferredAttrContext deferredAttrContext();
public boolean allowBoxing();
}
/**
@ -455,6 +466,18 @@ public class Check {
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
return enclosingContext.checkWarner(pos, found, req);
}
public Infer.InferenceContext inferenceContext() {
return enclosingContext.inferenceContext();
}
public DeferredAttrContext deferredAttrContext() {
return enclosingContext.deferredAttrContext();
}
public boolean allowBoxing() {
return enclosingContext.allowBoxing();
}
}
/**
@ -471,6 +494,18 @@ public class Check {
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
return convertWarner(pos, found, req);
}
public InferenceContext inferenceContext() {
return infer.emptyContext;
}
public DeferredAttrContext deferredAttrContext() {
return deferredAttr.emptyDeferredAttrContext;
}
public boolean allowBoxing() {
return true;
}
};
/** Check that a given type is assignable to a given proto-type.
@ -483,7 +518,16 @@ public class Check {
return checkType(pos, found, req, basicHandler);
}
Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
if (inferenceContext.free(req)) {
inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
}
});
}
if (req.tag == ERROR)
return req;
if (req.tag == NONE)
@ -523,9 +567,9 @@ public class Check {
*/
public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) {
if (!tree.type.isErroneous() &&
(env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
&& types.isSameType(tree.expr.type, tree.clazz.type)
&& !is292targetTypeCast(tree)) {
(env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
&& types.isSameType(tree.expr.type, tree.clazz.type)
&& !is292targetTypeCast(tree)) {
log.warning(Lint.LintCategory.CAST,
tree.pos(), "redundant.cast", tree.expr.type);
}
@ -604,6 +648,22 @@ public class Check {
return t;
}
/** Check that type is a valid qualifier for a constructor reference expression
*/
Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
t = checkClassType(pos, t);
if (t.tag == CLASS) {
if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
log.error(pos, "abstract.cant.be.instantiated");
t = types.createErrorType(t);
} else if ((t.tsym.flags() & ENUM) != 0) {
log.error(pos, "enum.cant.be.instantiated");
t = types.createErrorType(t);
}
}
return t;
}
/** Check that type is a class or interface type.
* @param pos Position to be used for error reporting.
* @param t The type to be checked.
@ -796,29 +856,34 @@ public class Check {
sym.owner == syms.enumSym)
formals = formals.tail.tail;
List<JCExpression> args = argtrees;
while (formals.head != last) {
JCTree arg = args.head;
Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
assertConvertible(arg, arg.type, formals.head, warn);
args = args.tail;
formals = formals.tail;
}
if (useVarargs) {
Type varArg = types.elemtype(last);
while (args.tail != null) {
DeferredAttr.DeferredTypeMap checkDeferredMap =
deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
if (args != null) {
//this is null when type-checking a method reference
while (formals.head != last) {
JCTree arg = args.head;
Warner warn = convertWarner(arg.pos(), arg.type, varArg);
assertConvertible(arg, arg.type, varArg, warn);
Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
assertConvertible(arg, arg.type, formals.head, warn);
args = args.tail;
formals = formals.tail;
}
if (useVarargs) {
Type varArg = types.elemtype(last);
while (args.tail != null) {
JCTree arg = args.head;
Warner warn = convertWarner(arg.pos(), arg.type, varArg);
assertConvertible(arg, arg.type, varArg, warn);
args = args.tail;
}
} else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
// non-varargs call to varargs method
Type varParam = owntype.getParameterTypes().last();
Type lastArg = checkDeferredMap.apply(argtypes.last());
if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
!types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
types.elemtype(varParam), varParam);
}
} else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
// non-varargs call to varargs method
Type varParam = owntype.getParameterTypes().last();
Type lastArg = argtypes.last();
if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
!types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
types.elemtype(varParam), varParam);
}
if (unchecked) {
warnUnchecked(env.tree.pos(),
@ -826,7 +891,7 @@ public class Check {
kindName(sym),
sym.name,
rs.methodArguments(sym.type.getParameterTypes()),
rs.methodArguments(argtypes),
rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
kindName(sym.location()),
sym.location());
owntype = new MethodType(owntype.getParameterTypes(),
@ -853,6 +918,9 @@ public class Check {
case NEWCLASS:
((JCNewClass) tree).varargsElement = elemtype;
break;
case REFERENCE:
((JCMemberReference) tree).varargsElement = elemtype;
break;
default:
throw new AssertionError(""+tree);
}
@ -870,6 +938,65 @@ public class Check {
return;
}
void checkAccessibleFunctionalDescriptor(DiagnosticPosition pos, Env<AttrContext> env, Type desc) {
AccessChecker accessChecker = new AccessChecker(env);
//check args accessibility (only if implicit parameter types)
for (Type arg : desc.getParameterTypes()) {
if (!accessChecker.visit(arg)) {
log.error(pos, "cant.access.arg.type.in.functional.desc", arg);
return;
}
}
//check return type accessibility
if (!accessChecker.visit(desc.getReturnType())) {
log.error(pos, "cant.access.return.in.functional.desc", desc.getReturnType());
return;
}
//check thrown types accessibility
for (Type thrown : desc.getThrownTypes()) {
if (!accessChecker.visit(thrown)) {
log.error(pos, "cant.access.thrown.in.functional.desc", thrown);
return;
}
}
}
class AccessChecker extends Types.UnaryVisitor<Boolean> {
Env<AttrContext> env;
AccessChecker(Env<AttrContext> env) {
this.env = env;
}
Boolean visit(List<Type> ts) {
for (Type t : ts) {
if (!visit(t))
return false;
}
return true;
}
public Boolean visitType(Type t, Void s) {
return true;
}
@Override
public Boolean visitArrayType(ArrayType t, Void s) {
return visit(t.elemtype);
}
@Override
public Boolean visitClassType(ClassType t, Void s) {
return rs.isAccessible(env, t, true) &&
visit(t.getTypeArguments());
}
@Override
public Boolean visitWildcardType(WildcardType t, Void s) {
return visit(t.type);
}
};
/**
* Check that type 't' is a valid instantiation of a generic class
* (see JLS 4.5)
@ -2470,6 +2597,7 @@ public class Check {
validateDocumented(t.tsym, s, pos);
validateInherited(t.tsym, s, pos);
validateTarget(t.tsym, s, pos);
validateDefault(t.tsym, s, pos);
}
/**
@ -2650,6 +2778,21 @@ public class Check {
return true;
}
private void validateDefault(Symbol container, Symbol contained, DiagnosticPosition pos) {
// validate that all other elements of containing type has defaults
Scope scope = container.members();
for(Symbol elm : scope.getElements()) {
if (elm.name != names.value &&
elm.kind == Kinds.MTH &&
((MethodSymbol)elm).defaultValue == null) {
log.error(pos,
"invalid.containedby.annotation.elem.nondefault",
container,
elm);
}
}
}
/** Is s a method symbol that overrides a method in a superclass? */
boolean isOverrider(Symbol s) {
if (s.kind != MTH || s.isStatic())

View File

@ -0,0 +1,640 @@
/*
* Copyright (c) 2012, 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.
*/
package com.sun.tools.javac.comp;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.comp.Attr.ResultInfo;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
import com.sun.tools.javac.tree.JCTree.*;
import javax.tools.JavaFileObject;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.WeakHashMap;
import static com.sun.tools.javac.code.TypeTags.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
* This is an helper class that is used to perform deferred type-analysis.
* Each time a poly expression occurs in argument position, javac attributes it
* with a temporary 'deferred type' that is checked (possibly multiple times)
* against an expected formal type.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class DeferredAttr extends JCTree.Visitor {
protected static final Context.Key<DeferredAttr> deferredAttrKey =
new Context.Key<DeferredAttr>();
final Attr attr;
final Check chk;
final Enter enter;
final Infer infer;
final Log log;
final Symtab syms;
final TreeMaker make;
final Types types;
public static DeferredAttr instance(Context context) {
DeferredAttr instance = context.get(deferredAttrKey);
if (instance == null)
instance = new DeferredAttr(context);
return instance;
}
protected DeferredAttr(Context context) {
context.put(deferredAttrKey, this);
attr = Attr.instance(context);
chk = Check.instance(context);
enter = Enter.instance(context);
infer = Infer.instance(context);
log = Log.instance(context);
syms = Symtab.instance(context);
make = TreeMaker.instance(context);
types = Types.instance(context);
}
/**
* This type represents a deferred type. A deferred type starts off with
* no information on the underlying expression type. Such info needs to be
* discovered through type-checking the deferred type against a target-type.
* Every deferred type keeps a pointer to the AST node from which it originated.
*/
public class DeferredType extends Type {
public JCExpression tree;
Env<AttrContext> env;
AttrMode mode;
SpeculativeCache speculativeCache;
DeferredType(JCExpression tree, Env<AttrContext> env) {
super(DEFERRED, null);
this.tree = tree;
this.env = env.dup(tree, env.info.dup());
this.speculativeCache = new SpeculativeCache();
}
/**
* A speculative cache is used to keep track of all overload resolution rounds
* that triggered speculative attribution on a given deferred type. Each entry
* stores a pointer to the speculative tree and the resolution phase in which the entry
* has been added.
*/
class SpeculativeCache {
private Map<Symbol, List<Entry>> cache =
new WeakHashMap<Symbol, List<Entry>>();
class Entry {
JCTree speculativeTree;
Resolve.MethodResolutionPhase phase;
public Entry(JCTree speculativeTree, MethodResolutionPhase phase) {
this.speculativeTree = speculativeTree;
this.phase = phase;
}
boolean matches(Resolve.MethodResolutionPhase phase) {
return this.phase == phase;
}
}
/**
* Clone a speculative cache entry as a fresh entry associated
* with a new method (this maybe required to fixup speculative cache
* misses after Resolve.access())
*/
void dupAllTo(Symbol from, Symbol to) {
Assert.check(cache.get(to) == null);
List<Entry> entries = cache.get(from);
if (entries != null) {
cache.put(to, entries);
}
}
/**
* Retrieve a speculative cache entry corresponding to given symbol
* and resolution phase
*/
Entry get(Symbol msym, MethodResolutionPhase phase) {
List<Entry> entries = cache.get(msym);
if (entries == null) return null;
for (Entry e : entries) {
if (e.matches(phase)) return e;
}
return null;
}
/**
* Stores a speculative cache entry corresponding to given symbol
* and resolution phase
*/
void put(Symbol msym, JCTree speculativeTree, MethodResolutionPhase phase) {
List<Entry> entries = cache.get(msym);
if (entries == null) {
entries = List.nil();
}
cache.put(msym, entries.prepend(new Entry(speculativeTree, phase)));
}
}
/**
* Get the type that has been computed during a speculative attribution round
*/
Type speculativeType(Symbol msym, MethodResolutionPhase phase) {
SpeculativeCache.Entry e = speculativeCache.get(msym, phase);
return e != null ? e.speculativeTree.type : Type.noType;
}
/**
* Check a deferred type against a potential target-type. Depending on
* the current attribution mode, a normal vs. speculative attribution
* round is performed on the underlying AST node. There can be only one
* speculative round for a given target method symbol; moreover, a normal
* attribution round must follow one or more speculative rounds.
*/
Type check(ResultInfo resultInfo) {
DeferredAttrContext deferredAttrContext =
resultInfo.checkContext.deferredAttrContext();
Assert.check(deferredAttrContext != emptyDeferredAttrContext);
List<Type> stuckVars = stuckVars(tree, resultInfo);
if (stuckVars.nonEmpty()) {
deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
return Type.noType;
} else {
try {
switch (deferredAttrContext.mode) {
case SPECULATIVE:
Assert.check(mode == null ||
(mode == AttrMode.SPECULATIVE &&
speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).tag == NONE));
JCTree speculativeTree = attribSpeculative(tree, env, resultInfo);
speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
return speculativeTree.type;
case CHECK:
Assert.check(mode == AttrMode.SPECULATIVE);
return attr.attribTree(tree, env, resultInfo);
}
Assert.error();
return null;
} finally {
mode = deferredAttrContext.mode;
}
}
}
}
/**
* The 'mode' in which the deferred type is to be type-checked
*/
public enum AttrMode {
/**
* A speculative type-checking round is used during overload resolution
* mainly to generate constraints on inference variables. Side-effects
* arising from type-checking the expression associated with the deferred
* type are reversed after the speculative round finishes. This means the
* expression tree will be left in a blank state.
*/
SPECULATIVE,
/**
* This is the plain type-checking mode. Produces side-effects on the underlying AST node
*/
CHECK;
}
/**
* Routine that performs speculative type-checking; the input AST node is
* cloned (to avoid side-effects cause by Attr) and compiler state is
* restored after type-checking. All diagnostics (but critical ones) are
* disabled during speculative type-checking.
*/
JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
JCTree newTree = new TreeCopier<Object>(make).copy(tree);
Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared()));
speculativeEnv.info.scope.owner = env.info.scope.owner;
Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
Queue<JCDiagnostic> prevDeferredDiags = log.deferredDiagnostics;
final JavaFileObject currentSource = log.currentSourceFile();
try {
log.deferredDiagnostics = new ListBuffer<JCDiagnostic>();
log.deferredDiagFilter = new Filter<JCDiagnostic>() {
public boolean accepts(JCDiagnostic t) {
return t.getDiagnosticSource().getFile().equals(currentSource);
}
};
attr.attribTree(newTree, speculativeEnv, resultInfo);
unenterScanner.scan(newTree);
return newTree;
} catch (Abort ex) {
//if some very bad condition occurred during deferred attribution
//we should dump all errors before killing javac
log.reportDeferredDiagnostics();
throw ex;
} finally {
unenterScanner.scan(newTree);
log.deferredDiagFilter = prevDeferDiagsFilter;
log.deferredDiagnostics = prevDeferredDiags;
}
}
//where
protected TreeScanner unenterScanner = new TreeScanner() {
@Override
public void visitClassDef(JCClassDecl tree) {
ClassSymbol csym = tree.sym;
enter.typeEnvs.remove(csym);
chk.compiled.remove(csym.flatname);
syms.classes.remove(csym.flatname);
super.visitClassDef(tree);
}
};
/**
* A deferred context is created on each method check. A deferred context is
* used to keep track of information associated with the method check, such as
* the symbol of the method being checked, the overload resolution phase,
* the kind of attribution mode to be applied to deferred types and so forth.
* As deferred types are processed (by the method check routine) stuck AST nodes
* are added (as new deferred attribution nodes) to this context. The complete()
* routine makes sure that all pending nodes are properly processed, by
* progressively instantiating all inference variables on which one or more
* deferred attribution node is stuck.
*/
class DeferredAttrContext {
/** attribution mode */
final AttrMode mode;
/** symbol of the method being checked */
final Symbol msym;
/** method resolution step */
final Resolve.MethodResolutionPhase phase;
/** inference context */
final InferenceContext inferenceContext;
/** list of deferred attribution nodes to be processed */
ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>();
DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) {
this.mode = mode;
this.msym = msym;
this.phase = phase;
this.inferenceContext = inferenceContext;
}
/**
* Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable
* Nodes added this way act as 'roots' for the out-of-order method checking process.
*/
void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars));
}
/**
* Incrementally process all nodes, by skipping 'stuck' nodes and attributing
* 'unstuck' ones. If at any point no progress can be made (no 'unstuck' nodes)
* some inference variable might get eagerly instantiated so that all nodes
* can be type-checked.
*/
void complete() {
while (!deferredAttrNodes.isEmpty()) {
Set<Type> stuckVars = new HashSet<Type>();
boolean progress = false;
//scan a defensive copy of the node list - this is because a deferred
//attribution round can add new nodes to the list
for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
if (!deferredAttrNode.isStuck()) {
deferredAttrNode.process();
deferredAttrNodes.remove(deferredAttrNode);
progress = true;
} else {
stuckVars.addAll(deferredAttrNode.stuckVars);
}
}
if (!progress) {
//remove all variables that have already been instantiated
//from the list of stuck variables
inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)), types, infer);
inferenceContext.notifyChange(types);
}
}
}
/**
* Class representing a deferred attribution node. It keeps track of
* a deferred type, along with the expected target type information.
*/
class DeferredAttrNode implements Infer.InferenceContext.FreeTypeListener {
/** underlying deferred type */
DeferredType dt;
/** underlying target type information */
ResultInfo resultInfo;
/** list of uninferred inference variables causing this node to be stuck */
List<Type> stuckVars;
DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
this.dt = dt;
this.resultInfo = resultInfo;
this.stuckVars = stuckVars;
if (!stuckVars.isEmpty()) {
resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
}
}
@Override
public void typesInferred(InferenceContext inferenceContext) {
stuckVars = List.nil();
resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
}
/**
* is this node stuck?
*/
boolean isStuck() {
return stuckVars.nonEmpty();
}
/**
* Process a deferred attribution node.
* Invariant: a stuck node cannot be processed.
*/
void process() {
if (isStuck()) {
throw new IllegalStateException("Cannot process a stuck deferred node");
}
dt.check(resultInfo);
}
}
}
/** an empty deferred attribution context - all methods throw exceptions */
final DeferredAttrContext emptyDeferredAttrContext =
new DeferredAttrContext(null, null, null, null) {
@Override
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
Assert.error("Empty deferred context!");
}
@Override
void complete() {
Assert.error("Empty deferred context!");
}
};
/**
* 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 {
DeferredAttrContext deferredAttrContext;
protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
super(String.format("deferredTypeMap[%s]", mode));
this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext);
}
protected boolean validState(DeferredType dt) {
return dt.mode != null &&
deferredAttrContext.mode.ordinal() <= dt.mode.ordinal();
}
@Override
public Type apply(Type t) {
if (t.tag != DEFERRED) {
return t.map(this);
} else {
DeferredType dt = (DeferredType)t;
Assert.check(validState(dt));
return typeOf(dt);
}
}
protected Type typeOf(DeferredType dt) {
switch (deferredAttrContext.mode) {
case CHECK:
return dt.tree.type == null ? Type.noType : dt.tree.type;
case SPECULATIVE:
return dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase);
}
Assert.error();
return null;
}
}
/**
* Specialized recovery deferred mapping.
* Each deferred type D is mapped into a type T, where T is computed either by
* (i) retrieving the type that has already been computed for D during a previous
* attribution round (as before), or (ii) by synthesizing a new type R for D
* (the latter step is useful in a recovery scenario).
*/
public class RecoveryDeferredTypeMap extends DeferredTypeMap {
public RecoveryDeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
super(mode, msym, phase);
}
@Override
protected Type typeOf(DeferredType dt) {
Type owntype = super.typeOf(dt);
return owntype.tag == NONE ?
recover(dt) : owntype;
}
@Override
protected boolean validState(DeferredType dt) {
return true;
}
/**
* Synthesize a type for a deferred type that hasn't been previously
* reduced to an ordinary type. Functional deferred types and conditionals
* are mapped to themselves, in order to have a richer diagnostic
* representation. Remaining deferred types are attributed using
* a default expected type (j.l.Object).
*/
private Type recover(DeferredType dt) {
dt.check(attr.new RecoveryInfo(deferredAttrContext));
switch (TreeInfo.skipParens(dt.tree).getTag()) {
case LAMBDA:
case REFERENCE:
case CONDEXPR:
//propagate those deferred types to the
//diagnostic formatter
return dt;
default:
return super.apply(dt);
}
}
}
/**
* Retrieves the list of inference variables that need to be inferred before
* an AST node can be type-checked
*/
@SuppressWarnings("fallthrough")
List<Type> stuckVars(JCTree tree, ResultInfo resultInfo) {
if (resultInfo.pt.tag == NONE || resultInfo.pt.isErroneous()) {
return List.nil();
} else {
StuckChecker sc = new StuckChecker(resultInfo);
sc.scan(tree);
return List.from(sc.stuckVars);
}
}
/**
* This visitor is used to check that structural expressions conform
* to their target - this step is required as inference could end up
* inferring types that make some of the nested expressions incompatible
* with their corresponding instantiated target
*/
class StuckChecker extends TreeScanner {
Type pt;
Filter<JCTree> treeFilter;
Infer.InferenceContext inferenceContext;
Set<Type> stuckVars = new HashSet<Type>();
final Filter<JCTree> argsFilter = new Filter<JCTree>() {
public boolean accepts(JCTree t) {
switch (t.getTag()) {
case CONDEXPR:
case LAMBDA:
case PARENS:
case REFERENCE:
return true;
default:
return false;
}
}
};
final Filter<JCTree> lambdaBodyFilter = new Filter<JCTree>() {
public boolean accepts(JCTree t) {
switch (t.getTag()) {
case BLOCK: case CASE: case CATCH: case DOLOOP:
case FOREACHLOOP: case FORLOOP: case RETURN:
case SYNCHRONIZED: case SWITCH: case TRY: case WHILELOOP:
return true;
default:
return false;
}
}
};
StuckChecker(ResultInfo resultInfo) {
this.pt = resultInfo.pt;
this.inferenceContext = resultInfo.checkContext.inferenceContext();
this.treeFilter = argsFilter;
}
@Override
public void scan(JCTree tree) {
if (tree != null && treeFilter.accepts(tree)) {
super.scan(tree);
}
}
@Override
public void visitLambda(JCLambda tree) {
Type prevPt = pt;
Filter<JCTree> prevFilter = treeFilter;
try {
if (inferenceContext.inferenceVars().contains(pt)) {
stuckVars.add(pt);
}
if (!types.isFunctionalInterface(pt.tsym)) {
return;
}
Type descType = types.findDescriptorType(pt);
List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
if (!TreeInfo.isExplicitLambda(tree) &&
freeArgVars.nonEmpty()) {
stuckVars.addAll(freeArgVars);
}
pt = descType.getReturnType();
if (tree.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
scan(tree.getBody());
} else {
treeFilter = lambdaBodyFilter;
super.visitLambda(tree);
}
} finally {
pt = prevPt;
treeFilter = prevFilter;
}
}
@Override
public void visitReference(JCMemberReference tree) {
scan(tree.expr);
if (inferenceContext.inferenceVars().contains(pt)) {
stuckVars.add(pt);
return;
}
if (!types.isFunctionalInterface(pt.tsym)) {
return;
}
Type descType = types.findDescriptorType(pt);
List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
stuckVars.addAll(freeArgVars);
}
@Override
public void visitReturn(JCReturn tree) {
Filter<JCTree> prevFilter = treeFilter;
try {
treeFilter = argsFilter;
if (tree.expr != null) {
scan(tree.expr);
}
} finally {
treeFilter = prevFilter;
}
}
}
}

View File

@ -50,8 +50,8 @@ import static com.sun.tools.javac.tree.JCTree.Tag.*;
* (see AssignAnalyzer) ensures that each variable is assigned when used. Definite
* unassignment analysis (see AssignAnalyzer) in ensures that no final variable
* is assigned more than once. Finally, local variable capture analysis (see CaptureAnalyzer)
* determines that local variables accessed within the scope of an inner class are
* either final or effectively-final.
* determines that local variables accessed within the scope of an inner class/lambda
* are either final or effectively-final.
*
* <p>The JLS has a number of problems in the
* specification of these flow analysis problems. This implementation
@ -211,6 +211,29 @@ public class Flow {
new CaptureAnalyzer().analyzeTree(env, make);
}
public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
java.util.Queue<JCDiagnostic> prevDeferredDiagnostics = log.deferredDiagnostics;
Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
//we need to disable diagnostics temporarily; the problem is that if
//a lambda expression contains e.g. an unreachable statement, an error
//message will be reported and will cause compilation to skip the flow analyis
//step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
//related errors, which will allow for more errors to be detected
if (!speculative) {
log.deferAll();
log.deferredDiagnostics = ListBuffer.lb();
}
try {
new AliveAnalyzer().analyzeTree(env, that, make);
new FlowAnalyzer().analyzeTree(env, that, make);
} finally {
if (!speculative) {
log.deferredDiagFilter = prevDeferDiagsFilter;
log.deferredDiagnostics = prevDeferredDiagnostics;
}
}
}
/**
* Definite assignment scan mode
*/
@ -659,6 +682,27 @@ public class Flow {
}
}
@Override
public void visitLambda(JCLambda tree) {
if (tree.type != null &&
tree.type.isErroneous()) {
return;
}
ListBuffer<PendingExit> prevPending = pendingExits;
boolean prevAlive = alive;
try {
pendingExits = ListBuffer.lb();
alive = true;
scanStat(tree.body);
tree.canCompleteNormally = alive;
}
finally {
pendingExits = prevPending;
alive = prevAlive;
}
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
@ -670,6 +714,9 @@ public class Flow {
/** Perform definite assignment/unassignment analysis on a tree.
*/
public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
analyzeTree(env, env.tree, make);
}
public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
try {
attrEnv = env;
Flow.this.make = make;
@ -1185,6 +1232,29 @@ public class Flow {
}
}
@Override
public void visitLambda(JCLambda tree) {
if (tree.type != null &&
tree.type.isErroneous()) {
return;
}
List<Type> prevCaught = caught;
List<Type> prevThrown = thrown;
ListBuffer<FlowPendingExit> prevPending = pendingExits;
try {
pendingExits = ListBuffer.lb();
caught = List.of(syms.throwableType); //inhibit exception checking
thrown = List.nil();
scan(tree.body);
tree.inferredThrownTypes = thrown;
}
finally {
pendingExits = prevPending;
caught = prevCaught;
thrown = prevThrown;
}
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
@ -1267,6 +1337,10 @@ public class Flow {
*/
int nextadr;
/** The first variable sequence number in a block that can return.
*/
int returnadr;
/** The list of unreferenced automatic resources.
*/
Scope unrefdResources;
@ -1296,8 +1370,8 @@ public class Flow {
@Override
void markDead() {
inits.inclRange(firstadr, nextadr);
uninits.inclRange(firstadr, nextadr);
inits.inclRange(returnadr, nextadr);
uninits.inclRange(returnadr, nextadr);
}
/*-------------- Processing variables ----------------------*/
@ -1318,11 +1392,7 @@ public class Flow {
* index into the vars array.
*/
void newVar(VarSymbol sym) {
if (nextadr == vars.length) {
VarSymbol[] newvars = new VarSymbol[nextadr * 2];
System.arraycopy(vars, 0, newvars, 0, nextadr);
vars = newvars;
}
vars = ArrayUtils.ensureCapacity(vars, nextadr);
if ((sym.flags() & FINAL) == 0) {
sym.flags_field |= EFFECTIVELY_FINAL;
}
@ -1556,6 +1626,7 @@ public class Flow {
Bits uninitsPrev = uninits.dup();
int nextadrPrev = nextadr;
int firstadrPrev = firstadr;
int returnadrPrev = returnadr;
Lint lintPrev = lint;
lint = lint.augment(tree.sym.annotations);
@ -1600,6 +1671,7 @@ public class Flow {
uninits = uninitsPrev;
nextadr = nextadrPrev;
firstadr = firstadrPrev;
returnadr = returnadrPrev;
lint = lintPrev;
}
}
@ -1984,6 +2056,35 @@ public class Flow {
scan(tree.def);
}
@Override
public void visitLambda(JCLambda tree) {
Bits prevUninits = uninits;
Bits prevInits = inits;
int returnadrPrev = returnadr;
ListBuffer<AssignPendingExit> prevPending = pendingExits;
try {
returnadr = nextadr;
pendingExits = new ListBuffer<AssignPendingExit>();
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
JCVariableDecl def = l.head;
scan(def);
inits.incl(def.sym.adr);
uninits.excl(def.sym.adr);
}
if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
scanExpr(tree.body);
} else {
scan(tree.body);
}
}
finally {
returnadr = returnadrPrev;
uninits = prevUninits;
inits = prevInits;
pendingExits = prevPending;
}
}
public void visitNewArray(JCNewArray tree) {
scanExprs(tree.dims);
scanExprs(tree.elems);

View File

@ -25,18 +25,24 @@
package com.sun.tools.javac.comp;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static com.sun.tools.javac.code.TypeTags.*;
/** Helper class for type parameter inference, used by the attribution phase.
@ -57,6 +63,7 @@ public class Infer {
Types types;
Check chk;
Resolve rs;
DeferredAttr deferredAttr;
Log log;
JCDiagnostic.Factory diags;
@ -72,45 +79,44 @@ public class Infer {
syms = Symtab.instance(context);
types = Types.instance(context);
rs = Resolve.instance(context);
deferredAttr = DeferredAttr.instance(context);
log = Log.instance(context);
chk = Check.instance(context);
diags = JCDiagnostic.Factory.instance(context);
inferenceException = new InferenceException(diags);
}
/**
* This exception class is design to store a list of diagnostics corresponding
* to inference errors that can arise during a method applicability check.
*/
public static class InferenceException extends InapplicableMethodException {
private static final long serialVersionUID = 0;
List<JCDiagnostic> messages = List.nil();
InferenceException(JCDiagnostic.Factory diags) {
super(diags);
}
@Override
InapplicableMethodException setMessage(JCDiagnostic diag) {
messages = messages.append(diag);
return this;
}
@Override
public JCDiagnostic getDiagnostic() {
return messages.head;
}
void clear() {
messages = List.nil();
}
}
private final InferenceException inferenceException;
/***************************************************************************
* Auxiliary type values and classes
***************************************************************************/
/** A mapping that turns type variables into undetermined type variables.
*/
List<Type> makeUndetvars(List<Type> tvars) {
List<Type> undetvars = Type.map(tvars, fromTypeVarFun);
for (Type t : undetvars) {
UndetVar uv = (UndetVar)t;
uv.hibounds = types.getBounds((TypeVar)uv.qtype);
}
return undetvars;
}
//where
Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
public Type apply(Type t) {
if (t.tag == TYPEVAR) return new UndetVar(t);
else return t.map(this);
}
};
/***************************************************************************
* Mini/Maximization of UndetVars
***************************************************************************/
@ -118,9 +124,9 @@ public class Infer {
/** Instantiate undetermined type variable to its minimal upper bound.
* Throw a NoInstanceException if this not possible.
*/
void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
if (that.eq.isEmpty()) {
void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
List<Type> hibounds = Type.filter(that.getBounds(InferenceBound.UPPER), boundFilter);
if (that.getBounds(InferenceBound.EQ).isEmpty()) {
if (hibounds.isEmpty())
that.inst = syms.objectType;
else if (hibounds.tail.isEmpty())
@ -128,7 +134,7 @@ public class Infer {
else
that.inst = types.glb(hibounds);
} else {
that.inst = that.eq.head;
that.inst = that.getBounds(InferenceBound.EQ).head;
}
if (that.inst == null ||
that.inst.isErroneous())
@ -137,10 +143,10 @@ public class Infer {
that.qtype, hibounds);
}
private Filter<Type> errorFilter = new Filter<Type>() {
private Filter<Type> boundFilter = new Filter<Type>() {
@Override
public boolean accepts(Type t) {
return !t.isErroneous();
return !t.isErroneous() && t.tag != BOT;
}
};
@ -148,11 +154,12 @@ public class Infer {
* Throw a NoInstanceException if this not possible.
*/
void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
if (that.eq.isEmpty()) {
if (lobounds.isEmpty())
that.inst = syms.botType;
else if (lobounds.tail.isEmpty())
List<Type> lobounds = Type.filter(that.getBounds(InferenceBound.LOWER), boundFilter);
if (that.getBounds(InferenceBound.EQ).isEmpty()) {
if (lobounds.isEmpty()) {
//do nothing - the inference variable is under-constrained
return;
} else if (lobounds.tail.isEmpty())
that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
else {
that.inst = types.lub(lobounds);
@ -162,120 +169,99 @@ public class Infer {
.setMessage("no.unique.minimal.instance.exists",
that.qtype, lobounds);
} else {
that.inst = that.eq.head;
that.inst = that.getBounds(InferenceBound.EQ).head;
}
}
Type asUndetType(Type t, List<Type> undetvars) {
return types.subst(t, inferenceVars(undetvars), undetvars);
}
List<Type> inferenceVars(List<Type> undetvars) {
ListBuffer<Type> tvars = ListBuffer.lb();
for (Type uv : undetvars) {
tvars.append(((UndetVar)uv).qtype);
}
return tvars.toList();
}
/***************************************************************************
* Exported Methods
***************************************************************************/
/** Try to instantiate expression type `that' to given type `to'.
* If a maximal instantiation exists which makes this type
* a subtype of type `to', return the instantiated type.
* If no instantiation exists, or if several incomparable
* best instantiations exist throw a NoInstanceException.
/**
* Instantiate uninferred inference variables (JLS 15.12.2.8). First
* if the method return type is non-void, we derive constraints from the
* expected type - then we use declared bound well-formedness to derive additional
* constraints. If no instantiation exists, or if several incomparable
* best instantiations exist throw a NoInstanceException.
*/
public List<Type> instantiateUninferred(DiagnosticPosition pos,
List<Type> undetvars,
List<Type> tvars,
MethodType mtype,
Attr.ResultInfo resultInfo,
Warner warn) throws InferenceException {
public void instantiateUninferred(DiagnosticPosition pos,
InferenceContext inferenceContext,
MethodType mtype,
Attr.ResultInfo resultInfo,
Warner warn) throws InferenceException {
Type to = resultInfo.pt;
if (to.tag == NONE) {
if (to.tag == NONE || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
to = mtype.getReturnType().tag <= VOID ?
mtype.getReturnType() : syms.objectType;
}
Type qtype1 = types.subst(mtype.getReturnType(), tvars, undetvars);
Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
if (!types.isSubtype(qtype1,
qtype1.tag == UNDETVAR ? types.boxedTypeOrType(to) : to)) {
throw inferenceException
.setMessage("infer.no.conforming.instance.exists",
tvars, mtype.getReturnType(), to);
.setMessage("infer.no.conforming.instance.exists",
inferenceContext.restvars(), mtype.getReturnType(), to);
}
List<Type> insttypes;
while (true) {
boolean stuck = true;
insttypes = List.nil();
for (Type t : undetvars) {
for (Type t : inferenceContext.undetvars) {
UndetVar uv = (UndetVar)t;
if (uv.inst == null && (uv.eq.nonEmpty() || !Type.containsAny(uv.hibounds, tvars))) {
if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() ||
!inferenceContext.free(uv.getBounds(InferenceBound.UPPER)))) {
maximizeInst((UndetVar)t, warn);
stuck = false;
}
insttypes = insttypes.append(uv.inst == null ? uv.qtype : uv.inst);
}
if (!Type.containsAny(insttypes, tvars)) {
if (inferenceContext.restvars().isEmpty()) {
//all variables have been instantiated - exit
break;
} else if (stuck) {
//some variables could not be instantiated because of cycles in
//upper bounds - provide a (possibly recursive) default instantiation
insttypes = types.subst(insttypes,
tvars,
instantiateAsUninferredVars(undetvars, tvars));
instantiateAsUninferredVars(inferenceContext);
break;
} else {
//some variables have been instantiated - replace newly instantiated
//variables in remaining upper bounds and continue
for (Type t : undetvars) {
for (Type t : inferenceContext.undetvars) {
UndetVar uv = (UndetVar)t;
uv.hibounds = types.subst(uv.hibounds, tvars, insttypes);
uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
}
}
}
return insttypes;
}
/**
* Infer cyclic inference variables as described in 15.12.2.8.
*/
private List<Type> instantiateAsUninferredVars(List<Type> undetvars, List<Type> tvars) {
Assert.check(undetvars.length() == tvars.length());
ListBuffer<Type> insttypes = ListBuffer.lb();
private void instantiateAsUninferredVars(InferenceContext inferenceContext) {
ListBuffer<Type> todo = ListBuffer.lb();
//step 1 - create fresh tvars
for (Type t : undetvars) {
for (Type t : inferenceContext.undetvars) {
UndetVar uv = (UndetVar)t;
if (uv.inst == null) {
TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null);
fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null);
todo.append(uv);
uv.inst = fresh_tvar.type;
}
insttypes.append(uv.inst);
}
//step 2 - replace fresh tvars in their bounds
List<Type> formals = tvars;
List<Type> formals = inferenceContext.inferenceVars();
for (Type t : todo) {
UndetVar uv = (UndetVar)t;
TypeVar ct = (TypeVar)uv.inst;
ct.bound = types.glb(types.subst(types.getBounds(ct), tvars, insttypes.toList()));
ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct), types));
if (ct.bound.isErroneous()) {
//report inference error if glb fails
reportBoundError(uv, BoundErrorKind.BAD_UPPER);
}
formals = formals.tail;
}
return insttypes.toList();
}
/** Instantiate method type `mt' by finding instantiations of
* `tvars' so that method can be applied to `argtypes'.
/** Instantiate a generic method type by finding instantiations for all its
* inference variables so that it can be applied to a given argument type list.
*/
public Type instantiateMethod(Env<AttrContext> env,
List<Type> tvars,
@ -285,85 +271,65 @@ public class Infer {
List<Type> argtypes,
boolean allowBoxing,
boolean useVarargs,
Resolve.MethodResolutionContext resolveContext,
Warner warn) throws InferenceException {
//-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
List<Type> undetvars = makeUndetvars(tvars);
final InferenceContext inferenceContext = new InferenceContext(tvars, this, true);
inferenceException.clear();
List<Type> capturedArgs =
rs.checkRawArgumentsAcceptable(env, undetvars, argtypes, mt.getParameterTypes(),
allowBoxing, useVarargs, warn, new InferenceCheckHandler(undetvars));
try {
rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext,
argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn,
new InferenceCheckHandler(inferenceContext));
// minimize as yet undetermined type variables
for (Type t : undetvars)
minimizeInst((UndetVar) t, warn);
/** Type variables instantiated to bottom */
ListBuffer<Type> restvars = new ListBuffer<Type>();
/** Undet vars instantiated to bottom */
final ListBuffer<Type> restundet = new ListBuffer<Type>();
/** Instantiated types or TypeVars if under-constrained */
ListBuffer<Type> insttypes = new ListBuffer<Type>();
/** Instantiated types or UndetVars if under-constrained */
ListBuffer<Type> undettypes = new ListBuffer<Type>();
for (Type t : undetvars) {
UndetVar uv = (UndetVar)t;
if (uv.inst.tag == BOT) {
restvars.append(uv.qtype);
restundet.append(uv);
insttypes.append(uv.qtype);
undettypes.append(uv);
uv.inst = null;
} else {
insttypes.append(uv.inst);
undettypes.append(uv.inst);
// minimize as yet undetermined type variables
for (Type t : inferenceContext.undetvars) {
minimizeInst((UndetVar)t, warn);
}
}
checkWithinBounds(tvars, undetvars, insttypes.toList(), warn);
mt = (MethodType)types.subst(mt, tvars, insttypes.toList());
checkWithinBounds(inferenceContext, warn);
if (!restvars.isEmpty() && resultInfo != null) {
List<Type> restInferred =
instantiateUninferred(env.tree.pos(), restundet.toList(), restvars.toList(), mt, resultInfo, warn);
checkWithinBounds(tvars, undetvars,
types.subst(insttypes.toList(), restvars.toList(), restInferred), warn);
mt = (MethodType)types.subst(mt, restvars.toList(), restInferred);
if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
mt = (MethodType)inferenceContext.asInstType(mt, types);
List<Type> restvars = inferenceContext.restvars();
if (!restvars.isEmpty()) {
if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
checkWithinBounds(inferenceContext, warn);
mt = (MethodType)inferenceContext.asInstType(mt, types);
if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
}
}
}
}
if (restvars.isEmpty() || resultInfo != null) {
// check that actuals conform to inferred formals
checkArgumentsAcceptable(env, capturedArgs, mt.getParameterTypes(), allowBoxing, useVarargs, warn);
// return instantiated version of method type
return mt;
} finally {
inferenceContext.notifyChange(types);
}
// return instantiated version of method type
return mt;
}
//where
/** inference check handler **/
class InferenceCheckHandler implements Resolve.MethodCheckHandler {
List<Type> undetvars;
InferenceContext inferenceContext;
public InferenceCheckHandler(List<Type> undetvars) {
this.undetvars = undetvars;
public InferenceCheckHandler(InferenceContext inferenceContext) {
this.inferenceContext = inferenceContext;
}
public InapplicableMethodException arityMismatch() {
return inferenceException.setMessage("infer.arg.length.mismatch", inferenceVars(undetvars));
return inferenceException.setMessage("infer.arg.length.mismatch", inferenceContext.inferenceVars());
}
public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
String key = varargs ?
"infer.varargs.argument.mismatch" :
"infer.no.conforming.assignment.exists";
return inferenceException.setMessage(key,
inferenceVars(undetvars), details);
inferenceContext.inferenceVars(), details);
}
public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
return inferenceException.setMessage("inaccessible.varargs.type",
@ -371,51 +337,61 @@ public class Infer {
}
}
private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
boolean allowBoxing, boolean useVarargs, Warner warn) {
try {
rs.checkRawArgumentsAcceptable(env, actuals, formals,
allowBoxing, useVarargs, warn);
}
catch (InapplicableMethodException ex) {
// inferred method is not applicable
throw inferenceException.setMessage(ex.getDiagnostic());
}
}
/** check that type parameters are within their bounds.
*/
void checkWithinBounds(List<Type> tvars,
List<Type> undetvars,
List<Type> arguments,
Warner warn)
throws InferenceException {
List<Type> args = arguments;
for (Type t : undetvars) {
void checkWithinBounds(InferenceContext inferenceContext,
Warner warn) throws InferenceException {
//step 1 - check compatibility of instantiated type w.r.t. initial bounds
for (Type t : inferenceContext.undetvars) {
UndetVar uv = (UndetVar)t;
uv.hibounds = types.subst(uv.hibounds, tvars, arguments);
uv.lobounds = types.subst(uv.lobounds, tvars, arguments);
uv.eq = types.subst(uv.eq, tvars, arguments);
checkCompatibleUpperBounds(uv, tvars);
if (args.head.tag != TYPEVAR || !args.head.containsAny(tvars)) {
Type inst = args.head;
for (Type u : uv.hibounds) {
if (!types.isSubtypeUnchecked(inst, types.subst(u, tvars, undetvars), warn)) {
uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
if (!inferenceContext.restvars().contains(uv.qtype)) {
Type inst = inferenceContext.asInstType(t, types);
for (Type u : uv.getBounds(InferenceBound.UPPER)) {
if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) {
reportBoundError(uv, BoundErrorKind.UPPER);
}
}
for (Type l : uv.lobounds) {
if (!types.isSubtypeUnchecked(types.subst(l, tvars, undetvars), inst, warn)) {
for (Type l : uv.getBounds(InferenceBound.LOWER)) {
Assert.check(!inferenceContext.free(l));
if (!types.isSubtypeUnchecked(l, inst, warn)) {
reportBoundError(uv, BoundErrorKind.LOWER);
}
}
for (Type e : uv.eq) {
if (!types.isSameType(inst, types.subst(e, tvars, undetvars))) {
for (Type e : uv.getBounds(InferenceBound.EQ)) {
Assert.check(!inferenceContext.free(e));
if (!types.isSameType(inst, e)) {
reportBoundError(uv, BoundErrorKind.EQ);
}
}
}
args = args.tail;
}
//step 2 - check that eq bounds are consistent w.r.t. eq/lower bounds
for (Type t : inferenceContext.undetvars) {
UndetVar uv = (UndetVar)t;
//check eq bounds consistency
Type eq = null;
for (Type e : uv.getBounds(InferenceBound.EQ)) {
Assert.check(!inferenceContext.free(e));
if (eq != null && !types.isSameType(e, eq)) {
reportBoundError(uv, BoundErrorKind.EQ);
}
eq = e;
for (Type l : uv.getBounds(InferenceBound.LOWER)) {
Assert.check(!inferenceContext.free(l));
if (!types.isSubtypeUnchecked(l, e, warn)) {
reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER);
}
}
for (Type u : uv.getBounds(InferenceBound.UPPER)) {
if (inferenceContext.free(u)) continue;
if (!types.isSubtypeUnchecked(e, u, warn)) {
reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER);
}
}
}
}
}
@ -423,7 +399,7 @@ public class Infer {
// VGJ: sort of inlined maximizeInst() below. Adding
// bounds can cause lobounds that are above hibounds.
ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
for (Type t : Type.filter(uv.hibounds, errorFilter)) {
for (Type t : Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter)) {
if (!t.containsAny(tvars)) {
hiboundsNoVars.append(t);
}
@ -444,25 +420,43 @@ public class Infer {
BAD_UPPER() {
@Override
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
return ex.setMessage("incompatible.upper.bounds", uv.qtype, uv.hibounds);
return ex.setMessage("incompatible.upper.bounds", uv.qtype,
uv.getBounds(InferenceBound.UPPER));
}
},
BAD_EQ_UPPER() {
@Override
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype,
uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER));
}
},
BAD_EQ_LOWER() {
@Override
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype,
uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER));
}
},
UPPER() {
@Override
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, uv.hibounds);
return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst,
uv.getBounds(InferenceBound.UPPER));
}
},
LOWER() {
@Override
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, uv.lobounds);
return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst,
uv.getBounds(InferenceBound.LOWER));
}
},
EQ() {
@Override
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, uv.eq);
return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst,
uv.getBounds(InferenceBound.EQ));
}
};
@ -473,6 +467,75 @@ public class Infer {
throw bk.setMessage(inferenceException, uv);
}
// <editor-fold desc="functional interface instantiation">
/**
* This method is used to infer a suitable target functional interface in case
* the original parameterized interface contains wildcards. An inference process
* is applied so that wildcard bounds, as well as explicit lambda/method ref parameters
* (where applicable) are used to constraint the solution.
*/
public Type instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface,
List<Type> paramTypes, Check.CheckContext checkContext) {
if (types.capture(funcInterface) == funcInterface) {
//if capture doesn't change the type then return the target unchanged
//(this means the target contains no wildcards!)
return funcInterface;
} else {
Type formalInterface = funcInterface.tsym.type;
InferenceContext funcInterfaceContext =
new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
if (paramTypes != null) {
//get constraints from explicit params (this is done by
//checking that explicit param types are equal to the ones
//in the functional interface descriptors)
List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
if (descParameterTypes.size() != paramTypes.size()) {
checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
return types.createErrorType(funcInterface);
}
for (Type p : descParameterTypes) {
if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
return types.createErrorType(funcInterface);
}
paramTypes = paramTypes.tail;
}
for (Type t : funcInterfaceContext.undetvars) {
UndetVar uv = (UndetVar)t;
minimizeInst(uv, Warner.noWarnings);
if (uv.inst == null &&
Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
maximizeInst(uv, Warner.noWarnings);
}
}
formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
}
ListBuffer<Type> typeargs = ListBuffer.lb();
List<Type> actualTypeargs = funcInterface.getTypeArguments();
//for remaining uninferred type-vars in the functional interface type,
//simply replace the wildcards with its bound
for (Type t : formalInterface.getTypeArguments()) {
if (actualTypeargs.head.tag == WILDCARD) {
WildcardType wt = (WildcardType)actualTypeargs.head;
typeargs.append(wt.type);
} else {
typeargs.append(actualTypeargs.head);
}
actualTypeargs = actualTypeargs.tail;
}
Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList());
if (!chk.checkValidGenericType(owntype)) {
//if the inferred functional interface type is not well-formed,
//or if it's not a subtype of the original target, issue an error
checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
return types.createErrorType(funcInterface);
}
return owntype;
}
}
// </editor-fold>
/**
* Compute a synthetic method type corresponding to the requested polymorphic
* method signature. The target return type is computed from the immediately
@ -480,6 +543,7 @@ public class Infer {
*/
Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env,
MethodSymbol spMethod, // sig. poly. method or null if none
Resolve.MethodResolutionContext resolveContext,
List<Type> argtypes) {
final Type restype;
@ -509,7 +573,7 @@ public class Infer {
restype = syms.objectType;
}
List<Type> paramtypes = Type.map(argtypes, implicitArgType);
List<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step));
List<Type> exType = spMethod != null ?
spMethod.getThrownTypes() :
List.of(syms.throwableType); // make it throw all exceptions
@ -521,14 +585,234 @@ public class Infer {
return mtype;
}
//where
Mapping implicitArgType = new Mapping ("implicitArgType") {
public Type apply(Type t) {
t = types.erasure(t);
if (t.tag == 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;
return t;
class ImplicitArgType extends DeferredAttr.DeferredTypeMap {
public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) {
deferredAttr.super(AttrMode.SPECULATIVE, msym, phase);
}
public Type apply(Type t) {
t = types.erasure(super.apply(t));
if (t.tag == 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;
return t;
}
}
/**
* Mapping that turns inference variables into undet vars
* (used by inference context)
*/
class FromTypeVarFun extends Mapping {
boolean includeBounds;
FromTypeVarFun(boolean includeBounds) {
super("fromTypeVarFunWithBounds");
this.includeBounds = includeBounds;
}
public Type apply(Type t) {
if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types, includeBounds);
else return t.map(this);
}
};
/**
* An inference context keeps track of the set of variables that are free
* in the current context. It provides utility methods for opening/closing
* types to their corresponding free/closed forms. It also provide hooks for
* attaching deferred post-inference action (see PendingCheck). Finally,
* it can be used as an entry point for performing upper/lower bound inference
* (see InferenceKind).
*/
static class InferenceContext {
/**
* Single-method-interface for defining inference callbacks. Certain actions
* (i.e. subtyping checks) might need to be redone after all inference variables
* have been fixed.
*/
interface FreeTypeListener {
void typesInferred(InferenceContext inferenceContext);
}
/** list of inference vars as undet vars */
List<Type> undetvars;
/** list of inference vars in this context */
List<Type> inferencevars;
java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
new java.util.HashMap<FreeTypeListener, List<Type>>();
List<FreeTypeListener> freetypeListeners = List.nil();
public InferenceContext(List<Type> inferencevars, Infer infer, boolean includeBounds) {
this.undetvars = Type.map(inferencevars, infer.new FromTypeVarFun(includeBounds));
this.inferencevars = inferencevars;
}
/**
* returns the list of free variables (as type-variables) in this
* inference context
*/
List<Type> inferenceVars() {
return inferencevars;
}
/**
* returns the list of uninstantiated variables (as type-variables) in this
* inference context (usually called after instantiate())
*/
List<Type> restvars() {
List<Type> undetvars = this.undetvars;
ListBuffer<Type> restvars = ListBuffer.lb();
for (Type t : instTypes()) {
UndetVar uv = (UndetVar)undetvars.head;
if (uv.qtype == t) {
restvars.append(t);
}
};
undetvars = undetvars.tail;
}
return restvars.toList();
}
/**
* is this type free?
*/
final boolean free(Type t) {
return t.containsAny(inferencevars);
}
final boolean free(List<Type> ts) {
for (Type t : ts) {
if (free(t)) return true;
}
return false;
}
/**
* Returns a list of free variables in a given type
*/
final List<Type> freeVarsIn(Type t) {
ListBuffer<Type> buf = ListBuffer.lb();
for (Type iv : inferenceVars()) {
if (t.contains(iv)) {
buf.add(iv);
}
}
return buf.toList();
}
final List<Type> freeVarsIn(List<Type> ts) {
ListBuffer<Type> buf = ListBuffer.lb();
for (Type t : ts) {
buf.appendList(freeVarsIn(t));
}
ListBuffer<Type> buf2 = ListBuffer.lb();
for (Type t : buf) {
if (!buf2.contains(t)) {
buf2.add(t);
}
}
return buf2.toList();
}
/**
* Replace all free variables in a given type with corresponding
* undet vars (used ahead of subtyping/compatibility checks to allow propagation
* of inference constraints).
*/
final Type asFree(Type t, Types types) {
return types.subst(t, inferencevars, undetvars);
}
final List<Type> asFree(List<Type> ts, Types types) {
ListBuffer<Type> buf = ListBuffer.lb();
for (Type t : ts) {
buf.append(asFree(t, types));
}
return buf.toList();
}
List<Type> instTypes() {
ListBuffer<Type> buf = ListBuffer.lb();
for (Type t : undetvars) {
UndetVar uv = (UndetVar)t;
buf.append(uv.inst != null ? uv.inst : uv.qtype);
}
return buf.toList();
}
/**
* Replace all free variables in a given type with corresponding
* instantiated types - if one or more free variable has not been
* fully instantiated, it will still be available in the resulting type.
*/
Type asInstType(Type t, Types types) {
return types.subst(t, inferencevars, instTypes());
}
List<Type> asInstTypes(List<Type> ts, Types types) {
ListBuffer<Type> buf = ListBuffer.lb();
for (Type t : ts) {
buf.append(asInstType(t, types));
}
return buf.toList();
}
/**
* Add custom hook for performing post-inference action
*/
void addFreeTypeListener(List<Type> types, FreeTypeListener ftl) {
freeTypeListeners.put(ftl, freeVarsIn(types));
}
/**
* Mark the inference context as complete and trigger evaluation
* of all deferred checks.
*/
void notifyChange(Types types) {
InferenceException thrownEx = null;
for (Map.Entry<FreeTypeListener, List<Type>> entry :
new HashMap<FreeTypeListener, List<Type>>(freeTypeListeners).entrySet()) {
if (!Type.containsAny(entry.getValue(), restvars())) {
try {
entry.getKey().typesInferred(this);
freeTypeListeners.remove(entry.getKey());
} catch (InferenceException ex) {
if (thrownEx == null) {
thrownEx = ex;
}
}
}
}
//inference exception multiplexing - present any inference exception
//thrown when processing listeners as a single one
if (thrownEx != null) {
throw thrownEx;
}
}
void solveAny(List<Type> varsToSolve, Types types, Infer infer) {
boolean progress = false;
for (Type t : varsToSolve) {
UndetVar uv = (UndetVar)asFree(t, types);
if (uv.inst == null) {
infer.minimizeInst(uv, Warner.noWarnings);
if (uv.inst != null) {
progress = true;
}
}
}
if (!progress) {
throw infer.inferenceException.setMessage("cyclic.inference", varsToSolve);
}
}
}
final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this, false);
}

View File

@ -1998,7 +1998,7 @@ public class Lower extends TreeTranslator {
// replace with <BoxedClass>.TYPE
ClassSymbol c = types.boxedClass(type);
Symbol typeSym =
rs.access(
rs.accessBase(
rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR),
pos, c.type, names.TYPE, true);
if (typeSym.kind == VAR)

View File

@ -604,6 +604,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
env.dup(tree, env.info.dup(env.info.scope.dupUnshared()));
localEnv.enclMethod = tree;
localEnv.info.scope.owner = tree.sym;
if (tree.sym.type != null) {
//when this is called in the enter stage, there's no type to be set
localEnv.info.returnResult = attr.new ResultInfo(VAL, tree.sym.type.getReturnType());
}
if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
return localEnv;
}
@ -642,7 +646,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
tree.sym = v;
if (tree.init != null) {
v.flags_field |= HASINIT;
if ((v.flags_field & FINAL) != 0 && !tree.init.hasTag(NEWCLASS)) {
if ((v.flags_field & FINAL) != 0 &&
!tree.init.hasTag(NEWCLASS) &&
!tree.init.hasTag(LAMBDA)) {
Env<AttrContext> initEnv = getInitEnv(tree, env);
initEnv.info.enclVar = v;
v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init);
@ -667,7 +673,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) {
Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup()));
if (tree.sym.owner.kind == TYP) {
localEnv.info.scope = new Scope.DelegatedScope(env.info.scope);
localEnv.info.scope = env.info.scope.dupUnshared();
localEnv.info.scope.owner = tree.sym;
}
if ((tree.mods.flags & STATIC) != 0 ||
@ -970,9 +976,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
List<Type> thrown = List.nil();
long ctorFlags = 0;
boolean based = false;
boolean addConstructor = true;
if (c.name.isEmpty()) {
JCNewClass nc = (JCNewClass)env.next.tree;
if (nc.constructor != null) {
addConstructor = nc.constructor.kind != ERR;
Type superConstrType = types.memberType(c.type,
nc.constructor);
argtypes = superConstrType.getParameterTypes();
@ -985,10 +993,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
thrown = superConstrType.getThrownTypes();
}
}
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
typarams, argtypes, thrown,
ctorFlags, based);
tree.defs = tree.defs.prepend(constrDef);
if (addConstructor) {
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
typarams, argtypes, thrown,
ctorFlags, based);
tree.defs = tree.defs.prepend(constrDef);
}
}
// If this is a class, enter symbols for this and super into

View File

@ -627,6 +627,16 @@ public class TransTypes extends TreeTranslator {
result = tree;
}
@Override
public void visitLambda(JCLambda tree) {
Assert.error("Translation of lambda expression not supported yet");
}
@Override
public void visitReference(JCMemberReference tree) {
Assert.error("Translation of method reference not supported yet");
}
public void visitParens(JCParens tree) {
tree.expr = translate(tree.expr, pt);
tree.type = erasure(tree.type);

View File

@ -733,11 +733,7 @@ public class Locations {
urls[count++] = url;
}
}
if (urls.length != count) {
URL[] tmp = new URL[count];
System.arraycopy(urls, 0, tmp, 0, count);
urls = tmp;
}
urls = Arrays.copyOf(urls, count);
return urls;
}

View File

@ -84,6 +84,16 @@ public class ClassFile {
public final static int CONSTANT_MethodType = 16;
public final static int CONSTANT_InvokeDynamic = 18;
public final static int REF_getField = 1;
public final static int REF_getStatic = 2;
public final static int REF_putField = 3;
public final static int REF_putStatic = 4;
public final static int REF_invokeVirtual = 5;
public final static int REF_invokeStatic = 6;
public final static int REF_invokeSpecial = 7;
public final static int REF_newInvokeSpecial = 8;
public final static int REF_invokeInterface = 9;
public final static int MAX_PARAMETERS = 0xff;
public final static int MAX_DIMENSIONS = 0xff;
public final static int MAX_CODE = 0xffff;

View File

@ -26,6 +26,8 @@
package com.sun.tools.javac.jvm;
import java.io.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
@ -137,6 +139,11 @@ public class ClassWriter extends ClassFile {
*/
ListBuffer<ClassSymbol> innerClassesQueue;
/** The bootstrap methods to be written in the corresponding class attribute
* (one for each invokedynamic)
*/
Map<MethodSymbol, Pool.MethodHandle> bootstrapMethods;
/** The log to use for verbose output.
*/
private final Log log;
@ -477,11 +484,27 @@ public class ClassWriter extends ClassFile {
if (value instanceof MethodSymbol) {
MethodSymbol m = (MethodSymbol)value;
poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
? CONSTANT_InterfaceMethodref
: CONSTANT_Methodref);
poolbuf.appendChar(pool.put(m.owner));
poolbuf.appendChar(pool.put(nameType(m)));
if (!m.isDynamic()) {
poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
? CONSTANT_InterfaceMethodref
: CONSTANT_Methodref);
poolbuf.appendChar(pool.put(m.owner));
poolbuf.appendChar(pool.put(nameType(m)));
} else {
//invokedynamic
DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
Pool.MethodHandle handle = new Pool.MethodHandle(dynSym.bsmKind, dynSym.bsm);
bootstrapMethods.put(dynSym, handle);
//init cp entries
pool.put(names.BootstrapMethods);
pool.put(handle);
for (Object staticArg : dynSym.staticArgs) {
pool.put(staticArg);
}
poolbuf.appendByte(CONSTANT_InvokeDynamic);
poolbuf.appendChar(bootstrapMethods.size() - 1);
poolbuf.appendChar(pool.put(nameType(dynSym)));
}
} else if (value instanceof VarSymbol) {
VarSymbol v = (VarSymbol)value;
poolbuf.appendByte(CONSTANT_Fieldref);
@ -526,11 +549,20 @@ public class ClassWriter extends ClassFile {
} else if (value instanceof String) {
poolbuf.appendByte(CONSTANT_String);
poolbuf.appendChar(pool.put(names.fromString((String)value)));
} else if (value instanceof MethodType) {
MethodType mtype = (MethodType)value;
poolbuf.appendByte(CONSTANT_MethodType);
poolbuf.appendChar(pool.put(typeSig(mtype)));
} else if (value instanceof Type) {
Type type = (Type)value;
if (type.tag == CLASS) enterInner((ClassSymbol)type.tsym);
poolbuf.appendByte(CONSTANT_Class);
poolbuf.appendChar(pool.put(xClassName(type)));
} else if (value instanceof Pool.MethodHandle) {
Pool.MethodHandle ref = (Pool.MethodHandle)value;
poolbuf.appendByte(CONSTANT_MethodHandle);
poolbuf.appendByte(ref.refKind);
poolbuf.appendChar(pool.put(ref.refSym));
} else {
Assert.error("writePool " + value);
}
@ -914,6 +946,25 @@ public class ClassWriter extends ClassFile {
endAttr(alenIdx);
}
/** Write "bootstrapMethods" attribute.
*/
void writeBootstrapMethods() {
int alenIdx = writeAttr(names.BootstrapMethods);
databuf.appendChar(bootstrapMethods.size());
for (Map.Entry<MethodSymbol, Pool.MethodHandle> entry : bootstrapMethods.entrySet()) {
DynamicMethodSymbol dsym = (DynamicMethodSymbol)entry.getKey();
//write BSM handle
databuf.appendChar(pool.get(entry.getValue()));
//write static args length
databuf.appendChar(dsym.staticArgs.length);
//write static args array
for (Object o : dsym.staticArgs) {
databuf.appendChar(pool.get(o));
}
}
endAttr(alenIdx);
}
/** Write field symbol, entering all references into constant pool.
*/
void writeField(VarSymbol v) {
@ -1483,6 +1534,7 @@ public class ClassWriter extends ClassFile {
pool = c.pool;
innerClasses = null;
innerClassesQueue = null;
bootstrapMethods = new LinkedHashMap<MethodSymbol, Pool.MethodHandle>();
Type supertype = types.supertype(c.type);
List<Type> interfaces = types.interfaces(c.type);
@ -1589,6 +1641,12 @@ public class ClassWriter extends ClassFile {
writeInnerClasses();
acount++;
}
if (!bootstrapMethods.isEmpty()) {
writeBootstrapMethods();
acount++;
}
endAttrs(acountIdx, acount);
poolbuf.appendBytes(databuf.elems, 0, databuf.length);

View File

@ -314,11 +314,7 @@ public class Code {
*/
private void emit1(int od) {
if (!alive) return;
if (cp == code.length) {
byte[] newcode = new byte[cp * 2];
System.arraycopy(code, 0, newcode, 0, cp);
code = newcode;
}
code = ArrayUtils.ensureCapacity(code, cp);
code[cp++] = (byte)od;
}
@ -903,6 +899,8 @@ public class Code {
if (o instanceof Double) return syms.doubleType;
if (o instanceof ClassSymbol) return syms.classType;
if (o instanceof Type.ArrayType) return syms.classType;
if (o instanceof Type.MethodType) return syms.methodTypeType;
if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
throw new AssertionError(o);
}
@ -1245,12 +1243,8 @@ public class Code {
if (stackMapBuffer == null) {
stackMapBuffer = new StackMapFrame[20];
} else if (stackMapBuffer.length == stackMapBufferSize) {
StackMapFrame[] newStackMapBuffer =
new StackMapFrame[stackMapBufferSize << 1];
System.arraycopy(stackMapBuffer, 0, newStackMapBuffer,
0, stackMapBufferSize);
stackMapBuffer = newStackMapBuffer;
} else {
stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
}
StackMapFrame frame =
stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
@ -1318,12 +1312,10 @@ public class Code {
if (stackMapTableBuffer == null) {
stackMapTableBuffer = new StackMapTableFrame[20];
} else if (stackMapTableBuffer.length == stackMapBufferSize) {
StackMapTableFrame[] newStackMapTableBuffer =
new StackMapTableFrame[stackMapBufferSize << 1];
System.arraycopy(stackMapTableBuffer, 0, newStackMapTableBuffer,
0, stackMapBufferSize);
stackMapTableBuffer = newStackMapTableBuffer;
} else {
stackMapTableBuffer = ArrayUtils.ensureCapacity(
stackMapTableBuffer,
stackMapBufferSize);
}
stackMapTableBuffer[stackMapBufferSize++] =
StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
@ -1649,10 +1641,8 @@ public class Code {
void lock(int register) {
if (locks == null) {
locks = new int[20];
} else if (locks.length == nlocks) {
int[] newLocks = new int[locks.length << 1];
System.arraycopy(locks, 0, newLocks, 0, locks.length);
locks = newLocks;
} else {
locks = ArrayUtils.ensureCapacity(locks, nlocks);
}
locks[nlocks] = register;
nlocks++;
@ -1678,11 +1668,7 @@ public class Code {
default:
break;
}
if (stacksize+2 >= stack.length) {
Type[] newstack = new Type[2*stack.length];
System.arraycopy(stack, 0, newstack, 0, stack.length);
stack = newstack;
}
stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
stack[stacksize++] = t;
switch (width(t)) {
case 1:
@ -1869,13 +1855,7 @@ public class Code {
/** Add a new local variable. */
private void addLocalVar(VarSymbol v) {
int adr = v.adr;
if (adr+1 >= lvar.length) {
int newlength = lvar.length << 1;
if (newlength <= adr) newlength = adr + 10;
LocalVar[] new_lvar = new LocalVar[newlength];
System.arraycopy(lvar, 0, new_lvar, 0, lvar.length);
lvar = new_lvar;
}
lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
Assert.checkNull(lvar[adr]);
if (pendingJumps != null) resolvePending();
lvar[adr] = new LocalVar(v);
@ -1955,11 +1935,8 @@ public class Code {
if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
if (varBuffer == null)
varBuffer = new LocalVar[20];
else if (varBufferSize >= varBuffer.length) {
LocalVar[] newVarBuffer = new LocalVar[varBufferSize*2];
System.arraycopy(varBuffer, 0, newVarBuffer, 0, varBuffer.length);
varBuffer = newVarBuffer;
}
else
varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
varBuffer[varBufferSize++] = var;
}

View File

@ -2103,6 +2103,8 @@ public class Gen extends JCTree.Visitor {
result = res;
} else if (sym.kind == VAR && sym.owner.kind == MTH) {
result = items.makeLocalItem((VarSymbol)sym);
} else if (isInvokeDynamic(sym)) {
result = items.makeDynamicItem(sym);
} else if ((sym.flags() & STATIC) != 0) {
if (!isAccessSuper(env.enclMethod))
sym = binaryQualifier(sym, env.enclClass.type);
@ -2152,8 +2154,12 @@ public class Gen extends JCTree.Visitor {
result = items.
makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
} else {
if (!accessSuper)
if (isInvokeDynamic(sym)) {
result = items.makeDynamicItem(sym);
return;
} else if (!accessSuper) {
sym = binaryQualifier(sym, tree.selected.type);
}
if ((sym.flags() & STATIC) != 0) {
if (!selectSuper && (ssym == null || ssym.kind != TYP))
base = base.load();
@ -2174,6 +2180,10 @@ public class Gen extends JCTree.Visitor {
}
}
public boolean isInvokeDynamic(Symbol sym) {
return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
}
public void visitLiteral(JCLiteral tree) {
if (tree.type.tag == TypeTags.BOT) {
code.emitop0(aconst_null);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2012, 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
@ -110,6 +110,13 @@ public class Items {
return stackItem[Code.typecode(type)];
}
/** Make an item representing a dynamically invoked method.
* @param member The represented symbol.
*/
Item makeDynamicItem(Symbol member) {
return new DynamicItem(member);
}
/** Make an item representing an indexed expression.
* @param type The expression's type.
*/
@ -457,6 +464,35 @@ public class Items {
}
}
/** An item representing a dynamic call site.
*/
class DynamicItem extends StaticItem {
DynamicItem(Symbol member) {
super(member);
}
Item load() {
assert false;
return null;
}
void store() {
assert false;
}
Item invoke() {
// assert target.hasNativeInvokeDynamic();
MethodType mtype = (MethodType)member.erasure(types);
int rescode = Code.typecode(mtype.restype);
code.emitInvokedynamic(pool.put(member), mtype);
return stackItem[rescode];
}
public String toString() {
return "dynamic(" + member + ")";
}
}
/** An item representing an instance variable or method.
*/
class MemberItem extends Item {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2012, 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
@ -25,10 +25,17 @@
package com.sun.tools.javac.jvm;
import java.util.*;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.util.ArrayUtils;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Filter;
import com.sun.tools.javac.util.Name;
import java.util.*;
/** An internal structure that corresponds to the constant pool of a classfile.
*
* <p><b>This is NOT part of any supported API.
@ -83,14 +90,6 @@ public class Pool {
indices.clear();
}
/** Double pool buffer in size.
*/
private void doublePool() {
Object[] newpool = new Object[pool.length * 2];
System.arraycopy(pool, 0, newpool, 0, pool.length);
pool = newpool;
}
/** Place an object in the pool, unless it is already there.
* If object is a symbol also enter its owner unless the owner is a
* package. Return the object's index in the pool.
@ -106,10 +105,10 @@ public class Pool {
// System.err.println("put " + value + " " + value.getClass());//DEBUG
index = pp;
indices.put(value, index);
if (pp == pool.length) doublePool();
pool = ArrayUtils.ensureCapacity(pool, pp);
pool[pp++] = value;
if (value instanceof Long || value instanceof Double) {
if (pp == pool.length) doublePool();
pool = ArrayUtils.ensureCapacity(pool, pp);
pool[pp++] = null;
}
}
@ -167,4 +166,86 @@ public class Pool {
v.type.hashCode();
}
}
public static class MethodHandle {
/** Reference kind - see ClassFile */
int refKind;
/** Reference symbol */
Symbol refSym;
public MethodHandle(int refKind, Symbol refSym) {
this.refKind = refKind;
this.refSym = refSym;
checkConsistent();
}
public boolean equals(Object other) {
if (!(other instanceof MethodHandle)) return false;
MethodHandle mr = (MethodHandle) other;
if (mr.refKind != refKind) return false;
Symbol o = mr.refSym;
return
o.name == refSym.name &&
o.owner == refSym.owner &&
o.type.equals(refSym.type);
}
public int hashCode() {
return
refKind * 65 +
refSym.name.hashCode() * 33 +
refSym.owner.hashCode() * 9 +
refSym.type.hashCode();
}
/**
* Check consistency of reference kind and symbol (see JVMS 4.4.8)
*/
@SuppressWarnings("fallthrough")
private void checkConsistent() {
boolean staticOk = false;
int expectedKind = -1;
Filter<Name> nameFilter = nonInitFilter;
boolean interfaceOwner = false;
switch (refKind) {
case ClassFile.REF_getStatic:
case ClassFile.REF_putStatic:
staticOk = true;
case ClassFile.REF_getField:
case ClassFile.REF_putField:
expectedKind = Kinds.VAR;
break;
case ClassFile.REF_newInvokeSpecial:
nameFilter = initFilter;
expectedKind = Kinds.MTH;
break;
case ClassFile.REF_invokeInterface:
interfaceOwner = true;
expectedKind = Kinds.MTH;
break;
case ClassFile.REF_invokeStatic:
staticOk = true;
case ClassFile.REF_invokeVirtual:
case ClassFile.REF_invokeSpecial:
expectedKind = Kinds.MTH;
break;
}
Assert.check(!refSym.isStatic() || staticOk);
Assert.check(refSym.kind == expectedKind);
Assert.check(nameFilter.accepts(refSym.name));
Assert.check(!refSym.owner.isInterface() || interfaceOwner);
}
//where
Filter<Name> nonInitFilter = new Filter<Name>() {
public boolean accepts(Name n) {
return n != n.table.names.init && n != n.table.names.clinit;
}
};
Filter<Name> initFilter = new Filter<Name>() {
public boolean accepts(Name n) {
return n == n.table.names.init;
}
};
}
}

View File

@ -406,10 +406,17 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
? names.fromString(options.get("failcomplete"))
: null;
shouldStopPolicy =
options.isSet("shouldStopPolicy")
shouldStopPolicyIfError =
options.isSet("shouldStopPolicy") // backwards compatible
? CompileState.valueOf(options.get("shouldStopPolicy"))
: null;
: options.isSet("shouldStopPolicyIfError")
? CompileState.valueOf(options.get("shouldStopPolicyIfError"))
: CompileState.INIT;
shouldStopPolicyIfNoError =
options.isSet("shouldStopPolicyIfNoError")
? CompileState.valueOf(options.get("shouldStopPolicyIfNoError"))
: CompileState.GENERATE;
if (options.isUnset("oldDiags"))
log.setDiagnosticFormatter(RichDiagnosticFormatter.instance(context));
}
@ -486,12 +493,20 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
public boolean verboseCompilePolicy;
/**
* Policy of how far to continue processing. null means until first
* error.
* Policy of how far to continue compilation after errors have occurred.
* Set this to minimum CompileState (INIT) to stop as soon as possible
* after errors.
*/
public CompileState shouldStopPolicy;
public CompileState shouldStopPolicyIfError;
/** A queue of all as yet unattributed classes.
/**
* Policy of how far to continue compilation when no errors have occurred.
* Set this to maximum CompileState (GENERATE) to perform full compilation.
* Set this lower to perform partial compilation, such as -proc:only.
*/
public CompileState shouldStopPolicyIfNoError;
/** A queue of all as yet unattributed classes.oLo
*/
public Todo todo;
@ -501,6 +516,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
/** Ordered list of compiler phases for each compilation unit. */
public enum CompileState {
INIT(0),
PARSE(1),
ENTER(2),
PROCESS(3),
@ -512,8 +528,11 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
CompileState(int value) {
this.value = value;
}
boolean isDone(CompileState other) {
return value >= other.value;
boolean isAfter(CompileState other) {
return value > other.value;
}
public static CompileState max(CompileState a, CompileState b) {
return a.value > b.value ? a : b;
}
private int value;
};
@ -524,7 +543,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
private static final long serialVersionUID = 1812267524140424433L;
boolean isDone(Env<AttrContext> env, CompileState cs) {
CompileState ecs = get(env);
return ecs != null && ecs.isDone(cs);
return (ecs != null) && !cs.isAfter(ecs);
}
}
private CompileStates compileStates = new CompileStates();
@ -536,10 +555,10 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
protected Set<JavaFileObject> inputFiles = new HashSet<JavaFileObject>();
protected boolean shouldStop(CompileState cs) {
if (shouldStopPolicy == null)
return (errorCount() > 0 || unrecoverableError());
else
return cs.ordinal() > shouldStopPolicy.ordinal();
CompileState shouldStopPolicy = (errorCount() > 0 || unrecoverableError())
? shouldStopPolicyIfError
: shouldStopPolicyIfNoError;
return cs.isAfter(shouldStopPolicy);
}
/** The number of errors reported so far.
@ -923,6 +942,18 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
return trees.toList();
}
/**
* Enter the symbols found in a list of parse trees if the compilation
* is expected to proceed beyond anno processing into attr.
* As a side-effect, this puts elements on the "todo" list.
* Also stores a list of all top level classes in rootClasses.
*/
public List<JCCompilationUnit> enterTreesIfNeeded(List<JCCompilationUnit> roots) {
if (shouldStop(CompileState.ATTR))
return List.nil();
return enterTrees(roots);
}
/**
* Enter the symbols found in a list of parse trees.
* As a side-effect, this puts elements on the "todo" list.
@ -1010,7 +1041,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
genEndPos = true;
if (!taskListener.isEmpty())
taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
log.deferDiagnostics = true;
log.deferAll();
} else { // free resources
procEnvImpl.close();
}
@ -1120,7 +1151,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
if (c != this)
annotationProcessingOccurred = c.annotationProcessingOccurred = true;
// doProcessing will have handled deferred diagnostics
Assert.check(c.log.deferDiagnostics == false
Assert.check(c.log.deferredDiagFilter == null
&& c.log.deferredDiagnostics.size() == 0);
return c;
} finally {
@ -1196,7 +1227,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) {
//if in fail-over mode, ensure that AST expression nodes
//are correctly initialized (e.g. they have a type/symbol)
attr.postAttr(env);
attr.postAttr(env.tree);
}
compileStates.put(env, CompileState.ATTR);
}
@ -1648,6 +1679,8 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
hasBeenUsed = true;
closeables = prev.closeables;
prev.closeables = List.nil();
shouldStopPolicyIfError = prev.shouldStopPolicyIfError;
shouldStopPolicyIfNoError = prev.shouldStopPolicyIfNoError;
}
public static void enableLogging() {

View File

@ -638,10 +638,6 @@ public class JavaTokenizer {
lexError(pos, "unclosed.str.lit");
}
break loop;
case '#':
reader.scanChar();
tk = TokenKind.HASH;
break loop;
default:
if (isSpecial(reader.ch)) {
scanOperator();

View File

@ -950,12 +950,13 @@ public class JavacParser implements Parser {
break;
case LPAREN:
if (typeArgs == null && (mode & EXPR) != 0) {
if (peekToken(FINAL) ||
if (peekToken(MONKEYS_AT) ||
peekToken(FINAL) ||
peekToken(RPAREN) ||
peekToken(IDENTIFIER, COMMA) ||
peekToken(IDENTIFIER, RPAREN, ARROW)) {
//implicit n-ary lambda
t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos);
t = lambdaExpressionOrStatement(true, peekToken(MONKEYS_AT) || peekToken(FINAL), pos);
break;
} else {
nextToken();
@ -1159,7 +1160,7 @@ public class JavacParser implements Parser {
case LT:
if ((mode & TYPE) == 0 && isUnboundMemberRef()) {
//this is an unbound method reference whose qualifier
//is a generic type i.e. A<S>#m
//is a generic type i.e. A<S>::m
int pos1 = token.pos;
accept(LT);
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
@ -1177,7 +1178,8 @@ public class JavacParser implements Parser {
t = toP(F.at(token.pos).Select(t, ident()));
t = typeArgumentsOpt(t);
}
if (token.kind != HASH) {
t = bracketsOpt(t);
if (token.kind != COLCOL) {
//method reference expected here
t = illegal();
}
@ -1237,6 +1239,10 @@ public class JavacParser implements Parser {
nextToken();
t = bracketsOpt(t);
t = toP(F.at(pos1).TypeArray(t));
if (token.kind == COLCOL) {
mode = EXPR;
continue;
}
return t;
}
mode = oldmode;
@ -1269,10 +1275,10 @@ public class JavacParser implements Parser {
t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
typeArgs = null;
}
} else if ((mode & EXPR) != 0 && token.kind == HASH) {
} else if ((mode & EXPR) != 0 && token.kind == COLCOL) {
mode = EXPR;
if (typeArgs != null) return illegal();
accept(HASH);
accept(COLCOL);
t = memberReferenceSuffix(pos1, t);
} else {
break;
@ -1311,9 +1317,11 @@ public class JavacParser implements Parser {
case GT:
depth--;
if (depth == 0) {
TokenKind nextKind = S.token(pos + 1).kind;
return
S.token(pos + 1).kind == TokenKind.DOT ||
S.token(pos + 1).kind == TokenKind.HASH;
nextKind == TokenKind.DOT ||
nextKind == TokenKind.LBRACKET ||
nextKind == TokenKind.COLCOL;
}
break;
default:
@ -1343,11 +1351,6 @@ public class JavacParser implements Parser {
}
JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
if (token.kind != ARROW) {
//better error recovery
return F.at(pos).Erroneous(args);
}
checkLambda();
accept(ARROW);
@ -1372,7 +1375,7 @@ public class JavacParser implements Parser {
nextToken();
if (token.kind == LPAREN || typeArgs != null) {
t = arguments(typeArgs, t);
} else if (token.kind == HASH) {
} else if (token.kind == COLCOL) {
if (typeArgs != null) return illegal();
t = memberReferenceSuffix(t);
} else {
@ -1583,20 +1586,22 @@ public class JavacParser implements Parser {
t = toP(F.at(pos).Select(t, names._class));
}
} else if ((mode & TYPE) != 0) {
mode = TYPE;
} else {
if (token.kind != COLCOL) {
mode = TYPE;
}
} else if (token.kind != COLCOL) {
syntaxError(token.pos, "dot.class.expected");
}
return t;
}
/**
* MemberReferenceSuffix = "#" [TypeArguments] Ident
* | "#" [TypeArguments] "new"
* MemberReferenceSuffix = "::" [TypeArguments] Ident
* | "::" [TypeArguments] "new"
*/
JCExpression memberReferenceSuffix(JCExpression t) {
int pos1 = token.pos;
accept(HASH);
accept(COLCOL);
return memberReferenceSuffix(pos1, t);
}
@ -2165,27 +2170,10 @@ public class JavacParser implements Parser {
while (true) {
int pos = token.pos;
switch (token.kind) {
case CASE: {
nextToken();
JCExpression pat = parseExpression();
accept(COLON);
List<JCStatement> stats = blockStatements();
JCCase c = F.at(pos).Case(pat, stats);
if (stats.isEmpty())
storeEnd(c, S.prevToken().endPos);
cases.append(c);
case CASE:
case DEFAULT:
cases.append(switchBlockStatementGroup());
break;
}
case DEFAULT: {
nextToken();
accept(COLON);
List<JCStatement> stats = blockStatements();
JCCase c = F.at(pos).Case(null, stats);
if (stats.isEmpty())
storeEnd(c, S.prevToken().endPos);
cases.append(c);
break;
}
case RBRACE: case EOF:
return cases.toList();
default:
@ -2196,6 +2184,32 @@ public class JavacParser implements Parser {
}
}
protected JCCase switchBlockStatementGroup() {
int pos = token.pos;
List<JCStatement> stats;
JCCase c;
switch (token.kind) {
case CASE:
nextToken();
JCExpression pat = parseExpression();
accept(COLON);
stats = blockStatements();
c = F.at(pos).Case(pat, stats);
if (stats.isEmpty())
storeEnd(c, S.prevToken().endPos);
return c;
case DEFAULT:
nextToken();
accept(COLON);
stats = blockStatements();
c = F.at(pos).Case(null, stats);
if (stats.isEmpty())
storeEnd(c, S.prevToken().endPos);
return c;
}
throw new AssertionError("should not reach here");
}
/** MoreStatementExpressions = { COMMA StatementExpression }
*/
<T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,

View File

@ -177,7 +177,7 @@ public class Tokens {
FALSE("false", Tag.NAMED),
NULL("null", Tag.NAMED),
ARROW("->"),
HASH("#"),
COLCOL("::"),
LPAREN("("),
RPAREN(")"),
LBRACE("{"),

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2012, 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
@ -25,13 +25,15 @@
package com.sun.tools.javac.parser;
import java.nio.CharBuffer;
import java.util.Arrays;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.ArrayUtils;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import java.nio.CharBuffer;
import static com.sun.tools.javac.util.LayoutCharacters.*;
/** The char reader used by the javac lexer/tokenizer. Returns the sequence of
@ -91,9 +93,7 @@ public class UnicodeReader {
if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
inputLength--;
} else {
char[] newInput = new char[inputLength + 1];
System.arraycopy(input, 0, newInput, 0, input.length);
input = newInput;
input = Arrays.copyOf(input, inputLength + 1);
}
}
buf = input;
@ -130,11 +130,7 @@ public class UnicodeReader {
/** Append a character to sbuf.
*/
protected void putChar(char ch, boolean scan) {
if (sp == sbuf.length) {
char[] newsbuf = new char[sbuf.length * 2];
System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
sbuf = newsbuf;
}
sbuf = ArrayUtils.ensureCapacity(sbuf, sp);
sbuf[sp++] = ch;
if (scan)
scanChar();

View File

@ -49,7 +49,7 @@ import static javax.tools.StandardLocation.*;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.api.MultiTaskListener;
import com.sun.tools.javac.code.*;
@ -97,11 +97,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
private final boolean printRounds;
private final boolean verbose;
private final boolean lint;
private final boolean procOnly;
private final boolean fatalErrors;
private final boolean werror;
private final boolean showResolveErrors;
private boolean foundTypeProcessors;
private final JavacFiler filer;
private final JavacMessager messager;
@ -167,12 +165,14 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
printRounds = options.isSet(XPRINTROUNDS);
verbose = options.isSet(VERBOSE);
lint = Lint.instance(context).isEnabled(PROCESSING);
procOnly = options.isSet(PROC, "only") || options.isSet(XPRINT);
if (options.isSet(PROC, "only") || options.isSet(XPRINT)) {
JavaCompiler compiler = JavaCompiler.instance(context);
compiler.shouldStopPolicyIfNoError = CompileState.PROCESS;
}
fatalErrors = options.isSet("fatalEnterError");
showResolveErrors = options.isSet("showResolveErrors");
werror = options.isSet(WERROR);
platformAnnotations = initPlatformAnnotations();
foundTypeProcessors = false;
// Initialize services before any processors are initialized
// in case processors use them.
@ -462,7 +462,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
* State about how a processor has been used by the tool. If a
* processor has been used on a prior round, its process method is
* called on all subsequent rounds, perhaps with an empty set of
* annotations to process. The {@code annotatedSupported} method
* annotations to process. The {@code annotationSupported} method
* caches the supported annotation information from the first (and
* only) getSupportedAnnotationTypes call to the processor.
*/
@ -806,7 +806,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
log = Log.instance(context);
log.nerrors = priorErrors;
log.nwarnings += priorWarnings;
log.deferDiagnostics = true;
log.deferAll();
// the following is for the benefit of JavacProcessingEnvironment.getContext()
JavacProcessingEnvironment.this.context = context;
@ -882,7 +882,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/** Create the compiler to be used for the final compilation. */
JavaCompiler finalCompiler(boolean errorStatus) {
try {
JavaCompiler c = JavaCompiler.instance(nextContext());
Context nextCtx = nextContext();
JavacProcessingEnvironment.this.context = nextCtx;
JavaCompiler c = JavaCompiler.instance(nextCtx);
c.log.nwarnings += compiler.log.nwarnings;
if (errorStatus) {
c.log.nerrors += compiler.log.nerrors;
@ -1021,7 +1023,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
/** Get the context for the next round of processing.
* Important values are propogated from round to round;
* Important values are propagated from round to round;
* other values are implicitly reset.
*/
private Context nextContext() {
@ -1086,10 +1088,11 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
elementUtils.setContext(next);
typeUtils.setContext(next);
JavacTaskImpl task = (JavacTaskImpl) context.get(JavacTask.class);
JavacTask task = context.get(JavacTask.class);
if (task != null) {
next.put(JavacTask.class, task);
task.updateContext(next);
if (task instanceof BasicJavacTask)
((BasicJavacTask) task).updateContext(next);
}
JavacTrees trees = context.get(JavacTrees.class);
@ -1189,14 +1192,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
return compiler;
}
if (procOnly && !foundTypeProcessors) {
compiler.todo.clear();
} else {
if (procOnly && foundTypeProcessors)
compiler.shouldStopPolicy = CompileState.FLOW;
compiler.enterTrees(roots);
}
compiler.enterTreesIfNeeded(roots);
return compiler;
}

View File

@ -148,13 +148,8 @@ compiler.err.break.outside.switch.loop=\
compiler.err.call.must.be.first.stmt.in.ctor=\
call to {0} must be first statement in constructor
compiler.err.cant.apply.symbol=\
{0} {1} in {4} {5} cannot be applied to given types\n\
required: {2}\n\
found: {3}
# 0: symbol kind, 1: name, 2: list of type or message segment, 3: list of type or message segment, 4: symbol kind, 5: type, 6: message segment
compiler.err.cant.apply.symbol.1=\
compiler.err.cant.apply.symbol=\
{0} {1} in {4} {5} cannot be applied to given types;\n\
required: {2}\n\
found: {3}\n\
@ -164,6 +159,74 @@ compiler.err.cant.apply.symbol.1=\
compiler.err.cant.apply.symbols=\
no suitable {0} found for {1}({2})
# 0: symbol kind, 1: name, 2: list of type or message segment, 3: list of type or message segment, 4: symbol kind, 5: type, 6: message segment
compiler.misc.cant.apply.symbol=\
{0} {1} in {4} {5} cannot be applied to given types\n\
required: {2}\n\
found: {3}\n\
reason: {6}
# 0: symbol kind, 1: name, 2: list of type
compiler.misc.cant.apply.symbols=\
no suitable {0} found for {1}({2})
# 0: type
compiler.err.cant.access.arg.type.in.functional.desc=\
cannot access parameter type {0} in target functional descriptor
# 0: type
compiler.err.cant.access.return.in.functional.desc=\
cannot access return type {0} in target functional descriptor
# 0: type
compiler.err.cant.access.thrown.in.functional.desc=\
cannot access thrown type {0} in target functional descriptor
# 0: symbol kind, 1: symbol
compiler.misc.no.abstracts=\
no abstract method found in {0} {1}
# 0: symbol kind, 1: symbol
compiler.misc.incompatible.abstracts=\
multiple non-overriding abstract methods found in {0} {1}
compiler.misc.not.a.functional.intf=\
the target type must be a functional interface
# 0: message segment
compiler.misc.not.a.functional.intf.1=\
the target type must be a functional interface\n\
{0}
# 0: symbol, 1: symbol kind, 2: symbol
compiler.misc.invalid.generic.desc.in.functional.intf=\
invalid functional descriptor: method {0} in {1} {2} is generic
# 0: symbol kind, 1: symbol
compiler.misc.incompatible.descs.in.functional.intf=\
incompatible function descriptors found in {0} {1}
# 0: name, 1: list of type, 2: type, 3: list of type
compiler.misc.descriptor=\
descriptor: {2} {0}({1})
# 0: name, 1: list of type, 2: type, 3: list of type
compiler.misc.descriptor.throws=\
descriptor: {2} {0}({1}) throws {3}
# 0: type
compiler.misc.no.suitable.functional.intf.inst=\
cannot infer functional interface descriptor for {0}
# 0: symbol kind, 1: message segment
compiler.err.invalid.mref=\
invalid {0} reference; {1}
# 0: symbol kind, 1: message segment
compiler.misc.invalid.mref=\
invalid {0} reference; {1}
# 0: symbol
compiler.err.cant.assign.val.to.final.var=\
cannot assign a value to final variable {0}
@ -173,6 +236,9 @@ compiler.err.cant.ref.non.effectively.final.var=\
local variables referenced from {1} must be final or effectively final
compiler.misc.lambda=\
a lambda expression
compiler.misc.inner.cls=\
an inner class
@ -292,7 +358,7 @@ compiler.err.invalid.containedby.annotation.value.return=\
# 0: type, 1: symbol
compiler.err.invalid.containedby.annotation.elem.nondefault=\
duplicate annotation, element {1} in containing annotation {0} does not have a default value
containing annotation {0} does not have a default value for element {1}
# 0: symbol, 1: type, 2: symbol, 3: type
compiler.err.invalid.containedby.annotation.retention=\
@ -592,6 +658,9 @@ compiler.err.missing.meth.body.or.decl.abstract=\
compiler.err.missing.ret.stmt=\
missing return statement
compiler.misc.missing.ret.val=\
missing return value
compiler.err.missing.ret.val=\
missing return value
@ -635,6 +704,31 @@ compiler.err.neither.conditional.subtype=\
second operand: {0}\n\
third operand : {1}
# 0: message segment
compiler.misc.incompatible.type.in.conditional=\
bad type in conditional expression; {0}
# 0: type
compiler.misc.incompatible.ret.type.in.lambda=\
bad return type in lambda expression\n\
{0}
# 0: type
compiler.misc.incompatible.ret.type.in.mref=\
bad return type in method reference\n\
{0}
# 0: list of type
compiler.err.incompatible.thrown.types.in.lambda=\
incompatible thrown types {0} in lambda expression
# 0: list of type
compiler.err.incompatible.thrown.types.in.mref=\
incompatible thrown types {0} in method reference
compiler.misc.incompatible.arg.types.in.lambda=\
incompatible parameter types in lambda expression
compiler.err.new.not.allowed.in.annotation=\
''new'' not allowed in an annotation
@ -657,6 +751,15 @@ compiler.err.not.annotation.type=\
compiler.err.not.def.access.class.intf.cant.access=\
{0} in {1} is defined in an inaccessible class or interface
# 0: symbol, 1: symbol
compiler.misc.not.def.access.class.intf.cant.access=\
{0} in {1} is defined in an inaccessible class or interface
# 0: symbol, 1: list of type, 2: type
compiler.misc.cant.access.inner.cls.constr=\
cannot access constructor {0}({1})\n\
an enclosing instance of type {2} is not in scope
# 0: symbol, 1: symbol
compiler.err.not.def.public.cant.access=\
{0} is not public in {1}; cannot be accessed from outside package
@ -755,7 +858,13 @@ compiler.err.recursive.ctor.invocation=\
# 0: name, 1: symbol kind, 2: symbol, 3: symbol, 4: symbol kind, 5: symbol, 6: symbol
compiler.err.ref.ambiguous=\
reference to {0} is ambiguous, both {1} {2} in {3} and {4} {5} in {6} match
reference to {0} is ambiguous\n\
both {1} {2} in {3} and {4} {5} in {6} match
# 0: name, 1: symbol kind, 2: symbol, 3: symbol, 4: symbol kind, 5: symbol, 6: symbol
compiler.misc.ref.ambiguous=\
reference to {0} is ambiguous\n\
both {1} {2} in {3} and {4} {5} in {6} match
compiler.err.repeated.annotation.target=\
repeated annotation target
@ -991,6 +1100,10 @@ compiler.misc.x.print.rounds=\
## The following string will appear before all messages keyed as:
## "compiler.note".
compiler.note.potential.lambda.found=\
This anonymous inner class creation can be turned into a lambda expression.
compiler.note.note=\
Note:\u0020
@ -1652,6 +1765,18 @@ compiler.misc.no.unique.minimal.instance.exists=\
compiler.misc.incompatible.upper.bounds=\
inference variable {0} has incompatible upper bounds {1}
# 0: type, 1: list of type, 2: list of type
compiler.misc.incompatible.eq.upper.bounds=\
inference variable {0} has incompatible bounds\n\
equality constraints: {1}\n\
upper bounds: {2}
# 0: type, 1: list of type, 2: list of type
compiler.misc.incompatible.eq.lower.bounds=\
inference variable {0} has incompatible bounds\n\
equality constraints: {1}\n\
lower bounds: {2}
# 0: list of type, 1: type, 2: type
compiler.misc.infer.no.conforming.instance.exists=\
no instance(s) of type variable(s) {0} exist so that {1} conforms to {2}
@ -1689,6 +1814,10 @@ compiler.misc.inferred.do.not.conform.to.eq.bounds=\
inferred: {0}\n\
equality constraints(s): {1}
# 0: list of type
compiler.misc.cyclic.inference=\
Cannot instantiate inference variables {0} because of an inference loop
# 0: symbol
compiler.misc.diamond=\
{0}<>
@ -1728,6 +1857,10 @@ compiler.err.abstract.cant.be.accessed.directly=\
compiler.err.non-static.cant.be.ref=\
non-static {0} {1} cannot be referenced from a static context
# 0: symbol kind, 1: symbol
compiler.misc.non-static.cant.be.ref=\
non-static {0} {1} cannot be referenced from a static context
## Both arguments ({0}, {1}) are "kindname"s. {0} is a comma-separated list
## of kindnames (the list should be identical to that provided in source.
compiler.err.unexpected.type=\
@ -1735,6 +1868,12 @@ compiler.err.unexpected.type=\
required: {0}\n\
found: {1}
compiler.err.unexpected.lambda=\
lambda expression not expected here
compiler.err.unexpected.mref=\
method reference not expected here
## The first argument {0} is a "kindname" (e.g. 'constructor', 'field', etc.)
## The second argument {1} is the non-resolved symbol
## The third argument {2} is a list of type parameters (non-empty if {1} is a method)
@ -1774,6 +1913,20 @@ compiler.err.cant.resolve.location.args.params=\
symbol: {0} <{2}>{1}({3})\n\
location: {4}
### Following are replicated/used for method reference diagnostics
# 0: symbol kind, 1: name, 2: unused, 3: list of type, 4: message segment
compiler.misc.cant.resolve.location.args=\
cannot find symbol\n\
symbol: {0} {1}({3})\n\
location: {4}
# 0: symbol kind, 1: name, 2: list of type, 3: list, 4: message segment
compiler.misc.cant.resolve.location.args.params=\
cannot find symbol\n\
symbol: {0} <{2}>{1}({3})\n\
location: {4}
##a location subdiagnostic is composed as follows:
## The first argument {0} is the location "kindname" (e.g. 'constructor', 'field', etc.)
## The second argument {1} is the location name

View File

@ -1810,11 +1810,46 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
public static class JCMemberReference extends JCExpression implements MemberReferenceTree {
public ReferenceMode mode;
public ReferenceKind kind;
public Name name;
public JCExpression expr;
public List<JCExpression> typeargs;
public Type targetType;
public Symbol sym;
public Type varargsElement;
/**
* Javac-dependent classification for member references, based
* on relevant properties w.r.t. code-generation
*/
public enum ReferenceKind {
/** super # instMethod */
SUPER(ReferenceMode.INVOKE, false),
/** Type # instMethod */
UNBOUND(ReferenceMode.INVOKE, true),
/** Type # staticMethod */
STATIC(ReferenceMode.INVOKE, false),
/** Expr # instMethod */
BOUND(ReferenceMode.INVOKE, false),
/** Expr # staticMethod */
STATIC_EVAL(ReferenceMode.INVOKE, false),
/** Inner # new */
IMPLICIT_INNER(ReferenceMode.NEW, false),
/** Toplevel # new */
TOPLEVEL(ReferenceMode.NEW, false);
ReferenceMode mode;
boolean unbound;
private ReferenceKind(ReferenceMode mode, boolean unbound) {
this.mode = mode;
this.unbound = unbound;
}
public boolean isUnbound() {
return unbound;
}
}
protected JCMemberReference(ReferenceMode mode, Name name, JCExpression expr, List<JCExpression> typeargs) {
this.mode = mode;
@ -1843,6 +1878,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public Tag getTag() {
return REFERENCE;
}
public boolean hasKind(ReferenceKind kind) {
return this.kind == kind;
}
}
/**

View File

@ -81,6 +81,17 @@ public class Pretty extends JCTree.Visitor {
*/
DocCommentTable docComments = null;
/**
* A string sequence to be used when Pretty output should be constrained
* to fit into a given size
*/
private final static String trimSequence = "[...]";
/**
* Max number of chars to be generated when output should fit into a single line
*/
private final static int PREFERRED_LENGTH = 20;
/** Align code to be indented to left margin.
*/
void align() throws IOException {
@ -129,6 +140,31 @@ public class Pretty extends JCTree.Visitor {
out.write(lineSep);
}
public static String toSimpleString(JCTree tree) {
return toSimpleString(tree, PREFERRED_LENGTH);
}
public static String toSimpleString(JCTree tree, int maxLength) {
StringWriter s = new StringWriter();
try {
new Pretty(s, false).printExpr(tree);
}
catch (IOException e) {
// should never happen, because StringWriter is defined
// never to throw any IOExceptions
throw new AssertionError(e);
}
//we need to (i) replace all line terminators with a space and (ii) remove
//occurrences of 'missing' in the Pretty output (generated when types are missing)
String res = s.toString().replaceAll("\\s+", " ").replaceAll("/\\*missing\\*/", "");
if (res.length() < maxLength) {
return res;
} else {
int split = (maxLength - trimSequence.length()) * 2 / 3;
return res.substring(0, split) + trimSequence + res.substring(split);
}
}
String lineSep = System.getProperty("line.separator");
/**************************************************************************
@ -911,7 +947,16 @@ public class Pretty extends JCTree.Visitor {
public void visitLambda(JCLambda tree) {
try {
print("(");
printExprs(tree.params);
if (TreeInfo.isExplicitLambda(tree)) {
printExprs(tree.params);
} else {
String sep = "";
for (JCVariableDecl param : tree.params) {
print(sep);
print(param.name);
sep = ",";
}
}
print(")->");
printExpr(tree.body);
} catch (IOException e) {

View File

@ -245,6 +245,27 @@ public class TreeInfo {
}
}
/** Return true if a a tree corresponds to a poly expression. */
public static boolean isPoly(JCTree tree, JCTree origin) {
switch (tree.getTag()) {
case APPLY:
case NEWCLASS:
case CONDEXPR:
return !origin.hasTag(TYPECAST);
case LAMBDA:
case REFERENCE:
return true;
case PARENS:
return isPoly(((JCParens)tree).expr, origin);
default:
return false;
}
}
public static boolean isExplicitLambda(JCLambda lambda) {
return lambda.params.isEmpty() ||
lambda.params.head.vartype != null;
}
/**
* Return true if the AST corresponds to a static select of the kind A.B
*/
@ -261,6 +282,7 @@ public class TreeInfo {
return isStaticSym(base) &&
isStaticSelector(((JCFieldAccess)base).selected, names);
case TYPEAPPLY:
case TYPEARRAY:
return true;
default:
return false;
@ -383,6 +405,10 @@ public class TreeInfo {
JCVariableDecl node = (JCVariableDecl)tree;
if (node.mods.pos != Position.NOPOS) {
return node.mods.pos;
} else if (node.vartype == null) {
//if there's no type (partially typed lambda parameter)
//simply return node position
return node.pos;
} else {
return getStartPos(node.vartype);
}

View File

@ -43,8 +43,10 @@ import com.sun.tools.javac.code.Printer;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.CapturedType;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.tree.Pretty;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
/**
@ -180,6 +182,9 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
}
return s;
}
else if (arg instanceof JCExpression) {
return expr2String((JCExpression)arg);
}
else if (arg instanceof Iterable<?>) {
return formatIterable(d, (Iterable<?>)arg, l);
}
@ -199,6 +204,20 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
return String.valueOf(arg);
}
}
//where
private String expr2String(JCExpression tree) {
switch(tree.getTag()) {
case PARENS:
return expr2String(((JCParens)tree).expr);
case LAMBDA:
case REFERENCE:
case CONDEXPR:
return Pretty.toSimpleString(tree);
default:
Assert.error("unexpected tree kind " + tree.getKind());
return null;
}
}
/**
* Format an iterable argument of a given diagnostic.
@ -490,6 +509,7 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
* lead to infinite loops.
*/
protected Printer printer = new Printer() {
@Override
protected String localize(Locale locale, String key, Object... args) {
return AbstractDiagnosticFormatter.this.localize(locale, key, args);

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 1999, 2012, 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.
*/
package com.sun.tools.javac.util;
import java.lang.reflect.Array;
/** <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class ArrayUtils {
private static int calculateNewLength(int currentLength, int maxIndex) {
while (currentLength < maxIndex + 1)
currentLength = currentLength * 2;
return currentLength;
}
public static <T> T[] ensureCapacity(T[] array, int maxIndex) {
if (maxIndex < array.length) {
return array;
} else {
int newLength = calculateNewLength(array.length, maxIndex);
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), newLength);
System.arraycopy(array, 0, result, 0, array.length);
return result;
}
}
public static byte[] ensureCapacity(byte[] array, int maxIndex) {
if (maxIndex < array.length) {
return array;
} else {
int newLength = calculateNewLength(array.length, maxIndex);
byte[] result = new byte[newLength];
System.arraycopy(array, 0, result, 0, array.length);
return result;
}
}
public static char[] ensureCapacity(char[] array, int maxIndex) {
if (maxIndex < array.length) {
return array;
} else {
int newLength = calculateNewLength(array.length, maxIndex);
char[] result = new char[newLength];
System.arraycopy(array, 0, result, 0, array.length);
return result;
}
}
public static int[] ensureCapacity(int[] array, int maxIndex) {
if (maxIndex < array.length) {
return array;
} else {
int newLength = calculateNewLength(array.length, maxIndex);
int[] result = new int[newLength];
System.arraycopy(array, 0, result, 0, array.length);
return result;
}
}
}

View File

@ -25,6 +25,8 @@
package com.sun.tools.javac.util;
import java.util.Arrays;
/** A class for extensible, mutable bit sets.
*
* <p><b>This is NOT part of any supported API.
@ -62,9 +64,7 @@ public class Bits {
private void sizeTo(int len) {
if (bits.length < len) {
int[] newbits = new int[len];
System.arraycopy(bits, 0, newbits, 0, bits.length);
bits = newbits;
bits = Arrays.copyOf(bits, len);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2012, 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
@ -60,16 +60,10 @@ public class ByteBuffer {
length = 0;
}
private void copy(int size) {
byte[] newelems = new byte[size];
System.arraycopy(elems, 0, newelems, 0, elems.length);
elems = newelems;
}
/** Append byte to this buffer.
*/
public void appendByte(int b) {
if (length >= elems.length) copy(elems.length * 2);
elems = ArrayUtils.ensureCapacity(elems, length);
elems[length++] = (byte)b;
}
@ -77,7 +71,7 @@ public class ByteBuffer {
* starting at given `start' offset.
*/
public void appendBytes(byte[] bs, int start, int len) {
while (length + len > elems.length) copy(elems.length * 2);
elems = ArrayUtils.ensureCapacity(elems, length + len);
System.arraycopy(bs, start, elems, length, len);
length += len;
}
@ -91,7 +85,7 @@ public class ByteBuffer {
/** Append a character as a two byte number.
*/
public void appendChar(int x) {
while (length + 1 >= elems.length) copy(elems.length * 2);
elems = ArrayUtils.ensureCapacity(elems, length + 1);
elems[length ] = (byte)((x >> 8) & 0xFF);
elems[length+1] = (byte)((x ) & 0xFF);
length = length + 2;
@ -100,7 +94,7 @@ public class ByteBuffer {
/** Append an integer as a four byte number.
*/
public void appendInt(int x) {
while (length + 3 >= elems.length) copy(elems.length * 2);
elems = ArrayUtils.ensureCapacity(elems, length + 3);
elems[length ] = (byte)((x >> 24) & 0xFF);
elems[length+1] = (byte)((x >> 16) & 0xFF);
elems[length+2] = (byte)((x >> 8) & 0xFF);

View File

@ -83,6 +83,19 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
}
};
/** Returns the list obtained from 'l' after removing all elements 'elem'
*/
public static <A> List<A> filter(List<A> l, A elem) {
Assert.checkNonNull(elem);
List<A> res = List.nil();
for (A a : l) {
if (a != null && !a.equals(elem)) {
res = res.prepend(a);
}
}
return res.reverse();
}
/** Construct a list consisting of given element.
*/
public static <A> List<A> of(A x1) {
@ -120,6 +133,14 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
return xs;
}
public static <A> List<A> from(Iterable<? extends A> coll) {
List<A> xs = nil();
for (A a : coll) {
xs = new List<A>(a, xs);
}
return xs;
}
/** Construct a list consisting of a given number of identical elements.
* @param len The number of elements in the list.
* @param init The value of each element.

View File

@ -130,7 +130,7 @@ public class Log extends AbstractLog {
/**
* Deferred diagnostics
*/
public boolean deferDiagnostics;
public Filter<JCDiagnostic> deferredDiagFilter;
public Queue<JCDiagnostic> deferredDiagnostics = new ListBuffer<JCDiagnostic>();
/** Construct a log with given I/O redirections.
@ -450,7 +450,7 @@ public class Log extends AbstractLog {
/** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */
public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) {
deferDiagnostics = false;
deferredDiagFilter = null;
JCDiagnostic d;
while ((d = deferredDiagnostics.poll()) != null) {
if (kinds.contains(d.getKind()))
@ -464,7 +464,7 @@ public class Log extends AbstractLog {
* reported so far, the diagnostic may be handed off to writeDiagnostic.
*/
public void report(JCDiagnostic diagnostic) {
if (deferDiagnostics) {
if (deferredDiagFilter != null && deferredDiagFilter.accepts(diagnostic)) {
deferredDiagnostics.add(diagnostic);
return;
}
@ -551,6 +551,18 @@ public class Log extends AbstractLog {
}
}
public void deferAll() {
deferredDiagFilter = new Filter<JCDiagnostic>() {
public boolean accepts(JCDiagnostic t) {
return true;
}
};
}
public void deferNone() {
deferredDiagFilter = null;
}
/** Find a localized string in the resource bundle.
* Because this method is static, it ignores the locale.
* Use localize(key, args) when possible.

View File

@ -118,6 +118,7 @@ public class Names {
// attribute names
public final Name Annotation;
public final Name AnnotationDefault;
public final Name BootstrapMethods;
public final Name Bridge;
public final Name CharacterRangeTable;
public final Name Code;
@ -246,6 +247,7 @@ public class Names {
// attribute names
Annotation = fromString("Annotation");
AnnotationDefault = fromString("AnnotationDefault");
BootstrapMethods = fromString("BootstrapMethods");
Bridge = fromString("Bridge");
CharacterRangeTable = fromString("CharacterRangeTable");
Code = fromString("Code");

View File

@ -32,6 +32,7 @@ import javax.tools.JavaFileObject;
import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.*;
import com.sun.tools.javac.api.Formattable;
import com.sun.tools.javac.file.BaseFileObject;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
import static com.sun.tools.javac.api.DiagnosticFormatter.PositionKind.*;
@ -117,16 +118,17 @@ public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
@Override
protected String formatArgument(JCDiagnostic diag, Object arg, Locale l) {
String s;
if (arg instanceof Formattable)
if (arg instanceof Formattable) {
s = arg.toString();
else if (arg instanceof BaseFileObject)
} else if (arg instanceof JCExpression) {
JCExpression tree = (JCExpression)arg;
s = "@" + tree.getStartPosition();
} else if (arg instanceof BaseFileObject) {
s = ((BaseFileObject) arg).getShortName();
else
} else {
s = super.formatArgument(diag, arg, null);
if (arg instanceof JCDiagnostic)
return "(" + s + ")";
else
return s;
}
return (arg instanceof JCDiagnostic) ? "(" + s + ")" : s;
}
@Override

View File

@ -392,11 +392,6 @@ public class RichDiagnosticFormatter extends
}
}
@Override
protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
return super.printMethodArgs(args, varArgs, locale);
}
@Override
public String visitClassSymbol(ClassSymbol s, Locale locale) {
String name = nameSimplifier.simplify(s);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2012, 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
@ -93,13 +93,7 @@ public class SharedNameTable extends Name.Table {
@Override
public Name fromChars(char[] cs, int start, int len) {
int nc = this.nc;
byte[] bytes = this.bytes;
while (nc + len * 3 >= bytes.length) {
// System.err.println("doubling name buffer of length " + names.length + " to fit " + len + " chars");//DEBUG
byte[] newnames = new byte[bytes.length * 2];
System.arraycopy(bytes, 0, newnames, 0, bytes.length);
bytes = this.bytes = newnames;
}
byte[] bytes = this.bytes = ArrayUtils.ensureCapacity(this.bytes, nc + len * 3);
int nbytes = Convert.chars2utf(cs, start, bytes, nc, len) - nc;
int h = hashValue(bytes, nc, nbytes) & hashMask;
NameImpl n = hashes[h];
@ -133,12 +127,7 @@ public class SharedNameTable extends Name.Table {
}
if (n == null) {
int nc = this.nc;
while (nc + len > names.length) {
// System.err.println("doubling name buffer of length + " + names.length + " to fit " + len + " bytes");//DEBUG
byte[] newnames = new byte[names.length * 2];
System.arraycopy(names, 0, newnames, 0, names.length);
names = this.bytes = newnames;
}
names = this.bytes = ArrayUtils.ensureCapacity(names, nc + len);
System.arraycopy(cs, start, names, nc, len);
n = new NameImpl(this);
n.index = nc;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2012, 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
@ -45,8 +45,8 @@ import com.sun.tools.classfile.Method;
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
class CodeWriter extends BasicWriter {
static CodeWriter instance(Context context) {
public class CodeWriter extends BasicWriter {
public static CodeWriter instance(Context context) {
CodeWriter instance = context.get(CodeWriter.class);
if (instance == null)
instance = new CodeWriter(context);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2012, 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
@ -25,10 +25,11 @@
package com.sun.tools.javap;
import com.sun.tools.classfile.AccessFlags;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.classfile.AccessFlags;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ConstantPool;
@ -233,8 +234,7 @@ public class StackMapWriter extends InstructionDetailWriter {
StackMap prev = map.get(pc);
assert (prev != null);
int k = 251 - frame.frame_type;
verification_type_info[] new_locals = new verification_type_info[prev.locals.length - k];
System.arraycopy(prev.locals, 0, new_locals, 0, new_locals.length);
verification_type_info[] new_locals = Arrays.copyOf(prev.locals, prev.locals.length - k);
StackMap m = new StackMap(new_locals, empty);
map.put(new_pc, m);
return new_pc;

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2012, 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 7132631
* @summary Make sure that the help file is generated correctly.
* @author Bhavesh Patel
* @library ../lib/
* @build JavadocTester TestHelpFile
* @run main TestHelpFile
*/
public class TestHelpFile extends JavadocTester {
//Test information.
private static final String BUG_ID = "7132631";
//Javadoc arguments.
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR,
SRC_DIR + FS + "TestHelpFile.java"
};
private static final String[][] NEGATED_TEST = NO_TEST;
private static final String[][] TEST = {
{BUG_ID + FS + "help-doc.html",
"<a href=\"constant-values.html\">Constant Field Values</a>"
},
};
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
public static void main(String[] args) {
TestHelpFile tester = new TestHelpFile();
run(tester, ARGS, TEST, NEGATED_TEST);
tester.printSummary();
}
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
/**
* {@inheritDoc}
*/
public String getBugName() {
return getClass().getName();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2012, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 4496290 4985072 7006178
* @bug 4496290 4985072 7006178 7068595
* @summary A simple test to determine if -use works.
* @author jamieh
* @library ../lib/
@ -34,7 +34,7 @@
public class TestUseOption extends JavadocTester {
private static final String BUG_ID = "4496290-4985072-7006178";
private static final String BUG_ID = "4496290-4985072-7006178-7068595";
//Input for string search tests.
private static final String[] TEST2 = {
@ -64,6 +64,13 @@ public class TestUseOption extends JavadocTester {
}
};
private static final String[][] TEST4 = {
{BUG_ID + "-4" + FS + "pkg2" + FS + "class-use" + FS + "C3.html", "<a href=" +
"\"../../index.html?pkg2/class-use/C3.html\" target=\"_top\">" +
"Frames</a></li>"
}
};
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR, "-use", "pkg1", "pkg2"
};
@ -76,6 +83,10 @@ public class TestUseOption extends JavadocTester {
"-d", BUG_ID + "-3", "-sourcepath", SRC_DIR, "-use", SRC_DIR + FS + "C.java", SRC_DIR + FS + "UsedInC.java"
};
private static final String[] ARGS4 = new String[] {
"-d", BUG_ID + "-4", "-sourcepath", SRC_DIR, "-use", "pkg1", "pkg2"
};
/**
* The entry point of the test.
* @param args the array of command line arguments.
@ -108,6 +119,7 @@ public class TestUseOption extends JavadocTester {
}
tester.printSummary();
run(tester, ARGS3, TEST3, NO_TEST);
run(tester, ARGS4, TEST4, NO_TEST);
tester.printSummary();
}

View File

@ -43,9 +43,9 @@ class Test {
boolean b = new Object() {
public boolean equals(Object other) {
String p = "p, other, super, this; super, this; List, Test2, Test; java.io.*, java.lang.*";
String q = "q, p, other, super, this; super, this; List, Test2, Test; java.io.*, java.lang.*";
String r = "r, q, p, other, super, this; super, this; List, Test2, Test; java.io.*, java.lang.*";
String p = "p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
String q = "q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
String r = "r, q, p, other, super, this; -, super, this; List, Test2, Test; java.io.*, java.lang.*";
return (this == other);
}

View File

@ -1,3 +1,3 @@
T6758789a.java:14:9: compiler.err.cant.apply.symbol.1: kindname.method, m1, compiler.misc.no.args, int, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
T6758789a.java:15:9: compiler.err.cant.apply.symbol.1: kindname.method, m2, int, compiler.misc.no.args, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
T6758789a.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m1, compiler.misc.no.args, int, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
T6758789a.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m2, int, compiler.misc.no.args, kindname.class, T6758789a, (compiler.misc.arg.length.mismatch)
2 errors

View File

@ -1,4 +1,4 @@
T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<java.lang.Object>
T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<X>
T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
- compiler.err.warnings.and.werror
1 error

View File

@ -1,3 +1,2 @@
T6840059.java:15:9: compiler.err.cant.apply.symbol.1: kindname.constructor, T6840059, java.lang.Integer, java.lang.String, kindname.class, T6840059, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
T6840059.java:15:25: compiler.err.cant.apply.symbol.1: kindname.constructor, T6840059, java.lang.Integer, compiler.misc.no.args, kindname.class, T6840059, (compiler.misc.arg.length.mismatch)
2 errors
T6840059.java:15:9: compiler.err.cant.apply.symbol: kindname.constructor, T6840059, java.lang.Integer, java.lang.String, kindname.class, T6840059, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
1 error

View File

@ -1,3 +1,2 @@
T6857948.java:16:32: compiler.err.cant.resolve.location.args: kindname.method, nosuchfunction, , , (compiler.misc.location: kindname.class, Test, null)
T6857948.java:16:50: compiler.err.cant.apply.symbol.1: kindname.constructor, Foo, java.lang.String, compiler.misc.no.args, kindname.class, Foo, (compiler.misc.arg.length.mismatch)
2 errors
1 error

View File

@ -1,4 +1,4 @@
T7132880.java:23:12: compiler.err.cant.apply.symbol.1: kindname.method, m1, java.lang.Integer, java.lang.String, kindname.class, Outer.Inner1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
T7132880.java:23:12: compiler.err.cant.apply.symbol: kindname.method, m1, java.lang.Integer, java.lang.String, kindname.class, Outer.Inner1, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
T7132880.java:33:12: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Double), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Double))),(compiler.misc.inapplicable.method: kindname.method, Outer.Inner2, m1(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer)))}
T7132880.java:43:12: compiler.err.ref.ambiguous: m2, kindname.method, m2(java.lang.Object,int), Outer.Inner3, kindname.method, m2(int,java.lang.Object), Outer.Inner3
3 errors

View File

@ -1,2 +1,2 @@
T6722234a.java:12:9: compiler.err.cant.apply.symbol.1: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
T6722234a.java:12:9: compiler.err.cant.apply.symbol: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
1 error

View File

@ -1,3 +1,3 @@
T6722234a.java:12:9: compiler.err.cant.apply.symbol.1: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
T6722234a.java:12:9: compiler.err.cant.apply.symbol: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
- compiler.misc.where.description.typevar.1: compiler.misc.type.var: T, 1,compiler.misc.type.var: T, 2,{(compiler.misc.where.typevar: compiler.misc.type.var: T, 1, java.lang.String, kindname.class, T6722234a),(compiler.misc.where.typevar: compiler.misc.type.var: T, 2, java.lang.Integer, kindname.method, <compiler.misc.type.var: T, 2>test(compiler.misc.type.var: T, 2))}
1 error

View File

@ -1,2 +1,2 @@
T6722234b.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, m, List<T>,List<T>, List<compiler.misc.type.captureof: 1, ? extends T6722234b>,List<compiler.misc.type.captureof: 2, ? extends T6722234b>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ? extends T6722234b, compiler.misc.type.captureof: 2, ? extends T6722234b,compiler.misc.type.captureof: 1, ? extends T6722234b)
T6722234b.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, List<T>,List<T>, List<compiler.misc.type.captureof: 1, ? extends T6722234b>,List<compiler.misc.type.captureof: 2, ? extends T6722234b>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ? extends T6722234b, compiler.misc.type.captureof: 2, ? extends T6722234b,compiler.misc.type.captureof: 1, ? extends T6722234b)
1 error

View File

@ -1,4 +1,4 @@
T6722234b.java:16:9: compiler.err.cant.apply.symbol.1: kindname.method, m, List<T>,List<T>, List<compiler.misc.captured.type: 1>,List<compiler.misc.captured.type: 2>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.captured.type: 2, compiler.misc.captured.type: 2,compiler.misc.captured.type: 1)
T6722234b.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, List<T>,List<T>, List<compiler.misc.captured.type: 1>,List<compiler.misc.captured.type: 2>, kindname.class, T6722234b, (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.captured.type: 2, compiler.misc.captured.type: 2,compiler.misc.captured.type: 1)
- compiler.misc.where.description.typevar: T,{(compiler.misc.where.typevar: T, Object, kindname.method, <T>m(List<T>,List<T>))}
- compiler.misc.where.description.captured.1: compiler.misc.captured.type: 1,compiler.misc.captured.type: 2,{(compiler.misc.where.captured.1: compiler.misc.captured.type: 1, T6722234b, compiler.misc.type.null, ? extends T6722234b),(compiler.misc.where.captured.1: compiler.misc.captured.type: 2, T6722234b, compiler.misc.type.null, ? extends T6722234b)}
1 error

View File

@ -1,2 +1,2 @@
T6722234c.java:14:9: compiler.err.cant.apply.symbol.1: kindname.method, m, T6722234c.String, java.lang.String, kindname.class, T6722234c, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.lang.String, T6722234c.String))
T6722234c.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, T6722234c.String, java.lang.String, kindname.class, T6722234c, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.lang.String, T6722234c.String))
1 error

View File

@ -1,3 +1,3 @@
T6862608a.java:19:33: compiler.err.cant.apply.symbol.1: kindname.method, compound, java.lang.Iterable<? extends java.util.Comparator<? super T>>, java.util.List<java.util.Comparator<?>>, kindname.class, T6862608a, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.util.List<java.util.Comparator<?>>, java.lang.Iterable<? extends java.util.Comparator<? super T>>))
T6862608a.java:19:33: compiler.err.cant.apply.symbol: kindname.method, compound, java.lang.Iterable<? extends java.util.Comparator<? super T>>, java.util.List<java.util.Comparator<?>>, kindname.class, T6862608a, (compiler.misc.infer.no.conforming.assignment.exists: T, (compiler.misc.inconvertible.types: java.util.List<java.util.Comparator<?>>, java.lang.Iterable<? extends java.util.Comparator<? super T>>))
- compiler.misc.where.description.typevar: T,{(compiler.misc.where.typevar: T, java.lang.Object, kindname.method, <T>compound(java.lang.Iterable<? extends java.util.Comparator<? super T>>))}
1 error

View File

@ -1,3 +1,3 @@
T6862608b.java:11:7: compiler.err.cant.apply.symbol.1: kindname.method, test, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T66862608b<compiler.misc.type.var: T, 1,compiler.misc.type.var: S, 2>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
T6862608b.java:11:7: compiler.err.cant.apply.symbol: kindname.method, test, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T66862608b<compiler.misc.type.var: T, 1,compiler.misc.type.var: S, 2>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
- compiler.misc.where.description.typevar.1: compiler.misc.type.var: T, 1,compiler.misc.type.var: T, 2,compiler.misc.type.var: S, 1,compiler.misc.type.var: S, 2,{(compiler.misc.where.typevar: compiler.misc.type.var: T, 1, java.lang.String, kindname.class, T66862608b),(compiler.misc.where.typevar: compiler.misc.type.var: T, 2, compiler.misc.type.var: S, 1, kindname.method, <compiler.misc.type.var: S, 1,compiler.misc.type.var: T, 2>foo(compiler.misc.type.var: T, 2)),(compiler.misc.where.typevar: compiler.misc.type.var: S, 1, java.lang.Object, kindname.method, <compiler.misc.type.var: S, 1,compiler.misc.type.var: T, 2>foo(compiler.misc.type.var: T, 2)),(compiler.misc.where.typevar: compiler.misc.type.var: S, 2, java.lang.Object, kindname.class, T66862608b)}
1 error

View File

@ -1,7 +1,7 @@
T6326754.java:44:12: compiler.err.name.clash.same.erasure: TestConstructor(T), TestConstructor(K)
T6326754.java:52:17: compiler.err.name.clash.same.erasure: setT(K), setT(T)
T6326754.java:64:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: T, T)
T6326754.java:70:11: compiler.err.cant.apply.symbol.1: kindname.method, setT, java.lang.Object, compiler.misc.no.args, kindname.class, TestC<T>, (compiler.misc.arg.length.mismatch)
T6326754.java:70:11: compiler.err.cant.apply.symbol: kindname.method, setT, java.lang.Object, compiler.misc.no.args, kindname.class, TestC<T>, (compiler.misc.arg.length.mismatch)
- compiler.note.unchecked.filename: T6326754.java
- compiler.note.unchecked.recompile
4 errors

View File

@ -27,6 +27,7 @@
* @summary Conditional operator applies assignment conversion
* @author Tim Hanson, BEA
*
* @compile -XDallowPoly Conditional.java
* @compile/fail Conditional.java
*/

View File

@ -185,6 +185,8 @@ public class CheckResourceKeys {
"compiler.err.cant.resolve.args.params",
"compiler.err.cant.resolve.location.args",
"compiler.err.cant.resolve.location.args.params",
"compiler.misc.cant.resolve.location.args",
"compiler.misc.cant.resolve.location.args.params",
// JavaCompiler, reports #errors and #warnings
"compiler.misc.count.error",
"compiler.misc.count.error.plural",

View File

@ -1,7 +1,6 @@
compiler.err.already.annotated # internal compiler error?
compiler.err.already.defined.this.unit # seems to be masked by compiler.err.duplicate.class
compiler.err.annotation.value.not.allowable.type # cannot happen: precluded by complete type-specific tests
compiler.err.cant.apply.symbol
compiler.err.cant.read.file # (apt.JavaCompiler?)
compiler.err.cant.select.static.class.from.param.type
compiler.err.illegal.char.for.encoding
@ -65,6 +64,7 @@ compiler.misc.kindname.static
compiler.misc.kindname.type.variable
compiler.misc.kindname.type.variable.bound
compiler.misc.kindname.value
compiler.misc.incompatible.eq.lower.bounds # cannot happen?
compiler.misc.no.unique.minimal.instance.exists
compiler.misc.resume.abort # prompt for a response
compiler.misc.source.unavailable # DiagnosticSource

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.cant.access.arg.type.in.functional.desc
// key: compiler.err.report.access
// options: -XDallowLambda
interface SAM_InaccessibleArg {
void m(Foo.Bar bar);
static class Foo { private class Bar { } }
}
class CantAccessArgTypeInFunctionalDesc {
SAM_InaccessibleArg s = x-> { };
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.cant.access.inner.cls.constr
// key: compiler.misc.invalid.mref
// options: -XDallowMethodReferences
class CantAccessInnerClsConstructor {
interface SAM {
Outer m();
}
class Outer { }
static void test() {
SAM s = Outer::new;
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.cant.access.return.in.functional.desc
// options: -XDallowLambda
interface SAM_InaccessibleRet {
Foo.Bar m();
static class Foo { private class Bar { } }
}
class CantAccessReturnTypeInFunctionalDesc {
SAM_InaccessibleRet s = ()->null;
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.cant.access.thrown.in.functional.desc
// options: -XDallowLambda
interface SAM_InaccessibleThrown {
void m() throws Foo.Bar;
static class Foo { private class Bar extends Exception { } }
}
class CantAccessThrownTypesInFunctionalDesc {
SAM_InaccessibleThrown s = ()-> { };
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.inconvertible.types
// key: compiler.misc.no.conforming.assignment.exists
// key: compiler.misc.cant.apply.symbol
// key: compiler.misc.invalid.mref
// options: -XDallowMethodReferences
class CantApplySymbolFragment {
interface SAM {
void m(Integer u);
}
static void f(String s) { }
void test() {
SAM s = CantApplySymbolFragment::f;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.inconvertible.types
// key: compiler.misc.no.conforming.assignment.exists
// key: compiler.misc.arg.length.mismatch
// key: compiler.misc.inapplicable.method
// key: compiler.misc.cant.apply.symbols
// key: compiler.misc.invalid.mref
// options: -XDallowMethodReferences
class CantApplySymbolsFragment {
interface SAM {
void m(Integer u);
}
static void f() { }
static void f(String s) { }
void test() {
SAM s = CantApplySymbolsFragment::f;
}
}

View File

@ -23,7 +23,8 @@
// key: compiler.err.cant.ref.non.effectively.final.var
// key: compiler.misc.inner.cls
// options: -XDallowEffectivelyFinalInInnerClasses
// key: compiler.misc.lambda
// options: -XDallowLambda -XDallowEffectivelyFinalInInnerClasses
class CantRefNonEffectivelyFinalVar {
void test() {
@ -31,4 +32,14 @@ class CantRefNonEffectivelyFinalVar {
new Object() { int j = i; };
i = 2;
}
interface SAM {
void m();
}
void test2() {
int i = 0;
SAM s = ()-> { int j = i; };
i++;
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.misc.cant.resolve.location.args
// key: compiler.misc.location
// key: compiler.err.invalid.mref
// options: -XDallowMethodReferences
class CantResolveLocationArgsFragment {
interface SAM {
void m(Integer u);
}
void test() {
SAM s = CantResolveLocationArgsFragment::f;
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.misc.cant.resolve.location.args.params
// key: compiler.misc.location
// key: compiler.err.invalid.mref
// options: -XDallowMethodReferences
class CantResolveLocationArgsParamsFragment {
interface SAM {
void m(Integer u);
}
void test() {
SAM s = CantResolveLocationArgsParamsFragment::<String>f;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2012, 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
@ -23,6 +23,8 @@
// key: compiler.err.catch.without.try
// key: compiler.err.expected
// key: compiler.err.not.stmt
// key: compiler.err.lambda.not.supported.in.source
class CatchWithoutTry {
void m() {

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.cyclic.inference
// options: -XDallowLambda -XDallowPoly
class CyclicInference {
interface SAM<X> {
void m(X x);
}
<Z> void g(SAM<Z> sz) { }
void test() {
g(x-> {});
}
}

View File

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.cant.apply.symbol.1
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.explicit.param.do.not.conform.to.bounds
class ExplicitParamsDoNotConformToBounds {

View File

@ -22,7 +22,7 @@
*/
// key: compiler.misc.inaccessible.varargs.type
// key: compiler.err.cant.apply.symbol.1
// key: compiler.err.cant.apply.symbol
import p1.B;

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.not.a.functional.intf.1
// key: compiler.misc.incompatible.abstracts
// options: -XDallowLambda
class IncompatibleAbstracts {
interface SAM {
void m(String s);
void m(Integer i);
}
SAM s = x-> { };
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.incompatible.arg.types.in.lambda
// options: -XDallowLambda -XDallowPoly
class IncompatibleArgTypesInLambda {
interface SAM {
void m(Integer x);
}
SAM s = (String x)-> {};
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.types.incompatible.diff.ret
// key: compiler.err.prob.found.req
// key: compiler.misc.incompatible.descs.in.functional.intf
// key: compiler.misc.descriptor
// key: compiler.misc.descriptor.throws
// options: -XDallowLambda
class IncompatibleDescsInFunctionalIntf {
interface A {
Integer m(String i) throws Exception;
}
interface B {
String m(String i);
}
interface SAM extends A,B { }
SAM s = x-> { };
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
//key: compiler.err.cant.apply.symbol
//key: compiler.misc.incompatible.eq.upper.bounds
import java.util.List;
class IncompatibleEqUpperBounds {
<S, T extends List<S>> void m(List<? super S> s1, T s2) { }
void test(List<Integer> li, List<String> ls) {
m(li, ls);
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.inconvertible.types
// key: compiler.misc.incompatible.ret.type.in.lambda
// options: -XDallowLambda -XDallowPoly
class IncompatibleRetTypeInLambda {
interface SAM {
Integer m();
}
SAM s = ()-> "";
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.inconvertible.types
// key: compiler.misc.incompatible.ret.type.in.mref
// options: -XDallowMethodReferences -XDallowPoly
class IncompatibleRetTypeInMref {
interface SAM {
Integer m();
}
static String f() { }
SAM s = IncompatibleRetTypeInMref::f;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.incompatible.thrown.types.in.lambda
// options: -XDallowLambda
class IncompatibleThrownTypesInLambda {
interface SAM {
void m();
}
SAM s = ()-> { throw new Exception(); };
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.incompatible.thrown.types.in.mref
// options: -XDallowMethodReferences
class IncompatibleThrownTypesInMref {
interface SAM {
void m();
}
static void f() throws Exception { }
SAM s = IncompatibleThrownTypesInMref::f;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.prob.found.req
// key: compiler.misc.incompatible.type.in.conditional
// key: compiler.misc.inconvertible.types
// options: -XDallowPoly
class IncompatibleTypesInConditional {
interface A { }
interface B { }
B b = true ? (A)null : (B)null;
}

View File

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.cant.apply.symbol.1
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.infer.arg.length.mismatch
class InferArgsLengthMismatch {

View File

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.cant.apply.symbol.1
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.inconvertible.types
// key: compiler.misc.infer.no.conforming.assignment.exists

View File

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.cant.apply.symbol.1
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.infer.varargs.argument.mismatch
// key: compiler.misc.inconvertible.types

View File

@ -21,7 +21,7 @@
* questions.
*/
// key: compiler.err.cant.apply.symbol.1
// key: compiler.err.cant.apply.symbol
// key: compiler.misc.inferred.do.not.conform.to.eq.bounds
import java.util.*;

Some files were not shown because too many files have changed in this diff Show More