Skip to content

Commit 8a3ba47

Browse files
committed
Fix canSerialize logic
1 parent 6676288 commit 8a3ba47

File tree

3 files changed

+73
-7
lines changed

3 files changed

+73
-7
lines changed

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
203203
for (Type replType : Subs.getReplacementTypes()) {
204204
switch (mode) {
205205
case VisitMode::DetectSerializableInst:
206-
CMS.canSerializeType(replType->getCanonicalType());
206+
if (!CMS.canSerializeType(replType->getCanonicalType()))
207+
isInstSerializable = false;
207208
break;
208209
case VisitMode::SerializeInst:
209210
/// Ensure that all replacement types of \p Subs are usable from serialized
@@ -667,16 +668,17 @@ bool CrossModuleOptimization::canSerializeType(CanType type) {
667668
if (iter != canTypesChecked.end())
668669
return iter->getSecond();
669670

670-
bool success = type.findIf(
671+
bool success = !type.findIf(
671672
[this](Type rawSubType) {
672673
CanType subType = rawSubType->getCanonicalType();
673674
if (auto nominal = subType->getNominalOrBoundGenericNominal()) {
674-
return canSerializeDecl(nominal);
675+
return !canSerializeDecl(nominal);
675676
}
676-
// If reached here, the type is a Builtin type or similar,
677-
// e.g. Builtin.Int64, Builtin.Word, Builtin.NativeObject, etc.
678-
return true;
679-
});
677+
// Types that might not have nominal include Builtin types (e.g. Builtin.Int64),
678+
// generic parameter types (e.g. T as in Foo<T>), SIL function result types
679+
// (e.g. @convention(method) (Int, @thin Hasher.Type) -> Hasher), etc.
680+
return false;
681+
});
680682

681683
canTypesChecked[type] = success;
682684
return success;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-frontend -emit-module -wmo -enable-default-cmo -parse-as-library %t/Lib.swift -emit-module-path=%t/Lib.swiftmodule -module-name=Lib -enable-testing -I%t
5+
6+
/// TEST: Deserializing Lib module should not cause an assert fail.
7+
// RUN: %target-swift-frontend -emit-sil -sil-verify-all %t/Client.swift -I%t
8+
9+
// REQUIRES: swift_in_compiler
10+
// REQUIRES: asserts
11+
12+
//--- Client.swift
13+
@testable import Lib
14+
15+
//--- Lib.swift
16+
import Foundation
17+
18+
public class PubKlass {
19+
var field = InternalStruct()
20+
/// This function should not be serialized as it returns an opaque type that isn't cast to a concrete nominal type.
21+
func run(from arg: PubStruct) -> some Sequence<InternalStruct.Klass> {
22+
field.run(from: arg)
23+
}
24+
}
25+
26+
public struct PubStruct: Hashable { }
27+
28+
struct InternalStruct: Hashable {
29+
class Klass: Hashable {
30+
let data: PubStruct
31+
init(_ arg: PubStruct) {
32+
self.data = arg
33+
}
34+
func hash(into hasher: inout Hasher) {
35+
hasher.combine(data)
36+
}
37+
static func == (lhs: Klass, rhs: Klass) -> Bool {
38+
return lhs.data == rhs.data
39+
}
40+
}
41+
42+
var entities: [PubStruct: Klass] = [:]
43+
44+
func run(from arg: PubStruct) -> some Sequence<Klass> {
45+
IteratorSequence(EntityIterator(from: arg))
46+
.lazy.map { entities[$0]! }
47+
}
48+
}
49+
50+
51+
private struct EntityIterator<T: Hashable>: IteratorProtocol {
52+
private var list: [T]
53+
init(from start: T) {
54+
self.list = [start]
55+
}
56+
private mutating func pop() -> T? {
57+
return nil
58+
}
59+
mutating func next() -> T? {
60+
return nil
61+
}
62+
}
63+
64+

0 commit comments

Comments
 (0)