Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions lib/IRGen/GenReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,8 @@ getRuntimeVersionThatSupportsDemanglingType(CanType type) {
// where completing the metadata during demangling might cause cyclic
// dependencies.
static std::pair<llvm::Constant *, unsigned>
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(
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
21 changes: 21 additions & 0 deletions test/IRGen/Inputs/associated_type_by_mangled_name.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
public protocol Proto {
associatedtype T: Proto

var value: T {get}
}

public func makeThing<P: Proto>(_ t: P) -> some Proto {
return ProtoImpl(t.value)
}

public struct ProtoImpl<V>: Proto {
public let genValue: V

public init(_ genValue: V) {
self.genValue = genValue
}

public var value: some Proto {
return self
}
}
55 changes: 55 additions & 0 deletions test/IRGen/nonisolated_nonsending_closure.swift
Original file line number Diff line number Diff line change
@@ -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<T: P>: Proto {
typealias Closure = nonisolated(nonsending) (Int) async throws -> Void

let x: T

public var value: some Proto {
return ProtoImpl<Closure> { _ in }
}
}

print(makeThing(MyStruct(x: PImpl())))