8007464: Add graph inference support

Tue, 12 Feb 2013 19:25:09 +0000

author
mcimadamore
date
Tue, 12 Feb 2013 19:25:09 +0000
changeset 1562
2154ed9ff6c8
parent 1561
073696f59241
child 1563
bc456436c613

8007464: Add graph inference support
Summary: Add support for more aggressive type-inference scheme
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/code/Source.java file | annotate | diff | comparison | revisions
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/util/GraphUtils.java file | annotate | diff | comparison | revisions
test/tools/javac/6758789/T6758789b.out file | annotate | diff | comparison | revisions
test/tools/javac/Diagnostics/6799605/T6799605.out file | annotate | diff | comparison | revisions
test/tools/javac/diags/examples/CantApplyDiamond1.java file | annotate | diff | comparison | revisions
test/tools/javac/diags/examples/InferredDoNotConformToEq.java file | annotate | diff | comparison | revisions
test/tools/javac/diags/examples/InferredDoNotConformToUpper.java file | annotate | diff | comparison | revisions
test/tools/javac/diags/examples/WhereFreshTvar.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/7015430/T7015430.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/7151802/T7151802.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/diamond/neg/Neg06.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6278587/T6278587Neg.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6638712/T6638712d.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/6638712/T6638712e.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/7154127/T7154127.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/7154127/T7154127.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/7177306/T7177306a.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/7177306/T7177306e.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/inference/7177306/T7177306e.out file | annotate | diff | comparison | revisions
test/tools/javac/generics/odersky/BadTest4.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType14.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType20.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType20.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType28.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType50.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType50.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType51.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType52.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType52.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType53.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType54.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType55.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType56.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType57.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType57.out file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType58.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType59.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType61.java file | annotate | diff | comparison | revisions
test/tools/javac/lambda/TargetType62.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Source.java	Tue Feb 12 13:36:56 2013 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java	Tue Feb 12 19:25:09 2013 +0000
     1.3 @@ -221,7 +221,7 @@
     1.4      public boolean allowIntersectionTypesInCast() {
     1.5          return compareTo(JDK1_8) >= 0;
     1.6      }
     1.7 -    public boolean allowEarlyReturnConstraints() {
     1.8 +    public boolean allowGraphInference() {
     1.9          return compareTo(JDK1_8) >= 0;
    1.10      }
    1.11      public boolean allowStructuralMostSpecific() {
     2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Feb 12 13:36:56 2013 +0000
     2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Feb 12 19:25:09 2013 +0000
     2.3 @@ -4152,7 +4152,9 @@
     2.4          }
     2.5  
     2.6      private Type capture(Type type) {
     2.7 -        return types.capture(type);
     2.8 +        //do not capture free types
     2.9 +        return resultInfo.checkContext.inferenceContext().free(type) ?
    2.10 +                type : types.capture(type);
    2.11      }
    2.12  
    2.13      private void validateTypeAnnotations(JCTree tree) {
     3.1 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Tue Feb 12 13:36:56 2013 +0000
     3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Tue Feb 12 19:25:09 2013 +0000
     3.3 @@ -234,7 +234,7 @@
     3.4                      dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
     3.5                      return speculativeTree.type;
     3.6                  case CHECK:
     3.7 -                    Assert.check(dt.mode == AttrMode.SPECULATIVE);
     3.8 +                    Assert.check(dt.mode != null);
     3.9                      return attr.attribTree(dt.tree, dt.env, resultInfo);
    3.10              }
    3.11              Assert.error();
    3.12 @@ -242,6 +242,13 @@
    3.13          }
    3.14      };
    3.15  
    3.16 +    DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
    3.17 +        public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
    3.18 +            Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
    3.19 +            return dt.tree.type = Type.noType;
    3.20 +        }
    3.21 +    };
    3.22 +
    3.23      /**
    3.24       * The 'mode' in which the deferred type is to be type-checked
    3.25       */
    3.26 @@ -382,7 +389,7 @@
    3.27                  if (!progress) {
    3.28                      //remove all variables that have already been instantiated
    3.29                      //from the list of stuck variables
    3.30 -                    inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)));
    3.31 +                    inferenceContext.solveAny(List.from(stuckVars), warn);
    3.32                      inferenceContext.notifyChange();
    3.33                  }
    3.34              }
    3.35 @@ -431,7 +438,15 @@
    3.36                      return true;
    3.37                  case CHECK:
    3.38                      if (stuckVars.nonEmpty()) {
    3.39 -                        return false;
    3.40 +                        //stuck expression - see if we can propagate
    3.41 +                        if (deferredAttrContext.parent != emptyDeferredAttrContext &&
    3.42 +                                Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) {
    3.43 +                            deferredAttrContext.parent.deferredAttrNodes.add(this);
    3.44 +                            dt.check(resultInfo, List.<Type>nil(), dummyCompleter);
    3.45 +                            return true;
    3.46 +                        } else {
    3.47 +                            return false;
    3.48 +                        }
    3.49                      } else {
    3.50                          dt.check(resultInfo, stuckVars, basicCompleter);
    3.51                          return true;
     4.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Feb 12 13:36:56 2013 +0000
     4.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Feb 12 19:25:09 2013 +0000
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -25,22 +25,30 @@
    4.11  
    4.12  package com.sun.tools.javac.comp;
    4.13  
    4.14 -import com.sun.tools.javac.code.*;
    4.15 -import com.sun.tools.javac.code.Symbol.*;
    4.16 -import com.sun.tools.javac.code.Type.*;
    4.17 -import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
    4.18 -import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
    4.19 -import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
    4.20 -import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
    4.21  import com.sun.tools.javac.tree.JCTree;
    4.22  import com.sun.tools.javac.tree.JCTree.JCTypeCast;
    4.23  import com.sun.tools.javac.tree.TreeInfo;
    4.24  import com.sun.tools.javac.util.*;
    4.25 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    4.26  import com.sun.tools.javac.util.List;
    4.27 -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    4.28 +import com.sun.tools.javac.code.*;
    4.29 +import com.sun.tools.javac.code.Type.*;
    4.30 +import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
    4.31 +import com.sun.tools.javac.code.Symbol.*;
    4.32 +import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
    4.33 +import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph;
    4.34 +import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
    4.35 +import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
    4.36 +import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
    4.37  
    4.38  import java.util.HashMap;
    4.39  import java.util.Map;
    4.40 +import java.util.Set;
    4.41 +
    4.42 +import java.util.ArrayList;
    4.43 +import java.util.Collections;
    4.44 +import java.util.EnumSet;
    4.45 +import java.util.HashSet;
    4.46  
    4.47  import static com.sun.tools.javac.code.TypeTag.*;
    4.48  
    4.49 @@ -55,19 +63,15 @@
    4.50      protected static final Context.Key<Infer> inferKey =
    4.51          new Context.Key<Infer>();
    4.52  
    4.53 -    /** A value for prototypes that admit any type, including polymorphic ones. */
    4.54 -    public static final Type anyPoly = new Type(NONE, null);
    4.55 -
    4.56 +    Resolve rs;
    4.57 +    Check chk;
    4.58      Symtab syms;
    4.59      Types types;
    4.60 -    Check chk;
    4.61 -    Resolve rs;
    4.62 -    DeferredAttr deferredAttr;
    4.63 +    JCDiagnostic.Factory diags;
    4.64      Log log;
    4.65 -    JCDiagnostic.Factory diags;
    4.66  
    4.67 -    /** Should we inject return-type constraints earlier? */
    4.68 -    boolean allowEarlyReturnConstraints;
    4.69 +    /** should the graph solver be used? */
    4.70 +    boolean allowGraphInference;
    4.71  
    4.72      public static Infer instance(Context context) {
    4.73          Infer instance = context.get(inferKey);
    4.74 @@ -78,17 +82,22 @@
    4.75  
    4.76      protected Infer(Context context) {
    4.77          context.put(inferKey, this);
    4.78 +
    4.79 +        rs = Resolve.instance(context);
    4.80 +        chk = Check.instance(context);
    4.81          syms = Symtab.instance(context);
    4.82          types = Types.instance(context);
    4.83 -        rs = Resolve.instance(context);
    4.84 -        deferredAttr = DeferredAttr.instance(context);
    4.85 +        diags = JCDiagnostic.Factory.instance(context);
    4.86          log = Log.instance(context);
    4.87 -        chk = Check.instance(context);
    4.88 -        diags = JCDiagnostic.Factory.instance(context);
    4.89          inferenceException = new InferenceException(diags);
    4.90 -        allowEarlyReturnConstraints = Source.instance(context).allowEarlyReturnConstraints();
    4.91 +        Options options = Options.instance(context);
    4.92 +        allowGraphInference = Source.instance(context).allowGraphInference()
    4.93 +                && options.isUnset("useLegacyInference");
    4.94      }
    4.95  
    4.96 +    /** A value for prototypes that admit any type, including polymorphic ones. */
    4.97 +    public static final Type anyPoly = new Type(NONE, null);
    4.98 +
    4.99     /**
   4.100      * This exception class is design to store a list of diagnostics corresponding
   4.101      * to inference errors that can arise during a method applicability check.
   4.102 @@ -118,140 +127,12 @@
   4.103          }
   4.104      }
   4.105  
   4.106 -    final InferenceException inferenceException;
   4.107 +    protected final InferenceException inferenceException;
   4.108  
   4.109 -/***************************************************************************
   4.110 - * Mini/Maximization of UndetVars
   4.111 - ***************************************************************************/
   4.112 -
   4.113 -    /** Instantiate undetermined type variable to its minimal upper bound.
   4.114 -     *  Throw a NoInstanceException if this not possible.
   4.115 -     */
   4.116 -   void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
   4.117 -        List<Type> hibounds = Type.filter(that.getBounds(InferenceBound.UPPER), boundFilter);
   4.118 -        if (that.getBounds(InferenceBound.EQ).isEmpty()) {
   4.119 -            if (hibounds.isEmpty())
   4.120 -                that.inst = syms.objectType;
   4.121 -            else if (hibounds.tail.isEmpty())
   4.122 -                that.inst = hibounds.head;
   4.123 -            else
   4.124 -                that.inst = types.glb(hibounds);
   4.125 -        } else {
   4.126 -            that.inst = that.getBounds(InferenceBound.EQ).head;
   4.127 -        }
   4.128 -        if (that.inst == null ||
   4.129 -            that.inst.isErroneous())
   4.130 -            throw inferenceException
   4.131 -                .setMessage("no.unique.maximal.instance.exists",
   4.132 -                            that.qtype, hibounds);
   4.133 -    }
   4.134 -
   4.135 -    private Filter<Type> boundFilter = new Filter<Type>() {
   4.136 -        @Override
   4.137 -        public boolean accepts(Type t) {
   4.138 -            return !t.isErroneous() && !t.hasTag(BOT);
   4.139 -        }
   4.140 -    };
   4.141 -
   4.142 -    /** Instantiate undetermined type variable to the lub of all its lower bounds.
   4.143 -     *  Throw a NoInstanceException if this not possible.
   4.144 -     */
   4.145 -    void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
   4.146 -        List<Type> lobounds = Type.filter(that.getBounds(InferenceBound.LOWER), boundFilter);
   4.147 -        if (that.getBounds(InferenceBound.EQ).isEmpty()) {
   4.148 -            if (lobounds.isEmpty()) {
   4.149 -                //do nothing - the inference variable is under-constrained
   4.150 -                return;
   4.151 -            } else if (lobounds.tail.isEmpty())
   4.152 -                that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
   4.153 -            else {
   4.154 -                that.inst = types.lub(lobounds);
   4.155 -            }
   4.156 -            if (that.inst == null || that.inst.hasTag(ERROR))
   4.157 -                    throw inferenceException
   4.158 -                        .setMessage("no.unique.minimal.instance.exists",
   4.159 -                                    that.qtype, lobounds);
   4.160 -        } else {
   4.161 -            that.inst = that.getBounds(InferenceBound.EQ).head;
   4.162 -        }
   4.163 -    }
   4.164 -
   4.165 -/***************************************************************************
   4.166 - * Exported Methods
   4.167 - ***************************************************************************/
   4.168 -
   4.169 +    // <editor-fold defaultstate="collapsed" desc="Inference routines">
   4.170      /**
   4.171 -     * Instantiate uninferred inference variables (JLS 15.12.2.8). First
   4.172 -     * if the method return type is non-void, we derive constraints from the
   4.173 -     * expected type - then we use declared bound well-formedness to derive additional
   4.174 -     * constraints. If no instantiation exists, or if several incomparable
   4.175 -     * best instantiations exist throw a NoInstanceException.
   4.176 -     */
   4.177 -    public void instantiateUninferred(DiagnosticPosition pos,
   4.178 -            InferenceContext inferenceContext,
   4.179 -            MethodType mtype,
   4.180 -            Attr.ResultInfo resultInfo,
   4.181 -            Warner warn) throws InferenceException {
   4.182 -        while (true) {
   4.183 -            boolean stuck = true;
   4.184 -            for (Type t : inferenceContext.undetvars) {
   4.185 -                UndetVar uv = (UndetVar)t;
   4.186 -                if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() ||
   4.187 -                        !inferenceContext.free(uv.getBounds(InferenceBound.UPPER)))) {
   4.188 -                    maximizeInst((UndetVar)t, warn);
   4.189 -                    stuck = false;
   4.190 -                }
   4.191 -            }
   4.192 -            if (inferenceContext.restvars().isEmpty()) {
   4.193 -                //all variables have been instantiated - exit
   4.194 -                break;
   4.195 -            } else if (stuck) {
   4.196 -                //some variables could not be instantiated because of cycles in
   4.197 -                //upper bounds - provide a (possibly recursive) default instantiation
   4.198 -                instantiateAsUninferredVars(inferenceContext);
   4.199 -                break;
   4.200 -            } else {
   4.201 -                //some variables have been instantiated - replace newly instantiated
   4.202 -                //variables in remaining upper bounds and continue
   4.203 -                for (Type t : inferenceContext.undetvars) {
   4.204 -                    UndetVar uv = (UndetVar)t;
   4.205 -                    uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
   4.206 -                }
   4.207 -            }
   4.208 -        }
   4.209 -    }
   4.210 -
   4.211 -    /**
   4.212 -     * Infer cyclic inference variables as described in 15.12.2.8.
   4.213 -     */
   4.214 -    private void instantiateAsUninferredVars(InferenceContext inferenceContext) {
   4.215 -        ListBuffer<Type> todo = ListBuffer.lb();
   4.216 -        //step 1 - create fresh tvars
   4.217 -        for (Type t : inferenceContext.undetvars) {
   4.218 -            UndetVar uv = (UndetVar)t;
   4.219 -            if (uv.inst == null) {
   4.220 -                TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
   4.221 -                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null);
   4.222 -                todo.append(uv);
   4.223 -                uv.inst = fresh_tvar.type;
   4.224 -            }
   4.225 -        }
   4.226 -        //step 2 - replace fresh tvars in their bounds
   4.227 -        List<Type> formals = inferenceContext.inferenceVars();
   4.228 -        for (Type t : todo) {
   4.229 -            UndetVar uv = (UndetVar)t;
   4.230 -            TypeVar ct = (TypeVar)uv.inst;
   4.231 -            ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct)));
   4.232 -            if (ct.bound.isErroneous()) {
   4.233 -                //report inference error if glb fails
   4.234 -                reportBoundError(uv, BoundErrorKind.BAD_UPPER);
   4.235 -            }
   4.236 -            formals = formals.tail;
   4.237 -        }
   4.238 -    }
   4.239 -
   4.240 -    /** Instantiate a generic method type by finding instantiations for all its
   4.241 -     * inference variables so that it can be applied to a given argument type list.
   4.242 +     * Main inference entry point - instantiate a generic method type
   4.243 +     * using given argument types and (possibly) an expected target-type.
   4.244       */
   4.245      public Type instantiateMethod(Env<AttrContext> env,
   4.246                                    List<Type> tvars,
   4.247 @@ -267,259 +148,144 @@
   4.248          //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
   4.249          final InferenceContext inferenceContext = new InferenceContext(tvars);
   4.250          inferenceException.clear();
   4.251 +        try {
   4.252 +            DeferredAttr.DeferredAttrContext deferredAttrContext =
   4.253 +                    resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
   4.254  
   4.255 -        DeferredAttr.DeferredAttrContext deferredAttrContext =
   4.256 -                resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
   4.257 +            methodCheck.argumentsAcceptable(env, deferredAttrContext,
   4.258 +                    argtypes, mt.getParameterTypes(), warn);
   4.259  
   4.260 -        try {
   4.261 -            methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
   4.262 -
   4.263 -            if (resultInfo != null && allowEarlyReturnConstraints &&
   4.264 +            if (allowGraphInference &&
   4.265 +                    resultInfo != null &&
   4.266                      !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
   4.267 -                generateReturnConstraints(mt, inferenceContext, resultInfo);
   4.268 +                //inject return constraints earlier
   4.269 +                checkWithinBounds(inferenceContext, warn); //propagation
   4.270 +                generateReturnConstraints(resultInfo, mt, inferenceContext);
   4.271 +                //propagate outwards if needed
   4.272 +                if (resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
   4.273 +                    //propagate inference context outwards and exit
   4.274 +                    inferenceContext.dupTo(resultInfo.checkContext.inferenceContext());
   4.275 +                    deferredAttrContext.complete();
   4.276 +                    return mt;
   4.277 +                }
   4.278              }
   4.279  
   4.280              deferredAttrContext.complete();
   4.281  
   4.282              // minimize as yet undetermined type variables
   4.283 -            for (Type t : inferenceContext.undetvars) {
   4.284 -                minimizeInst((UndetVar)t, warn);
   4.285 +            if (allowGraphInference) {
   4.286 +                inferenceContext.solve(warn);
   4.287 +            } else {
   4.288 +                inferenceContext.solveLegacy(true, warn, LegacyInferenceSteps.EQ_LOWER.steps); //minimizeInst
   4.289              }
   4.290  
   4.291 -            checkWithinBounds(inferenceContext, warn);
   4.292 -
   4.293              mt = (MethodType)inferenceContext.asInstType(mt);
   4.294  
   4.295 -            List<Type> restvars = inferenceContext.restvars();
   4.296 +            if (!allowGraphInference &&
   4.297 +                    inferenceContext.restvars().nonEmpty() &&
   4.298 +                    resultInfo != null &&
   4.299 +                    !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
   4.300 +                generateReturnConstraints(resultInfo, mt, inferenceContext);
   4.301 +                inferenceContext.solveLegacy(false, warn, LegacyInferenceSteps.EQ_UPPER.steps); //maximizeInst
   4.302 +                mt = (MethodType)inferenceContext.asInstType(mt);
   4.303 +            }
   4.304  
   4.305 -            if (!restvars.isEmpty()) {
   4.306 -                if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
   4.307 -                    if (!allowEarlyReturnConstraints) {
   4.308 -                        generateReturnConstraints(mt, inferenceContext, resultInfo);
   4.309 -                    }
   4.310 -                    instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
   4.311 -                    checkWithinBounds(inferenceContext, warn);
   4.312 -                    mt = (MethodType)inferenceContext.asInstType(mt);
   4.313 -                    if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
   4.314 -                        log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
   4.315 -                    }
   4.316 -                }
   4.317 +            if (resultInfo != null && rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) {
   4.318 +                log.note(env.tree.pos, "deferred.method.inst", msym, mt, resultInfo.pt);
   4.319              }
   4.320  
   4.321              // return instantiated version of method type
   4.322              return mt;
   4.323          } finally {
   4.324 -            inferenceContext.notifyChange();
   4.325 -        }
   4.326 -    }
   4.327 -    //where
   4.328 -        void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) {
   4.329 -            if (resultInfo != null) {
   4.330 -                Type to = resultInfo.pt;
   4.331 -                if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
   4.332 -                    to = mt.getReturnType().isPrimitiveOrVoid() ?
   4.333 -                            mt.getReturnType() : syms.objectType;
   4.334 -                }
   4.335 -                Type qtype1 = inferenceContext.asFree(mt.getReturnType());
   4.336 -                Warner retWarn = new Warner();
   4.337 -                if (!resultInfo.checkContext.compatible(qtype1, qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to, retWarn) ||
   4.338 -                        //unchecked conversion is not allowed
   4.339 -                        retWarn.hasLint(Lint.LintCategory.UNCHECKED)) {
   4.340 -                    throw inferenceException
   4.341 -                            .setMessage("infer.no.conforming.instance.exists",
   4.342 -                            inferenceContext.restvars(), mt.getReturnType(), to);
   4.343 -                }
   4.344 -            }
   4.345 -        }
   4.346 -
   4.347 -    /** check that type parameters are within their bounds.
   4.348 -     */
   4.349 -    void checkWithinBounds(InferenceContext inferenceContext,
   4.350 -                           Warner warn) throws InferenceException {
   4.351 -        //step 1 - check compatibility of instantiated type w.r.t. initial bounds
   4.352 -        for (Type t : inferenceContext.undetvars) {
   4.353 -            UndetVar uv = (UndetVar)t;
   4.354 -            uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
   4.355 -            checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
   4.356 -            if (!inferenceContext.restvars().contains(uv.qtype)) {
   4.357 -                Type inst = inferenceContext.asInstType(t);
   4.358 -                for (Type u : uv.getBounds(InferenceBound.UPPER)) {
   4.359 -                    if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u), warn)) {
   4.360 -                        reportBoundError(uv, BoundErrorKind.UPPER);
   4.361 -                    }
   4.362 -                }
   4.363 -                for (Type l : uv.getBounds(InferenceBound.LOWER)) {
   4.364 -                    Assert.check(!inferenceContext.free(l));
   4.365 -                    if (!types.isSubtypeUnchecked(l, inst, warn)) {
   4.366 -                        reportBoundError(uv, BoundErrorKind.LOWER);
   4.367 -                    }
   4.368 -                }
   4.369 -                for (Type e : uv.getBounds(InferenceBound.EQ)) {
   4.370 -                    Assert.check(!inferenceContext.free(e));
   4.371 -                    if (!types.isSameType(inst, e)) {
   4.372 -                        reportBoundError(uv, BoundErrorKind.EQ);
   4.373 -                    }
   4.374 -                }
   4.375 -            }
   4.376 -        }
   4.377 -
   4.378 -        //step 2 - check that eq bounds are consistent w.r.t. eq/lower bounds
   4.379 -        for (Type t : inferenceContext.undetvars) {
   4.380 -            UndetVar uv = (UndetVar)t;
   4.381 -            //check eq bounds consistency
   4.382 -            Type eq = null;
   4.383 -            for (Type e : uv.getBounds(InferenceBound.EQ)) {
   4.384 -                Assert.check(!inferenceContext.free(e));
   4.385 -                if (eq != null && !types.isSameType(e, eq)) {
   4.386 -                    reportBoundError(uv, BoundErrorKind.EQ);
   4.387 -                }
   4.388 -                eq = e;
   4.389 -                for (Type l : uv.getBounds(InferenceBound.LOWER)) {
   4.390 -                    Assert.check(!inferenceContext.free(l));
   4.391 -                    if (!types.isSubtypeUnchecked(l, e, warn)) {
   4.392 -                        reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER);
   4.393 -                    }
   4.394 -                }
   4.395 -                for (Type u : uv.getBounds(InferenceBound.UPPER)) {
   4.396 -                    if (inferenceContext.free(u)) continue;
   4.397 -                    if (!types.isSubtypeUnchecked(e, u, warn)) {
   4.398 -                        reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER);
   4.399 -                    }
   4.400 -                }
   4.401 +            if (resultInfo != null || !allowGraphInference) {
   4.402 +                inferenceContext.notifyChange();
   4.403 +            } else {
   4.404 +                inferenceContext.notifyChange(inferenceContext.boundedVars());
   4.405              }
   4.406          }
   4.407      }
   4.408  
   4.409 -    void checkCompatibleUpperBounds(UndetVar uv, List<Type> tvars) {
   4.410 -        // VGJ: sort of inlined maximizeInst() below.  Adding
   4.411 -        // bounds can cause lobounds that are above hibounds.
   4.412 -        ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
   4.413 -        for (Type t : Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter)) {
   4.414 -            if (!t.containsAny(tvars)) {
   4.415 -                hiboundsNoVars.append(t);
   4.416 +    /**
   4.417 +     * Generate constraints from the generic method's return type. If the method
   4.418 +     * call occurs in a context where a type T is expected, use the expected
   4.419 +     * type to derive more constraints on the generic method inference variables.
   4.420 +     */
   4.421 +    void generateReturnConstraints(Attr.ResultInfo resultInfo,
   4.422 +            MethodType mt, InferenceContext inferenceContext) {
   4.423 +        Type qtype1 = inferenceContext.asFree(mt.getReturnType());
   4.424 +        Type to = returnConstraintTarget(qtype1, resultInfo.pt);
   4.425 +        Assert.check(allowGraphInference || !resultInfo.checkContext.inferenceContext().free(to),
   4.426 +                "legacy inference engine cannot handle constraints on both sides of a subtyping assertion");
   4.427 +        //we need to skip capture?
   4.428 +        Warner retWarn = new Warner();
   4.429 +        if (!resultInfo.checkContext.compatible(qtype1, resultInfo.checkContext.inferenceContext().asFree(to), retWarn) ||
   4.430 +                //unchecked conversion is not allowed
   4.431 +                retWarn.hasLint(Lint.LintCategory.UNCHECKED)) {
   4.432 +            throw inferenceException
   4.433 +                    .setMessage("infer.no.conforming.instance.exists",
   4.434 +                    inferenceContext.restvars(), mt.getReturnType(), to);
   4.435 +        }
   4.436 +    }
   4.437 +    //where
   4.438 +        private Type returnConstraintTarget(Type from, Type to) {
   4.439 +            if (from.hasTag(VOID)) {
   4.440 +                return syms.voidType;
   4.441 +            } else if (to.hasTag(NONE)) {
   4.442 +                return from.isPrimitive() ? from : syms.objectType;
   4.443 +            } else if (from.hasTag(UNDETVAR) && to.isPrimitive()) {
   4.444 +                if (!allowGraphInference) {
   4.445 +                    //if legacy, just return boxed type
   4.446 +                    return types.boxedClass(to).type;
   4.447 +                }
   4.448 +                //if graph inference we need to skip conflicting boxed bounds...
   4.449 +                UndetVar uv = (UndetVar)from;
   4.450 +                for (Type t : uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)) {
   4.451 +                    Type boundAsPrimitive = types.unboxedType(t);
   4.452 +                    if (boundAsPrimitive == null) continue;
   4.453 +                    if (types.isConvertible(boundAsPrimitive, to)) {
   4.454 +                        //effectively skip return-type constraint generation (compatibility)
   4.455 +                        return syms.objectType;
   4.456 +                    }
   4.457 +                }
   4.458 +                return types.boxedClass(to).type;
   4.459 +            } else {
   4.460 +                return to;
   4.461              }
   4.462          }
   4.463 -        List<Type> hibounds = hiboundsNoVars.toList();
   4.464 -        Type hb = null;
   4.465 -        if (hibounds.isEmpty())
   4.466 -            hb = syms.objectType;
   4.467 -        else if (hibounds.tail.isEmpty())
   4.468 -            hb = hibounds.head;
   4.469 -        else
   4.470 -            hb = types.glb(hibounds);
   4.471 -        if (hb == null || hb.isErroneous())
   4.472 -            reportBoundError(uv, BoundErrorKind.BAD_UPPER);
   4.473 -    }
   4.474  
   4.475 -    enum BoundErrorKind {
   4.476 -        BAD_UPPER() {
   4.477 -            @Override
   4.478 -            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
   4.479 -                return ex.setMessage("incompatible.upper.bounds", uv.qtype,
   4.480 -                        uv.getBounds(InferenceBound.UPPER));
   4.481 +    /**
   4.482 +      * Infer cyclic inference variables as described in 15.12.2.8.
   4.483 +      */
   4.484 +    private void instantiateAsUninferredVars(List<Type> vars, InferenceContext inferenceContext) {
   4.485 +        ListBuffer<Type> todo = ListBuffer.lb();
   4.486 +        //step 1 - create fresh tvars
   4.487 +        for (Type t : vars) {
   4.488 +            UndetVar uv = (UndetVar)inferenceContext.asFree(t);
   4.489 +            List<Type> upperBounds = uv.getBounds(InferenceBound.UPPER);
   4.490 +            if (Type.containsAny(upperBounds, vars)) {
   4.491 +                TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
   4.492 +                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null);
   4.493 +                todo.append(uv);
   4.494 +                uv.inst = fresh_tvar.type;
   4.495 +            } else if (upperBounds.nonEmpty()) {
   4.496 +                uv.inst = types.glb(upperBounds);
   4.497 +            } else {
   4.498 +                uv.inst = syms.objectType;
   4.499              }
   4.500 -        },
   4.501 -        BAD_EQ_UPPER() {
   4.502 -            @Override
   4.503 -            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
   4.504 -                return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype,
   4.505 -                        uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER));
   4.506 +        }
   4.507 +        //step 2 - replace fresh tvars in their bounds
   4.508 +        List<Type> formals = vars;
   4.509 +        for (Type t : todo) {
   4.510 +            UndetVar uv = (UndetVar)t;
   4.511 +            TypeVar ct = (TypeVar)uv.inst;
   4.512 +            ct.bound = types.glb(inferenceContext.asInstTypes(types.getBounds(ct)));
   4.513 +            if (ct.bound.isErroneous()) {
   4.514 +                //report inference error if glb fails
   4.515 +                reportBoundError(uv, BoundErrorKind.BAD_UPPER);
   4.516              }
   4.517 -        },
   4.518 -        BAD_EQ_LOWER() {
   4.519 -            @Override
   4.520 -            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
   4.521 -                return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype,
   4.522 -                        uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER));
   4.523 -            }
   4.524 -        },
   4.525 -        UPPER() {
   4.526 -            @Override
   4.527 -            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
   4.528 -                return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst,
   4.529 -                        uv.getBounds(InferenceBound.UPPER));
   4.530 -            }
   4.531 -        },
   4.532 -        LOWER() {
   4.533 -            @Override
   4.534 -            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
   4.535 -                return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst,
   4.536 -                        uv.getBounds(InferenceBound.LOWER));
   4.537 -            }
   4.538 -        },
   4.539 -        EQ() {
   4.540 -            @Override
   4.541 -            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
   4.542 -                return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst,
   4.543 -                        uv.getBounds(InferenceBound.EQ));
   4.544 -            }
   4.545 -        };
   4.546 -
   4.547 -        abstract InapplicableMethodException setMessage(InferenceException ex, UndetVar uv);
   4.548 -    }
   4.549 -    //where
   4.550 -    void reportBoundError(UndetVar uv, BoundErrorKind bk) {
   4.551 -        throw bk.setMessage(inferenceException, uv);
   4.552 -    }
   4.553 -
   4.554 -    // <editor-fold desc="functional interface instantiation">
   4.555 -    /**
   4.556 -     * This method is used to infer a suitable target functional interface in case
   4.557 -     * the original parameterized interface contains wildcards. An inference process
   4.558 -     * is applied so that wildcard bounds, as well as explicit lambda/method ref parameters
   4.559 -     * (where applicable) are used to constraint the solution.
   4.560 -     */
   4.561 -    public Type instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface,
   4.562 -            List<Type> paramTypes, Check.CheckContext checkContext) {
   4.563 -        if (types.capture(funcInterface) == funcInterface) {
   4.564 -            //if capture doesn't change the type then return the target unchanged
   4.565 -            //(this means the target contains no wildcards!)
   4.566 -            return funcInterface;
   4.567 -        } else {
   4.568 -            Type formalInterface = funcInterface.tsym.type;
   4.569 -            InferenceContext funcInterfaceContext =
   4.570 -                    new InferenceContext(funcInterface.tsym.type.getTypeArguments());
   4.571 -            Assert.check(paramTypes != null);
   4.572 -            //get constraints from explicit params (this is done by
   4.573 -            //checking that explicit param types are equal to the ones
   4.574 -            //in the functional interface descriptors)
   4.575 -            List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
   4.576 -            if (descParameterTypes.size() != paramTypes.size()) {
   4.577 -                checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
   4.578 -                return types.createErrorType(funcInterface);
   4.579 -            }
   4.580 -            for (Type p : descParameterTypes) {
   4.581 -                if (!types.isSameType(funcInterfaceContext.asFree(p), paramTypes.head)) {
   4.582 -                    checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   4.583 -                    return types.createErrorType(funcInterface);
   4.584 -                }
   4.585 -                paramTypes = paramTypes.tail;
   4.586 -            }
   4.587 -            List<Type> actualTypeargs = funcInterface.getTypeArguments();
   4.588 -            for (Type t : funcInterfaceContext.undetvars) {
   4.589 -                UndetVar uv = (UndetVar)t;
   4.590 -                if (funcInterfaceContext.boundedVars().contains(uv.qtype)) {
   4.591 -                    minimizeInst(uv, types.noWarnings);
   4.592 -                    if (uv.inst == null &&
   4.593 -                            Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
   4.594 -                        maximizeInst(uv, types.noWarnings);
   4.595 -                    }
   4.596 -                } else {
   4.597 -                    uv.inst = actualTypeargs.head;
   4.598 -                }
   4.599 -                Assert.check(uv.inst != null);
   4.600 -                actualTypeargs = actualTypeargs.tail;
   4.601 -            }
   4.602 -            Type owntype = funcInterfaceContext.asInstType(formalInterface);
   4.603 -            if (!chk.checkValidGenericType(owntype)) {
   4.604 -                //if the inferred functional interface type is not well-formed,
   4.605 -                //or if it's not a subtype of the original target, issue an error
   4.606 -                checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   4.607 -            }
   4.608 -            return owntype;
   4.609 +            formals = formals.tail;
   4.610          }
   4.611      }
   4.612 -    // </editor-fold>
   4.613  
   4.614      /**
   4.615       * Compute a synthetic method type corresponding to the requested polymorphic
   4.616 @@ -573,7 +339,7 @@
   4.617          class ImplicitArgType extends DeferredAttr.DeferredTypeMap {
   4.618  
   4.619              public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) {
   4.620 -                deferredAttr.super(AttrMode.SPECULATIVE, msym, phase);
   4.621 +                rs.deferredAttr.super(AttrMode.SPECULATIVE, msym, phase);
   4.622              }
   4.623  
   4.624              public Type apply(Type t) {
   4.625 @@ -587,6 +353,920 @@
   4.626          }
   4.627  
   4.628      /**
   4.629 +      * This method is used to infer a suitable target SAM in case the original
   4.630 +      * SAM type contains one or more wildcards. An inference process is applied
   4.631 +      * so that wildcard bounds, as well as explicit lambda/method ref parameters
   4.632 +      * (where applicable) are used to constraint the solution.
   4.633 +      */
   4.634 +    public Type instantiateFunctionalInterface(DiagnosticPosition pos, Type funcInterface,
   4.635 +            List<Type> paramTypes, Check.CheckContext checkContext) {
   4.636 +        if (types.capture(funcInterface) == funcInterface) {
   4.637 +            //if capture doesn't change the type then return the target unchanged
   4.638 +            //(this means the target contains no wildcards!)
   4.639 +            return funcInterface;
   4.640 +        } else {
   4.641 +            Type formalInterface = funcInterface.tsym.type;
   4.642 +            InferenceContext funcInterfaceContext =
   4.643 +                    new InferenceContext(funcInterface.tsym.type.getTypeArguments());
   4.644 +
   4.645 +            Assert.check(paramTypes != null);
   4.646 +            //get constraints from explicit params (this is done by
   4.647 +            //checking that explicit param types are equal to the ones
   4.648 +            //in the functional interface descriptors)
   4.649 +            List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
   4.650 +            if (descParameterTypes.size() != paramTypes.size()) {
   4.651 +                checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
   4.652 +                return types.createErrorType(funcInterface);
   4.653 +            }
   4.654 +            for (Type p : descParameterTypes) {
   4.655 +                if (!types.isSameType(funcInterfaceContext.asFree(p), paramTypes.head)) {
   4.656 +                    checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   4.657 +                    return types.createErrorType(funcInterface);
   4.658 +                }
   4.659 +                paramTypes = paramTypes.tail;
   4.660 +            }
   4.661 +
   4.662 +            try {
   4.663 +                funcInterfaceContext.solve(funcInterfaceContext.boundedVars(), types.noWarnings);
   4.664 +            } catch (InferenceException ex) {
   4.665 +                checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   4.666 +            }
   4.667 +
   4.668 +            List<Type> actualTypeargs = funcInterface.getTypeArguments();
   4.669 +            for (Type t : funcInterfaceContext.undetvars) {
   4.670 +                UndetVar uv = (UndetVar)t;
   4.671 +                if (uv.inst == null) {
   4.672 +                    uv.inst = actualTypeargs.head;
   4.673 +                }
   4.674 +                actualTypeargs = actualTypeargs.tail;
   4.675 +            }
   4.676 +
   4.677 +            Type owntype = funcInterfaceContext.asInstType(formalInterface);
   4.678 +            if (!chk.checkValidGenericType(owntype)) {
   4.679 +                //if the inferred functional interface type is not well-formed,
   4.680 +                //or if it's not a subtype of the original target, issue an error
   4.681 +                checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
   4.682 +            }
   4.683 +            return owntype;
   4.684 +        }
   4.685 +    }
   4.686 +    // </editor-fold>
   4.687 +
   4.688 +    // <editor-fold defaultstate="collapsed" desc="Bound checking">
   4.689 +    /**
   4.690 +     * Check bounds and perform incorporation
   4.691 +     */
   4.692 +    void checkWithinBounds(InferenceContext inferenceContext,
   4.693 +                             Warner warn) throws InferenceException {
   4.694 +        MultiUndetVarListener mlistener = new MultiUndetVarListener(inferenceContext.undetvars);
   4.695 +        try {
   4.696 +            while (true) {
   4.697 +                mlistener.reset();
   4.698 +                if (!allowGraphInference) {
   4.699 +                    //in legacy mode we lack of transitivity, so bound check
   4.700 +                    //cannot be run in parallel with other incoprporation rounds
   4.701 +                    for (Type t : inferenceContext.undetvars) {
   4.702 +                        UndetVar uv = (UndetVar)t;
   4.703 +                        IncorporationStep.CHECK_BOUNDS.apply(uv, inferenceContext, warn);
   4.704 +                    }
   4.705 +                }
   4.706 +                for (Type t : inferenceContext.undetvars) {
   4.707 +                    UndetVar uv = (UndetVar)t;
   4.708 +                    //bound incorporation
   4.709 +                    EnumSet<IncorporationStep> incorporationSteps = allowGraphInference ?
   4.710 +                            incorporationStepsGraph : incorporationStepsLegacy;
   4.711 +                    for (IncorporationStep is : incorporationSteps) {
   4.712 +                        is.apply(uv, inferenceContext, warn);
   4.713 +                    }
   4.714 +                }
   4.715 +                if (!mlistener.changed || !allowGraphInference) break;
   4.716 +            }
   4.717 +        }
   4.718 +        finally {
   4.719 +            mlistener.detach();
   4.720 +        }
   4.721 +    }
   4.722 +    //where
   4.723 +        /**
   4.724 +         * This listener keeps track of changes on a group of inference variable
   4.725 +         * bounds. Note: the listener must be detached (calling corresponding
   4.726 +         * method) to make sure that the underlying inference variable is
   4.727 +         * left in a clean state.
   4.728 +         */
   4.729 +        class MultiUndetVarListener implements UndetVar.UndetVarListener {
   4.730 +
   4.731 +            int rounds;
   4.732 +            boolean changed;
   4.733 +            List<Type> undetvars;
   4.734 +
   4.735 +            public MultiUndetVarListener(List<Type> undetvars) {
   4.736 +                this.undetvars = undetvars;
   4.737 +                for (Type t : undetvars) {
   4.738 +                    UndetVar uv = (UndetVar)t;
   4.739 +                    uv.listener = this;
   4.740 +                }
   4.741 +            }
   4.742 +
   4.743 +            public void varChanged(UndetVar uv, Set<InferenceBound> ibs) {
   4.744 +                //avoid non-termination
   4.745 +                if (rounds < MAX_INCORPORATION_STEPS) {
   4.746 +                    changed = true;
   4.747 +                }
   4.748 +            }
   4.749 +
   4.750 +            void reset() {
   4.751 +                rounds++;
   4.752 +                changed = false;
   4.753 +            }
   4.754 +
   4.755 +            void detach() {
   4.756 +                for (Type t : undetvars) {
   4.757 +                    UndetVar uv = (UndetVar)t;
   4.758 +                    uv.listener = null;
   4.759 +                }
   4.760 +            }
   4.761 +        };
   4.762 +
   4.763 +        /** max number of incorporation rounds */
   4.764 +        static final int MAX_INCORPORATION_STEPS = 100;
   4.765 +
   4.766 +    /**
   4.767 +     * This enumeration defines an entry point for doing inference variable
   4.768 +     * bound incorporation - it can be used to inject custom incorporation
   4.769 +     * logic into the basic bound checking routine
   4.770 +     */
   4.771 +    enum IncorporationStep {
   4.772 +        /**
   4.773 +         * Performs basic bound checking - i.e. is the instantiated type for a given
   4.774 +         * inference variable compatible with its bounds?
   4.775 +         */
   4.776 +        CHECK_BOUNDS() {
   4.777 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.778 +                Infer infer = inferenceContext.infer();
   4.779 +                uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), infer.types);
   4.780 +                infer.checkCompatibleUpperBounds(uv, inferenceContext);
   4.781 +                if (uv.inst != null) {
   4.782 +                    Type inst = uv.inst;
   4.783 +                    for (Type u : uv.getBounds(InferenceBound.UPPER)) {
   4.784 +                        if (!infer.types.isSubtypeUnchecked(inst, inferenceContext.asFree(u), warn)) {
   4.785 +                            infer.reportBoundError(uv, BoundErrorKind.UPPER);
   4.786 +                        }
   4.787 +                    }
   4.788 +                    for (Type l : uv.getBounds(InferenceBound.LOWER)) {
   4.789 +                        if (!infer.types.isSubtypeUnchecked(inferenceContext.asFree(l), inst, warn)) {
   4.790 +                            infer.reportBoundError(uv, BoundErrorKind.LOWER);
   4.791 +                        }
   4.792 +                    }
   4.793 +                    for (Type e : uv.getBounds(InferenceBound.EQ)) {
   4.794 +                        if (!infer.types.isSameType(inst, inferenceContext.asFree(e))) {
   4.795 +                            infer.reportBoundError(uv, BoundErrorKind.EQ);
   4.796 +                        }
   4.797 +                    }
   4.798 +                }
   4.799 +            }
   4.800 +        },
   4.801 +        /**
   4.802 +         * Check consistency of equality constraints. This is a slightly more aggressive
   4.803 +         * inference routine that is designed as to maximize compatibility with JDK 7.
   4.804 +         * Note: this is not used in graph mode.
   4.805 +         */
   4.806 +        EQ_CHECK_LEGACY() {
   4.807 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.808 +                Infer infer = inferenceContext.infer();
   4.809 +                Type eq = null;
   4.810 +                for (Type e : uv.getBounds(InferenceBound.EQ)) {
   4.811 +                    Assert.check(!inferenceContext.free(e));
   4.812 +                    if (eq != null && !infer.types.isSameType(e, eq)) {
   4.813 +                        infer.reportBoundError(uv, BoundErrorKind.EQ);
   4.814 +                    }
   4.815 +                    eq = e;
   4.816 +                    for (Type l : uv.getBounds(InferenceBound.LOWER)) {
   4.817 +                        Assert.check(!inferenceContext.free(l));
   4.818 +                        if (!infer.types.isSubtypeUnchecked(l, e, warn)) {
   4.819 +                            infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER);
   4.820 +                        }
   4.821 +                    }
   4.822 +                    for (Type u : uv.getBounds(InferenceBound.UPPER)) {
   4.823 +                        if (inferenceContext.free(u)) continue;
   4.824 +                        if (!infer.types.isSubtypeUnchecked(e, u, warn)) {
   4.825 +                            infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER);
   4.826 +                        }
   4.827 +                    }
   4.828 +                }
   4.829 +            }
   4.830 +        },
   4.831 +        /**
   4.832 +         * Check consistency of equality constraints.
   4.833 +         */
   4.834 +        EQ_CHECK() {
   4.835 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.836 +                Infer infer = inferenceContext.infer();
   4.837 +                for (Type e : uv.getBounds(InferenceBound.EQ)) {
   4.838 +                    if (e.containsAny(inferenceContext.inferenceVars())) continue;
   4.839 +                    for (Type u : uv.getBounds(InferenceBound.UPPER)) {
   4.840 +                        if (!infer.types.isSubtypeUnchecked(e, inferenceContext.asFree(u), warn)) {
   4.841 +                            infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER);
   4.842 +                        }
   4.843 +                    }
   4.844 +                    for (Type l : uv.getBounds(InferenceBound.LOWER)) {
   4.845 +                        if (!infer.types.isSubtypeUnchecked(inferenceContext.asFree(l), e, warn)) {
   4.846 +                            infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER);
   4.847 +                        }
   4.848 +                    }
   4.849 +                }
   4.850 +            }
   4.851 +        },
   4.852 +        /**
   4.853 +         * Given a bound set containing {@code alpha <: T} and {@code alpha :> S}
   4.854 +         * perform {@code S <: T} (which could lead to new bounds).
   4.855 +         */
   4.856 +        CROSS_UPPER_LOWER() {
   4.857 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.858 +                Infer infer = inferenceContext.infer();
   4.859 +                for (Type b1 : uv.getBounds(InferenceBound.UPPER)) {
   4.860 +                    for (Type b2 : uv.getBounds(InferenceBound.LOWER)) {
   4.861 +                        if (!inferenceContext.inferenceVars().contains(b1) &&
   4.862 +                                !inferenceContext.inferenceVars().contains(b2) &&
   4.863 +                                infer.types.asSuper(b2, b1.tsym) != null) {
   4.864 +                            infer.types.isSubtypeUnchecked(inferenceContext.asFree(b2), inferenceContext.asFree(b1));
   4.865 +                        }
   4.866 +                    }
   4.867 +                }
   4.868 +            }
   4.869 +        },
   4.870 +        /**
   4.871 +         * Given a bound set containing {@code alpha <: T} and {@code alpha == S}
   4.872 +         * perform {@code S <: T} (which could lead to new bounds).
   4.873 +         */
   4.874 +        CROSS_UPPER_EQ() {
   4.875 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.876 +                Infer infer = inferenceContext.infer();
   4.877 +                for (Type b1 : uv.getBounds(InferenceBound.UPPER)) {
   4.878 +                    for (Type b2 : uv.getBounds(InferenceBound.EQ)) {
   4.879 +                        if (!inferenceContext.inferenceVars().contains(b1) &&
   4.880 +                                !inferenceContext.inferenceVars().contains(b2) &&
   4.881 +                                infer.types.asSuper(b2, b1.tsym) != null) {
   4.882 +                            infer.types.isSubtypeUnchecked(inferenceContext.asFree(b2), inferenceContext.asFree(b1));
   4.883 +                        }
   4.884 +                    }
   4.885 +                }
   4.886 +            }
   4.887 +        },
   4.888 +        /**
   4.889 +         * Given a bound set containing {@code alpha :> S} and {@code alpha == T}
   4.890 +         * perform {@code S <: T} (which could lead to new bounds).
   4.891 +         */
   4.892 +        CROSS_EQ_LOWER() {
   4.893 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.894 +                Infer infer = inferenceContext.infer();
   4.895 +                for (Type b1 : uv.getBounds(InferenceBound.EQ)) {
   4.896 +                    for (Type b2 : uv.getBounds(InferenceBound.LOWER)) {
   4.897 +                        if (!inferenceContext.inferenceVars().contains(b1) &&
   4.898 +                                !inferenceContext.inferenceVars().contains(b2) &&
   4.899 +                                infer.types.asSuper(b2, b1.tsym) != null) {
   4.900 +                            infer.types.isSubtypeUnchecked(inferenceContext.asFree(b2), inferenceContext.asFree(b1));
   4.901 +                        }
   4.902 +                    }
   4.903 +                }
   4.904 +            }
   4.905 +        },
   4.906 +        /**
   4.907 +         * Given a bound set containing {@code alpha <: beta} propagate lower bounds
   4.908 +         * from alpha to beta; also propagate upper bounds from beta to alpha.
   4.909 +         */
   4.910 +        PROP_UPPER() {
   4.911 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.912 +                Infer infer = inferenceContext.infer();
   4.913 +                for (Type b : uv.getBounds(InferenceBound.UPPER)) {
   4.914 +                    if (inferenceContext.inferenceVars().contains(b)) {
   4.915 +                        UndetVar uv2 = (UndetVar)inferenceContext.asFree(b);
   4.916 +                        //alpha <: beta
   4.917 +                        //1. copy alpha's lower to beta's
   4.918 +                        for (Type l : uv.getBounds(InferenceBound.LOWER)) {
   4.919 +                            uv2.addBound(InferenceBound.LOWER, inferenceContext.asInstType(l), infer.types);
   4.920 +                        }
   4.921 +                        //2. copy beta's upper to alpha's
   4.922 +                        for (Type u : uv2.getBounds(InferenceBound.UPPER)) {
   4.923 +                            uv.addBound(InferenceBound.UPPER, inferenceContext.asInstType(u), infer.types);
   4.924 +                        }
   4.925 +                    }
   4.926 +                }
   4.927 +            }
   4.928 +        },
   4.929 +        /**
   4.930 +         * Given a bound set containing {@code alpha :> beta} propagate lower bounds
   4.931 +         * from beta to alpha; also propagate upper bounds from alpha to beta.
   4.932 +         */
   4.933 +        PROP_LOWER() {
   4.934 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.935 +                Infer infer = inferenceContext.infer();
   4.936 +                for (Type b : uv.getBounds(InferenceBound.LOWER)) {
   4.937 +                    if (inferenceContext.inferenceVars().contains(b)) {
   4.938 +                        UndetVar uv2 = (UndetVar)inferenceContext.asFree(b);
   4.939 +                        //alpha :> beta
   4.940 +                        //1. copy alpha's upper to beta's
   4.941 +                        for (Type u : uv.getBounds(InferenceBound.UPPER)) {
   4.942 +                            uv2.addBound(InferenceBound.UPPER, inferenceContext.asInstType(u), infer.types);
   4.943 +                        }
   4.944 +                        //2. copy beta's lower to alpha's
   4.945 +                        for (Type l : uv2.getBounds(InferenceBound.LOWER)) {
   4.946 +                            uv.addBound(InferenceBound.LOWER, inferenceContext.asInstType(l), infer.types);
   4.947 +                        }
   4.948 +                    }
   4.949 +                }
   4.950 +            }
   4.951 +        },
   4.952 +        /**
   4.953 +         * Given a bound set containing {@code alpha == beta} propagate lower/upper
   4.954 +         * bounds from alpha to beta and back.
   4.955 +         */
   4.956 +        PROP_EQ() {
   4.957 +            public void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn) {
   4.958 +                Infer infer = inferenceContext.infer();
   4.959 +                for (Type b : uv.getBounds(InferenceBound.EQ)) {
   4.960 +                    if (inferenceContext.inferenceVars().contains(b)) {
   4.961 +                        UndetVar uv2 = (UndetVar)inferenceContext.asFree(b);
   4.962 +                        //alpha == beta
   4.963 +                        //1. copy all alpha's bounds to beta's
   4.964 +                        for (InferenceBound ib : InferenceBound.values()) {
   4.965 +                            for (Type b2 : uv.getBounds(ib)) {
   4.966 +                                if (b2 != uv2) {
   4.967 +                                    uv2.addBound(ib, inferenceContext.asInstType(b2), infer.types);
   4.968 +                                }
   4.969 +                            }
   4.970 +                        }
   4.971 +                        //2. copy all beta's bounds to alpha's
   4.972 +                        for (InferenceBound ib : InferenceBound.values()) {
   4.973 +                            for (Type b2 : uv2.getBounds(ib)) {
   4.974 +                                if (b2 != uv) {
   4.975 +                                    uv.addBound(ib, inferenceContext.asInstType(b2), infer.types);
   4.976 +                                }
   4.977 +                            }
   4.978 +                        }
   4.979 +                    }
   4.980 +                }
   4.981 +            }
   4.982 +        };
   4.983 +
   4.984 +        abstract void apply(UndetVar uv, InferenceContext inferenceContext, Warner warn);
   4.985 +    }
   4.986 +
   4.987 +    /** incorporation steps to be executed when running in legacy mode */
   4.988 +    EnumSet<IncorporationStep> incorporationStepsLegacy = EnumSet.of(IncorporationStep.EQ_CHECK_LEGACY);
   4.989 +
   4.990 +    /** incorporation steps to be executed when running in graph mode */
   4.991 +    EnumSet<IncorporationStep> incorporationStepsGraph =
   4.992 +            EnumSet.complementOf(EnumSet.of(IncorporationStep.EQ_CHECK_LEGACY));
   4.993 +
   4.994 +    /**
   4.995 +     * Make sure that the upper bounds we got so far lead to a solvable inference
   4.996 +     * variable by making sure that a glb exists.
   4.997 +     */
   4.998 +    void checkCompatibleUpperBounds(UndetVar uv, InferenceContext inferenceContext) {
   4.999 +        List<Type> hibounds =
  4.1000 +                Type.filter(uv.getBounds(InferenceBound.UPPER), new BoundFilter(inferenceContext));
  4.1001 +        Type hb = null;
  4.1002 +        if (hibounds.isEmpty())
  4.1003 +            hb = syms.objectType;
  4.1004 +        else if (hibounds.tail.isEmpty())
  4.1005 +            hb = hibounds.head;
  4.1006 +        else
  4.1007 +            hb = types.glb(hibounds);
  4.1008 +        if (hb == null || hb.isErroneous())
  4.1009 +            reportBoundError(uv, BoundErrorKind.BAD_UPPER);
  4.1010 +    }
  4.1011 +    //where
  4.1012 +        protected static class BoundFilter implements Filter<Type> {
  4.1013 +
  4.1014 +            InferenceContext inferenceContext;
  4.1015 +
  4.1016 +            public BoundFilter(InferenceContext inferenceContext) {
  4.1017 +                this.inferenceContext = inferenceContext;
  4.1018 +            }
  4.1019 +
  4.1020 +            @Override
  4.1021 +            public boolean accepts(Type t) {
  4.1022 +                return !t.isErroneous() && !inferenceContext.free(t) &&
  4.1023 +                        !t.hasTag(BOT);
  4.1024 +            }
  4.1025 +        };
  4.1026 +
  4.1027 +    /**
  4.1028 +     * This enumeration defines all possible bound-checking related errors.
  4.1029 +     */
  4.1030 +    enum BoundErrorKind {
  4.1031 +        /**
  4.1032 +         * The (uninstantiated) inference variable has incompatible upper bounds.
  4.1033 +         */
  4.1034 +        BAD_UPPER() {
  4.1035 +            @Override
  4.1036 +            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
  4.1037 +                return ex.setMessage("incompatible.upper.bounds", uv.qtype,
  4.1038 +                        uv.getBounds(InferenceBound.UPPER));
  4.1039 +            }
  4.1040 +        },
  4.1041 +        /**
  4.1042 +         * An equality constraint is not compatible with an upper bound.
  4.1043 +         */
  4.1044 +        BAD_EQ_UPPER() {
  4.1045 +            @Override
  4.1046 +            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
  4.1047 +                return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype,
  4.1048 +                        uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER));
  4.1049 +            }
  4.1050 +        },
  4.1051 +        /**
  4.1052 +         * An equality constraint is not compatible with a lower bound.
  4.1053 +         */
  4.1054 +        BAD_EQ_LOWER() {
  4.1055 +            @Override
  4.1056 +            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
  4.1057 +                return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype,
  4.1058 +                        uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER));
  4.1059 +            }
  4.1060 +        },
  4.1061 +        /**
  4.1062 +         * Instantiated inference variable is not compatible with an upper bound.
  4.1063 +         */
  4.1064 +        UPPER() {
  4.1065 +            @Override
  4.1066 +            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
  4.1067 +                return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst,
  4.1068 +                        uv.getBounds(InferenceBound.UPPER));
  4.1069 +            }
  4.1070 +        },
  4.1071 +        /**
  4.1072 +         * Instantiated inference variable is not compatible with a lower bound.
  4.1073 +         */
  4.1074 +        LOWER() {
  4.1075 +            @Override
  4.1076 +            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
  4.1077 +                return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst,
  4.1078 +                        uv.getBounds(InferenceBound.LOWER));
  4.1079 +            }
  4.1080 +        },
  4.1081 +        /**
  4.1082 +         * Instantiated inference variable is not compatible with an equality constraint.
  4.1083 +         */
  4.1084 +        EQ() {
  4.1085 +            @Override
  4.1086 +            InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
  4.1087 +                return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst,
  4.1088 +                        uv.getBounds(InferenceBound.EQ));
  4.1089 +            }
  4.1090 +        };
  4.1091 +
  4.1092 +        abstract InapplicableMethodException setMessage(InferenceException ex, UndetVar uv);
  4.1093 +    }
  4.1094 +
  4.1095 +    /**
  4.1096 +     * Report a bound-checking error of given kind
  4.1097 +     */
  4.1098 +    void reportBoundError(UndetVar uv, BoundErrorKind bk) {
  4.1099 +        throw bk.setMessage(inferenceException, uv);
  4.1100 +    }
  4.1101 +    // </editor-fold>
  4.1102 +
  4.1103 +    // <editor-fold defaultstate="collapsed" desc="Inference engine">
  4.1104 +    /**
  4.1105 +     * Graph inference strategy - act as an input to the inference solver; a strategy is
  4.1106 +     * composed of two ingredients: (i) find a node to solve in the inference graph,
  4.1107 +     * and (ii) tell th engine when we are done fixing inference variables
  4.1108 +     */
  4.1109 +    interface GraphStrategy {
  4.1110 +        /**
  4.1111 +         * Pick the next node (leaf) to solve in the graph
  4.1112 +         */
  4.1113 +        Node pickNode(InferenceGraph g);
  4.1114 +        /**
  4.1115 +         * Is this the last step?
  4.1116 +         */
  4.1117 +        boolean done();
  4.1118 +    }
  4.1119 +
  4.1120 +    /**
  4.1121 +     * Simple solver strategy class that locates all leaves inside a graph
  4.1122 +     * and picks the first leaf as the next node to solve
  4.1123 +     */
  4.1124 +    abstract class LeafSolver implements GraphStrategy {
  4.1125 +        public Node pickNode(InferenceGraph g) {
  4.1126 +                        Assert.check(!g.nodes.isEmpty(), "No nodes to solve!");
  4.1127 +            return g.nodes.get(0);
  4.1128 +        }
  4.1129 +    }
  4.1130 +
  4.1131 +    /**
  4.1132 +     * This solver uses an heuristic to pick the best leaf - the heuristic
  4.1133 +     * tries to select the node that has maximal probability to contain one
  4.1134 +     * or more inference variables in a given list
  4.1135 +     */
  4.1136 +    abstract class BestLeafSolver extends LeafSolver {
  4.1137 +
  4.1138 +        List<Type> varsToSolve;
  4.1139 +
  4.1140 +        BestLeafSolver(List<Type> varsToSolve) {
  4.1141 +            this.varsToSolve = varsToSolve;
  4.1142 +        }
  4.1143 +
  4.1144 +        /**
  4.1145 +         * Computes the cost associated with a given node; the cost is computed
  4.1146 +         * as the total number of type-variables that should be eagerly instantiated
  4.1147 +         * in order to get to some of the variables in {@code varsToSolve} from
  4.1148 +         * a given node
  4.1149 +         */
  4.1150 +        void computeCostIfNeeded(Node n, Map<Node, Integer> costMap) {
  4.1151 +            if (costMap.containsKey(n)) {
  4.1152 +                return;
  4.1153 +            } else if (!Collections.disjoint(n.data, varsToSolve)) {
  4.1154 +                costMap.put(n, n.data.size());
  4.1155 +            } else {
  4.1156 +                int subcost = Integer.MAX_VALUE;
  4.1157 +                costMap.put(n, subcost); //avoid loops
  4.1158 +                for (Node n2 : n.getDependencies()) {
  4.1159 +                    computeCostIfNeeded(n2, costMap);
  4.1160 +                    subcost = Math.min(costMap.get(n2), subcost);
  4.1161 +                }
  4.1162 +                //update cost map to reflect real cost
  4.1163 +                costMap.put(n, subcost == Integer.MAX_VALUE ?
  4.1164 +                        Integer.MAX_VALUE :
  4.1165 +                        n.data.size() + subcost);
  4.1166 +            }
  4.1167 +        }
  4.1168 +
  4.1169 +        /**
  4.1170 +         * Pick the leaf that minimize cost
  4.1171 +         */
  4.1172 +        @Override
  4.1173 +        public Node pickNode(final InferenceGraph g) {
  4.1174 +            final Map<Node, Integer> costMap = new HashMap<Node, Integer>();
  4.1175 +            ArrayList<Node> leaves = new ArrayList<Node>();
  4.1176 +            for (Node n : g.nodes) {
  4.1177 +                computeCostIfNeeded(n, costMap);
  4.1178 +                if (n.isLeaf(n)) {
  4.1179 +                    leaves.add(n);
  4.1180 +                }
  4.1181 +            }
  4.1182 +            Assert.check(!leaves.isEmpty(), "No nodes to solve!");
  4.1183 +            Collections.sort(leaves, new java.util.Comparator<Node>() {
  4.1184 +                public int compare(Node n1, Node n2) {
  4.1185 +                    return costMap.get(n1) - costMap.get(n2);
  4.1186 +                }
  4.1187 +            });
  4.1188 +            return leaves.get(0);
  4.1189 +        }
  4.1190 +    }
  4.1191 +
  4.1192 +    /**
  4.1193 +     * The inference process can be thought of as a sequence of steps. Each step
  4.1194 +     * instantiates an inference variable using a subset of the inference variable
  4.1195 +     * bounds, if certain condition are met. Decisions such as the sequence in which
  4.1196 +     * steps are applied, or which steps are to be applied are left to the inference engine.
  4.1197 +     */
  4.1198 +    enum InferenceStep {
  4.1199 +
  4.1200 +        /**
  4.1201 +         * Instantiate an inference variables using one of its (ground) equality
  4.1202 +         * constraints
  4.1203 +         */
  4.1204 +        EQ(InferenceBound.EQ) {
  4.1205 +            @Override
  4.1206 +            Type solve(UndetVar uv, InferenceContext inferenceContext) {
  4.1207 +                return filterBounds(uv, inferenceContext).head;
  4.1208 +            }
  4.1209 +        },
  4.1210 +        /**
  4.1211 +         * Instantiate an inference variables using its (ground) lower bounds. Such
  4.1212 +         * bounds are merged together using lub().
  4.1213 +         */
  4.1214 +        LOWER(InferenceBound.LOWER) {
  4.1215 +            @Override
  4.1216 +            Type solve(UndetVar uv, InferenceContext inferenceContext) {
  4.1217 +                Infer infer = inferenceContext.infer();
  4.1218 +                List<Type> lobounds = filterBounds(uv, inferenceContext);
  4.1219 +                Type owntype = infer.types.lub(lobounds);
  4.1220 +                if (owntype.hasTag(ERROR)) {
  4.1221 +                    throw infer.inferenceException
  4.1222 +                        .setMessage("no.unique.minimal.instance.exists",
  4.1223 +                                    uv.qtype, lobounds);
  4.1224 +                } else {
  4.1225 +                    return owntype;
  4.1226 +                }
  4.1227 +            }
  4.1228 +        },
  4.1229 +        /**
  4.1230 +         * Instantiate an inference variables using its (ground) upper bounds. Such
  4.1231 +         * bounds are merged together using glb().
  4.1232 +         */
  4.1233 +        UPPER(InferenceBound.UPPER) {
  4.1234 +            @Override
  4.1235 +            Type solve(UndetVar uv, InferenceContext inferenceContext) {
  4.1236 +                Infer infer = inferenceContext.infer();
  4.1237 +                List<Type> hibounds = filterBounds(uv, inferenceContext);
  4.1238 +                Type owntype = infer.types.glb(hibounds);
  4.1239 +                if (owntype.isErroneous()) {
  4.1240 +                    throw infer.inferenceException
  4.1241 +                        .setMessage("no.unique.maximal.instance.exists",
  4.1242 +                                    uv.qtype, hibounds);
  4.1243 +                } else {
  4.1244 +                    return owntype;
  4.1245 +                }
  4.1246 +            }
  4.1247 +        },
  4.1248 +        /**
  4.1249 +         * Like the former; the only difference is that this step can only be applied
  4.1250 +         * if all upper bounds are ground.
  4.1251 +         */
  4.1252 +        UPPER_LEGACY(InferenceBound.UPPER) {
  4.1253 +            @Override
  4.1254 +            public boolean accepts(UndetVar t, InferenceContext inferenceContext) {
  4.1255 +                return !inferenceContext.free(t.getBounds(ib));
  4.1256 +            }
  4.1257 +
  4.1258 +            @Override
  4.1259 +            Type solve(UndetVar uv, InferenceContext inferenceContext) {
  4.1260 +                return UPPER.solve(uv, inferenceContext);
  4.1261 +            }
  4.1262 +        };
  4.1263 +
  4.1264 +        final InferenceBound ib;
  4.1265 +
  4.1266 +        InferenceStep(InferenceBound ib) {
  4.1267 +            this.ib = ib;
  4.1268 +        }
  4.1269 +
  4.1270 +        /**
  4.1271 +         * Find an instantiated type for a given inference variable within
  4.1272 +         * a given inference context
  4.1273 +         */
  4.1274 +        abstract Type solve(UndetVar uv, InferenceContext inferenceContext);
  4.1275 +
  4.1276 +        /**
  4.1277 +         * Can the inference variable be instantiated using this step?
  4.1278 +         */
  4.1279 +        public boolean accepts(UndetVar t, InferenceContext inferenceContext) {
  4.1280 +            return filterBounds(t, inferenceContext).nonEmpty();
  4.1281 +        }
  4.1282 +
  4.1283 +        /**
  4.1284 +         * Return the subset of ground bounds in a given bound set (i.e. eq/lower/upper)
  4.1285 +         */
  4.1286 +        List<Type> filterBounds(UndetVar uv, InferenceContext inferenceContext) {
  4.1287 +            return Type.filter(uv.getBounds(ib), new BoundFilter(inferenceContext));
  4.1288 +        }
  4.1289 +    }
  4.1290 +
  4.1291 +    /**
  4.1292 +     * This enumeration defines the sequence of steps to be applied when the
  4.1293 +     * solver works in legacy mode. The steps in this enumeration reflect
  4.1294 +     * the behavior of old inference routine (see JLS SE 7 15.12.2.7/15.12.2.8).
  4.1295 +     */
  4.1296 +    enum LegacyInferenceSteps {
  4.1297 +
  4.1298 +        EQ_LOWER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER)),
  4.1299 +        EQ_UPPER(EnumSet.of(InferenceStep.EQ, InferenceStep.UPPER_LEGACY));
  4.1300 +
  4.1301 +        final EnumSet<InferenceStep> steps;
  4.1302 +
  4.1303 +        LegacyInferenceSteps(EnumSet<InferenceStep> steps) {
  4.1304 +            this.steps = steps;
  4.1305 +        }
  4.1306 +    }
  4.1307 +
  4.1308 +    /**
  4.1309 +     * This enumeration defines the sequence of steps to be applied when the
  4.1310 +     * graph solver is used. This order is defined so as to maximize compatibility
  4.1311 +     * w.r.t. old inference routine (see JLS SE 7 15.12.2.7/15.12.2.8).
  4.1312 +     */
  4.1313 +    enum GraphInferenceSteps {
  4.1314 +
  4.1315 +        EQ(EnumSet.of(InferenceStep.EQ)),
  4.1316 +        EQ_LOWER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER)),
  4.1317 +        EQ_LOWER_UPPER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER, InferenceStep.UPPER));
  4.1318 +
  4.1319 +        final EnumSet<InferenceStep> steps;
  4.1320 +
  4.1321 +        GraphInferenceSteps(EnumSet<InferenceStep> steps) {
  4.1322 +            this.steps = steps;
  4.1323 +        }
  4.1324 +    }
  4.1325 +
  4.1326 +    /**
  4.1327 +     * This is the graph inference solver - the solver organizes all inference variables in
  4.1328 +     * a given inference context by bound dependencies - in the general case, such dependencies
  4.1329 +     * would lead to a cyclic directed graph (hence the name); the dependency info is used to build
  4.1330 +     * an acyclic graph, where all cyclic variables are bundled together. An inference
  4.1331 +     * step corresponds to solving a node in the acyclic graph - this is done by
  4.1332 +     * relying on a given strategy (see GraphStrategy).
  4.1333 +     */
  4.1334 +    class GraphSolver {
  4.1335 +
  4.1336 +        InferenceContext inferenceContext;
  4.1337 +        Warner warn;
  4.1338 +
  4.1339 +        GraphSolver(InferenceContext inferenceContext, Warner warn) {
  4.1340 +            this.inferenceContext = inferenceContext;
  4.1341 +            this.warn = warn;
  4.1342 +        }
  4.1343 +
  4.1344 +        /**
  4.1345 +         * Solve variables in a given inference context. The amount of variables
  4.1346 +         * to be solved, and the way in which the underlying acyclic graph is explored
  4.1347 +         * depends on the selected solver strategy.
  4.1348 +         */
  4.1349 +        void solve(GraphStrategy sstrategy) {
  4.1350 +            checkWithinBounds(inferenceContext, warn); //initial propagation of bounds
  4.1351 +            InferenceGraph inferenceGraph = new InferenceGraph();
  4.1352 +            while (!sstrategy.done()) {
  4.1353 +                InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph);
  4.1354 +                List<Type> varsToSolve = List.from(nodeToSolve.data);
  4.1355 +                inferenceContext.save();
  4.1356 +                try {
  4.1357 +                    //repeat until all variables are solved
  4.1358 +                    outer: while (Type.containsAny(inferenceContext.restvars(), varsToSolve)) {
  4.1359 +                        //for each inference phase
  4.1360 +                        for (GraphInferenceSteps step : GraphInferenceSteps.values()) {
  4.1361 +                            if (inferenceContext.solveBasic(varsToSolve, step.steps)) {
  4.1362 +                                checkWithinBounds(inferenceContext, warn);
  4.1363 +                                continue outer;
  4.1364 +                            }
  4.1365 +                        }
  4.1366 +                        //no progress
  4.1367 +                        throw inferenceException;
  4.1368 +                    }
  4.1369 +                }
  4.1370 +                catch (InferenceException ex) {
  4.1371 +                    inferenceContext.rollback();
  4.1372 +                    instantiateAsUninferredVars(varsToSolve, inferenceContext);
  4.1373 +                    checkWithinBounds(inferenceContext, warn);
  4.1374 +                }
  4.1375 +                inferenceGraph.deleteNode(nodeToSolve);
  4.1376 +            }
  4.1377 +        }
  4.1378 +
  4.1379 +        /**
  4.1380 +         * The dependencies between the inference variables that need to be solved
  4.1381 +         * form a (possibly cyclic) graph. This class reduces the original dependency graph
  4.1382 +         * to an acyclic version, where cyclic nodes are folded into a single 'super node'.
  4.1383 +         */
  4.1384 +        class InferenceGraph {
  4.1385 +
  4.1386 +            /**
  4.1387 +             * This class represents a node in the graph. Each node corresponds
  4.1388 +             * to an inference variable and has edges (dependencies) on other
  4.1389 +             * nodes. The node defines an entry point that can be used to receive
  4.1390 +             * updates on the structure of the graph this node belongs to (used to
  4.1391 +             * keep dependencies in sync).
  4.1392 +             */
  4.1393 +            class Node extends GraphUtils.TarjanNode<ListBuffer<Type>> {
  4.1394 +
  4.1395 +                Set<Node> deps;
  4.1396 +
  4.1397 +                Node(Type ivar) {
  4.1398 +                    super(ListBuffer.of(ivar));
  4.1399 +                    this.deps = new HashSet<Node>();
  4.1400 +                }
  4.1401 +
  4.1402 +                @Override
  4.1403 +                public Iterable<? extends Node> getDependencies() {
  4.1404 +                    return deps;
  4.1405 +                }
  4.1406 +
  4.1407 +                @Override
  4.1408 +                public String printDependency(GraphUtils.Node<ListBuffer<Type>> to) {
  4.1409 +                    StringBuilder buf = new StringBuilder();
  4.1410 +                    String sep = "";
  4.1411 +                    for (Type from : data) {
  4.1412 +                        UndetVar uv = (UndetVar)inferenceContext.asFree(from);
  4.1413 +                        for (Type bound : uv.getBounds(InferenceBound.values())) {
  4.1414 +                            if (bound.containsAny(List.from(to.data))) {
  4.1415 +                                buf.append(sep);
  4.1416 +                                buf.append(bound);
  4.1417 +                                sep = ",";
  4.1418 +                            }
  4.1419 +                        }
  4.1420 +                    }
  4.1421 +                    return buf.toString();
  4.1422 +                }
  4.1423 +
  4.1424 +                boolean isLeaf(Node n) {
  4.1425 +                    //no deps, or only one self dep
  4.1426 +                    return (n.deps.isEmpty() ||
  4.1427 +                            n.deps.size() == 1 && n.deps.contains(n));
  4.1428 +                }
  4.1429 +
  4.1430 +                void mergeWith(List<? extends Node> nodes) {
  4.1431 +                    for (Node n : nodes) {
  4.1432 +                        Assert.check(n.data.length() == 1, "Attempt to merge a compound node!");
  4.1433 +                        data.appendList(n.data);
  4.1434 +                        deps.addAll(n.deps);
  4.1435 +                    }
  4.1436 +                    //update deps
  4.1437 +                    Set<Node> deps2 = new HashSet<Node>();
  4.1438 +                    for (Node d : deps) {
  4.1439 +                        if (data.contains(d.data.first())) {
  4.1440 +                            deps2.add(this);
  4.1441 +                        } else {
  4.1442 +                            deps2.add(d);
  4.1443 +                        }
  4.1444 +                    }
  4.1445 +                    deps = deps2;
  4.1446 +                }
  4.1447 +
  4.1448 +                void graphChanged(Node from, Node to) {
  4.1449 +                    if (deps.contains(from)) {
  4.1450 +                        deps.remove(from);
  4.1451 +                        if (to != null) {
  4.1452 +                            deps.add(to);
  4.1453 +                        }
  4.1454 +                    }
  4.1455 +                }
  4.1456 +            }
  4.1457 +
  4.1458 +            /** the nodes in the inference graph */
  4.1459 +            ArrayList<Node> nodes;
  4.1460 +
  4.1461 +            InferenceGraph() {
  4.1462 +                initNodes();
  4.1463 +            }
  4.1464 +
  4.1465 +            /**
  4.1466 +             * Delete a node from the graph. This update the underlying structure
  4.1467 +             * of the graph (including dependencies) via listeners updates.
  4.1468 +             */
  4.1469 +            public void deleteNode(Node n) {
  4.1470 +                Assert.check(nodes.contains(n));
  4.1471 +                nodes.remove(n);
  4.1472 +                notifyUpdate(n, null);
  4.1473 +            }
  4.1474 +
  4.1475 +            /**
  4.1476 +             * Notify all nodes of a change in the graph. If the target node is
  4.1477 +             * {@code null} the source node is assumed to be removed.
  4.1478 +             */
  4.1479 +            void notifyUpdate(Node from, Node to) {
  4.1480 +                for (Node n : nodes) {
  4.1481 +                    n.graphChanged(from, to);
  4.1482 +                }
  4.1483 +            }
  4.1484 +
  4.1485 +            /**
  4.1486 +             * Create the graph nodes. First a simple node is created for every inference
  4.1487 +             * variables to be solved. Then Tarjan is used to found all connected components
  4.1488 +             * in the graph. For each component containing more than one node, a super node is
  4.1489 +                 * created, effectively replacing the original cyclic nodes.
  4.1490 +             */
  4.1491 +            void initNodes() {
  4.1492 +                ArrayList<Node> nodes = new ArrayList<Node>();
  4.1493 +                for (Type t : inferenceContext.restvars()) {
  4.1494 +                    nodes.add(new Node(t));
  4.1495 +                }
  4.1496 +                for (Node n_i : nodes) {
  4.1497 +                    Type i = n_i.data.first();
  4.1498 +                    for (Node n_j : nodes) {
  4.1499 +                        Type j = n_j.data.first();
  4.1500 +                        UndetVar uv_i = (UndetVar)inferenceContext.asFree(i);
  4.1501 +                        if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) {
  4.1502 +                            //update i's deps
  4.1503 +                            n_i.deps.add(n_j);
  4.1504 +                            //update j's deps - only if i's bounds contain _exactly_ j
  4.1505 +                            if (uv_i.getBounds(InferenceBound.values()).contains(j)) {
  4.1506 +                                n_j.deps.add(n_i);
  4.1507 +                            }
  4.1508 +                        }
  4.1509 +                    }
  4.1510 +                }
  4.1511 +                this.nodes = new ArrayList<Node>();
  4.1512 +                for (List<? extends Node> conSubGraph : GraphUtils.tarjan(nodes)) {
  4.1513 +                    if (conSubGraph.length() > 1) {
  4.1514 +                        Node root = conSubGraph.head;
  4.1515 +                        root.mergeWith(conSubGraph.tail);
  4.1516 +                        for (Node n : conSubGraph) {
  4.1517 +                            notifyUpdate(n, root);
  4.1518 +                        }
  4.1519 +                    }
  4.1520 +                    this.nodes.add(conSubGraph.head);
  4.1521 +                }
  4.1522 +            }
  4.1523 +
  4.1524 +            /**
  4.1525 +             * Debugging: dot representation of this graph
  4.1526 +             */
  4.1527 +            String toDot() {
  4.1528 +                StringBuilder buf = new StringBuilder();
  4.1529 +                for (Type t : inferenceContext.undetvars) {
  4.1530 +                    UndetVar uv = (UndetVar)t;
  4.1531 +                    buf.append(String.format("var %s - upper bounds = %s, lower bounds = %s, eq bounds = %s\\n",
  4.1532 +                            uv.qtype, uv.getBounds(InferenceBound.UPPER), uv.getBounds(InferenceBound.LOWER),
  4.1533 +                            uv.getBounds(InferenceBound.EQ)));
  4.1534 +                }
  4.1535 +                return GraphUtils.toDot(nodes, "inferenceGraph" + hashCode(), buf.toString());
  4.1536 +            }
  4.1537 +        }
  4.1538 +    }
  4.1539 +    // </editor-fold>
  4.1540 +
  4.1541 +    // <editor-fold defaultstate="collapsed" desc="Inference context">
  4.1542 +    /**
  4.1543       * Functional interface for defining inference callbacks. Certain actions
  4.1544       * (i.e. subtyping checks) might need to be redone after all inference variables
  4.1545       * have been fixed.
  4.1546 @@ -603,7 +1283,7 @@
  4.1547       * it can be used as an entry point for performing upper/lower bound inference
  4.1548       * (see InferenceKind).
  4.1549       */
  4.1550 -    class InferenceContext {
  4.1551 +     class InferenceContext {
  4.1552  
  4.1553          /** list of inference vars as undet vars */
  4.1554          List<Type> undetvars;
  4.1555 @@ -611,6 +1291,9 @@
  4.1556          /** list of inference vars in this context */
  4.1557          List<Type> inferencevars;
  4.1558  
  4.1559 +        /** backed up inference variables */
  4.1560 +        List<Type> saved_undet;
  4.1561 +
  4.1562          java.util.Map<FreeTypeListener, List<Type>> freeTypeListeners =
  4.1563                  new java.util.HashMap<FreeTypeListener, List<Type>>();
  4.1564  
  4.1565 @@ -782,10 +1465,14 @@
  4.1566           * of all deferred checks.
  4.1567           */
  4.1568          void notifyChange() {
  4.1569 +            notifyChange(inferencevars.diff(restvars()));
  4.1570 +        }
  4.1571 +
  4.1572 +        void notifyChange(List<Type> inferredVars) {
  4.1573              InferenceException thrownEx = null;
  4.1574              for (Map.Entry<FreeTypeListener, List<Type>> entry :
  4.1575                      new HashMap<FreeTypeListener, List<Type>>(freeTypeListeners).entrySet()) {
  4.1576 -                if (!Type.containsAny(entry.getValue(), restvars())) {
  4.1577 +                if (!Type.containsAny(entry.getValue(), inferencevars.diff(inferredVars))) {
  4.1578                      try {
  4.1579                          entry.getKey().typesInferred(this);
  4.1580                          freeTypeListeners.remove(entry.getKey());
  4.1581 @@ -803,20 +1490,153 @@
  4.1582              }
  4.1583          }
  4.1584  
  4.1585 -        void solveAny(List<Type> varsToSolve) {
  4.1586 -            boolean progress = false;
  4.1587 -            for (Type t : varsToSolve) {
  4.1588 +        /**
  4.1589 +         * Save the state of this inference context
  4.1590 +         */
  4.1591 +        void save() {
  4.1592 +            ListBuffer<Type> buf = ListBuffer.lb();
  4.1593 +            for (Type t : undetvars) {
  4.1594 +                UndetVar uv = (UndetVar)t;
  4.1595 +                UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types);
  4.1596 +                for (InferenceBound ib : InferenceBound.values()) {
  4.1597 +                    for (Type b : uv.getBounds(ib)) {
  4.1598 +                        uv2.addBound(ib, b, types);
  4.1599 +                    }
  4.1600 +                }
  4.1601 +                uv2.inst = uv.inst;
  4.1602 +                buf.add(uv2);
  4.1603 +            }
  4.1604 +            saved_undet = buf.toList();
  4.1605 +        }
  4.1606 +
  4.1607 +        /**
  4.1608 +         * Restore the state of this inference context to the previous known checkpoint
  4.1609 +         */
  4.1610 +        void rollback() {
  4.1611 +            Assert.check(saved_undet != null && saved_undet.length() == undetvars.length());
  4.1612 +            undetvars = saved_undet;
  4.1613 +            saved_undet = null;
  4.1614 +        }
  4.1615 +
  4.1616 +        /**
  4.1617 +         * Copy variable in this inference context to the given context
  4.1618 +         */
  4.1619 +        void dupTo(final InferenceContext that) {
  4.1620 +            that.inferencevars = that.inferencevars.appendList(inferencevars);
  4.1621 +            that.undetvars = that.undetvars.appendList(undetvars);
  4.1622 +            //set up listeners to notify original inference contexts as
  4.1623 +            //propagated vars are inferred in new context
  4.1624 +            for (Type t : inferencevars) {
  4.1625 +                that.freeTypeListeners.put(new FreeTypeListener() {
  4.1626 +                    public void typesInferred(InferenceContext inferenceContext) {
  4.1627 +                        InferenceContext.this.notifyChange();
  4.1628 +                    }
  4.1629 +                }, List.of(t));
  4.1630 +            }
  4.1631 +        }
  4.1632 +
  4.1633 +        /**
  4.1634 +         * Solve with given graph strategy.
  4.1635 +         */
  4.1636 +        private void solve(GraphStrategy ss, Warner warn) {
  4.1637 +            GraphSolver s = new GraphSolver(this, warn);
  4.1638 +            s.solve(ss);
  4.1639 +        }
  4.1640 +
  4.1641 +        /**
  4.1642 +         * Solve all variables in this context.
  4.1643 +         */
  4.1644 +        public void solve(Warner warn) {
  4.1645 +            solve(new LeafSolver() {
  4.1646 +                public boolean done() {
  4.1647 +                    return restvars().isEmpty();
  4.1648 +                }
  4.1649 +            }, warn);
  4.1650 +        }
  4.1651 +
  4.1652 +        /**
  4.1653 +         * Solve all variables in the given list.
  4.1654 +         */
  4.1655 +        public void solve(final List<Type> vars, Warner warn) {
  4.1656 +            solve(new BestLeafSolver(vars) {
  4.1657 +                public boolean done() {
  4.1658 +                    return !free(asInstTypes(vars));
  4.1659 +                }
  4.1660 +            }, warn);
  4.1661 +        }
  4.1662 +
  4.1663 +        /**
  4.1664 +         * Solve at least one variable in given list.
  4.1665 +         */
  4.1666 +        public void solveAny(List<Type> varsToSolve, Warner warn) {
  4.1667 +            checkWithinBounds(this, warn); //propagate bounds
  4.1668 +            List<Type> boundedVars = boundedVars().intersect(restvars()).intersect(varsToSolve);
  4.1669 +            if (boundedVars.isEmpty()) {
  4.1670 +                throw inferenceException.setMessage("cyclic.inference",
  4.1671 +                                freeVarsIn(varsToSolve));
  4.1672 +            }
  4.1673 +            solve(new BestLeafSolver(boundedVars) {
  4.1674 +                public boolean done() {
  4.1675 +                    return instvars().intersect(varsToSolve).nonEmpty();
  4.1676 +                }
  4.1677 +            }, warn);
  4.1678 +        }
  4.1679 +
  4.1680 +        /**
  4.1681 +         * Apply a set of inference steps
  4.1682 +         */
  4.1683 +        private boolean solveBasic(EnumSet<InferenceStep> steps) {
  4.1684 +            return solveBasic(inferencevars, steps);
  4.1685 +        }
  4.1686 +
  4.1687 +        private boolean solveBasic(List<Type> varsToSolve, EnumSet<InferenceStep> steps) {
  4.1688 +            boolean changed = false;
  4.1689 +            for (Type t : varsToSolve.intersect(restvars())) {
  4.1690                  UndetVar uv = (UndetVar)asFree(t);
  4.1691 -                if (uv.inst == null) {
  4.1692 -                    minimizeInst(uv, types.noWarnings);
  4.1693 -                    if (uv.inst != null) {
  4.1694 -                        progress = true;
  4.1695 +                for (InferenceStep step : steps) {
  4.1696 +                    if (step.accepts(uv, this)) {
  4.1697 +                        uv.inst = step.solve(uv, this);
  4.1698 +                        changed = true;
  4.1699 +                        break;
  4.1700                      }
  4.1701                  }
  4.1702              }
  4.1703 -            if (!progress) {
  4.1704 -                throw inferenceException.setMessage("cyclic.inference", varsToSolve);
  4.1705 +            return changed;
  4.1706 +        }
  4.1707 +
  4.1708 +        /**
  4.1709 +         * Instantiate inference variables in legacy mode (JLS 15.12.2.7, 15.12.2.8).
  4.1710 +         * During overload resolution, instantiation is done by doing a partial
  4.1711 +         * inference process using eq/lower bound instantiation. During check,
  4.1712 +         * we also instantiate any remaining vars by repeatedly using eq/upper
  4.1713 +         * instantiation, until all variables are solved.
  4.1714 +         */
  4.1715 +        public void solveLegacy(boolean partial, Warner warn, EnumSet<InferenceStep> steps) {
  4.1716 +            while (true) {
  4.1717 +                boolean stuck = !solveBasic(steps);
  4.1718 +                if (restvars().isEmpty() || partial) {
  4.1719 +                    //all variables have been instantiated - exit
  4.1720 +                    break;
  4.1721 +                } else if (stuck) {
  4.1722 +                    //some variables could not be instantiated because of cycles in
  4.1723 +                    //upper bounds - provide a (possibly recursive) default instantiation
  4.1724 +                    instantiateAsUninferredVars(restvars(), this);
  4.1725 +                    break;
  4.1726 +                } else {
  4.1727 +                    //some variables have been instantiated - replace newly instantiated
  4.1728 +                    //variables in remaining upper bounds and continue
  4.1729 +                    for (Type t : undetvars) {
  4.1730 +                        UndetVar uv = (UndetVar)t;
  4.1731 +                        uv.substBounds(inferenceVars(), instTypes(), types);
  4.1732 +                    }
  4.1733 +                }
  4.1734              }
  4.1735 +            checkWithinBounds(this, warn);
  4.1736 +        }
  4.1737 +
  4.1738 +        private Infer infer() {
  4.1739 +            //back-door to infer
  4.1740 +            return Infer.this;
  4.1741          }
  4.1742      }
  4.1743  
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/share/classes/com/sun/tools/javac/util/GraphUtils.java	Tue Feb 12 19:25:09 2013 +0000
     5.3 @@ -0,0 +1,145 @@
     5.4 +/*
     5.5 + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.7 + *
     5.8 + * This code is free software; you can redistribute it and/or modify it
     5.9 + * under the terms of the GNU General Public License version 2 only, as
    5.10 + * published by the Free Software Foundation.  Oracle designates this
    5.11 + * particular file as subject to the "Classpath" exception as provided
    5.12 + * by Oracle in the LICENSE file that accompanied this code.
    5.13 + *
    5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    5.17 + * version 2 for more details (a copy is included in the LICENSE file that
    5.18 + * accompanied this code).
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License version
    5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    5.23 + *
    5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    5.25 + * or visit www.oracle.com if you need additional information or have any
    5.26 + * questions.
    5.27 + */
    5.28 +
    5.29 +package com.sun.tools.javac.util;
    5.30 +
    5.31 +/** <p><b>This is NOT part of any supported API.
    5.32 + *  If you write code that depends on this, you do so at your own risk.
    5.33 + *  This code and its internal interfaces are subject to change or
    5.34 + *  deletion without notice.</b>
    5.35 + */
    5.36 +public class GraphUtils {
    5.37 +
    5.38 +    /**
    5.39 +     * This class is a basic abstract class for representing a node.
    5.40 +     * A node is associated with a given data.
    5.41 +     */
    5.42 +    public static abstract class Node<D> {
    5.43 +        public final D data;
    5.44 +
    5.45 +        public Node(D data) {
    5.46 +            this.data = data;
    5.47 +        }
    5.48 +
    5.49 +        public abstract Iterable<? extends Node<D>> getDependencies();
    5.50 +
    5.51 +        public abstract String printDependency(Node<D> to);
    5.52 +
    5.53 +        @Override
    5.54 +        public String toString() {
    5.55 +            return data.toString();
    5.56 +        }
    5.57 +    }
    5.58 +
    5.59 +    /**
    5.60 +     * This class specialized Node, by adding elements that are required in order
    5.61 +     * to perform Tarjan computation of strongly connected components.
    5.62 +     */
    5.63 +    public static abstract class TarjanNode<D> extends Node<D> implements Comparable<TarjanNode<D>> {
    5.64 +        int index = -1;
    5.65 +        int lowlink;
    5.66 +        boolean active;
    5.67 +
    5.68 +        public TarjanNode(D data) {
    5.69 +            super(data);
    5.70 +        }
    5.71 +
    5.72 +        public abstract Iterable<? extends TarjanNode<D>> getDependencies();
    5.73 +
    5.74 +        public int compareTo(TarjanNode<D> o) {
    5.75 +            return (index < o.index) ? -1 : (index == o.index) ? 0 : 1;
    5.76 +        }
    5.77 +    }
    5.78 +
    5.79 +    /**
    5.80 +     * Tarjan's algorithm to determine strongly connected components of a
    5.81 +     * directed graph in linear time. Works on TarjanNode.
    5.82 +     */
    5.83 +    public static <D, N extends TarjanNode<D>> List<? extends List<? extends N>> tarjan(Iterable<? extends N> nodes) {
    5.84 +        ListBuffer<List<N>> cycles = ListBuffer.lb();
    5.85 +        ListBuffer<N> stack = ListBuffer.lb();
    5.86 +        int index = 0;
    5.87 +        for (N node: nodes) {
    5.88 +            if (node.index == -1) {
    5.89 +                index += tarjan(node, index, stack, cycles);
    5.90 +            }
    5.91 +        }
    5.92 +        return cycles.toList();
    5.93 +    }
    5.94 +
    5.95 +    private static <D, N extends TarjanNode<D>> int tarjan(N v, int index, ListBuffer<N> stack, ListBuffer<List<N>> cycles) {
    5.96 +        v.index = index;
    5.97 +        v.lowlink = index;
    5.98 +        index++;
    5.99 +        stack.prepend(v);
   5.100 +        v.active = true;
   5.101 +        for (TarjanNode<D> nd: v.getDependencies()) {
   5.102 +            @SuppressWarnings("unchecked")
   5.103 +            N n = (N)nd;
   5.104 +            if (n.index == -1) {
   5.105 +                tarjan(n, index, stack, cycles);
   5.106 +                v.lowlink = Math.min(v.lowlink, n.lowlink);
   5.107 +            } else if (stack.contains(n)) {
   5.108 +                v.lowlink = Math.min(v.lowlink, n.index);
   5.109 +            }
   5.110 +        }
   5.111 +        if (v.lowlink == v.index) {
   5.112 +            N n;
   5.113 +            ListBuffer<N> cycle = ListBuffer.lb();
   5.114 +            do {
   5.115 +                n = stack.remove();
   5.116 +                n.active = false;
   5.117 +                cycle.add(n);
   5.118 +            } while (n != v);
   5.119 +            cycles.add(cycle.toList());
   5.120 +        }
   5.121 +        return index;
   5.122 +    }
   5.123 +
   5.124 +    /**
   5.125 +     * Debugging: dot representation of a set of connected nodes. The resulting
   5.126 +     * dot representation will use {@code Node.toString} to display node labels
   5.127 +     * and {@code Node.printDependency} to display edge labels. The resulting
   5.128 +     * representation is also customizable with a graph name and a header.
   5.129 +     */
   5.130 +    public static <D> String toDot(Iterable<? extends TarjanNode<D>> nodes, String name, String header) {
   5.131 +        StringBuilder buf = new StringBuilder();
   5.132 +        buf.append(String.format("digraph %s {\n", name));
   5.133 +        buf.append(String.format("label = \"%s\";\n", header));
   5.134 +        //dump nodes
   5.135 +        for (TarjanNode<D> n : nodes) {
   5.136 +            buf.append(String.format("%s [label = \"%s\"];\n", n.hashCode(), n.toString()));
   5.137 +        }
   5.138 +        //dump arcs
   5.139 +        for (TarjanNode<D> from : nodes) {
   5.140 +            for (TarjanNode<D> to : from.getDependencies()) {
   5.141 +                buf.append(String.format("%s -> %s [label = \" %s \"];\n",
   5.142 +                        from.hashCode(), to.hashCode(), from.printDependency(to)));
   5.143 +            }
   5.144 +        }
   5.145 +        buf.append("}\n");
   5.146 +        return buf.toString();
   5.147 +    }
   5.148 +}
     6.1 --- a/test/tools/javac/6758789/T6758789b.out	Tue Feb 12 13:36:56 2013 +0000
     6.2 +++ b/test/tools/javac/6758789/T6758789b.out	Tue Feb 12 19:25:09 2013 +0000
     6.3 @@ -1,4 +1,4 @@
     6.4 -T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<X>
     6.5 +T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<java.lang.Object>
     6.6  T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
     6.7  - compiler.err.warnings.and.werror
     6.8  1 error
     7.1 --- a/test/tools/javac/Diagnostics/6799605/T6799605.out	Tue Feb 12 13:36:56 2013 +0000
     7.2 +++ b/test/tools/javac/Diagnostics/6799605/T6799605.out	Tue Feb 12 19:25:09 2013 +0000
     7.3 @@ -1,4 +1,4 @@
     7.4 -T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.inferred.do.not.conform.to.upper.bounds: compiler.misc.type.captureof: 1, ?, T6799605<compiler.misc.type.captureof: 1, ?>)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
     7.5 +T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.incompatible.eq.upper.bounds: T, compiler.misc.type.captureof: 1, ?, T6799605<T>)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
     7.6  T6799605.java:18:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 2, ?, compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
     7.7  T6799605.java:19:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,T6799605<compiler.misc.type.captureof: 3, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.inferred.do.not.conform.to.eq.bounds: compiler.misc.type.captureof: 3, ?, compiler.misc.type.captureof: 3, ?,compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?))}
     7.8  3 errors
     8.1 --- a/test/tools/javac/diags/examples/CantApplyDiamond1.java	Tue Feb 12 13:36:56 2013 +0000
     8.2 +++ b/test/tools/javac/diags/examples/CantApplyDiamond1.java	Tue Feb 12 19:25:09 2013 +0000
     8.3 @@ -1,5 +1,5 @@
     8.4  /*
     8.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     8.6 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     8.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.8   *
     8.9   * This code is free software; you can redistribute it and/or modify it
    8.10 @@ -23,7 +23,7 @@
    8.11  
    8.12  // key: compiler.err.prob.found.req
    8.13  // key: compiler.misc.cant.apply.diamond.1
    8.14 -// key: compiler.misc.inferred.do.not.conform.to.upper.bounds
    8.15 +// key: compiler.misc.incompatible.eq.upper.bounds
    8.16  // key: compiler.misc.diamond
    8.17  
    8.18  class CantApplyDiamond1<X> {
     9.1 --- a/test/tools/javac/diags/examples/InferredDoNotConformToEq.java	Tue Feb 12 13:36:56 2013 +0000
     9.2 +++ b/test/tools/javac/diags/examples/InferredDoNotConformToEq.java	Tue Feb 12 19:25:09 2013 +0000
     9.3 @@ -1,5 +1,5 @@
     9.4  /*
     9.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
     9.6 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     9.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.8   *
     9.9   * This code is free software; you can redistribute it and/or modify it
    9.10 @@ -23,6 +23,7 @@
    9.11  
    9.12  // key: compiler.err.cant.apply.symbol
    9.13  // key: compiler.misc.inferred.do.not.conform.to.eq.bounds
    9.14 +// options: -source 7 -Xlint:-options
    9.15  
    9.16  import java.util.*;
    9.17  
    10.1 --- a/test/tools/javac/diags/examples/InferredDoNotConformToUpper.java	Tue Feb 12 13:36:56 2013 +0000
    10.2 +++ b/test/tools/javac/diags/examples/InferredDoNotConformToUpper.java	Tue Feb 12 19:25:09 2013 +0000
    10.3 @@ -1,5 +1,5 @@
    10.4  /*
    10.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
    10.6 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    10.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.8   *
    10.9   * This code is free software; you can redistribute it and/or modify it
   10.10 @@ -23,6 +23,7 @@
   10.11  
   10.12  // key: compiler.err.cant.apply.symbol
   10.13  // key: compiler.misc.inferred.do.not.conform.to.upper.bounds
   10.14 +// options: -source 7 -Xlint:-options
   10.15  
   10.16  import java.util.*;
   10.17  
    11.1 --- a/test/tools/javac/diags/examples/WhereFreshTvar.java	Tue Feb 12 13:36:56 2013 +0000
    11.2 +++ b/test/tools/javac/diags/examples/WhereFreshTvar.java	Tue Feb 12 19:25:09 2013 +0000
    11.3 @@ -1,5 +1,5 @@
    11.4  /*
    11.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
    11.6 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    11.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.8   *
    11.9   * This code is free software; you can redistribute it and/or modify it
   11.10 @@ -24,7 +24,7 @@
   11.11  // key: compiler.misc.where.fresh.typevar
   11.12  // key: compiler.misc.where.description.typevar
   11.13  // key: compiler.err.prob.found.req
   11.14 -// key: compiler.misc.inferred.do.not.conform.to.upper.bounds
   11.15 +// key: compiler.misc.inconvertible.types
   11.16  // options: -XDdiags=where,simpleNames
   11.17  // run: simple
   11.18  
   11.19 @@ -33,5 +33,5 @@
   11.20  class WhereFreshTvar {
   11.21      <T extends List<T>> T m() {}
   11.22  
   11.23 -    { List<String> ls = m(); }
   11.24 +    { Object o = (List<String>)m(); }
   11.25  }
    12.1 --- a/test/tools/javac/generics/7015430/T7015430.out	Tue Feb 12 13:36:56 2013 +0000
    12.2 +++ b/test/tools/javac/generics/7015430/T7015430.out	Tue Feb 12 19:25:09 2013 +0000
    12.3 @@ -1,14 +1,14 @@
    12.4 -T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
    12.5 +T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
    12.6  T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
    12.7  T7015430.java:50:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
    12.8  T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
    12.9 -T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
   12.10 +T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
   12.11  T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
   12.12  T7015430.java:77:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
   12.13  T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
   12.14  T7015430.java:104:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
   12.15  T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
   12.16 -T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
   12.17 +T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
   12.18  T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
   12.19  T7015430.java:41:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
   12.20  T7015430.java:68:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
    13.1 --- a/test/tools/javac/generics/7151802/T7151802.out	Tue Feb 12 13:36:56 2013 +0000
    13.2 +++ b/test/tools/javac/generics/7151802/T7151802.out	Tue Feb 12 19:25:09 2013 +0000
    13.3 @@ -1,5 +1,5 @@
    13.4  T7151802.java:14:31: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get1, Z, T7151802.Foo, kindname.class, T7151802
    13.5 -T7151802.java:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<Z>
    13.6 +T7151802.java:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.Object>
    13.7  T7151802.java:22:30: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get3, T7151802.Foo<Z>, T7151802.Foo, kindname.class, T7151802
    13.8  T7151802.java:30:36: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get5, compiler.misc.no.args, compiler.misc.no.args, kindname.class, T7151802
    13.9  T7151802.java:38:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.String>
    14.1 --- a/test/tools/javac/generics/diamond/neg/Neg06.out	Tue Feb 12 13:36:56 2013 +0000
    14.2 +++ b/test/tools/javac/generics/diamond/neg/Neg06.out	Tue Feb 12 19:25:09 2013 +0000
    14.3 @@ -1,2 +1,2 @@
    14.4 -Neg06.java:16:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number))
    14.5 +Neg06.java:16:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
    14.6  1 error
    15.1 --- a/test/tools/javac/generics/inference/6278587/T6278587Neg.java	Tue Feb 12 13:36:56 2013 +0000
    15.2 +++ b/test/tools/javac/generics/inference/6278587/T6278587Neg.java	Tue Feb 12 19:25:09 2013 +0000
    15.3 @@ -1,5 +1,5 @@
    15.4  /*
    15.5 - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
    15.6 + * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
    15.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.8   *
    15.9   * This code is free software; you can redistribute it and/or modify it
   15.10 @@ -23,10 +23,11 @@
   15.11  
   15.12  /*
   15.13   * @test
   15.14 - * @bug     6278587
   15.15 + * @bug     6278587 8007464
   15.16   * @summary Inference broken for subtypes of subtypes of F-bounded types
   15.17   * @author  Peter von der Ah\u00e9
   15.18 - * @compile/fail T6278587Neg.java
   15.19 + * @compile/fail -source 7 T6278587Neg.java
   15.20 + * @compile T6278587Neg.java
   15.21   */
   15.22  
   15.23  public abstract class T6278587Neg {
    16.1 --- a/test/tools/javac/generics/inference/6638712/T6638712d.out	Tue Feb 12 13:36:56 2013 +0000
    16.2 +++ b/test/tools/javac/generics/inference/6638712/T6638712d.out	Tue Feb 12 19:25:09 2013 +0000
    16.3 @@ -1,2 +1,2 @@
    16.4 -T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.String, java.lang.Integer)
    16.5 +T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.incompatible.eq.lower.bounds: U, java.lang.String, java.lang.Integer)
    16.6  1 error
    17.1 --- a/test/tools/javac/generics/inference/6638712/T6638712e.out	Tue Feb 12 13:36:56 2013 +0000
    17.2 +++ b/test/tools/javac/generics/inference/6638712/T6638712e.out	Tue Feb 12 19:25:09 2013 +0000
    17.3 @@ -1,2 +1,2 @@
    17.4 -T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Boolean,java.lang.Object)
    17.5 +T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Boolean,java.lang.Object)
    17.6  1 error
    18.1 --- a/test/tools/javac/generics/inference/7154127/T7154127.java	Tue Feb 12 13:36:56 2013 +0000
    18.2 +++ b/test/tools/javac/generics/inference/7154127/T7154127.java	Tue Feb 12 19:25:09 2013 +0000
    18.3 @@ -1,8 +1,9 @@
    18.4  /**
    18.5   * @test /nodynamiccopyright/
    18.6 - * @bug 7154127
    18.7 + * @bug 7154127 8007464
    18.8   * @summary Inference cleanup: remove bound check analysis from visitors in Types.java
    18.9 - * @compile/fail/ref=T7154127.out -XDrawDiagnostics T7154127.java
   18.10 + * @compile/fail/ref=T7154127.out -Xlint:-options -source 7 -XDrawDiagnostics T7154127.java
   18.11 + * @compile T7154127.java
   18.12   */
   18.13  class T7154127 {
   18.14  
    19.1 --- a/test/tools/javac/generics/inference/7154127/T7154127.out	Tue Feb 12 13:36:56 2013 +0000
    19.2 +++ b/test/tools/javac/generics/inference/7154127/T7154127.out	Tue Feb 12 19:25:09 2013 +0000
    19.3 @@ -1,2 +1,2 @@
    19.4 -T7154127.java:19:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: Y, T7154127.B<U>,T7154127.D)
    19.5 +T7154127.java:20:49: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: Y, T7154127.B<U>,T7154127.D)
    19.6  1 error
    20.1 --- a/test/tools/javac/generics/inference/7177306/T7177306a.out	Tue Feb 12 13:36:56 2013 +0000
    20.2 +++ b/test/tools/javac/generics/inference/7177306/T7177306a.out	Tue Feb 12 19:25:09 2013 +0000
    20.3 @@ -1,4 +1,4 @@
    20.4 -T7177306a.java:13:34: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List<E>
    20.5 +T7177306a.java:13:34: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List<java.lang.Object>
    20.6  T7177306a.java:13:33: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, java.util.List<E>, java.util.List, kindname.class, T7177306a
    20.7  T7177306a.java:13:33: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7177306a, T7177306a<java.lang.Object>
    20.8  - compiler.err.warnings.and.werror
    21.1 --- a/test/tools/javac/generics/inference/7177306/T7177306e.java	Tue Feb 12 13:36:56 2013 +0000
    21.2 +++ b/test/tools/javac/generics/inference/7177306/T7177306e.java	Tue Feb 12 19:25:09 2013 +0000
    21.3 @@ -1,8 +1,9 @@
    21.4  /**
    21.5   * @test /nodynamiccopyright/
    21.6 - * @bug 7177306
    21.7 + * @bug 7177306 8007464
    21.8   * @summary Regression: unchecked method call does not erase return type
    21.9 - * @compile/fail/ref=T7177306e.out -XDrawDiagnostics T7177306e.java
   21.10 + * @compile/fail/ref=T7177306e.out -source 7 -Xlint:-options -XDrawDiagnostics T7177306e.java
   21.11 + * @compile/fail T7177306e.java
   21.12   */
   21.13  
   21.14  import java.util.List;
    22.1 --- a/test/tools/javac/generics/inference/7177306/T7177306e.out	Tue Feb 12 13:36:56 2013 +0000
    22.2 +++ b/test/tools/javac/generics/inference/7177306/T7177306e.out	Tue Feb 12 19:25:09 2013 +0000
    22.3 @@ -1,2 +1,2 @@
    22.4 -T7177306e.java:15:9: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List<?>, java.util.List<compiler.misc.type.captureof: 1, ?>)
    22.5 +T7177306e.java:16:9: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List<?>, java.util.List<compiler.misc.type.captureof: 1, ?>)
    22.6  1 error
    23.1 --- a/test/tools/javac/generics/odersky/BadTest4.java	Tue Feb 12 13:36:56 2013 +0000
    23.2 +++ b/test/tools/javac/generics/odersky/BadTest4.java	Tue Feb 12 19:25:09 2013 +0000
    23.3 @@ -23,11 +23,12 @@
    23.4  
    23.5  /*
    23.6   * @test
    23.7 - * @ bug
    23.8 + * @bug 8007464
    23.9   * @summary Negative regression test from odersky
   23.10   * @author odersky
   23.11   *
   23.12 - * @compile/fail  BadTest4.java
   23.13 + * @compile/fail -source 7 BadTest4.java
   23.14 + * @compile BadTest4.java
   23.15   */
   23.16  
   23.17  class BadTest4 {
    24.1 --- a/test/tools/javac/lambda/TargetType14.out	Tue Feb 12 13:36:56 2013 +0000
    24.2 +++ b/test/tools/javac/lambda/TargetType14.out	Tue Feb 12 19:25:09 2013 +0000
    24.3 @@ -1,2 +1,2 @@
    24.4 -TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.lower.bounds: java.lang.Integer, java.lang.String)
    24.5 +TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.lower.bounds: X, java.lang.Integer, java.lang.String)
    24.6  1 error
    25.1 --- a/test/tools/javac/lambda/TargetType20.java	Tue Feb 12 13:36:56 2013 +0000
    25.2 +++ b/test/tools/javac/lambda/TargetType20.java	Tue Feb 12 19:25:09 2013 +0000
    25.3 @@ -1,10 +1,33 @@
    25.4  /*
    25.5 - * @test /nodynamiccopyright/
    25.6 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    25.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    25.8 + *
    25.9 + * This code is free software; you can redistribute it and/or modify it
   25.10 + * under the terms of the GNU General Public License version 2 only, as
   25.11 + * published by the Free Software Foundation.
   25.12 + *
   25.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
   25.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   25.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   25.16 + * version 2 for more details (a copy is included in the LICENSE file that
   25.17 + * accompanied this code).
   25.18 + *
   25.19 + * You should have received a copy of the GNU General Public License version
   25.20 + * 2 along with this work; if not, write to the Free Software Foundation,
   25.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   25.22 + *
   25.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   25.24 + * or visit www.oracle.com if you need additional information or have any
   25.25 + * questions.
   25.26 + */
   25.27 +
   25.28 +/*
   25.29 + * @test
   25.30   * @bug 8003280
   25.31   * @summary Add lambda tests
   25.32   *  complex case of lambda return type that depends on generic method
   25.33   *          inference variable
   25.34 - * @compile/fail/ref=TargetType20.out -XDrawDiagnostics TargetType20.java
   25.35 + * @compile -XDrawDiagnostics TargetType20.java
   25.36   */
   25.37  import java.util.*;
   25.38  
    26.1 --- a/test/tools/javac/lambda/TargetType20.out	Tue Feb 12 13:36:56 2013 +0000
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,2 +0,0 @@
    26.4 -TargetType20.java:19:10: compiler.err.cant.apply.symbol: kindname.method, call, TargetType20.SAM2<Z>,TargetType20.SAM2<Z>, @428,@459, kindname.class, TargetType20.Test, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.String, java.lang.String,java.lang.Object)
    26.5 -1 error
    27.1 --- a/test/tools/javac/lambda/TargetType28.out	Tue Feb 12 13:36:56 2013 +0000
    27.2 +++ b/test/tools/javac/lambda/TargetType28.out	Tue Feb 12 19:25:09 2013 +0000
    27.3 @@ -1,3 +1,2 @@
    27.4 -TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.String)
    27.5 -TargetType28.java:21:33: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Number, java.lang.Number,java.lang.Integer)
    27.6 -2 errors
    27.7 +TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String,X, java.lang.Object,java.lang.Number)
    27.8 +1 error
    28.1 --- a/test/tools/javac/lambda/TargetType50.java	Tue Feb 12 13:36:56 2013 +0000
    28.2 +++ b/test/tools/javac/lambda/TargetType50.java	Tue Feb 12 19:25:09 2013 +0000
    28.3 @@ -1,9 +1,32 @@
    28.4  /*
    28.5 - * @test /nodynamiccopyright/
    28.6 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    28.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    28.8 + *
    28.9 + * This code is free software; you can redistribute it and/or modify it
   28.10 + * under the terms of the GNU General Public License version 2 only, as
   28.11 + * published by the Free Software Foundation.
   28.12 + *
   28.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
   28.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   28.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   28.16 + * version 2 for more details (a copy is included in the LICENSE file that
   28.17 + * accompanied this code).
   28.18 + *
   28.19 + * You should have received a copy of the GNU General Public License version
   28.20 + * 2 along with this work; if not, write to the Free Software Foundation,
   28.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   28.22 + *
   28.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   28.24 + * or visit www.oracle.com if you need additional information or have any
   28.25 + * questions.
   28.26 + */
   28.27 +
   28.28 +/*
   28.29 + * @test
   28.30   * @bug 8003280
   28.31   * @summary Add lambda tests
   28.32   *  bad stuck check for method reference leads to javac crash
   28.33 - * @compile/fail/ref=TargetType50.out -XDrawDiagnostics TargetType50.java
   28.34 + * @compile TargetType50.java
   28.35   */
   28.36  import java.util.*;
   28.37  
   28.38 @@ -17,7 +40,7 @@
   28.39          static <Z> Sink<Z> make() { return null; }
   28.40      }
   28.41  
   28.42 -    <Y, S extends Sink<Y>> List<Y> m(Factory<S> factory) {  }
   28.43 +    <Y, S extends Sink<Y>> List<Y> m(Factory<S> factory) { return null; }
   28.44  
   28.45      void test() {
   28.46          List<?> l1 = m(Sink::new);
    29.1 --- a/test/tools/javac/lambda/TargetType50.out	Tue Feb 12 13:36:56 2013 +0000
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,3 +0,0 @@
    29.4 -TargetType50.java:25:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink<java.lang.Object>, TargetType50.Sink<java.lang.String>)
    29.5 -TargetType50.java:26:28: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: TargetType50.Sink<java.lang.Object>, TargetType50.Sink<java.lang.String>)
    29.6 -2 errors
    30.1 --- a/test/tools/javac/lambda/TargetType51.java	Tue Feb 12 13:36:56 2013 +0000
    30.2 +++ b/test/tools/javac/lambda/TargetType51.java	Tue Feb 12 19:25:09 2013 +0000
    30.3 @@ -23,7 +23,9 @@
    30.4  
    30.5  /*
    30.6   * @test
    30.7 - * @summary smoke test for combinator-like stuck analysis
    30.8 + * @bug 8005244
    30.9 + * @summary Implement overload resolution as per latest spec EDR
   30.10 + *          smoke test for combinator-like stuck analysis
   30.11   * @author  Maurizio Cimadamore
   30.12   * @compile TargetType51.java
   30.13   */
    31.1 --- a/test/tools/javac/lambda/TargetType52.java	Tue Feb 12 13:36:56 2013 +0000
    31.2 +++ b/test/tools/javac/lambda/TargetType52.java	Tue Feb 12 19:25:09 2013 +0000
    31.3 @@ -1,6 +1,8 @@
    31.4  /*
    31.5   * @test /nodynamiccopyright/
    31.6 - * @summary uncatched sam conversion failure exception lead to javac crash
    31.7 + * @bug 8005244
    31.8 + * @summary Implement overload resolution as per latest spec EDR
    31.9 + *          uncatched sam conversion failure exception lead to javac crash
   31.10   * @compile/fail/ref=TargetType52.out -XDrawDiagnostics TargetType52.java
   31.11   */
   31.12  class TargetType52 {
    32.1 --- a/test/tools/javac/lambda/TargetType52.out	Tue Feb 12 13:36:56 2013 +0000
    32.2 +++ b/test/tools/javac/lambda/TargetType52.out	Tue Feb 12 19:25:09 2013 +0000
    32.3 @@ -1,2 +1,2 @@
    32.4 -TargetType52.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, TargetType52.FI<? extends java.lang.CharSequence,? extends java.util.ArrayList<? extends java.lang.CharSequence>>, @444, kindname.class, TargetType52, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: TargetType52.FI<java.lang.CharSequence,java.util.ArrayList<? extends java.lang.CharSequence>>))
    32.5 +TargetType52.java:17:9: compiler.err.cant.apply.symbol: kindname.method, m, TargetType52.FI<? extends java.lang.CharSequence,? extends java.util.ArrayList<? extends java.lang.CharSequence>>, @525, kindname.class, TargetType52, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.no.suitable.functional.intf.inst: TargetType52.FI<java.lang.CharSequence,java.util.ArrayList<? extends java.lang.CharSequence>>))
    32.6  1 error
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/test/tools/javac/lambda/TargetType53.java	Tue Feb 12 19:25:09 2013 +0000
    33.3 @@ -0,0 +1,47 @@
    33.4 +/*
    33.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 + *
    33.8 + * This code is free software; you can redistribute it and/or modify it
    33.9 + * under the terms of the GNU General Public License version 2 only, as
   33.10 + * published by the Free Software Foundation.
   33.11 + *
   33.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   33.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.15 + * version 2 for more details (a copy is included in the LICENSE file that
   33.16 + * accompanied this code).
   33.17 + *
   33.18 + * You should have received a copy of the GNU General Public License version
   33.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   33.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.21 + *
   33.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.23 + * or visit www.oracle.com if you need additional information or have any
   33.24 + * questions.
   33.25 + */
   33.26 +
   33.27 +/*
   33.28 + * @test
   33.29 + * @bug 8007464
   33.30 + * @summary Add graph inference support
   33.31 + *          smoke test for graph inference
   33.32 + * @ignore  awaits stream API: 800NNNN
   33.33 + * @compile TargetType53.java
   33.34 + */
   33.35 +import java.util.*;
   33.36 +import java.util.stream.*;
   33.37 +import java.util.function.*;
   33.38 +
   33.39 +class TargetType53 {
   33.40 +
   33.41 +    <P> List<List<P>> perm(List<P> l) { return null; }
   33.42 +
   33.43 +    void g(List<List<UnaryOperator<IntStream>>> l) { }
   33.44 +
   33.45 +    void test() {
   33.46 +        List<List<UnaryOperator<IntStream>>> l =
   33.47 +            perm(Arrays.asList(s -> s.sorted()));
   33.48 +        g(perm(Arrays.asList(s -> s.sorted())));
   33.49 +    }
   33.50 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/test/tools/javac/lambda/TargetType54.java	Tue Feb 12 19:25:09 2013 +0000
    34.3 @@ -0,0 +1,45 @@
    34.4 +/*
    34.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 + *
    34.8 + * This code is free software; you can redistribute it and/or modify it
    34.9 + * under the terms of the GNU General Public License version 2 only, as
   34.10 + * published by the Free Software Foundation.
   34.11 + *
   34.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   34.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   34.15 + * version 2 for more details (a copy is included in the LICENSE file that
   34.16 + * accompanied this code).
   34.17 + *
   34.18 + * You should have received a copy of the GNU General Public License version
   34.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   34.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.21 + *
   34.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   34.23 + * or visit www.oracle.com if you need additional information or have any
   34.24 + * questions.
   34.25 + */
   34.26 +
   34.27 +/*
   34.28 + * @test
   34.29 + * @bug 8007464
   34.30 + * @summary Add graph inference support
   34.31 + *          smoke test for graph inference
   34.32 + * @ignore  awaits stream API: 800NNNN
   34.33 + * @compile TargetType54.java
   34.34 + */
   34.35 +import java.util.stream.*;
   34.36 +import java.util.*;
   34.37 +import static java.util.stream.Collectors.*;
   34.38 +
   34.39 +class TargetType54 {
   34.40 +    void test(Stream<Integer> si) {
   34.41 +        List<Integer> l1 = si.collect(toList());
   34.42 +        List<Integer> l2 = si.collect(toCollection(ArrayList::new));
   34.43 +        m(si.collect(toList()));
   34.44 +        m(si.collect(toCollection(ArrayList::new)));
   34.45 +    }
   34.46 +
   34.47 +    void m(List<Integer> l) { }
   34.48 +}
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/test/tools/javac/lambda/TargetType55.java	Tue Feb 12 19:25:09 2013 +0000
    35.3 @@ -0,0 +1,42 @@
    35.4 +/*
    35.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + *
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.
   35.11 + *
   35.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.15 + * version 2 for more details (a copy is included in the LICENSE file that
   35.16 + * accompanied this code).
   35.17 + *
   35.18 + * You should have received a copy of the GNU General Public License version
   35.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.21 + *
   35.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.23 + * or visit www.oracle.com if you need additional information or have any
   35.24 + * questions.
   35.25 + */
   35.26 +
   35.27 +/*
   35.28 + * @test
   35.29 + * @bug 8007464
   35.30 + * @summary Add graph inference
   35.31 + *          support smoke test for graph inference
   35.32 + * @compile TargetType55.java
   35.33 + */
   35.34 +import java.util.function.*;
   35.35 +
   35.36 +class TargetType55  {
   35.37 +
   35.38 +    <R> void m(Function<Integer, R> collector) { }
   35.39 +
   35.40 +    <T, D> Function<T, Integer> g(D d, BinaryOperator<D> reducer) { return null; }
   35.41 +
   35.42 +    public void test() {
   35.43 +        m(g((Integer)null, (x,y)->1));
   35.44 +    }
   35.45 +}
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/test/tools/javac/lambda/TargetType56.java	Tue Feb 12 19:25:09 2013 +0000
    36.3 @@ -0,0 +1,40 @@
    36.4 +/*
    36.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    36.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    36.7 + *
    36.8 + * This code is free software; you can redistribute it and/or modify it
    36.9 + * under the terms of the GNU General Public License version 2 only, as
   36.10 + * published by the Free Software Foundation.
   36.11 + *
   36.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   36.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   36.15 + * version 2 for more details (a copy is included in the LICENSE file that
   36.16 + * accompanied this code).
   36.17 + *
   36.18 + * You should have received a copy of the GNU General Public License version
   36.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   36.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   36.21 + *
   36.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   36.23 + * or visit www.oracle.com if you need additional information or have any
   36.24 + * questions.
   36.25 + */
   36.26 +
   36.27 +/*
   36.28 + * @test
   36.29 + * @bug 8007464
   36.30 + * @summary Add graph inference support
   36.31 + *          smoke test for graph inference
   36.32 + * @compile TargetType56.java
   36.33 + */
   36.34 +class TargetType56 {
   36.35 +    <Z> Z m(Z z) { return null; }
   36.36 +
   36.37 +    void test() {
   36.38 +        double d1 = m(1);
   36.39 +        double d2 = m((Integer)null);
   36.40 +        double d3 = m(m(1));
   36.41 +        double d4 = m(m((Integer)null));
   36.42 +    }
   36.43 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/test/tools/javac/lambda/TargetType57.java	Tue Feb 12 19:25:09 2013 +0000
    37.3 @@ -0,0 +1,20 @@
    37.4 +/*
    37.5 + * @test /nodynamiccopyright/
    37.6 + * @bug 8007464
    37.7 + * @summary Add graph inference support
    37.8 + *          more smoke tests for graph inference
    37.9 + * @compile/fail/ref=TargetType57.out -XDrawDiagnostics TargetType57.java
   37.10 + */
   37.11 +import java.util.*;
   37.12 +import java.util.function.*;
   37.13 +
   37.14 +class TargetType57 {
   37.15 +
   37.16 +    void test(List<Integer> list) {
   37.17 +        m(list, s -> s.intValue(), s -> s.nonExistentMethod());
   37.18 +    }
   37.19 +
   37.20 +    <U, R, S_IN, S_OUT> R m(List<S_IN> list,
   37.21 +                        Function<S_IN, S_OUT> f1,
   37.22 +                        Function<S_OUT, R> f2) { return null; }
   37.23 +}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/test/tools/javac/lambda/TargetType57.out	Tue Feb 12 19:25:09 2013 +0000
    38.3 @@ -0,0 +1,2 @@
    38.4 +TargetType57.java:14:42: compiler.err.cant.resolve.location.args: kindname.method, nonExistentMethod, , , (compiler.misc.location.1: kindname.variable, s, java.lang.Integer)
    38.5 +1 error
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/test/tools/javac/lambda/TargetType58.java	Tue Feb 12 19:25:09 2013 +0000
    39.3 @@ -0,0 +1,46 @@
    39.4 +/*
    39.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    39.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    39.7 + *
    39.8 + * This code is free software; you can redistribute it and/or modify it
    39.9 + * under the terms of the GNU General Public License version 2 only, as
   39.10 + * published by the Free Software Foundation.
   39.11 + *
   39.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   39.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   39.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   39.15 + * version 2 for more details (a copy is included in the LICENSE file that
   39.16 + * accompanied this code).
   39.17 + *
   39.18 + * You should have received a copy of the GNU General Public License version
   39.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   39.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   39.21 + *
   39.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   39.23 + * or visit www.oracle.com if you need additional information or have any
   39.24 + * questions.
   39.25 + */
   39.26 +
   39.27 +/*
   39.28 + * @test
   39.29 + * @bug 8007464
   39.30 + * @summary Add graph inference support
   39.31 + *          more smoke tests for graph inference
   39.32 + * @ignore  awaits stream API: 800NNNN
   39.33 + * @compile TargetType58.java
   39.34 + */
   39.35 +import java.util.*;
   39.36 +import java.util.function.*;
   39.37 +import java.util.stream.*;
   39.38 +
   39.39 +class TargetType58 {
   39.40 +
   39.41 +    void test(List<Integer> li) {
   39.42 +        g(li, s -> s.substream(200), Collections.emptyList());
   39.43 +    }
   39.44 +
   39.45 +    <T, U, S_OUT extends Stream<U>,
   39.46 +            I extends Iterable<U>> Collection<U> g(Collection<T> coll, Function<Stream<T>, S_OUT> f, I i) {
   39.47 +        return null;
   39.48 +    }
   39.49 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/test/tools/javac/lambda/TargetType59.java	Tue Feb 12 19:25:09 2013 +0000
    40.3 @@ -0,0 +1,49 @@
    40.4 +/*
    40.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    40.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    40.7 + *
    40.8 + * This code is free software; you can redistribute it and/or modify it
    40.9 + * under the terms of the GNU General Public License version 2 only, as
   40.10 + * published by the Free Software Foundation.
   40.11 + *
   40.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   40.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   40.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   40.15 + * version 2 for more details (a copy is included in the LICENSE file that
   40.16 + * accompanied this code).
   40.17 + *
   40.18 + * You should have received a copy of the GNU General Public License version
   40.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   40.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   40.21 + *
   40.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   40.23 + * or visit www.oracle.com if you need additional information or have any
   40.24 + * questions.
   40.25 + */
   40.26 +
   40.27 +/*
   40.28 + * @test
   40.29 + * @bug 8007464
   40.30 + * @summary Add graph inference support
   40.31 + *          more smoke tests for graph inference
   40.32 + * @ignore  awaits stream API: 800NNNN
   40.33 + * @compile TargetType59.java
   40.34 + */
   40.35 +import java.util.*;
   40.36 +import java.util.function.*;
   40.37 +import java.util.stream.*;
   40.38 +
   40.39 +class TargetType59 {
   40.40 +
   40.41 +    <T, R> Collector<T, R> m(Supplier<? extends R> supplier, BiConsumer<R, T> accumulator) {
   40.42 +        return null;
   40.43 +    }
   40.44 +
   40.45 +    <T, C extends Collection<T>> Collector<T,C> test1(Supplier<C> collectionFactory) {
   40.46 +        return m(collectionFactory, Collection::add);
   40.47 +    }
   40.48 +
   40.49 +    Collector<String, StringBuilder> test2(Supplier<StringBuilder> sb) {
   40.50 +        return m(sb, StringBuilder::append);
   40.51 +    }
   40.52 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/test/tools/javac/lambda/TargetType61.java	Tue Feb 12 19:25:09 2013 +0000
    41.3 @@ -0,0 +1,47 @@
    41.4 +/*
    41.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    41.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.7 + *
    41.8 + * This code is free software; you can redistribute it and/or modify it
    41.9 + * under the terms of the GNU General Public License version 2 only, as
   41.10 + * published by the Free Software Foundation.
   41.11 + *
   41.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   41.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   41.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   41.15 + * version 2 for more details (a copy is included in the LICENSE file that
   41.16 + * accompanied this code).
   41.17 + *
   41.18 + * You should have received a copy of the GNU General Public License version
   41.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   41.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   41.21 + *
   41.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   41.23 + * or visit www.oracle.com if you need additional information or have any
   41.24 + * questions.
   41.25 + */
   41.26 +
   41.27 +/*
   41.28 + * @test
   41.29 + * @bug 8007464
   41.30 + * @summary Add graph inference support
   41.31 + *          check that new wildcards inference strategy doesn't run into 7190296
   41.32 + * @compile TargetType61.java
   41.33 + */
   41.34 +class TargetType61 {
   41.35 +
   41.36 +    interface Stream<T> {
   41.37 +        void forEach(Sink<? super T> sink);
   41.38 +    }
   41.39 +
   41.40 +    interface Sink<T> {
   41.41 +        void put(T t);
   41.42 +    }
   41.43 +
   41.44 +    public boolean add(CharSequence s) { return false; }
   41.45 +
   41.46 +    public void addAll(Stream<? extends CharSequence> stream) {
   41.47 +        stream.forEach(this::add);
   41.48 +        stream.forEach(e -> { add(e); });
   41.49 +    }
   41.50 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/test/tools/javac/lambda/TargetType62.java	Tue Feb 12 19:25:09 2013 +0000
    42.3 @@ -0,0 +1,46 @@
    42.4 +/*
    42.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    42.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    42.7 + *
    42.8 + * This code is free software; you can redistribute it and/or modify it
    42.9 + * under the terms of the GNU General Public License version 2 only, as
   42.10 + * published by the Free Software Foundation.
   42.11 + *
   42.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   42.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   42.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   42.15 + * version 2 for more details (a copy is included in the LICENSE file that
   42.16 + * accompanied this code).
   42.17 + *
   42.18 + * You should have received a copy of the GNU General Public License version
   42.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   42.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   42.21 + *
   42.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   42.23 + * or visit www.oracle.com if you need additional information or have any
   42.24 + * questions.
   42.25 + */
   42.26 +
   42.27 +/*
   42.28 + * @test
   42.29 + * @bug 8007464
   42.30 + * @summary Add graph inference support
   42.31 + *          check that new wildcards inference strategy doesn't run into 7190296
   42.32 + * @ignore  awaits stream API: 800NNNN
   42.33 + * @compile TargetType62.java
   42.34 + */
   42.35 +import java.util.*;
   42.36 +import java.util.function.*;
   42.37 +import java.util.stream.*;
   42.38 +
   42.39 +class TargetType61 {
   42.40 +
   42.41 +    Collector test(Function<Integer, Integer> classifier) {
   42.42 +        return g(classifier, TreeMap::new, m(HashSet::new));
   42.43 +    }
   42.44 +
   42.45 +    <R> Collector<Integer, R> m(Supplier<R> s) { return null; }
   42.46 +
   42.47 +    <T, K, D, M extends Map<K, D>>
   42.48 +            Collector<T, M> g(Function<T, K> classifier, Supplier<M> mapFactory, Collector<T, D> downstream) { return null; }
   42.49 +}

mercurial