mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
IDE: Fix my own lazyness in SynthesizedExtensionAnalyzer::Implementation::isApplicable()
This routine was never properly updated to handle layout requirements, conditional conformances, or parameter packs. Let's clear out the FIXMEs and do things properly here. Fixes https://github.com/swiftlang/swift/issues/76561
This commit is contained in:
@@ -191,22 +191,24 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
||||
|
||||
struct ExtensionMergeInfo {
|
||||
struct Requirement {
|
||||
Type First;
|
||||
Type Second;
|
||||
RequirementKind Kind;
|
||||
CanType CanFirst;
|
||||
CanType CanSecond;
|
||||
swift::Requirement Req;
|
||||
|
||||
bool operator< (const Requirement& Rhs) const {
|
||||
if (Kind != Rhs.Kind)
|
||||
return Kind < Rhs.Kind;
|
||||
else if (CanFirst != Rhs.CanFirst)
|
||||
return CanFirst < Rhs.CanFirst;
|
||||
else
|
||||
return CanSecond < Rhs.CanSecond;
|
||||
bool operator<(const Requirement& Rhs) const {
|
||||
if (auto result = unsigned(Req.getKind()) - unsigned(Rhs.Req.getKind())) {
|
||||
return result < 0;
|
||||
} else if (!Req.getFirstType()->isEqual(Rhs.Req.getFirstType())) {
|
||||
return (Req.getFirstType()->getCanonicalType() <
|
||||
Rhs.Req.getFirstType()->getCanonicalType());
|
||||
} else if (Req.getKind() != RequirementKind::Layout) {
|
||||
return (Req.getSecondType()->getCanonicalType() <
|
||||
Rhs.Req.getSecondType()->getCanonicalType());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator== (const Requirement& Rhs) const {
|
||||
return (!(*this < Rhs)) && (!(Rhs < *this));
|
||||
return Req.getCanonical() == Rhs.Req.getCanonical();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -214,12 +216,7 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
||||
unsigned InheritsCount;
|
||||
std::set<Requirement> Requirements;
|
||||
void addRequirement(swift::Requirement Req) {
|
||||
auto First = Req.getFirstType();
|
||||
auto CanFirst = First->getCanonicalType();
|
||||
auto Second = Req.getSecondType();
|
||||
auto CanSecond = Second->getCanonicalType();
|
||||
|
||||
Requirements.insert({First, Second, Req.getKind(), CanFirst, CanSecond});
|
||||
Requirements.insert({Req});
|
||||
}
|
||||
bool operator== (const ExtensionMergeInfo& Another) const {
|
||||
// Trivially unmergeable.
|
||||
@@ -333,10 +330,6 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
||||
ProtocolDecl *BaseProto = OwningExt->getInnermostDeclContext()
|
||||
->getSelfProtocolDecl();
|
||||
for (auto Req : Reqs) {
|
||||
// FIXME: Don't skip layout requirements.
|
||||
if (Req.getKind() == RequirementKind::Layout)
|
||||
continue;
|
||||
|
||||
// Skip protocol's Self : <Protocol> requirement.
|
||||
if (BaseProto &&
|
||||
Req.getKind() == RequirementKind::Conformance &&
|
||||
@@ -357,40 +350,35 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
||||
}
|
||||
|
||||
assert(!Req.getFirstType()->hasArchetype());
|
||||
assert(!Req.getSecondType()->hasArchetype());
|
||||
|
||||
auto SubstReq = Req.subst(
|
||||
[&](Type type) -> Type {
|
||||
if (type->isTypeParameter())
|
||||
return Target->mapTypeIntoContext(type);
|
||||
|
||||
return type;
|
||||
},
|
||||
LookUpConformanceInModule());
|
||||
if (Req.getKind() != RequirementKind::Layout)
|
||||
assert(!Req.getSecondType()->hasArchetype());
|
||||
|
||||
auto *env = Target->getGenericEnvironment();
|
||||
SmallVector<Requirement, 2> subReqs;
|
||||
switch (SubstReq.checkRequirement(subReqs)) {
|
||||
case CheckRequirementResult::Success:
|
||||
break;
|
||||
subReqs.push_back(
|
||||
Req.subst(
|
||||
QueryInterfaceTypeSubstitutions(env),
|
||||
LookUpConformanceInModule(),
|
||||
SubstFlags::PreservePackExpansionLevel));
|
||||
|
||||
case CheckRequirementResult::ConditionalConformance:
|
||||
// FIXME: Need to handle conditional requirements here!
|
||||
break;
|
||||
while (!subReqs.empty()) {
|
||||
auto req = subReqs.pop_back_val();
|
||||
switch (req.checkRequirement(subReqs)) {
|
||||
case CheckRequirementResult::Success:
|
||||
case CheckRequirementResult::PackRequirement:
|
||||
case CheckRequirementResult::ConditionalConformance:
|
||||
break;
|
||||
|
||||
case CheckRequirementResult::PackRequirement:
|
||||
// FIXME
|
||||
assert(false && "Refactor this");
|
||||
return true;
|
||||
|
||||
case CheckRequirementResult::SubstitutionFailure:
|
||||
return true;
|
||||
|
||||
case CheckRequirementResult::RequirementFailure:
|
||||
if (!SubstReq.canBeSatisfied())
|
||||
case CheckRequirementResult::SubstitutionFailure:
|
||||
return true;
|
||||
|
||||
MergeInfo.addRequirement(Req);
|
||||
break;
|
||||
case CheckRequirementResult::RequirementFailure:
|
||||
if (!req.canBeSatisfied())
|
||||
return true;
|
||||
|
||||
MergeInfo.addRequirement(Req);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// RUN: %FileCheck %s -check-prefix=CHECK1 < %t.syn.txt
|
||||
// RUN: %FileCheck %s -check-prefix=CHECK2 < %t.syn.txt
|
||||
// RUN: %FileCheck %s -check-prefix=CHECK3 < %t.syn.txt
|
||||
@@ -17,6 +17,7 @@
|
||||
// RUN: %FileCheck %s -check-prefix=CHECK14 < %t.syn.txt
|
||||
// RUN: %FileCheck %s -check-prefix=CHECK15 < %t.syn.txt
|
||||
// RUN: %FileCheck %s -check-prefix=CHECK16 < %t.syn.txt
|
||||
// RUN: %FileCheck %s -check-prefix=CHECK17 < %t.syn.txt
|
||||
|
||||
public protocol P1 {
|
||||
associatedtype T1
|
||||
@@ -312,8 +313,6 @@ extension S13 : P5 {
|
||||
// CHECK11-NEXT: public func <loc>foo3()</loc></decl>
|
||||
// CHECK11-NEXT: <decl:Func>/// This is picked
|
||||
// CHECK11-NEXT: public func <loc>foo4()</loc></decl>
|
||||
// CHECK11-NEXT: <decl:Func>/// This should not crash
|
||||
// CHECK11-NEXT: public func <loc>foo5()</loc></decl>
|
||||
// CHECK11-NEXT: }</synthesized>
|
||||
|
||||
// CHECK12: <decl:Protocol>public protocol <loc>P6</loc> {
|
||||
@@ -338,8 +337,6 @@ extension S13 : P5 {
|
||||
// CHECK14-NEXT: public func <loc>foo3()</loc></decl>
|
||||
// CHECK14-NEXT: <decl:Func>/// This is picked
|
||||
// CHECK14-NEXT: public func <loc>foo4()</loc></decl>
|
||||
// CHECK14-NEXT: <decl:Func>/// This should not crash
|
||||
// CHECK14-NEXT: public func <loc>foo5()</loc></decl>
|
||||
// CHECK14-NEXT: }</synthesized>
|
||||
|
||||
// rdar://76868074: Make sure we print the extensions for C.
|
||||
@@ -398,3 +395,19 @@ extension F : P8 {}
|
||||
// CHECK16-NEXT: }</synthesized>
|
||||
|
||||
// CHECK16-NOT: <synthesized>extension <ref:Class>F</ref> where <ref:GenericTypeParam>T</ref> : <ref:module>print_synthesized_extensions</ref>.<ref:Class>E</ref> {
|
||||
|
||||
|
||||
// Parameter packs
|
||||
public protocol P14 {}
|
||||
|
||||
extension P14 {
|
||||
public func foo<each T: Equatable>(_: repeat each T) {}
|
||||
}
|
||||
|
||||
public struct S14<each T: Equatable> {}
|
||||
|
||||
extension S14 : P14 where repeat each T: Hashable {}
|
||||
|
||||
// CHECK17: <synthesized>extension <ref:Struct>S14</ref> {
|
||||
// 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>
|
||||
// CHECK17-NEXT: }</synthesized>
|
||||
Reference in New Issue
Block a user