[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.
This commit is contained in:
Doug Gregor
2019-04-22 16:56:03 -07:00
parent 502a7bf3d7
commit e29469b9c0
8 changed files with 36 additions and 7 deletions

View File

@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important; /// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format. /// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line. /// Don't worry about adhering to the 80-column limit for this line.
const uint16_t SWIFTMODULE_VERSION_MINOR = 486; // Last change: Opaque result types const uint16_t SWIFTMODULE_VERSION_MINOR = 487; // Last change: Opaque result types generic params
using DeclIDField = BCFixed<31>; using DeclIDField = BCFixed<31>;
@@ -1101,6 +1101,7 @@ namespace decls_block {
TypeIDField, // interface type for opaque type TypeIDField, // interface type for opaque type
GenericEnvironmentIDField, // generic environment GenericEnvironmentIDField, // generic environment
SubstitutionMapIDField // optional substitution map for underlying type SubstitutionMapIDField // optional substitution map for underlying type
// trailed by generic parameters
>; >;
// TODO: remove the unnecessary FuncDecl components here // TODO: remove the unnecessary FuncDecl components here

View File

@@ -985,7 +985,7 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
// Use the fully elaborated explicit mangling. // Use the fully elaborated explicit mangling.
appendOpaqueDeclName(opaqueDecl); appendOpaqueDeclName(opaqueDecl);
bool isFirstArgList = true; bool isFirstArgList = true;
appendBoundGenericArgs(opaqueDecl->getInnermostDeclContext(), appendBoundGenericArgs(opaqueDecl,
opaqueType->getSubstitutions(), opaqueType->getSubstitutions(),
isFirstArgList); isFirstArgList);
appendRetroactiveConformances(opaqueType->getSubstitutions(), appendRetroactiveConformances(opaqueType->getSubstitutions(),
@@ -1168,7 +1168,9 @@ unsigned ASTMangler::appendBoundGenericArgs(DeclContext *dc,
auto decl = dc->getInnermostDeclarationDeclContext(); auto decl = dc->getInnermostDeclarationDeclContext();
if (!decl) return 0; if (!decl) return 0;
// For an extension declaration, use the nominal type declaration instead. // For a non-protocol extension declaration, use the nominal type declaration
// instead.
//
// This is important when extending a nested type, because the generic // This is important when extending a nested type, because the generic
// parameters will line up with the (semantic) nesting of the nominal type. // parameters will line up with the (semantic) nesting of the nominal type.
if (auto ext = dyn_cast<ExtensionDecl>(decl)) if (auto ext = dyn_cast<ExtensionDecl>(decl))

View File

@@ -690,7 +690,8 @@ NodePointer Demangler::demangleSymbolicReference(unsigned char rawKind,
return nullptr; return nullptr;
// Types register as substitutions even when symbolically referenced. // Types register as substitutions even when symbolically referenced.
if (kind == SymbolicReferenceKind::Context) if (kind == SymbolicReferenceKind::Context &&
resolved->getKind() != Node::Kind::OpaqueTypeDescriptorSymbolicReference)
addSubstitution(resolved); addSubstitution(resolved);
return resolved; return resolved;
} }

View File

@@ -3099,6 +3099,9 @@ public:
sig, interfaceType); sig, interfaceType);
declOrOffset = opaqueDecl; declOrOffset = opaqueDecl;
if (auto genericParams = MF.maybeReadGenericParams(opaqueDecl))
opaqueDecl->setGenericParams(genericParams);
auto genericEnv = MF.getGenericEnvironment(genericEnvID); auto genericEnv = MF.getGenericEnvironment(genericEnvID);
opaqueDecl->setGenericEnvironment(genericEnv); opaqueDecl->setGenericEnvironment(genericEnv);
if (underlyingTypeID) if (underlyingTypeID)

View File

@@ -3437,6 +3437,7 @@ void Serializer::writeDecl(const Decl *D) {
contextID, namingDeclID, interfaceSigID, contextID, namingDeclID, interfaceSigID,
interfaceTypeID, genericEnvID, interfaceTypeID, genericEnvID,
underlyingTypeID); underlyingTypeID);
writeGenericParams(opaqueDecl->getGenericParams());
break; break;
} }

View File

@@ -6,9 +6,16 @@ protocol P {
func foo() -> AT func foo() -> AT
} }
struct Adapter<T: P>: P {
var inner: T
func foo() -> some P {
return inner
}
}
extension P { extension P {
func foo() -> some P { func foo() -> some P {
return self return Adapter(inner: self)
} }
} }
@@ -18,5 +25,5 @@ func getPAT<T: P>(_: T.Type) -> Any.Type {
extension Int: P { } extension Int: P { }
// CHECK: Int // CHECK: Adapter<Int>
print(getPAT(Int.self)) print(getPAT(Int.self))

View File

@@ -19,3 +19,9 @@ public struct Subscript {
return FooImpl() return FooImpl()
} }
} }
extension Foo {
public func identity<T>(_: T) -> some Foo {
return self
}
}

View File

@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t) // RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module-path %t/OpaqueCrossFileB.swiftmodule -module-name OpaqueCrossFileB %S/Inputs/OpaqueCrossFileB.swift // RUN: %target-swift-frontend -emit-module-path %t/OpaqueCrossFileB.swiftmodule -module-name OpaqueCrossFileB %S/Inputs/OpaqueCrossFileB.swift
// RUN: %target-swift-frontend -I %t -emit-ir -verify %s // RUN: %target-swift-frontend -I %t -emit-ir -verify %s | %FileCheck %s
import OpaqueCrossFileB import OpaqueCrossFileB
@@ -8,3 +8,11 @@ dump(anyFoo())
dump(anyFooProp) dump(anyFooProp)
dump(Subscript()[]) dump(Subscript()[])
public struct UsesAdapterMethod: Foo {
// Ensure that the mangling of the result type of adaptFoo correctly captures
// both the Self type and the parameter type.
// CHECK: @"symbolic _____y______SdQo_ 16OpaqueCrossFileB3FooPAAE8identityyQrqd__lFQO 17opaque_cross_file17UsesAdapterMethodV" =
public func adaptFoo(_ d: Double) -> some Foo {
return identity(d)
}
}