8016175: Add bottom-up type-checking support for unambiguous method references

Wed, 17 Jul 2013 14:09:46 +0100

author
mcimadamore
date
Wed, 17 Jul 2013 14:09:46 +0100
changeset 1897
866c87c01285
parent 1896
44e27378f523
child 1898
a204cf7aab7e

8016175: Add bottom-up type-checking support for unambiguous method references
Summary: Type-checking of non-overloaded method references should be independent from target-type
Reviewed-by: jjg, vromero

src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Infer.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Resolve.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference68.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference68.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference69.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference69.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference70.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference70.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference71.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference71.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference72.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/MethodReference72.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType60.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType76.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 17 14:04:01 2013 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Jul 17 14:09:46 2013 +0100
     1.3 @@ -2708,10 +2708,21 @@
     1.4  
     1.5              setFunctionalInfo(that, pt(), desc, target, resultInfo.checkContext.inferenceContext());
     1.6              List<Type> argtypes = desc.getParameterTypes();
     1.7 -
     1.8 -            Pair<Symbol, Resolve.ReferenceLookupHelper> refResult =
     1.9 -                    rs.resolveMemberReference(that.pos(), localEnv, that,
    1.10 -                        that.expr.type, that.name, argtypes, typeargtypes, true, rs.resolveMethodCheck);
    1.11 +            Resolve.MethodCheck referenceCheck = rs.resolveMethodCheck;
    1.12 +
    1.13 +            if (resultInfo.checkContext.inferenceContext().free(argtypes)) {
    1.14 +                referenceCheck = rs.new MethodReferenceCheck(resultInfo.checkContext.inferenceContext());
    1.15 +            }
    1.16 +
    1.17 +            Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = null;
    1.18 +            List<Type> saved_undet = resultInfo.checkContext.inferenceContext().save();
    1.19 +            try {
    1.20 +                refResult = rs.resolveMemberReference(that.pos(), localEnv, that, that.expr.type,
    1.21 +                        that.name, argtypes, typeargtypes, true, referenceCheck,
    1.22 +                        resultInfo.checkContext.inferenceContext());
    1.23 +            } finally {
    1.24 +                resultInfo.checkContext.inferenceContext().rollback(saved_undet);
    1.25 +            }
    1.26  
    1.27              Symbol refSym = refResult.fst;
    1.28              Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
    1.29 @@ -2823,17 +2834,24 @@
    1.30                  }
    1.31              }
    1.32  
    1.33 -            that.sym = refSym.baseSymbol();
    1.34 -            that.kind = lookupHelper.referenceKind(that.sym);
    1.35 -
    1.36              ResultInfo checkInfo =
    1.37                      resultInfo.dup(newMethodTemplate(
    1.38                          desc.getReturnType().hasTag(VOID) ? Type.noType : desc.getReturnType(),
    1.39 -                        lookupHelper.argtypes,
    1.40 -                        typeargtypes));
    1.41 +                        that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes));
    1.42  
    1.43              Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo);
    1.44  
    1.45 +            if (that.kind.isUnbound() &&
    1.46 +                    resultInfo.checkContext.inferenceContext().free(argtypes.head)) {
    1.47 +                //re-generate inference constraints for unbound receiver
    1.48 +                if (!types.isSubtype(resultInfo.checkContext.inferenceContext().asFree(argtypes.head), exprType)) {
    1.49 +                    //cannot happen as this has already been checked - we just need
    1.50 +                    //to regenerate the inference constraints, as that has been lost
    1.51 +                    //as a result of the call to inferenceContext.save()
    1.52 +                    Assert.error("Can't get here");
    1.53 +                }
    1.54 +            }
    1.55 +
    1.56              if (!refType.isErroneous()) {
    1.57                  refType = types.createMethodTypeWithReturn(refType,
    1.58                          adjustMethodReturnType(lookupHelper.site, that.name, checkInfo.pt.getParameterTypes(), refType.getReturnType()));
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 17 14:04:01 2013 +0100
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Jul 17 14:09:46 2013 +0100
     2.3 @@ -34,15 +34,14 @@
     2.4  import com.sun.tools.javac.comp.Attr.ResultInfo;
     2.5  import com.sun.tools.javac.comp.Infer.InferenceContext;
     2.6  import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
     2.7 +import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper;
     2.8  import com.sun.tools.javac.tree.JCTree.*;
     2.9  
    2.10 -import javax.tools.JavaFileObject;
    2.11  
    2.12  import java.util.ArrayList;
    2.13  import java.util.EnumSet;
    2.14  import java.util.LinkedHashSet;
    2.15  import java.util.Map;
    2.16 -import java.util.Queue;
    2.17  import java.util.Set;
    2.18  import java.util.WeakHashMap;
    2.19  
    2.20 @@ -96,6 +95,17 @@
    2.21          types = Types.instance(context);
    2.22          Names names = Names.instance(context);
    2.23          stuckTree = make.Ident(names.empty).setType(Type.stuckType);
    2.24 +        emptyDeferredAttrContext =
    2.25 +            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
    2.26 +                @Override
    2.27 +                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
    2.28 +                    Assert.error("Empty deferred context!");
    2.29 +                }
    2.30 +                @Override
    2.31 +                void complete() {
    2.32 +                    Assert.error("Empty deferred context!");
    2.33 +                }
    2.34 +            };
    2.35      }
    2.36  
    2.37      /** shared tree for stuck expressions */
    2.38 @@ -479,12 +489,10 @@
    2.39  
    2.40              ResultInfo resultInfo;
    2.41              InferenceContext inferenceContext;
    2.42 -            Env<AttrContext> env;
    2.43  
    2.44              public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
    2.45                  this.resultInfo = resultInfo;
    2.46                  this.inferenceContext = deferredAttrContext.inferenceContext;
    2.47 -                this.env = dt.env.dup(dt.tree, dt.env.info.dup());
    2.48                  dt.tree.accept(this);
    2.49                  dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
    2.50                  return Type.noType;
    2.51 @@ -533,18 +541,7 @@
    2.52                      } catch (Types.FunctionDescriptorLookupError ex) {
    2.53                          checkContext.report(null, ex.getDiagnostic());
    2.54                      }
    2.55 -                    JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), env,
    2.56 -                            attr.memberReferenceQualifierResult(tree));
    2.57 -                    ListBuffer<Type> argtypes = ListBuffer.lb();
    2.58 -                    for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
    2.59 -                        argtypes.append(Type.noType);
    2.60 -                    }
    2.61 -                    JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
    2.62 -                    mref2.expr = exprTree;
    2.63 -                    Pair<Symbol, ?> lookupRes =
    2.64 -                            rs.resolveMemberReference(tree, env, mref2, exprTree.type,
    2.65 -                                tree.name, argtypes.toList(), null, true, rs.arityMethodCheck);
    2.66 -                    switch (lookupRes.fst.kind) {
    2.67 +                    switch (tree.sym.kind) {
    2.68                          //note: as argtypes are erroneous types, type-errors must
    2.69                          //have been caused by arity mismatch
    2.70                          case Kinds.ABSENT_MTH:
    2.71 @@ -560,17 +557,7 @@
    2.72      }
    2.73  
    2.74      /** an empty deferred attribution context - all methods throw exceptions */
    2.75 -    final DeferredAttrContext emptyDeferredAttrContext =
    2.76 -            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) {
    2.77 -                @Override
    2.78 -                void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
    2.79 -                    Assert.error("Empty deferred context!");
    2.80 -                }
    2.81 -                @Override
    2.82 -                void complete() {
    2.83 -                    Assert.error("Empty deferred context!");
    2.84 -                }
    2.85 -            };
    2.86 +    final DeferredAttrContext emptyDeferredAttrContext;
    2.87  
    2.88      /**
    2.89       * Map a list of types possibly containing one or more deferred types
    2.90 @@ -668,12 +655,12 @@
    2.91                  if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
    2.92              return List.nil();
    2.93          } else {
    2.94 -            return stuckVarsInternal(tree, resultInfo.pt, resultInfo.checkContext.inferenceContext());
    2.95 +            return stuckVarsInternal(tree, resultInfo.pt, env, resultInfo.checkContext.inferenceContext());
    2.96          }
    2.97      }
    2.98      //where
    2.99 -        private List<Type> stuckVarsInternal(JCTree tree, Type pt, Infer.InferenceContext inferenceContext) {
   2.100 -            StuckChecker sc = new StuckChecker(pt, inferenceContext);
   2.101 +        private List<Type> stuckVarsInternal(JCTree tree, Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
   2.102 +            StuckChecker sc = new StuckChecker(pt, env, inferenceContext);
   2.103              sc.scan(tree);
   2.104              return List.from(sc.stuckVars);
   2.105          }
   2.106 @@ -753,11 +740,13 @@
   2.107      class StuckChecker extends PolyScanner {
   2.108  
   2.109          Type pt;
   2.110 +        Env<AttrContext> env;
   2.111          Infer.InferenceContext inferenceContext;
   2.112          Set<Type> stuckVars = new LinkedHashSet<Type>();
   2.113  
   2.114 -        StuckChecker(Type pt, Infer.InferenceContext inferenceContext) {
   2.115 +        StuckChecker(Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
   2.116              this.pt = pt;
   2.117 +            this.env = env;
   2.118              this.inferenceContext = inferenceContext;
   2.119          }
   2.120  
   2.121 @@ -791,18 +780,41 @@
   2.122  
   2.123              Type descType = types.findDescriptorType(pt);
   2.124              List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
   2.125 -            stuckVars.addAll(freeArgVars);
   2.126 +            Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
   2.127 +            if (freeArgVars.nonEmpty()) {
   2.128 +                //perform arity-based check
   2.129 +                JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
   2.130 +                        attr.memberReferenceQualifierResult(tree));
   2.131 +                ListBuffer<Type> argtypes = ListBuffer.lb();
   2.132 +                for (Type t : descType.getParameterTypes()) {
   2.133 +                    argtypes.append(Type.noType);
   2.134 +                }
   2.135 +                JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
   2.136 +                mref2.expr = exprTree;
   2.137 +                Pair<Symbol, ReferenceLookupHelper> lookupRes =
   2.138 +                        rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
   2.139 +                            tree.name, argtypes.toList(), null, true, rs.arityMethodCheck,
   2.140 +                            inferenceContext);
   2.141 +                Symbol res = tree.sym = lookupRes.fst;
   2.142 +                if (res.kind >= Kinds.ERRONEOUS ||
   2.143 +                        res.type.hasTag(FORALL) ||
   2.144 +                        (res.flags() & Flags.VARARGS) != 0 ||
   2.145 +                        (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
   2.146 +                        exprTree.type.isRaw())) {
   2.147 +                    stuckVars.addAll(freeArgVars);
   2.148 +                }
   2.149 +            }
   2.150          }
   2.151  
   2.152          void scanLambdaBody(JCLambda lambda, final Type pt) {
   2.153              if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
   2.154 -                stuckVars.addAll(stuckVarsInternal(lambda.body, pt, inferenceContext));
   2.155 +                stuckVars.addAll(stuckVarsInternal(lambda.body, pt, env, inferenceContext));
   2.156              } else {
   2.157                  LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
   2.158                      @Override
   2.159                      public void visitReturn(JCReturn tree) {
   2.160                          if (tree.expr != null) {
   2.161 -                            stuckVars.addAll(stuckVarsInternal(tree.expr, pt, inferenceContext));
   2.162 +                            stuckVars.addAll(stuckVarsInternal(tree.expr, pt, env, inferenceContext));
   2.163                          }
   2.164                      }
   2.165                  };
   2.166 @@ -950,12 +962,9 @@
   2.167                  site = site.getUpperBound();
   2.168              }
   2.169  
   2.170 -            ListBuffer<Type> args = ListBuffer.lb();
   2.171 -            for (int i = 0; i < tree.args.length(); i ++) {
   2.172 -                args.append(Type.noType);
   2.173 -            }
   2.174 +            List<Type> args = rs.dummyArgs(tree.args.length());
   2.175  
   2.176 -            Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args.toList(), List.<Type>nil(), MethodResolutionPhase.VARARITY) {
   2.177 +            Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args, List.<Type>nil(), MethodResolutionPhase.VARARITY) {
   2.178                  @Override
   2.179                  Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
   2.180                      return rec == null ?
     3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 17 14:04:01 2013 +0100
     3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 17 14:09:46 2013 +0100
     3.3 @@ -149,7 +149,7 @@
     3.4          inferenceException.clear();
     3.5          try {
     3.6              DeferredAttr.DeferredAttrContext deferredAttrContext =
     3.7 -                    resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
     3.8 +                        resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
     3.9  
    3.10              resolveContext.methodCheck.argumentsAcceptable(env, deferredAttrContext,
    3.11                      argtypes, mt.getParameterTypes(), warn);
    3.12 @@ -225,32 +225,32 @@
    3.13                      inferenceContext.restvars(), mt.getReturnType(), to);
    3.14          }
    3.15      }
    3.16 -    //where
    3.17 -        private Type returnConstraintTarget(Type from, Type to) {
    3.18 -            if (from.hasTag(VOID)) {
    3.19 -                return syms.voidType;
    3.20 -            } else if (to.hasTag(NONE)) {
    3.21 -                return from.isPrimitive() ? from : syms.objectType;
    3.22 -            } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) {
    3.23 -                if (!allowGraphInference) {
    3.24 -                    //if legacy, just return boxed type
    3.25 -                    return types.boxedClass(to).type;
    3.26 +
    3.27 +    Type returnConstraintTarget(Type from, Type to) {
    3.28 +        if (from.hasTag(VOID)) {
    3.29 +            return syms.voidType;
    3.30 +        } else if (to.hasTag(NONE)) {
    3.31 +            return from.isPrimitive() ? from : syms.objectType;
    3.32 +        } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) {
    3.33 +            if (!allowGraphInference) {
    3.34 +                //if legacy, just return boxed type
    3.35 +                return types.boxedClass(to).type;
    3.36 +            }
    3.37 +            //if graph inference we need to skip conflicting boxed bounds...
    3.38 +            UndetVar uv = (UndetVar)from;
    3.39 +            for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) {
    3.40 +                Type boundAsPrimitive = types.unboxedType(t);
    3.41 +                if (boundAsPrimitive == null) continue;
    3.42 +                if (types.isConvertible(boundAsPrimitive, to)) {
    3.43 +                    //effectively skip return-type constraint generation (compatibility)
    3.44 +                    return syms.objectType;
    3.45                  }
    3.46 -                //if graph inference we need to skip conflicting boxed bounds...
    3.47 -                UndetVar uv = (UndetVar)from;
    3.48 -                for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) {
    3.49 -                    Type boundAsPrimitive = types.unboxedType(t);
    3.50 -                    if (boundAsPrimitive == null) continue;
    3.51 -                    if (types.isConvertible(boundAsPrimitive, to)) {
    3.52 -                        //effectively skip return-type constraint generation (compatibility)
    3.53 -                        return syms.objectType;
    3.54 -                    }
    3.55 -                }
    3.56 -                return types.boxedClass(to).type;
    3.57 -            } else {
    3.58 -                return to;
    3.59              }
    3.60 +            return types.boxedClass(to).type;
    3.61 +        } else {
    3.62 +            return to;
    3.63          }
    3.64 +    }
    3.65  
    3.66      /**
    3.67        * Infer cyclic inference variables as described in 15.12.2.8.
    3.68 @@ -1337,9 +1337,6 @@
    3.69          /** list of inference vars in this context */
    3.70          List<Type> inferencevars;
    3.71  
    3.72 -        /** backed up inference variables */
    3.73 -        List<Type> saved_undet;
    3.74 -
    3.75          java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
    3.76                  new java.util.HashMap<FreeTypeListener, List<Type>>();
    3.77  
     4.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 17 14:04:01 2013 +0100
     4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Jul 17 14:09:46 2013 +0100
     4.3 @@ -584,6 +584,13 @@
     4.4          try {
     4.5              currentResolutionContext = new MethodResolutionContext();
     4.6              currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
     4.7 +            if (env.tree.hasTag(JCTree.Tag.REFERENCE)) {
     4.8 +                //method/constructor references need special check class
     4.9 +                //to handle inference variables in 'argtypes' (might happen
    4.10 +                //during an unsticking round)
    4.11 +                currentResolutionContext.methodCheck =
    4.12 +                        new MethodReferenceCheck(resultInfo.checkContext.inferenceContext());
    4.13 +            }
    4.14              MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
    4.15              return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
    4.16                      step.isBoxingRequired(), step.isVarargsRequired(), warn);
    4.17 @@ -773,6 +780,14 @@
    4.18          }
    4.19      };
    4.20  
    4.21 +    List<Type> dummyArgs(int length) {
    4.22 +        ListBuffer<Type> buf = ListBuffer.lb();
    4.23 +        for (int i = 0 ; i < length ; i++) {
    4.24 +            buf.append(Type.noType);
    4.25 +        }
    4.26 +        return buf.toList();
    4.27 +    }
    4.28 +
    4.29      /**
    4.30       * Main method applicability routine. Given a list of actual types A,
    4.31       * a list of formal types F, determines whether the types in A are
    4.32 @@ -850,6 +865,47 @@
    4.33          }
    4.34      };
    4.35  
    4.36 +    class MethodReferenceCheck extends AbstractMethodCheck {
    4.37 +
    4.38 +        InferenceContext pendingInferenceContext;
    4.39 +
    4.40 +        MethodReferenceCheck(InferenceContext pendingInferenceContext) {
    4.41 +            this.pendingInferenceContext = pendingInferenceContext;
    4.42 +        }
    4.43 +
    4.44 +        @Override
    4.45 +        void checkArg(DiagnosticPosition pos, boolean varargs, Type actual, Type formal, DeferredAttrContext deferredAttrContext, Warner warn) {
    4.46 +            ResultInfo mresult = methodCheckResult(varargs, formal, deferredAttrContext, warn);
    4.47 +            mresult.check(pos, actual);
    4.48 +        }
    4.49 +
    4.50 +        private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
    4.51 +                final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) {
    4.52 +            CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) {
    4.53 +                MethodCheckDiag methodDiag = varargsCheck ?
    4.54 +                                 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
    4.55 +
    4.56 +                @Override
    4.57 +                public boolean compatible(Type found, Type req, Warner warn) {
    4.58 +                    found = pendingInferenceContext.asFree(found);
    4.59 +                    req = infer.returnConstraintTarget(found, req);
    4.60 +                    return super.compatible(found, req, warn);
    4.61 +                }
    4.62 +
    4.63 +                @Override
    4.64 +                public void report(DiagnosticPosition pos, JCDiagnostic details) {
    4.65 +                    reportMC(pos, methodDiag, deferredAttrContext.inferenceContext, details);
    4.66 +                }
    4.67 +            };
    4.68 +            return new MethodResultInfo(to, checkContext);
    4.69 +        }
    4.70 +
    4.71 +        @Override
    4.72 +        public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
    4.73 +            return new MostSpecificCheck(strict, actuals);
    4.74 +        }
    4.75 +    };
    4.76 +
    4.77      /**
    4.78       * Check context to be used during method applicability checks. A method check
    4.79       * context might contain inference variables.
    4.80 @@ -2576,7 +2632,8 @@
    4.81                                    Name name, List<Type> argtypes,
    4.82                                    List<Type> typeargtypes,
    4.83                                    boolean boxingAllowed,
    4.84 -                                  MethodCheck methodCheck) {
    4.85 +                                  MethodCheck methodCheck,
    4.86 +                                  InferenceContext inferenceContext) {
    4.87          MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
    4.88  
    4.89          ReferenceLookupHelper boundLookupHelper;
    4.90 @@ -2599,7 +2656,7 @@
    4.91          Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, methodCheck, boundLookupHelper);
    4.92  
    4.93          //step 2 - unbound lookup
    4.94 -        ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup();
    4.95 +        ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(inferenceContext);
    4.96          Env<AttrContext> unboundEnv = env.dup(env.tree, env.info.dup());
    4.97          Symbol unboundSym = lookupMethod(unboundEnv, env.tree.pos(), site.tsym, methodCheck, unboundLookupHelper);
    4.98  
    4.99 @@ -2739,11 +2796,11 @@
   4.100           * Returns an unbound version of this lookup helper. By default, this
   4.101           * method returns an dummy lookup helper.
   4.102           */
   4.103 -        ReferenceLookupHelper unboundLookup() {
   4.104 +        ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
   4.105              //dummy loopkup helper that always return 'methodNotFound'
   4.106              return new ReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase) {
   4.107                  @Override
   4.108 -                ReferenceLookupHelper unboundLookup() {
   4.109 +                ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
   4.110                      return this;
   4.111                  }
   4.112                  @Override
   4.113 @@ -2793,14 +2850,15 @@
   4.114          }
   4.115  
   4.116          @Override
   4.117 -        ReferenceLookupHelper unboundLookup() {
   4.118 +        ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
   4.119              if (TreeInfo.isStaticSelector(referenceTree.expr, names) &&
   4.120                      argtypes.nonEmpty() &&
   4.121 -                    (argtypes.head.hasTag(NONE) || types.isSubtypeUnchecked(argtypes.head, site))) {
   4.122 +                    (argtypes.head.hasTag(NONE) ||
   4.123 +                    types.isSubtypeUnchecked(inferenceContext.asFree(argtypes.head), site))) {
   4.124                  return new UnboundMethodReferenceLookupHelper(referenceTree, name,
   4.125                          site, argtypes, typeargtypes, maxPhase);
   4.126              } else {
   4.127 -                return super.unboundLookup();
   4.128 +                return super.unboundLookup(inferenceContext);
   4.129              }
   4.130          }
   4.131  
   4.132 @@ -2836,7 +2894,7 @@
   4.133          }
   4.134  
   4.135          @Override
   4.136 -        ReferenceLookupHelper unboundLookup() {
   4.137 +        ReferenceLookupHelper unboundLookup(InferenceContext inferenceContext) {
   4.138              return this;
   4.139          }
   4.140  
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/tools/javac/lambda/MethodReference68.java	Wed Jul 17 14:09:46 2013 +0100
     5.3 @@ -0,0 +1,23 @@
     5.4 +/*
     5.5 + * @test /nodynamiccopyright/
     5.6 + * @bug 8016175
     5.7 + * @summary Add bottom-up type-checking support for unambiguous method references
     5.8 + * @compile/fail/ref=MethodReference68.out -XDrawDiagnostics MethodReference68.java
     5.9 + */
    5.10 +class MethodReference68 {
    5.11 +    interface F<X> {
    5.12 +       String m(X x);
    5.13 +    }
    5.14 +
    5.15 +    static class Foo {
    5.16 +        String getName() { return ""; }
    5.17 +    }
    5.18 +
    5.19 +    @SuppressWarnings("unchecked")
    5.20 +    <Z> void g(F<Z> fz, Z... zs) { }
    5.21 +
    5.22 +    void test() {
    5.23 +         g(Foo::getName);
    5.24 +         g(Foo::getName, 1); //incompatible constraints, Z <: Foo, Z :> Integer
    5.25 +    }
    5.26 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/tools/javac/lambda/MethodReference68.out	Wed Jul 17 14:09:46 2013 +0100
     6.3 @@ -0,0 +1,2 @@
     6.4 +MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @493,int, kindname.class, MethodReference68, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, MethodReference68.Foo,java.lang.Object)
     6.5 +1 error
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/tools/javac/lambda/MethodReference69.java	Wed Jul 17 14:09:46 2013 +0100
     7.3 @@ -0,0 +1,21 @@
     7.4 +/*
     7.5 + * @test /nodynamiccopyright/
     7.6 + * @bug 8016175
     7.7 + * @summary Add bottom-up type-checking support for unambiguous method references
     7.8 + * @compile/fail/ref=MethodReference69.out -XDrawDiagnostics MethodReference69.java
     7.9 + */
    7.10 +class MethodReference69 {
    7.11 +    interface F<X> {
    7.12 +        String m(Integer x1, X x2);
    7.13 +    }
    7.14 +
    7.15 +    static class Foo {
    7.16 +        String getNameAt(Integer i) { return ""; }
    7.17 +    }
    7.18 +
    7.19 +    <Z> void g(F<Z> fz) { }
    7.20 +
    7.21 +    void test() {
    7.22 +         g(Foo::getName);
    7.23 +    }
    7.24 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/tools/javac/lambda/MethodReference69.out	Wed Jul 17 14:09:46 2013 +0100
     8.3 @@ -0,0 +1,2 @@
     8.4 +MethodReference69.java:19:12: compiler.err.invalid.mref: kindname.method, (compiler.misc.cant.resolve.location.args: kindname.method, getName, , , (compiler.misc.location: kindname.class, MethodReference69.Foo, null))
     8.5 +1 error
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/tools/javac/lambda/MethodReference70.java	Wed Jul 17 14:09:46 2013 +0100
     9.3 @@ -0,0 +1,28 @@
     9.4 +/*
     9.5 + * @test /nodynamiccopyright/
     9.6 + * @bug 8016175
     9.7 + * @summary Add bottom-up type-checking support for unambiguous method references
     9.8 + * @compile/fail/ref=MethodReference70.out -XDrawDiagnostics MethodReference70.java
     9.9 + */
    9.10 +class MethodReference70 {
    9.11 +    interface F<X> {
    9.12 +        void m(X x);
    9.13 +    }
    9.14 +
    9.15 +    interface G<X> {
    9.16 +        Integer m(X x);
    9.17 +    }
    9.18 +
    9.19 +    void m1(Integer i) { }
    9.20 +
    9.21 +    void m2(Integer i) { }
    9.22 +    void m2(String i) { }
    9.23 +
    9.24 +    <Z> void g(F<Z> fz) { }
    9.25 +    <Z> void g(G<Z> gz) { }
    9.26 +
    9.27 +    void test() {
    9.28 +         g(this::m1); //ok
    9.29 +         g(this::m2); //ambiguous (stuck!)
    9.30 +    }
    9.31 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/tools/javac/lambda/MethodReference70.out	Wed Jul 17 14:09:46 2013 +0100
    10.3 @@ -0,0 +1,3 @@
    10.4 +MethodReference70.java:26:10: compiler.err.ref.ambiguous: g, kindname.method, <Z>g(MethodReference70.F<Z>), MethodReference70, kindname.method, <Z>g(MethodReference70.G<Z>), MethodReference70
    10.5 +MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
    10.6 +2 errors
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/tools/javac/lambda/MethodReference71.java	Wed Jul 17 14:09:46 2013 +0100
    11.3 @@ -0,0 +1,26 @@
    11.4 +/*
    11.5 + * @test /nodynamiccopyright/
    11.6 + * @bug 8016175
    11.7 + * @summary Add bottom-up type-checking support for unambiguous method references
    11.8 + * @compile/fail/ref=MethodReference71.out -XDrawDiagnostics MethodReference71.java
    11.9 + */
   11.10 +class MethodReference71 {
   11.11 +    interface F<X> {
   11.12 +        void m(X x);
   11.13 +    }
   11.14 +
   11.15 +    interface G<X> {
   11.16 +        Integer m(X x);
   11.17 +    }
   11.18 +
   11.19 +    void m1(Integer i) { }
   11.20 +    void m2(Integer... i) { }
   11.21 +
   11.22 +    <Z> void g(F<Z> f) { }
   11.23 +    <Z> void g(G<Z> g) { }
   11.24 +
   11.25 +    void test() {
   11.26 +         g(this::m1); //ok
   11.27 +         g(this::m2); //ambiguous (stuck!)
   11.28 +    }
   11.29 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/test/tools/javac/lambda/MethodReference71.out	Wed Jul 17 14:09:46 2013 +0100
    12.3 @@ -0,0 +1,3 @@
    12.4 +MethodReference71.java:24:10: compiler.err.ref.ambiguous: g, kindname.method, <Z>g(MethodReference71.F<Z>), MethodReference71, kindname.method, <Z>g(MethodReference71.G<Z>), MethodReference71
    12.5 +MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z)
    12.6 +2 errors
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/test/tools/javac/lambda/MethodReference72.java	Wed Jul 17 14:09:46 2013 +0100
    13.3 @@ -0,0 +1,20 @@
    13.4 +/*
    13.5 + * @test /nodynamiccopyright/
    13.6 + * @bug 8016175
    13.7 + * @summary Add bottom-up type-checking support for unambiguous method references
    13.8 + * @compile/fail/ref=MethodReference72.out -XDrawDiagnostics MethodReference72.java
    13.9 + */
   13.10 +class MethodReference72 {
   13.11 +    interface F<X> {
   13.12 +        @SuppressWarnings("unchecked")
   13.13 +        void m(X... x);
   13.14 +    }
   13.15 +
   13.16 +    void m1(Integer i) { }
   13.17 +
   13.18 +    <Z> void g(F<Z> f) { }
   13.19 +
   13.20 +    void test() {
   13.21 +        g(this::m1); //?
   13.22 +    }
   13.23 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/test/tools/javac/lambda/MethodReference72.out	Wed Jul 17 14:09:46 2013 +0100
    14.3 @@ -0,0 +1,2 @@
    14.4 +MethodReference72.java:18:9: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference72.F<Z>, @420, kindname.class, MethodReference72, (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m1, java.lang.Integer, Z[], kindname.class, MethodReference72, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: Z[], java.lang.Integer)))))
    14.5 +1 error
    15.1 --- a/test/tools/javac/lambda/TargetType60.out	Wed Jul 17 14:04:01 2013 +0100
    15.2 +++ b/test/tools/javac/lambda/TargetType60.out	Wed Jul 17 14:09:46 2013 +0100
    15.3 @@ -1,7 +1,7 @@
    15.4  TargetType60.java:54:21: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType60.Sam0), TargetType60, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60
    15.5  TargetType60.java:55:21: compiler.err.ref.ambiguous: g, kindname.method, <U>g(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>g(TargetType60.Sam2<U,java.lang.String>), TargetType60
    15.6  TargetType60.java:60:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
    15.7 -TargetType60.java:60:28: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, n1, java.lang.String, TargetType60, kindname.class, TargetType60, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: TargetType60, java.lang.String)))))
    15.8 +TargetType60.java:60:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n1(java.lang.String))
    15.9  TargetType60.java:61:29: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, n2(TargetType60,java.lang.String))
   15.10  TargetType60.java:62:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
   15.11  TargetType60.java:63:27: compiler.err.ref.ambiguous: u, kindname.method, <U>u(TargetType60.Sam1<U>), TargetType60, kindname.method, <U>u(TargetType60.Sam2<U,java.lang.String>), TargetType60
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/test/tools/javac/lambda/TargetType76.java	Wed Jul 17 14:09:46 2013 +0100
    16.3 @@ -0,0 +1,65 @@
    16.4 +/*
    16.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.7 + *
    16.8 + * This code is free software; you can redistribute it and/or modify it
    16.9 + * under the terms of the GNU General Public License version 2 only, as
   16.10 + * published by the Free Software Foundation.
   16.11 + *
   16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   16.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16.15 + * version 2 for more details (a copy is included in the LICENSE file that
   16.16 + * accompanied this code).
   16.17 + *
   16.18 + * You should have received a copy of the GNU General Public License version
   16.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   16.21 + *
   16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   16.23 + * or visit www.oracle.com if you need additional information or have any
   16.24 + * questions.
   16.25 + */
   16.26 +
   16.27 +/*
   16.28 + * @test
   16.29 + * @bug 8016175
   16.30 + * @summary Add bottom-up type-checking support for unambiguous method references
   16.31 + * @compile TargetType76.java
   16.32 + */
   16.33 +class TargetType76 {
   16.34 +
   16.35 +    interface Function<X, Y> {
   16.36 +        Y m(X x);
   16.37 +    }
   16.38 +
   16.39 +    interface OfRef<T> { }
   16.40 +
   16.41 +    interface Supplier<X> {
   16.42 +        X make();
   16.43 +    }
   16.44 +
   16.45 +    interface Stream<X> { }
   16.46 +
   16.47 +    interface Node<E> {
   16.48 +        Spliterator<E> spliterator();
   16.49 +    }
   16.50 +
   16.51 +    interface Spliterator<X> {
   16.52 +        Spliterator<X> spliterator();
   16.53 +    }
   16.54 +
   16.55 +    class RefTestData<T, I> implements OfRef<T> {
   16.56 +        RefTestData(I state,
   16.57 +                    Function<I, Stream<T>> streamFn,
   16.58 +                    Function<I, Spliterator<T>> splitrFn) { }
   16.59 +    }
   16.60 +
   16.61 +    <O> OfRef<O> ofCollection(Node<O> collection) {
   16.62 +        return new RefTestData<>(collection,
   16.63 +                                 x->stream(x::spliterator),
   16.64 +                                 Node::spliterator);
   16.65 +    }
   16.66 +
   16.67 +    <S> Stream<S> stream(Supplier<? extends Spliterator<S>> supplier) { return null; }
   16.68 +}

mercurial