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

changeset 1510
7873d37f5b37
parent 1479
38d3d1027f5a
child 1519
97bd5e7151bc
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Jan 21 11:16:28 2013 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Jan 21 20:13:56 2013 +0000
     1.3 @@ -66,6 +66,9 @@
     1.4      Log log;
     1.5      JCDiagnostic.Factory diags;
     1.6  
     1.7 +    /** Should we inject return-type constraints earlier? */
     1.8 +    boolean allowEarlyReturnConstraints;
     1.9 +
    1.10      public static Infer instance(Context context) {
    1.11          Infer instance = context.get(inferKey);
    1.12          if (instance == null)
    1.13 @@ -83,6 +86,7 @@
    1.14          chk = Check.instance(context);
    1.15          diags = JCDiagnostic.Factory.instance(context);
    1.16          inferenceException = new InferenceException(diags);
    1.17 +        allowEarlyReturnConstraints = Source.instance(context).allowEarlyReturnConstraints();
    1.18      }
    1.19  
    1.20     /**
    1.21 @@ -188,19 +192,6 @@
    1.22              MethodType mtype,
    1.23              Attr.ResultInfo resultInfo,
    1.24              Warner warn) throws InferenceException {
    1.25 -        Type to = resultInfo.pt;
    1.26 -        if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
    1.27 -            to = mtype.getReturnType().isPrimitiveOrVoid() ?
    1.28 -                    mtype.getReturnType() : syms.objectType;
    1.29 -        }
    1.30 -        Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
    1.31 -        if (!types.isSubtype(qtype1,
    1.32 -                qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) {
    1.33 -            throw inferenceException
    1.34 -                    .setMessage("infer.no.conforming.instance.exists",
    1.35 -                    inferenceContext.restvars(), mtype.getReturnType(), to);
    1.36 -        }
    1.37 -
    1.38          while (true) {
    1.39              boolean stuck = true;
    1.40              for (Type t : inferenceContext.undetvars) {
    1.41 @@ -283,6 +274,11 @@
    1.42          try {
    1.43              methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
    1.44  
    1.45 +            if (resultInfo != null && allowEarlyReturnConstraints &&
    1.46 +                    !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
    1.47 +                generateReturnConstraints(mt, inferenceContext, resultInfo);
    1.48 +            }
    1.49 +
    1.50              deferredAttrContext.complete();
    1.51  
    1.52              // minimize as yet undetermined type variables
    1.53 @@ -298,6 +294,9 @@
    1.54  
    1.55              if (!restvars.isEmpty()) {
    1.56                  if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
    1.57 +                    if (!allowEarlyReturnConstraints) {
    1.58 +                        generateReturnConstraints(mt, inferenceContext, resultInfo);
    1.59 +                    }
    1.60                      instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
    1.61                      checkWithinBounds(inferenceContext, warn);
    1.62                      mt = (MethodType)inferenceContext.asInstType(mt, types);
    1.63 @@ -313,6 +312,23 @@
    1.64              inferenceContext.notifyChange(types);
    1.65          }
    1.66      }
    1.67 +    //where
    1.68 +        void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) {
    1.69 +            if (resultInfo != null) {
    1.70 +                Type to = resultInfo.pt;
    1.71 +                if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
    1.72 +                    to = mt.getReturnType().isPrimitiveOrVoid() ?
    1.73 +                            mt.getReturnType() : syms.objectType;
    1.74 +                }
    1.75 +                Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types);
    1.76 +                if (!types.isSubtype(qtype1,
    1.77 +                        qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) {
    1.78 +                    throw inferenceException
    1.79 +                            .setMessage("infer.no.conforming.instance.exists",
    1.80 +                            inferenceContext.restvars(), mt.getReturnType(), to);
    1.81 +                }
    1.82 +            }
    1.83 +        }
    1.84  
    1.85      /** check that type parameters are within their bounds.
    1.86       */
    1.87 @@ -461,52 +477,40 @@
    1.88              Type formalInterface = funcInterface.tsym.type;
    1.89              InferenceContext funcInterfaceContext =
    1.90                      new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
    1.91 -            if (paramTypes != null) {
    1.92 -                //get constraints from explicit params (this is done by
    1.93 -                //checking that explicit param types are equal to the ones
    1.94 -                //in the functional interface descriptors)
    1.95 -                List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
    1.96 -                if (descParameterTypes.size() != paramTypes.size()) {
    1.97 -                    checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
    1.98 +            Assert.check(paramTypes != null);
    1.99 +            //get constraints from explicit params (this is done by
   1.100 +            //checking that explicit param types are equal to the ones
   1.101 +            //in the functional interface descriptors)
   1.102 +            List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
   1.103 +            if (descParameterTypes.size() != paramTypes.size()) {
   1.104 +                checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
   1.105 +                return types.createErrorType(funcInterface);
   1.106 +            }
   1.107 +            for (Type p : descParameterTypes) {
   1.108 +                if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
   1.109 +                    checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   1.110                      return types.createErrorType(funcInterface);
   1.111                  }
   1.112 -                for (Type p : descParameterTypes) {
   1.113 -                    if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
   1.114 -                        checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   1.115 -                        return types.createErrorType(funcInterface);
   1.116 -                    }
   1.117 -                    paramTypes = paramTypes.tail;
   1.118 +                paramTypes = paramTypes.tail;
   1.119 +            }
   1.120 +            List<Type> actualTypeargs = funcInterface.getTypeArguments();
   1.121 +            for (Type t : funcInterfaceContext.undetvars) {
   1.122 +                UndetVar uv = (UndetVar)t;
   1.123 +                minimizeInst(uv, types.noWarnings);
   1.124 +                if (uv.inst == null &&
   1.125 +                        Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
   1.126 +                    maximizeInst(uv, types.noWarnings);
   1.127                  }
   1.128 -                for (Type t : funcInterfaceContext.undetvars) {
   1.129 -                    UndetVar uv = (UndetVar)t;
   1.130 -                    minimizeInst(uv, types.noWarnings);
   1.131 -                    if (uv.inst == null &&
   1.132 -                            Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
   1.133 -                        maximizeInst(uv, types.noWarnings);
   1.134 -                    }
   1.135 -                }
   1.136 -
   1.137 -                formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
   1.138 -            }
   1.139 -            ListBuffer<Type> typeargs = ListBuffer.lb();
   1.140 -            List<Type> actualTypeargs = funcInterface.getTypeArguments();
   1.141 -            //for remaining uninferred type-vars in the functional interface type,
   1.142 -            //simply replace the wildcards with its bound
   1.143 -            for (Type t : formalInterface.getTypeArguments()) {
   1.144 -                if (actualTypeargs.head.hasTag(WILDCARD)) {
   1.145 -                    WildcardType wt = (WildcardType)actualTypeargs.head;
   1.146 -                    typeargs.append(wt.type);
   1.147 -                } else {
   1.148 -                    typeargs.append(actualTypeargs.head);
   1.149 +                if (uv.inst == null) {
   1.150 +                    uv.inst = actualTypeargs.head;
   1.151                  }
   1.152                  actualTypeargs = actualTypeargs.tail;
   1.153              }
   1.154 -            Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList());
   1.155 +            Type owntype = funcInterfaceContext.asInstType(formalInterface, types);
   1.156              if (!chk.checkValidGenericType(owntype)) {
   1.157                  //if the inferred functional interface type is not well-formed,
   1.158                  //or if it's not a subtype of the original target, issue an error
   1.159                  checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   1.160 -                return types.createErrorType(funcInterface);
   1.161              }
   1.162              return owntype;
   1.163          }

mercurial