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

changeset 1570
f91144b7da75
parent 1519
97bd5e7151bc
child 1550
1df20330f6bd
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Jan 21 01:27:42 2013 -0500
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Feb 04 18:08:53 2013 -0500
     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,25 @@
    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 +                Warner retWarn = new Warner();
    1.77 +                if (!resultInfo.checkContext.compatible(qtype1, qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to, retWarn) ||
    1.78 +                        //unchecked conversion is not allowed
    1.79 +                        retWarn.hasLint(Lint.LintCategory.UNCHECKED)) {
    1.80 +                    throw inferenceException
    1.81 +                            .setMessage("infer.no.conforming.instance.exists",
    1.82 +                            inferenceContext.restvars(), mt.getReturnType(), to);
    1.83 +                }
    1.84 +            }
    1.85 +        }
    1.86  
    1.87      /** check that type parameters are within their bounds.
    1.88       */
    1.89 @@ -461,52 +479,40 @@
    1.90              Type formalInterface = funcInterface.tsym.type;
    1.91              InferenceContext funcInterfaceContext =
    1.92                      new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
    1.93 -            if (paramTypes != null) {
    1.94 -                //get constraints from explicit params (this is done by
    1.95 -                //checking that explicit param types are equal to the ones
    1.96 -                //in the functional interface descriptors)
    1.97 -                List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
    1.98 -                if (descParameterTypes.size() != paramTypes.size()) {
    1.99 -                    checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
   1.100 +            Assert.check(paramTypes != null);
   1.101 +            //get constraints from explicit params (this is done by
   1.102 +            //checking that explicit param types are equal to the ones
   1.103 +            //in the functional interface descriptors)
   1.104 +            List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
   1.105 +            if (descParameterTypes.size() != paramTypes.size()) {
   1.106 +                checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
   1.107 +                return types.createErrorType(funcInterface);
   1.108 +            }
   1.109 +            for (Type p : descParameterTypes) {
   1.110 +                if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
   1.111 +                    checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   1.112                      return types.createErrorType(funcInterface);
   1.113                  }
   1.114 -                for (Type p : descParameterTypes) {
   1.115 -                    if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
   1.116 -                        checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   1.117 -                        return types.createErrorType(funcInterface);
   1.118 -                    }
   1.119 -                    paramTypes = paramTypes.tail;
   1.120 +                paramTypes = paramTypes.tail;
   1.121 +            }
   1.122 +            List<Type> actualTypeargs = funcInterface.getTypeArguments();
   1.123 +            for (Type t : funcInterfaceContext.undetvars) {
   1.124 +                UndetVar uv = (UndetVar)t;
   1.125 +                minimizeInst(uv, types.noWarnings);
   1.126 +                if (uv.inst == null &&
   1.127 +                        Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
   1.128 +                    maximizeInst(uv, types.noWarnings);
   1.129                  }
   1.130 -                for (Type t : funcInterfaceContext.undetvars) {
   1.131 -                    UndetVar uv = (UndetVar)t;
   1.132 -                    minimizeInst(uv, types.noWarnings);
   1.133 -                    if (uv.inst == null &&
   1.134 -                            Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
   1.135 -                        maximizeInst(uv, types.noWarnings);
   1.136 -                    }
   1.137 -                }
   1.138 -
   1.139 -                formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
   1.140 -            }
   1.141 -            ListBuffer<Type> typeargs = ListBuffer.lb();
   1.142 -            List<Type> actualTypeargs = funcInterface.getTypeArguments();
   1.143 -            //for remaining uninferred type-vars in the functional interface type,
   1.144 -            //simply replace the wildcards with its bound
   1.145 -            for (Type t : formalInterface.getTypeArguments()) {
   1.146 -                if (actualTypeargs.head.hasTag(WILDCARD)) {
   1.147 -                    WildcardType wt = (WildcardType)actualTypeargs.head;
   1.148 -                    typeargs.append(wt.type);
   1.149 -                } else {
   1.150 -                    typeargs.append(actualTypeargs.head);
   1.151 +                if (uv.inst == null) {
   1.152 +                    uv.inst = actualTypeargs.head;
   1.153                  }
   1.154                  actualTypeargs = actualTypeargs.tail;
   1.155              }
   1.156 -            Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList());
   1.157 +            Type owntype = funcInterfaceContext.asInstType(formalInterface, types);
   1.158              if (!chk.checkValidGenericType(owntype)) {
   1.159                  //if the inferred functional interface type is not well-formed,
   1.160                  //or if it's not a subtype of the original target, issue an error
   1.161                  checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   1.162 -                return types.createErrorType(funcInterface);
   1.163              }
   1.164              return owntype;
   1.165          }

mercurial