Skip to content

Commit 2a96825

Browse files
authored
Merge pull request #82854 from slavapestov/cache-invertible-conformances
AST: Cache isNoncopyable() and isEscapable() bits inside TypeBase
2 parents b37d0f6 + b91ed32 commit 2a96825

File tree

2 files changed

+56
-55
lines changed

2 files changed

+56
-55
lines changed

include/swift/AST/Types.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -413,15 +413,19 @@ class alignas(1 << TypeAlignInBits) TypeBase
413413
// clang-format off
414414
union { uint64_t OpaqueBits;
415415

416-
SWIFT_INLINE_BITFIELD_BASE(TypeBase, bitmax(NumTypeKindBits,8) +
417-
RecursiveTypeProperties::BitWidth + 1,
416+
SWIFT_INLINE_BITFIELD_BASE(TypeBase, NumTypeKindBits +
417+
RecursiveTypeProperties::BitWidth + 1 + 3,
418418
/// Kind - The discriminator that indicates what subclass of type this is.
419-
Kind : bitmax(NumTypeKindBits,8),
419+
Kind : NumTypeKindBits,
420420

421421
Properties : RecursiveTypeProperties::BitWidth,
422422

423423
/// Whether this type is canonical or not.
424-
IsCanonical : 1
424+
IsCanonical : 1,
425+
426+
ComputedInvertibleConformances : 1,
427+
IsCopyable : 1,
428+
IsEscapable : 1
425429
);
426430

427431
SWIFT_INLINE_BITFIELD(ErrorType, TypeBase, 1,
@@ -441,8 +445,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
441445
HasClangTypeInfo : 1,
442446
HasThrownError : 1,
443447
HasLifetimeDependencies : 1,
444-
: NumPadBits,
445-
NumParams : 16
448+
NumParams : 15
446449
);
447450

448451
SWIFT_INLINE_BITFIELD_FULL(ArchetypeType, TypeBase, 1+1+16,
@@ -455,9 +458,8 @@ class alignas(1 << TypeAlignInBits) TypeBase
455458
SWIFT_INLINE_BITFIELD_FULL(TypeVariableType, TypeBase, 7+28,
456459
/// Type variable options.
457460
Options : 7,
458-
: NumPadBits,
459461
/// The unique number assigned to this type variable.
460-
ID : 28
462+
ID : 27
461463
);
462464

463465
SWIFT_INLINE_BITFIELD_FULL(ErrorUnionType, TypeBase, 32,
@@ -560,6 +562,11 @@ class alignas(1 << TypeAlignInBits) TypeBase
560562
Bits.TypeBase.IsCanonical = true;
561563
Context = CanTypeCtx;
562564
}
565+
566+
Bits.TypeBase.ComputedInvertibleConformances = false;
567+
Bits.TypeBase.IsCopyable = false;
568+
Bits.TypeBase.IsEscapable = false;
569+
563570
setRecursiveProperties(properties);
564571
}
565572

@@ -591,6 +598,8 @@ class alignas(1 << TypeAlignInBits) TypeBase
591598
private:
592599
CanType computeCanonicalType();
593600

601+
void computeInvertibleConformances();
602+
594603
public:
595604
/// getCanonicalType - Return the canonical version of this type, which has
596605
/// sugar from all levels stripped off.

lib/AST/ConformanceLookup.cpp

Lines changed: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -897,68 +897,60 @@ bool TypeBase::isSendableType() {
897897
/// Copyable and Escapable checking utilities
898898
///
899899

900-
/// Preprocesses a type before querying whether it conforms to an invertible.
901-
static CanType preprocessTypeForInvertibleQuery(Type orig) {
902-
Type type = orig;
903-
904-
// Strip off any StorageType wrapper.
905-
type = type->getReferenceStorageReferent();
906-
907-
// Pack expansions such as `repeat T` themselves do not have conformances,
908-
// so check its pattern type for conformance.
909-
if (auto *pet = type->getAs<PackExpansionType>()) {
910-
type = pet->getPatternType()->getCanonicalType();
911-
}
912-
913-
// Strip @lvalue and canonicalize.
914-
auto canType = type->getRValueType()->getCanonicalType();
915-
return canType;
916-
}
917-
918900
static bool conformsToInvertible(CanType type, InvertibleProtocolKind ip) {
919-
auto &ctx = type->getASTContext();
920-
921-
auto *proto = ctx.getProtocol(getKnownProtocolKind(ip));
922-
assert(proto && "missing Copyable/Escapable from stdlib!");
901+
// FIXME: Remove these.
902+
if (isa<SILPackType>(type))
903+
return true;
923904

924-
// Must not have a type parameter!
925-
assert(!type->hasTypeParameter() && "caller forgot to mapTypeIntoContext!");
905+
if (isa<SILTokenType>(type))
906+
return true;
926907

927-
assert(!type->hasUnboundGenericType() && "a UGT has no conformances!");
908+
auto *proto = type->getASTContext().getProtocol(getKnownProtocolKind(ip));
909+
ASSERT(proto);
928910

929-
assert(!type->is<PackExpansionType>());
911+
return (bool) checkConformance(type, proto, /*allowMissing=*/false);
912+
}
930913

931-
// FIXME: lldb misbehaves by getting here with a SILPackType.
932-
// just pretend it it conforms.
933-
if (type->is<SILPackType>())
934-
return true;
914+
void TypeBase::computeInvertibleConformances() {
915+
Bits.TypeBase.ComputedInvertibleConformances = true;
935916

936-
if (type->is<SILTokenType>()) {
937-
return true;
938-
}
939-
940-
// The SIL types in the AST do not have real conformances, and should have
941-
// been handled in SILType instead.
942-
assert(!(type->is<SILBoxType,
943-
SILMoveOnlyWrappedType,
944-
SILPackType,
945-
SILTokenType>()));
917+
Type type(this);
946918

947-
const bool conforms =
948-
(bool) checkConformance(type, proto, /*allowMissing=*/false);
919+
// FIXME: Remove all of the below. Callers should be changed to perform any
920+
// necessary unwrapping themselves.
949921

950-
return conforms;
922+
// Pack expansions such as `repeat T` themselves do not have conformances,
923+
// so check its pattern type for conformance.
924+
if (auto *pet = type->getAs<PackExpansionType>())
925+
type = pet->getPatternType();
926+
927+
auto canType = type->getReferenceStorageReferent()
928+
->getWithoutSpecifierType()
929+
->getCanonicalType();
930+
931+
assert(!canType->hasTypeParameter());
932+
assert(!canType->hasUnboundGenericType());
933+
assert(!isa<SILBoxType>(canType));
934+
assert(!isa<SILMoveOnlyWrappedType>(canType));
935+
936+
Bits.TypeBase.IsCopyable = conformsToInvertible(
937+
canType, InvertibleProtocolKind::Copyable);
938+
Bits.TypeBase.IsEscapable = conformsToInvertible(
939+
canType, InvertibleProtocolKind::Escapable);
951940
}
952941

953942
/// \returns true iff this type lacks conformance to Copyable.
954943
bool TypeBase::isNoncopyable() {
955-
auto canType = preprocessTypeForInvertibleQuery(this);
956-
return !conformsToInvertible(canType, InvertibleProtocolKind::Copyable);
944+
if (!Bits.TypeBase.ComputedInvertibleConformances)
945+
computeInvertibleConformances();
946+
return !Bits.TypeBase.IsCopyable;
957947
}
958948

949+
/// \returns true iff this type conforms to Escaping.
959950
bool TypeBase::isEscapable() {
960-
auto canType = preprocessTypeForInvertibleQuery(this);
961-
return conformsToInvertible(canType, InvertibleProtocolKind::Escapable);
951+
if (!Bits.TypeBase.ComputedInvertibleConformances)
952+
computeInvertibleConformances();
953+
return Bits.TypeBase.IsEscapable;
962954
}
963955

964956
bool TypeBase::isEscapable(GenericSignature sig) {

0 commit comments

Comments
 (0)