Skip to content

Commit 94938d8

Browse files
committed
IDE: Fix my own lazyness in SynthesizedExtensionAnalyzer::Implementation::isApplicable()
Fixes #76561
1 parent cdc2145 commit 94938d8

File tree

2 files changed

+42
-58
lines changed

2 files changed

+42
-58
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: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,8 +312,6 @@ extension S13 : P5 {
312312
// CHECK11-NEXT: public func <loc>foo3()</loc></decl>
313313
// CHECK11-NEXT: <decl:Func>/// This is picked
314314
// 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>
317315
// CHECK11-NEXT: }</synthesized>
318316

319317
// CHECK12: <decl:Protocol>public protocol <loc>P6</loc> {
@@ -338,8 +336,6 @@ extension S13 : P5 {
338336
// CHECK14-NEXT: public func <loc>foo3()</loc></decl>
339337
// CHECK14-NEXT: <decl:Func>/// This is picked
340338
// 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>
343339
// CHECK14-NEXT: }</synthesized>
344340

345341
// rdar://76868074: Make sure we print the extensions for C.

0 commit comments

Comments
 (0)