17
17
#ifndef SWIFT_AST_REQUIREMENT_H
18
18
#define SWIFT_AST_REQUIREMENT_H
19
19
20
+ #include " swift/AST/LayoutConstraint.h"
21
+ #include " swift/AST/RequirementBase.h"
20
22
#include " swift/AST/Type.h"
21
23
#include " swift/Basic/Debug.h"
22
24
#include " llvm/ADT/Hashing.h"
25
27
26
28
namespace swift {
27
29
28
- // / Describes the kind of a requirement that occurs within a requirements
29
- // / clause.
30
- enum class RequirementKind : unsigned {
31
- // / A conformance requirement T : P, where T is a type that depends
32
- // / on a generic parameter and P is a protocol to which T must conform.
33
- Conformance,
34
- // / A superclass requirement T : C, where T is a type that depends
35
- // / on a generic parameter and C is a concrete class type which T must
36
- // / equal or be a subclass of.
37
- Superclass,
38
- // / A same-type requirement T == U, where T and U are types that shall be
39
- // / equivalent.
40
- SameType,
41
- // / A layout bound T : L, where T is a type that depends on a generic
42
- // / parameter and L is some layout specification that should bound T.
43
- Layout,
44
-
45
- // Note: there is code that packs this enum in a 2-bit bitfield. Audit users
46
- // when adding enumerators.
47
- };
48
-
49
30
// / A single requirement placed on the type parameters (or associated
50
31
// / types thereof) of a
51
- class Requirement {
52
- llvm::PointerIntPair<Type, 3 , RequirementKind> FirstTypeAndKind;
53
- // / The second element of the requirement. Its content is dependent
54
- // / on the requirement kind.
55
- // / The payload of the following enum should always match the kind!
56
- // / Any access to the fields of this enum should first check if the
57
- // / requested access matches the kind of the requirement.
58
- union {
59
- Type SecondType;
60
- LayoutConstraint SecondLayout;
61
- };
62
-
32
+ class Requirement
33
+ : public RequirementBase<Type,
34
+ llvm::PointerIntPair<Type, 3 , RequirementKind>,
35
+ LayoutConstraint> {
63
36
public:
64
37
// / Create a conformance or same-type requirement.
65
38
Requirement (RequirementKind kind, Type first, Type second)
66
- : FirstTypeAndKind(first, kind), SecondType(second) {
67
- assert (first);
68
- assert (second);
69
- }
39
+ : RequirementBase(kind, first, second) {}
70
40
71
41
// / Create a layout constraint requirement.
72
42
Requirement (RequirementKind kind, Type first, LayoutConstraint second)
73
- : FirstTypeAndKind(first, kind), SecondLayout(second) {
74
- assert (first);
75
- assert (second);
76
- }
77
-
78
- // / Determine the kind of requirement.
79
- RequirementKind getKind () const { return FirstTypeAndKind.getInt (); }
43
+ : RequirementBase(kind, first, second) {}
80
44
81
- // / Retrieve the first type.
82
- Type getFirstType () const {
83
- return FirstTypeAndKind.getPointer ();
84
- }
45
+ // / Whether this requirement is in its canonical form.
46
+ bool isCanonical () const ;
85
47
86
- // / Retrieve the second type.
87
- Type getSecondType () const {
88
- assert (getKind () != RequirementKind::Layout);
89
- return SecondType;
90
- }
48
+ // / Get the canonical form of this requirement.
49
+ Requirement getCanonical () const ;
91
50
92
51
// / Subst the types involved in this requirement.
93
52
// /
94
53
// / The \c args arguments are passed through to Type::subst. This doesn't
95
54
// / touch the superclasses, protocols or layout constraints.
96
- template <typename ... Args>
97
- Optional<Requirement> subst (Args &&... args) const {
55
+ template <typename ...Args>
56
+ llvm:: Optional<Requirement> subst (Args &&...args) const {
98
57
auto newFirst = getFirstType ().subst (std::forward<Args>(args)...);
99
58
if (newFirst->hasError ())
100
59
return None;
@@ -115,61 +74,10 @@ class Requirement {
115
74
llvm_unreachable (" Unhandled RequirementKind in switch." );
116
75
}
117
76
118
- // / Retrieve the layout constraint.
119
- LayoutConstraint getLayoutConstraint () const {
120
- assert (getKind () == RequirementKind::Layout);
121
- return SecondLayout;
122
- }
123
-
124
- // / Whether this requirement is in its canonical form.
125
- bool isCanonical () const ;
126
-
127
- // / Get the canonical form of this requirement.
128
- Requirement getCanonical () const ;
129
-
130
77
SWIFT_DEBUG_DUMP;
131
78
void dump (raw_ostream &out) const ;
132
79
void print (raw_ostream &os, const PrintOptions &opts) const ;
133
80
void print (ASTPrinter &printer, const PrintOptions &opts) const ;
134
-
135
- friend llvm::hash_code hash_value (const Requirement &requirement) {
136
- using llvm::hash_value;
137
-
138
- llvm::hash_code first =
139
- hash_value (requirement.FirstTypeAndKind .getOpaqueValue ());
140
- llvm::hash_code second;
141
- switch (requirement.getKind ()) {
142
- case RequirementKind::Conformance:
143
- case RequirementKind::Superclass:
144
- case RequirementKind::SameType:
145
- second = hash_value (requirement.getSecondType ().getPointer ());
146
- break ;
147
-
148
- case RequirementKind::Layout:
149
- second = hash_value (requirement.getLayoutConstraint ());
150
- break ;
151
- }
152
-
153
- return llvm::hash_combine (first, second);
154
- }
155
-
156
- friend bool operator ==(const Requirement &lhs, const Requirement &rhs) {
157
- if (lhs.FirstTypeAndKind .getOpaqueValue ()
158
- != rhs.FirstTypeAndKind .getOpaqueValue ())
159
- return false ;
160
-
161
- switch (lhs.getKind ()) {
162
- case RequirementKind::Conformance:
163
- case RequirementKind::Superclass:
164
- case RequirementKind::SameType:
165
- return lhs.getSecondType ().getPointer () ==
166
- rhs.getSecondType ().getPointer ();
167
-
168
- case RequirementKind::Layout:
169
- return lhs.getLayoutConstraint () == rhs.getLayoutConstraint ();
170
- }
171
- llvm_unreachable (" Unhandled RequirementKind in switch" );
172
- }
173
81
};
174
82
175
83
inline void simple_display (llvm::raw_ostream &out, const Requirement &req) {
0 commit comments