Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 41 additions & 13 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2859,34 +2859,50 @@ static bool diagnoseContextualFunctionCallGenericAmbiguity(
return false;

auto contextualFix = contextualFixes.front();
if (!std::all_of(contextualFixes.begin() + 1, contextualFixes.end(),
[&contextualFix](FixInContext fix) {
return fix.second->getLocator() ==
contextualFix.second->getLocator();
}))
return false;

auto fixLocator = contextualFix.second->getLocator();

auto contextualAnchor = fixLocator->getAnchor();
auto *AE = getAsExpr<ApplyExpr>(contextualAnchor);
// All contextual failures anchored on the same function call.
if (!AE)
return false;

auto fnLocator = cs.getConstraintLocator(AE->getSemanticFn());
auto overload = contextualFix.first->getOverloadChoiceIfAvailable(fnLocator);
if (!overload)
return false;

auto applyFnType = overload->adjustedOpenedType->castTo<FunctionType>();
auto resultTypeVar = applyFnType->getResult()->getAs<TypeVariableType>();
auto getResultTypeVar = [&](FixInContext contextualFix) -> TypeVariableType * {
auto overload = contextualFix.first->getOverloadChoiceIfAvailable(fnLocator);
if (!overload)
return nullptr;

auto applyFnType = overload->adjustedOpenedType->castTo<FunctionType>();
return applyFnType->getResult()->getAs<TypeVariableType>();
};

auto resultTypeVar = getResultTypeVar(contextualFix);
if (!resultTypeVar)
return false;

auto *GP = resultTypeVar->getImpl().getGenericParameter();
if (!GP)
return false;

if (!std::all_of(contextualFixes.begin() + 1, contextualFixes.end(),
[&](FixInContext fix) {
if (fix.second->getLocator() != fixLocator)
return false;

auto resultTypeVar = getResultTypeVar(fix);

if (!resultTypeVar)
return false;

if (resultTypeVar->getImpl().getGenericParameter() != GP)
return false;

return true;
}))
return false;

auto applyLoc =
cs.getConstraintLocator(AE, {LocatorPathElt::ApplyArgument()});
auto argMatching =
Expand All @@ -2903,6 +2919,11 @@ static bool diagnoseContextualFunctionCallGenericAmbiguity(
continue;

auto argParamMatch = argMatching->second.parameterBindings[i];

// FIXME: We're just looking at the first solution's overload here,
// is that correct?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for now, the whole method expects the first overload with an issue to be generic which is not really correct but we can refactor that separately.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, I now understand what is going on here - the expectation is that the overload is the same across solutions and only generic parameter bindings are different…

auto overload = contextualFix.first->getOverloadChoiceIfAvailable(fnLocator);
auto applyFnType = overload->adjustedOpenedType->castTo<FunctionType>();
auto param = applyFnType->getParams()[argParamMatch.front()];
auto paramFnType = param.getPlainType()->getAs<FunctionType>();
if (!paramFnType)
Expand All @@ -2922,8 +2943,15 @@ static bool diagnoseContextualFunctionCallGenericAmbiguity(
// from all the closure contextual fix/solutions and if there are more than
// one fixed type diagnose it.
swift::SmallSetVector<Type, 4> genericParamInferredTypes;
for (auto &fix : contextualFixes)
for (auto &fix : contextualFixes) {
auto resultTypeVar = getResultTypeVar(fix);
genericParamInferredTypes.insert(fix.first->getFixedType(resultTypeVar));
}

for (auto &fix : allFixes) {
auto resultTypeVar = getResultTypeVar(fix);
genericParamInferredTypes.insert(fix.first->getFixedType(resultTypeVar));
}

if (llvm::all_of(allFixes, [&](FixInContext fix) {
auto fixLocator = fix.second->getLocator();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// {"kind":"typecheck","signature":"swift::constraints::Solution::getFixedType(swift::TypeVariableType*) const","signatureAssert":"Assertion failed: (knownBinding != typeBindings.end()), function getFixedType"}
// RUN: not --crash %target-swift-frontend -typecheck %s
// RUN: not %target-swift-frontend -typecheck %s
class a {
static
b {
Expand Down