Skip to content

Commit 01873c9

Browse files
authored
Merge pull request #84283 from DougGregor/embedded-swift-untyped-throws-restriction
[Embedded] Diagnose untyped throws as an Embedded Swift restriction
2 parents a28d7a7 + 865c643 commit 01873c9

18 files changed

+443
-8
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,10 @@ namespace swift {
701701
ignoredDiagnostics[(unsigned)id] = ignored;
702702
}
703703

704+
bool isIgnoredDiagnostic(DiagID id) const {
705+
return ignoredDiagnostics[(unsigned)id];
706+
}
707+
704708
void swap(DiagnosticState &other) {
705709
std::swap(showDiagnosticsAfterFatalError, other.showDiagnosticsAfterFatalError);
706710
std::swap(suppressWarnings, other.suppressWarnings);
@@ -947,6 +951,10 @@ namespace swift {
947951
state.setIgnoredDiagnostic(id, true);
948952
}
949953

954+
bool isIgnoredDiagnostic(DiagID id) const {
955+
return state.isIgnoredDiagnostic(id);
956+
}
957+
950958
void resetHadAnyError() {
951959
state.resetHadAnyError();
952960
}

include/swift/AST/DiagnosticGroups.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ GROUP(ClangDeclarationImport, "clang-declaration-import")
4646
GROUP(ConformanceIsolation, "conformance-isolation")
4747
GROUP(DeprecatedDeclaration, "deprecated-declaration")
4848
GROUP(DynamicCallable, "dynamic-callable-requirements")
49+
GROUP(EmbeddedRestrictions, "embedded-restrictions")
4950
GROUP(ErrorInFutureSwiftVersion, "error-in-future-swift-version")
5051
GROUP(ExclusivityViolation, "exclusivity-violation")
5152
GROUP(ExistentialAny, "existential-any")

include/swift/AST/DiagnosticsSema.def

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,9 +2237,6 @@ ERROR(attr_only_at_non_generic_scope, none,
22372237
ERROR(attr_only_on_static_properties, none,
22382238
"properties with attribute %0 must be static", (DeclAttribute))
22392239

2240-
ERROR(weak_unowned_in_embedded_swift, none,
2241-
"attribute %0 cannot be used in embedded Swift", (ReferenceOwnership))
2242-
22432240
ERROR(access_control_in_protocol,none,
22442241
"%0 modifier cannot be used in protocols", (DeclAttribute))
22452242
NOTE(access_control_in_protocol_detail,none,
@@ -8611,6 +8608,18 @@ ERROR(inlinearray_literal_incorrect_count,none,
86118608
ERROR(inline_array_type_backwards,none,
86128609
"element count must precede inline array element type", ())
86138610

8611+
//===----------------------------------------------------------------------===//
8612+
// MARK: Embedded Swift
8613+
//===----------------------------------------------------------------------===//
8614+
8615+
GROUPED_ERROR(weak_unowned_in_embedded_swift, EmbeddedRestrictions, none,
8616+
"attribute %0 cannot be used in Embedded Swift",
8617+
(ReferenceOwnership))
8618+
8619+
GROUPED_WARNING(untyped_throws_in_embedded_swift, EmbeddedRestrictions,
8620+
DefaultIgnore,
8621+
"untyped throws is not available in Embedded Swift; add a thrown error type with '(type)'", ())
8622+
86148623
//===----------------------------------------------------------------------===//
86158624
// MARK: @abi Attribute
86168625
//===----------------------------------------------------------------------===//

include/swift/Bridging/ASTGen.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ intptr_t swift_ASTGen_configuredRegions(
117117
void swift_ASTGen_freeConfiguredRegions(
118118
BridgedIfConfigClauseRangeInfo *_Nullable regions, intptr_t numRegions);
119119

120+
intptr_t swift_ASTGen_activeInEmbeddedSwift(
121+
BridgedASTContext astContext,
122+
void *_Nonnull sourceFile,
123+
swift::SourceLoc location);
124+
120125
bool swift_ASTGen_validateUnqualifiedLookup(
121126
void *_Nonnull sourceFile,
122127
BridgedASTContext astContext,

lib/ASTGen/Sources/ASTGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_pure_swift_host_library(swiftASTGen STATIC CXX_INTEROP
99
Decls.swift
1010
Diagnostics.swift
1111
DiagnosticsBridge.swift
12+
EmbeddedSupport.swift
1213
Exprs.swift
1314
Fingerprint.swift
1415
Generics.swift
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//===--- EmbeddedSupport.swift --------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022-2025 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import ASTBridging
14+
import BasicBridging
15+
import SwiftIfConfig
16+
import SwiftSyntax
17+
18+
extension ExportedSourceFile {
19+
/// Return the configured regions for this source file.
20+
mutating func configuredRegionsIfEmbedded(astContext: BridgedASTContext) -> ConfiguredRegions {
21+
if let _configuredRegionsIfEmbedded {
22+
return _configuredRegionsIfEmbedded
23+
}
24+
25+
// Ensure that we've already computed the configured regions, which can
26+
// emit diagnostics.
27+
_ = configuredRegions(astContext: astContext)
28+
29+
let configuration = EmbeddedBuildConfiguration(
30+
ctx: astContext,
31+
sourceBuffer: buffer
32+
)
33+
34+
let regions = syntax.configuredRegions(in: configuration)
35+
_configuredRegionsIfEmbedded = regions
36+
return regions
37+
}
38+
}
39+
40+
/// Determine whether the given source location is active when this source
41+
/// file is compiled in Embedded Swift.
42+
@_cdecl("swift_ASTGen_activeInEmbeddedSwift")
43+
public func activeInEmbeddedSwift(
44+
astContext: BridgedASTContext,
45+
sourceFilePtr: UnsafeMutableRawPointer,
46+
at location: SourceLoc
47+
) -> Int {
48+
guard let token = findToken(
49+
in: UnsafeRawPointer(sourceFilePtr),
50+
at: location.raw?.assumingMemoryBound(to: UInt8.self)
51+
) else {
52+
return 0
53+
}
54+
55+
let sourceFile = sourceFilePtr.assumingMemoryBound(to: ExportedSourceFile.self)
56+
let regions = sourceFile.pointee.configuredRegionsIfEmbedded(astContext: astContext)
57+
return regions.isActive(token) == .active ? 1 : 0
58+
}
59+
60+
/// A build configuration that is a thin shim over the
61+
/// CompilerBuildConfiguration that enables the Embedded language feature,
62+
/// allowing the compiler to determine whether code we're in will be available
63+
/// in an embedded context or not.
64+
struct EmbeddedBuildConfiguration: BuildConfiguration {
65+
let configuration: CompilerBuildConfiguration
66+
67+
init(ctx: BridgedASTContext, sourceBuffer: UnsafeBufferPointer<UInt8>) {
68+
self.configuration = .init(ctx: ctx, sourceBuffer: sourceBuffer)
69+
}
70+
71+
func isCustomConditionSet(name: String) throws -> Bool {
72+
// $Embedded is set when building Embedded Swift
73+
if name == "$Embedded" {
74+
return true
75+
}
76+
77+
return try configuration.isCustomConditionSet(name: name)
78+
}
79+
80+
func hasFeature(name: String) throws -> Bool {
81+
// The "Embedded" feature is set when building Embedded Swift.
82+
if name == "Embedded" {
83+
return true
84+
}
85+
86+
return try configuration.hasFeature(name: name)
87+
}
88+
89+
func hasAttribute(name: String) throws -> Bool {
90+
return try configuration.hasAttribute(name: name)
91+
}
92+
93+
func canImport(
94+
importPath: [(TokenSyntax, String)],
95+
version: CanImportVersion
96+
) throws -> Bool {
97+
// FIXME: We would prefer to call the underlying canImport in some kind of
98+
// "replay" mode that is not allowed to produce diagnostics or trigger any
99+
// loading.
100+
return false
101+
}
102+
103+
func isActiveTargetOS(name: String) throws -> Bool {
104+
return try configuration.isActiveTargetOS(name: name)
105+
}
106+
107+
func isActiveTargetArchitecture(name: String) throws -> Bool {
108+
return try configuration.isActiveTargetArchitecture(name: name)
109+
}
110+
111+
func isActiveTargetEnvironment(name: String) throws -> Bool {
112+
return try configuration.isActiveTargetEnvironment(name: name)
113+
}
114+
115+
func isActiveTargetRuntime(name: String) throws -> Bool {
116+
return try configuration.isActiveTargetRuntime(name: name)
117+
}
118+
119+
func isActiveTargetPointerAuthentication(name: String) throws -> Bool {
120+
return try configuration.isActiveTargetPointerAuthentication(name: name)
121+
}
122+
123+
var targetPointerBitWidth: Int {
124+
return configuration.targetPointerBitWidth
125+
}
126+
127+
var targetAtomicBitWidths: [Int] {
128+
return configuration.targetAtomicBitWidths
129+
}
130+
131+
var endianness: Endianness {
132+
return configuration.endianness
133+
}
134+
135+
var languageVersion: VersionTuple {
136+
return configuration.languageVersion
137+
}
138+
139+
var compilerVersion: VersionTuple {
140+
return configuration.compilerVersion
141+
}
142+
}

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ public struct ExportedSourceFile {
4343
/// This is a cached value; access via configuredRegions(astContext:).
4444
var _configuredRegions: ConfiguredRegions? = nil
4545

46+
/// Configured regions for this source file assuming if it were being treated
47+
/// as Embedded Swift. This is used only when we are compiling non-Embedded
48+
/// Swift but diagnosing uses of constructs that aren't allowed in Embedded
49+
/// Swift.
50+
///
51+
/// This is a cached value; access via configuredRegionsAsEmbedded(astContext:).
52+
var _configuredRegionsIfEmbedded: ConfiguredRegions? = nil
53+
4654
public func position(of location: SourceLoc) -> AbsolutePosition? {
4755
let sourceFileBaseAddress = UnsafeRawPointer(buffer.baseAddress!)
4856
guard let rawAddress = location.raw else {

lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ add_swift_host_library(swiftSema STATIC
6969
TypeCheckEffects.cpp
7070
TypeCheckExpr.cpp
7171
TypeCheckExprObjC.cpp
72+
TypeCheckEmbedded.cpp
7273
TypeCheckGeneric.cpp
7374
TypeCheckInvertible.cpp
7475
TypeCheckMacros.cpp

lib/Sema/ConstraintSystem.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "OpenedExistentials.h"
2121
#include "TypeCheckAvailability.h"
2222
#include "TypeCheckConcurrency.h"
23+
#include "TypeCheckEmbedded.h"
2324
#include "TypeCheckMacros.h"
2425
#include "TypeCheckType.h"
2526
#include "TypeChecker.h"
@@ -1456,6 +1457,9 @@ FunctionType::ExtInfo ClosureEffectsRequest::evaluate(
14561457
bool sendable = expr->getAttrs().hasAttribute<SendableAttr>();
14571458

14581459
if (throws || async) {
1460+
if (expr->getThrowsLoc().isValid() && !expr->getExplicitThrownTypeRepr())
1461+
diagnoseUntypedThrowsInEmbedded(expr, expr->getThrowsLoc());
1462+
14591463
return ASTExtInfoBuilder()
14601464
.withThrows(throws, /*FIXME:*/Type())
14611465
.withAsync(async)

lib/Sema/TypeCheckAttr.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "TypeCheckAvailability.h"
1919
#include "TypeCheckConcurrency.h"
2020
#include "TypeCheckDistributed.h"
21+
#include "TypeCheckEmbedded.h"
2122
#include "TypeCheckMacros.h"
2223
#include "TypeCheckObjC.h"
2324
#include "TypeCheckType.h"
@@ -5501,12 +5502,14 @@ Type TypeChecker::checkReferenceOwnershipAttr(VarDecl *var, Type type,
55015502
}
55025503

55035504
// Embedded Swift prohibits weak/unowned but allows unowned(unsafe).
5504-
if (ctx.LangOpts.hasFeature(Feature::Embedded)) {
5505+
if (auto behavior = shouldDiagnoseEmbeddedLimitations(
5506+
dc, attr->getLocation(),
5507+
/*wasAlwaysEmbeddedError=*/true)) {
55055508
if (ownershipKind == ReferenceOwnership::Weak ||
55065509
ownershipKind == ReferenceOwnership::Unowned) {
55075510
Diags.diagnose(attr->getLocation(), diag::weak_unowned_in_embedded_swift,
5508-
ownershipKind);
5509-
attr->setInvalid();
5511+
ownershipKind)
5512+
.limitBehavior(*behavior);
55105513
}
55115514
}
55125515

0 commit comments

Comments
 (0)