Skip to content

Commit f128803

Browse files
committed
[Serialization] Fix incorrect counting of value witnesses.
If any of the witnesses were missing (because the requirement was optional or marked unavailable), we would forget to count it, which led to us dropping or even misinterpreting further witness records. This led to strange crashes down the line when the type checker would expect witness entries to be present when they weren't.
1 parent 4345a04 commit f128803

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

lib/Serialization/Serialization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,7 @@ void Serializer::writeNormalConformance(
12961296

12971297
conformance->forEachValueWitness(nullptr,
12981298
[&](ValueDecl *req, Witness witness) {
1299+
++numValueWitnesses;
12991300
data.push_back(addDeclRef(req));
13001301
data.push_back(addDeclRef(witness.getDecl()));
13011302
assert(witness.getDecl() || req->getAttrs().hasAttribute<OptionalAttr>()
@@ -1319,11 +1320,10 @@ void Serializer::writeNormalConformance(
13191320

13201321
// Requirements come at the end.
13211322
} else {
1322-
data.push_back(0);
1323+
data.push_back(/*number of generic parameters*/0);
13231324
}
13241325

13251326
data.push_back(witness.getSubstitutions().size());
1326-
++numValueWitnesses;
13271327
});
13281328

13291329
conformance->forEachTypeWitness(/*resolver=*/nullptr,

test/Serialization/cross_module_optional_protocol_reqt.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,28 @@
22
// RUN: %target-swift-frontend -module-name cross_module_optional_protocol_reqt -c -emit-module-path %t/cross_module_optional_protocol_reqt~partial.swiftmodule -primary-file %s %S/Inputs/cross_module_optional_protocol_reqt_2.swift -import-objc-header %S/Inputs/cross_module_optional_protocol_reqt.h -o /dev/null
33
// RUN: %target-swift-frontend -module-name cross_module_optional_protocol_reqt -c -emit-module-path %t/cross_module_optional_protocol_reqt_2~partial.swiftmodule %s -primary-file %S/Inputs/cross_module_optional_protocol_reqt_2.swift -import-objc-header %S/Inputs/cross_module_optional_protocol_reqt.h -o /dev/null
44
// RUN: %target-swift-frontend -module-name cross_module_optional_protocol_reqt -emit-module -emit-module-path %t/cross_module_optional_protocol_reqt.swiftmodule %t/cross_module_optional_protocol_reqt~partial.swiftmodule %t/cross_module_optional_protocol_reqt_2~partial.swiftmodule -import-objc-header %S/Inputs/cross_module_optional_protocol_reqt.h
5+
// RUN: %target-swift-frontend -I %t -typecheck %s -DTEST -module-name main
56
// REQUIRES: objc_interop
67

8+
#if TEST
9+
10+
import cross_module_optional_protocol_reqt
11+
12+
func test(_ foo: Foo) {
13+
// At one point this forced deserialization of the conformance to ObjCProto,
14+
// which was corrupted by the presence of the optional requirement with no
15+
// witness.
16+
foo.nonoptionalMethod()
17+
foo.nonoptionalMethod2()
18+
}
19+
20+
#else // TEST
21+
722
public protocol SwiftProto: ObjCProto {}
823

924
public class Foo: ObjCFoo, SwiftProto {
1025
public func nonoptionalMethod() {}
1126
public func nonoptionalMethod2() {}
1227
}
28+
29+
#endif // TEST

0 commit comments

Comments
 (0)