ellis
(Ellis)
October 25, 2023, 11:30pm
1
I recently came across a Swift crash when trying to create an ObjC protocol function that throws. I managed to find a reproducer and I've reported a github issue. I somehow also managed to find a workaround by using _Nullable
, but I'm not sure how fragile this is. This crash is particularly bad because it crashes even when asserts are disabled.
opened 10:34PM - 25 Oct 23 UTC
bug
triage needed
**Description**
Swift is crashing when trying to compile an ObjC protocol that … throws. The crash seems to go away when `s` has `_Nullable`.
**Steps to reproduce**
```
$ cat foo.h
#import <Foundation/Foundation.h>
@protocol PFoo<NSObject>
- (void)yesCrash:(void (^)(NSString *_Nonnull s, NSError *_Nullable e))completionHandler;
- (void)noCrash:(void (^)(NSString *_Nullable s, NSError *_Nullable e))completionHandler;
@end
$ cat foo.swift
import Foundation
@objc public final class Foo : NSObject, PFoo {
public func yesCrash() async throws -> String { "hi" }
public func noCrash() async throws -> String { "hi" }
}
$ swiftc foo.swift -import-objc-header foo.h -c
```
```
SIL verification failed: EnumInst must return an enum: ud
Verifying instruction:
-> %34 = enum $NSString, #Optional.none!enumelt // user: %36
%36 = apply %30(%34, %35) : $@convention(block) (NSString, Optional<NSError>) -> ()
In function:
// @objc closure #1 in Foo.yesCrash()
sil shared [thunk] [ossa] @$s3foo3FooC8yesCrashSSyYaKFyyYacfU_To : $@convention(thin) @Sendable @async (Optional<@convention(block) (NSString, Optional<NSError>) -> ()>, Foo) -> () {
// %0 // user: %2
// %1 // user: %3
bb0(%0 : @unowned $Optional<@convention(block) (NSString, Optional<NSError>) -> ()>, %1 : @unowned $Foo):
%2 = copy_block %0 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()> // users: %41, %27, %23, %8
%3 = copy_value %1 : $Foo // users: %45, %4
%4 = begin_borrow %3 : $Foo // users: %44, %6
// function_ref Foo.yesCrash()
%5 = function_ref @$s3foo3FooC8yesCrashSSyYaKF : $@convention(method) @async (@guaranteed Foo) -> (@owned String, @error any Error) // user: %6
try_apply %5(%4) : $@convention(method) @async (@guaranteed Foo) -> (@owned String, @error any Error), normal bb1, error bb5 // id: %6
// %7 // users: %24, %13
bb1(%7 : @owned $String): // Preds: bb0
%8 = begin_borrow %2 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()> // users: %22, %9
switch_enum %8 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()>, case #Optional.some!enumelt: bb3, case #Optional.none!enumelt: bb2 // id: %9
bb2: // Preds: bb1
br bb4 // id: %10
// %11 // user: %18
bb3(%11 : @guaranteed $@convention(block) (NSString, Optional<NSError>) -> ()): // Preds: bb1
// function_ref String._bridgeToObjectiveC()
%12 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString // user: %14
%13 = begin_borrow %7 : $String // users: %15, %14
%14 = apply %12(%13) : $@convention(method) (@guaranteed String) -> @owned NSString // users: %20, %16
end_borrow %13 : $String // id: %15
%16 = begin_borrow %14 : $NSString // users: %19, %18
%17 = enum $Optional<NSError>, #Optional.none!enumelt // user: %18
%18 = apply %11(%16, %17) : $@convention(block) (NSString, Optional<NSError>) -> ()
end_borrow %16 : $NSString // id: %19
destroy_value %14 : $NSString // id: %20
br bb4 // id: %21
bb4: // Preds: bb3 bb2
end_borrow %8 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()> // id: %22
destroy_value %2 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()> // id: %23
destroy_value %7 : $String // id: %24
br bb9 // id: %25
// %26 // users: %42, %32
bb5(%26 : @owned $any Error): // Preds: bb0
%27 = begin_borrow %2 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()> // users: %40, %28
switch_enum %27 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()>, case #Optional.some!enumelt: bb7, case #Optional.none!enumelt: bb6 // id: %28
bb6: // Preds: bb5
br bb8 // id: %29
// %30 // user: %36
bb7(%30 : @guaranteed $@convention(block) (NSString, Optional<NSError>) -> ()): // Preds: bb5
// function_ref _convertErrorToNSError(_:)
%31 = function_ref @$s10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF : $@convention(thin) (@guaranteed any Error) -> @owned NSError // user: %32
%32 = apply %31(%26) : $@convention(thin) (@guaranteed any Error) -> @owned NSError // user: %33
%33 = enum $Optional<NSError>, #Optional.some!enumelt, %32 : $NSError // users: %38, %35
%34 = enum $NSString, #Optional.none!enumelt // user: %36
%35 = begin_borrow %33 : $Optional<NSError> // users: %37, %36
%36 = apply %30(%34, %35) : $@convention(block) (NSString, Optional<NSError>) -> ()
end_borrow %35 : $Optional<NSError> // id: %37
destroy_value %33 : $Optional<NSError> // id: %38
br bb8 // id: %39
bb8: // Preds: bb7 bb6
end_borrow %27 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()> // id: %40
destroy_value %2 : $Optional<@convention(block) (NSString, Optional<NSError>) -> ()> // id: %41
destroy_value %26 : $any Error // id: %42
br bb9 // id: %43
bb9: // Preds: bb8 bb4
end_borrow %4 : $Foo // id: %44
destroy_value %3 : $Foo // id: %45
return undef : $() // id: %46
} // end
```
**Expected behavior**
The code should compile without issues.
**Environment**
- Swift compiler version info 1.75.2 Apple Swift version 5.8.1 (swiftlang-5.8.0.124.5 clang-1403.0.22.11.100)
- Xcode version info Xcode 14.3.1
- Deployment target: iOS 13.4
Somewhat related, a while back I also reported a crash in TypeCheckStmt.cpp
. I did find a workaround to be explicitly setting the optional to nil
, but that triggers a swift lint redundant_optional_initialization
. Today I'm seeing this workaround littered throughout our source in several places.
opened 09:10PM - 04 Mar 22 UTC
bug
compiler
type checker
SILGen
crash
property wrappers
attributes
swift 5.9
@autoclosure
assertion failure
| | |
|------------------|-----------------… |
|Previous ID | SR-15940 |
|Radar | None |
|Original Reporter | ellis (JIRA User) |
|Type | Bug |
<details>
<summary>Additional Detail from JIRA</summary>
| | |
|------------------|-----------------|
|Votes | 0 |
|Component/s | |
|Labels | Bug |
|Assignee | None |
|Priority | Medium |
md5: c0318b50fadbb361c90032f67b6a66fb
</details>
**Issue Description:**
Swift crashes when compiling the following source.
```swift
@propertyWrapper
public class Bar<Value> {
public init(wrappedValue: @autoclosure () -> Value) {}
public var wrappedValue: Value {}
}
class Foo {
@Bar var a: Bool?
}
```
Here is the backtrace
```
error: compile command failed due to signal 6 (use -v to see invocation)
test.swift:4:35: error: computed property must have accessors specified
public var wrappedValue: Value {}
^
swift-frontend: swift/lib/Sema/TypeCheckStmt.cpp:86: virtual std::pair<bool, Expr *> (anonymous namespace)::ContextualizeClosures::walkToExprPre(swift::Expr *): Assertion `CE->getDiscriminator() == AutoClosureExpr::InvalidDiscriminator' failed.
Please submit a bug report (<https://swift.org/contributing/#reporting-bugs)> and include the project and the crash backtrace.
Stack dump:
0. Program arguments: swift-frontend -frontend -c -primary-file test.swift -target arm64-apple-ios11.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -color-diagnostics -new-driver-path /swift-driver -resource-dir swift -module-name EmojiPickerLayout -target-sdk-version 15.2 -o /tmp/TemporaryDirectory.qXz2A9/EmojiPickerLayout-1.o
1. Swift version 5.6-dev (LLVM a5fb80477a008fd, Swift c2abee2cb7c2471)
2. Compiling with the current language version
3. While evaluating request TypeCheckSourceFileRequest(source_file "test.swift")
4. While type-checking 'Foo' (at test.swift:7:1)
5. While type-checking declaration 0x8841d80 (in module 'EmojiPickerLayout')
#0 0x0000000007d136f3 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) llvm-project/llvm/lib/Support/Unix/Signals.inc:565:13
#1 0x0000000007d11a50 llvm::sys::RunSignalHandlers() llvm-project/llvm/lib/Support/Signals.cpp:98:18
#2 0x0000000007d13a7f SignalHandler(int) llvm-project/llvm/lib/Support/Unix/Signals.inc:407:1
#3 0x00007f72a1d3f130 __restore_rt (/usr/local/fbcode/platform009/lib/libpthread.so.0+0x15130)
#4 0x00007f72a17d2530 raise /home/engshare/third-party2/glibc/2.30/src/glibc-2.30/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
#5 0x00007f72a17b951d abort /home/engshare/third-party2/glibc/2.30/src/glibc-2.30/stdlib/abort.c:81:7
#6 0x00007f72a17c94c3 __assert_fail_base /home/engshare/third-party2/glibc/2.30/src/glibc-2.30/assert/assert.c:89:7
#7 0x00007f72a17c9533 (/usr/local/fbcode/platform009/lib/libc.so.6+0x35533)
#8 0x00000000040db1cf swift::AbstractClosureExpr::setDiscriminator(unsigned int) swift/include/swift/AST/Expr.h:3610:5
#9 0x00000000040db1cf (anonymous namespace)::ContextualizeClosures::walkToExprPre(swift::Expr*) swift/lib/Sema/TypeCheckStmt.cpp:87:13
#10 0x00000000043404af (anonymous namespace)::Traversal::doIt(swift::Expr*) swift/lib/AST/ASTWalker.cpp:1197:14
#11 0x00000000043404af (anonymous namespace)::Traversal::doIt(swift::ArgumentList*) swift/lib/AST/ASTWalker.cpp:1360:17
#12 0x00000000043432cd (anonymous namespace)::Traversal::visitApplyExpr(swift::ApplyExpr*) swift/lib/AST/ASTWalker.cpp:856:15
#13 0x000000000433f891 (anonymous namespace)::Traversal::SetParentRAII::~SetParentRAII() swift/lib/AST/ASTWalker.cpp:93:21
#14 0x000000000433f891 (anonymous namespace)::Traversal::visit(swift::Expr*) swift/lib/AST/ASTWalker.cpp:100:3
#15 0x000000000433f891 (anonymous namespace)::Traversal::doIt(swift::Expr*) swift/lib/AST/ASTWalker.cpp:1201:9
#16 0x000000000433f891 swift::Expr::walk(swift::ASTWalker&) swift/lib/AST/ASTWalker.cpp:1891:28
#17 0x00000000040d64ab swift::TypeChecker::contextualizeInitializer(swift::Initializer*, swift::Expr*) swift/lib/Sema/TypeCheckStmt.cpp:202:1
#18 0x0000000004024715 (anonymous namespace)::DeclChecker::visitPatternBindingDecl(swift::PatternBindingDecl*) swift/lib/Sema/TypeCheckDeclPrimary.cpp:2088:13
#19 0x0000000004024715 swift::ASTVisitor<(anonymous namespace)::DeclChecker, void, void, void, void, void, void>::visit(swift::Decl*) swift/include/swift/AST/DeclNodes.def:185:1
#20 0x0000000004024715 (anonymous namespace)::DeclChecker::visit(swift::Decl*) swift/lib/Sema/TypeCheckDeclPrimary.cpp:1697:31
#21 0x000000000402a1ac (anonymous namespace)::DeclChecker::visitClassDecl(swift::ClassDecl*) swift/lib/Sema/TypeCheckDeclPrimary.cpp:2478:23
#22 0x0000000004023aeb swift::ASTVisitor<(anonymous namespace)::DeclChecker, void, void, void, void, void, void>::visit(swift::Decl*) swift/include/swift/AST/DeclNodes.def:0:9
#23 0x0000000004023aeb (anonymous namespace)::DeclChecker::visit(swift::Decl*) swift/lib/Sema/TypeCheckDeclPrimary.cpp:1697:31
#24 0x000000000402383e swift::TypeChecker::typeCheckDecl(swift::Decl*, bool) swift/lib/Sema/TypeCheckDeclPrimary.cpp:3186:1
#25 0x000000000410e267 swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*) const swift/lib/Sema/TypeChecker.cpp:336:17
#26 0x0000000004110258 llvm::Expected<swift::TypeCheckSourceFileRequest::OutputType> swift::Evaluator::getResultUncached<swift::TypeCheckSourceFileRequest>(swift::TypeCheckSourceFileRequest const&) swift/include/swift/AST/Evaluator.h:362:14
#27 0x000000000410ff72 llvm::Expected<std::tuple<> >::operator bool() llvm-project/llvm/include/llvm/Support/Error.h:564:17
#28 0x000000000410ff72 llvm::Expected<swift::TypeCheckSourceFileRequest::OutputType> swift::Evaluator::getResultCached<swift::TypeCheckSourceFileRequest, (void*)0>(swift::TypeCheckSourceFileRequest const&) swift/include/swift/AST/Evaluator.h:393:10
#29 0x000000000410e0c4 llvm::Expected<std::tuple<> >::takeError() llvm-project/llvm/include/llvm/Support/Error.h:592:15
#30 0x000000000410e0c4 swift::TypeCheckSourceFileRequest::OutputType swift::evaluateOrDefault<swift::TypeCheckSourceFileRequest>(swift::Evaluator&, swift::TypeCheckSourceFileRequest, swift::TypeCheckSourceFileRequest::OutputType) swift/include/swift/AST/Evaluator.h:106:25
#31 0x000000000410e06e swift::performTypeChecking(swift::SourceFile&) swift/lib/Sema/TypeChecker.cpp:286:3
#32 0x000000000321ab3a swift::CompilerInstance::forEachFileToTypeCheck(llvm::function_ref<void (swift::SourceFile&)>) swift/lib/Frontend/Frontend.cpp:1138:19
#33 0x000000000321aa08 _*gnu_cxx::normal_iterator<unsigned int const*, std::vector<unsigned int, std::allocator<unsigned int> > >::*_normal_iterator(unsigned int const* const&) /mnt/gvfs/third-party2/libgcc/9ec50d4571ff7613c2a4dc750831a6d1cb86995f/9.x/platform009/9202ce7/include/c++/9.x/bits/stl_iterator.h:808:20
#34 0x000000000321aa08 std::vector<unsigned int, std::allocator<unsigned int> >::begin() const /mnt/gvfs/third-party2/libgcc/9ec50d4571ff7613c2a4dc750831a6d1cb86995f/9.x/platform009/9202ce7/include/c++/9.x/bits/stl_vector.h:818:16
#35 0x000000000321aa08 std::vector<unsigned int, std::allocator<unsigned int> >::empty() const /mnt/gvfs/third-party2/libgcc/9ec50d4571ff7613c2a4dc750831a6d1cb86995f/9.x/platform009/9202ce7/include/c++/9.x/bits/stl_vector.h:1005:16
#36 0x000000000321aa08 llvm::SetVector<unsigned int, std::vector<unsigned int, std::allocator<unsigned int> >, llvm::DenseSet<unsigned int, llvm::DenseMapInfo<unsigned int> > >::empty() const llvm-project/llvm/include/llvm/ADT/SetVector.h:73:20
#37 0x000000000321aa08 swift::CompilerInstance::isWholeModuleCompilation() const swift/include/swift/Frontend/Frontend.h:454:67
#38 0x000000000321aa08 swift::CompilerInstance::forEachFileToTypeCheck(llvm::function_ref<void (swift::SourceFile&)>) swift/lib/Frontend/Frontend.cpp:1129:7
#39 0x000000000321aa08 swift::CompilerInstance::finishTypeChecking() swift/lib/Frontend/Frontend.cpp:1145:3
#40 0x000000000321aa08 swift::CompilerInstance::performSema() swift/lib/Frontend/Frontend.cpp:1070:3
#41 0x000000000308123b withSemanticAnalysis(swift::CompilerInstance&, swift::FrontendObserver*, llvm::function_ref<bool (swift::CompilerInstance&)>) swift/lib/FrontendTool/FrontendTool.cpp:1108:7
#42 0x000000000307838d performAction(swift::CompilerInstance&, int&, swift::FrontendObserver*) swift/lib/FrontendTool/FrontendTool.cpp:0:12
#43 0x000000000307838d performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) swift/lib/FrontendTool/FrontendTool.cpp:1306:19
#44 0x00000000030778f6 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) swift/lib/FrontendTool/FrontendTool.cpp:2080:46
#45 0x0000000003045f83 swift::mainEntry(int, char const**) swift/lib/DriverTool/driver.cpp:405:12
#46 0x00007f72a17b9dc5 __libc_start_main /home/engshare/third-party2/glibc/2.30/src/glibc-2.30/csu/../csu/libc-start.c:308:16
#47 0x000000000304590a _start /home/engshare/third-party2/glibc/2.30/src/glibc-2.30/csu/../sysdeps/x86_64/start.S:122:0
```
This second issue has been open for a while. How can I get more visibility on these bugs so they can get fixed?
3 Likes