Skip to content

Commit ad4e2b3

Browse files
authored
Merge pull request #59208 from gottesmm/sil-move-only-type-typesystem-changes
[move-only] Add initial type system changes to express move only ness in the type system
2 parents 399d5f3 + 0e2526d commit ad4e2b3

32 files changed

+610
-36
lines changed

include/swift/AST/Attr.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ TYPE_ATTR(yields)
8585
TYPE_ATTR(yield_once)
8686
TYPE_ATTR(yield_many)
8787
TYPE_ATTR(captures_generics)
88+
// Used at the SIL level to mark a type as moveOnly.
89+
TYPE_ATTR(moveOnly)
8890

8991
// SIL metatype attributes.
9092
TYPE_ATTR(thin)

include/swift/AST/TypeDifferenceVisitor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,11 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
333333
return asImpl().visit(type1->getCaptureType(), type2->getCaptureType());
334334
}
335335

336+
bool visitSILMoveOnlyType(CanSILMoveOnlyType type1,
337+
CanSILMoveOnlyType type2) {
338+
return asImpl().visit(type1->getInnerType(), type2->getInnerType());
339+
}
340+
336341
bool visitProtocolCompositionType(CanProtocolCompositionType type1,
337342
CanProtocolCompositionType type2) {
338343
return visitComponentArray(type1, type2,

include/swift/AST/TypeMatcher.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ class TypeMatcher {
352352
TRIVIAL_CASE(SILFunctionType)
353353
TRIVIAL_CASE(SILBlockStorageType)
354354
TRIVIAL_CASE(SILBoxType)
355+
TRIVIAL_CASE(SILMoveOnlyType)
355356

356357
bool visitProtocolCompositionType(CanProtocolCompositionType firstProtocolComposition,
357358
Type secondType,

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ ABSTRACT_TYPE(AnyFunction, Type)
159159
ARTIFICIAL_TYPE(SILFunction, Type)
160160
ARTIFICIAL_TYPE(SILBlockStorage, Type)
161161
ARTIFICIAL_TYPE(SILBox, Type)
162+
ARTIFICIAL_TYPE(SILMoveOnly, Type)
162163
ARTIFICIAL_TYPE(SILToken, Type)
163164
TYPE(ProtocolComposition, Type)
164165
TYPE(ParameterizedProtocol, Type)

include/swift/AST/Types.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4995,6 +4995,33 @@ class SILBoxType final : public TypeBase, public llvm::FoldingSetNode
49954995
};
49964996
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILBoxType, Type)
49974997

4998+
class SILMoveOnlyType;
4999+
class SILModule; // From SIL
5000+
typedef CanTypeWrapper<SILMoveOnlyType> CanMoveOnlyType;
5001+
5002+
/// A wrapper type that marks an inner type as being a move only value. Can not
5003+
/// be written directly at the Swift level, instead it is triggered by adding
5004+
/// the type attribute @_moveOnly to a different type. We transform these in
5005+
/// TypeLowering into a moveOnly SILType on the inner type.
5006+
class SILMoveOnlyType final : public TypeBase, public llvm::FoldingSetNode {
5007+
CanType innerType;
5008+
5009+
SILMoveOnlyType(CanType innerType)
5010+
: TypeBase(TypeKind::SILMoveOnly, &innerType->getASTContext(),
5011+
innerType->getRecursiveProperties()),
5012+
innerType(innerType) {}
5013+
5014+
public:
5015+
CanType getInnerType() const { return innerType; }
5016+
5017+
static CanMoveOnlyType get(CanType innerType);
5018+
5019+
static bool classof(const TypeBase *T) {
5020+
return T->getKind() == TypeKind::SILMoveOnly;
5021+
}
5022+
};
5023+
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILMoveOnlyType, Type)
5024+
49985025
class SILBlockStorageType;
49995026
typedef CanTypeWrapper<SILBlockStorageType> CanSILBlockStorageType;
50005027

include/swift/SIL/AbstractionPattern.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,14 @@ class AbstractionPattern {
13371337
llvm_unreachable("bad kind");
13381338
}
13391339

1340+
/// Given that the value being abstracted is a move only type, return the
1341+
/// abstraction pattern with the move only bit removed.
1342+
AbstractionPattern withoutMoveOnly() const;
1343+
1344+
/// Given that the value being abstracted is not a move only type, return the
1345+
/// abstraction pattern with the move only bit added.
1346+
AbstractionPattern withMoveOnly() const;
1347+
13401348
/// Given that the value being abstracted is a tuple type, return
13411349
/// the abstraction pattern for its object type.
13421350
AbstractionPattern getTupleElementType(unsigned index) const;

include/swift/SIL/SILType.h

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,18 @@ class SILType {
179179
/// `@thick AnyObject.Type`.
180180
/// More generally, you cannot recover a formal type from
181181
/// a lowered type. See docs/SIL.rst for more details.
182-
CanType getASTType() const {
183-
return CanType(value.getPointer());
184-
}
185-
182+
/// 3. If the underlying type is move only, the returned CanType will not be
183+
/// pointer equal to the RawASTType since we return the unwrapped inner
184+
/// type. This is done under the assumption that in all cases where we are
185+
/// performing these AST queries on SILType, we are not interested in the
186+
/// move only-ness of the value (which we can query separately anyways).
187+
CanType getASTType() const { return withoutMoveOnly().getRawASTType(); }
188+
189+
/// Returns the canonical AST type references by this SIL type without looking
190+
/// through move only. Should only be used by internal utilities of SILType.
191+
CanType getRawASTType() const { return CanType(value.getPointer()); }
192+
193+
public:
186194
// FIXME -- Temporary until LLDB adopts getASTType()
187195
LLVM_ATTRIBUTE_DEPRECATED(CanType getSwiftRValueType() const,
188196
"Please use getASTType()") {
@@ -411,9 +419,7 @@ class SILType {
411419
}
412420

413421
/// True if the type involves any archetypes.
414-
bool hasArchetype() const {
415-
return getASTType()->hasArchetype();
416-
}
422+
bool hasArchetype() const { return getASTType()->hasArchetype(); }
417423

418424
/// True if the type involves any opaque archetypes.
419425
bool hasOpaqueArchetype() const {
@@ -586,7 +592,42 @@ class SILType {
586592

587593
/// Returns true if this is the AnyObject SILType;
588594
bool isAnyObject() const { return getASTType()->isAnyObject(); }
589-
595+
596+
/// Returns true if this SILType is a move only wrapper type.
597+
///
598+
/// Canonical way to check if a SILType is move only. Using is/getAs/castTo
599+
/// will look through moveonly-ness.
600+
bool isMoveOnly() const { return getRawASTType()->is<SILMoveOnlyType>(); }
601+
602+
/// Return *this if already move only... otherwise, wrap the current type
603+
/// within a move only type wrapper and return that. Idempotent!
604+
SILType asMoveOnly() const {
605+
if (isMoveOnly())
606+
return *this;
607+
auto newType = SILMoveOnlyType::get(getRawASTType());
608+
return SILType::getPrimitiveType(newType, getCategory());
609+
}
610+
611+
/// Return this SILType, removing moveonly-ness.
612+
///
613+
/// Is idempotent.
614+
SILType withoutMoveOnly() const {
615+
if (!isMoveOnly())
616+
return *this;
617+
auto moveOnly = getRawASTType()->castTo<SILMoveOnlyType>();
618+
return SILType::getPrimitiveType(moveOnly->getInnerType(), getCategory());
619+
}
620+
621+
/// If \p otherType is move only, return this type that is move only as
622+
/// well. Otherwise, returns self. Useful for propagating "move only"-ness
623+
/// from a parent type to a subtype.
624+
SILType copyMoveOnly(SILType otherType) const {
625+
if (otherType.isMoveOnly()) {
626+
return asMoveOnly();
627+
}
628+
return *this;
629+
}
630+
590631
/// Returns a SILType with any archetypes mapped out of context.
591632
SILType mapTypeOutOfContext() const;
592633

include/swift/SIL/TypeLowering.h

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,19 @@ enum IsInfiniteType_t : bool {
169169
IsInfiniteType = true,
170170
};
171171

172+
/// Does this type contain a move only type that affects type lowering?
173+
enum IsMoveOnly_t : bool {
174+
IsNotMoveOnly = false,
175+
IsMoveOnly = true,
176+
};
177+
172178
/// Extended type information used by SIL.
173179
class TypeLowering {
174180
public:
175181
class RecursiveProperties {
176182
// These are chosen so that bitwise-or merges the flags properly.
183+
//
184+
// clang-format off
177185
enum : unsigned {
178186
NonTrivialFlag = 1 << 0,
179187
NonFixedABIFlag = 1 << 1,
@@ -182,7 +190,9 @@ class TypeLowering {
182190
TypeExpansionSensitiveFlag = 1 << 4,
183191
InfiniteFlag = 1 << 5,
184192
HasRawPointerFlag = 1 << 6,
193+
MoveOnlyFlag = 1 << 7,
185194
};
195+
// clang-format on
186196

187197
uint8_t Flags;
188198
public:
@@ -195,13 +205,15 @@ class TypeLowering {
195205
IsAddressOnly_t isAddressOnly, IsResilient_t isResilient,
196206
IsTypeExpansionSensitive_t isTypeExpansionSensitive =
197207
IsNotTypeExpansionSensitive,
198-
HasRawPointer_t hasRawPointer = DoesNotHaveRawPointer)
208+
HasRawPointer_t hasRawPointer = DoesNotHaveRawPointer,
209+
IsMoveOnly_t isMoveOnly = IsNotMoveOnly)
199210
: Flags((isTrivial ? 0U : NonTrivialFlag) |
200211
(isFixedABI ? 0U : NonFixedABIFlag) |
201212
(isAddressOnly ? AddressOnlyFlag : 0U) |
202213
(isResilient ? ResilientFlag : 0U) |
203214
(isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0U) |
204-
(hasRawPointer ? HasRawPointerFlag : 0U)) {}
215+
(hasRawPointer ? HasRawPointerFlag : 0U) |
216+
(isMoveOnly ? MoveOnlyFlag : 0U)) {}
205217

206218
constexpr bool operator==(RecursiveProperties p) const {
207219
return Flags == p.Flags;
@@ -228,6 +240,35 @@ class TypeLowering {
228240
return {IsTrivial, IsFixedABI, IsNotAddressOnly, IsResilient};
229241
}
230242

243+
static constexpr RecursiveProperties forMoveOnlyReference() {
244+
return {IsNotTrivial,
245+
IsFixedABI,
246+
IsNotAddressOnly,
247+
IsNotResilient,
248+
IsNotTypeExpansionSensitive,
249+
DoesNotHaveRawPointer,
250+
IsMoveOnly};
251+
}
252+
253+
static constexpr RecursiveProperties forMoveOnlyOpaque() {
254+
return {IsNotTrivial,
255+
IsNotFixedABI,
256+
IsAddressOnly,
257+
IsNotResilient,
258+
IsNotTypeExpansionSensitive,
259+
DoesNotHaveRawPointer,
260+
IsMoveOnly};
261+
}
262+
263+
static constexpr RecursiveProperties forMoveOnlyResilient() {
264+
return {IsTrivial,
265+
IsFixedABI,
266+
IsNotAddressOnly,
267+
IsResilient,
268+
IsNotTypeExpansionSensitive,
269+
DoesNotHaveRawPointer,
270+
IsMoveOnly};
271+
}
231272

232273
void addSubobject(RecursiveProperties other) {
233274
Flags |= other.Flags;
@@ -255,6 +296,9 @@ class TypeLowering {
255296
IsInfiniteType_t isInfinite() const {
256297
return IsInfiniteType_t((Flags & InfiniteFlag) != 0);
257298
}
299+
IsMoveOnly_t isMoveOnly() const {
300+
return IsMoveOnly_t((Flags & MoveOnlyFlag) != 0);
301+
}
258302

259303
void setNonTrivial() { Flags |= NonTrivialFlag; }
260304
void setNonFixedABI() { Flags |= NonFixedABIFlag; }
@@ -265,6 +309,7 @@ class TypeLowering {
265309
(isTypeExpansionSensitive ? TypeExpansionSensitiveFlag : 0);
266310
}
267311
void setInfinite() { Flags |= InfiniteFlag; }
312+
void setMoveOnly() { Flags |= MoveOnlyFlag; }
268313
};
269314

270315
private:

lib/AST/ASTContext.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ struct ASTContext::Implementation {
464464
llvm::FoldingSet<GenericFunctionType> GenericFunctionTypes;
465465
llvm::FoldingSet<SILFunctionType> SILFunctionTypes;
466466
llvm::DenseMap<CanType, SILBlockStorageType *> SILBlockStorageTypes;
467+
llvm::DenseMap<CanType, SILMoveOnlyType *> SILMoveOnlyTypes;
467468
llvm::FoldingSet<SILBoxType> SILBoxTypes;
468469
llvm::DenseMap<BuiltinIntegerWidth, BuiltinIntegerType*> IntegerTypes;
469470
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
@@ -4067,6 +4068,19 @@ SILFunctionType::SILFunctionType(
40674068
#endif
40684069
}
40694070

4071+
CanSILMoveOnlyType SILMoveOnlyType::get(CanType innerType) {
4072+
ASTContext &ctx = innerType->getASTContext();
4073+
auto found = ctx.getImpl().SILMoveOnlyTypes.find(innerType);
4074+
if (found != ctx.getImpl().SILMoveOnlyTypes.end())
4075+
return CanSILMoveOnlyType(found->second);
4076+
4077+
void *mem = ctx.Allocate(sizeof(SILMoveOnlyType), alignof(SILMoveOnlyType));
4078+
4079+
auto *storageTy = new (mem) SILMoveOnlyType(innerType);
4080+
ctx.getImpl().SILMoveOnlyTypes.insert({innerType, storageTy});
4081+
return CanSILMoveOnlyType(storageTy);
4082+
}
4083+
40704084
CanSILBlockStorageType SILBlockStorageType::get(CanType captureType) {
40714085
ASTContext &ctx = captureType->getASTContext();
40724086
auto found = ctx.getImpl().SILBlockStorageTypes.find(captureType);

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3935,6 +3935,12 @@ namespace {
39353935
PrintWithColorRAII(OS, ParenthesisColor) << ')';
39363936
}
39373937

3938+
void visitSILMoveOnlyType(SILMoveOnlyType *T, StringRef label) {
3939+
printCommon(label, "sil_move_only_type");
3940+
printRec(T->getInnerType());
3941+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3942+
}
3943+
39383944
void visitSILBoxType(SILBoxType *T, StringRef label) {
39393945
printCommon(label, "sil_box_type");
39403946
// FIXME: Print the structure of the type.

lib/AST/ASTMangler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,9 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
14481448

14491449
return;
14501450
}
1451-
1451+
case TypeKind::SILMoveOnly:
1452+
// If we hit this, we just mangle the underlying name and move on.
1453+
llvm_unreachable("should never be mangled?");
14521454
case TypeKind::SILBlockStorage:
14531455
llvm_unreachable("should never be mangled");
14541456
}

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6193,6 +6193,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
61936193
}
61946194
}
61956195

6196+
void visitSILMoveOnlyType(SILMoveOnlyType *T) {
6197+
Printer << "@moveOnly ";
6198+
printWithParensIfNotSimple(T->getInnerType());
6199+
}
6200+
61966201
void visitArraySliceType(ArraySliceType *T) {
61976202
Printer << "[";
61986203
visit(T->getBaseType());

lib/AST/ExistentialGeneralization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ class Generalizer : public CanTypeVisitor<Generalizer, Type> {
175175
INVALID_TO_GENERALIZE(SILBox)
176176
INVALID_TO_GENERALIZE(SILFunction)
177177
INVALID_TO_GENERALIZE(SILToken)
178+
INVALID_TO_GENERALIZE(SILMoveOnly)
178179
#undef INVALID_TO_GENERALIZE
179180

180181
/// Generalize the generic arguments of the given generic type.s

0 commit comments

Comments
 (0)