|
31 | 31 | #include "swift/AST/SourceFile.h"
|
32 | 32 | #include "swift/AST/Stmt.h"
|
33 | 33 | #include "swift/AST/Types.h"
|
| 34 | +#include "swift/AST/GenericEnvironment.h" |
| 35 | +#include "swift/AST/NameLookupRequests.h" |
34 | 36 | #include "swift/Basic/SourceLoc.h"
|
35 | 37 | #include "swift/Parse/Lexer.h"
|
36 | 38 | #include "llvm/ADT/ArrayRef.h"
|
@@ -3109,6 +3111,53 @@ DeclName MissingMemberFailure::findCorrectEnumCaseName(
|
3109 | 3111 | return (candidate ? candidate->getName() : DeclName());
|
3110 | 3112 | }
|
3111 | 3113 |
|
| 3114 | +bool MissingMemberFailure::findUnintendedExtraGenericParam(Type instanceTy, FunctionRefKind functionKind) { |
| 3115 | + auto archetype = instanceTy->getAs<ArchetypeType>(); |
| 3116 | + if (!archetype) |
| 3117 | + return false; |
| 3118 | + auto genericTy = archetype->mapTypeOutOfContext()->getAs<GenericTypeParamType>(); |
| 3119 | + if (!genericTy) |
| 3120 | + return false; |
| 3121 | + |
| 3122 | + for (auto param : archetype->getGenericEnvironment()->getGenericParams()) { |
| 3123 | + // Find a param at the same depth and one index past the type we're dealing with |
| 3124 | + if (param->getDepth() != genericTy->getDepth() || param->getIndex() != genericTy->getIndex() + 1) |
| 3125 | + continue; |
| 3126 | + |
| 3127 | + auto &cs = getConstraintSystem(); |
| 3128 | + auto paramDecl = param->getDecl(); |
| 3129 | + auto descriptor = UnqualifiedLookupDescriptor( |
| 3130 | + DeclNameRef(param->getName()), paramDecl->getDeclContext()->getParentForLookup(), paramDecl->getStartLoc(), |
| 3131 | + UnqualifiedLookupFlags::KnownPrivate | UnqualifiedLookupFlags::TypeLookup); |
| 3132 | + auto lookup = evaluateOrDefault(cs.getASTContext().evaluator, UnqualifiedLookupRequest{descriptor}, {}); |
| 3133 | + for (auto &result : lookup) { |
| 3134 | + if (auto proto = dyn_cast_or_null<ProtocolDecl>(result.getValueDecl())) { |
| 3135 | + auto memberLookup = cs.performMemberLookup( |
| 3136 | + ConstraintKind::ValueMember, getName().withoutArgumentLabels(), |
| 3137 | + proto->getDeclaredType(), functionKind, getLocator(), |
| 3138 | + /*includeInaccessibleMembers=*/true); |
| 3139 | + if (memberLookup.ViableCandidates.size() || memberLookup.UnviableCandidates.size()) { |
| 3140 | + SourceLoc loc = genericTy->getDecl()->getSourceRange().End; |
| 3141 | + StringRef replacement; |
| 3142 | + |
| 3143 | + if (archetype->getConformsTo().size()) { |
| 3144 | + loc = loc.getAdvancedLoc(archetype->getConformsTo().back()->getName().getLength()); |
| 3145 | + replacement = " &"; |
| 3146 | + } else { |
| 3147 | + loc = loc.getAdvancedLoc(archetype->getName().getLength()); |
| 3148 | + replacement = ":"; |
| 3149 | + } |
| 3150 | + emitDiagnosticAt(loc, diag::did_you_mean_generic_param_as_conformance, paramDecl->getName(), archetype) |
| 3151 | + .fixItReplaceChars(loc, loc.getAdvancedLoc(1), replacement); |
| 3152 | + return true; |
| 3153 | + } |
| 3154 | + } |
| 3155 | + } |
| 3156 | + break; |
| 3157 | + } |
| 3158 | + return false; |
| 3159 | +} |
| 3160 | + |
3112 | 3161 | bool MissingMemberFailure::diagnoseAsError() {
|
3113 | 3162 | auto anchor = getRawAnchor();
|
3114 | 3163 | auto memberBase = getAnchor();
|
@@ -3217,6 +3266,7 @@ bool MissingMemberFailure::diagnoseAsError() {
|
3217 | 3266 | }
|
3218 | 3267 | } else {
|
3219 | 3268 | emitBasicError(baseType);
|
| 3269 | + findUnintendedExtraGenericParam(instanceTy, FunctionRefKind::DoubleApply); |
3220 | 3270 | }
|
3221 | 3271 | } else if (auto moduleTy = baseType->getAs<ModuleType>()) {
|
3222 | 3272 | emitDiagnosticAt(::getLoc(memberBase), diag::no_member_of_module,
|
@@ -3278,6 +3328,7 @@ bool MissingMemberFailure::diagnoseAsError() {
|
3278 | 3328 | correction->addFixits(diagnostic);
|
3279 | 3329 | } else {
|
3280 | 3330 | emitBasicError(baseType);
|
| 3331 | + findUnintendedExtraGenericParam(baseType, FunctionRefKind::SingleApply); |
3281 | 3332 | }
|
3282 | 3333 | }
|
3283 | 3334 | }
|
|
0 commit comments