From 495a86dd0e188e5bbabf481eb61deb3a919bd492 Mon Sep 17 00:00:00 2001 From: Dario Rexin Date: Tue, 9 Sep 2025 14:41:40 -0700 Subject: [PATCH] [IRGen] Only emit AssociatedTypeInProtocolContextByte for default associated type witnesses rdar://159310652 This was causing the runtime to try to get types by mangled names for types of which the mangling was not supported by the target runtime, which led to runtime crashes. --- lib/IRGen/GenReflection.cpp | 17 +++--- .../associated_type_by_mangled_name.swift | 21 +++++++ .../nonisolated_nonsending_closure.swift | 55 +++++++++++++++++++ 3 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 test/IRGen/Inputs/associated_type_by_mangled_name.swift create mode 100644 test/IRGen/nonisolated_nonsending_closure.swift diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp index 7fcf19be024a7..13ee6e213d347 100644 --- a/lib/IRGen/GenReflection.cpp +++ b/lib/IRGen/GenReflection.cpp @@ -315,9 +315,8 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) { // where completing the metadata during demangling might cause cyclic // dependencies. static std::pair -getTypeRefByFunction(IRGenModule &IGM, - CanGenericSignature sig, - CanType t) { +getTypeRefByFunction(IRGenModule &IGM, CanGenericSignature sig, CanType t, + MangledTypeRefRole role) { IRGenMangler mangler(IGM.Context); std::string symbolName = mangler.mangleSymbolNameForMangledMetadataAccessorString( @@ -433,7 +432,11 @@ getTypeRefByFunction(IRGenModule &IGM, // Form the mangled name with its relative reference. auto S = B.beginStruct(); S.setPacked(true); - S.add(llvm::ConstantInt::get(IGM.Int8Ty, 255)); + if (role == MangledTypeRefRole::DefaultAssociatedTypeWitness) { + S.add(llvm::ConstantInt::get( + IGM.Int8Ty, + ProtocolRequirementFlags::AssociatedTypeInProtocolContextByte)); + } S.add(llvm::ConstantInt::get(IGM.Int8Ty, 9)); S.addCompactFunctionReference(accessor); @@ -513,7 +516,7 @@ getTypeRefImpl(IRGenModule &IGM, // the field will be artificially hidden to reflectors. if (isAlwaysNoncopyable) { IGM.IRGen.noteUseOfTypeMetadata(type); - return getTypeRefByFunction(IGM, sig, type); + return getTypeRefByFunction(IGM, sig, type, role); } } LLVM_FALLTHROUGH; @@ -524,12 +527,12 @@ getTypeRefImpl(IRGenModule &IGM, // ensuring that we can always reconstruct type metadata from a mangled name // in-process. IGM.IRGen.noteUseOfTypeMetadata(type); - + // If the minimum deployment target's runtime demangler wouldn't understand // this mangled name, then fall back to generating a "mangled name" with a // symbolic reference with a callback function. if (mangledNameIsUnknownToDeployTarget(IGM, type)) { - return getTypeRefByFunction(IGM, sig, type); + return getTypeRefByFunction(IGM, sig, type, role); } break; diff --git a/test/IRGen/Inputs/associated_type_by_mangled_name.swift b/test/IRGen/Inputs/associated_type_by_mangled_name.swift new file mode 100644 index 0000000000000..3e8ee23c00200 --- /dev/null +++ b/test/IRGen/Inputs/associated_type_by_mangled_name.swift @@ -0,0 +1,21 @@ +public protocol Proto { + associatedtype T: Proto + + var value: T {get} +} + +public func makeThing(_ t: P) -> some Proto { + return ProtoImpl(t.value) +} + +public struct ProtoImpl: Proto { + public let genValue: V + + public init(_ genValue: V) { + self.genValue = genValue + } + + public var value: some Proto { + return self + } +} diff --git a/test/IRGen/nonisolated_nonsending_closure.swift b/test/IRGen/nonisolated_nonsending_closure.swift new file mode 100644 index 0000000000000..32edb5efbb14d --- /dev/null +++ b/test/IRGen/nonisolated_nonsending_closure.swift @@ -0,0 +1,55 @@ +// RUN: %empty-directory(%t) + +// RUN: %target-build-swift-dylib(%t/%target-library-name(associated_type_by_mangled_name)) -target %target-cpu-apple-macosx15.0 -enable-library-evolution %S/Inputs/associated_type_by_mangled_name.swift -emit-module -emit-module-path %t/associated_type_by_mangled_name.swiftmodule -module-name associated_type_by_mangled_name +// RUN: %target-codesign %t/%target-library-name(associated_type_by_mangled_name) + +// RUN: %target-swift-frontend -target %target-cpu-apple-macosx15.0 -I %t %s -emit-ir -o - | %FileCheck %s +// RUN: %target-swift-frontend -target %target-cpu-apple-macosx26.0 -I %t %s -emit-ir -o - | %FileCheck %s -check-prefix CHECK-SUPPORTED + +// RUN: %target-build-swift -target %target-cpu-apple-macosx15.0 %s -lassociated_type_by_mangled_name -I %t -L %t -o %t/main15 %target-rpath(%t) +// RUN: %target-codesign %t/main15 + +// RUN: %target-run %t/main15 %t/%target-library-name(associated_type_by_mangled_name) + +// RUN: %target-build-swift -target %target-cpu-apple-macosx26.0 %s -lassociated_type_by_mangled_name -I %t -L %t -o %t/main26 %target-rpath(%t) +// RUN: %target-codesign %t/main26 + +// RUN: %target-run %t/main26 %t/%target-library-name(associated_type_by_mangled_name) + +// REQUIRES: executable_test +// REQUIRES: OS=macosx +// UNSUPPORTED: back_deployment_runtime || use_os_stdlib + +import associated_type_by_mangled_name + +protocol P: Sendable { + associatedtype T: Proto + func foo() -> T +} + +struct PImpl: P { + func foo() -> some Proto { + return ProtoImpl(2) + } +} + +// CHECK: @"get_type_metadata 30nonisolated_nonsending_closure1PRzl31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcG.3" = linkonce_odr hidden constant <{ i8, i32, i8 }> <{ i8 9, i32 trunc (i64 sub (i64 ptrtoint (ptr @"get_type_metadata 30nonisolated_nonsending_closure1PRzl31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcG" to i64), i64 ptrtoint (ptr getelementptr inbounds (<{ i8, i32, i8 }>, ptr @"get_type_metadata 30nonisolated_nonsending_closure1PRzl31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcG.3", i32 0, i32 1) to i64)) to i32), i8 0 }> +// CHECK: define linkonce_odr hidden ptr @"$s31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcGACyxGAA0F0AAWl"() #1 { +// CHECK: call swiftcc %swift.metadata_response @"$s31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcGMa"(i64 255) +// CHECK: } + +// CHECK-SUPPORTED-NOT: @"get_type_metadata 30nonisolated_nonsending_closure1PRzl31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcG.3" +// CHECK-SUPPORTED: define linkonce_odr hidden ptr @"$s31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcGACyxGAA0F0AAWl"() #1 { +// CHECK-SUPPORTED: call ptr @__swift_instantiateConcreteTypeFromMangledNameAbstract(ptr @"$s31associated_type_by_mangled_name9ProtoImplVyySiYaKYCcGMD") +// CHECK-SUPPORTED: } +struct MyStruct: Proto { + typealias Closure = nonisolated(nonsending) (Int) async throws -> Void + + let x: T + + public var value: some Proto { + return ProtoImpl { _ in } + } +} + +print(makeThing(MyStruct(x: PImpl())))