Reproducible Crash in Type-Checker

The following snippet of code reliably crashes the type checker. Is there something obviously wrong here? Changing String.self to NSString.self resolves the issue.

import Foundation

class MyDecoder {
  
  private let coder = NSKeyedArchiver(requiringSecureCoding: true)

  func decode(_ key: String, into storage: inout String) {
    storage = coder.decodeObject(of: [String.self], forKey: key) as! String
  }
}

Console Output:

1.	Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53)
2.	While evaluating request TypeCheckSourceFileRequest(source_file "Untitled.swift", 0)
3.	While evaluating request TypeCheckFunctionBodyUntilRequest(Untitled.(file).MyDecoder.decode(_:into:)@Untitled.swift:7:8, )
4.	While type-checking 'decode(_:into:)' (at Untitled.swift:7:3)
5.	While type-checking statement at [Untitled.swift:7:58 - line:9:3] RangeText="{
    storage = coder.decodeObject(of: [String.self], forKey: key) as! String
  "
6.	While type-checking expression at [Untitled.swift:8:5 - line:8:70] RangeText="storage = coder.decodeObject(of: [String.self], forKey: key) as! "
0  swift                    0x000000011002a4ea PrintStackTraceSignalHandler(void*) + 42
1  swift                    0x0000000110029cc0 SignalHandler(int) + 352
2  libsystem_platform.dylib 0x00007fff6f4bc5fd _sigtramp + 29
3  libsystem_platform.dylib 000000000000000000 _sigtramp + 2427730464
4  swift                    0x000000010c85131e swift::constraints::MissingConformance::diagnose(bool) const + 382
5  swift                    0x000000010c797cf9 swift::constraints::ConstraintSystem::applySolution(swift::constraints::Solution&, swift::Expr*, swift::Type, bool, bool) + 5849
6  swift                    0x000000010c95b1f9 swift::TypeChecker::typeCheckExpressionImpl(swift::Expr*&, swift::DeclContext*, swift::TypeLoc, swift::ContextualTypePurpose, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>, swift::ExprTypeCheckListener&, swift::constraints::ConstraintSystem*) + 1033
7  swift                    0x000000010ca2a255 swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*) + 7893
8  swift                    0x000000010ca27d19 bool (anonymous namespace)::StmtChecker::typeCheckStmt<swift::BraceStmt>(swift::BraceStmt*&) + 121
9  swift                    0x000000010ca1fc6f swift::SimpleRequest<swift::TypeCheckFunctionBodyUntilRequest, bool (swift::AbstractFunctionDecl*, swift::SourceLoc), (swift::CacheKind)1>::evaluateRequest(swift::TypeCheckFunctionBodyUntilRequest const&, swift::Evaluator&) + 2879
10 swift                    0x000000010ca264de swift::TypeCheckFunctionBodyUntilRequest::OutputType swift::evaluateOrDefault<swift::TypeCheckFunctionBodyUntilRequest>(swift::Evaluator&, swift::TypeCheckFunctionBodyUntilRequest, swift::TypeCheckFunctionBodyUntilRequest::OutputType) + 718
11 swift                    0x000000010ca5521e swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*, unsigned int) const + 6270
12 swift                    0x000000010ca244b7 swift::SimpleRequest<swift::TypeCheckSourceFileRequest, bool (swift::SourceFile*, unsigned int), (swift::CacheKind)2>::evaluateRequest(swift::TypeCheckSourceFileRequest const&, swift::Evaluator&) + 23
13 swift                    0x000000010ca52b1e swift::performTypeChecking(swift::SourceFile&, unsigned int) + 1006
14 swift                    0x000000010c0867eb swift::CompilerInstance::performSemaUpTo(swift::SourceFile::ASTStage_t) + 5915
15 swift                    0x000000010bd729b9 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 10281
16 swift                    0x000000010bcf3b73 main + 1283
17 libdyld.dylib            0x00007fff6f2c3cc9 start + 1
18 libdyld.dylib            0x000000000000000f start + 2429797191
<unknown>:0: error: unable to execute command: Segmentation fault: 11
<unknown>:0: error: compile command failed due to signal 11 (use -v to see invocation)

Is there something obviously wrong here?

Well, yes, the compiler should never crash, regardless of what code you throw at it. Please file a bug about that, and post your bug number here, just for the record.

As to what’s triggering the crash, it’s your use of String.self. A keyed archiver only works for objects and String isn’t an object. If you replace String with NSString, it no longer crashes.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

Looks like this has been fixed on master; it prints an error.

error: cannot convert value of type 'String.Type' to expected element type 'AnyClass' (aka 'AnyObject.Type')
    storage = coder.decodeObject(of: [String.self], forKey: key) as! String
                                      ^

FWIW, you can also test code with a recent Swift on godbolt. :slightly_smiling_face: Might be helpful in case you see another crash later.

1 Like