diff --git a/stdlib/public/core/EmbeddedRuntime.swift b/stdlib/public/core/EmbeddedRuntime.swift index 187e9ab55be..a1f3d2a8b75 100644 --- a/stdlib/public/core/EmbeddedRuntime.swift +++ b/stdlib/public/core/EmbeddedRuntime.swift @@ -272,11 +272,19 @@ public func swift_dynamicCastClass(object: UnsafeMutableRawPointer, targetMetada public func swift_dynamicCastClassUnconditional(object: UnsafeMutableRawPointer, targetMetadata: UnsafeRawPointer, file: UnsafePointer, line: CUnsignedInt, column: CUnsignedInt) -> UnsafeMutableRawPointer { guard let result = swift_dynamicCastClass(object: object, targetMetadata: targetMetadata) else { - Builtin.int_trap() + fatalError("failed cast") } return result } +@_cdecl("swift_isEscapingClosureAtFileLocation") +public func swift_isEscapingClosureAtFileLocation(object: Builtin.RawPointer, filename: UnsafePointer, filenameLength: Int32, line: Int32, column: Int32, verificationType: CUnsignedInt) -> Bool { + guard swift_isUniquelyReferenced_native(object: object) else { + fatalError("non-escaping closure escaped") + } + return false +} + @_cdecl("swift_isUniquelyReferenced_native") public func swift_isUniquelyReferenced_native(object: Builtin.RawPointer) -> Bool { if !isValidPointerForNativeRetain(object: object) { return false } diff --git a/test/embedded/without-actually-escaping.swift b/test/embedded/without-actually-escaping.swift new file mode 100644 index 00000000000..a478440a33c --- /dev/null +++ b/test/embedded/without-actually-escaping.swift @@ -0,0 +1,41 @@ +// RUN: %empty-directory(%t) +// RUN: %target-clang -x c -c %S/Inputs/unbuffered-putchar.c -o %t/unbuffered-putchar.o + +// RUN: %target-build-swift -enable-experimental-feature Embedded -wmo %s -Xlinker %t/unbuffered-putchar.o -o %t/a.out +// RUN: not --crash %t/a.out 2>&1 | %FileCheck %s + +// REQUIRES: swift_in_compiler +// REQUIRES: executable_test +// REQUIRES: swift_feature_Embedded + +var sink: ()->() = {} + +func dontEscape(f: () -> ()) { + withoutActuallyEscaping(f) { + $0() + } +} + +func dontEscape2(f: () -> ()) { + withoutActuallyEscaping(f) { + sink = $0 + sink() + sink = {} + } +} + +func letEscape(f: () -> ()) { + withoutActuallyEscaping(f) { + sink = $0 + sink() + } +} + +dontEscape(f: { print("A") }) +dontEscape2(f: { print("B") }) +letEscape(f: { print("C") }) + +// CHECK: A +// CHECK: B +// CHECK: C +// CHECK: non-escaping closure escaped