Skip to content

Commit e29469b

Browse files
committed
[Opaque result types] Fix mangling issues with opaque result types.
Fix a trio of issues involving mangling for opaque result types: * Symbolic references to opaque type descriptors are not substitutions * Mangle protocol extension contexts correctly * Mangle generic arguments for opaque result types of generic functions The (de-)serialization of generic parameter lists for opaque type declarations is important for the last bullet, to ensure that the mangling of generic arguments of opaque result types works across module boundaries. Fixes the rest of rdar://problem/50038754.
1 parent 502a7bf commit e29469b

File tree

8 files changed

+36
-7
lines changed

8 files changed

+36
-7
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 486; // Last change: Opaque result types
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 487; // Last change: Opaque result types generic params
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -1101,6 +1101,7 @@ namespace decls_block {
11011101
TypeIDField, // interface type for opaque type
11021102
GenericEnvironmentIDField, // generic environment
11031103
SubstitutionMapIDField // optional substitution map for underlying type
1104+
// trailed by generic parameters
11041105
>;
11051106

11061107
// TODO: remove the unnecessary FuncDecl components here

lib/AST/ASTMangler.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
985985
// Use the fully elaborated explicit mangling.
986986
appendOpaqueDeclName(opaqueDecl);
987987
bool isFirstArgList = true;
988-
appendBoundGenericArgs(opaqueDecl->getInnermostDeclContext(),
988+
appendBoundGenericArgs(opaqueDecl,
989989
opaqueType->getSubstitutions(),
990990
isFirstArgList);
991991
appendRetroactiveConformances(opaqueType->getSubstitutions(),
@@ -1168,7 +1168,9 @@ unsigned ASTMangler::appendBoundGenericArgs(DeclContext *dc,
11681168
auto decl = dc->getInnermostDeclarationDeclContext();
11691169
if (!decl) return 0;
11701170

1171-
// For an extension declaration, use the nominal type declaration instead.
1171+
// For a non-protocol extension declaration, use the nominal type declaration
1172+
// instead.
1173+
//
11721174
// This is important when extending a nested type, because the generic
11731175
// parameters will line up with the (semantic) nesting of the nominal type.
11741176
if (auto ext = dyn_cast<ExtensionDecl>(decl))

lib/Demangling/Demangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,8 @@ NodePointer Demangler::demangleSymbolicReference(unsigned char rawKind,
690690
return nullptr;
691691

692692
// Types register as substitutions even when symbolically referenced.
693-
if (kind == SymbolicReferenceKind::Context)
693+
if (kind == SymbolicReferenceKind::Context &&
694+
resolved->getKind() != Node::Kind::OpaqueTypeDescriptorSymbolicReference)
694695
addSubstitution(resolved);
695696
return resolved;
696697
}

lib/Serialization/Deserialization.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,6 +3099,9 @@ class swift::DeclDeserializer {
30993099
sig, interfaceType);
31003100
declOrOffset = opaqueDecl;
31013101

3102+
if (auto genericParams = MF.maybeReadGenericParams(opaqueDecl))
3103+
opaqueDecl->setGenericParams(genericParams);
3104+
31023105
auto genericEnv = MF.getGenericEnvironment(genericEnvID);
31033106
opaqueDecl->setGenericEnvironment(genericEnv);
31043107
if (underlyingTypeID)

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3437,6 +3437,7 @@ void Serializer::writeDecl(const Decl *D) {
34373437
contextID, namingDeclID, interfaceSigID,
34383438
interfaceTypeID, genericEnvID,
34393439
underlyingTypeID);
3440+
writeGenericParams(opaqueDecl->getGenericParams());
34403441
break;
34413442
}
34423443

test/Interpreter/opaque_return_type_protocol_ext.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@ protocol P {
66
func foo() -> AT
77
}
88

9+
struct Adapter<T: P>: P {
10+
var inner: T
11+
func foo() -> some P {
12+
return inner
13+
}
14+
}
15+
916
extension P {
1017
func foo() -> some P {
11-
return self
18+
return Adapter(inner: self)
1219
}
1320
}
1421

@@ -18,5 +25,5 @@ func getPAT<T: P>(_: T.Type) -> Any.Type {
1825

1926
extension Int: P { }
2027

21-
// CHECK: Int
28+
// CHECK: Adapter<Int>
2229
print(getPAT(Int.self))

test/Serialization/Inputs/OpaqueCrossFileB.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,9 @@ public struct Subscript {
1919
return FooImpl()
2020
}
2121
}
22+
23+
extension Foo {
24+
public func identity<T>(_: T) -> some Foo {
25+
return self
26+
}
27+
}
Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend -emit-module-path %t/OpaqueCrossFileB.swiftmodule -module-name OpaqueCrossFileB %S/Inputs/OpaqueCrossFileB.swift
3-
// RUN: %target-swift-frontend -I %t -emit-ir -verify %s
3+
// RUN: %target-swift-frontend -I %t -emit-ir -verify %s | %FileCheck %s
44

55
import OpaqueCrossFileB
66

77
dump(anyFoo())
88
dump(anyFooProp)
99
dump(Subscript()[])
1010

11+
public struct UsesAdapterMethod: Foo {
12+
// Ensure that the mangling of the result type of adaptFoo correctly captures
13+
// both the Self type and the parameter type.
14+
// CHECK: @"symbolic _____y______SdQo_ 16OpaqueCrossFileB3FooPAAE8identityyQrqd__lFQO 17opaque_cross_file17UsesAdapterMethodV" =
15+
public func adaptFoo(_ d: Double) -> some Foo {
16+
return identity(d)
17+
}
18+
}

0 commit comments

Comments
 (0)