diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp index b561b1e22718b..e4f21d07caa6e 100644 --- a/lib/AST/DeclContext.cpp +++ b/lib/AST/DeclContext.cpp @@ -348,6 +348,13 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator, auto *VD = cast(dc->getAsDecl()); assert(VD->hasParameterList()); + if (VD->getDeclContext()->isLocalContext()) { + auto kind = VD->getDeclContext()->getFragileFunctionKind(); + if (kind.kind != FragileFunctionKind::None) + return {FragileFunctionKind::DefaultArgument, + kind.allowUsableFromInline}; + } + auto effectiveAccess = VD->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 5abf3a81364be..a05a1a15f4b22 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -442,12 +442,9 @@ bool SILDeclRef::isTransparent() const { /// True if the function should have its body serialized. IsSerialized_t SILDeclRef::isSerialized() const { - DeclContext *dc; if (auto closure = getAbstractClosureExpr()) { - dc = closure->getLocalContext(); - - // Otherwise, ask the AST if we're inside an @inlinable context. - if (dc->getResilienceExpansion() == ResilienceExpansion::Minimal) { + // Ask the AST if we're inside an @inlinable context. + if (closure->getResilienceExpansion() == ResilienceExpansion::Minimal) { if (isForeign) return IsSerializable; @@ -465,6 +462,13 @@ IsSerialized_t SILDeclRef::isSerialized() const { // Default argument generators are serialized if the containing // declaration is public. if (isDefaultArgGenerator()) { + // Ask the AST if we're inside an @inlinable context. + if (d->getDeclContext()->getResilienceExpansion() + == ResilienceExpansion::Minimal) { + return IsSerialized; + } + + // Otherwise, check if the owning declaration is public. auto scope = d->getFormalAccessScope(/*useDC=*/nullptr, /*treatUsableFromInlineAsPublic=*/true); @@ -490,7 +494,7 @@ IsSerialized_t SILDeclRef::isSerialized() const { // Note: if 'd' is a function, then 'dc' is the function itself, not // its parent context. - dc = d->getInnermostDeclContext(); + auto *dc = d->getInnermostDeclContext(); // Local functions are serializable if their parent function is // serializable. diff --git a/test/SILGen/default_arguments_local.swift b/test/SILGen/default_arguments_local.swift index faf8df999103c..d2d804f1e8a6a 100644 --- a/test/SILGen/default_arguments_local.swift +++ b/test/SILGen/default_arguments_local.swift @@ -57,3 +57,16 @@ class ArtClass { return 0 } } + +// Default arguments of local functions inside @inlinable contexts should be serialized. +// https://bugs.swift.org/browse/SR-12404 + +// CHECK-LABEL: sil [serialized] [ossa] @$s23default_arguments_local5outeryyF : $@convention(thin) () -> () { +@inlinable public func outer() { + // CHECK-LABEL: sil shared [serialized] [ossa] @$s23default_arguments_local5outeryyF5innerL_1xySi_tFfA_ : $@convention(thin) () -> Int { + + // CHECK-LABEL: sil shared [serializable] [ossa] @$s23default_arguments_local5outeryyF5innerL_1xySi_tF : $@convention(thin) (Int) -> () { + func inner(x: Int = 0) {} + + inner() +} diff --git a/test/attr/attr_inlinable.swift b/test/attr/attr_inlinable.swift index 034a19ed56d81..ade8d9e7278c1 100644 --- a/test/attr/attr_inlinable.swift +++ b/test/attr/attr_inlinable.swift @@ -9,11 +9,11 @@ // expected-warning@-1 {{'@inlinable' declaration is already '@usableFromInline'}} private func privateFunction() {} -// expected-note@-1{{global function 'privateFunction()' is not '@usableFromInline' or public}} +// expected-note@-1 2{{global function 'privateFunction()' is not '@usableFromInline' or public}} fileprivate func fileprivateFunction() {} // expected-note@-1{{global function 'fileprivateFunction()' is not '@usableFromInline' or public}} func internalFunction() {} -// expected-note@-1{{global function 'internalFunction()' is not '@usableFromInline' or public}} +// expected-note@-1 2{{global function 'internalFunction()' is not '@usableFromInline' or public}} @usableFromInline func versionedFunction() {} public func publicFunction() {} @@ -306,3 +306,16 @@ public struct PrivateInlinableCrash { value ? "YES" : "NO" } } + +// https://bugs.swift.org/browse/SR-12404 +@inlinable public func inlinableOuterFunction() { + func innerFunction1(x: () = privateFunction()) {} + // expected-error@-1 {{global function 'privateFunction()' is private and cannot be referenced from a default argument value}} + + func innerFunction2(x: () = internalFunction()) {} + // expected-error@-1 {{global function 'internalFunction()' is internal and cannot be referenced from a default argument value}} + + func innerFunction3(x: () = versionedFunction()) {} + + func innerFunction4(x: () = publicFunction()) {} +} \ No newline at end of file