Skip to content

Commit 4d63471

Browse files
committed
Typo correction: don't try to resolve anything about vars in their own initializer.
1 parent 5c5bba8 commit 4d63471

File tree

3 files changed

+102
-7
lines changed

3 files changed

+102
-7
lines changed

include/swift/AST/LazyResolver.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,72 @@ class LazyResolver {
108108
ExtensionDecl *protocolExtension) = 0;
109109
};
110110

111+
/// An implementation of LazyResolver that delegates to another.
112+
class DelegatingLazyResolver : public LazyResolver {
113+
protected:
114+
LazyResolver &Principal;
115+
public:
116+
DelegatingLazyResolver(LazyResolver &principal) : Principal(principal) {}
117+
~DelegatingLazyResolver(); // v-table anchor
118+
119+
void resolveTypeWitness(const NormalProtocolConformance *conformance,
120+
AssociatedTypeDecl *assocType) override {
121+
Principal.resolveTypeWitness(conformance, assocType);
122+
}
123+
124+
void resolveWitness(const NormalProtocolConformance *conformance,
125+
ValueDecl *requirement) override {
126+
Principal.resolveWitness(conformance, requirement);
127+
}
128+
129+
130+
Type resolveMemberType(DeclContext *dc, Type type, Identifier name) override {
131+
return Principal.resolveMemberType(dc, type, name);
132+
}
133+
134+
void resolveAccessibility(ValueDecl *VD) override {
135+
Principal.resolveAccessibility(VD);
136+
}
137+
138+
void resolveDeclSignature(ValueDecl *VD) override {
139+
Principal.resolveDeclSignature(VD);
140+
}
141+
142+
void resolveInheritanceClause(
143+
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl) override {
144+
Principal.resolveInheritanceClause(decl);
145+
}
146+
147+
void resolveSuperclass(ClassDecl *classDecl) override {
148+
Principal.resolveSuperclass(classDecl);
149+
}
150+
151+
void resolveRawType(EnumDecl *enumDecl) override {
152+
Principal.resolveRawType(enumDecl);
153+
}
154+
155+
void resolveInheritedProtocols(ProtocolDecl *protocol) override {
156+
Principal.resolveInheritedProtocols(protocol);
157+
}
158+
159+
void resolveExtension(ExtensionDecl *ext) override {
160+
Principal.resolveExtension(ext);
161+
}
162+
163+
void resolveImplicitConstructors(NominalTypeDecl *nominal) override {
164+
Principal.resolveImplicitConstructors(nominal);
165+
}
166+
167+
void resolveExternalDeclImplicitMembers(NominalTypeDecl *nominal) override {
168+
Principal.resolveExternalDeclImplicitMembers(nominal);
169+
}
170+
171+
bool isProtocolExtensionUsable(DeclContext *dc, Type type,
172+
ExtensionDecl *protocolExtension) override {
173+
return Principal.isProtocolExtensionUsable(dc, type, protocolExtension);
174+
}
175+
};
176+
111177

112178
/// A class that can lazily load members from a serialized format.
113179
class alignas(void*) LazyMemberLoader {

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
using namespace swift;
4949

5050
LazyResolver::~LazyResolver() = default;
51+
DelegatingLazyResolver::~DelegatingLazyResolver() = default;
5152
void ModuleLoader::anchor() {}
5253
void ClangModuleLoader::anchor() {}
5354

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,37 @@ static bool isPlausibleTypo(DeclRefKind refKind, DeclName typedName,
464464
return true;
465465
}
466466

467+
static bool isLocInVarInit(TypeChecker &TC, VarDecl *var, SourceLoc loc) {
468+
auto binding = var->getParentPatternBinding();
469+
if (!binding || binding->isImplicit())
470+
return false;
471+
472+
auto initRange = binding->getSourceRange();
473+
return TC.Context.SourceMgr.rangeContainsTokenLoc(initRange, loc);
474+
}
475+
476+
namespace {
477+
class TypoCorrectionResolver : public DelegatingLazyResolver {
478+
TypeChecker &TC() { return static_cast<TypeChecker&>(Principal); }
479+
SourceLoc NameLoc;
480+
public:
481+
TypoCorrectionResolver(TypeChecker &TC, SourceLoc nameLoc)
482+
: DelegatingLazyResolver(TC), NameLoc(nameLoc) {}
483+
484+
void resolveDeclSignature(ValueDecl *VD) override {
485+
if (VD->isInvalid() || VD->hasType()) return;
486+
487+
// Don't process a variable if we're within its initializer.
488+
if (auto var = dyn_cast<VarDecl>(VD)) {
489+
if (isLocInVarInit(TC(), var, NameLoc))
490+
return;
491+
}
492+
493+
DelegatingLazyResolver::resolveDeclSignature(VD);
494+
}
495+
};
496+
}
497+
467498
void TypeChecker::performTypoCorrection(DeclContext *DC, DeclRefKind refKind,
468499
DeclName targetDeclName,
469500
SourceLoc nameLoc,
@@ -481,12 +512,8 @@ void TypeChecker::performTypoCorrection(DeclContext *DC, DeclRefKind refKind,
481512

482513
// Don't suggest a variable within its own initializer.
483514
if (auto var = dyn_cast<VarDecl>(decl)) {
484-
if (auto binding = var->getParentPatternBinding()) {
485-
if (!binding->isImplicit() &&
486-
Context.SourceMgr.rangeContainsTokenLoc(binding->getSourceRange(),
487-
nameLoc))
488-
return;
489-
}
515+
if (isLocInVarInit(*this, var, nameLoc))
516+
return;
490517
}
491518

492519
// Don't waste time computing edit distances that are more than
@@ -504,7 +531,8 @@ void TypeChecker::performTypoCorrection(DeclContext *DC, DeclRefKind refKind,
504531
entries.insert(distance, std::move(decl));
505532
});
506533

507-
lookupVisibleDecls(consumer, DC, this, /*top level*/ true, nameLoc);
534+
TypoCorrectionResolver resolver(*this, nameLoc);
535+
lookupVisibleDecls(consumer, DC, &resolver, /*top level*/ true, nameLoc);
508536

509537
// Impose a maximum distance from the best score.
510538
entries.filterMaxScoreRange(MaxCallEditDistanceFromBestCandidate);

0 commit comments

Comments
 (0)