Skip to content

Commit bba87cd

Browse files
committed
SIL: Fix witness visibility hack to handle non-serialized declarations.
We have a hack to handle "public" declarations in extensions to internal protcols that are intended as default implementations for a public protocol that the internal protocol refines. This hack failed to trigger for synthesized declarations with shared linkage, such as automatically generated `read` coroutines, causing a visibility assertion failure where we would try to refer to the non-serializable synthesized declaration from the witness thunk we would normally consider serialized. Fixes rdar://problem/55846638.
1 parent f125d12 commit bba87cd

File tree

6 files changed

+38
-18
lines changed

6 files changed

+38
-18
lines changed

include/swift/SIL/SILDeclRef.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "swift/AST/ClangNode.h"
2323
#include "swift/AST/TypeAlignments.h"
24+
#include "swift/SIL/SILLinkage.h"
2425
#include "llvm/ADT/Hashing.h"
2526
#include "llvm/ADT/DenseMap.h"
2627
#include "llvm/ADT/PointerUnion.h"
@@ -42,7 +43,6 @@ namespace swift {
4243
class ASTContext;
4344
class ClassDecl;
4445
class SILFunctionType;
45-
enum class SILLinkage : unsigned char;
4646
enum IsSerialized_t : unsigned char;
4747
enum class SubclassScope : unsigned char;
4848
class SILModule;
@@ -413,6 +413,22 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, SILDeclRef C) {
413413
return OS;
414414
}
415415

416+
// FIXME: This should not be necessary, but it looks like visibility rules for
417+
// extension members are slightly bogus, and so some protocol witness thunks
418+
// need to be public.
419+
//
420+
// We allow a 'public' member of an extension to witness a public
421+
// protocol requirement, even if the extended type is not public;
422+
// then SILGen gives the member private linkage, ignoring the more
423+
// visible access level it was given in the AST.
424+
inline bool
425+
fixmeWitnessHasLinkageThatNeedsToBePublic(SILDeclRef witness) {
426+
auto witnessLinkage = witness.getLinkage(ForDefinition);
427+
return !hasPublicVisibility(witnessLinkage)
428+
&& (!hasSharedVisibility(witnessLinkage)
429+
|| !witness.isSerialized());
430+
}
431+
416432
} // end swift namespace
417433

418434
namespace llvm {

include/swift/SIL/SILLinkage.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -265,20 +265,6 @@ inline SILLinkage effectiveLinkageForClassMember(SILLinkage linkage,
265265
return linkage;
266266
}
267267

268-
// FIXME: This should not be necessary, but it looks like visibility rules for
269-
// extension members are slightly bogus, and so some protocol witness thunks
270-
// need to be public.
271-
//
272-
// We allow a 'public' member of an extension to witness a public
273-
// protocol requirement, even if the extended type is not public;
274-
// then SILGen gives the member private linkage, ignoring the more
275-
// visible access level it was given in the AST.
276-
inline bool
277-
fixmeWitnessHasLinkageThatNeedsToBePublic(SILLinkage witnessLinkage) {
278-
return !hasPublicVisibility(witnessLinkage) &&
279-
!hasSharedVisibility(witnessLinkage);
280-
}
281-
282268
} // end swift namespace
283269

284270
#endif

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
681681
}
682682
llvm::dbgs() << "In function:\n";
683683
F.print(llvm::dbgs());
684+
llvm::dbgs() << "In module:\n";
685+
F.getModule().print(llvm::dbgs());
684686

685687
// We abort by default because we want to always crash in
686688
// the debugger.

lib/SILGen/SILGenType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ class SILGenConformance : public SILGenWitnessTable<SILGenConformance> {
567567
auto witnessLinkage = witnessRef.getLinkage(ForDefinition);
568568
auto witnessSerialized = Serialized;
569569
if (witnessSerialized &&
570-
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessLinkage)) {
570+
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessRef)) {
571571
witnessLinkage = SILLinkage::Public;
572572
witnessSerialized = IsNotSerialized;
573573
} else {

lib/TBDGen/TBDGen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,10 +473,11 @@ void TBDGenVisitor::addConformances(DeclContext *DC) {
473473
rootConformance);
474474
auto addSymbolIfNecessary = [&](ValueDecl *requirementDecl,
475475
ValueDecl *witnessDecl) {
476-
auto witnessLinkage = SILDeclRef(witnessDecl).getLinkage(ForDefinition);
476+
auto witnessRef = SILDeclRef(witnessDecl);
477+
auto witnessLinkage = witnessRef.getLinkage(ForDefinition);
477478
if (conformanceIsFixed &&
478479
(isa<SelfProtocolConformance>(rootConformance) ||
479-
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessLinkage))) {
480+
fixmeWitnessHasLinkageThatNeedsToBePublic(witnessRef))) {
480481
Mangle::ASTMangler Mangler;
481482
addSymbol(
482483
Mangler.mangleWitnessThunk(rootConformance, requirementDecl));
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swift-emit-silgen -verify %s
2+
3+
public protocol A {
4+
@_borrowed
5+
subscript() -> Int { get }
6+
}
7+
8+
protocol B: A { }
9+
10+
extension B {
11+
public subscript() -> Int { return 0 }
12+
}
13+
14+
public struct S: B {
15+
}

0 commit comments

Comments
 (0)