Skip to content

Commit d72cbbc

Browse files
authored
Merge pull request swiftlang#19253 from slavapestov/serialize-generic-typealias
Serialization: Fix deserialization of generic typealiases
2 parents c0275b8 + 3feaf87 commit d72cbbc

File tree

6 files changed

+72
-37
lines changed

6 files changed

+72
-37
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
5757
/// Don't worry about adhering to the 80-column limit for this line.
58-
const uint16_t VERSION_MINOR = 442; // Last change: operator protocol
58+
const uint16_t VERSION_MINOR = 443; // Last change: serialize unsubstituted type alias type
5959

6060
using DeclIDField = BCFixed<31>;
6161

lib/Serialization/Deserialization.cpp

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4195,37 +4195,53 @@ Expected<Type> ModuleFile::getTypeChecked(TypeID TID) {
41954195
return aliasOrError.takeError();
41964196
auto alias = dyn_cast<TypeAliasDecl>(aliasOrError.get());
41974197

4198+
bool formSugaredType = true;
4199+
41984200
Type underlyingType;
41994201
if (ctx.LangOpts.EnableDeserializationRecovery) {
4200-
Expected<Type> expectedType = getTypeChecked(underlyingTypeID);
4201-
if (!expectedType)
4202-
return expectedType.takeError();
4203-
if (expectedType.get()) {
4204-
if (!alias ||
4205-
!alias->getDeclaredInterfaceType()->isEqual(expectedType.get())) {
4206-
// Fall back to the canonical type.
4207-
typeOrOffset = expectedType.get()->getCanonicalType();
4208-
break;
4209-
}
4202+
auto underlyingTypeOrError = getTypeChecked(underlyingTypeID);
4203+
if (!underlyingTypeOrError)
4204+
return underlyingTypeOrError.takeError();
4205+
4206+
underlyingType = underlyingTypeOrError.get();
4207+
4208+
if (!alias ||
4209+
!alias->getDeclaredInterfaceType()->isEqual(underlyingType)) {
4210+
// Fall back to the canonical type.
4211+
formSugaredType = false;
42104212
}
42114213

4212-
underlyingType = expectedType.get();
42134214
} else {
42144215
underlyingType = getType(underlyingTypeID);
42154216
}
42164217

4217-
Type parentType = getType(parentTypeID);
4218-
42194218
// Read the substitutions.
4220-
SubstitutionMap subMap = getSubstitutionMap(substitutionsID);
4219+
auto subMap = getSubstitutionMap(substitutionsID);
4220+
underlyingType = underlyingType.subst(subMap);
4221+
assert(underlyingType);
4222+
4223+
auto parentTypeOrError = getTypeChecked(parentTypeID);
4224+
if (!parentTypeOrError) {
4225+
typeOrOffset = underlyingType;
4226+
break;
4227+
}
42214228

42224229
// Look through compatibility aliases that are now unavailable.
4223-
if (alias->getAttrs().isUnavailable(ctx) &&
4230+
if (alias &&
4231+
alias->getAttrs().isUnavailable(ctx) &&
42244232
alias->isCompatibilityAlias()) {
4225-
typeOrOffset = alias->getUnderlyingTypeLoc().getType();
4233+
underlyingType = alias->getUnderlyingTypeLoc().getType().subst(subMap);
4234+
assert(underlyingType);
4235+
typeOrOffset = underlyingType;
4236+
break;
4237+
}
4238+
4239+
if (!formSugaredType) {
4240+
typeOrOffset = underlyingType;
42264241
break;
42274242
}
42284243

4244+
auto parentType = parentTypeOrError.get();
42294245
typeOrOffset = NameAliasType::get(alias, parentType, subMap,
42304246
underlyingType);
42314247
break;

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3625,13 +3625,14 @@ void Serializer::writeType(Type ty) {
36253625
case TypeKind::NameAlias: {
36263626
auto alias = cast<NameAliasType>(ty.getPointer());
36273627
const TypeAliasDecl *typeAlias = alias->getDecl();
3628+
auto underlyingType = typeAlias->getUnderlyingTypeLoc().getType();
36283629

36293630
unsigned abbrCode = DeclTypeAbbrCodes[NameAliasTypeLayout::Code];
36303631
NameAliasTypeLayout::emitRecord(
36313632
Out, ScratchRecord, abbrCode,
36323633
addDeclRef(typeAlias, /*allowTypeAliasXRef*/true),
36333634
addTypeRef(alias->getParent()),
3634-
addTypeRef(alias->getSinglyDesugaredType()),
3635+
addTypeRef(underlyingType),
36353636
addSubstitutionMapRef(alias->getSubstitutionMap()));
36363637
break;
36373638
}

test/IDE/print_swift_module.swift

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,43 @@
44
// RUN: %FileCheck %s -check-prefix=CHECK1 < %t.syn.txt
55

66
public protocol P1 {
7-
/// foo1 comment from P1
8-
func foo1()
9-
/// foo2 comment from P1
10-
func foo2()
7+
/// foo1 comment from P1
8+
func foo1()
9+
/// foo2 comment from P1
10+
func foo2()
1111
}
1212
public class C1 : P1 {
13-
public func foo1() {
14-
}
15-
/// foo2 comment from C1
16-
public func foo2() {
17-
}
13+
public func foo1() {
14+
}
15+
/// foo2 comment from C1
16+
public func foo2() {
17+
}
1818
}
1919

20-
// CHECK1: public class C1 : P1 {
21-
// CHECK1-NEXT: /// foo1 comment from P1
22-
// CHECK1-NEXT: public func foo1()
23-
// CHECK1-NEXT: /// foo2 comment from C1
24-
// CHECK1-NEXT: public func foo2()
20+
/// Alias comment
21+
public typealias Alias<T> = (T, T)
22+
23+
/// returnsAlias() comment
24+
public func returnsAlias() -> Alias<Int> {
25+
return (0, 0)
26+
}
27+
28+
// CHECK1: /// Alias comment
29+
// CHECK1-NEXT: typealias Alias<T> = (T, T)
30+
31+
// CHECK1: public class C1 : P1 {
32+
// CHECK1-NEXT: /// foo1 comment from P1
33+
// CHECK1-NEXT: public func foo1()
34+
// CHECK1-NEXT: /// foo2 comment from C1
35+
// CHECK1-NEXT: public func foo2()
2536
// CHECK1-NEXT: }
37+
38+
// CHECK1: public protocol P1 {
39+
// CHECK1-NEXT: /// foo1 comment from P1
40+
// CHECK1-NEXT: func foo1()
41+
// CHECK1-NEXT: /// foo2 comment from P1
42+
// CHECK1-NEXT: func foo2()
43+
// CHECK1-NEXT: }
44+
45+
// CHECK1: /// returnsAlias() comment
46+
// CHECK1-NEXT: func returnsAlias() -> Alias<Int>

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,7 @@ public func A_renameAllTheThings(
4949

5050
// CHECK-4-LABEL: func A_renameAllTheThings(
5151
// CHECK-4-SAME: a: Swift4RenamedClass?
52-
53-
// FIXME: An issue not specific to the importer where generic typealiases are
54-
// not preserved when provided arguments.
55-
// CHECK-4-SAME: b: RenamedGenericClass<AnyObject>?
56-
52+
// CHECK-4-SAME: b: Swift4RenamedGenericClass<AnyObject>?
5753
// CHECK-4-SAME: c: Swift4RenamedTypedef
5854
// CHECK-4-SAME: d: Swift4RenamedStruct
5955
// CHECK-4-SAME: e: Swift4RenamedEnum

test/api-digester/source-stability.swift.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
/* Generic Signature Changes */
3+
Func Substring.replaceSubrange(_:with:) has generic signature change from <C where C : Collection, C.Element == Character> to <C where C : Collection, C.Element == Substring.Iterator.Element>
34
Protocol BinaryInteger has generic signature change from <Self : CustomStringConvertible, Self : Hashable, Self : Numeric, Self : Strideable, Self.Magnitude : BinaryInteger, Self.Magnitude == Self.Magnitude.Magnitude, Self.Words : Sequence, Self.Words.Element == UInt> to <Self : CustomStringConvertible, Self : Hashable, Self : Numeric, Self : Strideable, Self.Magnitude : BinaryInteger, Self.Magnitude == Self.Magnitude.Magnitude, Self.Words : RandomAccessCollection, Self.Words.Element == UInt, Self.Words.Index == Int>
45
/* RawRepresentable Changes */
56

0 commit comments

Comments
 (0)