Perform the unintended generic detection in simplifyMemberConstraint and define a ConstraintFix to produce the new note.

This commit is contained in:
Greg Titus
2020-06-09 09:02:42 -07:00
parent be4e23f41e
commit c73b144ad8
5 changed files with 135 additions and 55 deletions

View File

@@ -31,8 +31,6 @@
#include "swift/AST/SourceFile.h"
#include "swift/AST/Stmt.h"
#include "swift/AST/Types.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/Basic/SourceLoc.h"
#include "swift/Parse/Lexer.h"
#include "llvm/ADT/ArrayRef.h"
@@ -3111,53 +3109,6 @@ DeclName MissingMemberFailure::findCorrectEnumCaseName(
return (candidate ? candidate->getName() : DeclName());
}
bool MissingMemberFailure::findUnintendedExtraGenericParam(Type instanceTy, FunctionRefKind functionKind) {
auto archetype = instanceTy->getAs<ArchetypeType>();
if (!archetype)
return false;
auto genericTy = archetype->mapTypeOutOfContext()->getAs<GenericTypeParamType>();
if (!genericTy)
return false;
for (auto param : archetype->getGenericEnvironment()->getGenericParams()) {
// Find a param at the same depth and one index past the type we're dealing with
if (param->getDepth() != genericTy->getDepth() || param->getIndex() != genericTy->getIndex() + 1)
continue;
auto &cs = getConstraintSystem();
auto paramDecl = param->getDecl();
auto descriptor = UnqualifiedLookupDescriptor(
DeclNameRef(param->getName()), paramDecl->getDeclContext()->getParentForLookup(), paramDecl->getStartLoc(),
UnqualifiedLookupFlags::KnownPrivate | UnqualifiedLookupFlags::TypeLookup);
auto lookup = evaluateOrDefault(cs.getASTContext().evaluator, UnqualifiedLookupRequest{descriptor}, {});
for (auto &result : lookup) {
if (auto proto = dyn_cast_or_null<ProtocolDecl>(result.getValueDecl())) {
auto memberLookup = cs.performMemberLookup(
ConstraintKind::ValueMember, getName().withoutArgumentLabels(),
proto->getDeclaredType(), functionKind, getLocator(),
/*includeInaccessibleMembers=*/true);
if (memberLookup.ViableCandidates.size() || memberLookup.UnviableCandidates.size()) {
SourceLoc loc = genericTy->getDecl()->getSourceRange().End;
StringRef replacement;
if (archetype->getConformsTo().size()) {
loc = loc.getAdvancedLoc(archetype->getConformsTo().back()->getName().getLength());
replacement = " &";
} else {
loc = loc.getAdvancedLoc(archetype->getName().getLength());
replacement = ":";
}
emitDiagnosticAt(loc, diag::did_you_mean_generic_param_as_conformance, paramDecl->getName(), archetype)
.fixItReplaceChars(loc, loc.getAdvancedLoc(1), replacement);
return true;
}
}
}
break;
}
return false;
}
bool MissingMemberFailure::diagnoseAsError() {
auto anchor = getRawAnchor();
auto memberBase = getAnchor();
@@ -3266,7 +3217,6 @@ bool MissingMemberFailure::diagnoseAsError() {
}
} else {
emitBasicError(baseType);
findUnintendedExtraGenericParam(instanceTy, FunctionRefKind::DoubleApply);
}
} else if (auto moduleTy = baseType->getAs<ModuleType>()) {
emitDiagnosticAt(::getLoc(memberBase), diag::no_member_of_module,
@@ -3328,7 +3278,6 @@ bool MissingMemberFailure::diagnoseAsError() {
correction->addFixits(diagnostic);
} else {
emitBasicError(baseType);
findUnintendedExtraGenericParam(baseType, FunctionRefKind::SingleApply);
}
}
}
@@ -3386,6 +3335,30 @@ bool MissingMemberFailure::diagnoseInLiteralCollectionContext() const {
return false;
}
bool UnintendedExtraGenericParamMemberFailure::diagnoseAsError() {
MissingMemberFailure::diagnoseAsError();
auto baseType = resolveType(getBaseType())->getWithoutSpecifierType();
auto archetype = baseType->getMetatypeInstanceType()->castTo<ArchetypeType>();
auto genericTy =
archetype->mapTypeOutOfContext()->castTo<GenericTypeParamType>();
SourceLoc loc = genericTy->getDecl()->getSourceRange().End;
StringRef replacement;
if (archetype->getConformsTo().size()) {
loc = loc.getAdvancedLoc(
archetype->getConformsTo().back()->getName().getLength());
replacement = " &";
} else {
loc = loc.getAdvancedLoc(archetype->getName().getLength());
replacement = ":";
}
emitDiagnosticAt(loc, diag::did_you_mean_generic_param_as_conformance,
ParamName, archetype)
.fixItReplaceChars(loc, loc.getAdvancedLoc(1), replacement);
return true;
}
bool InvalidMemberRefOnExistential::diagnoseAsError() {
auto anchor = getRawAnchor();