Skip to content

Commit cd21d6c

Browse files
authored
Merge pull request #76955 from slavapestov/fix-issue-76561
IDE: Fix my own lazyness in SynthesizedExtensionAnalyzer::Implementation::isApplicable()
2 parents 79d8de9 + f751d50 commit cd21d6c

File tree

2 files changed

+61
-60
lines changed

2 files changed

+61
-60
lines changed

lib/IDE/IDETypeChecking.cpp

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -191,35 +191,32 @@ struct SynthesizedExtensionAnalyzer::Implementation {
191191

192192
struct ExtensionMergeInfo {
193193
struct Requirement {
194-
Type First;
195-
Type Second;
196-
RequirementKind Kind;
197-
CanType CanFirst;
198-
CanType CanSecond;
199-
200-
bool operator< (const Requirement& Rhs) const {
201-
if (Kind != Rhs.Kind)
202-
return Kind < Rhs.Kind;
203-
else if (CanFirst != Rhs.CanFirst)
204-
return CanFirst < Rhs.CanFirst;
205-
else
206-
return CanSecond < Rhs.CanSecond;
194+
swift::Requirement Req;
195+
196+
bool operator<(const Requirement& Rhs) const {
197+
if (auto result = unsigned(Req.getKind()) - unsigned(Rhs.Req.getKind())) {
198+
return result < 0;
199+
} else if (!Req.getFirstType()->isEqual(Rhs.Req.getFirstType())) {
200+
return (Req.getFirstType()->getCanonicalType() <
201+
Rhs.Req.getFirstType()->getCanonicalType());
202+
} else if (Req.getKind() != RequirementKind::Layout) {
203+
return (Req.getSecondType()->getCanonicalType() <
204+
Rhs.Req.getSecondType()->getCanonicalType());
205+
}
206+
207+
return false;
207208
}
209+
208210
bool operator== (const Requirement& Rhs) const {
209-
return (!(*this < Rhs)) && (!(Rhs < *this));
211+
return Req.getCanonical() == Rhs.Req.getCanonical();
210212
}
211213
};
212214

213215
bool Unmergable;
214216
unsigned InheritsCount;
215217
std::set<Requirement> Requirements;
216218
void addRequirement(swift::Requirement Req) {
217-
auto First = Req.getFirstType();
218-
auto CanFirst = First->getCanonicalType();
219-
auto Second = Req.getSecondType();
220-
auto CanSecond = Second->getCanonicalType();
221-
222-
Requirements.insert({First, Second, Req.getKind(), CanFirst, CanSecond});
219+
Requirements.insert({Req});
223220
}
224221
bool operator== (const ExtensionMergeInfo& Another) const {
225222
// Trivially unmergeable.
@@ -333,10 +330,6 @@ struct SynthesizedExtensionAnalyzer::Implementation {
333330
ProtocolDecl *BaseProto = OwningExt->getInnermostDeclContext()
334331
->getSelfProtocolDecl();
335332
for (auto Req : Reqs) {
336-
// FIXME: Don't skip layout requirements.
337-
if (Req.getKind() == RequirementKind::Layout)
338-
continue;
339-
340333
// Skip protocol's Self : <Protocol> requirement.
341334
if (BaseProto &&
342335
Req.getKind() == RequirementKind::Conformance &&
@@ -357,40 +350,35 @@ struct SynthesizedExtensionAnalyzer::Implementation {
357350
}
358351

359352
assert(!Req.getFirstType()->hasArchetype());
360-
assert(!Req.getSecondType()->hasArchetype());
361-
362-
auto SubstReq = Req.subst(
363-
[&](Type type) -> Type {
364-
if (type->isTypeParameter())
365-
return Target->mapTypeIntoContext(type);
366-
367-
return type;
368-
},
369-
LookUpConformanceInModule());
353+
if (Req.getKind() != RequirementKind::Layout)
354+
assert(!Req.getSecondType()->hasArchetype());
370355

356+
auto *env = Target->getGenericEnvironment();
371357
SmallVector<Requirement, 2> subReqs;
372-
switch (SubstReq.checkRequirement(subReqs)) {
373-
case CheckRequirementResult::Success:
374-
break;
375-
376-
case CheckRequirementResult::ConditionalConformance:
377-
// FIXME: Need to handle conditional requirements here!
378-
break;
379-
380-
case CheckRequirementResult::PackRequirement:
381-
// FIXME
382-
assert(false && "Refactor this");
383-
return true;
384-
385-
case CheckRequirementResult::SubstitutionFailure:
386-
return true;
387-
388-
case CheckRequirementResult::RequirementFailure:
389-
if (!SubstReq.canBeSatisfied())
358+
subReqs.push_back(
359+
Req.subst(
360+
QueryInterfaceTypeSubstitutions(env),
361+
LookUpConformanceInModule(),
362+
SubstFlags::PreservePackExpansionLevel));
363+
364+
while (!subReqs.empty()) {
365+
auto req = subReqs.pop_back_val();
366+
switch (req.checkRequirement(subReqs)) {
367+
case CheckRequirementResult::Success:
368+
case CheckRequirementResult::PackRequirement:
369+
case CheckRequirementResult::ConditionalConformance:
370+
break;
371+
372+
case CheckRequirementResult::SubstitutionFailure:
390373
return true;
391374

392-
MergeInfo.addRequirement(Req);
393-
break;
375+
case CheckRequirementResult::RequirementFailure:
376+
if (!req.canBeSatisfied())
377+
return true;
378+
379+
MergeInfo.addRequirement(Req);
380+
break;
381+
}
394382
}
395383
}
396384
return false;

test/IDE/print_synthesized_extensions.swift

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend -emit-module-path %t/print_synthesized_extensions.swiftmodule -emit-module-doc -emit-module-doc-path %t/print_synthesized_extensions.swiftdoc %s
3-
// RUN: %target-swift-ide-test -print-module -annotate-print -synthesize-extension -print-interface -no-empty-line-between-members -module-to-print=print_synthesized_extensions -I %t -source-filename=%s > %t.syn.txt
2+
// RUN: %target-swift-frontend -target %target-swift-5.9-abi-triple -emit-module-path %t/print_synthesized_extensions.swiftmodule -emit-module-doc -emit-module-doc-path %t/print_synthesized_extensions.swiftdoc %s
3+
// RUN: %target-swift-ide-test -annotate-print -print-module -synthesize-extension -print-interface -no-empty-line-between-members -module-to-print=print_synthesized_extensions -I %t -source-filename=%s -target=%target-swift-5.9-abi-triple > %t.syn.txt
44
// RUN: %FileCheck %s -check-prefix=CHECK1 < %t.syn.txt
55
// RUN: %FileCheck %s -check-prefix=CHECK2 < %t.syn.txt
66
// RUN: %FileCheck %s -check-prefix=CHECK3 < %t.syn.txt
@@ -17,6 +17,7 @@
1717
// RUN: %FileCheck %s -check-prefix=CHECK14 < %t.syn.txt
1818
// RUN: %FileCheck %s -check-prefix=CHECK15 < %t.syn.txt
1919
// RUN: %FileCheck %s -check-prefix=CHECK16 < %t.syn.txt
20+
// RUN: %FileCheck %s -check-prefix=CHECK17 < %t.syn.txt
2021

2122
public protocol P1 {
2223
associatedtype T1
@@ -312,8 +313,6 @@ extension S13 : P5 {
312313
// CHECK11-NEXT: public func <loc>foo3()</loc></decl>
313314
// CHECK11-NEXT: <decl:Func>/// This is picked
314315
// CHECK11-NEXT: public func <loc>foo4()</loc></decl>
315-
// CHECK11-NEXT: <decl:Func>/// This should not crash
316-
// CHECK11-NEXT: public func <loc>foo5()</loc></decl>
317316
// CHECK11-NEXT: }</synthesized>
318317

319318
// CHECK12: <decl:Protocol>public protocol <loc>P6</loc> {
@@ -338,8 +337,6 @@ extension S13 : P5 {
338337
// CHECK14-NEXT: public func <loc>foo3()</loc></decl>
339338
// CHECK14-NEXT: <decl:Func>/// This is picked
340339
// CHECK14-NEXT: public func <loc>foo4()</loc></decl>
341-
// CHECK14-NEXT: <decl:Func>/// This should not crash
342-
// CHECK14-NEXT: public func <loc>foo5()</loc></decl>
343340
// CHECK14-NEXT: }</synthesized>
344341

345342
// rdar://76868074: Make sure we print the extensions for C.
@@ -398,3 +395,19 @@ extension F : P8 {}
398395
// CHECK16-NEXT: }</synthesized>
399396

400397
// CHECK16-NOT: <synthesized>extension <ref:Class>F</ref> where <ref:GenericTypeParam>T</ref> : <ref:module>print_synthesized_extensions</ref>.<ref:Class>E</ref> {
398+
399+
400+
// Parameter packs
401+
public protocol P14 {}
402+
403+
extension P14 {
404+
public func foo<each T: Equatable>(_: repeat each T) {}
405+
}
406+
407+
public struct S14<each T: Equatable> {}
408+
409+
extension S14 : P14 where repeat each T: Hashable {}
410+
411+
// CHECK17: <synthesized>extension <ref:Struct>S14</ref> {
412+
// CHECK17-NEXT: <decl:Func>public func <loc>foo<each <ref:GenericTypeParam>T</ref>>(<decl:Param>_: repeat each <ref:GenericTypeParam>T</ref></decl>)</loc> where Pack{repeat each <ref:GenericTypeParam>T</ref>} : <ref:Protocol>Equatable</ref></decl>
413+
// CHECK17-NEXT: }</synthesized>

0 commit comments

Comments
 (0)