Skip to content

Commit 72c8e78

Browse files
committed
SIL: Don't serialize imported conformances nested in non-public types
Apparently you can use a swift_name attribute in Clang to import types as members of Swift types. If the Swift type is not public, we would still try to serialize the witness thunks, which tripped SIL verifier checks since the witnesses themselves were not serialized. Note that the fix here is to just delete the special case of an imported conformance; the regular "type is public and protocol is public" condition suffices here. Fixes <rdar://problem/48218483>.
1 parent a5e4fd5 commit 72c8e78

File tree

4 files changed

+57
-12
lines changed

4 files changed

+57
-12
lines changed

lib/SIL/SILWitnessTable.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
//
1313
// This file defines the SILWitnessTable class, which is used to map a protocol
1414
// conformance for a type to its implementing SILFunctions. This information is
15-
// (FIXME will be) used by IRGen to create witness tables for protocol dispatch.
15+
// used by IRGen to create witness tables for protocol dispatch.
16+
//
1617
// It can also be used by generic specialization and existential
17-
// devirtualization passes to promote witness_method and protocol_method
18-
// instructions to static function_refs.
18+
// devirtualization passes to promote witness_method instructions to static
19+
// function_refs.
1920
//
2021
//===----------------------------------------------------------------------===//
2122

@@ -24,7 +25,6 @@
2425
#include "swift/AST/ASTMangler.h"
2526
#include "swift/AST/Module.h"
2627
#include "swift/AST/ProtocolConformance.h"
27-
#include "swift/ClangImporter/ClangModule.h"
2828
#include "swift/SIL/SILModule.h"
2929
#include "llvm/ADT/SmallString.h"
3030

@@ -172,11 +172,6 @@ bool SILWitnessTable::conformanceIsSerialized(
172172
if (normalConformance && normalConformance->isResilient())
173173
return false;
174174

175-
// Serialize witness tables for conformances synthesized by
176-
// the ClangImporter.
177-
if (isa<ClangModuleUnit>(conformance->getDeclContext()->getModuleScopeContext()))
178-
return true;
179-
180175
if (conformance->getProtocol()->getEffectiveAccess() < AccessLevel::Public)
181176
return false;
182177

lib/SILGen/SILGenType.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -487,9 +487,18 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
487487
} else {
488488
// This is the "real" rule; the above case should go away once we
489489
// figure out what's going on.
490-
witnessLinkage = (witnessSerialized
491-
? SILLinkage::Shared
492-
: SILLinkage::Private);
490+
491+
// Normally witness thunks can be private.
492+
witnessLinkage = SILLinkage::Private;
493+
494+
// Unless the witness table is going to be serialized.
495+
if (witnessSerialized)
496+
witnessLinkage = SILLinkage::Shared;
497+
498+
// Or even if its not serialized, it might be for an imported
499+
// conformance in which case it can be emitted multiple times.
500+
if (Linkage == SILLinkage::Shared)
501+
witnessLinkage = SILLinkage::Shared;
493502
}
494503

495504
SILFunction *witnessFn = SGM.emitProtocolWitness(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@class Public;
2+
@class Internal;
3+
4+
enum InternalInner { a, b, c } __attribute__((swift_name("Public.Inner")));
5+
enum PublicInner { d, e, f } __attribute__((swift_name("Internal.Inner")));
6+
enum TopLevel { g, h, i };
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-swift-emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -import-objc-header %S/Inputs/objc_witnesses_serialized.h | %FileCheck %s
2+
3+
// REQUIRES: objc_interop
4+
5+
import Foundation
6+
7+
func useRawRepresentable<T : RawRepresentable>(_: T) {}
8+
9+
// FIXME: getEffectiveClangContext() is broken and checks
10+
// for an explicit '@objc' attribute.
11+
12+
@objc public class Public : NSObject {
13+
func takesInner(_ value: Inner) {
14+
useRawRepresentable(value)
15+
}
16+
}
17+
18+
@objc internal class Internal : NSObject {
19+
func takesInner(_ value: Inner) {
20+
useRawRepresentable(value)
21+
}
22+
}
23+
24+
func takesTopLevel(_ value: TopLevel) {
25+
useRawRepresentable(value)
26+
}
27+
28+
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] [ossa] @$sSo13InternalInnerVSYSCSY8rawValuexSg03RawD0Qz_tcfCTW : $@convention(witness_method: RawRepresentable) (@in UInt32, @thick Public.Inner.Type) -> @out Optional<Public.Inner>
29+
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] [ossa] @$sSo13InternalInnerVSYSCSY8rawValue03RawD0QzvgTW : $@convention(witness_method: RawRepresentable) (@in_guaranteed Public.Inner) -> @out UInt32
30+
31+
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$sSo11PublicInnerVSYSCSY8rawValuexSg03RawD0Qz_tcfCTW : $@convention(witness_method: RawRepresentable) (@in UInt32, @thick Internal.Inner.Type) -> @out Optional<Internal.Inner>
32+
// CHECK-LABEL: sil shared [transparent] [thunk] [ossa] @$sSo11PublicInnerVSYSCSY8rawValue03RawD0QzvgTW : $@convention(witness_method: RawRepresentable) (@in_guaranteed Internal.Inner) -> @out UInt32
33+
34+
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] [ossa] @$sSo8TopLevelVSYSCSY8rawValuexSg03RawD0Qz_tcfCTW : $@convention(witness_method: RawRepresentable) (@in UInt32, @thick TopLevel.Type) -> @out Optional<TopLevel>
35+
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] [ossa] @$sSo8TopLevelVSYSCSY8rawValue03RawD0QzvgTW : $@convention(witness_method: RawRepresentable) (@in_guaranteed TopLevel) -> @out UInt32

0 commit comments

Comments
 (0)