Skip to content

Commit 9a38021

Browse files
committed
[embedded] Add an interim attr to mark declarations as unavailable in embedded Swift
Implemented as custom parsing logic instead of a proper attribute because we want it to be rewritten at parse time (into nothing in regular Swift mode, and into unconditional unavailable attr in embedded Swift mode), no serialization, printing, etc.
1 parent 2307bc0 commit 9a38021

File tree

5 files changed

+64
-8
lines changed

5 files changed

+64
-8
lines changed

lib/Frontend/CompilerInvocation.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1316,9 +1316,13 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
13161316
}
13171317
Opts.BypassResilienceChecks |= Args.hasArg(OPT_bypass_resilience);
13181318

1319-
if (FrontendOpts.EnableLibraryEvolution && Opts.hasFeature(Feature::Embedded)) {
1320-
Diags.diagnose(SourceLoc(), diag::evolution_with_embedded);
1321-
HadError = true;
1319+
if (Opts.hasFeature(Feature::Embedded)) {
1320+
Opts.UnavailableDeclOptimizationMode = UnavailableDeclOptimization::Complete;
1321+
1322+
if (FrontendOpts.EnableLibraryEvolution) {
1323+
Diags.diagnose(SourceLoc(), diag::evolution_with_embedded);
1324+
HadError = true;
1325+
}
13221326
}
13231327

13241328
if (auto A = Args.getLastArg(OPT_checked_async_objc_bridging)) {

lib/Parse/ParseDecl.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4154,6 +4154,25 @@ ParserStatus Parser::parseDeclAttribute(
41544154
return makeParserSuccess();
41554155
}
41564156

4157+
// Rewrite @_unavailableInEmbedded into @available(*, unavailable) when in
4158+
// embedded Swift mode, or into nothing when in regular mode.
4159+
if (DK == DAK_Count && Tok.getText() == "_unavailableInEmbedded") {
4160+
SourceLoc attrLoc = consumeToken();
4161+
if (Context.LangOpts.hasFeature(Feature::Embedded)) {
4162+
StringRef Message = "unavailable in embedded Swift", Renamed;
4163+
auto attr = new (Context) AvailableAttr(AtLoc, SourceRange(AtLoc, attrLoc),
4164+
PlatformKind::none,
4165+
Message, Renamed, /*RenameDecl=*/nullptr,
4166+
llvm::VersionTuple(), SourceRange(),
4167+
llvm::VersionTuple(), SourceRange(),
4168+
llvm::VersionTuple(), SourceRange(),
4169+
PlatformAgnosticAvailabilityKind::Unavailable,
4170+
/*Implicit=*/false, /*IsSPI=*/false);
4171+
Attributes.add(attr);
4172+
}
4173+
return makeParserSuccess();
4174+
}
4175+
41574176
if (DK != DAK_Count && !DeclAttribute::shouldBeRejectedByParser(DK)) {
41584177
return parseNewDeclAttribute(Attributes, AtLoc, DK, isFromClangAttribute);
41594178
}

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,14 @@ static bool isInsideCompatibleUnavailableDeclaration(
345345
return false;
346346
}
347347

348-
// Refuse calling unavailable functions from unavailable code,
349-
// but allow the use of types.
348+
// Unless in embedded Swift mode, refuse calling unavailable functions from
349+
// unavailable code, but allow the use of types.
350350
PlatformKind platform = attr->Platform;
351-
if (platform == PlatformKind::none && !isa<TypeDecl>(D) &&
352-
!isa<ExtensionDecl>(D)) {
353-
return false;
351+
if (!D->getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
352+
if (platform == PlatformKind::none && !isa<TypeDecl>(D) &&
353+
!isa<ExtensionDecl>(D)) {
354+
return false;
355+
}
354356
}
355357

356358
return (*referencedPlatform == platform ||
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %target-swift-frontend -emit-ir %s -parse-stdlib -enable-experimental-feature Embedded
2+
3+
public protocol Player {}
4+
struct Concrete: Player {}
5+
6+
@_unavailableInEmbedded
7+
public func test() -> any Player {
8+
Concrete() // no error because we're in unavailable-in-embedded context
9+
}

test/embedded/availability.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Building with regular Swift should succeed
2+
// RUN: %target-swift-emit-ir %s -parse-stdlib
3+
4+
// Building with embedded Swift should produce unavailability errors
5+
// RUN: %target-typecheck-verify-swift -parse-stdlib -enable-experimental-feature Embedded
6+
7+
@_unavailableInEmbedded
8+
public func embedded() { }
9+
public func regular() {
10+
embedded() // expected-error {{'embedded()' is unavailable: unavailable in embedded Swift}}
11+
// expected-note@-3 {{'embedded()' has been explicitly marked unavailable here}}
12+
}
13+
14+
@_unavailableInEmbedded
15+
public func unused() { } // no error
16+
17+
@_unavailableInEmbedded
18+
public func called_from_unavailable() { }
19+
@_unavailableInEmbedded
20+
public func also_embedded() {
21+
called_from_unavailable() // no error
22+
}

0 commit comments

Comments
 (0)