Merge
This commit is contained in:
commit
babd792880
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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">
|
||||
|
@ -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
@ -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() + "]";
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -177,7 +177,7 @@ public class Tokens {
|
||||
FALSE("false", Tag.NAMED),
|
||||
NULL("null", Tag.NAMED),
|
||||
ARROW("->"),
|
||||
HASH("#"),
|
||||
COLCOL("::"),
|
||||
LPAREN("("),
|
||||
RPAREN(")"),
|
||||
LBRACE("{"),
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -27,6 +27,7 @@
|
||||
* @summary Conditional operator applies assignment conversion
|
||||
* @author Tim Hanson, BEA
|
||||
*
|
||||
* @compile -XDallowPoly Conditional.java
|
||||
* @compile/fail Conditional.java
|
||||
*/
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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-> { };
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 = ()-> { };
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -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-> {});
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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-> { };
|
||||
}
|
@ -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)-> {};
|
||||
}
|
@ -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-> { };
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 = ()-> "";
|
||||
}
|
@ -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;
|
||||
}
|
@ -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(); };
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user