diff --git a/lib/IRGen/TypeLayout.cpp b/lib/IRGen/TypeLayout.cpp index f7660b8833fa5..b5201c123d5f3 100644 --- a/lib/IRGen/TypeLayout.cpp +++ b/lib/IRGen/TypeLayout.cpp @@ -1295,14 +1295,14 @@ bool ScalarTypeLayoutEntry::refCountString(IRGenModule &IGM, B.addRefCount(LayoutStringBuilder::RefCountingKind::Block, size); break; case ScalarKind::ObjCReference: { - auto *classTI = dyn_cast(&typeInfo); - assert(classTI); - if (!classTI->getClass()->hasClangNode()) { - B.addRefCount(LayoutStringBuilder::RefCountingKind::NativeSwiftObjC, - size); - } else { - B.addRefCount(LayoutStringBuilder::RefCountingKind::ObjC, size); + if (auto *classDecl = representative.getClassOrBoundGenericClass()) { + if (!classDecl->hasClangNode()) { + B.addRefCount(LayoutStringBuilder::RefCountingKind::NativeSwiftObjC, + size); + break; + } } + B.addRefCount(LayoutStringBuilder::RefCountingKind::ObjC, size); break; } case ScalarKind::ThickFunc: diff --git a/test/Interpreter/layout_string_witnesses_objc.swift b/test/Interpreter/layout_string_witnesses_objc.swift index 04870c97bd28a..5f49b7169e40a 100644 --- a/test/Interpreter/layout_string_witnesses_objc.swift +++ b/test/Interpreter/layout_string_witnesses_objc.swift @@ -190,3 +190,103 @@ func testMultiPayloadBlock() { } testMultiPayloadBlock() + +class GenericOuterClassNSObject { + enum InnerEnum { + case x(T.Type) + case y(T) + } +} + +func testNestedGenericEnumNSObject() { + let ptr = UnsafeMutablePointer.InnerEnum>.allocate(capacity: 1) + + // initWithCopy + do { + let x = GenericOuterClassNSObject.InnerEnum.y(ObjCPrintOnDealloc()) + testInit(ptr, to: x) + } + + // assignWithTake + do { + let y = GenericOuterClassNSObject.InnerEnum.y(ObjCPrintOnDealloc()) + + // CHECK-NEXT: Before deinit + print("Before deinit") + + // CHECK-NEXT: ObjCPrintOnDealloc deinitialized! + testAssign(ptr, from: y) + } + + // assignWithCopy + do { + var z = GenericOuterClassNSObject.InnerEnum.y(ObjCPrintOnDealloc()) + + // CHECK-NEXT: Before deinit + print("Before deinit") + + // CHECK-NEXT: ObjCPrintOnDealloc deinitialized! + testAssignCopy(ptr, from: &z) + } + + // CHECK-NEXT: Before deinit + print("Before deinit") + + // destroy + // CHECK-NEXT: ObjCPrintOnDealloc deinitialized! + testDestroy(ptr) + + ptr.deallocate() +} + +testNestedGenericEnumNSObject() + +class GenericOuterClassSwiftObjC { + enum InnerEnum { + case x(T.Type) + case y(T) + } +} + +func testNestedGenericEnumSwiftObjC() { + let ptr = UnsafeMutablePointer.InnerEnum>.allocate(capacity: 1) + + // initWithCopy + do { + let x = GenericOuterClassSwiftObjC.InnerEnum.y(SwiftObjC()) + testInit(ptr, to: x) + } + + // assignWithTake + do { + let y = GenericOuterClassSwiftObjC.InnerEnum.y(SwiftObjC()) + + // CHECK-NEXT: Before deinit + print("Before deinit") + + // CHECK-NEXT: SwiftObjC deinitialized! + testAssign(ptr, from: y) + } + + // assignWithCopy + do { + var z = GenericOuterClassSwiftObjC.InnerEnum.y(SwiftObjC()) + + // CHECK-NEXT: Before deinit + print("Before deinit") + + // CHECK-NEXT: SwiftObjC deinitialized! + testAssignCopy(ptr, from: &z) + } + + // CHECK-NEXT: Before deinit + print("Before deinit") + + // destroy + // CHECK-NEXT: SwiftObjC deinitialized! + testDestroy(ptr) + + ptr.deallocate() +} + +testNestedGenericEnumSwiftObjC()