Skip to content

Commit 92a5dba

Browse files
committed
[move-only] Add support to SILType for unwrapping move only types and performing basic queries by looking through the move only type wrapper.
This is done by introducing the API SILType::getSemanticASTType(). This can be used in contexts for type queries like getStructOrBoundGenericStruct() where one wants to look through the move only wrapper to the underlying type.
1 parent 02759d1 commit 92a5dba

File tree

4 files changed

+85
-29
lines changed

4 files changed

+85
-29
lines changed

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

lib/AST/Type.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,19 +322,25 @@ ExistentialLayout TypeBase::getExistentialLayout() {
322322
}
323323

324324
ExistentialLayout CanType::getExistentialLayout() {
325-
if (auto existential = dyn_cast<ExistentialType>(*this))
326-
return existential.getConstraintType().getExistentialLayout();
325+
CanType ty = *this;
326+
327+
// Always remove one layer of move only ness.
328+
if (auto mv = dyn_cast<SILMoveOnlyType>(ty))
329+
ty = mv->getInnerType();
330+
331+
if (auto existential = dyn_cast<ExistentialType>(ty))
332+
return existential->getConstraintType()->getExistentialLayout();
327333

328-
if (auto metatype = dyn_cast<ExistentialMetatypeType>(*this))
329-
return metatype.getInstanceType().getExistentialLayout();
334+
if (auto metatype = dyn_cast<ExistentialMetatypeType>(ty))
335+
return metatype->getInstanceType()->getExistentialLayout();
330336

331-
if (auto proto = dyn_cast<ProtocolType>(*this))
337+
if (auto proto = dyn_cast<ProtocolType>(ty))
332338
return ExistentialLayout(proto);
333339

334-
if (auto param = dyn_cast<ParameterizedProtocolType>(*this))
340+
if (auto param = dyn_cast<ParameterizedProtocolType>(ty))
335341
return ExistentialLayout(param);
336342

337-
auto comp = cast<ProtocolCompositionType>(*this);
343+
auto comp = cast<ProtocolCompositionType>(ty);
338344
return ExistentialLayout(comp);
339345
}
340346

lib/SIL/IR/SILPrinter.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,12 @@ static void printSILTypeColorAndSigil(raw_ostream &OS, SILType t) {
461461

462462
void SILType::print(raw_ostream &OS, const PrintOptions &PO) const {
463463
printSILTypeColorAndSigil(OS, *this);
464-
464+
465465
// Print other types as their Swift representation.
466-
getASTType().print(OS, PO);
466+
//
467+
// NOTE: We always print the Raw AST type so we don't look through
468+
// move-onlyness.
469+
getRawASTType().print(OS, PO);
467470
}
468471

469472
void SILType::dump() const {
@@ -647,7 +650,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
647650

648651
SILPrinter &operator<<(SILType t) {
649652
printSILTypeColorAndSigil(PrintState.OS, t);
650-
t.getASTType().print(PrintState.OS, PrintState.ASTOptions);
653+
t.getRawASTType().print(PrintState.OS, PrintState.ASTOptions);
651654
return *this;
652655
}
653656

lib/SIL/IR/SILType.cpp

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ SILType SILType::getOptionalType(SILType type) {
9191
auto &ctx = type.getASTContext();
9292
auto optType = BoundGenericEnumType::get(ctx.getOptionalDecl(), Type(),
9393
{ type.getASTType() });
94-
return getPrimitiveType(CanType(optType), type.getCategory());
94+
return getPrimitiveType(CanType(optType), type.getCategory())
95+
.copyMoveOnly(type);
9596
}
9697

9798
SILType SILType::getEmptyTupleType(const ASTContext &C) {
@@ -164,7 +165,7 @@ bool SILType::isNoReturnFunction(SILModule &M,
164165

165166
std::string SILType::getMangledName() const {
166167
Mangle::ASTMangler mangler;
167-
return mangler.mangleTypeWithoutPrefix(getASTType());
168+
return mangler.mangleTypeWithoutPrefix(getRawASTType());
168169
}
169170

170171
std::string SILType::getAsString() const {
@@ -287,11 +288,17 @@ SILType SILType::getFieldType(VarDecl *field, TypeConverter &TC,
287288
substFieldTy = origFieldTy.getType();
288289
} else {
289290
substFieldTy =
290-
getASTType()->getTypeOfMember(&TC.M, field)->getCanonicalType();
291+
getASTType()->getTypeOfMember(&TC.M, field)->getCanonicalType();
291292
}
292293

293294
auto loweredTy =
294295
TC.getLoweredRValueType(context, origFieldTy, substFieldTy);
296+
297+
// If this type is not a class type, then we propagate "move only"-ness to the
298+
// field. Example:
299+
if (!getClassOrBoundGenericClass() && isMoveOnly())
300+
loweredTy = SILMoveOnlyType::get(loweredTy);
301+
295302
if (isAddress() || getClassOrBoundGenericClass() != nullptr) {
296303
return SILType::getPrimitiveAddressType(loweredTy);
297304
} else {
@@ -311,7 +318,7 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, TypeConverter &TC,
311318

312319
if (auto objectType = getASTType().getOptionalObjectType()) {
313320
assert(elt == TC.Context.getOptionalSomeDecl());
314-
return SILType(objectType, getCategory());
321+
return SILType(objectType, getCategory()).copyMoveOnly(*this);
315322
}
316323

317324
// If the case is indirect, then the payload is boxed.
@@ -321,13 +328,12 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, TypeConverter &TC,
321328
getCategory());
322329
}
323330

324-
auto substEltTy =
325-
getASTType()->getTypeOfMember(&TC.M, elt,
326-
elt->getArgumentInterfaceType());
331+
auto substEltTy = getASTType()->getTypeOfMember(
332+
&TC.M, elt, elt->getArgumentInterfaceType());
327333
auto loweredTy = TC.getLoweredRValueType(
328334
context, TC.getAbstractionPattern(elt), substEltTy);
329335

330-
return SILType(loweredTy, getCategory());
336+
return SILType(loweredTy, getCategory()).copyMoveOnly(*this);
331337
}
332338

333339
SILType SILType::getEnumElementType(EnumElementDecl *elt, SILModule &M,
@@ -432,15 +438,15 @@ bool SILType::aggregateHasUnreferenceableStorage() const {
432438

433439
SILType SILType::getOptionalObjectType() const {
434440
if (auto objectTy = getASTType().getOptionalObjectType()) {
435-
return SILType(objectTy, getCategory());
441+
return SILType(objectTy, getCategory()).copyMoveOnly(*this);
436442
}
437443

438444
return SILType();
439445
}
440446

441447
SILType SILType::unwrapOptionalType() const {
442-
if (auto objectTy = getOptionalObjectType()) {
443-
return objectTy;
448+
if (auto objectTy = withoutMoveOnly().getOptionalObjectType()) {
449+
return objectTy.copyMoveOnly(*this);
444450
}
445451

446452
return *this;

0 commit comments

Comments
 (0)