diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index e7805518c6ab7..c4c8ca310944a 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -806,11 +806,13 @@ namespace { struct FailedArgumentInfo { int argumentNumber = -1; ///< Arg # at the call site. Type parameterType = Type(); ///< Expected type at the decl site. + DeclContext *declContext = nullptr; ///< Context at the candidate declaration. bool isValid() const { return argumentNumber != -1; } bool operator!=(const FailedArgumentInfo &other) { if (argumentNumber != other.argumentNumber) return true; + if (declContext != other.declContext) return true; // parameterType can be null, and isEqual doesn't handle this. if (!parameterType || !other.parameterType) return parameterType.getPointer() != other.parameterType.getPointer(); @@ -1186,6 +1188,8 @@ CalleeCandidateInfo::evaluateCloseness(DeclContext *dc, Type candArgListType, failureInfo.argumentNumber = argNo; failureInfo.parameterType = paramType; + if (paramType->hasTypeParameter()) + failureInfo.declContext = dc; } } @@ -1735,18 +1739,25 @@ bool CalleeCandidateInfo::diagnoseAnyStructuralArgumentError(Expr *fnExpr, /// archetype that has argument type errors, diagnose that error and /// return true. bool CalleeCandidateInfo::diagnoseGenericParameterErrors(Expr *badArgExpr) { - bool foundFailure = false; - Type paramType = failedArgument.parameterType; Type argType = badArgExpr->getType(); - - if (auto genericParam = paramType->getAs()) - paramType = genericParam->getDecl()->getArchetype(); - if (paramType->is() && !argType->hasTypeVariable() && - // FIXME: For protocol argument types, could add specific error - // similar to could_not_use_member_on_existential. - !argType->is() && !argType->is()) { - auto archetype = paramType->castTo(); + // FIXME: For protocol argument types, could add specific error + // similar to could_not_use_member_on_existential. + if (argType->hasTypeVariable() || argType->is() || + argType->is()) + return false; + + bool foundFailure = false; + SmallVector archetypes; + SmallVector substitutions; + + if (!findGenericSubstitutions(failedArgument.declContext, failedArgument.parameterType, + argType, archetypes, substitutions)) + return false; + + for (unsigned i = 0, c = archetypes.size(); i < c; i++) { + auto archetype = archetypes[i]; + auto argType = substitutions[i]; // FIXME: Add specific error for not subclass, if the archetype has a superclass?