Skip to content

Commit 59df11b

Browse files
authored
Merge pull request #68421 from apple/embedded-availability
[embedded] Add an interim attr to mark declarations as unavailable in embedded Swift
2 parents 8770c7f + f4258dd commit 59df11b

File tree

5 files changed

+77
-8
lines changed

5 files changed

+77
-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: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// This test is checking that usage of an existential (which is normally
2+
// disallowed in embedded Swift and flagged in IRGen) is left undiagnosed
3+
// because the context is @_unavailableInEmbedded.
4+
//
5+
// The breakdown of that is
6+
// - (1) @_unavailableInEmbedded makes the declaration unavailable,
7+
// - (2) unavailable function bodies is removed in embedded Swift,
8+
// - (3) the test() function is not reported by the existential checker.
9+
10+
// RUN: %target-swift-frontend -emit-ir %s -parse-stdlib | %FileCheck %s --check-prefix CHECK-A
11+
// RUN: %target-swift-frontend -emit-ir %s -parse-stdlib -enable-experimental-feature Embedded | %FileCheck %s --check-prefix CHECK-B
12+
13+
public protocol Player {}
14+
struct Concrete: Player {}
15+
16+
@_unavailableInEmbedded
17+
public func test() -> any Player {
18+
Concrete() // no error because we're in unavailable-in-embedded context
19+
}
20+
21+
// CHECK-A: $s4main4testAA6Player_pyF
22+
// CHECK-B-NOT: $s4main4testAA6Player_pyF

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)