/*******************************************************************************
 * Copyright (c) 2013, 2016 GK Software AG, and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Stephan Herrmann - initial API and implementation
 *     IBM Corporation - Bug fixes
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FunctionalExpression;
import org.eclipse.jdt.internal.compiler.ast.Invocation;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.util.Sorting;

/**
 * Main class for new type inference as per JLS8 sect 18.
 * Keeps contextual state and drives the algorithm.
 * 
 * <h2>Inference Basics</h2>
 * <ul>
 * <li>18.1.1 Inference variables: {@link InferenceVariable}</li>
 * <li>18.1.2 Constraint Formulas: subclasses of {@link ConstraintFormula}</li>
 * <li>18.1.3 Bounds: {@link TypeBound}<br/>
 * 	Capture bounds are directly captured in {@link BoundSet#captures}, throws-bounds in {@link BoundSet#inThrows}.<br/>
 * 	Also: {@link BoundSet}: main state during inference.</li>
 * </ul>
 * Each instance of {@link InferenceContext18} manages instances of the above and coordinates the inference process.
 * <h3>Queries and utilities</h3>
 * <ul>
 * <li>{@link TypeBinding#isProperType(boolean)}:
 * 	 used to exclude "types" that mention inference variables (18.1.1).</li>
 * <li>{@link TypeBinding#mentionsAny(TypeBinding[], int)}:
 * 	 does the receiver type binding mention any of the given types?</li>
 * <li>{@link TypeBinding#substituteInferenceVariable(InferenceVariable, TypeBinding)}:
 * 	 replace occurrences of an inference variable with a proper type.</li>
 * <li>{@link TypeBinding#collectInferenceVariables(Set)}:
 * 	 collect all inference variables mentioned in the receiver type into the given set.</li>
 * <li>{@link TypeVariableBinding#getTypeBounds(InferenceVariable, InferenceSubstitution)}:
 * 	Compute the initial type bounds for one inference variable as per JLS8 sect 18.1.3.</li>
 * </ul>
 * <h2>Phases of Inference</h2>
 * <ul>
 * <li>18.2 <b>Reduction</b>: {@link #reduce()} with most work happening in implementations of
 *  {@link ConstraintFormula#reduce(InferenceContext18)}:
 *  <ul>
 *  <li>18.2.1 Expression Compatibility Constraints: {@link ConstraintExpressionFormula#reduce(InferenceContext18)}.</li>
 *  <li>18.2.2 Type Compatibility Constraints ff. {@link ConstraintTypeFormula#reduce(InferenceContext18)}.</li>
 *  </ul></li>
 * <li>18.3 <b>Incorporation</b>: {@link BoundSet#incorporate(InferenceContext18)}; during inference new constraints
 * 	are accepted via {@link BoundSet#reduceOneConstraint(InferenceContext18, ConstraintFormula)} (combining 18.2 & 18.3)</li>
 * <li>18.4 <b>Resolution</b>: {@link #resolve(InferenceVariable[])}.
 * </ul>
 * Some of the above operations accumulate their results into {@link #currentBounds}, whereas
 * the last phase <em>returns</em> the resulting bound set while keeping the previous state in {@link #currentBounds}.
 * <h2>18.5. Uses of Inference</h2>
 * These are the main entries from the compiler into the inference engine:
 * <dl>
 * <dt>18.5.1 Invocation Applicability Inference</dt>
 * <dd>{@link #inferInvocationApplicability(MethodBinding, TypeBinding[], boolean)}. Prepare the initial state for
 * 	inference of a generic invocation - no target type used at this point.
 *  Need to call {@link #solve(boolean)} with true afterwards to produce the intermediate result.<br/>
 *  Called indirectly from {@link Scope#findMethod(ReferenceBinding, char[], TypeBinding[], InvocationSite, boolean)} et al
 *  to select applicable methods into overload resolution.</dd>
 * <dt>18.5.2 Invocation Type Inference</dt>
 * <dd>{@link InferenceContext18#inferInvocationType(TypeBinding, InvocationSite, MethodBinding)}. After a
 * 	most specific method has been picked, and given a target type determine the final generic instantiation.
 *  As long as a target type is still unavailable this phase keeps getting deferred.</br>
 *  Different wrappers exist for the convenience of different callers.</dd>
 * <dt>18.5.3 Functional Interface Parameterization Inference</dt>
 * <dd>Controlled from {@link LambdaExpression#resolveType(BlockScope)}.</dd>
 * <dt>18.5.4 More Specific Method Inference</dt>
 * <dd><em>Not Yet Implemented</em></dd>
 * </dl>
 * For 18.5.1 and 18.5.2 high-level control is implemented in
 *  {@link ParameterizedGenericMethodBinding#computeCompatibleMethod(MethodBinding, TypeBinding[], Scope, InvocationSite)}.
 * <h2>Inference Lifecycle</h2>
 * <li>Decision whether or not an invocation is a <b>variable-arity</b> invocation is made by first attempting
 * 		to solve 18.5.1 in mode {@link #CHECK_LOOSE}. Only if that fails, another attempt is made in mode {@link #CHECK_VARARG}.
 * 		Which of these two attempts was successful is stored in {@link #inferenceKind}.
 * 		This field must be consulted whenever arguments of an invocation should be further processed.
 * 		See also {@link #getParameter(TypeBinding[], int, boolean)} and its clients.</li>
 * </ul>
 */
public class InferenceContext18 {

	/** to conform with javac regarding https://bugs.openjdk.java.net/browse/JDK-8026527 */
	static final boolean SIMULATE_BUG_JDK_8026527 = true;
	
	/** Temporary workaround until we know fully what to do with https://bugs.openjdk.java.net/browse/JDK-8054721 
	 *  It looks likely that we have a bug independent of this JLS bug in that we clear the capture bounds eagerly.
	*/
	static final boolean SHOULD_WORKAROUND_BUG_JDK_8054721 = true; // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=437444#c24 onwards
	
	static final boolean SHOULD_WORKAROUND_BUG_JDK_8153748 = true; // emulating javac behaviour after private email communication
	
	/**
	 * Detail flag to control the extent of {@link #SIMULATE_BUG_JDK_8026527}.
	 * A setting of 'false' implements the advice from http://mail.openjdk.java.net/pipermail/lambda-spec-experts/2013-December/000447.html
	 * i.e., raw types are not considered as compatible in constraints/bounds derived from invocation arguments,
	 * but only for constraints derived from type variable bounds.
	 */
	static final boolean ARGUMENT_CONSTRAINTS_ARE_SOFT = false;

	// --- Main State of the Inference: ---

	/** the invocation being inferred (for 18.5.1 and 18.5.2) */
	InvocationSite currentInvocation;
	/** arguments of #currentInvocation, if any */
	Expression[] invocationArguments;
	
	/** The inference variables for which as solution is sought. */
	InferenceVariable[] inferenceVariables;

	/** Constraints that have not yet been reduced and incorporated. */
	ConstraintFormula[] initialConstraints;
	ConstraintExpressionFormula[] finalConstraints; // for final revalidation at a "macroscopic" level

	/** The accumulated type bounds etc. */
	BoundSet currentBounds;

	/** One of CHECK_STRICT, CHECK_LOOSE, or CHECK_VARARGS. */
	int inferenceKind;
	/** Marks how much work has been done so far? Used to avoid performing any of these tasks more than once. */
	public int stepCompleted = NOT_INFERRED;

	public static final int NOT_INFERRED = 0;
	/** Applicability Inference (18.5.1) has been completed. */
	public static final int APPLICABILITY_INFERRED = 1;
	/** Invocation Type Inference (18.5.2) has been completed (for some target type). */
	public static final int TYPE_INFERRED = 2;
	
	/** Signals whether any type compatibility makes use of unchecked conversion. */
	public List<ConstraintFormula> constraintsWithUncheckedConversion;
	public boolean usesUncheckedConversion;
	public InferenceContext18 outerContext;
	Scope scope;
	LookupEnvironment environment;
	ReferenceBinding object; // java.lang.Object
	public BoundSet b2;
	private BoundSet b3;
	/** Not per JLS: inbox for emulation of how javac passes type bounds from inner to outer */
	private BoundSet innerInbox; 
	/** Not per JLS: signal when current is ready to directly merge all bounds from inner. */
	private boolean directlyAcceptingInnerBounds = false;
	
	public static boolean isSameSite(InvocationSite site1, InvocationSite site2) {
		if (site1 == site2)
			return true;
		if (site1 == null || site2 == null)
			return false;
		if (site1.sourceStart() == site2.sourceStart() && site1.sourceEnd() == site2.sourceEnd())
			return true;
		return false;
	}

	public static final int CHECK_UNKNOWN = 0;
	public static final int CHECK_STRICT = 1;
	public static final int CHECK_LOOSE = 2;
	public static final int CHECK_VARARG = 3;
	
	static class SuspendedInferenceRecord {
		InvocationSite site;
		Expression[] invocationArguments;
		InferenceVariable[] inferenceVariables;
		int inferenceKind;
		boolean usesUncheckedConversion;
		SuspendedInferenceRecord(InvocationSite site, Expression[] invocationArguments, InferenceVariable[] inferenceVariables, int inferenceKind, boolean usesUncheckedConversion) {
			this.site = site;
			this.invocationArguments = invocationArguments;
			this.inferenceVariables = inferenceVariables;
			this.inferenceKind = inferenceKind;
			this.usesUncheckedConversion = usesUncheckedConversion;
		}
	}
	
	/** Construct an inference context for an invocation (method/constructor). */
	public InferenceContext18(Scope scope, Expression[] arguments, InvocationSite site, InferenceContext18 outerContext) {
		this.scope = scope;
		this.environment = scope.environment();
		this.object = scope.getJavaLangObject();
		this.invocationArguments = arguments;
		this.currentInvocation = site;
		this.outerContext = outerContext;
		if (site instanceof Invocation)
			scope.compilationUnitScope().registerInferredInvocation((Invocation) site);
	}

	public InferenceContext18(Scope scope) {
		this.scope = scope;
		this.environment = scope.environment();
		this.object = scope.getJavaLangObject();
	}

	/**
	 * JLS 18.1.3: Create initial bounds from a given set of type parameters declarations.
	 * @return the set of inference variables created for the given typeParameters
	 */
	public InferenceVariable[] createInitialBoundSet(TypeVariableBinding[] typeParameters) {
		// 
		if (this.currentBounds == null) {
			this.currentBounds = new BoundSet();
		}
		if (typeParameters != null) {
			InferenceVariable[] newInferenceVariables = addInitialTypeVariableSubstitutions(typeParameters);
			this.currentBounds.addBoundsFromTypeParameters(this, typeParameters, newInferenceVariables);
			return newInferenceVariables;
		}
		return Binding.NO_INFERENCE_VARIABLES;
	}

	/**
	 * Substitute any type variables mentioned in 'type' by the corresponding inference variable, if one exists. 
	 */
	public TypeBinding substitute(TypeBinding type) {
		InferenceSubstitution inferenceSubstitution = new InferenceSubstitution(this);
		return 	inferenceSubstitution.substitute(inferenceSubstitution, type);
	}

	/** JLS 18.5.1: compute bounds from formal and actual parameters. */
	public void createInitialConstraintsForParameters(TypeBinding[] parameters, boolean checkVararg, TypeBinding varArgsType, MethodBinding method) {
		if (this.invocationArguments == null)
			return;
		int len = checkVararg ? parameters.length - 1 : Math.min(parameters.length, this.invocationArguments.length);
		int maxConstraints = checkVararg ? this.invocationArguments.length : len;
		int numConstraints = 0;
		boolean ownConstraints;
		if (this.initialConstraints == null) {
			this.initialConstraints = new ConstraintFormula[maxConstraints];
			ownConstraints = true;
		} else {
			numConstraints = this.initialConstraints.length;
			maxConstraints += numConstraints;
			System.arraycopy(this.initialConstraints, 0,
					this.initialConstraints=new ConstraintFormula[maxConstraints], 0, numConstraints);
			ownConstraints = false; // these are lifted from a nested poly expression.
		}
		for (int i = 0; i < len; i++) {
			TypeBinding thetaF = substitute(parameters[i]);
			if (this.invocationArguments[i].isPertinentToApplicability(parameters[i], method)) {
				this.initialConstraints[numConstraints++] = new ConstraintExpressionFormula(this.invocationArguments[i], thetaF, ReductionResult.COMPATIBLE, ARGUMENT_CONSTRAINTS_ARE_SOFT);
			} else if (!isTypeVariableOfCandidate(parameters[i], method)) {
				this.initialConstraints[numConstraints++] = new ConstraintExpressionFormula(this.invocationArguments[i], thetaF, ReductionResult.POTENTIALLY_COMPATIBLE);
			} // else we know it is potentially compatible, no need to assert.
		}
		if (checkVararg && varArgsType instanceof ArrayBinding) {
			varArgsType = ((ArrayBinding)varArgsType).elementsType();
			TypeBinding thetaF = substitute(varArgsType);
			for (int i = len; i < this.invocationArguments.length; i++) {
				if (this.invocationArguments[i].isPertinentToApplicability(varArgsType, method)) {
					this.initialConstraints[numConstraints++] = new ConstraintExpressionFormula(this.invocationArguments[i], thetaF, ReductionResult.COMPATIBLE, ARGUMENT_CONSTRAINTS_ARE_SOFT);
				} else if (!isTypeVariableOfCandidate(varArgsType, method)) {
					this.initialConstraints[numConstraints++] = new ConstraintExpressionFormula(this.invocationArguments[i], thetaF, ReductionResult.POTENTIALLY_COMPATIBLE);
				} // else we know it is potentially compatible, no need to assert.
			}
		}
		if (numConstraints == 0)
			this.initialConstraints = ConstraintFormula.NO_CONSTRAINTS;
		else if (numConstraints < maxConstraints)
			System.arraycopy(this.initialConstraints, 0, this.initialConstraints = new ConstraintFormula[numConstraints], 0, numConstraints);
		if (ownConstraints) { // lifted constraints get validated at their own context.
			final int length = this.initialConstraints.length;
			System.arraycopy(this.initialConstraints, 0, this.finalConstraints = new ConstraintExpressionFormula[length], 0, length);
		}
	}

	private boolean isTypeVariableOfCandidate(TypeBinding type, MethodBinding candidate) {
		// cf. FunctionalExpression.isPertinentToApplicability()
		if (type instanceof TypeVariableBinding) {
			Binding declaringElement = ((TypeVariableBinding) type).declaringElement;
			if (declaringElement == candidate)
				return true;
			if (candidate.isConstructor() && declaringElement == candidate.declaringClass)
				return true;
		}
		return false;
	}

	private InferenceVariable[] addInitialTypeVariableSubstitutions(TypeBinding[] typeVariables) {
		int len = typeVariables.length;
		if (len == 0) {
			if (this.inferenceVariables == null)
				this.inferenceVariables = Binding.NO_INFERENCE_VARIABLES;
			return Binding.NO_INFERENCE_VARIABLES;
		}
		InferenceVariable[] newVariables = new InferenceVariable[len];
		for (int i = 0; i < len; i++)
			newVariables[i] = InferenceVariable.get(typeVariables[i], i, this.currentInvocation, this.scope, this.object);
		addInferenceVariables(newVariables);
		return newVariables;
	}

	private void addInferenceVariables(InferenceVariable[] newVariables) {
		if (this.inferenceVariables == null || this.inferenceVariables.length == 0) {
			this.inferenceVariables = newVariables;
		} else {
			// merge into this.inferenceVariables:
			int len = newVariables.length;
			int prev = this.inferenceVariables.length;
			System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables = new InferenceVariable[len+prev], 0, prev);
			System.arraycopy(newVariables, 0, this.inferenceVariables, prev, len);
		}
	}

	/** Add new inference variables for the given type variables. */
	public InferenceVariable[] addTypeVariableSubstitutions(TypeBinding[] typeVariables) {
		int len2 = typeVariables.length;
		InferenceVariable[] newVariables = new InferenceVariable[len2];
		InferenceVariable[] toAdd = new InferenceVariable[len2];
		int numToAdd = 0;
		for (int i = 0; i < typeVariables.length; i++) {
			if (typeVariables[i] instanceof InferenceVariable)
				newVariables[i] = (InferenceVariable) typeVariables[i]; // prevent double substitution of an already-substituted inferenceVariable
			else
				toAdd[numToAdd++] =
					newVariables[i] = InferenceVariable.get(typeVariables[i], i, this.currentInvocation, this.scope, this.object);
		}
		if (numToAdd > 0) {
			int start = 0;
			if (this.inferenceVariables != null) {
				int len1 = this.inferenceVariables.length;
				System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables = new InferenceVariable[len1+numToAdd], 0, len1);
				start = len1;
			} else {
				this.inferenceVariables = new InferenceVariable[numToAdd];
			}
			System.arraycopy(toAdd, 0, this.inferenceVariables, start, numToAdd);
		}
		return newVariables;
	}

	/** JLS 18.1.3 Bounds: throws α: the inference variable α appears in a throws clause */
	public void addThrowsContraints(TypeBinding[] parameters, InferenceVariable[] variables, ReferenceBinding[] thrownExceptions) {
		for (int i = 0; i < parameters.length; i++) {
			TypeBinding parameter = parameters[i];
			for (int j = 0; j < thrownExceptions.length; j++) {
				if (TypeBinding.equalsEquals(parameter, thrownExceptions[j])) {
					this.currentBounds.inThrows.add(variables[i].prototype());
					break;
				}
			}
		}		
	}

	/** JLS 18.5.1 Invocation Applicability Inference. */
	public void inferInvocationApplicability(MethodBinding method, TypeBinding[] arguments, boolean isDiamond) {
		ConstraintExpressionFormula.inferInvocationApplicability(this, method, arguments, isDiamond, this.inferenceKind);
	}

	/** Perform steps from JLS 18.5.2. needed for computing the bound set B3. */
	boolean computeB3(InvocationSite invocationSite, TypeBinding targetType, MethodBinding method) 
				throws InferenceFailureException 
	{
		boolean result = ConstraintExpressionFormula.inferPolyInvocationType(this, invocationSite, targetType, method);
		if (result) {
			mergeInnerBounds();
			if (this.b3 == null)
				this.b3 = this.currentBounds.copy();
		}
		return result;
	}

	/** JLS 18.5.2 Invocation Type Inference 
	 */
	public BoundSet inferInvocationType(TypeBinding expectedType, InvocationSite invocationSite, MethodBinding method) throws InferenceFailureException 
	{
		// not JLS: simply ensure that null hints from the return type have been seen even in standalone contexts:
		if (expectedType == null && method.returnType != null)
			substitute(method.returnType); // result is ignore, the only effect is on InferenceVariable.nullHints
		
		this.currentBounds = this.b2.copy();
		
		try {
			// bullets 1&2: definitions only.
			if (expectedType != null
					&& expectedType != TypeBinding.VOID
					&& invocationSite instanceof Expression
					&& ((Expression)invocationSite).isPolyExpression(method)) 
			{
				// 3. bullet: special treatment for poly expressions
				if (!computeB3(invocationSite, expectedType, method)) {
					return null;
				}
			} else {
				mergeInnerBounds();
				this.b3 = this.currentBounds.copy();
			}

			if (SHOULD_WORKAROUND_BUG_JDK_8153748) { // "before 18.5.2", but should not spill into b3 ... (heuristically)
				ReductionResult jdk8153748result = addJDK_8153748ConstraintsFromInvocation(this.invocationArguments, method);
				if (jdk8153748result != null) {
					this.currentBounds.incorporate(this);
				}
			}

			pushBoundsToOuter();
			this.directlyAcceptingInnerBounds = true;

			// 4. bullet: assemble C:
			Set<ConstraintFormula> c = new HashSet<ConstraintFormula>();
			if (!addConstraintsToC(this.invocationArguments, c, method, this.inferenceKind, invocationSite))
				return null;
			// 5. bullet: determine B4 from C
			List<Set<InferenceVariable>> components = this.currentBounds.computeConnectedComponents(this.inferenceVariables);
			while (!c.isEmpty()) {
				// *
				Set<ConstraintFormula> bottomSet = findBottomSet(c, allOutputVariables(c), components);
				if (bottomSet.isEmpty()) {
					bottomSet.add(pickFromCycle(c));
				}
				// *
				c.removeAll(bottomSet);
				// * The union of the input variables of all the selected constraints, α1, ..., αm, ...
				Set<InferenceVariable> allInputs = new HashSet<InferenceVariable>();
				Iterator<ConstraintFormula> bottomIt = bottomSet.iterator();
				while (bottomIt.hasNext()) {
					allInputs.addAll(bottomIt.next().inputVariables(this));
				}
				InferenceVariable[] variablesArray = allInputs.toArray(new InferenceVariable[allInputs.size()]);
				//   ... is resolved
				if (!this.currentBounds.incorporate(this))
					return null;
				BoundSet solution = resolve(variablesArray);
				// in rare cases resolving just one set of variables doesn't suffice,
				// don't bother with finding the necessary superset, just resolve all:
				if (solution == null)
					solution = resolve(this.inferenceVariables);
				// * ~ apply substitutions to all constraints: 
				bottomIt = bottomSet.iterator();
				while (bottomIt.hasNext()) {
					ConstraintFormula constraint = bottomIt.next();
					if (solution != null)
						if (!constraint.applySubstitution(solution, variablesArray))
							return null;
				// * reduce and incorporate
					if (!this.currentBounds.reduceOneConstraint(this, constraint))
						return null;
				}
			}
			// 6. bullet: solve
			BoundSet solution = solve();
			if (solution == null || !isResolved(solution)) {
				this.currentBounds = this.b2; // don't let bounds from unsuccessful attempt leak into subsequent attempts
				return null;
			}
			// we're done, start reporting:
			reportUncheckedConversions(solution);
			return this.currentBounds = solution; // this is final, keep the result:
		} finally {
			this.stepCompleted = TYPE_INFERRED;
		}
	}

	// ---  not per JLS: emulate how javac passes type bounds from inner to outer: ---
	/** Not per JLS: push current bounds to outer inference if outer is ready for it. */
	private void pushBoundsToOuter() {
		InferenceContext18 outer = this.outerContext;
		if (outer != null && outer.stepCompleted >= APPLICABILITY_INFERRED) {
			if (outer.directlyAcceptingInnerBounds) {
				outer.currentBounds.addBounds(this.currentBounds, this.environment);
			} else if (outer.innerInbox == null) {
				outer.innerInbox = this.currentBounds.copy();
			} else {
				outer.innerInbox.addBounds(this.currentBounds, this.environment);
			}
		}
	}
	/** Not JLS: merge pending bounds of inner inference into current. */
	private void mergeInnerBounds() {
		if (this.innerInbox != null) {
			this.currentBounds.addBounds(this.innerInbox, this.environment);
			this.innerInbox = null;
		}
	}

	interface InferenceOperation {
		boolean perform() throws InferenceFailureException;
	}
	/** Not per JLS: if operation succeeds merge new bounds from inner into current. */
	private boolean collectingInnerBounds(InferenceOperation operation) throws InferenceFailureException {
		boolean result = operation.perform();
		if (result)
			mergeInnerBounds();
		else
			this.innerInbox = null;
		return result;
	}
	// ---

	private ReductionResult addJDK_8153748ConstraintsFromInvocation(Expression[] arguments, MethodBinding method) throws InferenceFailureException {
		// not per JLS, trying to mimic javac behavior
		boolean constraintAdded = false;
		if (arguments != null) {
			for (int i = 0; i < arguments.length; i++) {
				Expression argument = arguments[i];
				TypeBinding parameter = getParameter(method.parameters, i, method.isVarargs());
				parameter = this.substitute(parameter);
				ReductionResult result = addJDK_8153748ConstraintsFromExpression(argument, parameter, method);
				if (result == ReductionResult.FALSE)
					return ReductionResult.FALSE;
				if (result == ReductionResult.TRUE)
					constraintAdded = true;
			}
		}
		return constraintAdded ? ReductionResult.TRUE : null;
	}

	private ReductionResult addJDK_8153748ConstraintsFromExpression(Expression argument, TypeBinding parameter, MethodBinding method) throws InferenceFailureException {
		if (argument instanceof FunctionalExpression) {
			return addJDK_8153748ConstraintsFromFunctionalExpr((FunctionalExpression) argument, parameter, method);
		} else if (argument instanceof Invocation && argument.isPolyExpression(method)) {
			Invocation invocation = (Invocation) argument;
			Expression[] innerArgs = invocation.arguments();
			MethodBinding innerMethod = invocation.binding();
			if (innerMethod != null && innerMethod.isValidBinding()) {
				return addJDK_8153748ConstraintsFromInvocation(innerArgs, innerMethod.original());
			}
		} else if (argument instanceof ConditionalExpression) {
			ConditionalExpression ce = (ConditionalExpression) argument;
			if (addJDK_8153748ConstraintsFromExpression(ce.valueIfTrue, parameter, method) == ReductionResult.FALSE)
				return ReductionResult.FALSE;
			return addJDK_8153748ConstraintsFromExpression(ce.valueIfFalse, parameter, method);
		}
		return null;
	}

	private ReductionResult addJDK_8153748ConstraintsFromFunctionalExpr(FunctionalExpression functionalExpr, TypeBinding targetType, MethodBinding method) throws InferenceFailureException {
		if (!functionalExpr.isPertinentToApplicability(targetType, method)) {
			ConstraintFormula exprConstraint = new ConstraintExpressionFormula(functionalExpr, targetType, ReductionResult.COMPATIBLE, ARGUMENT_CONSTRAINTS_ARE_SOFT);
			if (collectingInnerBounds(() -> exprConstraint.inputVariables(this).isEmpty())) { // input variable would signal: not ready for inference
				if (!collectingInnerBounds(() -> reduceAndIncorporate(exprConstraint)))
					return ReductionResult.FALSE;
				ConstraintFormula excConstraint = new ConstraintExceptionFormula(functionalExpr, targetType); // ??
				if (!collectingInnerBounds(() -> reduceAndIncorporate(excConstraint)))
					return ReductionResult.FALSE;
				return ReductionResult.TRUE;
			}
		}
		return null;
	}

	private boolean addConstraintsToC(Expression[] exprs, Set<ConstraintFormula> c, MethodBinding method, int inferenceKindForMethod, InvocationSite site)
			throws InferenceFailureException
	{
		TypeBinding[] fs;
		if (exprs != null) {
			int k = exprs.length;
			int p = method.parameters.length;
			if (method.isVarargs()) {
				if (k < p - 1) return false;
			} else if (k != p) {
				return false;
			}
			switch (inferenceKindForMethod) {
				case CHECK_STRICT:
				case CHECK_LOOSE:
					fs = method.parameters;
					break;
				case CHECK_VARARG:
					fs = varArgTypes(method.parameters, k);
					break;
				default:
					throw new IllegalStateException("Unexpected checkKind "+this.inferenceKind); //$NON-NLS-1$
			}
			for (int i = 0; i < k; i++) {
				TypeBinding fsi = fs[Math.min(i, p-1)];
				InferenceSubstitution inferenceSubstitution = new InferenceSubstitution(this.environment, this.inferenceVariables, site);
				TypeBinding substF = inferenceSubstitution.substitute(inferenceSubstitution,fsi);
				if (!addConstraintsToC_OneExpr(exprs[i], c, fsi, substF, method))
					return false;
	        }
		}
		return true;
	}

	private boolean addConstraintsToC_OneExpr(Expression expri, Set<ConstraintFormula> c, TypeBinding fsi, TypeBinding substF, MethodBinding method)
			throws InferenceFailureException
	{
		// -- not per JLS, emulate javac behavior:
		substF = Scope.substitute(getResultSubstitution(this.b3), substF);
		// --

		// For all i (1 ≤ i ≤ k), if ei is not pertinent to applicability, the set contains ⟨ei → θ Fi⟩.
		if (!expri.isPertinentToApplicability(fsi, method)) {
			c.add(new ConstraintExpressionFormula(expri, substF, ReductionResult.COMPATIBLE, ARGUMENT_CONSTRAINTS_ARE_SOFT));
		}
		if (expri instanceof FunctionalExpression) {
			c.add(new ConstraintExceptionFormula((FunctionalExpression) expri, substF));
			if (expri instanceof LambdaExpression) {
				// https://bugs.openjdk.java.net/browse/JDK-8038747
				LambdaExpression lambda = (LambdaExpression) expri;
				BlockScope skope = lambda.enclosingScope;
				if (substF.isFunctionalInterface(skope)) { // could be an inference variable.
					ReferenceBinding t = (ReferenceBinding) substF;
					ParameterizedTypeBinding withWildCards = InferenceContext18.parameterizedWithWildcard(t);
					if (withWildCards != null) {
						t = ConstraintExpressionFormula.findGroundTargetType(this, skope, lambda, withWildCards);
					}
					MethodBinding functionType;
					if (t != null && (functionType = t.getSingleAbstractMethod(skope, true)) != null && (lambda = lambda.resolveExpressionExpecting(t, this.scope, this)) != null) {
						TypeBinding r = functionType.returnType;
						Expression[] resultExpressions = lambda.resultExpressions();
						for (int i = 0, length = resultExpressions == null ? 0 : resultExpressions.length; i < length; i++) {
							Expression resultExpression = resultExpressions[i];
							if (!addConstraintsToC_OneExpr(resultExpression, c, r.original(), r, method))
								return false;
						}
					}
				}
			}
		} else if (expri instanceof Invocation && expri.isPolyExpression()) {

			if (substF.isProperType(true)) // https://bugs.openjdk.java.net/browse/JDK-8052325 
				return true;

			Invocation invocation = (Invocation) expri;
			MethodBinding innerMethod = invocation.binding();
			if (innerMethod == null)
				return true; 		  // -> proceed with no new C set elements.
			
			Expression[] arguments = invocation.arguments();
			TypeBinding[] argumentTypes = arguments == null ? Binding.NO_PARAMETERS : new TypeBinding[arguments.length];
			for (int i = 0; i < argumentTypes.length; i++)
				argumentTypes[i] = arguments[i].resolvedType;
			InferenceContext18 innerContext = null;
			if (innerMethod instanceof ParameterizedGenericMethodBinding)
				 innerContext = invocation.getInferenceContext((ParameterizedGenericMethodBinding) innerMethod);
			
			if (innerContext != null) {
				MethodBinding shallowMethod = innerMethod.shallowOriginal();
				innerContext.outerContext = this;
				if (innerContext.stepCompleted < InferenceContext18.APPLICABILITY_INFERRED) // shouldn't happen, but let's play safe
					innerContext.inferInvocationApplicability(shallowMethod, argumentTypes, shallowMethod.isConstructor());
				if (!innerContext.computeB3(invocation, substF, shallowMethod))
					return false;
				return innerContext.addConstraintsToC(arguments, c, innerMethod.genericMethod(), innerContext.inferenceKind, invocation);
			} else {
				int applicabilityKind = getInferenceKind(innerMethod, argumentTypes);
				return this.addConstraintsToC(arguments, c, innerMethod.genericMethod(), applicabilityKind, invocation);
			}
		} else if (expri instanceof ConditionalExpression) {
			ConditionalExpression ce = (ConditionalExpression) expri;
			return addConstraintsToC_OneExpr(ce.valueIfTrue, c, fsi, substF, method)
					&& addConstraintsToC_OneExpr(ce.valueIfFalse, c, fsi, substF, method);
		}
		return true;
	}

	
	protected int getInferenceKind(MethodBinding nonGenericMethod, TypeBinding[] argumentTypes) {
		switch (this.scope.parameterCompatibilityLevel(nonGenericMethod, argumentTypes)) {
			case Scope.AUTOBOX_COMPATIBLE:
				return CHECK_LOOSE;
			case Scope.VARARGS_COMPATIBLE:
				return CHECK_VARARG;
			default:
				return CHECK_STRICT;
		}
	}

	/**
	 * 18.5.3 Functional Interface Parameterization Inference
	 */
	public ReferenceBinding inferFunctionalInterfaceParameterization(LambdaExpression lambda, BlockScope blockScope, 
			ParameterizedTypeBinding targetTypeWithWildCards) 
	{
		TypeBinding[] q = createBoundsForFunctionalInterfaceParameterizationInference(targetTypeWithWildCards);
		if (q == null || q.length != lambda.arguments().length) {
			// fail  TODO: can this still happen here?
		} else {
			if (reduceWithEqualityConstraints(lambda.argumentTypes(), q)) {
				ReferenceBinding genericType = targetTypeWithWildCards.genericType();
				TypeBinding[] a = targetTypeWithWildCards.arguments; // a is not-null by construction of parameterizedWithWildcard()
				TypeBinding[] aprime = getFunctionInterfaceArgumentSolutions(a);
				// TODO If F<A'1, ..., A'm> is a well-formed type, ...
				return blockScope.environment().createParameterizedType(genericType, aprime, targetTypeWithWildCards.enclosingType());
			}
		}
		return targetTypeWithWildCards;
	}

	/**
	 * Create initial bound set for 18.5.3 Functional Interface Parameterization Inference
	 * @param functionalInterface the functional interface F<A1,..Am>
	 * @return the parameter types Q1..Qk of the function type of the type F<α1, ..., αm>, or null 
	 */
	TypeBinding[] createBoundsForFunctionalInterfaceParameterizationInference(ParameterizedTypeBinding functionalInterface) {
		if (this.currentBounds == null)
			this.currentBounds = new BoundSet();
		TypeBinding[] a = functionalInterface.arguments;
		if (a == null)
			return null;
		InferenceVariable[] alpha = addInitialTypeVariableSubstitutions(a);

		for (int i = 0; i < a.length; i++) {
			TypeBound bound;
			if (a[i].kind() == Binding.WILDCARD_TYPE) {
				WildcardBinding wildcard = (WildcardBinding) a[i];
				switch(wildcard.boundKind) {
    				case Wildcard.EXTENDS :
    					bound = new TypeBound(alpha[i], wildcard.allBounds(), ReductionResult.SUBTYPE);
    					break;
    				case Wildcard.SUPER :
    					bound = new TypeBound(alpha[i], wildcard.bound, ReductionResult.SUPERTYPE);
    					break;
    				case Wildcard.UNBOUND :
    					bound = new TypeBound(alpha[i], this.object, ReductionResult.SUBTYPE);
    					break;
    				default:
    					continue; // cannot
				}
			} else {
				bound = new TypeBound(alpha[i], a[i], ReductionResult.SAME);
			}
			this.currentBounds.addBound(bound, this.environment);
		}
		TypeBinding falpha = substitute(functionalInterface);
		return falpha.getSingleAbstractMethod(this.scope, true).parameters;
	}

	public boolean reduceWithEqualityConstraints(TypeBinding[] p, TypeBinding[] q) {
		if (p != null) {
			for (int i = 0; i < p.length; i++) {
				try {
					if (!this.reduceAndIncorporate(ConstraintTypeFormula.create(p[i], q[i], ReductionResult.SAME)))
						return false;
				} catch (InferenceFailureException e) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 18.5.4 More Specific Method Inference
	 */
	public boolean isMoreSpecificThan(MethodBinding m1, MethodBinding m2, boolean isVarArgs, boolean isVarArgs2) {
		// TODO: we don't yet distinguish vararg-with-passthrough from vararg-with-exactly-one-vararg-arg
		if (isVarArgs != isVarArgs2) {
			return isVarArgs2;
		}
		Expression[] arguments = this.invocationArguments;
		int numInvocArgs = arguments == null ? 0 : arguments.length;
		TypeVariableBinding[] p = m2.typeVariables();
		TypeBinding[] s = m1.parameters;
		TypeBinding[] t = new TypeBinding[m2.parameters.length];
		createInitialBoundSet(p);
		for (int i = 0; i < t.length; i++)
			t[i] = substitute(m2.parameters[i]);

		try {
			for (int i = 0; i < numInvocArgs; i++) {
				TypeBinding si = getParameter(s, i, isVarArgs);
				TypeBinding ti = getParameter(t, i, isVarArgs);
				Boolean result = moreSpecificMain(si, ti, this.invocationArguments[i]);
				if (result == Boolean.FALSE)
					return false;
				if (result == null)
					if (!reduceAndIncorporate(ConstraintTypeFormula.create(si, ti, ReductionResult.SUBTYPE)))
						return false;
			}
			if (t.length == numInvocArgs + 1) {
				TypeBinding skplus1 = getParameter(s, numInvocArgs, true);
				TypeBinding tkplus1 = getParameter(t, numInvocArgs, true);
				if (!reduceAndIncorporate(ConstraintTypeFormula.create(skplus1, tkplus1, ReductionResult.SUBTYPE)))
					return false;
			}
			return solve() != null;
		} catch (InferenceFailureException e) {
			return false;
		}
	}
	
	// FALSE: inference fails
	// TRUE:  constraints have been incorporated
	// null:  need to create the si <: ti constraint
	private Boolean moreSpecificMain(TypeBinding si, TypeBinding ti, Expression expri) throws InferenceFailureException {
		if (si.isProperType(true) && ti.isProperType(true)) {
			return expri.sIsMoreSpecific(si, ti, this.scope) ? Boolean.TRUE : Boolean.FALSE;
		}
		// "if Ti is not a functional interface type" specifically requests the si <: ti constraint created by our caller
		if (!ti.isFunctionalInterface(this.scope))
			return null;

		TypeBinding funcI = ti.original();
		// "It must be determined whether Si satisfies the following five conditions:"
		// (we negate each condition for early exit):
		if (si.isFunctionalInterface(this.scope)) {			// bullet 1
			if (siSuperI(si, funcI) || siSubI(si, funcI))
				return null;								// bullets 2 & 3
			if (si instanceof IntersectionTypeBinding18) {
				TypeBinding[] elements = ((IntersectionTypeBinding18)si).intersectingTypes;
				checkSuper: {
					for (int i = 0; i < elements.length; i++)
						if (!siSuperI(elements[i], funcI))
							break checkSuper;
					return null;							// bullet 4 
					// each element of the intersection is a superinterface of I, or a parameterization of a superinterface of I.
				}
				for (int i = 0; i < elements.length; i++)
					if (siSubI(elements[i], funcI))
						return null;						// bullet 5
						// some element of the intersection is a subinterface of I, or a parameterization of a subinterface of I.	
			}
			// all passed, time to do some work:
			TypeBinding siCapture = si.capture(this.scope, expri.sourceStart, expri.sourceEnd);
			MethodBinding sam = siCapture.getSingleAbstractMethod(this.scope, false); // no wildcards should be left needing replacement
			TypeBinding[] u = sam.parameters;
			TypeBinding r1 = sam.isConstructor() ? sam.declaringClass : sam.returnType;
			sam = ti.getSingleAbstractMethod(this.scope, true); // TODO
			TypeBinding[] v = sam.parameters;
			TypeBinding r2 = sam.isConstructor() ? sam.declaringClass : sam.returnType;
			return Boolean.valueOf(checkExpression(expri, u, r1, v, r2));
		}
		return null;
	}

	private boolean checkExpression(Expression expri, TypeBinding[] u, TypeBinding r1, TypeBinding[] v, TypeBinding r2) 
			throws InferenceFailureException {
		if (expri instanceof LambdaExpression && !((LambdaExpression)expri).argumentsTypeElided()) {
			for (int i = 0; i < u.length; i++) {
				if (!reduceAndIncorporate(ConstraintTypeFormula.create(u[i], v[i], ReductionResult.SAME)))
					return false;
			}
			if (r2.id == TypeIds.T_void)
				return true;
			LambdaExpression lambda = (LambdaExpression) expri;
			Expression[] results = lambda.resultExpressions();
			if (results != Expression.NO_EXPRESSIONS) {
				if (r1.isFunctionalInterface(this.scope) && r2.isFunctionalInterface(this.scope)
						&& !(r1.isCompatibleWith(r2) || r2.isCompatibleWith(r1))) {
					// "these rules are applied recursively to R1 and R2, for each result expression in expi."
					// (what does "applied .. to R1 and R2" mean? Why mention R1/R2 and not U/V?)
					for (int i = 0; i < results.length; i++) {
						if (!checkExpression(results[i], u, r1, v, r2))
							return false;
					}
					return true;
				}
				checkPrimitive1: if (r1.isPrimitiveType() && !r2.isPrimitiveType()) {
					// check: each result expression is a standalone expression of a primitive type
					for (int i = 0; i < results.length; i++) {
						if (results[i].isPolyExpression() || (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType()))
							break checkPrimitive1;
					}
					return true;
				}
				checkPrimitive2: if (r2.isPrimitiveType() && !r1.isPrimitiveType()) {
					for (int i = 0; i < results.length; i++) {
						// for all expressions (not for any expression not)
						if (!(
								(!results[i].isPolyExpression() && (results[i].resolvedType != null && !results[i].resolvedType.isPrimitiveType())) // standalone of a referencetype
								|| results[i].isPolyExpression()))	// or a poly
							break checkPrimitive2;
					}
					return true;
				}	
			}
			return reduceAndIncorporate(ConstraintTypeFormula.create(r1, r2, ReductionResult.SUBTYPE));
		} else if (expri instanceof ReferenceExpression && ((ReferenceExpression)expri).isExactMethodReference()) {
			ReferenceExpression reference = (ReferenceExpression) expri;
			for (int i = 0; i < u.length; i++) {
				if (!reduceAndIncorporate(ConstraintTypeFormula.create(u[i], v[i], ReductionResult.SAME)))
					return false;
			}
			if (r2.id == TypeIds.T_void)
				return true;
			MethodBinding method = reference.getExactMethod();
			TypeBinding returnType = method.isConstructor() ? method.declaringClass : method.returnType;
			if (r1.isPrimitiveType() && !r2.isPrimitiveType() && returnType.isPrimitiveType()) 
				return true;
			if (r2.isPrimitiveType() && !r1.isPrimitiveType() && !returnType.isPrimitiveType())
				return true;
			return reduceAndIncorporate(ConstraintTypeFormula.create(r1, r2, ReductionResult.SUBTYPE));
		} else if (expri instanceof ConditionalExpression) {
			ConditionalExpression cond = (ConditionalExpression) expri;
			return  checkExpression(cond.valueIfTrue, u, r1, v, r2) && checkExpression(cond.valueIfFalse, u, r1, v, r2);
		} else {
			return false;
		}
	}

	private boolean siSuperI(TypeBinding si, TypeBinding funcI) {
		if (TypeBinding.equalsEquals(si, funcI) || TypeBinding.equalsEquals(si.original(), funcI))
			return true;
		TypeBinding[] superIfcs = funcI.superInterfaces();
		if (superIfcs == null) return false;
		for (int i = 0; i < superIfcs.length; i++) {
			if (siSuperI(si, superIfcs[i].original()))
				return true;
		}
		return false;
	}

	private boolean siSubI(TypeBinding si, TypeBinding funcI) {
		if (TypeBinding.equalsEquals(si, funcI) || TypeBinding.equalsEquals(si.original(), funcI))
			return true;
		TypeBinding[] superIfcs = si.superInterfaces();
		if (superIfcs == null) return false;
		for (int i = 0; i < superIfcs.length; i++) {
			if (siSubI(superIfcs[i], funcI))
				return true;
		}
		return false;
	}

	// ========== Below this point: implementation of the generic algorithm: ==========

	/**
	 * Try to solve the inference problem defined by constraints and bounds previously registered.
	 * @return a bound set representing the solution, or null if inference failed
	 * @throws InferenceFailureException a compile error has been detected during inference
	 */
	public /*@Nullable*/ BoundSet solve(boolean inferringApplicability) throws InferenceFailureException {

		if (!reduce())
			return null;
		if (!this.currentBounds.incorporate(this))
			return null;
		if (inferringApplicability)
			this.b2 = this.currentBounds.copy(); // Preserve the result after reduction, without effects of resolve() for later use in invocation type inference.

		BoundSet solution = resolve(this.inferenceVariables);
		
		/* If inferring applicability make a final pass over the initial constraints preserved as final constraints to make sure they hold true at a macroscopic level.
		   See https://bugs.eclipse.org/bugs/show_bug.cgi?id=426537#c55 onwards.
		*/
		if (inferringApplicability && solution != null && this.finalConstraints != null) {
			for (ConstraintExpressionFormula constraint: this.finalConstraints) {
				if (constraint.left.isPolyExpression())
					continue; // avoid redundant re-inference, inner poly's own constraints get validated in its own context & poly invocation type inference proved compatibility against target. 
				constraint.applySubstitution(solution, this.inferenceVariables);
				if (!this.currentBounds.reduceOneConstraint(this, constraint)) {
					return null;
				}
			}
		}
		return solution;
	}
	
	public /*@Nullable*/ BoundSet solve() throws InferenceFailureException {
		return solve(false);
	}
	
	public /*@Nullable*/ BoundSet solve(InferenceVariable[] toResolve) throws InferenceFailureException {
		if (!reduce())
			return null;
		if (!this.currentBounds.incorporate(this))
			return null;

		return resolve(toResolve);
	}

	/**
	 * JLS 18.2. reduce all initial constraints 
	 * @throws InferenceFailureException 
	 */
	private boolean reduce() throws InferenceFailureException {
		// Caution: This can be reentered recursively even as an earlier call is munching through the constraints !
		for (int i = 0; this.initialConstraints != null && i < this.initialConstraints.length; i++) {
			final ConstraintFormula currentConstraint = this.initialConstraints[i];
			if (currentConstraint == null)
				continue;
			this.initialConstraints[i] = null;
			if (!this.currentBounds.reduceOneConstraint(this, currentConstraint))
				return false;
		}
		this.initialConstraints = null;
		return true;
	}

	/**
	 * Have all inference variables been instantiated successfully?
	 */
	public boolean isResolved(BoundSet boundSet) {
		if (this.inferenceVariables != null) {
			for (int i = 0; i < this.inferenceVariables.length; i++) {
				if (!boundSet.isInstantiated(this.inferenceVariables[i]))
					return false;
			}
		}
		return true;
	}

	/**
	 * Retrieve the resolved solutions for all given type variables.
	 * @param typeParameters
	 * @param boundSet where instantiations are to be found
	 * @return array containing the substituted types or <code>null</code> elements for any type variable that could not be substituted.
	 */
	public TypeBinding /*@Nullable*/[] getSolutions(TypeVariableBinding[] typeParameters, InvocationSite site, BoundSet boundSet) {
		int len = typeParameters.length;
		TypeBinding[] substitutions = new TypeBinding[len];
		InferenceVariable[] outerVariables = null;
		if (this.outerContext != null && this.outerContext.stepCompleted < TYPE_INFERRED)
			outerVariables = this.outerContext.inferenceVariables;
		for (int i = 0; i < typeParameters.length; i++) {
			for (int j = 0; j < this.inferenceVariables.length; j++) {
				InferenceVariable variable = this.inferenceVariables[j];
				if (isSameSite(variable.site, site) && TypeBinding.equalsEquals(variable.typeParameter, typeParameters[i])) {
					TypeBinding outerVar = null;
					if (outerVariables != null && (outerVar = boundSet.getEquivalentOuterVariable(variable, outerVariables)) != null)
						substitutions[i] = outerVar;
					else
						substitutions[i] = boundSet.getInstantiation(variable, this.environment);
					break;
				}
			}
			if (substitutions[i] == null)
				return null;
		}
		return substitutions;
	}

	/** When inference produces a new constraint, reduce it to a suitable type bound and add the latter to the bound set. */
	public boolean reduceAndIncorporate(ConstraintFormula constraint) throws InferenceFailureException {
		return this.currentBounds.reduceOneConstraint(this, constraint); // TODO(SH): should we immediately call a diat incorporate, or can we simply wait for the next round?
	}

	/**
	 * <b>JLS 18.4</b> Resolution
	 * @return answer null if some constraint resolved to FALSE, otherwise the boundset representing the solution
	 * @throws InferenceFailureException 
	 */
	private /*@Nullable*/ BoundSet resolve(InferenceVariable[] toResolve) throws InferenceFailureException {
		this.captureId = 0;
		// NOTE: 18.5.2 ... 
		// "(While it was necessary to demonstrate that the inference variables in B1 could be resolved
		//   in order to establish applicability, the resulting instantiations are not considered part of B1.)
		// For this reason, resolve works on a temporary bound set, copied before any modification.
		BoundSet tmpBoundSet = this.currentBounds;
		if (this.inferenceVariables != null) {
			// find a minimal set of dependent variables:
			Set<InferenceVariable> variableSet;
			while ((variableSet = getSmallestVariableSet(tmpBoundSet, toResolve)) != null) {
				int oldNumUninstantiated = tmpBoundSet.numUninstantiatedVariables(this.inferenceVariables);
				final int numVars = variableSet.size();
				if (numVars > 0) {
					final InferenceVariable[] variables = variableSet.toArray(new InferenceVariable[numVars]);
					variables: if (!tmpBoundSet.hasCaptureBound(variableSet)) {
						// try to instantiate this set of variables in a fresh copy of the bound set:
						BoundSet prevBoundSet = tmpBoundSet;
						tmpBoundSet = tmpBoundSet.copy();
						for (int j = 0; j < variables.length; j++) {
							InferenceVariable variable = variables[j];
							// try lower bounds:
							TypeBinding[] lowerBounds = tmpBoundSet.lowerBounds(variable, true/*onlyProper*/);
							if (lowerBounds != Binding.NO_TYPES) {
								TypeBinding lub = this.scope.lowerUpperBound(lowerBounds);
								if (lub == TypeBinding.VOID || lub == null)
									return null;
								tmpBoundSet.addBound(new TypeBound(variable, lub, ReductionResult.SAME), this.environment);
							} else {
								TypeBinding[] upperBounds = tmpBoundSet.upperBounds(variable, true/*onlyProper*/);
								// check exception bounds:
								if (tmpBoundSet.inThrows.contains(variable.prototype()) && tmpBoundSet.hasOnlyTrivialExceptionBounds(variable, upperBounds)) {
									TypeBinding runtimeException = this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3);
									tmpBoundSet.addBound(new TypeBound(variable, runtimeException, ReductionResult.SAME), this.environment);
								} else {
									// try upper bounds:
									TypeBinding glb = this.object;
									if (upperBounds != Binding.NO_TYPES) {
										if (upperBounds.length == 1) {
											glb = upperBounds[0];
										} else {
											ReferenceBinding[] glbs = Scope.greaterLowerBound((ReferenceBinding[])upperBounds);
											if (glbs == null) {
												throw new UnsupportedOperationException("no glb for "+Arrays.asList(upperBounds)); //$NON-NLS-1$
											} else if (glbs.length == 1) {
												glb = glbs[0];
											} else {
												IntersectionTypeBinding18 intersection = (IntersectionTypeBinding18) this.environment.createIntersectionType18(glbs);
												if (!ReferenceBinding.isConsistentIntersection(intersection.intersectingTypes)) {
													tmpBoundSet = prevBoundSet; // clean up
													break variables; // and start over
												}
												glb = intersection;
											}
										}
									}
									tmpBoundSet.addBound(new TypeBound(variable, glb, ReductionResult.SAME), this.environment);
								}
							}
						}
						if (tmpBoundSet.incorporate(this))
							continue;
						tmpBoundSet = prevBoundSet;// clean-up for second attempt
					}
					// Otherwise, a second attempt is made...
					Sorting.sortInferenceVariables(variables); // ensure stability of capture IDs
					final CaptureBinding18[] zs = new CaptureBinding18[numVars];
					for (int j = 0; j < numVars; j++)
						zs[j] = freshCapture(variables[j]);
					final BoundSet kurrentBoundSet = tmpBoundSet;
					Substitution theta = new Substitution() {
						public LookupEnvironment environment() { 
							return InferenceContext18.this.environment;
						}
						public boolean isRawSubstitution() {
							return false;
						}
						public TypeBinding substitute(TypeVariableBinding typeVariable) {
							for (int j = 0; j < numVars; j++)
								if (TypeBinding.equalsEquals(variables[j], typeVariable))
									return zs[j];
							/* If we have an instantiation, lower it to the instantiation. We don't want downstream abstractions to be confused about multiple versions of bounds without
							   and with instantiations propagated by incorporation. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=430686. There is no value whatsoever in continuing
							   to speak in two tongues. Also fixes https://bugs.eclipse.org/bugs/show_bug.cgi?id=425031.
							*/
							if (typeVariable instanceof InferenceVariable) {
								InferenceVariable inferenceVariable = (InferenceVariable) typeVariable;
								TypeBinding instantiation = kurrentBoundSet.getInstantiation(inferenceVariable, null);
								if (instantiation != null)
									return instantiation;
							}
							return typeVariable;
						}
					};
					for (int j = 0; j < numVars; j++) {
						InferenceVariable variable = variables[j];
						CaptureBinding18 zsj = zs[j];
						// add lower bounds:
						TypeBinding[] lowerBounds = tmpBoundSet.lowerBounds(variable, true/*onlyProper*/);
						if (lowerBounds != Binding.NO_TYPES) {
							TypeBinding lub = this.scope.lowerUpperBound(lowerBounds);
							if (lub != TypeBinding.VOID && lub != null)
								zsj.lowerBound = lub;
						}
						// add upper bounds:
						TypeBinding[] upperBounds = tmpBoundSet.upperBounds(variable, false/*onlyProper*/);
						if (upperBounds != Binding.NO_TYPES) {
							for (int k = 0; k < upperBounds.length; k++)
								upperBounds[k] = Scope.substitute(theta, upperBounds[k]);
							if (!setUpperBounds(zsj, upperBounds))
								continue; // at violation of well-formedness skip this candidate and proceed
						}
						if (tmpBoundSet == this.currentBounds)
							tmpBoundSet = tmpBoundSet.copy();
						Iterator<ParameterizedTypeBinding> captureKeys = tmpBoundSet.captures.keySet().iterator();
						Set<ParameterizedTypeBinding> toRemove = new HashSet<ParameterizedTypeBinding>();
						while (captureKeys.hasNext()) {
							ParameterizedTypeBinding key = captureKeys.next();
							int len = key.arguments.length;
							for (int i = 0; i < len; i++) {
								if (TypeBinding.equalsEquals(key.arguments[i], variable)) {
									toRemove.add(key);
									break;
								}
							}
						}
						captureKeys = toRemove.iterator();
						while (captureKeys.hasNext())
							tmpBoundSet.captures.remove(captureKeys.next());
						tmpBoundSet.addBound(new TypeBound(variable, zsj, ReductionResult.SAME), this.environment);
					}
					if (tmpBoundSet.incorporate(this)) {
						if (tmpBoundSet.numUninstantiatedVariables(this.inferenceVariables) == oldNumUninstantiated)
							return null; // abort because we made no progress
						continue;
					}
					return null;
				}
			}
		}
		return tmpBoundSet;
	}
	
	int captureId = 0;
	
	/** For 18.4: "Let Z1, ..., Zn be fresh type variables" use capture bindings. */
	private CaptureBinding18 freshCapture(InferenceVariable variable) {
		int id = this.captureId++;
		char[] sourceName = CharOperation.concat("Z".toCharArray(), '#', String.valueOf(id).toCharArray(), '-', variable.sourceName); //$NON-NLS-1$
		int start = this.currentInvocation != null ? this.currentInvocation.sourceStart() : 0;
		int end = this.currentInvocation != null ? this.currentInvocation.sourceEnd() : 0;
		return new CaptureBinding18(this.scope.enclosingSourceType(), sourceName, variable.typeParameter.shortReadableName(),
						start, end, id, this.environment);
	}
	// === ===
	
	private boolean setUpperBounds(CaptureBinding18 typeVariable, TypeBinding[] substitutedUpperBounds) {
		// 18.4: ... define the upper bound of Zi as glb(L1θ, ..., Lkθ)
		if (substitutedUpperBounds.length == 1) {
			return typeVariable.setUpperBounds(substitutedUpperBounds, this.object); // shortcut
		} else {
			TypeBinding[] glbs = Scope.greaterLowerBound(substitutedUpperBounds, this.scope, this.environment);
			if (glbs == null)
				return false;
			if (typeVariable.lowerBound != null) {
				for (int i = 0; i < glbs.length; i++) {
					if (!typeVariable.lowerBound.isCompatibleWith(glbs[i]))
						return false; // not well-formed
				}
			}
			// for deterministic results sort this array by id:
			sortTypes(glbs);
			if (!typeVariable.setUpperBounds(glbs, this.object))
				return false;
		}
		return true;
	}

	static void sortTypes(TypeBinding[] types) {
		Arrays.sort(types, new Comparator<TypeBinding>() {
			public int compare(TypeBinding o1, TypeBinding o2) {
				int i1 = o1.id, i2 = o2.id; 
				return (i1<i2 ? -1 : (i1==i2 ? 0 : 1));
			}
		});
	}

	/**
	 * Find the smallest set of uninstantiated inference variables not depending
	 * on any uninstantiated variable outside the set.
	 */
	private Set<InferenceVariable> getSmallestVariableSet(BoundSet bounds, InferenceVariable[] subSet) {
		// "Given a set of inference variables to resolve, let V be the union of this set and
		//  all variables upon which the resolution of at least one variable in this set depends." 
		Set<InferenceVariable> v = new HashSet<InferenceVariable>();
		Map<InferenceVariable,Set<InferenceVariable>> dependencies = new HashMap<>(); // compute only once, store for the final loop over 'v'.
		for (InferenceVariable iv : subSet) {
			Set<InferenceVariable> tmp = new HashSet<>();
			addDependencies(bounds, tmp, iv);
			dependencies.put(iv, tmp);
			v.addAll(tmp);
		}
		// "If every variable in V has an instantiation, then resolution succeeds and this procedure terminates."
		//  -> (implicit if result remains unassigned)
		// "Otherwise, let { α1, ..., αn } be a non-empty subset of uninstantiated variables in V such that ...
		int min = Integer.MAX_VALUE;
		Set<InferenceVariable> result = null;
		// "i) for all i (1 ≤ i ≤ n), ..."
		for (InferenceVariable currentVariable : v) {
			if (!bounds.isInstantiated(currentVariable)) {
				// "... if αi depends on the resolution of a variable β, then either β has an instantiation or there is some j such that β = αj; ..."
				Set<InferenceVariable> set = dependencies.get(currentVariable);
				if (set == null) // not an element of the original subSet, still need to fetch this var's dependencies
					addDependencies(bounds, set = new HashSet<>(), currentVariable);
				//  "... and ii) there exists no non-empty proper subset of { α1, ..., αn } with this property."
				int cur = set.size();
				if (cur == 1)
					return set; // won't get smaller
				if (cur < min) {
					result = set;
					min = cur;
				}
			}
		}
		return result;
	}

	private void addDependencies(BoundSet boundSet, Set<InferenceVariable> variableSet, InferenceVariable currentVariable) {
		if (boundSet.isInstantiated(currentVariable)) return; // not added
		if (!variableSet.add(currentVariable)) return; // already present
		for (int j = 0; j < this.inferenceVariables.length; j++) {
			InferenceVariable nextVariable = this.inferenceVariables[j];
			if (TypeBinding.equalsEquals(nextVariable, currentVariable)) continue;
			if (boundSet.dependsOnResolutionOf(currentVariable, nextVariable))
				addDependencies(boundSet, variableSet, nextVariable);
		}
	}

	private ConstraintFormula pickFromCycle(Set<ConstraintFormula> c) {
		// Detail from 18.5.2 bullet 6.1

		// Note on performance: this implementation could quite possibly be optimized a lot.
		// However, we only *very rarely* reach here,
		// so nobody should really be affected by the performance penalty paid here.

		// Note on spec conformance: the spec seems to require _all_ criteria (i)-(iv) to be fulfilled
		// with the sole exception of (iii), which should only be used, if _any_ constraints matching (i) & (ii)
		// also fulfill this condition.
		// Experiments, however, show that strict application of the above is prone to failing to pick any constraint,
		// causing non-termination of the algorithm.
		// Since that is not acceptable, I'm *interpreting* the spec to request a search for a constraint
		// that "best matches" the given conditions.
		
		// collect all constraints participating in a cycle
		HashMap<ConstraintFormula,Set<ConstraintFormula>> dependencies = new HashMap<ConstraintFormula, Set<ConstraintFormula>>();
		Set<ConstraintFormula> cycles = new HashSet<ConstraintFormula>();
		for (ConstraintFormula constraint : c) {
			Collection<InferenceVariable> infVars = constraint.inputVariables(this);
			for (ConstraintFormula other : c) {
				if (other == constraint) continue;
				if (dependsOn(infVars, other.outputVariables(this))) {
					// found a dependency, record it:
					Set<ConstraintFormula> targetSet = dependencies.get(constraint);
					if (targetSet == null)
						dependencies.put(constraint, targetSet = new HashSet<ConstraintFormula>());
					targetSet.add(other);
					// look for a cycle:
					Set<ConstraintFormula> nodesInCycle = new HashSet<ConstraintFormula>();
					if (isReachable(dependencies, other, constraint, new HashSet<ConstraintFormula>(), nodesInCycle)) {
						// found a cycle, record the involved nodes:
						cycles.addAll(nodesInCycle);
					}
				}
			}
		}
		Set<ConstraintFormula> outside = new HashSet<ConstraintFormula>(c);
		outside.removeAll(cycles);

		Set<ConstraintFormula> candidatesII = new HashSet<ConstraintFormula>();
		// (i): participates in a cycle:
		candidates: for (ConstraintFormula candidate : cycles) {
			Collection<InferenceVariable> infVars = candidate.inputVariables(this);
			// (ii) does not depend on any constraints outside the cycle
			for (ConstraintFormula out : outside) {
				if (dependsOn(infVars, out.outputVariables(this)))
					continue candidates;
			}
			candidatesII.add(candidate);
		}
		if (candidatesII.isEmpty())
			candidatesII = c; // not spec'ed but needed to avoid returning null below, witness: java.util.stream.Collectors
		
		// tentatively: (iii)  has the form ⟨Expression → T⟩
		Set<ConstraintFormula> candidatesIII = new HashSet<ConstraintFormula>();
		for (ConstraintFormula candidate : candidatesII) {
			if (candidate instanceof ConstraintExpressionFormula)
				candidatesIII.add(candidate);
		}
		if (candidatesIII.isEmpty()) {
			candidatesIII = candidatesII; // no constraint fulfills (iii) -> ignore this condition
		} else { // candidatesIII contains all relevant constraints ⟨Expression → T⟩
			// (iv) contains an expression that appears to the left of the expression
			// 		of every other constraint satisfying the previous three requirements
			
			// collect containment info regarding all expressions in candidate constraints:
			// (a) find minimal enclosing expressions:
			Map<ConstraintExpressionFormula,ConstraintExpressionFormula> expressionContainedBy = new HashMap<ConstraintExpressionFormula, ConstraintExpressionFormula>();
			for (ConstraintFormula one : candidatesIII) {
				ConstraintExpressionFormula oneCEF = (ConstraintExpressionFormula) one;
				Expression exprOne = oneCEF.left;
				for (ConstraintFormula two : candidatesIII) {
					if (one == two) continue;
					ConstraintExpressionFormula twoCEF = (ConstraintExpressionFormula) two;
					Expression exprTwo = twoCEF.left;
					if (doesExpressionContain(exprOne, exprTwo)) {
						ConstraintExpressionFormula previous = expressionContainedBy.get(two);
						if (previous == null || doesExpressionContain(previous.left, exprOne)) // only if improving
							expressionContainedBy.put(twoCEF, oneCEF);
					}
				}
			}
			// (b) build the tree from the above
			Map<ConstraintExpressionFormula,Set<ConstraintExpressionFormula>> containmentForest = new HashMap<ConstraintExpressionFormula, Set<ConstraintExpressionFormula>>();
			for (Map.Entry<ConstraintExpressionFormula, ConstraintExpressionFormula> parentRelation : expressionContainedBy.entrySet()) {
				ConstraintExpressionFormula parent = parentRelation.getValue();
				Set<ConstraintExpressionFormula> children = containmentForest.get(parent);
				if (children == null)
					containmentForest.put(parent, children = new HashSet<ConstraintExpressionFormula>());
				children.add(parentRelation.getKey());
			}
			
			// approximate the spec by searching the largest containment tree:
			int bestRank = -1;
			ConstraintExpressionFormula candidate = null;
			for (ConstraintExpressionFormula parent : containmentForest.keySet()) {
				int rank = rankNode(parent, expressionContainedBy, containmentForest);
				if (rank > bestRank) {
					bestRank = rank;
					candidate = parent;
				}
			}
			if (candidate != null)
				return candidate;
		}
		
		if (candidatesIII.isEmpty())
			throw new IllegalStateException("cannot pick constraint from cyclic set"); //$NON-NLS-1$
		return candidatesIII.iterator().next();
	}

	/**
	 * Does the first constraint depend on the other?
	 * The first constraint is represented by its input variables and the other constraint by its output variables.
	 */
	private boolean dependsOn(Collection<InferenceVariable> inputsOfFirst, Collection<InferenceVariable> outputsOfOther) {
		for (InferenceVariable iv : inputsOfFirst) {
			for (InferenceVariable otherIV : outputsOfOther)
				if (this.currentBounds.dependsOnResolutionOf(iv, otherIV))
					return true;
		}
		return false;
	}

	/** Does 'deps' contain a chain of dependencies leading from 'from' to 'to'? */
	private boolean isReachable(Map<ConstraintFormula,Set<ConstraintFormula>> deps, ConstraintFormula from, ConstraintFormula to,
			Set<ConstraintFormula> nodesVisited, Set<ConstraintFormula> nodesInCycle)
	{
		if (from == to) {
			nodesInCycle.add(from);
			return true;
		}
		if (!nodesVisited.add(from))
			return false;
		Set<ConstraintFormula> targetSet = deps.get(from);
		if (targetSet != null) {
			for (ConstraintFormula tgt : targetSet) {
				if (isReachable(deps, tgt, to, nodesVisited, nodesInCycle)) {
					nodesInCycle.add(from);
					return true;
				}
			}
		}
		return false;
	}

	/** Does exprOne lexically contain exprTwo? */
	private boolean doesExpressionContain(Expression exprOne, Expression exprTwo) {
		if (exprTwo.sourceStart > exprOne.sourceStart) {
			return exprTwo.sourceEnd <= exprOne.sourceEnd;
		} else if (exprTwo.sourceStart == exprOne.sourceStart) {
			return exprTwo.sourceEnd < exprOne.sourceEnd;
		}
		return false;
	}

	/** non-roots answer -1, roots answer the size of the spanned tree */
	private int rankNode(ConstraintExpressionFormula parent, 
			Map<ConstraintExpressionFormula,ConstraintExpressionFormula> expressionContainedBy,
			Map<ConstraintExpressionFormula, Set<ConstraintExpressionFormula>> containmentForest)
	{
		if (expressionContainedBy.get(parent) != null)
			return -1; // not a root
		Set<ConstraintExpressionFormula> children = containmentForest.get(parent);
		if (children == null)
			return 1; // unconnected node or leaf
		int sum = 1;
		for (ConstraintExpressionFormula child : children) {
			int cRank = rankNode(child, expressionContainedBy, containmentForest);
			if (cRank > 0)
				sum += cRank;
		}
		return sum;
	}

	private Set<ConstraintFormula> findBottomSet(Set<ConstraintFormula> constraints, 
			Set<InferenceVariable> allOutputVariables, List<Set<InferenceVariable>> components)
	{
		// 18.5.2 bullet 5.(1)
		//  A subset of constraints is selected, satisfying the property that,
		//  for each constraint, no input variable can influence an output variable of another constraint in C. ...
		//  An inference variable α can influence an inference variable β if α depends on the resolution of β (§18.4), or vice versa;
		//  or if there exists a third inference variable γ such that α can influence γ and γ can influence β.  ...
		Set<ConstraintFormula> result = new HashSet<ConstraintFormula>();
	  constraintLoop:
		for (ConstraintFormula constraint : constraints) {
			for (InferenceVariable in : constraint.inputVariables(this)) {
				if (canInfluenceAnyOf(in, allOutputVariables, components))
					continue constraintLoop;
			}
			result.add(constraint);
		}
		return result;
	}

	private boolean canInfluenceAnyOf(InferenceVariable in, Set<InferenceVariable> allOuts, List<Set<InferenceVariable>> components) {
		// can influence == lives in the same component
		for (Set<InferenceVariable> component : components) {
			if (component.contains(in)) {
				for (InferenceVariable out : allOuts)
					if (component.contains(out))
						return true;
				return false;
			}
		}
		return false;
	}

	Set<InferenceVariable> allOutputVariables(Set<ConstraintFormula> constraints) {
		Set<InferenceVariable> result = new HashSet<InferenceVariable>();
		Iterator<ConstraintFormula> it = constraints.iterator();
		while (it.hasNext()) {
			result.addAll(it.next().outputVariables(this));
		}
		return result;
	}

	private TypeBinding[] varArgTypes(TypeBinding[] parameters, int k) {
		TypeBinding[] types = new TypeBinding[k];
		int declaredLength = parameters.length-1;
		System.arraycopy(parameters, 0, types, 0, declaredLength);
		TypeBinding last = ((ArrayBinding)parameters[declaredLength]).elementsType();
		for (int i = declaredLength; i < k; i++)
			types[i] = last;
		return types;
	}
	
	public SuspendedInferenceRecord enterPolyInvocation(InvocationSite invocation, Expression[] innerArguments) {
		SuspendedInferenceRecord record = new SuspendedInferenceRecord(this.currentInvocation, this.invocationArguments, this.inferenceVariables, this.inferenceKind, this.usesUncheckedConversion);
		this.inferenceVariables = null;
		this.invocationArguments = innerArguments;
		this.currentInvocation = invocation;
		this.usesUncheckedConversion = false;
		return record;
	}
	
	public SuspendedInferenceRecord enterLambda(LambdaExpression lambda) {
		SuspendedInferenceRecord record = new SuspendedInferenceRecord(this.currentInvocation, this.invocationArguments, this.inferenceVariables, this.inferenceKind, this.usesUncheckedConversion);
		this.inferenceVariables = null;
		this.invocationArguments = null;
		this.currentInvocation = null;
		this.usesUncheckedConversion = false;
		return record;
	}

	public void integrateInnerInferenceB2(InferenceContext18 innerCtx) {
		this.currentBounds.addBounds(innerCtx.b2, this.environment);
		this.inferenceVariables = innerCtx.inferenceVariables;
		this.inferenceKind = innerCtx.inferenceKind;
		if (!isSameSite(innerCtx.currentInvocation, this.currentInvocation))
			innerCtx.outerContext = this;
		this.usesUncheckedConversion = innerCtx.usesUncheckedConversion;
	}

	public void resumeSuspendedInference(SuspendedInferenceRecord record) {
		// merge inference variables:
		if (this.inferenceVariables == null) { // no new ones, assume we aborted prematurely
			this.inferenceVariables = record.inferenceVariables;
		} else {
			int l1 = this.inferenceVariables.length;
			int l2 = record.inferenceVariables.length;
			// move to back, add previous to front:
			System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables=new InferenceVariable[l1+l2], l2, l1);
			System.arraycopy(record.inferenceVariables, 0, this.inferenceVariables, 0, l2);
		}

		// replace invocation site & arguments:
		this.currentInvocation = record.site;
		this.invocationArguments = record.invocationArguments;
		this.inferenceKind = record.inferenceKind;
		this.usesUncheckedConversion = record.usesUncheckedConversion;
	}

	private Substitution getResultSubstitution(final BoundSet result) {
		return new Substitution() {
			public LookupEnvironment environment() { 
				return InferenceContext18.this.environment;
			}
			public boolean isRawSubstitution() {
				return false;
			}
			public TypeBinding substitute(TypeVariableBinding typeVariable) {
				if (typeVariable instanceof InferenceVariable) {
					TypeBinding instantiation = result.getInstantiation((InferenceVariable) typeVariable, InferenceContext18.this.environment);
					if (instantiation != null)
						return instantiation;
				}
				return typeVariable;
			}
		};
	}

	public boolean isVarArgs() {
		return this.inferenceKind == CHECK_VARARG;
	}

	/**
	 * Retrieve the rank'th parameter, possibly respecting varargs invocation, see 15.12.2.4.
	 * Returns null if out of bounds and CHECK_VARARG was not requested.
	 * Precondition: isVarArgs implies method.isVarargs()
	 */
	public static TypeBinding getParameter(TypeBinding[] parameters, int rank, boolean isVarArgs) {
		if (isVarArgs) {
			if (rank >= parameters.length-1)
				return ((ArrayBinding)parameters[parameters.length-1]).elementsType();			
		} else if (rank >= parameters.length) {
			return null;
		}
		return parameters[rank];
	}

	/**
	 * Create a problem method signaling failure of invocation type inference,
	 * unless the given candidate is tolerable to be compatible with buggy javac.
	 */
	public MethodBinding getReturnProblemMethodIfNeeded(TypeBinding expectedType, MethodBinding method) {
		if (InferenceContext18.SIMULATE_BUG_JDK_8026527 && expectedType != null && method.returnType instanceof ReferenceBinding) {
			if (method.returnType.erasure().isCompatibleWith(expectedType))
				return method; // don't count as problem.
		}
		/* We used to check if expected type is null and if so return method, but that is wrong - it injects an incompatible method into overload resolution.
		   if we get here with expected type set to null at all, the target context does not define a target type (vanilla context), so inference has done its
		   best and nothing more to do than to signal error. 
		 */
		ProblemMethodBinding problemMethod = new ProblemMethodBinding(method, method.selector, method.parameters, ProblemReasons.InvocationTypeInferenceFailure);
		problemMethod.returnType = expectedType != null ? expectedType : method.returnType;
		problemMethod.inferenceContext = this;
		return problemMethod;
	}

	// debugging:
	public String toString() {
		StringBuffer buf = new StringBuffer("Inference Context"); //$NON-NLS-1$
		switch (this.stepCompleted) {
			case NOT_INFERRED: buf.append(" (initial)");break; //$NON-NLS-1$
			case APPLICABILITY_INFERRED: buf.append(" (applicability inferred)");break; //$NON-NLS-1$
			case TYPE_INFERRED: buf.append(" (type inferred)");break; //$NON-NLS-1$
		}
		switch (this.inferenceKind) {
			case CHECK_STRICT: buf.append(" (strict)");break; //$NON-NLS-1$
			case CHECK_LOOSE: buf.append(" (loose)");break; //$NON-NLS-1$
			case CHECK_VARARG: buf.append(" (vararg)");break; //$NON-NLS-1$
		}
		if (this.currentBounds != null && isResolved(this.currentBounds))
			buf.append(" (resolved)"); //$NON-NLS-1$
		buf.append('\n');
		if (this.inferenceVariables != null) {
			buf.append("Inference Variables:\n"); //$NON-NLS-1$
			for (int i = 0; i < this.inferenceVariables.length; i++) {
				buf.append('\t').append(this.inferenceVariables[i].sourceName).append("\t:\t"); //$NON-NLS-1$
				if (this.currentBounds != null && this.currentBounds.isInstantiated(this.inferenceVariables[i]))
					buf.append(this.currentBounds.getInstantiation(this.inferenceVariables[i], this.environment).readableName());
				else
					buf.append("NOT INSTANTIATED"); //$NON-NLS-1$
				buf.append('\n');
			}
		}
		if (this.initialConstraints != null) {
			buf.append("Initial Constraints:\n"); //$NON-NLS-1$
			for (int i = 0; i < this.initialConstraints.length; i++)
				if (this.initialConstraints[i] != null)
					buf.append('\t').append(this.initialConstraints[i].toString()).append('\n');
		}
		if (this.currentBounds != null)
			buf.append(this.currentBounds.toString());
		return buf.toString();
	}

	/**
	 * If 'type' is a parameterized type and one of its arguments is a wildcard answer the casted type, else null.
	 * A nonnull answer is ensured to also have nonnull arguments.
	 */
	public static ParameterizedTypeBinding parameterizedWithWildcard(TypeBinding type) {
		if (type == null || type.kind() != Binding.PARAMETERIZED_TYPE)
			return null;
		ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) type;
		TypeBinding[] arguments = parameterizedType.arguments;
		if (arguments != null) {
			for (int i = 0; i < arguments.length; i++)
				if (arguments[i].isWildcard())
					return parameterizedType;
		}
		return null;
	}

	public TypeBinding[] getFunctionInterfaceArgumentSolutions(TypeBinding[] a) {
		int m = a.length;
		TypeBinding[] aprime = new TypeBinding[m];
		for (int i = 0; i < this.inferenceVariables.length; i++) {
			InferenceVariable alphai = this.inferenceVariables[i];
			TypeBinding t = this.currentBounds.getInstantiation(alphai, this.environment);
			if (t != null)
				aprime[i] = t;
			else
				aprime[i] = a[i];
		}
		return aprime;
	}

	/** Record the fact that the given constraint requires unchecked conversion. */
	public void recordUncheckedConversion(ConstraintTypeFormula constraint) {
		if (this.constraintsWithUncheckedConversion == null)
			this.constraintsWithUncheckedConversion = new ArrayList<ConstraintFormula>();
		this.constraintsWithUncheckedConversion.add(constraint);
		this.usesUncheckedConversion = true;
	}
	
	void reportUncheckedConversions(BoundSet solution) {
		if (this.constraintsWithUncheckedConversion != null) {
			int len = this.constraintsWithUncheckedConversion.size();
			Substitution substitution = getResultSubstitution(solution);
			for (int i = 0; i < len; i++) {
				ConstraintTypeFormula constraint = (ConstraintTypeFormula) this.constraintsWithUncheckedConversion.get(i);
				TypeBinding expectedType = constraint.right;
				TypeBinding providedType = constraint.left;
				if (!expectedType.isProperType(true)) {
					expectedType = Scope.substitute(substitution, expectedType);
				}
				if (!providedType.isProperType(true)) {
					providedType = Scope.substitute(substitution, providedType);
				}
/* FIXME(stephan): enable once we solved:
                    (a) avoid duplication with traditional reporting
                    (b) improve location to report against
				if (this.currentInvocation instanceof Expression)
					this.scope.problemReporter().unsafeTypeConversion((Expression) this.currentInvocation, providedType, expectedType);
 */
			}
		}
	}
	
	/** For use by 15.12.2.6 Method Invocation Type */
	public boolean usesUncheckedConversion() {
		return this.constraintsWithUncheckedConversion != null;
	}

	// INTERIM: infrastructure for detecting failures caused by specific known incompleteness:
	public static void missingImplementation(String msg) {
		throw new UnsupportedOperationException(msg);
	}

	public void forwardResults(BoundSet result, Invocation invocation, ParameterizedMethodBinding pmb, TypeBinding targetType) {
		if (targetType != null)
			invocation.registerResult(targetType, pmb);
		Expression[] arguments = invocation.arguments();
		for (int i = 0, length = arguments == null ? 0 : arguments.length; i < length; i++) {
			Expression [] expressions = arguments[i].getPolyExpressions();
			for (int j = 0, jLength = expressions.length; j < jLength; j++) {
				Expression expression = expressions[j];
				if (!(expression instanceof Invocation))
					continue;
				Invocation polyInvocation = (Invocation) expression;
				MethodBinding binding = polyInvocation.binding();
				if (binding == null || !binding.isValidBinding())
					continue;
				ParameterizedMethodBinding methodSubstitute = null;
				if (binding instanceof ParameterizedGenericMethodBinding) {
					MethodBinding shallowOriginal = binding.shallowOriginal();
					TypeBinding[] solutions = getSolutions(shallowOriginal.typeVariables(), polyInvocation, result);
					if (solutions == null)  // in CEF.reduce, we lift inner poly expressions into outer context only if their target type has inference variables. 
						continue;
					methodSubstitute = this.environment.createParameterizedGenericMethod(shallowOriginal, solutions);
				} else {
					if (!binding.isConstructor() || !(binding instanceof ParameterizedMethodBinding))
						continue; // throw ISE ?
					MethodBinding shallowOriginal = binding.shallowOriginal();
					ReferenceBinding genericType = shallowOriginal.declaringClass;
					TypeBinding[] solutions = getSolutions(genericType.typeVariables(), polyInvocation, result);
					if (solutions == null)  // in CEF.reduce, we lift inner poly expressions into outer context only if their target type has inference variables. 
						continue;
					ParameterizedTypeBinding parameterizedType = this.environment.createParameterizedType(genericType, solutions, binding.declaringClass.enclosingType());
					for (MethodBinding parameterizedMethod : parameterizedType.methods()) {
						if (parameterizedMethod.original() == shallowOriginal) {
							methodSubstitute = (ParameterizedMethodBinding) parameterizedMethod;
							break;
						}
					}
				}
				if (methodSubstitute == null || !methodSubstitute.isValidBinding())
					continue;
				boolean variableArity = pmb.isVarargs();
				final TypeBinding[] parameters = pmb.parameters;
				if (variableArity && parameters.length == arguments.length && i == length - 1) {
					TypeBinding returnType = methodSubstitute.returnType.capture(this.scope, expression.sourceStart, expression.sourceEnd);
					if (returnType.isCompatibleWith(parameters[parameters.length - 1], this.scope)) {
						variableArity = false;
					}
				}
				TypeBinding parameterType = InferenceContext18.getParameter(parameters, i, variableArity);
				forwardResults(result, polyInvocation, methodSubstitute, parameterType);		
			}
		}
	}

	public void cleanUp() {
		this.b2 = null;
		this.currentBounds = null;
	}
}
