From 5ba28eda3df8ee0199ac882825d7b3e3beafe9fe Mon Sep 17 00:00:00 2001 From: gregomni Date: Thu, 4 Feb 2016 11:56:13 -0800 Subject: [PATCH] Replace use of getArchetype() in diagnoseGenericParameterErrors() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a quick follow-up to , to replace the becoming deprecated getArchetype() with doing the same thing via calling through to ArchetypeBuilder with a declContext. Uses findGenericSubstitutions() to do so. So this site could take advantage of destructuring of more complex params containing generics. Right now, though, that never happens. For complex params the (unfortunately, worse) diagnosis happens in diagnoseFailureForExpr() on the argument expression before reaching here. I’d like to improve that in future work. --- lib/Sema/CSDiag.cpp | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) 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?