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

changeset 1348
573ceb23beeb
parent 1347
1408af4cd8b0
child 1357
c75be5bc5283
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Oct 04 13:04:53 2012 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Oct 05 14:35:24 2012 +0100
     1.3 @@ -274,7 +274,7 @@
     1.4                                    Resolve.MethodResolutionContext resolveContext,
     1.5                                    Warner warn) throws InferenceException {
     1.6          //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
     1.7 -        final InferenceContext inferenceContext = new InferenceContext(tvars, this);
     1.8 +        final InferenceContext inferenceContext = new InferenceContext(tvars, this, true);
     1.9          inferenceException.clear();
    1.10  
    1.11          try {
    1.12 @@ -467,6 +467,75 @@
    1.13          throw bk.setMessage(inferenceException, uv);
    1.14      }
    1.15  
    1.16 +    // <editor-fold desc="functional interface instantiation">
    1.17 +    /**
    1.18 +     * This method is used to infer a suitable target functional interface in case
    1.19 +     * the original parameterized interface contains wildcards. An inference process
    1.20 +     * is applied so that wildcard bounds, as well as explicit lambda/method ref parameters
    1.21 +     * (where applicable) are used to constraint the solution.
    1.22 +     */
    1.23 +    public Type instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface,
    1.24 +            List<Type> paramTypes, Check.CheckContext checkContext) {
    1.25 +        if (types.capture(funcInterface) == funcInterface) {
    1.26 +            //if capture doesn't change the type then return the target unchanged
    1.27 +            //(this means the target contains no wildcards!)
    1.28 +            return funcInterface;
    1.29 +        } else {
    1.30 +            Type formalInterface = funcInterface.tsym.type;
    1.31 +            InferenceContext funcInterfaceContext =
    1.32 +                    new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
    1.33 +            if (paramTypes != null) {
    1.34 +                //get constraints from explicit params (this is done by
    1.35 +                //checking that explicit param types are equal to the ones
    1.36 +                //in the functional interface descriptors)
    1.37 +                List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
    1.38 +                if (descParameterTypes.size() != paramTypes.size()) {
    1.39 +                    checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
    1.40 +                    return types.createErrorType(funcInterface);
    1.41 +                }
    1.42 +                for (Type p : descParameterTypes) {
    1.43 +                    if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
    1.44 +                        checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
    1.45 +                        return types.createErrorType(funcInterface);
    1.46 +                    }
    1.47 +                    paramTypes = paramTypes.tail;
    1.48 +                }
    1.49 +                for (Type t : funcInterfaceContext.undetvars) {
    1.50 +                    UndetVar uv = (UndetVar)t;
    1.51 +                    minimizeInst(uv, Warner.noWarnings);
    1.52 +                    if (uv.inst == null &&
    1.53 +                            Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
    1.54 +                        maximizeInst(uv, Warner.noWarnings);
    1.55 +                    }
    1.56 +                }
    1.57 +
    1.58 +                formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
    1.59 +            }
    1.60 +            ListBuffer<Type> typeargs = ListBuffer.lb();
    1.61 +            List<Type> actualTypeargs = funcInterface.getTypeArguments();
    1.62 +            //for remaining uninferred type-vars in the functional interface type,
    1.63 +            //simply replace the wildcards with its bound
    1.64 +            for (Type t : formalInterface.getTypeArguments()) {
    1.65 +                if (actualTypeargs.head.tag == WILDCARD) {
    1.66 +                    WildcardType wt = (WildcardType)actualTypeargs.head;
    1.67 +                    typeargs.append(wt.type);
    1.68 +                } else {
    1.69 +                    typeargs.append(actualTypeargs.head);
    1.70 +                }
    1.71 +                actualTypeargs = actualTypeargs.tail;
    1.72 +            }
    1.73 +            Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList());
    1.74 +            if (!chk.checkValidGenericType(owntype)) {
    1.75 +                //if the inferred functional interface type is not well-formed,
    1.76 +                //or if it's not a subtype of the original target, issue an error
    1.77 +                checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
    1.78 +                return types.createErrorType(funcInterface);
    1.79 +            }
    1.80 +            return owntype;
    1.81 +        }
    1.82 +    }
    1.83 +    // </editor-fold>
    1.84 +
    1.85      /**
    1.86       * Compute a synthetic method type corresponding to the requested polymorphic
    1.87       * method signature. The target return type is computed from the immediately
    1.88 @@ -536,9 +605,17 @@
    1.89       * Mapping that turns inference variables into undet vars
    1.90       * (used by inference context)
    1.91       */
    1.92 -    Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
    1.93 +    class FromTypeVarFun extends Mapping {
    1.94 +
    1.95 +        boolean includeBounds;
    1.96 +
    1.97 +        FromTypeVarFun(boolean includeBounds) {
    1.98 +            super("fromTypeVarFunWithBounds");
    1.99 +            this.includeBounds = includeBounds;
   1.100 +        }
   1.101 +
   1.102          public Type apply(Type t) {
   1.103 -            if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types);
   1.104 +            if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types, includeBounds);
   1.105              else return t.map(this);
   1.106          }
   1.107      };
   1.108 @@ -573,8 +650,8 @@
   1.109  
   1.110          List<FreeTypeListener> freetypeListeners = List.nil();
   1.111  
   1.112 -        public InferenceContext(List<Type> inferencevars, Infer infer) {
   1.113 -            this.undetvars = Type.map(inferencevars, infer.fromTypeVarFun);
   1.114 +        public InferenceContext(List<Type> inferencevars, Infer infer, boolean includeBounds) {
   1.115 +            this.undetvars = Type.map(inferencevars, infer.new FromTypeVarFun(includeBounds));
   1.116              this.inferencevars = inferencevars;
   1.117          }
   1.118  
   1.119 @@ -737,5 +814,5 @@
   1.120          }
   1.121      }
   1.122  
   1.123 -    final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this);
   1.124 +    final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this, false);
   1.125  }

mercurial