Skip to content

Commit e27b4a5

Browse files
authored
Merge pull request #83357 from tshortli/non-public-setter-back-deployed-crash
AST: Skip serializing non-public accessors of `@backDeployed` properties
2 parents aa16ff5 + 7d866bf commit e27b4a5

File tree

8 files changed

+101
-11
lines changed

8 files changed

+101
-11
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,9 +1121,8 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
11211121
getBackDeployedAttrAndRange(ASTContext &Ctx,
11221122
bool forTargetVariant = false) const;
11231123

1124-
/// Returns true if the decl has an active `@backDeployed` attribute for the
1125-
/// given context.
1126-
bool isBackDeployed(ASTContext &Ctx) const;
1124+
/// Returns true if the decl has a valid and active `@backDeployed` attribute.
1125+
bool isBackDeployed() const;
11271126

11281127
/// Returns the starting location of the entire declaration.
11291128
SourceLoc getStartLoc() const { return getSourceRange().Start; }

lib/AST/ASTDumper.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3075,7 +3075,14 @@ void ValueDecl::dumpRef(raw_ostream &os) const {
30753075
printContext(os, getDeclContext());
30763076
os << ".";
30773077
// Print name.
3078-
getName().printPretty(os);
3078+
if (auto accessor = dyn_cast<AccessorDecl>(this)) {
3079+
// If it's an accessor, print the name of the storage and then the
3080+
// accessor kind.
3081+
accessor->getStorage()->getName().printPretty(os);
3082+
os << "." << Decl::getDescriptiveKindName(accessor->getDescriptiveKind());
3083+
} else {
3084+
getName().printPretty(os);
3085+
}
30793086
} else {
30803087
auto moduleName = cast<ModuleDecl>(this)->getRealName();
30813088
os << moduleName;

lib/AST/Decl.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,22 @@ Decl::getBackDeployedAttrAndRange(ASTContext &Ctx,
630630
return std::nullopt;
631631
}
632632

633-
bool Decl::isBackDeployed(ASTContext &Ctx) const {
633+
bool Decl::isBackDeployed() const {
634+
auto &Ctx = getASTContext();
635+
636+
// A function declared in a local context can never be back-deployed.
637+
if (getDeclContext()->isLocalContext())
638+
return false;
639+
640+
// A non-public function can never be back-deployed.
641+
if (auto VD = dyn_cast<ValueDecl>(this)) {
642+
auto access =
643+
VD->getFormalAccessScope(/*useDC=*/nullptr,
644+
/*treatUsableFromInlineAsPublic=*/true);
645+
if (!access.isPublic())
646+
return false;
647+
}
648+
634649
if (getBackDeployedAttrAndRange(Ctx))
635650
return true;
636651

lib/AST/DeclContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
562562
return {FragileFunctionKind::AlwaysEmitIntoClient};
563563
}
564564

565-
if (AFD->isBackDeployed(context->getASTContext())) {
565+
if (AFD->isBackDeployed()) {
566566
return {FragileFunctionKind::BackDeploy};
567567
}
568568

@@ -576,7 +576,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
576576
if (storage->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>()) {
577577
return {FragileFunctionKind::AlwaysEmitIntoClient};
578578
}
579-
if (storage->isBackDeployed(context->getASTContext())) {
579+
if (storage->isBackDeployed()) {
580580
return {FragileFunctionKind::BackDeploy};
581581
}
582582
}

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,7 @@ bool SILDeclRef::isBackDeployed() const {
10841084
&& "should not get backDeployed from ABI-only decl");
10851085

10861086
if (auto afd = dyn_cast<AbstractFunctionDecl>(decl))
1087-
return afd->isBackDeployed(getASTContext());
1087+
return afd->isBackDeployed();
10881088

10891089
return false;
10901090
}

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,7 +1527,7 @@ void SILGenModule::emitAbstractFuncDecl(AbstractFunctionDecl *AFD) {
15271527

15281528
emitDistributedThunkForDecl(AFD);
15291529

1530-
if (AFD->isBackDeployed(M.getASTContext())) {
1530+
if (AFD->isBackDeployed()) {
15311531
// Emit the fallback function that will be used when the original function
15321532
// is unavailable at runtime.
15331533
auto fallback = SILDeclRef(AFD).asBackDeploymentKind(

test/Inputs/lazy_typecheck.swift

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public func publicFuncWithOpaqueReturnType() -> some PublicProto {
6464

6565
@available(SwiftStdlib 5.1, *)
6666
@_alwaysEmitIntoClient public func publicAEICFuncWithOpaqueReturnType() -> some Any {
67-
if #available(macOS 20, *) {
67+
if #available(macOS 99, *) {
6868
return 3
6969
} else {
7070
return "hi"
@@ -109,6 +109,30 @@ var internalGlobalVar: NoTypecheck = NoTypecheck()
109109
var internalGlobalVarInferredType = NoTypecheck()
110110
var internalGlobalTypealiasVar: PublicIntAlias = NoTypecheck.int
111111

112+
@backDeployed(before: macOS 99, iOS 99, tvOS 99, watchOS 99, visionOS 99)
113+
public private(set) var publicGlobalVarBackDeployedWithPrivateSetter: Int {
114+
get { 0 }
115+
set { // Implicitly not @backDeployed.
116+
_ = NoTypecheck()
117+
}
118+
}
119+
120+
@backDeployed(before: macOS 99, iOS 99, tvOS 99, watchOS 99, visionOS 99)
121+
public internal(set) var publicGlobalVarBackDeployedWithInternalSetter: Int {
122+
get { 0 }
123+
set { // Implicitly not @backDeployed.
124+
_ = NoTypecheck()
125+
}
126+
}
127+
128+
@backDeployed(before: macOS 99, iOS 99, tvOS 99, watchOS 99, visionOS 99)
129+
public package(set) var publicGlobalVarBackDeployedWithPackageSetter: Int {
130+
get { 0 }
131+
set { // Implicitly not @backDeployed.
132+
_ = NoTypecheck()
133+
}
134+
}
135+
112136
// MARK: - Nominal types
113137

114138
public protocol EmptyPublicProto {}

test/attr/attr_backDeployed.swift

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ public struct TopLevelStruct {
3434
set(newValue) {}
3535
}
3636

37+
@backDeployed(before: macOS 12.0)
38+
public private(set) var readWritePropertyPrivateSet: Int {
39+
get { 42 }
40+
set(newValue) {}
41+
}
42+
43+
@backDeployed(before: macOS 12.0)
44+
public internal(set) var readWritePropertyInternalSet: Int {
45+
get { 42 }
46+
set(newValue) {}
47+
}
48+
3749
@backDeployed(before: macOS 12.0)
3850
public subscript(at index: Int) -> Int {
3951
get { 42 }
@@ -234,7 +246,6 @@ public final class CannotBackDeployClassDeinit {
234246
deinit {}
235247
}
236248

237-
// Ok, final decls in a non-final, derived class
238249
public class CannotBackDeployOverride: TopLevelClass {
239250
@backDeployed(before: macOS 12.0) // expected-error {{'@backDeployed' cannot be combined with 'override'}}
240251
final public override func hook() {}
@@ -293,6 +304,40 @@ public func cannotBackDeployFuncWithOpaqueResultType() -> some TopLevelProtocol
293304
return ConformsToTopLevelProtocol()
294305
}
295306

307+
public struct CannotBackDeployNonPublicAccessors {
308+
private var privateVar: Int {
309+
@backDeployed(before: macOS 12.0) // expected-error {{'@backDeployed' may not be used on private declarations}}
310+
get { 0 }
311+
312+
@backDeployed(before: macOS 12.0) // expected-error {{'@backDeployed' may not be used on private declarations}}
313+
set { }
314+
}
315+
316+
internal var internalVar: Int {
317+
@backDeployed(before: macOS 12.0) // expected-error {{'@backDeployed' may not be used on internal declarations}}
318+
get { 0 }
319+
320+
@backDeployed(before: macOS 12.0) // expected-error {{'@backDeployed' may not be used on internal declarations}}
321+
set { }
322+
}
323+
324+
public private(set) var publicVarPrivateSet: Int {
325+
@backDeployed(before: macOS 12.0)
326+
get { 0 }
327+
328+
@backDeployed(before: macOS 12.0) // expected-error {{'@backDeployed' may not be used on private declarations}}
329+
set { }
330+
}
331+
332+
public internal(set) var publicVarInternalSet: Int {
333+
@backDeployed(before: macOS 12.0)
334+
get { 0 }
335+
336+
@backDeployed(before: macOS 12.0) // expected-error {{'@backDeployed' may not be used on internal declarations}}
337+
set { }
338+
}
339+
}
340+
296341
// MARK: - Function body diagnostics
297342

298343
public struct FunctionBodyDiagnostics {

0 commit comments

Comments
 (0)