Skip to content

Commit d60f2ff

Browse files
authored
Merge pull request #20091 from jrose-apple/deeply-cross
[Serialization] Encode depth for cross-refs to generic parameters
2 parents 73589ec + 3455510 commit d60f2ff

9 files changed

+151
-5
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 2 deletions
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 = 455; // Last change: reorder block IDs
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 456; // Last change: encode depth in generic param XREFs
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -1403,7 +1403,8 @@ namespace decls_block {
14031403

14041404
using XRefGenericParamPathPieceLayout = BCRecordLayout<
14051405
XREF_GENERIC_PARAM_PATH_PIECE,
1406-
BCVBR<5> // index
1406+
BCVBR<5>, // depth
1407+
BCVBR<5> // index
14071408
>;
14081409

14091410
using SILGenNameDeclAttrLayout = BCRecordLayout<

lib/Serialization/Deserialization.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,8 +1622,8 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
16221622
getXRefDeclNameForError());
16231623
}
16241624

1625-
uint32_t paramIndex;
1626-
XRefGenericParamPathPieceLayout::readRecord(scratch, paramIndex);
1625+
uint32_t depth, paramIndex;
1626+
XRefGenericParamPathPieceLayout::readRecord(scratch, depth, paramIndex);
16271627

16281628
pathTrace.addGenericParam(paramIndex);
16291629

@@ -1645,7 +1645,7 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
16451645
assert(paramList && "Couldn't find constrained extension");
16461646
} else {
16471647
// Simple case: use the nominal type's generic parameters.
1648-
paramList = nominal->getGenericParams();
1648+
paramList = nominal->getGenericParamsOfContext();
16491649
}
16501650
} else if (auto alias = dyn_cast<TypeAliasDecl>(base)) {
16511651
paramList = alias->getGenericParams();
@@ -1660,6 +1660,18 @@ ModuleFile::resolveCrossReference(ModuleDecl *baseModule, uint32_t pathLen) {
16601660
"cross-reference to generic param for non-generic type",
16611661
pathTrace, getXRefDeclNameForError());
16621662
}
1663+
1664+
unsigned currentDepth = paramList->getDepth();
1665+
if (currentDepth < depth) {
1666+
return llvm::make_error<XRefError>(
1667+
"a containing type has been made non-generic",
1668+
pathTrace, getXRefDeclNameForError());
1669+
}
1670+
while (currentDepth > depth) {
1671+
paramList = paramList->getOuterParameters();
1672+
--currentDepth;
1673+
}
1674+
16631675
if (paramIndex >= paramList->size()) {
16641676
return llvm::make_error<XRefError>(
16651677
"generic argument index out of bounds",

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,6 +2026,7 @@ void Serializer::writeCrossReference(const Decl *D) {
20262026
"Cannot cross reference a generic type decl at module scope.");
20272027
abbrCode = DeclTypeAbbrCodes[XRefGenericParamPathPieceLayout::Code];
20282028
XRefGenericParamPathPieceLayout::emitRecord(Out, ScratchRecord, abbrCode,
2029+
genericParam->getDepth(),
20292030
genericParam->getIndex());
20302031
return;
20312032
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
public struct OuterNonGeneric {}
2+
extension OuterNonGeneric {
3+
public struct InnerNonGeneric {}
4+
public struct InnerGeneric<Y1, Y2> {}
5+
}
6+
7+
public struct OuterGeneric<X1, X2> {}
8+
extension OuterGeneric {
9+
public struct InnerNonGeneric {}
10+
public struct InnerGeneric<Y1, Y2> {}
11+
}
12+
13+
14+
extension OuterNonGeneric.InnerNonGeneric {
15+
public typealias AliasTy = ()
16+
}
17+
18+
extension OuterNonGeneric.InnerGeneric where Y1: Equatable {
19+
public typealias AliasTy = (Y1, Y2)
20+
}
21+
22+
extension OuterGeneric.InnerNonGeneric where X1: Equatable {
23+
public typealias AliasTy = (X1, X2)
24+
}
25+
26+
extension OuterGeneric.InnerGeneric where X1: Equatable, Y1: Equatable {
27+
public typealias AliasTy = (X1, X2, Y1, Y2)
28+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
public struct OuterNonGeneric {}
2+
extension OuterNonGeneric {
3+
public struct InnerNonGeneric {
4+
public typealias AliasTy = ()
5+
}
6+
public struct InnerGeneric<Y1, Y2> {
7+
public typealias AliasTy = (Y1, Y2)
8+
}
9+
}
10+
11+
public struct OuterGeneric<X1, X2> {}
12+
extension OuterGeneric {
13+
public struct InnerNonGeneric {
14+
public typealias AliasTy = (X1, X2)
15+
}
16+
public struct InnerGeneric<Y1, Y2> {
17+
public typealias AliasTy = (X1, X2, Y1, Y2)
18+
}
19+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
public struct OuterNonGeneric {}
2+
extension OuterNonGeneric {
3+
public struct InnerNonGeneric {}
4+
public struct InnerGeneric<Y1, Y2> {}
5+
}
6+
7+
public struct OuterGeneric<X1, X2> {}
8+
extension OuterGeneric {
9+
public struct InnerNonGeneric {}
10+
public struct InnerGeneric<Y1, Y2> {}
11+
}
12+
13+
14+
extension OuterNonGeneric.InnerNonGeneric {
15+
public typealias AliasTy = ()
16+
}
17+
18+
extension OuterNonGeneric.InnerGeneric {
19+
public typealias AliasTy = (Y1, Y2)
20+
}
21+
22+
extension OuterGeneric.InnerNonGeneric {
23+
public typealias AliasTy = (X1, X2)
24+
}
25+
26+
extension OuterGeneric.InnerGeneric {
27+
public typealias AliasTy = (X1, X2, Y1, Y2)
28+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public struct OuterNonGeneric {
2+
public struct InnerNonGeneric {
3+
public typealias AliasTy = ()
4+
}
5+
public struct InnerGeneric<Y1, Y2> {
6+
public typealias AliasTy = (Y1, Y2)
7+
}
8+
}
9+
10+
public struct OuterGeneric<X1, X2> {
11+
public struct InnerNonGeneric {
12+
public typealias AliasTy = (X1, X2)
13+
}
14+
public struct InnerGeneric<Y1, Y2> {
15+
public typealias AliasTy = (X1, X2, Y1, Y2)
16+
}
17+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// Run the same test several times, providing the nested types a different way
4+
// each time.
5+
6+
// RUN: %target-swift-frontend -emit-module -o %t/a.swiftmodule -primary-file %s %S/Inputs/xref-generic-params-other.swift -module-name main
7+
// RUN: %target-swift-frontend -emit-module -o %t/b.swiftmodule %s -primary-file %S/Inputs/xref-generic-params-other.swift -module-name main
8+
// RUN: %target-swift-frontend -merge-modules -emit-module -o %t/main.swiftmodule %t/a.swiftmodule %t/b.swiftmodule -module-name main
9+
// RUN: %target-swift-ide-test -print-module -module-to-print=main -I %t -source-filename=x | %FileCheck %s
10+
11+
// RUN: %target-swift-frontend -emit-module -o %t/a-extensions.swiftmodule -primary-file %s %S/Inputs/xref-generic-params-other-extensions.swift -module-name extensions
12+
// RUN: %target-swift-frontend -emit-module -o %t/b-extensions.swiftmodule %s -primary-file %S/Inputs/xref-generic-params-other-extensions.swift -module-name extensions
13+
// RUN: %target-swift-frontend -merge-modules -emit-module -o %t/extensions.swiftmodule %t/a-extensions.swiftmodule %t/b-extensions.swiftmodule -module-name extensions
14+
// RUN: %target-swift-ide-test -print-module -module-to-print=extensions -I %t -source-filename=x | %FileCheck %s
15+
16+
// RUN: %target-swift-frontend -emit-module -o %t/a-extensions_mixed.swiftmodule -primary-file %s %S/Inputs/xref-generic-params-other-extensions-mixed.swift -module-name extensions_mixed
17+
// RUN: %target-swift-frontend -emit-module -o %t/b-extensions_mixed.swiftmodule %s -primary-file %S/Inputs/xref-generic-params-other-extensions-mixed.swift -module-name extensions_mixed
18+
// RUN: %target-swift-frontend -merge-modules -emit-module -o %t/extensions_mixed.swiftmodule %t/a-extensions_mixed.swiftmodule %t/b-extensions_mixed.swiftmodule -module-name extensions_mixed
19+
// RUN: %target-swift-ide-test -print-module -module-to-print=extensions_mixed -I %t -source-filename=x | %FileCheck %s
20+
21+
// RUN: %target-swift-frontend -emit-module -o %t/a-extensions_constrained.swiftmodule -primary-file %s %S/Inputs/xref-generic-params-other-extensions-constrained.swift -module-name extensions_constrained
22+
// RUN: %target-swift-frontend -emit-module -o %t/b-extensions_constrained.swiftmodule %s -primary-file %S/Inputs/xref-generic-params-other-extensions-constrained.swift -module-name extensions_constrained
23+
// RUN: %target-swift-frontend -merge-modules -emit-module -o %t/extensions_constrained.swiftmodule %t/a-extensions_constrained.swiftmodule %t/b-extensions_constrained.swiftmodule -module-name extensions_constrained
24+
// RUN: %target-swift-ide-test -print-module -module-to-print=extensions_constrained -I %t -source-filename=x | %FileCheck %s
25+
26+
public struct A: Equatable {}
27+
public struct B: Equatable {}
28+
public struct C: Equatable {}
29+
public struct D: Equatable {}
30+
31+
// CHECK-LABEL: func test(
32+
public func test(
33+
// CHECK-SAME: _: OuterNonGeneric.InnerNonGeneric.AliasTy
34+
_: OuterNonGeneric.InnerNonGeneric.AliasTy,
35+
// CHECK-SAME: _: OuterNonGeneric.InnerGeneric<C, D>.AliasTy
36+
_: OuterNonGeneric.InnerGeneric<C, D>.AliasTy,
37+
// CHECK-SAME: _: OuterGeneric<A, B>.InnerNonGeneric.AliasTy
38+
_: OuterGeneric<A, B>.InnerNonGeneric.AliasTy,
39+
// CHECK-SAME: _: OuterGeneric<A, B>.InnerGeneric<C, D>.AliasTy
40+
_: OuterGeneric<A, B>.InnerGeneric<C, D>.AliasTy) {}

0 commit comments

Comments
 (0)