Skip to content

Commit b4e145d

Browse files
committed
SE-0193: @inlinable implies @usableFromInline
1 parent 618cbca commit b4e145d

File tree

5 files changed

+30
-17
lines changed

5 files changed

+30
-17
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3741,6 +3741,9 @@ ERROR(usable_from_inline_attr_with_explicit_access,
37413741
"declarations, but %0 is %select{private|fileprivate|%error|public|open}1",
37423742
(DeclName, AccessLevel))
37433743

3744+
WARNING(inlinable_implies_usable_from_inline,none,
3745+
"'@inlinable' declaration is already '@usableFromInline'",())
3746+
37443747
ERROR(usable_from_inline_attr_in_protocol,none,
37453748
"'@usableFromInline' attribute cannot be used in protocols", ())
37463749

lib/AST/Decl.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,12 +2106,16 @@ SourceLoc ValueDecl::getAttributeInsertionLoc(bool forModifier) const {
21062106
bool ValueDecl::isUsableFromInline() const {
21072107
assert(getFormalAccess() == AccessLevel::Internal);
21082108

2109-
if (getAttrs().hasAttribute<UsableFromInlineAttr>())
2109+
if (getAttrs().hasAttribute<UsableFromInlineAttr>() ||
2110+
getAttrs().hasAttribute<InlinableAttr>())
21102111
return true;
21112112

2112-
if (auto *accessor = dyn_cast<AccessorDecl>(this))
2113-
if (accessor->getStorage()->getAttrs().hasAttribute<UsableFromInlineAttr>())
2113+
if (auto *accessor = dyn_cast<AccessorDecl>(this)) {
2114+
auto *storage = accessor->getStorage();
2115+
if (storage->getAttrs().hasAttribute<UsableFromInlineAttr>() ||
2116+
storage->getAttrs().hasAttribute<InlinableAttr>())
21142117
return true;
2118+
}
21152119

21162120
if (auto *EED = dyn_cast<EnumElementDecl>(this))
21172121
if (EED->getParentEnum()->getAttrs().hasAttribute<UsableFromInlineAttr>())
@@ -2261,7 +2265,9 @@ void ValueDecl::copyFormalAccessFrom(ValueDecl *source) {
22612265
}
22622266

22632267
// Inherit the @usableFromInline attribute.
2264-
if (source->getAttrs().hasAttribute<UsableFromInlineAttr>()) {
2268+
if (source->getAttrs().hasAttribute<UsableFromInlineAttr>() &&
2269+
!getAttrs().hasAttribute<UsableFromInlineAttr>() &&
2270+
!getAttrs().hasAttribute<InlinableAttr>()) {
22652271
auto &ctx = getASTContext();
22662272
auto *clonedAttr = new (ctx) UsableFromInlineAttr(/*implicit=*/true);
22672273
getAttrs().add(clonedAttr);

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2025,7 +2025,8 @@ static void configureDesignatedInitAttributes(TypeChecker &tc,
20252025
/*treatUsableFromInlineAsPublic=*/true)
20262026
>= AccessLevel::Public) {
20272027
if (access == AccessLevel::Internal &&
2028-
!superclassCtor->isDynamic()) {
2028+
!superclassCtor->isDynamic() &&
2029+
!ctor->getAttrs().hasAttribute<InlinableAttr>()) {
20292030
auto *clonedAttr = new (ctx) UsableFromInlineAttr(/*implicit=*/true);
20302031
ctor->getAttrs().add(clonedAttr);
20312032
}

lib/Sema/TypeCheckAttr.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,6 +1978,12 @@ void AttributeChecker::visitUsableFromInlineAttr(UsableFromInlineAttr *attr) {
19781978
diagnoseAndRemoveAttr(attr, diag::usable_from_inline_dynamic_not_supported);
19791979
return;
19801980
}
1981+
1982+
// On internal declarations, @inlinable implies @usableFromInline.
1983+
if (VD->getAttrs().hasAttribute<InlinableAttr>()) {
1984+
diagnoseAndRemoveAttr(attr, diag::inlinable_implies_usable_from_inline);
1985+
return;
1986+
}
19811987
}
19821988

19831989
void AttributeChecker::visitInlinableAttr(InlinableAttr *attr) {
@@ -2004,11 +2010,9 @@ void AttributeChecker::visitInlinableAttr(InlinableAttr *attr) {
20042010
return;
20052011
}
20062012

2007-
// @inlinable can only be applied to public or @usableFromInline
2008-
// declarations.
2009-
auto access = VD->getFormalAccess(/*useDC=*/nullptr,
2010-
/*treatUsableFromInlineAsPublic=*/true);
2011-
if (access < AccessLevel::Public) {
2013+
// @inlinable can only be applied to public or internal declarations.
2014+
auto access = VD->getFormalAccess();
2015+
if (access < AccessLevel::Internal) {
20122016
diagnoseAndRemoveAttr(attr, diag::inlinable_decl_not_public,
20132017
VD->getBaseName(),
20142018
access);

test/attr/attr_inlinable.swift

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
@inlinable struct TestInlinableStruct {}
66
// expected-error@-1 {{'@inlinable' attribute cannot be applied to this declaration}}
77

8+
@inlinable @usableFromInline func redundantAttribute() {}
9+
// expected-warning@-1 {{'@inlinable' declaration is already '@usableFromInline'}}
10+
811
private func privateFunction() {}
912
// expected-note@-1{{global function 'privateFunction()' is not '@usableFromInline' or public}}
1013
fileprivate func fileprivateFunction() {}
@@ -101,8 +104,7 @@ public struct Struct {
101104
}
102105

103106
@inlinable
104-
@usableFromInline
105-
func versionedInlinableMethod() {
107+
func internalInlinableMethod() {
106108
struct Nested {}
107109
// expected-error@-1 {{type 'Nested' cannot be nested inside an '@inlinable' function}}
108110
}
@@ -121,8 +123,8 @@ public struct Struct {
121123
}
122124

123125
@inlinable
124-
func internalInlinableMethod() {
125-
// expected-error@-2 {{'@inlinable' attribute can only be applied to public declarations, but 'internalInlinableMethod' is internal}}
126+
private func privateInlinableMethod() {
127+
// expected-error@-2 {{'@inlinable' attribute can only be applied to public declarations, but 'privateInlinableMethod' is private}}
126128
struct Nested {}
127129
// OK
128130
}
@@ -148,7 +150,6 @@ extension VersionedProtocol {
148150
// expected-note@-1 {{instance method 'internalMethod()' is not '@usableFromInline' or public}}
149151

150152
@inlinable
151-
@usableFromInline
152153
func versionedMethod() -> T {
153154
internalMethod()
154155
// expected-error@-1 {{instance method 'internalMethod()' is internal and cannot be referenced from an '@inlinable' function}}
@@ -199,7 +200,6 @@ class Middle : Base {}
199200
@usableFromInline
200201
@_fixed_layout
201202
class Derived : Middle {
202-
@usableFromInline
203203
@inlinable
204204
init(y: Int) {
205205
super.init(x: y)
@@ -220,7 +220,6 @@ class Middle2 : Base2 {}
220220
@_fixed_layout
221221
@usableFromInline
222222
class Derived2 : Middle2 {
223-
@usableFromInline
224223
@inlinable
225224
init(y: Int) {
226225
super.init(x: y)

0 commit comments

Comments
 (0)