@@ -258,6 +258,8 @@ namespace {
258258 }
259259
260260 RetTy handleReference (CanType type) {
261+ // TODO: Consider final classes with no user deinit to be
262+ // HasOnlyDefaultDeinit.
261263 return handleReference (type, SILTypeProperties::forReference ());
262264 }
263265
@@ -754,6 +756,7 @@ namespace {
754756 RetTy
755757 visitArchetypeType (CanArchetypeType type, AbstractionPattern origType,
756758 IsTypeExpansionSensitive_t isSensitive) {
759+ // TODO: Add a HasOnlyDefaultDeinit "layout protocol".
757760 auto LayoutInfo = type->getLayoutConstraint ();
758761 if (LayoutInfo) {
759762 if (LayoutInfo->isFixedSizeTrivial ()) {
@@ -2625,6 +2628,9 @@ namespace {
26252628 if (origType.isNoncopyable (structType)) {
26262629 properties.setNonTrivial ();
26272630 properties.setLexical (IsLexical);
2631+ if (D->getValueTypeDestructor ()) {
2632+ properties.setCustomDeinit (MayHaveCustomDeinit);
2633+ }
26282634 if (properties.isAddressOnly ())
26292635 return handleMoveOnlyAddressOnly (structType, properties);
26302636 return new (TC) MoveOnlyLoadableStructTypeLowering (
@@ -2635,6 +2641,13 @@ namespace {
26352641 if (!origType.isEscapable (structType)) {
26362642 properties.setNonTrivial ();
26372643 }
2644+ // Merge the CustomDeinit properties of the type parameters.
2645+ if (hasConditionalDefaultDeinit (structType, D)) {
2646+ auto genericProps = classifyTypeParameters (structType, TC, Expansion);
2647+ if (genericProps.mayHaveCustomDeinit () == HasOnlyDefaultDeinit) {
2648+ properties.setCustomDeinit (HasOnlyDefaultDeinit);
2649+ }
2650+ }
26382651 return handleAggregateByProperties<LoadableStructTypeLowering>(structType,
26392652 properties);
26402653 }
@@ -2728,6 +2741,9 @@ namespace {
27282741 if (origType.isNoncopyable (enumType)) {
27292742 properties.setNonTrivial ();
27302743 properties.setLexical (IsLexical);
2744+ if (D->getValueTypeDestructor ()) {
2745+ properties.setCustomDeinit (MayHaveCustomDeinit);
2746+ }
27312747 if (properties.isAddressOnly ())
27322748 return handleMoveOnlyAddressOnly (enumType, properties);
27332749 return new (TC)
@@ -2769,6 +2785,43 @@ namespace {
27692785 }
27702786 return new (TC) LoadableLoweringClass (type, props, Expansion);
27712787 }
2788+
2789+ private:
2790+ bool hasConditionalDefaultDeinit (CanType type, StructDecl *structDecl) {
2791+ if (type->isArray () || type->is_ArrayBuffer ()
2792+ || type->is_ContiguousArrayBuffer () || type->isDictionary ()) {
2793+ return true ;
2794+ }
2795+ if (ProtocolDecl *DestructorSafeContainer =
2796+ TC.Context .getProtocol (KnownProtocolKind::DestructorSafeContainer)) {
2797+ return bool (lookupConformance (type, DestructorSafeContainer));
2798+ }
2799+ return false ;
2800+ }
2801+
2802+ // Merge the type properties of all the generic parameters. Useful for
2803+ // summarizing the properties of indirectly stored types, such as Array
2804+ // elements. Only non-layout flags, such as CustomDeinitFlag are relevant in
2805+ // the result.
2806+ //
2807+ // This may return an incomplete 'isInfinite' lowering on self-recursion. In
2808+ // this case, the non-layout flags have their default values.
2809+ SILTypeProperties classifyTypeParameters (CanType type, TypeConverter &tc,
2810+ TypeExpansionContext expansion) {
2811+ TypeConverter::NonLayoutTypeRAII nonLayoutLowering (tc);
2812+ SILTypeProperties props;
2813+ if (auto bgt = dyn_cast<BoundGenericType>(type)) {
2814+ for (auto paramType : bgt->getGenericArgs ()) {
2815+ // Use an opaque abstraction pattern for the element type because
2816+ // abstraction does not apply to the generic parameter itself.
2817+ AbstractionPattern origElementType = AbstractionPattern::getOpaque ();
2818+ auto &lowering = tc.getTypeLowering (origElementType, paramType,
2819+ expansion);
2820+ props.addSubobject (lowering.getRecursiveProperties ());
2821+ }
2822+ }
2823+ return props;
2824+ }
27722825 };
27732826} // end anonymous namespace
27742827
@@ -2823,7 +2876,22 @@ void TypeConverter::removeNullEntry(const TypeKey &k) {
28232876void TypeConverter::insert (const TypeKey &k, const TypeLowering *tl) {
28242877 if (!k.isCacheable ()) return ;
28252878
2826- LoweredTypes[k.getCachingKey ()] = tl;
2879+ if (isCacheableLowering (tl)) {
2880+ LoweredTypes[k.getCachingKey ()] = tl;
2881+ if (k == k.getKeyForMinimalExpansion ())
2882+ return ;
2883+ }
2884+ #ifndef NDEBUG
2885+ removeNullEntry (k.getKeyForMinimalExpansion ());
2886+ #endif
2887+ }
2888+
2889+ // Infinite lowerings are incomplete. They are only cached when they
2890+ // correspond to a self-recursive layout, which can never have a complete
2891+ // lowering. Avoid caching an infinite non-layout lowering so that the
2892+ // complete layout can be lowered later.
2893+ bool TypeConverter::isCacheableLowering (const TypeLowering *tl) {
2894+ return !tl || !isLoweringNonLayoutType || !tl->isInfinite ();
28272895}
28282896
28292897// / Lower each of the elements of the substituted type according to
@@ -2981,9 +3049,6 @@ TypeConverter::getTypeLowering(AbstractionPattern origType,
29813049 insert (key.getKeyForMinimalExpansion (), lowering);
29823050 } else {
29833051 insert (key, lowering);
2984- #ifndef NDEBUG
2985- removeNullEntry (key.getKeyForMinimalExpansion ());
2986- #endif
29873052 }
29883053
29893054#ifndef NDEBUG
@@ -3168,7 +3233,7 @@ void TypeConverter::verifyLowering(const TypeLowering &lowering,
31683233 AbstractionPattern origType,
31693234 CanType substType,
31703235 TypeExpansionContext forExpansion) {
3171- if (TypeLoweringDisableVerification) {
3236+ if (TypeLoweringDisableVerification || ! isCacheableLowering (&lowering) ) {
31723237 return ;
31733238 }
31743239 verifyLexicalLowering (lowering, origType, substType, forExpansion);
@@ -3815,9 +3880,6 @@ const TypeLowering &TypeConverter::getTypeLoweringForLoweredType(
38153880 insert (key.getKeyForMinimalExpansion (), lowering);
38163881 else {
38173882 insert (key, lowering);
3818- #ifndef NDEBUG
3819- removeNullEntry (key.getKeyForMinimalExpansion ());
3820- #endif
38213883 }
38223884
38233885 return *lowering;
@@ -5499,6 +5561,10 @@ void TypeLowering::print(llvm::raw_ostream &os) const {
54995561 << " .\n "
55005562 << " isLexical: " << BOOL (Properties.isLexical ()) << " .\n "
55015563 << " isOrContainsPack: " << BOOL (Properties.isOrContainsPack ()) << " .\n "
5564+ << " isAddressableForDependencies: "
5565+ << BOOL (Properties.isAddressableForDependencies ()) << " .\n "
5566+ << " hasOnlyDefaultDeinit: "
5567+ << BOOL (Properties.mayHaveCustomDeinit () == HasOnlyDefaultDeinit) << " .\n "
55025568 << " \n " ;
55035569}
55045570
0 commit comments