src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
Print this page
@@ -23,10 +23,11 @@
* questions.
*/
package com.sun.tools.javac.comp;
+import com.sun.source.tree.*;
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -74,10 +75,11 @@
final Symtab syms;
final TreeMaker make;
final Types types;
final Flow flow;
final Names names;
+ final Annotate annotate;
public static DeferredAttr instance(Context context) {
DeferredAttr instance = context.get(deferredAttrKey);
if (instance == null)
instance = new DeferredAttr(context);
@@ -97,10 +99,11 @@
make = TreeMaker.instance(context);
types = Types.instance(context);
flow = Flow.instance(context);
names = Names.instance(context);
stuckTree = make.Ident(names.empty).setType(Type.stuckType);
+ annotate = Annotate.instance(context);
emptyDeferredAttrContext =
new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
@Override
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) {
Assert.error("Empty deferred context!");
@@ -130,16 +133,23 @@
public JCExpression tree;
Env<AttrContext> env;
AttrMode mode;
SpeculativeCache speculativeCache;
+ final JCLambda currLambda;
+ final Annotate.PositionCreator creator;
- DeferredType(JCExpression tree, Env<AttrContext> env) {
+ DeferredType(JCExpression tree,
+ Env<AttrContext> env,
+ JCLambda currLambda,
+ Annotate.PositionCreator creator) {
super(null, noAnnotations);
this.tree = tree;
this.env = attr.copyEnv(env);
this.speculativeCache = new SpeculativeCache();
+ this.currLambda = currLambda;
+ this.creator = creator;
}
@Override
public DeferredType annotatedType(List<Attribute.TypeCompound> typeAnnotations) {
throw new AssertionError("Cannot annotate a deferred type");
@@ -275,16 +285,20 @@
switch (deferredAttrContext.mode) {
case SPECULATIVE:
//Note: if a symbol is imported twice we might do two identical
//speculative rounds...
Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
- JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
+ JCTree speculativeTree = attribSpeculative(dt.tree, dt.env,
+ resultInfo,
+ dt.currLambda,
+ dt.creator);
dt.speculativeCache.put(speculativeTree, resultInfo);
return speculativeTree.type;
case CHECK:
Assert.check(dt.mode != null);
- return attr.attribTree(dt.tree, dt.env, resultInfo);
+ return attr.attribTree(dt.tree, dt.env, dt.currLambda,
+ resultInfo, false);
}
Assert.error();
return null;
}
};
@@ -357,11 +371,15 @@
* 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 attribSpeculative(JCTree tree,
+ Env<AttrContext> env,
+ ResultInfo resultInfo,
+ JCLambda currLambda,
+ Annotate.PositionCreator creator) {
final JCTree newTree = new TreeCopier<>(make).copy(tree);
Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared()));
speculativeEnv.info.scope.owner = env.info.scope.owner;
Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
new Log.DeferredDiagnosticHandler(log, new Filter<JCDiagnostic>() {
@@ -382,11 +400,16 @@
posScanner.scan(newTree);
return posScanner.found;
}
});
try {
- attr.attribTree(newTree, speculativeEnv, resultInfo);
+ attr.attribTree(newTree, speculativeEnv, currLambda,
+ resultInfo, true);
+ annotate.typeAnnotateExprLater(newTree, speculativeEnv,
+ speculativeEnv.info.scope.owner,
+ newTree.pos(), currLambda,
+ creator);
unenterScanner.scan(newTree);
return newTree;
} finally {
unenterScanner.scan(newTree);
log.popDiagnosticHandler(deferredDiagnosticHandler);
@@ -596,15 +619,17 @@
class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
ResultInfo resultInfo;
InferenceContext inferenceContext;
Env<AttrContext> env;
+ JCLambda currLambda;
public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
this.resultInfo = resultInfo;
this.inferenceContext = deferredAttrContext.inferenceContext;
this.env = dt.env;
+ this.currLambda = dt.currLambda;
dt.tree.accept(this);
dt.speculativeCache.put(stuckTree, resultInfo);
return Type.noType;
}
@@ -679,11 +704,15 @@
while (tmpParams.nonEmpty()) {
tmpParams.head.vartype = make.at(tmpParams.head).Type(syms.errType);
tmpParams = tmpParams.tail;
}
- attr.attribStats(newTree.params, localEnv);
+ int i = 0;
+ for (List<JCVariableDecl> l = newTree.params;
+ l.nonEmpty(); l = l.tail, i++) {
+ attr.attribStat(l.head, tree, localEnv, true);
+ }
/* set pt to Type.noType to avoid generating any bound
* which may happen if lambda's return type is an
* inference variable
*/
@@ -700,11 +729,11 @@
* and the reachability of some statements depends
* on constant values, for example:
*
* while (true) {...}
*/
- attr.attribStats(body.stats, localEnv);
+ attr.attribStats(body.stats, tree, localEnv, true);
attr.preFlow(newTree);
/* make an aliveness / reachability analysis of the lambda
* to determine if it can complete normally
*/
@@ -739,12 +768,16 @@
types.findDescriptorType(pt);
} catch (Types.FunctionDescriptorLookupError ex) {
checkContext.report(null, ex.getDiagnostic());
}
Env<AttrContext> localEnv = env.dup(tree);
- JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
- attr.memberReferenceQualifierResult(tree));
+ JCExpression exprTree =
+ (JCExpression)attribSpeculative(tree.getQualifierExpression(),
+ localEnv,
+ attr.memberReferenceQualifierResult(tree),
+ currLambda,
+ annotate.methodRefCreator(tree.pos));
ListBuffer<Type> argtypes = new ListBuffer<>();
for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
argtypes.append(Type.noType);
}
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
@@ -1082,12 +1115,14 @@
}
/**
* Does the argument expression {@code expr} need speculative type-checking?
*/
- boolean isDeferred(Env<AttrContext> env, JCExpression expr) {
- DeferredChecker dc = new DeferredChecker(env);
+ boolean isDeferred(Env<AttrContext> env,
+ JCExpression expr,
+ JCLambda currLambda) {
+ DeferredChecker dc = new DeferredChecker(env, currLambda);
dc.scan(expr);
return dc.result.isPoly();
}
/**
@@ -1144,16 +1179,19 @@
* Tree scanner used for checking as to whether an argument expression
* requires speculative attribution
*/
final class DeferredChecker extends FilterScanner {
+ private final JCLambda currLambda;
Env<AttrContext> env;
ArgumentExpressionKind result;
- public DeferredChecker(Env<AttrContext> env) {
+ public DeferredChecker(Env<AttrContext> env,
+ JCLambda currLambda) {
super(deferredCheckerTags);
this.env = env;
+ this.currLambda = currLambda;
}
@Override
public void visitLambda(JCLambda tree) {
//a lambda is always a poly expression
@@ -1162,12 +1200,16 @@
@Override
public void visitReference(JCMemberReference tree) {
//perform arity-based check
Env<AttrContext> localEnv = env.dup(tree);
- JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
- attr.memberReferenceQualifierResult(tree));
+ JCExpression exprTree =
+ (JCExpression)attribSpeculative(tree.getQualifierExpression(),
+ localEnv,
+ attr.memberReferenceQualifierResult(tree),
+ currLambda,
+ annotate.methodRefCreator(tree.pos));
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
mref2.expr = exprTree;
Symbol res =
rs.getMemberReference(tree, localEnv, mref2,
exprTree.type, tree.name);
@@ -1230,11 +1272,12 @@
result = ArgumentExpressionKind.POLY;
return;
}
Type site = rec != null ?
- attribSpeculative(rec, env, attr.unknownTypeExprInfo).type :
+ attribSpeculative(rec, env, attr.unknownTypeExprInfo,
+ currLambda, annotate.noCreator).type :
env.enclClass.sym.type;
while (site.hasTag(TYPEVAR)) {
site = site.getUpperBound();
}