Skip to content

Commit 9ff09b0

Browse files
committed
[5.3] IRGen: Only replace opaque result types of function result types when
performing a dynamic replacement Explanation: When a opaque result type (``some P``) appeared as a parameter of a dynamic replacement function we used to try to emit this opaque result type as a replacement. This made no sense since you can only replace result types that are opaque result types not parameters that happen to have the type of an opaque result type. And doing so would lead to a compiler crash. Scope: Any use of a dynamic replacement with an opaque result type parameter would crash the compiler. Origination: This bug was introduced together with the dynamic replacement feature. Risk: Medium. Affects only dynamic replacements with opaque result types. Reviewed by: Joe Groff Testing: Unit test added. rdar://61936622
1 parent 83697ed commit 9ff09b0

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,17 +1527,23 @@ void IRGenerator::emitDynamicReplacements() {
15271527
llvm::SmallSet<OpaqueTypeArchetypeType *, 8> newUniqueOpaqueTypes;
15281528
llvm::SmallSet<OpaqueTypeArchetypeType *, 8> origUniqueOpaqueTypes;
15291529
for (auto *newFunc : DynamicReplacements) {
1530-
if (!newFunc->getLoweredFunctionType()->hasOpaqueArchetype())
1530+
auto newResultTy = newFunc->getLoweredFunctionType()
1531+
->getAllResultsInterfaceType()
1532+
.getASTType();
1533+
if (!newResultTy->hasOpaqueArchetype())
15311534
continue;
1532-
CanType(newFunc->getLoweredFunctionType()).visit([&](CanType ty) {
1535+
newResultTy.visit([&](CanType ty) {
15331536
if (auto opaque = ty->getAs<OpaqueTypeArchetypeType>())
15341537
if (newUniqueOpaqueTypes.insert(opaque).second)
15351538
newFuncTypes.push_back(opaque);
15361539
});
15371540
auto *origFunc = newFunc->getDynamicallyReplacedFunction();
15381541
assert(origFunc);
1539-
assert(origFunc->getLoweredFunctionType()->hasOpaqueArchetype());
1540-
CanType(origFunc->getLoweredFunctionType()).visit([&](CanType ty) {
1542+
auto origResultTy = origFunc->getLoweredFunctionType()
1543+
->getAllResultsInterfaceType()
1544+
.getASTType();
1545+
assert(origResultTy->hasOpaqueArchetype());
1546+
origResultTy.visit([&](CanType ty) {
15411547
if (auto opaque = ty->getAs<OpaqueTypeArchetypeType>())
15421548
if (origUniqueOpaqueTypes.insert(opaque).second)
15431549
origFuncTypes.push_back(opaque);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Base {}
2+
class Sub: Base {}
3+
4+
protocol Proto {
5+
associatedtype Assoc
6+
func make() -> Assoc
7+
}
8+
9+
private struct Container : Proto {
10+
func make() -> some Base {
11+
return Sub()
12+
}
13+
14+
func update(arg: Assoc) {}
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -disable-availability-checking -enable-implicit-dynamic -enable-private-imports %S/Inputs/opaque_return_type_parameter.swift -module-name Repo -emit-module -emit-module-path %t/Repo.swiftmodule
3+
// RUN: %target-swift-frontend -disable-availability-checking -I %t -module-name A -swift-version 5 -primary-file %s -emit-ir | %FileCheck %s
4+
// RUN: %target-swift-frontend -disable-availability-checking -I %t -module-name A -swift-version 5 -primary-file %s -c -o %t/tmp.o
5+
@_private(sourceFile: "opaque_return_type_parameter.swift") import Repo
6+
7+
// Make sure we are not emitting a replacement for the opaque result type used as parameter (Assoc).
8+
9+
// CHECK-NOT: @"\01l_unnamed_dynamic_replacements"{{.*}}(%swift.type_descriptor* ()*
10+
11+
extension Container {
12+
@_dynamicReplacement(for: update(arg:)) private func __update(arg: Assoc) {}
13+
}

0 commit comments

Comments
 (0)