src/share/classes/com/sun/tools/javac/comp/Attr.java

changeset 1510
7873d37f5b37
parent 1492
df694c775e8a
child 1513
cf84b07a82db
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jan 21 11:16:28 2013 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Jan 21 20:13:56 2013 +0000
     1.3 @@ -48,6 +48,7 @@
     1.4  import com.sun.tools.javac.jvm.Target;
     1.5  import com.sun.tools.javac.tree.*;
     1.6  import com.sun.tools.javac.tree.JCTree.*;
     1.7 +import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
     1.8  import com.sun.tools.javac.util.*;
     1.9  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    1.10  import com.sun.tools.javac.util.List;
    1.11 @@ -1376,18 +1377,19 @@
    1.12      public void visitConditional(JCConditional tree) {
    1.13          Type condtype = attribExpr(tree.cond, env, syms.booleanType);
    1.14  
    1.15 -        boolean standaloneConditional = !allowPoly ||
    1.16 +        tree.polyKind = (!allowPoly ||
    1.17                  pt().hasTag(NONE) && pt() != Type.recoveryType ||
    1.18 -                isBooleanOrNumeric(env, tree);
    1.19 -
    1.20 -        if (!standaloneConditional && resultInfo.pt.hasTag(VOID)) {
    1.21 +                isBooleanOrNumeric(env, tree)) ?
    1.22 +                PolyKind.STANDALONE : PolyKind.POLY;
    1.23 +
    1.24 +        if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
    1.25              //cannot get here (i.e. it means we are returning from void method - which is already an error)
    1.26              resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void"));
    1.27              result = tree.type = types.createErrorType(resultInfo.pt);
    1.28              return;
    1.29          }
    1.30  
    1.31 -        ResultInfo condInfo = standaloneConditional ?
    1.32 +        ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
    1.33                  unknownExprInfo :
    1.34                  resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
    1.35                      //this will use enclosing check context to check compatibility of
    1.36 @@ -1402,7 +1404,7 @@
    1.37          Type truetype = attribTree(tree.truepart, env, condInfo);
    1.38          Type falsetype = attribTree(tree.falsepart, env, condInfo);
    1.39  
    1.40 -        Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt();
    1.41 +        Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt();
    1.42          if (condtype.constValue() != null &&
    1.43                  truetype.constValue() != null &&
    1.44                  falsetype.constValue() != null &&
    1.45 @@ -1424,12 +1426,30 @@
    1.46                      JCConditional condTree = (JCConditional)tree;
    1.47                      return isBooleanOrNumeric(env, condTree.truepart) &&
    1.48                              isBooleanOrNumeric(env, condTree.falsepart);
    1.49 +                case APPLY:
    1.50 +                    JCMethodInvocation speculativeMethodTree =
    1.51 +                            (JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo);
    1.52 +                    Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType();
    1.53 +                    return types.unboxedTypeOrType(owntype).isPrimitive();
    1.54 +                case NEWCLASS:
    1.55 +                    JCExpression className =
    1.56 +                            removeClassParams.translate(((JCNewClass)tree).clazz);
    1.57 +                    JCExpression speculativeNewClassTree =
    1.58 +                            (JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo);
    1.59 +                    return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive();
    1.60                  default:
    1.61                      Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type;
    1.62                      speculativeType = types.unboxedTypeOrType(speculativeType);
    1.63                      return speculativeType.isPrimitive();
    1.64              }
    1.65          }
    1.66 +        //where
    1.67 +            TreeTranslator removeClassParams = new TreeTranslator() {
    1.68 +                @Override
    1.69 +                public void visitTypeApply(JCTypeApply tree) {
    1.70 +                    result = translate(tree.clazz);
    1.71 +                }
    1.72 +            };
    1.73  
    1.74          /** Compute the type of a conditional expression, after
    1.75           *  checking that it exists.  See JLS 15.25. Does not take into
    1.76 @@ -2173,17 +2193,18 @@
    1.77          boolean needsRecovery =
    1.78                  resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
    1.79          try {
    1.80 +            Type target = pt();
    1.81              List<Type> explicitParamTypes = null;
    1.82 -            if (TreeInfo.isExplicitLambda(that)) {
    1.83 +            if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) {
    1.84                  //attribute lambda parameters
    1.85                  attribStats(that.params, localEnv);
    1.86                  explicitParamTypes = TreeInfo.types(that.params);
    1.87 +                target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext);
    1.88              }
    1.89  
    1.90 -            Type target;
    1.91              Type lambdaType;
    1.92              if (pt() != Type.recoveryType) {
    1.93 -                target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext);
    1.94 +                target = checkIntersectionTarget(that, target, resultInfo.checkContext);
    1.95                  lambdaType = types.findDescriptorType(target);
    1.96                  chk.checkFunctionalInterface(that, target);
    1.97              } else {
    1.98 @@ -2191,6 +2212,8 @@
    1.99                  lambdaType = fallbackDescriptorType(that);
   1.100              }
   1.101  
   1.102 +            setFunctionalInfo(that, pt(), lambdaType, resultInfo.checkContext.inferenceContext());
   1.103 +
   1.104              if (lambdaType.hasTag(FORALL)) {
   1.105                  //lambda expression target desc cannot be a generic method
   1.106                  resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target",
   1.107 @@ -2199,7 +2222,7 @@
   1.108                  return;
   1.109              }
   1.110  
   1.111 -            if (!TreeInfo.isExplicitLambda(that)) {
   1.112 +            if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) {
   1.113                  //add param type info in the AST
   1.114                  List<Type> actuals = lambdaType.getParameterTypes();
   1.115                  List<JCVariableDecl> params = that.params;
   1.116 @@ -2282,8 +2305,7 @@
   1.117          }
   1.118      }
   1.119  
   1.120 -    private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) {
   1.121 -        Type pt = resultInfo.pt;
   1.122 +    private Type checkIntersectionTarget(DiagnosticPosition pos, Type pt, CheckContext checkContext) {
   1.123          if (pt != Type.recoveryType && pt.isCompound()) {
   1.124              IntersectionClassType ict = (IntersectionClassType)pt;
   1.125              List<Type> bounds = ict.allInterfaces ?
   1.126 @@ -2292,7 +2314,7 @@
   1.127              types.findDescriptorType(bounds.head); //propagate exception outwards!
   1.128              for (Type bound : bounds.tail) {
   1.129                  if (!types.isMarkerInterface(bound)) {
   1.130 -                    resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound));
   1.131 +                    checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound));
   1.132                  }
   1.133              }
   1.134              //for now (translation doesn't support intersection types)
   1.135 @@ -2355,9 +2377,9 @@
   1.136              @Override
   1.137              public boolean compatible(Type found, Type req, Warner warn) {
   1.138                  //return type must be compatible in both current context and assignment context
   1.139 -                return types.isAssignable(found, inferenceContext().asFree(req, types), warn) &&
   1.140 -                        super.compatible(found, req, warn);
   1.141 +                return chk.basicHandler.compatible(found, inferenceContext().asFree(req, types), warn);
   1.142              }
   1.143 +
   1.144              @Override
   1.145              public void report(DiagnosticPosition pos, JCDiagnostic details) {
   1.146                  enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details));
   1.147 @@ -2473,7 +2495,7 @@
   1.148              Type target;
   1.149              Type desc;
   1.150              if (pt() != Type.recoveryType) {
   1.151 -                target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext);
   1.152 +                target = checkIntersectionTarget(that, pt(), resultInfo.checkContext);
   1.153                  desc = types.findDescriptorType(target);
   1.154                  chk.checkFunctionalInterface(that, target);
   1.155              } else {
   1.156 @@ -2481,12 +2503,11 @@
   1.157                  desc = fallbackDescriptorType(that);
   1.158              }
   1.159  
   1.160 +            setFunctionalInfo(that, pt(), desc, resultInfo.checkContext.inferenceContext());
   1.161              List<Type> argtypes = desc.getParameterTypes();
   1.162  
   1.163 -            boolean allowBoxing =
   1.164 -                    resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired();
   1.165              Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
   1.166 -                    that.expr.type, that.name, argtypes, typeargtypes, allowBoxing);
   1.167 +                    that.expr.type, that.name, argtypes, typeargtypes, true);
   1.168  
   1.169              Symbol refSym = refResult.fst;
   1.170              Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
   1.171 @@ -2635,6 +2656,34 @@
   1.172          }
   1.173      }
   1.174  
   1.175 +    /**
   1.176 +     * Set functional type info on the underlying AST. Note: as the target descriptor
   1.177 +     * might contain inference variables, we might need to register an hook in the
   1.178 +     * current inference context.
   1.179 +     */
   1.180 +    private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, final Type descriptorType, InferenceContext inferenceContext) {
   1.181 +        if (inferenceContext.free(descriptorType)) {
   1.182 +            inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() {
   1.183 +                public void typesInferred(InferenceContext inferenceContext) {
   1.184 +                    setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType, types), inferenceContext);
   1.185 +                }
   1.186 +            });
   1.187 +        } else {
   1.188 +            ListBuffer<TypeSymbol> targets = ListBuffer.lb();
   1.189 +            if (pt.hasTag(CLASS)) {
   1.190 +                if (pt.isCompound()) {
   1.191 +                    for (Type t : ((IntersectionClassType)pt()).interfaces_field) {
   1.192 +                        targets.append(t.tsym);
   1.193 +                    }
   1.194 +                } else {
   1.195 +                    targets.append(pt.tsym);
   1.196 +                }
   1.197 +            }
   1.198 +            fExpr.targets = targets.toList();
   1.199 +            fExpr.descriptorType = descriptorType;
   1.200 +        }
   1.201 +    }
   1.202 +
   1.203      public void visitParens(JCParens tree) {
   1.204          Type owntype = attribTree(tree.expr, env, resultInfo);
   1.205          result = check(tree, owntype, pkind(), resultInfo);
   1.206 @@ -4078,11 +4127,28 @@
   1.207          }
   1.208  
   1.209          @Override
   1.210 +        public void visitLambda(JCLambda that) {
   1.211 +            super.visitLambda(that);
   1.212 +            if (that.descriptorType == null) {
   1.213 +                that.descriptorType = syms.unknownType;
   1.214 +            }
   1.215 +            if (that.targets == null) {
   1.216 +                that.targets = List.nil();
   1.217 +            }
   1.218 +        }
   1.219 +
   1.220 +        @Override
   1.221          public void visitReference(JCMemberReference that) {
   1.222              super.visitReference(that);
   1.223              if (that.sym == null) {
   1.224                  that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol);
   1.225              }
   1.226 +            if (that.descriptorType == null) {
   1.227 +                that.descriptorType = syms.unknownType;
   1.228 +            }
   1.229 +            if (that.targets == null) {
   1.230 +                that.targets = List.nil();
   1.231 +            }
   1.232          }
   1.233      }
   1.234      // </editor-fold>

mercurial