Skip to content

Commit ec90545

Browse files
authored
[Serialization] Follow compatibility typealiases for non-generic types (#16618)
Now that we use the C names of imported types in mangled names, it's safe to resolve a compatibility alias when a type gets an NS_SWIFT_NAME for the first time, rather than requiring the developer to recompile the imported library. This doesn't include generic types, which only applies for Objective-C generics. There shouldn't be additional complications here but I want to be extra careful. rdar://problem/39661212
1 parent 356522d commit ec90545

File tree

8 files changed

+98
-2
lines changed

8 files changed

+98
-2
lines changed

lib/Serialization/Deserialization.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4307,6 +4307,31 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
43074307
if (!nominalOrError)
43084308
return nominalOrError.takeError();
43094309

4310+
// Look through compatibility aliases.
4311+
if (auto *alias = dyn_cast<TypeAliasDecl>(nominalOrError.get())) {
4312+
// Reminder: TypeBase::getAs will look through sugar. But we don't want to
4313+
// do that here, so we do isa<> checks on the TypeBase itself instead of
4314+
// using the Type wrapper.
4315+
const TypeBase *underlyingTy = nullptr;
4316+
while (alias->isCompatibilityAlias()) {
4317+
underlyingTy = alias->getUnderlyingTypeLoc().getType().getPointer();
4318+
4319+
// If the underlying type is itself a typealias, it might be another
4320+
// compatibility alias, meaning we need to go around the loop again.
4321+
auto aliasTy = dyn_cast<NameAliasType>(underlyingTy);
4322+
if (!aliasTy)
4323+
break;
4324+
alias = aliasTy->getDecl();
4325+
}
4326+
4327+
// We only want to use the type we found if it's a simple non-generic
4328+
// nominal type.
4329+
if (auto simpleNominalTy = dyn_cast_or_null<NominalType>(underlyingTy)) {
4330+
nominalOrError = simpleNominalTy->getDecl();
4331+
(void)!nominalOrError; // "Check" the llvm::Expected<> value.
4332+
}
4333+
}
4334+
43104335
auto nominal = dyn_cast<NominalTypeDecl>(nominalOrError.get());
43114336
if (!nominal) {
43124337
XRefTracePath tinyTrace{*nominalOrError.get()->getModuleContext()};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#if NEW
2+
# define NEW_NAME(x) __attribute__((swift_name(#x)))
3+
#else
4+
# define NEW_NAME(x)
5+
#endif
6+
7+
struct BeforeStruct {
8+
int value;
9+
} NEW_NAME(AfterStruct);
10+
11+
typedef int BeforeTypedef NEW_NAME(AfterTypedef);
12+
typedef int BeforeWrappedTypedef __attribute__((swift_wrapper(struct))) NEW_NAME(AfterWrappedTypedef);
13+
14+
#if NEW
15+
typedef struct DifferentStruct {
16+
int value;
17+
} BeforeReplacedType NEW_NAME(AfterReplacedType);
18+
#else
19+
struct BeforeReplacedType {
20+
float value;
21+
};
22+
#endif

test/Serialization/Recovery/Inputs/custom-modules/Types.apinotes

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Classes:
77
Typedefs:
88
- Name: RenamedTypedef
99
SwiftName: RenamedTypedef
10+
- Name: RenamedWrappedTypedef
11+
SwiftName: RenamedWrappedTypedef
1012
Tags:
1113
- Name: RenamedStruct
1214
SwiftName: RenamedStruct
@@ -27,6 +29,8 @@ SwiftVersions:
2729
SwiftName: Swift3RenamedTypedef
2830
- Name: NewlyWrappedTypedef
2931
SwiftWrapper: none
32+
- Name: RenamedWrappedTypedef
33+
SwiftName: Swift3RenamedWrappedTypedef
3034
Tags:
3135
- Name: RenamedStruct
3236
SwiftName: Swift3RenamedStruct

test/Serialization/Recovery/Inputs/custom-modules/Types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
typedef int RenamedTypedef;
1212
typedef int NewlyWrappedTypedef __attribute__((swift_wrapper(struct)));
13+
typedef int RenamedWrappedTypedef __attribute__((swift_wrapper(struct)));
1314

1415
struct RenamedStruct {
1516
int value;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Overrides { header "Overrides.h" }
22
module ProtocolInheritance { header "ProtocolInheritance.h" }
3+
module RenameAcrossVersions { header "RenameAcrossVersions.h" }
34
module Typedefs { header "Typedefs.h" }
45
module TypeRemovalObjC { header "TypeRemovalObjC.h" }
56
module Types { header "Types.h" }
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module -o %t -module-name Lib -I %S/Inputs/custom-modules %s
3+
4+
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules | %FileCheck %s
5+
6+
// RUN: %target-swift-ide-test -source-filename=x -print-module -module-to-print Lib -I %t -I %S/Inputs/custom-modules -Xcc -DNEW > %t/recovery.txt
7+
// RUN: %FileCheck -check-prefix CHECK-RECOVERY %s < %t/recovery.txt
8+
// RUN: %FileCheck -check-prefix NEGATIVE-RECOVERY %s < %t/recovery.txt
9+
10+
import RenameAcrossVersions
11+
12+
public func test(
13+
a: BeforeStruct,
14+
b: BeforeTypedef,
15+
c: BeforeWrappedTypedef
16+
) {}
17+
18+
// CHECK-LABEL: func test(
19+
// CHECK-SAME: a: BeforeStruct
20+
// CHECK-SAME: b: BeforeTypedef
21+
// CHECK-SAME: c: BeforeWrappedTypedef
22+
// CHECK-SAME: )
23+
24+
// CHECK-RECOVERY-LABEL: func test(
25+
// CHECK-RECOVERY-SAME: a: AfterStruct
26+
// CHECK-RECOVERY-SAME: b: AfterTypedef
27+
// CHECK-RECOVERY-SAME: c: AfterWrappedTypedef
28+
// CHECK-RECOVERY-SAME: )
29+
30+
// Test replacements that look like renames.
31+
32+
// Please only include one parameter per function, so that we test that that one
33+
// parameter is enough to get the function dropped from the recovery interface.
34+
public func testReplacementA(_: BeforeReplacedType) {}
35+
36+
// CHECK-LABEL: func testReplacementA(_: BeforeReplacedType)
37+
38+
// NEGATIVE-RECOVERY-NOT: testReplacement

test/Serialization/Recovery/types-3-to-4.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public func A_renameAllTheThings(
3232
c: Swift3RenamedTypedef,
3333
d: Swift3RenamedStruct,
3434
e: Swift3RenamedEnum,
35-
f: Swift3RenamedProtocol
35+
f: Swift3RenamedProtocol,
36+
g: Swift3RenamedWrappedTypedef
3637
) {}
3738

3839
// CHECK-4-LABEL: func A_renameAllTheThings(
@@ -42,6 +43,7 @@ public func A_renameAllTheThings(
4243
// CHECK-4-SAME: d: RenamedStruct
4344
// CHECK-4-SAME: e: RenamedEnum
4445
// CHECK-4-SAME: f: RenamedProtocol
46+
// CHECK-4-SAME: g: RenamedWrappedTypedef
4547
// CHECK-4-SAME: )
4648

4749

@@ -56,6 +58,7 @@ public func A_renameAllTheThings(
5658
// CHECK-3-SAME: d: Swift3RenamedStruct
5759
// CHECK-3-SAME: e: Swift3RenamedEnum
5860
// CHECK-3-SAME: f: Swift3RenamedProtocol
61+
// CHECK-3-SAME: g: Swift3RenamedWrappedTypedef
5962
// CHECK-3-SAME: )
6063

6164

test/Serialization/Recovery/types-4-to-3.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ public func A_renameAllTheThings(
3232
c: RenamedTypedef,
3333
d: RenamedStruct,
3434
e: RenamedEnum,
35-
f: RenamedProtocol
35+
f: RenamedProtocol,
36+
g: RenamedWrappedTypedef
3637
) {}
3738

3839
// CHECK-LABEL: func A_renameAllTheThings(
@@ -42,6 +43,7 @@ public func A_renameAllTheThings(
4243
// CHECK-SAME: d: RenamedStruct
4344
// CHECK-SAME: e: RenamedEnum
4445
// CHECK-SAME: f: RenamedProtocol
46+
// CHECK-SAME: g: RenamedWrappedTypedef
4547
// CHECK-SAME: )
4648

4749

0 commit comments

Comments
 (0)