Skip to content

Commit 96901f1

Browse files
committed
SE-0193: Public default argument generators cannot reference declarations that are @usableFromInline
1 parent 4af8ff6 commit 96901f1

File tree

3 files changed

+53
-29
lines changed

3 files changed

+53
-29
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3765,10 +3765,10 @@ ERROR(resilience_decl_unavailable,
37653765

37663766
#undef FRAGILE_FUNC_KIND
37673767

3768-
NOTE(resilience_decl_declared_here,
3768+
NOTE(resilience_decl_declared_here_public,
37693769
none, "%0 %1 is not public", (DescriptiveDeclKind, DeclName))
37703770

3771-
NOTE(resilience_decl_declared_here_versioned,
3771+
NOTE(resilience_decl_declared_here,
37723772
none, "%0 %1 is not '@usableFromInline' or public", (DescriptiveDeclKind, DeclName))
37733773

37743774
ERROR(class_designated_init_inlinable_resilient,none,

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,15 @@ std::pair<FragileFunctionKind, bool>
2727
TypeChecker::getFragileFunctionKind(const DeclContext *DC) {
2828
for (; DC->isLocalContext(); DC = DC->getParent()) {
2929
if (isa<DefaultArgumentInitializer>(DC)) {
30+
// Default argument generators of public functions cannot reference
31+
// @usableFromInline declarations; all other fragile function kinds
32+
// can.
33+
auto *VD = cast<ValueDecl>(DC->getInnermostDeclarationDeclContext());
34+
auto access =
35+
VD->getFormalAccessScope(/*useDC=*/nullptr,
36+
/*treatUsableFromInlineAsPublic=*/false);
3037
return std::make_pair(FragileFunctionKind::DefaultArgument,
31-
/*treatUsableFromInlineAsPublic=*/true);
38+
!access.isPublic());
3239
}
3340

3441
if (isa<PatternBindingInitializer>(DC))
@@ -121,21 +128,11 @@ bool TypeChecker::diagnoseInlinableDeclRef(SourceLoc loc,
121128
D->getFormalAccessScope().accessLevelForDiagnostics(),
122129
static_cast<unsigned>(Kind));
123130

124-
bool isDefaultArgument = false;
125-
while (DC->isLocalContext()) {
126-
if (isa<DefaultArgumentInitializer>(DC)) {
127-
isDefaultArgument = true;
128-
break;
129-
}
130-
131-
DC = DC->getParent();
132-
}
133-
134-
if (isDefaultArgument) {
131+
if (TreatUsableFromInlineAsPublic) {
135132
diagnose(D, diag::resilience_decl_declared_here,
136133
D->getDescriptiveKind(), D->getFullName());
137134
} else {
138-
diagnose(D, diag::resilience_decl_declared_here_versioned,
135+
diagnose(D, diag::resilience_decl_declared_here_public,
139136
D->getDescriptiveKind(), D->getFullName());
140137
}
141138

test/decl/func/default-values-swift4.swift

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,27 @@
22
// RUN: %target-typecheck-verify-swift -swift-version 4 -enable-testing
33

44
private func privateFunction() {}
5-
// expected-note@-1 4{{global function 'privateFunction()' is not public}}
5+
// expected-note@-1 2{{global function 'privateFunction()' is not public}}
66
fileprivate func fileprivateFunction() {}
7-
// expected-note@-1 4{{global function 'fileprivateFunction()' is not public}}
7+
// expected-note@-1 2{{global function 'fileprivateFunction()' is not public}}
88
func internalFunction() {}
9-
// expected-note@-1 4{{global function 'internalFunction()' is not public}}
9+
// expected-note@-1 2{{global function 'internalFunction()' is not public}}
1010
@usableFromInline func versionedFunction() {}
11+
// expected-note@-1 5{{global function 'versionedFunction()' is not public}}
1112
public func publicFunction() {}
1213

1314
func internalIntFunction() -> Int {}
14-
// expected-note@-1 2{{global function 'internalIntFunction()' is not public}}
15+
// expected-note@-1 {{global function 'internalIntFunction()' is not public}}
16+
17+
private func privateFunction2() {}
18+
// expected-note@-1 2{{global function 'privateFunction2()' is not '@usableFromInline' or public}}
19+
fileprivate func fileprivateFunction2() {}
20+
// expected-note@-1 2{{global function 'fileprivateFunction2()' is not '@usableFromInline' or public}}
21+
func internalFunction2() {}
22+
// expected-note@-1 2{{global function 'internalFunction2()' is not '@usableFromInline' or public}}
23+
24+
func internalIntFunction2() -> Int {}
25+
// expected-note@-1 {{global function 'internalIntFunction2()' is not '@usableFromInline' or public}}
1526

1627
func internalFunctionWithDefaultValue(
1728
x: Int = {
@@ -44,17 +55,17 @@ func internalFunctionWithDefaultValue(
4455
// OK
4556
versionedFunction()
4657
// OK
47-
internalFunction()
48-
// expected-error@-1 2{{global function 'internalFunction()' is internal and cannot be referenced from a default argument value}}
49-
fileprivateFunction()
50-
// expected-error@-1 2{{global function 'fileprivateFunction()' is fileprivate and cannot be referenced from a default argument value}}
51-
privateFunction()
52-
// expected-error@-1 2{{global function 'privateFunction()' is private and cannot be referenced from a default argument value}}
58+
internalFunction2()
59+
// expected-error@-1 2{{global function 'internalFunction2()' is internal and cannot be referenced from a default argument value}}
60+
fileprivateFunction2()
61+
// expected-error@-1 2{{global function 'fileprivateFunction2()' is fileprivate and cannot be referenced from a default argument value}}
62+
privateFunction2()
63+
// expected-error@-1 2{{global function 'privateFunction2()' is private and cannot be referenced from a default argument value}}
5364

5465
return 0
5566
}(),
56-
y: Int = internalIntFunction()) {}
57-
// expected-error@-1 {{global function 'internalIntFunction()' is internal and cannot be referenced from a default argument value}}
67+
y: Int = internalIntFunction2()) {}
68+
// expected-error@-1 {{global function 'internalIntFunction2()' is internal and cannot be referenced from a default argument value}}
5869

5970
public func publicFunctionWithDefaultValue(
6071
x: Int = {
@@ -64,13 +75,16 @@ public func publicFunctionWithDefaultValue(
6475
// FIXME: Some errors below are diagnosed twice
6576

6677
publicFunction()
67-
// OK
78+
6879
versionedFunction()
69-
// OK
80+
// expected-error@-1 2{{global function 'versionedFunction()' is internal and cannot be referenced from a default argument value}}
81+
7082
internalFunction()
7183
// expected-error@-1 2{{global function 'internalFunction()' is internal and cannot be referenced from a default argument value}}
84+
7285
fileprivateFunction()
7386
// expected-error@-1 2{{global function 'fileprivateFunction()' is fileprivate and cannot be referenced from a default argument value}}
87+
7488
privateFunction()
7589
// expected-error@-1 2{{global function 'privateFunction()' is private and cannot be referenced from a default argument value}}
7690

@@ -83,3 +97,16 @@ public func publicFunctionWithDefaultValue(
8397
public class MyClass {
8498
public func method<T>(_: T.Type = T.self) -> T { }
8599
}
100+
101+
public func evilCode(
102+
x: Int = {
103+
let _ = publicFunction()
104+
let _ = versionedFunction()
105+
// expected-error@-1 2{{global function 'versionedFunction()' is internal and cannot be referenced from a default argument value}}
106+
107+
func localFunction() {
108+
publicFunction()
109+
versionedFunction()
110+
// expected-error@-1 {{global function 'versionedFunction()' is internal and cannot be referenced from a default argument value}}
111+
}
112+
}()) {}

0 commit comments

Comments
 (0)