Skip to content

Commit 9418718

Browse files
committed
[CodeCompletion] Remove code completion results from extensions that can never apply. rdar://24562621
1 parent 36d4d41 commit 9418718

File tree

4 files changed

+111
-35
lines changed

4 files changed

+111
-35
lines changed

lib/AST/LookupVisibleDecls.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/AST.h"
2121
#include "swift/Basic/SourceManager.h"
2222
#include "swift/Basic/STLExtras.h"
23+
#include "swift/Sema/IDETypeChecking.h"
2324
#include "llvm/ADT/SetVector.h"
2425
#include <set>
2526

@@ -174,6 +175,9 @@ static void doGlobalExtensionLookup(Type BaseType,
174175

175176
// Look in each extension of this type.
176177
for (auto extension : nominal->getExtensions()) {
178+
if (!isExtensionApplied(*const_cast<DeclContext*>(CurrDC), BaseType,
179+
extension))
180+
continue;
177181
bool validatedExtension = false;
178182
if (TypeResolver && extension->getAsProtocolExtensionContext()) {
179183
if (!TypeResolver->isProtocolExtensionUsable(

lib/Sema/CSGen.cpp

Lines changed: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,55 +3156,91 @@ Type swift::checkMemberType(DeclContext &DC, Type BaseTy,
31563156
return Type();
31573157
}
31583158

3159-
bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
3160-
const ExtensionDecl *ED) {
3159+
static ArrayRef<Identifier> getSubstitutableTypeNames(SubstitutableType *Ty,
3160+
std::vector<Identifier> &Scratch,
3161+
bool &IsSelfDependent) {
3162+
IsSelfDependent = false;
3163+
for (auto Cur = Ty; Cur; Cur = Cur->getParent()) {
3164+
if (Cur->getName().str() == "Self") {
3165+
IsSelfDependent = true;
3166+
break;
3167+
}
3168+
Scratch.insert(Scratch.begin(), Cur->getName());
3169+
}
3170+
return llvm::makeArrayRef(Scratch);
3171+
}
31613172

3162-
// We need to make sure the extension is about the give type decl.
3163-
bool FoundExtension = false;
3164-
if (auto ND = BaseTy->getNominalOrBoundGenericNominal()) {
3165-
for (auto ET : ND->getExtensions()) {
3166-
if (ET == ED) {
3167-
FoundExtension = true;
3168-
break;
3169-
}
3173+
static ArrayRef<Identifier> getDependentMemberNames(DependentMemberType *Dep,
3174+
std::vector<Identifier> &Scratch,
3175+
bool &IsSelfDependent) {
3176+
DependentMemberType *Prev = nullptr;
3177+
IsSelfDependent = false;
3178+
for (DependentMemberType *Cur = Dep; Cur;
3179+
Prev = Cur, Cur = Cur->getBase()->getAs<DependentMemberType>()) {
3180+
Scratch.insert(Scratch.begin(), Cur->getName());
3181+
Prev = Cur;
3182+
}
3183+
if (Type Base = Prev->getBase()) {
3184+
if (SubstitutableType *Sub = Base->getAs<SubstitutableType>()) {
3185+
getSubstitutableTypeNames(Sub, Scratch, IsSelfDependent);
31703186
}
31713187
}
3172-
assert(FoundExtension && "Cannot find the extension.");
3173-
ConstraintSystemOptions Options;
3188+
return llvm::makeArrayRef(Scratch);
3189+
}
31743190

3191+
bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
3192+
const ExtensionDecl *ED) {
3193+
ConstraintSystemOptions Options;
3194+
NominalTypeDecl *Nominal = BaseTy->getNominalOrBoundGenericNominal();
3195+
if (!Nominal || !BaseTy->isSpecialized() ||
3196+
ED->getGenericRequirements().empty())
3197+
return true;
31753198
std::unique_ptr<TypeChecker> CreatedTC;
31763199
// If the current ast context has no type checker, create one for it.
31773200
auto *TC = static_cast<TypeChecker*>(DC.getASTContext().getLazyResolver());
31783201
if (!TC) {
31793202
CreatedTC.reset(new TypeChecker(DC.getASTContext()));
31803203
TC = CreatedTC.get();
31813204
}
3182-
3183-
// Build substitution map for the given type.
3184-
SmallVector<Type, 3> Scratch;
3185-
auto genericArgs = BaseTy->getAllGenericArgs(Scratch);
3186-
TypeSubstitutionMap substitutions;
3187-
auto genericParams = BaseTy->getNominalOrBoundGenericNominal()
3188-
->getInnermostGenericParamTypes();
3189-
assert(genericParams.size() == genericArgs.size());
3190-
for (unsigned i = 0, n = genericParams.size(); i != n; ++i) {
3191-
auto gp = genericParams[i]->getCanonicalType()->castTo<GenericTypeParamType>();
3192-
substitutions[gp] = genericArgs[i];
3193-
}
31943205
ConstraintSystem CS(*TC, &DC, Options);
31953206
auto Loc = CS.getConstraintLocator(nullptr);
3196-
if (ED->getGenericRequirements().empty())
3197-
return true;
3207+
std::vector<Identifier> Scratch;
3208+
bool Failed = false;
3209+
SmallVector<Type, 3> TypeScratch;
3210+
3211+
// Prepare type substitution map.
3212+
auto GenericArgs = BaseTy->getAllGenericArgs(TypeScratch);
3213+
TypeSubstitutionMap Substitutions;
3214+
auto GenericParams = Nominal->getInnermostGenericParamTypes();
3215+
assert(GenericParams.size() == GenericArgs.size());
3216+
for (unsigned I = 0, N = GenericParams.size(); I != N; ++I) {
3217+
auto GP = GenericParams[I]->getCanonicalType()->castTo<GenericTypeParamType>();
3218+
Substitutions[GP] = GenericArgs[I];
3219+
}
3220+
auto resolveType = [&](Type Ty) {
3221+
ArrayRef<Identifier> Names;
3222+
bool IsSelfDependent = false;
3223+
if (SubstitutableType *Sub = Ty->getAs<SubstitutableType>()) {
3224+
Scratch.clear();
3225+
Names = getSubstitutableTypeNames(Sub, Scratch, IsSelfDependent);
3226+
} else if (DependentMemberType *Dep = Ty->getAs<DependentMemberType>()) {
3227+
Scratch.clear();
3228+
Names = getDependentMemberNames(Dep, Scratch, IsSelfDependent);
3229+
} else
3230+
return Ty;
3231+
return IsSelfDependent ? checkMemberType(DC, BaseTy, Names)
3232+
:Ty.subst(DC.getParentModule(), Substitutions,
3233+
SubstFlags::IgnoreMissing);
3234+
};
31983235
auto createMemberConstraint = [&](Requirement &Req, ConstraintKind Kind) {
3199-
3200-
// Use the substitution map of the given type to substitute the parameter of
3201-
// the extension.
3202-
auto First = Req.getFirstType().subst(ED->getParentModule(), substitutions,
3203-
SubstFlags::IgnoreMissing);
3204-
3236+
auto First = resolveType(Req.getFirstType());
3237+
auto Second = resolveType(Req.getSecondType());
3238+
if (First.isNull() || Second.isNull()) {
3239+
Failed = true;
3240+
return;
3241+
}
32053242
// Add constraints accordingly.
3206-
CS.addConstraint(Constraint::create(CS, Kind, First, Req.getSecondType(),
3207-
DeclName(), Loc));
3243+
CS.addConstraint(Constraint::create(CS, Kind, First, Second, DeclName(), Loc));
32083244
};
32093245

32103246
// For every requirement, add a constraint.
@@ -3223,6 +3259,8 @@ bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
32233259
break;
32243260
}
32253261
}
3262+
if (Failed)
3263+
return true;
32263264

32273265
// Having a solution implies the extension's requirements have been fulfilled.
32283266
return CS.solveSingle().hasValue();
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONSTRAINT1 | FileCheck %s -check-prefix=CONSTRAINT1
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=CONSTRAINT2 | FileCheck %s -check-prefix=CONSTRAINT2
3+
4+
public protocol P1 {}
5+
public protocol P2 {}
6+
public struct Example<T: Any> {}
7+
8+
extension Example where T: P1 {
9+
func P1Method() {}
10+
}
11+
12+
extension Example where T: P2 {
13+
func P2Method() {}
14+
}
15+
16+
public struct S1 : P1 {}
17+
public struct S2 : P2 {}
18+
19+
func foo1() {
20+
var I1 = Example<S1>()
21+
I1.#^CONSTRAINT1^#
22+
}
23+
24+
// CONSTRAINT1: Begin completions, 1 items
25+
// CONSTRAINT1-NEXT: Decl[InstanceMethod]/CurrNominal: P1Method()[#Void#]; name=P1Method()
26+
// CONSTRAINT1-NEXT: End completions
27+
28+
func foo2() {
29+
var I2 = Example<S2>()
30+
I2.#^CONSTRAINT2^#
31+
}
32+
33+
// CONSTRAINT2: Begin completions, 1 items
34+
// CONSTRAINT2-NEXT: Decl[InstanceMethod]/CurrNominal: P2Method()[#Void#]; name=P2Method()
35+
// CONSTRAINT2-NEXT: End completions

test/IDE/complete_from_stdlib.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ func testArchetypeReplacement1<FOO : Equatable>(_ a: [FOO]) {
129129
// PRIVATE_NOMINAL_MEMBERS_5-DAG: Decl[InstanceMethod]/CurrNominal: append({#(newElement): Equatable#})[#Void#]{{; name=.+}}
130130
// PRIVATE_NOMINAL_MEMBERS_5-DAG: Decl[InstanceMethod]/CurrNominal: insert({#(newElement): Equatable#}, {#at: Int#})[#Void#]{{; name=.+}}
131131
// PRIVATE_NOMINAL_MEMBERS_5-DAG: Decl[InstanceMethod]/CurrNominal: popLast()[#Equatable?#]{{; name=.+}}
132-
// PRIVATE_NOMINAL_MEMBERS_5-DAG: Decl[InstanceMethod]/Super: makeIterator()[#IndexingIterator<[Equatable]>#]{{; name=.+}}
133132
// PRIVATE_NOMINAL_MEMBERS_5-DAG: Decl[InstanceVar]/Super: isEmpty[#Bool#]{{; name=.+}}
134133
// PRIVATE_NOMINAL_MEMBERS_5-DAG: Decl[InstanceVar]/Super: first[#Equatable?#]{{; name=.+}}
135134
// PRIVATE_NOMINAL_MEMBERS_5-DAG: Decl[InstanceMethod]/Super: dropFirst({#(n): Int#})[#ArraySlice<Equatable>#]{{; name=.+}}

0 commit comments

Comments
 (0)