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