Skip to content

Commit 8638006

Browse files
committed
---
yaml --- r: 347207 b: refs/heads/master c: a64f8ac h: refs/heads/master i: 347205: ed8f238 347203: 06419c6 347199: 0110c1c
1 parent 91a2ed3 commit 8638006

File tree

10 files changed

+159
-50
lines changed

10 files changed

+159
-50
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 58b16c3e91ffc5a345e69b4956fe68d70b5019c9
2+
refs/heads/master: a64f8accdff1580d4515992c4a5932a549084893
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/Sema/IDETypeChecking.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,15 @@ namespace swift {
8282
/// decide if the extension has been applied, i.e. if the requirements of the
8383
/// extension have been fulfilled.
8484
/// \returns True on applied, false on not applied.
85-
bool isExtensionApplied(DeclContext &DC, Type Ty, const ExtensionDecl *ED);
85+
bool isExtensionApplied(const DeclContext *DC, Type Ty,
86+
const ExtensionDecl *ED);
8687

87-
/// The kind of type checking to perform for code completion.
88+
/// Given a type and an member value decl , decide if the decl is applied,
89+
/// i.e. if the \c where requirements of the decl have been fulfilled.
90+
/// \returns True on applied, false on not applied.
91+
bool isMemberDeclApplied(const DeclContext *DC, Type Ty, const ValueDecl *VD);
92+
93+
/// The kind of type checking to perform for code completion.
8894
enum class CompletionTypeCheckKind {
8995
/// Type check the expression as normal.
9096
Normal,

trunk/lib/IDE/IDETypeChecking.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ PrintOptions PrintOptions::printTypeInterface(Type T) {
6363
result.PrintExtensionFromConformingProtocols = true;
6464
result.TransformContext = TypeTransformContext(T);
6565
result.printExtensionContentAsMembers = [T](const ExtensionDecl *ED) {
66-
return isExtensionApplied(*T->getNominalOrBoundGenericNominal()->
67-
getDeclContext(), T, ED);
66+
return isExtensionApplied(
67+
T->getNominalOrBoundGenericNominal()->getDeclContext(), T, ED);
6868
};
6969
result.CurrentPrintabilityChecker.reset(new ModulePrinterPrintableChecker());
7070
return result;

trunk/lib/Sema/CSGen.cpp

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/ASTVisitor.h"
2020
#include "swift/AST/ASTWalker.h"
2121
#include "swift/AST/Expr.h"
22+
#include "swift/AST/GenericSignature.h"
2223
#include "swift/AST/ParameterList.h"
2324
#include "swift/AST/PrettyStackTrace.h"
2425
#include "swift/AST/SubstitutionMap.h"
@@ -3607,41 +3608,70 @@ void ConstraintSystem::optimizeConstraints(Expr *e) {
36073608
e->walk(optimizer);
36083609
}
36093610

3610-
bool swift::isExtensionApplied(DeclContext &DC, Type BaseTy,
3611-
const ExtensionDecl *ED) {
3612-
if (!ED->isConstrainedExtension() ||
3613-
// We'll crash if we leak type variables from one constraint
3614-
// system into the new one created below.
3615-
BaseTy->hasTypeVariable() ||
3616-
// We can't do anything if the base type has unbound generic
3617-
// parameters either.
3618-
BaseTy->hasUnboundGenericType())
3619-
return true;
3620-
3621-
TypeChecker *TC = &createTypeChecker(DC.getASTContext());
3622-
TC->validateExtension(const_cast<ExtensionDecl *>(ED));
3611+
static bool areGenericRequirementsSatisfied(
3612+
const DeclContext *DC, const GenericSignature *sig,
3613+
const SubstitutionMap &Substitutions, bool isExtension) {
36233614

3615+
TypeChecker &TC = createTypeChecker(DC->getASTContext());
36243616
ConstraintSystemOptions Options;
3625-
ConstraintSystem CS(*TC, &DC, Options);
3617+
ConstraintSystem CS(TC, const_cast<DeclContext *>(DC), Options);
36263618
auto Loc = CS.getConstraintLocator(nullptr);
36273619

3628-
// Prepare type substitution map.
3629-
SubstitutionMap Substitutions = BaseTy->getContextSubstitutionMap(
3630-
DC.getParentModule(), ED);
3631-
36323620
// For every requirement, add a constraint.
3633-
for (auto Req : ED->getGenericRequirements()) {
3621+
for (auto Req : sig->getRequirements()) {
36343622
if (auto resolved = Req.subst(Substitutions)) {
36353623
CS.addConstraint(*resolved, Loc);
3636-
} else {
3624+
} else if (isExtension) {
36373625
return false;
36383626
}
3627+
// Unresolved requirements are requirements of the function itself. This
3628+
// does not prevent it from being applied. E.g. func foo<T: Sequence>(x: T).
36393629
}
36403630

3641-
// Having a solution implies the extension's requirements have been fulfilled.
3631+
// Having a solution implies the requirements have been fulfilled.
36423632
return CS.solveSingle().hasValue();
36433633
}
36443634

3635+
bool swift::isExtensionApplied(const DeclContext *DC, Type BaseTy,
3636+
const ExtensionDecl *ED) {
3637+
// We can't do anything if the base type has unbound generic parameters.
3638+
// We can't leak type variables into another constraint system.
3639+
if (BaseTy->hasTypeVariable() || BaseTy->hasUnboundGenericType())
3640+
return true;
3641+
3642+
if (!ED->isConstrainedExtension())
3643+
return true;
3644+
3645+
TypeChecker *TC = &createTypeChecker(DC->getASTContext());
3646+
TC->validateExtension(const_cast<ExtensionDecl *>(ED));
3647+
3648+
GenericSignature *genericSig = ED->getGenericSignature();
3649+
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
3650+
DC->getParentModule(), ED->getExtendedNominal());
3651+
return areGenericRequirementsSatisfied(DC, genericSig, substMap,
3652+
/*isExtension=*/true);
3653+
}
3654+
3655+
bool swift::isMemberDeclApplied(const DeclContext *DC, Type BaseTy,
3656+
const ValueDecl *VD) {
3657+
// We can't leak type variables into another constraint system.
3658+
// We can't do anything if the base type has unbound generic parameters.
3659+
if (BaseTy->hasTypeVariable() || BaseTy->hasUnboundGenericType())
3660+
return true;
3661+
3662+
const GenericContext *genericDecl = VD->getAsGenericContext();
3663+
if (!genericDecl)
3664+
return true;
3665+
const GenericSignature *genericSig = genericDecl->getGenericSignature();
3666+
if (!genericSig)
3667+
return true;
3668+
3669+
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
3670+
DC->getParentModule(), VD->getDeclContext());
3671+
return areGenericRequirementsSatisfied(DC, genericSig, substMap,
3672+
/*isExtension=*/false);
3673+
}
3674+
36453675
static bool canSatisfy(Type type1, Type type2, bool openArchetypes,
36463676
ConstraintKind kind, DeclContext *dc) {
36473677
std::unique_ptr<TypeChecker> CreatedTC;

trunk/lib/Sema/LookupVisibleDecls.cpp

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,24 @@ static bool isDeclVisibleInLookupMode(ValueDecl *Member, LookupState LS,
174174
return true;
175175
}
176176

177+
/// Collect visble members from \p Parent into \p FoundDecls .
178+
static void collectVisibleMemberDecls(const DeclContext *CurrDC, LookupState LS,
179+
Type BaseType,
180+
IterableDeclContext *Parent,
181+
SmallVectorImpl<ValueDecl *> &FoundDecls,
182+
LazyResolver *TypeResolver) {
183+
for (auto Member : Parent->getMembers()) {
184+
auto *VD = dyn_cast<ValueDecl>(Member);
185+
if (!VD)
186+
continue;
187+
if (!isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
188+
continue;
189+
if (!isMemberDeclApplied(CurrDC, BaseType, VD))
190+
continue;
191+
FoundDecls.push_back(VD);
192+
}
193+
}
194+
177195
/// Lookup members in extensions of \p LookupType, using \p BaseType as the
178196
/// underlying type when checking any constraints on the extensions.
179197
static void doGlobalExtensionLookup(Type BaseType,
@@ -187,15 +205,12 @@ static void doGlobalExtensionLookup(Type BaseType,
187205

188206
// Look in each extension of this type.
189207
for (auto extension : nominal->getExtensions()) {
190-
if (!isExtensionApplied(*const_cast<DeclContext*>(CurrDC), BaseType,
208+
if (!isExtensionApplied(const_cast<DeclContext *>(CurrDC), BaseType,
191209
extension))
192210
continue;
193211

194-
for (auto Member : extension->getMembers()) {
195-
if (auto VD = dyn_cast<ValueDecl>(Member))
196-
if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
197-
FoundDecls.push_back(VD);
198-
}
212+
collectVisibleMemberDecls(CurrDC, LS, BaseType, extension, FoundDecls,
213+
TypeResolver);
199214
}
200215

201216
// Handle shadowing.
@@ -217,12 +232,8 @@ static void lookupTypeMembers(Type BaseType, Type LookupType,
217232
assert(D && "should have a nominal type");
218233

219234
SmallVector<ValueDecl*, 2> FoundDecls;
235+
collectVisibleMemberDecls(CurrDC, LS, BaseType, D, FoundDecls, TypeResolver);
220236

221-
for (Decl *Member : D->getMembers()) {
222-
if (auto *VD = dyn_cast<ValueDecl>(Member))
223-
if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
224-
FoundDecls.push_back(VD);
225-
}
226237
doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason,
227238
TypeResolver);
228239

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MYSTRUCT_INT_DOT | %FileCheck %s -check-prefix=MYSTRUCT_INT_DOT
2+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=META_MYSTRUCT_INT_DOT | %FileCheck %s -check-prefix=META_MYSTRUCT_INT_DOT
3+
4+
protocol SomeProto {
5+
associatedtype Assoc
6+
}
7+
8+
extension SomeProto where Assoc == String {
9+
func protoExt_AssocEqString_None() -> Int { return 1 }
10+
}
11+
extension SomeProto where Assoc == Int {
12+
func protoExt_AssocEqInt_None() -> Int { return 1 }
13+
}
14+
extension SomeProto where Assoc: SomeProto {
15+
func protoExt_AssocConformsToSomeProto_None() -> Int { return 1 }
16+
}
17+
18+
extension SomeProto {
19+
func protoExt_None_AssocEqString<U>(_ x: U) -> Int where Assoc == String { return 1 }
20+
func protoExt_None_AssocEqInt<U>(_ x: U) -> Int where Assoc == Int { return 1 }
21+
func protoExt_None_AssocConformsToSomeProto<U>(_ x: U) -> Int where Assoc: SomeProto { return 1 }
22+
}
23+
24+
struct MyStruct<T> : SomeProto {
25+
typealias Assoc = T
26+
init<U>(int: U) where T == Int {}
27+
init<U>(str: U) where T == String {}
28+
init<U: SomeProto>(withConstrainedGenericParam: U) {}
29+
func methodWithConstrainedGenericParam<U: SomeProto>(x: U) -> Int { return 1 }
30+
}
31+
32+
extension MyStruct where T == String {
33+
func concreteExt_TEqString_None() -> Int { return 1 }
34+
}
35+
extension MyStruct where T == Int {
36+
func concreteExt_TEqInt_None() -> Int { return 1 }
37+
}
38+
extension MyStruct where T: SomeProto {
39+
func concreteExt_TConformsToSomeProto_None() -> Int { return 1 }
40+
}
41+
42+
extension MyStruct {
43+
func concreteExt_None_TEqString<U>(_ x: U) -> Int where T == String { return 1 }
44+
func concreteExt_None_TEqInt<U>(_ x: U) -> Int where T == Int { return 1 }
45+
func concreteExt_None_TConformsToSomeProto<U>(_ x: U) -> Int where T: SomeProto { return 1 }
46+
}
47+
48+
func foo(s: MyStruct<Int>) {
49+
let _ = s.#^MYSTRUCT_INT_DOT^#
50+
// MYSTRUCT_INT_DOT: Begin completions, 6 items
51+
// MYSTRUCT_INT_DOT-DAG: Keyword[self]/CurrNominal: self[#MyStruct<Int>#]; name=self
52+
// MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/CurrNominal: methodWithConstrainedGenericParam({#x: SomeProto#})[#Int#]; name=methodWithConstrainedGenericParam(x: SomeProto)
53+
// MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/CurrNominal: concreteExt_TEqInt_None()[#Int#]; name=concreteExt_TEqInt_None()
54+
// MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/CurrNominal: concreteExt_None_TEqInt({#(x): U#})[#Int#]; name=concreteExt_None_TEqInt(x: U)
55+
// MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/Super: protoExt_AssocEqInt_None()[#Int#]; name=protoExt_AssocEqInt_None()
56+
// MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/Super: protoExt_None_AssocEqInt({#(x): U#})[#Int#]; name=protoExt_None_AssocEqInt(x: U)
57+
// MYSTRUCT_INT_DOT: End completions
58+
59+
let _ = MyStruct<Int>.#^META_MYSTRUCT_INT_DOT^#
60+
// META_MYSTRUCT_INT_DOT: Begin completions, 10 items
61+
// META_MYSTRUCT_INT_DOT-DAG: Keyword[self]/CurrNominal: self[#MyStruct<Int>.Type#]; name=self
62+
// META_MYSTRUCT_INT_DOT-DAG: Keyword/CurrNominal: Type[#MyStruct<Int>.Type#]; name=Type
63+
// META_MYSTRUCT_INT_DOT-DAG: Decl[TypeAlias]/CurrNominal: Assoc[#T#]; name=Assoc
64+
// META_MYSTRUCT_INT_DOT-DAG: Decl[Constructor]/CurrNominal: init({#int: U#})[#MyStruct<Int>#]; name=init(int: U)
65+
// META_MYSTRUCT_INT_DOT-DAG: Decl[Constructor]/CurrNominal: init({#withConstrainedGenericParam: SomeProto#})[#MyStruct<Int>#]; name=init(withConstrainedGenericParam: SomeProto)
66+
// META_MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/CurrNominal: methodWithConstrainedGenericParam({#(self): MyStruct<Int>#})[#(x: SomeProto) -> Int#]; name=methodWithConstrainedGenericParam(self: MyStruct<Int>)
67+
// META_MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/CurrNominal: concreteExt_TEqInt_None({#(self): MyStruct<Int>#})[#() -> Int#]; name=concreteExt_TEqInt_None(self: MyStruct<Int>)
68+
// META_MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/CurrNominal: concreteExt_None_TEqInt({#(self): MyStruct<Int>#})[#(U) -> Int#]; name=concreteExt_None_TEqInt(self: MyStruct<Int>)
69+
// META_MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/Super: protoExt_AssocEqInt_None({#(self): MyStruct<Int>#})[#() -> Int#]; name=protoExt_AssocEqInt_None(self: MyStruct<Int>)
70+
// META_MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/Super: protoExt_None_AssocEqInt({#(self): MyStruct<Int>#})[#(U) -> Int#]; name=protoExt_None_AssocEqInt(self: MyStruct<Int>)
71+
// META_MYSTRUCT_INT_DOT: End completions
72+
}

trunk/test/IDE/complete_operators.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,8 @@ func testInfix11() {
262262
func testInfix12() {
263263
P#^INFIX_12^#
264264
}
265-
// INFIX_12: Begin completions, 5 items
265+
// INFIX_12: Begin completions, 4 items
266266
// INFIX_12-NEXT: Decl[AssociatedType]/CurrNominal: .T; name=T
267-
// INFIX_12-NEXT: Decl[InstanceMethod]/CurrNominal: .foo({#(self): P#})[#() -> P.T#]; name=foo(self: P)
268267
// INFIX_12-NEXT: Keyword[self]/CurrNominal: .self[#P.Protocol#]; name=self
269268
// INFIX_12-NEXT: Keyword/CurrNominal: .Protocol[#P.Protocol#]; name=Protocol
270269
// INFIX_12-NEXT: Keyword/CurrNominal: .Type[#P.Type#]; name=Type

trunk/test/IDE/complete_unresolved_members.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,7 @@ func testSubType() {
493493
func testMemberTypealias() {
494494
var _: MyProtocol = .#^SUBTYPE_2^#
495495
}
496-
// SUBTYPE_2: Begin completions, 2 items
497-
// SUBTYPE_1-NOT: Concrete1(failable:
498-
// SUBTYPE_2-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: Concrete1()[#BaseClass#];
499-
// SUBTYPE_2-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: Concrete2()[#AnotherTy#];
500-
// SUBTYPE_2: End completions
496+
// SUBTYPE_2-NOT: Begin completions
501497

502498
enum Generic<T> {
503499
case contains(content: T)

trunk/test/IDE/complete_value_expr.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,14 +2074,10 @@ protocol ExistentialProto {
20742074

20752075
func testExistential() {
20762076
let _ = ExistentialProto.#^PROTOCOLTYPE_DOT_1^#
2077-
// PROTOCOLTYPE_DOT_1: Begin completions, 5 items
2077+
// PROTOCOLTYPE_DOT_1: Begin completions, 3 items
20782078
// PROTOCOLTYPE_DOT_1-DAG: Keyword[self]/CurrNominal: self[#ExistentialProto.Protocol#]; name=self
20792079
// PROTOCOLTYPE_DOT_1-DAG: Keyword/CurrNominal: Protocol[#ExistentialProto.Protocol#]; name=Protocol
20802080
// PROTOCOLTYPE_DOT_1-DAG: Keyword/CurrNominal: Type[#ExistentialProto.Type#]; name=Type
2081-
// FIXME(SR-75, rdar://problem/21289579): These 2 are invalid: {
2082-
// PROTOCOLTYPE_DOT_1-DAG: Decl[StaticMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: staticMethod()[#Void#]; name=staticMethod()
2083-
// PROTOCOLTYPE_DOT_1-DAG: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: instanceMethod({#(self): ExistentialProto#})[#() -> Void#]; name=instanceMethod(self: ExistentialProto)
2084-
// }
20852081
// PROTOCOLTYPE_DOT_1: End completions
20862082

20872083
let _ = ExistentialProto.Type.#^PROTOCOLTYPE_DOT_2^#

trunk/test/decl/typealias/protocol.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ protocol P3 {
145145
// Test for not crashing on recursive aliases
146146
protocol Circular {
147147
typealias Y = Self.Y // expected-error {{'Y' is not a member type of 'Self'}}
148-
// expected-note@-1 {{did you mean 'Y'?}}
149148

150149
typealias Y2 = Y2 // expected-error {{type alias 'Y2' references itself}}
151150
// expected-note@-1 {{type declared here}}

0 commit comments

Comments
 (0)