Skip to content

Commit affd1bf

Browse files
committed
AST: Fold RequirementBase into it's three subclasses
It's a very simple algebraic data type, and factoring it out into a template doesn't carry its weight.
1 parent 8731eb4 commit affd1bf

File tree

6 files changed

+238
-199
lines changed

6 files changed

+238
-199
lines changed

include/swift/AST/Requirement.h

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define SWIFT_AST_REQUIREMENT_H
1919

2020
#include "swift/AST/LayoutConstraint.h"
21-
#include "swift/AST/RequirementBase.h"
21+
#include "swift/AST/RequirementKind.h"
2222
#include "swift/AST/Type.h"
2323
#include "swift/Basic/Debug.h"
2424
#include "llvm/ADT/Hashing.h"
@@ -29,18 +29,97 @@ namespace swift {
2929

3030
/// A single requirement placed on the type parameters (or associated
3131
/// types thereof) of a
32-
class Requirement
33-
: public RequirementBase<Type,
34-
llvm::PointerIntPair<Type, 3, RequirementKind>,
35-
LayoutConstraint> {
32+
class Requirement {
33+
llvm::PointerIntPair<Type, 3, RequirementKind> FirstTypeAndKind;
34+
/// The second element of the requirement. Its content is dependent
35+
/// on the requirement kind.
36+
/// The payload of the following enum should always match the kind!
37+
/// Any access to the fields of this enum should first check if the
38+
/// requested access matches the kind of the requirement.
39+
union {
40+
Type SecondType;
41+
LayoutConstraint SecondLayout;
42+
};
43+
3644
public:
3745
/// Create a conformance or same-type requirement.
3846
Requirement(RequirementKind kind, Type first, Type second)
39-
: RequirementBase(kind, first, second) {}
47+
: FirstTypeAndKind(first, kind), SecondType(second) {
48+
assert(first);
49+
assert(second);
50+
assert(kind != RequirementKind::Layout);
51+
}
4052

4153
/// Create a layout constraint requirement.
4254
Requirement(RequirementKind kind, Type first, LayoutConstraint second)
43-
: RequirementBase(kind, first, second) {}
55+
: FirstTypeAndKind(first, kind), SecondLayout(second) {
56+
assert(first);
57+
assert(second);
58+
assert(kind == RequirementKind::Layout);
59+
}
60+
61+
62+
/// Determine the kind of requirement.
63+
RequirementKind getKind() const { return FirstTypeAndKind.getInt(); }
64+
65+
/// Retrieve the first type.
66+
Type getFirstType() const {
67+
return FirstTypeAndKind.getPointer();
68+
}
69+
70+
/// Retrieve the second type.
71+
Type getSecondType() const {
72+
assert(getKind() != RequirementKind::Layout);
73+
return SecondType;
74+
}
75+
76+
/// Retrieve the layout constraint.
77+
LayoutConstraint getLayoutConstraint() const {
78+
assert(getKind() == RequirementKind::Layout);
79+
return SecondLayout;
80+
}
81+
82+
friend llvm::hash_code hash_value(const Requirement &requirement) {
83+
using llvm::hash_value;
84+
85+
llvm::hash_code first =
86+
hash_value(requirement.FirstTypeAndKind.getOpaqueValue());
87+
llvm::hash_code second;
88+
switch (requirement.getKind()) {
89+
case RequirementKind::SameShape:
90+
case RequirementKind::Conformance:
91+
case RequirementKind::Superclass:
92+
case RequirementKind::SameType:
93+
second = hash_value(requirement.getSecondType());
94+
break;
95+
96+
case RequirementKind::Layout:
97+
second = hash_value(requirement.getLayoutConstraint());
98+
break;
99+
}
100+
101+
return llvm::hash_combine(first, second);
102+
}
103+
104+
friend bool operator==(const Requirement &lhs,
105+
const Requirement &rhs) {
106+
if (lhs.FirstTypeAndKind.getOpaqueValue()
107+
!= rhs.FirstTypeAndKind.getOpaqueValue())
108+
return false;
109+
110+
switch (lhs.getKind()) {
111+
case RequirementKind::SameShape:
112+
case RequirementKind::Conformance:
113+
case RequirementKind::Superclass:
114+
case RequirementKind::SameType:
115+
return lhs.getSecondType().getPointer() ==
116+
rhs.getSecondType().getPointer();
117+
118+
case RequirementKind::Layout:
119+
return lhs.getLayoutConstraint() == rhs.getLayoutConstraint();
120+
}
121+
llvm_unreachable("Unhandled RequirementKind in switch");
122+
}
44123

45124
/// Whether this requirement's types contain ErrorTypes.
46125
bool hasError() const;

include/swift/AST/RequirementBase.h

Lines changed: 0 additions & 144 deletions
This file was deleted.

include/swift/AST/RequirementKind.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===--- RequirementKind.h - Swift RequirementKind AST ---------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 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 defines the RequirementKind enum.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_AST_REQUIREMENTKIND_H
18+
#define SWIFT_AST_REQUIREMENTKIND_H
19+
20+
namespace swift {
21+
/// Describes the kind of a requirement that occurs within a requirements
22+
/// clause.
23+
enum class RequirementKind : unsigned {
24+
/// A conformance requirement T : P, where T is a type that depends
25+
/// on a generic parameter and P is a protocol to which T must conform.
26+
Conformance,
27+
/// A superclass requirement T : C, where T is a type that depends
28+
/// on a generic parameter and C is a concrete class type which T must
29+
/// equal or be a subclass of.
30+
Superclass,
31+
/// A same-type requirement T == U, where T and U are types that shall be
32+
/// equivalent.
33+
SameType,
34+
/// A layout bound T : L, where T is a type that depends on a generic
35+
/// parameter and L is some layout specification that should bound T.
36+
Layout,
37+
/// A same-shape requirement shape(T) == shape(U), where T and U are pack
38+
/// parameters.
39+
SameShape
40+
41+
// Note: there is code that packs this enum in a 3-bit bitfield. Audit users
42+
// when adding enumerators.
43+
};
44+
45+
} // namespace swift
46+
#endif

include/swift/Demangling/TypeDecoder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include "swift/Basic/LLVM.h"
2323
#include "swift/ABI/MetadataValues.h"
2424
#include "swift/AST/LayoutConstraintKind.h"
25-
#include "swift/AST/RequirementBase.h"
25+
#include "swift/AST/RequirementKind.h"
2626
#include "swift/Basic/Unreachable.h"
2727
#include "swift/Demangling/Demangler.h"
2828
#include "swift/Demangling/NamespaceMacros.h"

include/swift/RemoteInspection/TypeRef.h

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -141,18 +141,55 @@ struct TypeRefLayoutConstraint {
141141
}
142142
};
143143

144-
class TypeRefRequirement
145-
: public RequirementBase<
146-
const TypeRef *,
147-
llvm::PointerIntPair<const TypeRef *, 3, RequirementKind>,
148-
TypeRefLayoutConstraint> {
144+
class TypeRefRequirement {
145+
llvm::PointerIntPair<const TypeRef *, 3, RequirementKind> FirstTypeAndKind;
146+
147+
/// The second element of the requirement. Its content is dependent
148+
/// on the requirement kind.
149+
/// The payload of the following enum should always match the kind!
150+
/// Any access to the fields of this enum should first check if the
151+
/// requested access matches the kind of the requirement.
152+
union {
153+
const TypeRef * SecondType;
154+
TypeRefLayoutConstraint SecondLayout;
155+
};
156+
149157
public:
150158
TypeRefRequirement(RequirementKind kind, const TypeRef *first,
151159
const TypeRef *second)
152-
: RequirementBase(kind, first, second) {}
160+
: FirstTypeAndKind(first, kind), SecondType(second) {
161+
assert(first);
162+
assert(second);
163+
assert(kind != RequirementKind::Layout);
164+
}
165+
153166
TypeRefRequirement(RequirementKind kind, const TypeRef *first,
154167
TypeRefLayoutConstraint second)
155-
: RequirementBase(kind, first, second) {}
168+
: FirstTypeAndKind(first, kind), SecondLayout(second) {
169+
assert(first);
170+
assert(second);
171+
assert(kind == RequirementKind::Layout);
172+
}
173+
174+
/// Determine the kind of requirement.
175+
RequirementKind getKind() const { return FirstTypeAndKind.getInt(); }
176+
177+
/// Retrieve the first type.
178+
const TypeRef *getFirstType() const {
179+
return FirstTypeAndKind.getPointer();
180+
}
181+
182+
/// Retrieve the second type.
183+
const TypeRef *getSecondType() const {
184+
assert(getKind() != RequirementKind::Layout);
185+
return SecondType;
186+
}
187+
188+
/// Retrieve the layout constraint.
189+
TypeRefLayoutConstraint getLayoutConstraint() const {
190+
assert(getKind() == RequirementKind::Layout);
191+
return SecondLayout;
192+
}
156193
};
157194

158195
// On 32-bit systems this needs more than just pointer alignment to fit the
@@ -991,8 +1028,16 @@ class SILBoxTypeWithLayoutTypeRef final : public TypeRef {
9911028
ID.addPointer(s.first);
9921029
ID.addPointer(s.second);
9931030
}
994-
for (auto &r : Requirements)
995-
ID.addInteger((uint64_t)(size_t)hash_value(hash_value(r)));
1031+
for (auto &r : Requirements) {
1032+
ID.addInteger(uint32_t(r.getKind()));
1033+
ID.addPointer(r.getFirstType());
1034+
if (r.getKind() != RequirementKind::Layout)
1035+
ID.addPointer(r.getSecondType());
1036+
else {
1037+
// FIXME: Implement TypeRefLayoutConstraint
1038+
ID.addInteger(uint32_t(0));
1039+
}
1040+
}
9961041
return ID;
9971042
}
9981043

0 commit comments

Comments
 (0)