Skip to content

Commit e50beb0

Browse files
authored
Merge pull request #74962 from DougGregor/typed-throws-backdeploy-fixes
Typed throws backdeploy fixes
2 parents 46256f5 + 21e5066 commit e50beb0

File tree

9 files changed

+92
-3
lines changed

9 files changed

+92
-3
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ class ASTMangler : public Mangler {
8383
/// a critical role.
8484
bool AllowIsolatedAny = true;
8585

86+
/// If enabled, typed throws can be encoded in the mangled name.
87+
/// Suppressing type attributes this way is generally questionable ---
88+
/// for example, it does not interact properly with substitutions ---
89+
/// and should only be done in situations where it is just going to be
90+
/// interpreted as a type and the exact string value does not play
91+
/// a critical role.
92+
bool AllowTypedThrows = true;
93+
8694
/// If enabled, declarations annotated with @_originallyDefinedIn are mangled
8795
/// as if they're part of their original module. Disabled for debug mangling,
8896
/// because lldb wants to find declarations in the modules they're currently

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6737,6 +6737,11 @@ ERROR(availability_isolated_any_only_version_newer, none,
67376737
"%0 %1 or newer",
67386738
(StringRef, llvm::VersionTuple))
67396739

6740+
ERROR(availability_typed_throws_only_version_newer, none,
6741+
"runtime support for typed throws function types is only available in "
6742+
"%0 %1 or newer",
6743+
(StringRef, llvm::VersionTuple))
6744+
67406745
ERROR(availability_variadic_type_only_version_newer, none,
67416746
"parameter packs in generic types are only available in %0 %1 or newer",
67426747
(StringRef, llvm::VersionTuple))

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3062,7 +3062,8 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn,
30623062
if (fn->isSendable())
30633063
appendOperator("Yb");
30643064
if (auto thrownError = fn->getEffectiveThrownErrorType()) {
3065-
if ((*thrownError)->isEqual(fn->getASTContext().getErrorExistentialType())){
3065+
if ((*thrownError)->isEqual(fn->getASTContext().getErrorExistentialType())
3066+
|| !AllowTypedThrows) {
30663067
appendOperator("K");
30673068
} else {
30683069
appendType(*thrownError, sig);

lib/IRGen/IRGenMangler.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,18 +162,23 @@ IRGenMangler::mangleTypeForReflection(IRGenModule &IGM,
162162
llvm::SaveAndRestore<bool> savedConcurrencyStandardSubstitutions(
163163
AllowConcurrencyStandardSubstitutions);
164164
llvm::SaveAndRestore<bool> savedIsolatedAny(AllowIsolatedAny);
165+
llvm::SaveAndRestore<bool> savedTypedThrows(AllowTypedThrows);
165166
if (auto runtimeCompatVersion = getSwiftRuntimeCompatibilityVersionForTarget(
166167
ctx.LangOpts.Target)) {
168+
167169
if (*runtimeCompatVersion < llvm::VersionTuple(5, 5))
168170
AllowConcurrencyStandardSubstitutions = false;
169171

170-
// Suppress @isolated(any) if we're mangling for pre-6.0 runtimes.
172+
// Suppress @isolated(any) and typed throws if we're mangling for pre-6.0
173+
// runtimes.
171174
// This is unprincipled but, because of the restrictions in e.g.
172175
// mangledNameIsUnknownToDeployTarget, should only happen when
173176
// mangling for certain reflective uses where we have to hope that
174177
// the exact type identity is generally unimportant.
175-
if (*runtimeCompatVersion < llvm::VersionTuple(6, 0))
178+
if (*runtimeCompatVersion < llvm::VersionTuple(6, 0)) {
176179
AllowIsolatedAny = false;
180+
AllowTypedThrows = false;
181+
}
177182
}
178183

179184
llvm::SaveAndRestore<bool> savedAllowStandardSubstitutions(

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3023,6 +3023,15 @@ static bool diagnoseIsolatedAnyAvailability(
30233023
ReferenceDC);
30243024
}
30253025

3026+
static bool diagnoseTypedThrowsAvailability(
3027+
SourceRange ReferenceRange, const DeclContext *ReferenceDC) {
3028+
return TypeChecker::checkAvailability(
3029+
ReferenceRange,
3030+
ReferenceDC->getASTContext().getTypedThrowsAvailability(),
3031+
diag::availability_typed_throws_only_version_newer,
3032+
ReferenceDC);
3033+
}
3034+
30263035
static bool checkTypeMetadataAvailabilityInternal(CanType type,
30273036
SourceRange refLoc,
30283037
const DeclContext *refDC) {
@@ -3033,6 +3042,8 @@ static bool checkTypeMetadataAvailabilityInternal(CanType type,
30333042
auto isolation = fnType->getIsolation();
30343043
if (isolation.isErased())
30353044
return diagnoseIsolatedAnyAvailability(refLoc, refDC);
3045+
if (fnType.getThrownError())
3046+
return diagnoseTypedThrowsAvailability(refLoc, refDC);
30363047
}
30373048
return false;
30383049
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %target-swift-frontend -emit-ir -target %target-cpu-apple-macos99.99 %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-PRESENT %s
2+
// RUN: %target-swift-frontend -emit-ir -target %target-cpu-apple-macos14.4 %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-SUPPRESSED %s
3+
4+
// REQUIRES: OS=macosx
5+
// UNSUPPORTED: CPU=arm64e
6+
7+
// Make sure that a dangling-based type description involving typed throws is
8+
// only used when deploying to runtimes that support it.
9+
10+
// Closure capture metadata:
11+
12+
enum MyError: Error {
13+
case fail
14+
}
15+
16+
// CHECK-LABEL: @"\01l__swift5_reflection_descriptor" = private constant
17+
// CHECK-PRESENT-SAME: ptr @"symbolic Si_____Ieghdzo_ 32reflection_metadata_typed_throws7MyErrorO"
18+
// CHECK-SUPPRESSED-SAME: ptr @"symbolic Si_____Ieghdzo_ 32reflection_metadata_typed_throws7MyErrorO"
19+
// CHECK-LABEL: @metadata = private constant %swift.full_boxmetadata { {{.*}}, ptr @"\01l__swift5_reflection_descriptor" }, align
20+
func makeClosure(fn: @escaping @Sendable () throws(MyError) -> Int) -> (() throws(MyError) -> Int) {
21+
return { try fn() + 1 }
22+
}
23+
24+
// Struct field metadata:
25+
26+
public struct MyStruct {
27+
let fn: () throws (MyError) -> ()
28+
}
29+
30+
// CHECK-LABEL: @"$s32reflection_metadata_typed_throws8MyStructVMF" = internal constant
31+
// CHECK-PRESENT-SAME: ptr @"symbolic yy_____YKc 32reflection_metadata_typed_throws7MyErrorO"
32+
// CHECK-SUPPRESSED-SAME: ptr @"get_type_metadata yy32reflection_metadata_typed_throws7MyErrorOYKc.1"

test/IRGen/typed_throws.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,14 @@ public enum MyBigError: Error {
1313
}
1414

1515
// CHECK-MANGLE: @"$s12typed_throws1XVAA1PAAWP" = hidden global [2 x ptr] [ptr @"$s12typed_throws1XVAA1PAAMc", ptr getelementptr inbounds (i8, ptr @"symbolic ySi_____YKc 12typed_throws10MyBigErrorO", {{i32|i64}} 1)]
16+
@available(SwiftStdlib 6.0, *)
1617
struct X: P {
1718
typealias A = (Int) throws(MyBigError) -> Void
1819
}
1920

2021
func requiresP<T: P>(_: T.Type) { }
22+
23+
@available(SwiftStdlib 6.0, *)
2124
func createsP() {
2225
requiresP(X.self)
2326
}
@@ -27,6 +30,7 @@ func createsP() {
2730

2831

2932
// CHECK-LABEL: define {{.*}}hidden swiftcc ptr @"$s12typed_throws13buildMetatypeypXpyF"()
33+
@available(SwiftStdlib 6.0, *)
3034
func buildMetatype() -> Any.Type {
3135
typealias Fn = (Int) throws(MyBigError) -> Void
3236

test/Parse/typed_throws.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func testClosures() {
2020
let _ = { (x: Int, y: Int) throws(MyError) -> Int in x + y }
2121
}
2222

23+
@available(SwiftStdlib 6.0, *)
2324
func testTypes() {
2425
let _ = [(Int, Int) throws(MyError) -> Int]()
2526
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 5 -module-name test
2+
3+
// REQUIRES: OS=macosx
4+
5+
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macos14.4
6+
7+
enum MyError: Error {
8+
case fail
9+
}
10+
11+
func bad() -> Any.Type {
12+
// expected-note@-1{{add @available attribute to enclosing global function}}
13+
typealias Fn = () throws(MyError) -> ()
14+
// expected-error@+2{{runtime support for typed throws function types is only available in macOS 15.0.0 or newer}}
15+
// expected-note@+1{{add 'if #available' version check}}
16+
return Fn.self
17+
}
18+
19+
func good() -> Any.Type {
20+
typealias Fn = () throws(any Error) -> ()
21+
return Fn.self
22+
}

0 commit comments

Comments
 (0)