Skip to content

Commit b83bb7d

Browse files
committed
Sema: Fix bug where enum cases could not be referenced from inlineable context
Enum cases do not have their own accessibility or @_versioned attribute, and we already diagnose invalid references to the enum type itself.
1 parent 9424f2b commit b83bb7d

File tree

2 files changed

+56
-44
lines changed

2 files changed

+56
-44
lines changed

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,27 +77,42 @@ bool TypeChecker::diagnoseInlineableDeclRef(SourceLoc loc,
7777
const ValueDecl *D,
7878
const DeclContext *DC) {
7979
auto expansion = DC->getResilienceExpansion();
80-
if (expansion == ResilienceExpansion::Minimal) {
81-
if (!isa<GenericTypeParamDecl>(D) &&
82-
// Protocol requirements are not versioned because there's no
83-
// global entry point
84-
!(isa<ProtocolDecl>(D->getDeclContext()) && isRequirement(D)) &&
85-
// FIXME: Figure out what to do with typealiases
86-
!isa<TypeAliasDecl>(D) &&
87-
!D->getDeclContext()->isLocalContext() &&
88-
D->hasAccessibility()) {
89-
if (D->getEffectiveAccess() < Accessibility::Public) {
90-
diagnose(loc, diag::resilience_decl_unavailable,
91-
D->getDescriptiveKind(), D->getFullName(),
92-
D->getFormalAccess(), getFragileFunctionKind(DC));
93-
diagnose(D, diag::resilience_decl_declared_here,
94-
D->getDescriptiveKind(), D->getFullName());
95-
return true;
96-
}
97-
}
98-
}
9980

100-
return false;
81+
// Internal declarations referenced from non-inlineable contexts are OK.
82+
if (expansion == ResilienceExpansion::Maximal)
83+
return false;
84+
85+
// Local declarations are OK.
86+
if (D->getDeclContext()->isLocalContext())
87+
return false;
88+
89+
// Type parameters are OK.
90+
if (isa<AbstractTypeParamDecl>(D))
91+
return false;
92+
93+
// Public declarations are OK.
94+
if (D->getEffectiveAccess() >= Accessibility::Public)
95+
return false;
96+
97+
// Enum cases are handled as part of their containing enum.
98+
if (isa<EnumElementDecl>(D))
99+
return false;
100+
101+
// Protocol requirements are not versioned because there's no
102+
// global entry point.
103+
if (isa<ProtocolDecl>(D->getDeclContext()) && isRequirement(D))
104+
return false;
105+
106+
// FIXME: Figure out what to do with typealiases
107+
if (isa<TypeAliasDecl>(D))
108+
return false;
109+
110+
diagnose(loc, diag::resilience_decl_unavailable,
111+
D->getDescriptiveKind(), D->getFullName(),
112+
D->getFormalAccess(), getFragileFunctionKind(DC));
113+
diagnose(D, diag::resilience_decl_declared_here,
114+
D->getDescriptiveKind(), D->getFullName());
115+
return true;
101116
}
102117

103118
void TypeChecker::diagnoseResilientValueConstructor(ConstructorDecl *ctor) {

test/attr/attr_inlineable.swift

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -217,32 +217,29 @@ extension VersionedProtocol {
217217
}
218218
}
219219

220-
protocol InternalProtocol {
221-
associatedtype T
222-
223-
func requirement() -> T
220+
enum InternalEnum {
221+
// expected-note@-1 2{{enum 'InternalEnum' is not '@_versioned' or public}}
222+
case apple
223+
case orange
224224
}
225225

226-
extension InternalProtocol {
227-
func internalMethod() {}
226+
@_inlineable public func usesInternalEnum() {
227+
_ = InternalEnum.apple
228+
// expected-error@-1 {{enum 'InternalEnum' is internal and cannot be referenced from an '@_inlineable' function}}
229+
let _: InternalEnum = .orange
230+
// expected-error@-1 {{enum 'InternalEnum' is internal and cannot be referenced from an '@_inlineable' function}}
231+
}
228232

229-
// FIXME: https://bugs.swift.org/browse/SR-3684
230-
//
231-
// This should either complain that the method cannot be '@_versioned' since
232-
// we're inside an extension of an internal protocol, or if such methods are
233-
// allowed, we should diagnose the reference to 'internalMethod()' from the
234-
// body.
235-
@_inlineable
236-
@_versioned
237-
func versionedMethod() -> T {
238-
internalMethod()
239-
return requirement()
240-
}
233+
@_versioned enum VersionedEnum {
234+
case apple
235+
case orange
236+
// FIXME: Should this be banned?
237+
case pear(InternalEnum)
238+
case persimmon(String)
239+
}
241240

242-
// Ditto, except s/@_versioned/public/.
243-
@_inlineable
244-
public func publicMethod() -> T {
245-
internalMethod()
246-
return requirement()
247-
}
241+
@_inlineable public func usesVersionedEnum() {
242+
_ = VersionedEnum.apple
243+
let _: VersionedEnum = .orange
244+
_ = VersionedEnum.persimmon
248245
}

0 commit comments

Comments
 (0)