Skip to content

Commit 70dec2b

Browse files
committed
AST: Split off Requirement.cpp from GenericSignature.cpp
1 parent 1e00c31 commit 70dec2b

File tree

3 files changed

+192
-168
lines changed

3 files changed

+192
-168
lines changed

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ add_swift_host_library(swiftAST STATIC
7777
ProtocolConformance.cpp
7878
ProtocolConformanceRef.cpp
7979
RawComment.cpp
80+
Requirement.cpp
8081
RequirementEnvironment.cpp
8182
RequirementMachine/ConcreteContraction.cpp
8283
RequirementMachine/ConcreteTypeWitness.cpp

lib/AST/GenericSignature.cpp

Lines changed: 0 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -741,174 +741,6 @@ void swift::simple_display(raw_ostream &out, GenericSignature sig) {
741741
out << "NULL";
742742
}
743743

744-
bool Requirement::hasError() const {
745-
if (getFirstType()->hasError())
746-
return true;
747-
748-
if (getKind() != RequirementKind::Layout && getSecondType()->hasError())
749-
return true;
750-
751-
return false;
752-
}
753-
754-
bool Requirement::isCanonical() const {
755-
if (!getFirstType()->isCanonical())
756-
return false;
757-
758-
switch (getKind()) {
759-
case RequirementKind::SameShape:
760-
case RequirementKind::Conformance:
761-
case RequirementKind::SameType:
762-
case RequirementKind::Superclass:
763-
if (!getSecondType()->isCanonical())
764-
return false;
765-
break;
766-
767-
case RequirementKind::Layout:
768-
break;
769-
}
770-
771-
return true;
772-
}
773-
774-
/// Get the canonical form of this requirement.
775-
Requirement Requirement::getCanonical() const {
776-
Type firstType = getFirstType()->getCanonicalType();
777-
778-
switch (getKind()) {
779-
case RequirementKind::SameShape:
780-
case RequirementKind::Conformance:
781-
case RequirementKind::SameType:
782-
case RequirementKind::Superclass: {
783-
Type secondType = getSecondType()->getCanonicalType();
784-
return Requirement(getKind(), firstType, secondType);
785-
}
786-
787-
case RequirementKind::Layout:
788-
return Requirement(getKind(), firstType, getLayoutConstraint());
789-
}
790-
llvm_unreachable("Unhandled RequirementKind in switch");
791-
}
792-
793-
ProtocolDecl *Requirement::getProtocolDecl() const {
794-
assert(getKind() == RequirementKind::Conformance);
795-
return getSecondType()->castTo<ProtocolType>()->getDecl();
796-
}
797-
798-
bool
799-
Requirement::isSatisfied(ArrayRef<Requirement> &conditionalRequirements,
800-
bool allowMissing) const {
801-
switch (getKind()) {
802-
case RequirementKind::Conformance: {
803-
auto *proto = getProtocolDecl();
804-
auto *module = proto->getParentModule();
805-
auto conformance = module->lookupConformance(
806-
getFirstType(), proto, allowMissing);
807-
if (!conformance)
808-
return false;
809-
810-
conditionalRequirements = conformance.getConditionalRequirements();
811-
return true;
812-
}
813-
814-
case RequirementKind::Layout: {
815-
if (auto *archetypeType = getFirstType()->getAs<ArchetypeType>()) {
816-
auto layout = archetypeType->getLayoutConstraint();
817-
return (layout && layout.merge(getLayoutConstraint()));
818-
}
819-
820-
if (getLayoutConstraint()->isClass())
821-
return getFirstType()->satisfiesClassConstraint();
822-
823-
// TODO: Statically check other layout constraints, once they can
824-
// be spelled in Swift.
825-
return true;
826-
}
827-
828-
case RequirementKind::Superclass:
829-
return getSecondType()->isExactSuperclassOf(getFirstType());
830-
831-
case RequirementKind::SameType:
832-
return getFirstType()->isEqual(getSecondType());
833-
834-
case RequirementKind::SameShape:
835-
return (getFirstType()->getReducedShape() ==
836-
getSecondType()->getReducedShape());
837-
}
838-
839-
llvm_unreachable("Bad requirement kind");
840-
}
841-
842-
bool Requirement::canBeSatisfied() const {
843-
switch (getKind()) {
844-
case RequirementKind::SameShape:
845-
llvm_unreachable("Same-shape requirements not supported here");
846-
847-
case RequirementKind::Conformance:
848-
return getFirstType()->is<ArchetypeType>();
849-
850-
case RequirementKind::Layout: {
851-
if (auto *archetypeType = getFirstType()->getAs<ArchetypeType>()) {
852-
auto layout = archetypeType->getLayoutConstraint();
853-
return (!layout || layout.merge(getLayoutConstraint()));
854-
}
855-
856-
return false;
857-
}
858-
859-
case RequirementKind::Superclass:
860-
return (getFirstType()->isBindableTo(getSecondType()) ||
861-
getSecondType()->isBindableTo(getFirstType()));
862-
863-
case RequirementKind::SameType:
864-
return (getFirstType()->isBindableTo(getSecondType()) ||
865-
getSecondType()->isBindableTo(getFirstType()));
866-
}
867-
868-
llvm_unreachable("Bad requirement kind");
869-
}
870-
871-
/// Determine the canonical ordering of requirements.
872-
static unsigned getRequirementKindOrder(RequirementKind kind) {
873-
switch (kind) {
874-
case RequirementKind::SameShape: return 4;
875-
case RequirementKind::Conformance: return 2;
876-
case RequirementKind::Superclass: return 0;
877-
case RequirementKind::SameType: return 3;
878-
case RequirementKind::Layout: return 1;
879-
}
880-
llvm_unreachable("unhandled kind");
881-
}
882-
883-
/// Linear order on requirements in a generic signature.
884-
int Requirement::compare(const Requirement &other) const {
885-
int compareLHS =
886-
compareDependentTypes(getFirstType(), other.getFirstType());
887-
888-
if (compareLHS != 0)
889-
return compareLHS;
890-
891-
int compareKind = (getRequirementKindOrder(getKind()) -
892-
getRequirementKindOrder(other.getKind()));
893-
894-
if (compareKind != 0)
895-
return compareKind;
896-
897-
// We should only have multiple conformance requirements.
898-
if (getKind() != RequirementKind::Conformance) {
899-
llvm::errs() << "Unordered generic requirements\n";
900-
llvm::errs() << "LHS: "; dump(llvm::errs()); llvm::errs() << "\n";
901-
llvm::errs() << "RHS: "; other.dump(llvm::errs()); llvm::errs() << "\n";
902-
abort();
903-
}
904-
905-
int compareProtos =
906-
TypeDecl::compare(getProtocolDecl(), other.getProtocolDecl());
907-
assert(compareProtos != 0 && "Duplicate conformance requirements");
908-
909-
return compareProtos;
910-
}
911-
912744
/// Compare two associated types.
913745
int swift::compareAssociatedTypes(AssociatedTypeDecl *assocType1,
914746
AssociatedTypeDecl *assocType2) {

lib/AST/Requirement.cpp

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
//===--- Requirement.cpp - Generic requirement ----------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements the Requirement class.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "swift/AST/Requirement.h"
18+
#include "swift/AST/Decl.h"
19+
#include "swift/AST/GenericSignature.h"
20+
#include "swift/AST/Module.h"
21+
#include "swift/AST/Types.h"
22+
23+
using namespace swift;
24+
25+
bool Requirement::hasError() const {
26+
if (getFirstType()->hasError())
27+
return true;
28+
29+
if (getKind() != RequirementKind::Layout && getSecondType()->hasError())
30+
return true;
31+
32+
return false;
33+
}
34+
35+
bool Requirement::isCanonical() const {
36+
if (!getFirstType()->isCanonical())
37+
return false;
38+
39+
switch (getKind()) {
40+
case RequirementKind::SameShape:
41+
case RequirementKind::Conformance:
42+
case RequirementKind::SameType:
43+
case RequirementKind::Superclass:
44+
if (!getSecondType()->isCanonical())
45+
return false;
46+
break;
47+
48+
case RequirementKind::Layout:
49+
break;
50+
}
51+
52+
return true;
53+
}
54+
55+
/// Get the canonical form of this requirement.
56+
Requirement Requirement::getCanonical() const {
57+
Type firstType = getFirstType()->getCanonicalType();
58+
59+
switch (getKind()) {
60+
case RequirementKind::SameShape:
61+
case RequirementKind::Conformance:
62+
case RequirementKind::SameType:
63+
case RequirementKind::Superclass: {
64+
Type secondType = getSecondType()->getCanonicalType();
65+
return Requirement(getKind(), firstType, secondType);
66+
}
67+
68+
case RequirementKind::Layout:
69+
return Requirement(getKind(), firstType, getLayoutConstraint());
70+
}
71+
llvm_unreachable("Unhandled RequirementKind in switch");
72+
}
73+
74+
ProtocolDecl *Requirement::getProtocolDecl() const {
75+
assert(getKind() == RequirementKind::Conformance);
76+
return getSecondType()->castTo<ProtocolType>()->getDecl();
77+
}
78+
79+
bool
80+
Requirement::isSatisfied(ArrayRef<Requirement> &conditionalRequirements,
81+
bool allowMissing) const {
82+
switch (getKind()) {
83+
case RequirementKind::Conformance: {
84+
auto *proto = getProtocolDecl();
85+
auto *module = proto->getParentModule();
86+
auto conformance = module->lookupConformance(
87+
getFirstType(), proto, allowMissing);
88+
if (!conformance)
89+
return false;
90+
91+
conditionalRequirements = conformance.getConditionalRequirements();
92+
return true;
93+
}
94+
95+
case RequirementKind::Layout: {
96+
if (auto *archetypeType = getFirstType()->getAs<ArchetypeType>()) {
97+
auto layout = archetypeType->getLayoutConstraint();
98+
return (layout && layout.merge(getLayoutConstraint()));
99+
}
100+
101+
if (getLayoutConstraint()->isClass())
102+
return getFirstType()->satisfiesClassConstraint();
103+
104+
// TODO: Statically check other layout constraints, once they can
105+
// be spelled in Swift.
106+
return true;
107+
}
108+
109+
case RequirementKind::Superclass:
110+
return getSecondType()->isExactSuperclassOf(getFirstType());
111+
112+
case RequirementKind::SameType:
113+
return getFirstType()->isEqual(getSecondType());
114+
115+
case RequirementKind::SameShape:
116+
return (getFirstType()->getReducedShape() ==
117+
getSecondType()->getReducedShape());
118+
}
119+
120+
llvm_unreachable("Bad requirement kind");
121+
}
122+
123+
bool Requirement::canBeSatisfied() const {
124+
switch (getKind()) {
125+
case RequirementKind::SameShape:
126+
llvm_unreachable("Same-shape requirements not supported here");
127+
128+
case RequirementKind::Conformance:
129+
return getFirstType()->is<ArchetypeType>();
130+
131+
case RequirementKind::Layout: {
132+
if (auto *archetypeType = getFirstType()->getAs<ArchetypeType>()) {
133+
auto layout = archetypeType->getLayoutConstraint();
134+
return (!layout || layout.merge(getLayoutConstraint()));
135+
}
136+
137+
return false;
138+
}
139+
140+
case RequirementKind::Superclass:
141+
return (getFirstType()->isBindableTo(getSecondType()) ||
142+
getSecondType()->isBindableTo(getFirstType()));
143+
144+
case RequirementKind::SameType:
145+
return (getFirstType()->isBindableTo(getSecondType()) ||
146+
getSecondType()->isBindableTo(getFirstType()));
147+
}
148+
149+
llvm_unreachable("Bad requirement kind");
150+
}
151+
152+
/// Determine the canonical ordering of requirements.
153+
static unsigned getRequirementKindOrder(RequirementKind kind) {
154+
switch (kind) {
155+
case RequirementKind::SameShape: return 4;
156+
case RequirementKind::Conformance: return 2;
157+
case RequirementKind::Superclass: return 0;
158+
case RequirementKind::SameType: return 3;
159+
case RequirementKind::Layout: return 1;
160+
}
161+
llvm_unreachable("unhandled kind");
162+
}
163+
164+
/// Linear order on requirements in a generic signature.
165+
int Requirement::compare(const Requirement &other) const {
166+
int compareLHS =
167+
compareDependentTypes(getFirstType(), other.getFirstType());
168+
169+
if (compareLHS != 0)
170+
return compareLHS;
171+
172+
int compareKind = (getRequirementKindOrder(getKind()) -
173+
getRequirementKindOrder(other.getKind()));
174+
175+
if (compareKind != 0)
176+
return compareKind;
177+
178+
// We should only have multiple conformance requirements.
179+
if (getKind() != RequirementKind::Conformance) {
180+
llvm::errs() << "Unordered generic requirements\n";
181+
llvm::errs() << "LHS: "; dump(llvm::errs()); llvm::errs() << "\n";
182+
llvm::errs() << "RHS: "; other.dump(llvm::errs()); llvm::errs() << "\n";
183+
abort();
184+
}
185+
186+
int compareProtos =
187+
TypeDecl::compare(getProtocolDecl(), other.getProtocolDecl());
188+
assert(compareProtos != 0 && "Duplicate conformance requirements");
189+
190+
return compareProtos;
191+
}

0 commit comments

Comments
 (0)