Skip to content

Commit 3af359c

Browse files
authored
Merge pull request #10242 from CodaFi/in-through-the-out-door
[NFC] Move HasInOut bit out of recursive type properties
2 parents 27515c9 + a4bf57f commit 3af359c

File tree

10 files changed

+103
-83
lines changed

10 files changed

+103
-83
lines changed

include/swift/AST/Types.h

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ namespace swift {
7676
First_##Id##Type = FirstId, Last_##Id##Type = LastId,
7777
#include "swift/AST/TypeNodes.def"
7878
};
79-
79+
8080
/// Various properties of types that are primarily defined recursively
8181
/// on structural types.
8282
class RecursiveTypeProperties {
8383
public:
84-
enum { BitWidth = 11 };
84+
enum { BitWidth = 10 };
8585

8686
/// A single property.
8787
///
@@ -99,31 +99,25 @@ class RecursiveTypeProperties {
9999

100100
/// This type expression contains an UnresolvedType.
101101
HasUnresolvedType = 0x08,
102-
103-
/// This type expression contains an InOutType other than as a
104-
/// function input.
105-
HasInOut = 0x10,
106-
102+
107103
/// Whether this type expression contains an unbound generic type.
108-
HasUnboundGeneric = 0x20,
104+
HasUnboundGeneric = 0x10,
109105

110106
/// This type expression contains an LValueType other than as a
111107
/// function input, and can be loaded to convert to an rvalue.
112-
IsLValue = 0x40,
108+
IsLValue = 0x20,
113109

114110
/// This type expression contains an opened existential ArchetypeType.
115-
HasOpenedExistential = 0x80,
111+
HasOpenedExistential = 0x40,
116112

117113
/// This type expression contains a DynamicSelf type.
118-
HasDynamicSelf = 0x100,
114+
HasDynamicSelf = 0x80,
119115

120116
/// This type contains an Error type.
121-
HasError = 0x200,
117+
HasError = 0x100,
122118

123119
/// This type contains a DependentMemberType.
124-
HasDependentMember = 0x400,
125-
126-
IsNotMaterializable = (HasInOut | IsLValue)
120+
HasDependentMember = 0x200,
127121
};
128122

129123
private:
@@ -150,10 +144,6 @@ class RecursiveTypeProperties {
150144

151145
/// Does a type with these properties have an unresolved type somewhere in it?
152146
bool hasUnresolvedType() const { return Bits & HasUnresolvedType; }
153-
154-
/// Does a type with these properties structurally contain an
155-
/// inout, except as the parameter of a function?
156-
bool hasInOut() const { return Bits & HasInOut; }
157147

158148
/// Is a type with these properties an lvalue?
159149
bool isLValue() const { return Bits & IsLValue; }
@@ -165,10 +155,6 @@ class RecursiveTypeProperties {
165155
/// non-type parameter base, such as a type variable or concrete type?
166156
bool hasDependentMember() const { return Bits & HasDependentMember; }
167157

168-
/// Is a type with these properties materializable: that is, is it a
169-
/// first-class value type?
170-
bool isMaterializable() const { return !(Bits & IsNotMaterializable); }
171-
172158
/// Does a type with these properties structurally contain an
173159
/// archetype?
174160
bool hasOpenedExistential() const { return Bits & HasOpenedExistential; }
@@ -349,6 +335,14 @@ class alignas(1 << TypeAlignInBits) TypeBase {
349335
};
350336
enum { NumProtocolCompositionTypeBits = NumTypeBaseBits + 1 };
351337
static_assert(NumProtocolCompositionTypeBits <= 32, "fits in an unsigned");
338+
struct TupleTypeBitfields {
339+
unsigned : NumTypeBaseBits;
340+
341+
/// Whether an element of the tuple is inout.
342+
unsigned HasInOutElement : 1;
343+
};
344+
enum { NumTupleTypeBits = NumTypeBaseBits + 1 };
345+
static_assert(NumTupleTypeBits <= 32, "fits in an unsigned");
352346

353347
union {
354348
TypeBaseBitfields TypeBaseBits;
@@ -359,6 +353,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
359353
SILFunctionTypeBitfields SILFunctionTypeBits;
360354
AnyMetatypeTypeBitfields AnyMetatypeTypeBits;
361355
ProtocolCompositionTypeBitfields ProtocolCompositionTypeBits;
356+
TupleTypeBitfields TupleTypeBits;
362357
};
363358

364359
protected:
@@ -444,13 +439,6 @@ class alignas(1 << TypeAlignInBits) TypeBase {
444439
return RecursiveTypeProperties(TypeBaseBits.Properties);
445440
}
446441

447-
/// isMaterializable - Is this type 'materializable' according to
448-
/// the rules of the language? Basically, does it not contain any
449-
/// l-value types?
450-
bool isMaterializable() const {
451-
return getRecursiveProperties().isMaterializable();
452-
}
453-
454442
/// hasReferenceSemantics() - Do objects of this type have reference
455443
/// semantics?
456444
bool hasReferenceSemantics();
@@ -489,13 +477,7 @@ class alignas(1 << TypeAlignInBits) TypeBase {
489477
bool hasUnresolvedType() const {
490478
return getRecursiveProperties().hasUnresolvedType();
491479
}
492-
493-
/// \brief Determine whether the type involves an inout type, except
494-
/// as a function input.
495-
bool hasInOut() const {
496-
return getRecursiveProperties().hasInOut();
497-
}
498-
480+
499481
/// \brief Determine whether the type involves an archetype.
500482
bool hasArchetype() const {
501483
return getRecursiveProperties().hasArchetype();
@@ -560,6 +542,10 @@ class alignas(1 << TypeAlignInBits) TypeBase {
560542
bool isLValueType() {
561543
return getRecursiveProperties().isLValue();
562544
}
545+
546+
/// Is a type with these properties materializable: that is, is it a
547+
/// first-class value type?
548+
bool isMaterializable();
563549

564550
/// Determine whether the type is dependent on DynamicSelf.
565551
bool hasDynamicSelfType() const {
@@ -1583,7 +1569,12 @@ class TupleType : public TypeBase, public llvm::FoldingSetNode {
15831569
/// varargs element (i.e., if it is "Int...", this returns Int, not [Int]).
15841570
/// Otherwise, this returns Type().
15851571
Type getVarArgsBaseType() const;
1586-
1572+
1573+
/// Returns true if this tuple has inout elements.
1574+
bool hasInOutElement() const {
1575+
return static_cast<bool>(TupleTypeBits.HasInOutElement);
1576+
}
1577+
15871578
// Implement isa/cast/dyncast/etc.
15881579
static bool classof(const TypeBase *T) {
15891580
return T->getKind() == TypeKind::Tuple;
@@ -1597,8 +1588,10 @@ class TupleType : public TypeBase, public llvm::FoldingSetNode {
15971588

15981589
private:
15991590
TupleType(ArrayRef<TupleTypeElt> elements, const ASTContext *CanCtx,
1600-
RecursiveTypeProperties properties)
1591+
RecursiveTypeProperties properties,
1592+
bool hasInOut)
16011593
: TypeBase(TypeKind::Tuple, CanCtx, properties), Elements(elements) {
1594+
TupleTypeBits.HasInOutElement = hasInOut;
16021595
}
16031596
};
16041597
BEGIN_CAN_TYPE_WRAPPER(TupleType, Type)
@@ -4394,6 +4387,19 @@ inline bool TypeBase::isTypeParameter() {
43944387
return false;
43954388
}
43964389

4390+
inline bool TypeBase::isMaterializable() {
4391+
if (isLValueType())
4392+
return false;
4393+
4394+
if (is<InOutType>())
4395+
return false;
4396+
4397+
if (auto *TTy = getAs<TupleType>())
4398+
return !TTy->hasInOutElement();
4399+
4400+
return true;
4401+
}
4402+
43974403
inline GenericTypeParamType *TypeBase::getRootGenericParam() {
43984404
Type t(this);
43994405

lib/AST/ASTContext.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2696,9 +2696,13 @@ Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
26962696
Fields[0].getParameterFlags());
26972697

26982698
RecursiveTypeProperties properties;
2699+
bool hasInOut = false;
26992700
for (const TupleTypeElt &Elt : Fields) {
2700-
if (Elt.getType())
2701-
properties |= Elt.getType()->getRecursiveProperties();
2701+
auto eltTy = Elt.getType();
2702+
if (!eltTy) continue;
2703+
2704+
properties |= eltTy->getRecursiveProperties();
2705+
hasInOut |= eltTy->is<InOutType>();
27022706
}
27032707

27042708
auto arena = getArena(properties);
@@ -2727,7 +2731,8 @@ Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
27272731
Fields = ArrayRef<TupleTypeElt>(FieldsCopy, Fields.size());
27282732

27292733
TupleType *New =
2730-
new (C, arena) TupleType(Fields, IsCanonical ? &C : nullptr, properties);
2734+
new (C, arena) TupleType(Fields, IsCanonical ? &C : nullptr,
2735+
properties, hasInOut);
27312736
C.Impl.getArena(arena).TupleTypes.InsertNode(New, InsertPos);
27322737
return New;
27332738
}
@@ -3080,8 +3085,10 @@ ModuleType *ModuleType::get(ModuleDecl *M) {
30803085
}
30813086

30823087
DynamicSelfType *DynamicSelfType::get(Type selfType, const ASTContext &ctx) {
3088+
assert(selfType->isMaterializable()
3089+
&& "non-materializable dynamic self?");
3090+
30833091
auto properties = selfType->getRecursiveProperties();
3084-
assert(properties.isMaterializable() && "non-materializable dynamic self?");
30853092
auto arena = getArena(properties);
30863093

30873094
auto &dynamicSelfTypes = ctx.Impl.getArena(arena).DynamicSelfTypes;
@@ -3100,8 +3107,6 @@ static void checkFunctionRecursiveProperties(Type Input,
31003107
// constraint solving:
31013108
//assert(!Input->getRecursiveProperties().isLValue()
31023109
// && "function should not take lvalues directly as parameters");
3103-
//assert(Result->getRecursiveProperties().isMaterializable()
3104-
// && "function return should be materializable");
31053110
}
31063111

31073112
static RecursiveTypeProperties getFunctionRecursiveProperties(Type Input,
@@ -3110,7 +3115,7 @@ static RecursiveTypeProperties getFunctionRecursiveProperties(Type Input,
31103115

31113116
auto properties = Input->getRecursiveProperties()
31123117
| Result->getRecursiveProperties();
3113-
properties &= ~RecursiveTypeProperties::IsNotMaterializable;
3118+
properties &= ~RecursiveTypeProperties::IsLValue;
31143119
return properties;
31153120
}
31163121

@@ -3121,7 +3126,7 @@ static RecursiveTypeProperties
31213126
getGenericFunctionRecursiveProperties(Type Input, Type Result) {
31223127
checkFunctionRecursiveProperties(Input, Result);
31233128

3124-
static_assert(RecursiveTypeProperties::BitWidth == 11,
3129+
static_assert(RecursiveTypeProperties::BitWidth == 10,
31253130
"revisit this if you add new recursive type properties");
31263131
RecursiveTypeProperties properties;
31273132
if (Result->getRecursiveProperties().hasDynamicSelf())
@@ -3392,7 +3397,7 @@ CanSILFunctionType SILFunctionType::get(GenericSignature *genericSig,
33923397
void *mem = ctx.Allocate(bytes, alignof(SILFunctionType));
33933398

33943399
RecursiveTypeProperties properties;
3395-
static_assert(RecursiveTypeProperties::BitWidth == 11,
3400+
static_assert(RecursiveTypeProperties::BitWidth == 10,
33963401
"revisit this if you add new recursive type properties");
33973402
for (auto &param : params)
33983403
properties |= param.getType()->getRecursiveProperties();
@@ -3533,8 +3538,7 @@ InOutType *InOutType::get(Type objectTy) {
35333538
assert(!objectTy->is<LValueType>() && !objectTy->is<InOutType>() &&
35343539
"cannot have 'inout' or @lvalue wrapped inside an 'inout'");
35353540

3536-
auto properties = objectTy->getRecursiveProperties() |
3537-
RecursiveTypeProperties::HasInOut;
3541+
auto properties = objectTy->getRecursiveProperties();
35383542

35393543
properties &= ~RecursiveTypeProperties::IsLValue;
35403544
auto arena = getArena(properties);

lib/SIL/SILFunctionType.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,9 +547,10 @@ enum class ConventionsKind : uint8_t {
547547
// the tuple type is materializable -- if it doesn't contain an
548548
// l-value type -- then it's a valid target for substitution and
549549
// we should not expand it.
550-
if (isa<TupleType>(substType) &&
550+
CanTupleType substTupleTy = dyn_cast<TupleType>(substType);
551+
if (substTupleTy &&
551552
(!origType.isTypeParameter() ||
552-
!substType->isMaterializable())) {
553+
substTupleTy->hasInOutElement())) {
553554
auto substTuple = cast<TupleType>(substType);
554555
assert(origType.isTypeParameter() ||
555556
origType.getNumTupleElements() == substTuple->getNumElements());

lib/SILGen/SILGenApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2573,7 +2573,7 @@ class ArgEmitter {
25732573

25742574
bool isUnmaterializableTupleType(CanType type) {
25752575
if (auto tuple = dyn_cast<TupleType>(type))
2576-
if (!tuple->isMaterializable())
2576+
if (tuple->hasInOutElement())
25772577
return true;
25782578
return false;
25792579
}

lib/SILGen/SILGenExpr.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,7 +2034,7 @@ class NominalTypeMemberRefRValueEmitter {
20342034
CanType baseFormalType =
20352035
Expr->getBase()->getType()->getCanonicalType();
20362036
assert(baseFormalType->isMaterializable());
2037-
2037+
20382038
RValue result =
20392039
SGF.emitRValueForPropertyLoad(Expr, base, baseFormalType,
20402040
Expr->isSuper(),
@@ -2062,7 +2062,7 @@ class NominalTypeMemberRefRValueEmitter {
20622062
CanType baseFormalType =
20632063
Expr->getBase()->getType()->getCanonicalType();
20642064
assert(baseFormalType->isMaterializable());
2065-
2065+
20662066
// And then emit our property using whether or not base is at +0 to
20672067
// discriminate whether or not the base was guaranteed.
20682068
RValue result =
@@ -3544,8 +3544,8 @@ namespace {
35443544

35453545
// If the destination is a tuple, recursively destructure.
35463546
void visitTupleExpr(TupleExpr *E) {
3547-
assert(E->getType()->is<TupleType>());
3548-
assert(!E->getType()->isMaterializable() || E->getType()->isVoid());
3547+
auto *TTy = E->getType()->castTo<TupleType>();
3548+
assert(TTy->isLValueType() || TTy->isVoid());
35493549
for (auto &elt : E->getElements()) {
35503550
visit(elt);
35513551
}
@@ -3654,7 +3654,7 @@ static void emitSimpleAssignment(SILGenFunction &SGF, SILLocation loc,
36543654
SGF.emitIgnoredExpr(src);
36553655
return;
36563656
}
3657-
3657+
36583658
FormalEvaluationScope writeback(SGF);
36593659
LValue destLV = SGF.emitLValue(dest, AccessKind::Write);
36603660
RValue srcRV = SGF.emitRValue(src);
@@ -4507,7 +4507,7 @@ RValue RValueEmitter::visitUnevaluatedInstanceExpr(UnevaluatedInstanceExpr *E,
45074507
}
45084508

45094509
RValue SILGenFunction::emitRValue(Expr *E, SGFContext C) {
4510-
assert(E->getType()->isMaterializable() &&
4510+
assert(!E->getType()->isLValueType() &&
45114511
"l-values must be emitted with emitLValue");
45124512
return RValueEmitter(*this).visit(E, C);
45134513
}
@@ -4527,7 +4527,7 @@ void SILGenFunction::emitIgnoredExpr(Expr *E) {
45274527
// arguments.
45284528

45294529
FullExpr scope(Cleanups, CleanupLocation(E));
4530-
if (!E->getType()->isMaterializable()) {
4530+
if (E->getType()->isLValueType()) {
45314531
// Emit the l-value, but don't perform an access.
45324532
FormalEvaluationScope scope(*this);
45334533
emitLValue(E, AccessKind::Read);

lib/SILGen/SILGenPoly.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ namespace {
894894
}
895895

896896
// Special-case: tuples containing inouts.
897-
if (inputTupleType && inputTupleType->hasInOut()) {
897+
if (inputTupleType && inputTupleType->hasInOutElement()) {
898898
// Non-materializable tuple types cannot be bound as generic
899899
// arguments, so none of the remaining transformations apply.
900900
// Instead, the outermost tuple layer is exploded, even when
@@ -1078,8 +1078,8 @@ namespace {
10781078
CanTupleType inputTupleType,
10791079
AbstractionPattern outputOrigType,
10801080
CanTupleType outputTupleType) {
1081-
assert(!inputTupleType->hasInOut() &&
1082-
!outputTupleType->hasInOut());
1081+
assert(!inputTupleType->hasInOutElement() &&
1082+
!outputTupleType->hasInOutElement());
10831083
assert(inputTupleType->getNumElements() ==
10841084
outputTupleType->getNumElements());
10851085

@@ -1164,8 +1164,8 @@ namespace {
11641164
// when witness method thunks re-abstract a non-mutating
11651165
// witness for a mutating requirement. The inout self is just
11661166
// loaded to produce a value in this case.
1167-
assert(inputSubstType->hasInOut() ||
1168-
!outputSubstType->hasInOut());
1167+
assert(inputSubstType->hasInOutElement() ||
1168+
!outputSubstType->hasInOutElement());
11691169
assert(inputSubstType->getNumElements() ==
11701170
outputSubstType->getNumElements());
11711171

@@ -1186,8 +1186,8 @@ namespace {
11861186
ManagedValue inputTupleAddr) {
11871187
assert(inputOrigType.isTypeParameter());
11881188
assert(outputOrigType.matchesTuple(outputSubstType));
1189-
assert(!inputSubstType->hasInOut() &&
1190-
!outputSubstType->hasInOut());
1189+
assert(!inputSubstType->hasInOutElement() &&
1190+
!outputSubstType->hasInOutElement());
11911191
assert(inputSubstType->getNumElements() ==
11921192
outputSubstType->getNumElements());
11931193

@@ -1233,8 +1233,8 @@ namespace {
12331233
TemporaryInitialization &tupleInit) {
12341234
assert(inputOrigType.matchesTuple(inputSubstType));
12351235
assert(outputOrigType.matchesTuple(outputSubstType));
1236-
assert(!inputSubstType->hasInOut() &&
1237-
!outputSubstType->hasInOut());
1236+
assert(!inputSubstType->hasInOutElement() &&
1237+
!outputSubstType->hasInOutElement());
12381238
assert(inputSubstType->getNumElements() ==
12391239
outputSubstType->getNumElements());
12401240

0 commit comments

Comments
 (0)