Skip to content

[5.7][CodeCompletion] Ensure synthesized members are available before lookup #42397

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/NameLookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,9 @@ void lookupVisibleMemberDecls(VisibleDeclConsumer &Consumer,

namespace namelookup {

/// Add semantic members to \p type before attempting a semantic lookup.
void installSemanticMembersIfNeeded(Type type, DeclNameRef name);

void extractDirectlyReferencedNominalTypes(
Type type, SmallVectorImpl<NominalTypeDecl *> &decls);

Expand Down
26 changes: 26 additions & 0 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,32 @@ void namelookup::pruneLookupResultSet(const DeclContext *dc, NLOptions options,
filterForDiscriminator(decls, M->getDebugClient());
}

// An unfortunate hack to kick the decl checker into adding semantic members to
// the current type before we attempt a semantic lookup. The places this method
// looks needs to be in sync with \c extractDirectlyReferencedNominalTypes.
// See the note in \c synthesizeSemanticMembersIfNeeded about a better, more
// just, and peaceful world.
void namelookup::installSemanticMembersIfNeeded(Type type, DeclNameRef name) {
// Look-through class-bound archetypes to ensure we synthesize e.g.
// inherited constructors.
if (auto archetypeTy = type->getAs<ArchetypeType>()) {
if (auto super = archetypeTy->getSuperclass()) {
type = super;
}
}

if (type->isExistentialType()) {
auto layout = type->getExistentialLayout();
if (auto super = layout.explicitSuperclass) {
type = super;
}
}

if (auto *current = type->getAnyNominal()) {
current->synthesizeSemanticMembersIfNeeded(name.getFullName());
}
}

/// Inspect the given type to determine which nominal type declarations it
/// directly references, to facilitate name lookup into those types.
void namelookup::extractDirectlyReferencedNominalTypes(
Expand Down
4 changes: 4 additions & 0 deletions lib/IDE/ExprContextAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "swift/AST/Initializer.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/SourceFile.h"
Expand Down Expand Up @@ -364,6 +365,9 @@ static void collectPossibleCalleesByQualifiedLookup(
if (!baseInstanceTy->mayHaveMembers())
return;

// Make sure we've resolved implicit members.
namelookup::installSemanticMembersIfNeeded(baseInstanceTy, name);

bool isOnMetaType = baseTy->is<AnyMetatypeType>();

SmallVector<ValueDecl *, 2> decls;
Expand Down
30 changes: 2 additions & 28 deletions lib/Sema/TypeCheckNameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,32 +273,6 @@ LookupResult TypeChecker::lookupUnqualified(DeclContext *dc, DeclNameRef name,
return result;
}

// An unfortunate hack to kick the decl checker into adding semantic members to
// the current type before we attempt a semantic lookup. The places this method
// looks needs to be in sync with \c extractDirectlyReferencedNominalTypes.
// See the note in \c synthesizeSemanticMembersIfNeeded about a better, more
// just, and peaceful world.
static void installSemanticMembersIfNeeded(Type type, DeclNameRef name) {
// Look-through class-bound archetypes to ensure we synthesize e.g.
// inherited constructors.
if (auto archetypeTy = type->getAs<ArchetypeType>()) {
if (auto super = archetypeTy->getSuperclass()) {
type = super;
}
}

if (type->isExistentialType()) {
auto layout = type->getExistentialLayout();
if (auto super = layout.explicitSuperclass) {
type = super;
}
}

if (auto *current = type->getAnyNominal()) {
current->synthesizeSemanticMembersIfNeeded(name.getFullName());
}
}

LookupResult
TypeChecker::lookupUnqualifiedType(DeclContext *dc, DeclNameRef name,
SourceLoc loc,
Expand Down Expand Up @@ -346,7 +320,7 @@ LookupResult TypeChecker::lookupMember(DeclContext *dc,
subOptions &= ~NL_RemoveNonVisible;

// Make sure we've resolved implicit members, if we need them.
installSemanticMembersIfNeeded(type, name);
namelookup::installSemanticMembersIfNeeded(type, name);

LookupResultBuilder builder(result, dc, options);
SmallVector<ValueDecl *, 4> lookupResults;
Expand Down Expand Up @@ -438,7 +412,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
subOptions |= NL_IncludeUsableFromInline;

// Make sure we've resolved implicit members, if we need them.
installSemanticMembersIfNeeded(type, name);
namelookup::installSemanticMembersIfNeeded(type, name);

if (!dc->lookupQualified(type, name, subOptions, decls))
return result;
Expand Down
15 changes: 15 additions & 0 deletions test/IDE/complete_call_arg.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,7 @@ func testSkippedCallArgInInvalidResultBuilderBody() {
Other(action: 2) {
MyImage(systemName: "", #^INVALID_RESULTBUILDER_ARG^#
struct Invalid
}
}

// INVALID_RESULTBUILDER_ARG: Begin completions, 1 item
Expand Down Expand Up @@ -1399,3 +1400,17 @@ func testVarInitializedByCallingClosure() {
// VAR_INITIALIZED_BY_CALLING_CLOSURE-DAG: Pattern/Local/Flair[ArgLabels]: {#withExtension: String?#}[#String?#];
// VAR_INITIALIZED_BY_CALLING_CLOSURE: End completions
}

struct Rdar89773376 {
var intVal: Int
}
extension Rdar89773376 {
init(string: String) { self.intVal = 1 }
}
func testRdar89773376(arry: [Int]) {
arry.map { Rdar89773376(#^RDAR89773376^#) }
// RDAR89773376: Begin completions, 2 items
// RDAR89773376-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#string: String#}[')'][#Rdar89773376#];
// RDAR89773376-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#intVal: Int#}[')'][#Rdar89773376#];
// RDAR89773376: End completions
}