Skip to content

Commit 2caef36

Browse files
authored
Merge pull request #31541 from slavapestov/fix-default-arguments-of-inlinable-local-functions
Fix default arguments of inlinable local functions
2 parents 1f6c3be + 001534c commit 2caef36

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

lib/AST/DeclContext.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,13 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
348348
auto *VD = cast<ValueDecl>(dc->getAsDecl());
349349
assert(VD->hasParameterList());
350350

351+
if (VD->getDeclContext()->isLocalContext()) {
352+
auto kind = VD->getDeclContext()->getFragileFunctionKind();
353+
if (kind.kind != FragileFunctionKind::None)
354+
return {FragileFunctionKind::DefaultArgument,
355+
kind.allowUsableFromInline};
356+
}
357+
351358
auto effectiveAccess =
352359
VD->getFormalAccessScope(/*useDC=*/nullptr,
353360
/*treatUsableFromInlineAsPublic=*/true);

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -442,12 +442,9 @@ bool SILDeclRef::isTransparent() const {
442442

443443
/// True if the function should have its body serialized.
444444
IsSerialized_t SILDeclRef::isSerialized() const {
445-
DeclContext *dc;
446445
if (auto closure = getAbstractClosureExpr()) {
447-
dc = closure->getLocalContext();
448-
449-
// Otherwise, ask the AST if we're inside an @inlinable context.
450-
if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal) {
446+
// Ask the AST if we're inside an @inlinable context.
447+
if (closure->getResilienceExpansion() == ResilienceExpansion::Minimal) {
451448
if (isForeign)
452449
return IsSerializable;
453450

@@ -465,6 +462,13 @@ IsSerialized_t SILDeclRef::isSerialized() const {
465462
// Default argument generators are serialized if the containing
466463
// declaration is public.
467464
if (isDefaultArgGenerator()) {
465+
// Ask the AST if we're inside an @inlinable context.
466+
if (d->getDeclContext()->getResilienceExpansion()
467+
== ResilienceExpansion::Minimal) {
468+
return IsSerialized;
469+
}
470+
471+
// Otherwise, check if the owning declaration is public.
468472
auto scope =
469473
d->getFormalAccessScope(/*useDC=*/nullptr,
470474
/*treatUsableFromInlineAsPublic=*/true);
@@ -490,7 +494,7 @@ IsSerialized_t SILDeclRef::isSerialized() const {
490494

491495
// Note: if 'd' is a function, then 'dc' is the function itself, not
492496
// its parent context.
493-
dc = d->getInnermostDeclContext();
497+
auto *dc = d->getInnermostDeclContext();
494498

495499
// Local functions are serializable if their parent function is
496500
// serializable.

test/SILGen/default_arguments_local.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,16 @@ class ArtClass<T> {
5757
return 0
5858
}
5959
}
60+
61+
// Default arguments of local functions inside @inlinable contexts should be serialized.
62+
// https://bugs.swift.org/browse/SR-12404
63+
64+
// CHECK-LABEL: sil [serialized] [ossa] @$s23default_arguments_local5outeryyF : $@convention(thin) () -> () {
65+
@inlinable public func outer() {
66+
// CHECK-LABEL: sil shared [serialized] [ossa] @$s23default_arguments_local5outeryyF5innerL_1xySi_tFfA_ : $@convention(thin) () -> Int {
67+
68+
// CHECK-LABEL: sil shared [serializable] [ossa] @$s23default_arguments_local5outeryyF5innerL_1xySi_tF : $@convention(thin) (Int) -> () {
69+
func inner(x: Int = 0) {}
70+
71+
inner()
72+
}

test/attr/attr_inlinable.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@
99
// expected-warning@-1 {{'@inlinable' declaration is already '@usableFromInline'}}
1010

1111
private func privateFunction() {}
12-
// expected-note@-1{{global function 'privateFunction()' is not '@usableFromInline' or public}}
12+
// expected-note@-1 2{{global function 'privateFunction()' is not '@usableFromInline' or public}}
1313
fileprivate func fileprivateFunction() {}
1414
// expected-note@-1{{global function 'fileprivateFunction()' is not '@usableFromInline' or public}}
1515
func internalFunction() {}
16-
// expected-note@-1{{global function 'internalFunction()' is not '@usableFromInline' or public}}
16+
// expected-note@-1 2{{global function 'internalFunction()' is not '@usableFromInline' or public}}
1717
@usableFromInline func versionedFunction() {}
1818
public func publicFunction() {}
1919

@@ -306,3 +306,16 @@ public struct PrivateInlinableCrash {
306306
value ? "YES" : "NO"
307307
}
308308
}
309+
310+
// https://bugs.swift.org/browse/SR-12404
311+
@inlinable public func inlinableOuterFunction() {
312+
func innerFunction1(x: () = privateFunction()) {}
313+
// expected-error@-1 {{global function 'privateFunction()' is private and cannot be referenced from a default argument value}}
314+
315+
func innerFunction2(x: () = internalFunction()) {}
316+
// expected-error@-1 {{global function 'internalFunction()' is internal and cannot be referenced from a default argument value}}
317+
318+
func innerFunction3(x: () = versionedFunction()) {}
319+
320+
func innerFunction4(x: () = publicFunction()) {}
321+
}

0 commit comments

Comments
 (0)