Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A typo in a protocol name can crash the compiler under certain conditions #73668

Open
RussBaz opened this issue May 16, 2024 · 0 comments
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software Frontend Area → compiler: Frontend triage needed This issue needs more specific labels type checker Area → compiler: Semantic analysis

Comments

@RussBaz
Copy link

RussBaz commented May 16, 2024

Description

I made a typo in my Vapor project model definition by mistyping Model and this caused a crash. I later managed to distil this crash and recreate it in a standalone repository. Here is the link: https://github.com/RussBaz/SwiftCompilerBug1. Just clone it and run a build command. The compiler will crash.

Please have a look at Sources/App/Models/Todo.swift file. Type checking of the QueryBuilder extension method (constrained to Todo model) in that file crashes the compiler when the Todo model is conforming to a non-existent protocol.

Reproduction

import Fluent
import Foundation

final class Todo: MyModel, @unchecked Sendable {
    static let schema = "todos"

    @ID(key: .id)
    var id: UUID?

    @OptionalField(key: "title")
    var title: String?

    @OptionalField(key: "done_at")
    var doneAt: Date?

    @Parent(key: "user_id")
    var user: User

    @Children(for: \.$todo)
    var items: [TodoItem]

    init() {}

    init(id: UUID? = nil, title: String) {
        self.id = id
        self.title = title
    }
}

extension QueryBuilder where Model == Todo {
    func filterToDos() -> Self {
        join(User.self, on: \User.$id == \Todo.$user.$id)
            .group(.or) { outer in
                outer.filter(Todo.self, \.$title == .null)
                    .filter(Todo.self, \.$doneAt == nil)
            }
            .join(TodoItem.self, on: \TodoItem.$todo.$id == \Todo.$id)
            .filter(Todo.self, \.$title ~~ "another")
    }
}

Stack dump

1.	Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
2.	Compiling with the current language version
3.	While evaluating request TypeCheckSourceFileRequest(source_file "/Users/user/Projects/GitHub/SwiftCompilerBug1/Sources/App/Models/Todo.swift")
4.	While evaluating request TypeCheckFunctionBodyRequest(App.(file).QueryBuilder extension.filterToDos()@/Users/user/Projects/GitHub/SwiftCompilerBug1/Sources/App/Models/Todo.swift:41:10)
5.	While type-checking statement at [/Users/user/Projects/GitHub/SwiftCompilerBug1/Sources/App/Models/Todo.swift:41:32 - line:49:5] RangeText="{
        join(User.self, on: \User.$id == \Todo.$user.$id)
            .group(.or) { outer in
                outer.filter(Todo.self, \.$title == .null)
                    .filter(Todo.self, \.$doneAt == nil)
            }
            .join(TodoItem.self, on: \TodoItem.$todo.$id == \Todo.$id)
            .filter(Todo.self, \.$title ~~ "another")
    "
6.	While type-checking statement at [/Users/user/Projects/GitHub/SwiftCompilerBug1/Sources/App/Models/Todo.swift:42:9 - line:48:53] RangeText="join(User.self, on: \User.$id == \Todo.$user.$id)
            .group(.or) { outer in
                outer.filter(Todo.self, \.$title == .null)
                    .filter(Todo.self, \.$doneAt == nil)
            }
            .join(TodoItem.self, on: \TodoItem.$todo.$id == \Todo.$id)
            .filter(Todo.self, \.$title ~~ "another""
7.	While type-checking expression at [/Users/user/Projects/GitHub/SwiftCompilerBug1/Sources/App/Models/Todo.swift:42:9 - line:48:53] RangeText="join(User.self, on: \User.$id == \Todo.$user.$id)
            .group(.or) { outer in
                outer.filter(Todo.self, \.$title == .null)
                    .filter(Todo.self, \.$doneAt == nil)
            }
            .join(TodoItem.self, on: \TodoItem.$todo.$id == \Todo.$id)
            .filter(Todo.self, \.$title ~~ "another""
8.	While type-checking-target starting at /Users/user/Projects/GitHub/SwiftCompilerBug1/Sources/App/Models/Todo.swift:48:14
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x0000000107bd3f3c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x0000000107bd30f8 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x0000000107bd4544 SignalHandler(int) + 360
3  libsystem_platform.dylib 0x000000018c4c7584 _sigtramp + 56
4  swift-frontend           0x000000010361de88 swift::constraints::DisjunctionStep::~DisjunctionStep() + 44
5  swift-frontend           0x000000010361ca8c swift::constraints::DisjunctionStep::~DisjunctionStep() + 12
6  swift-frontend           0x0000000103605790 swift::constraints::ConstraintSystem::solveImpl(llvm::SmallVectorImpl<swift::constraints::Solution>&) + 1132
7  swift-frontend           0x00000001036c1d0c swift::constraints::ConstraintSystem::salvage() + 212
8  swift-frontend           0x0000000103607a88 swift::constraints::ConstraintSystem::solve(swift::constraints::SyntacticElementTarget&, swift::FreeTypeVariableBinding) + 1756
9  swift-frontend           0x00000001037f3b48 swift::TypeChecker::typeCheckTarget(swift::constraints::SyntacticElementTarget&, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) + 584
10 swift-frontend           0x00000001037f37dc swift::TypeChecker::typeCheckExpression(swift::constraints::SyntacticElementTarget&, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) + 436
11 swift-frontend           0x00000001037f35d4 swift::TypeChecker::typeCheckExpression(swift::Expr*&, swift::DeclContext*, swift::constraints::ContextualTypeInfo, swift::OptionSet<swift::TypeCheckExprFlags, unsigned int>) + 92
12 swift-frontend           0x0000000103907cdc swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*) + 7136
13 swift-frontend           0x0000000103905fc4 bool (anonymous namespace)::StmtChecker::typeCheckStmt<swift::Stmt>(swift::Stmt*&) + 316
14 swift-frontend           0x0000000103901008 (anonymous namespace)::StmtChecker::typeCheckASTNode(swift::ASTNode&) + 104
15 swift-frontend           0x0000000103906224 swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*) + 296
16 swift-frontend           0x0000000103903a6c bool (anonymous namespace)::StmtChecker::typeCheckStmt<swift::BraceStmt>(swift::BraceStmt*&) + 316
17 swift-frontend           0x00000001039027dc swift::TypeCheckFunctionBodyRequest::evaluate(swift::Evaluator&, swift::AbstractFunctionDecl*) const + 732
18 swift-frontend           0x0000000103ce3f68 swift::TypeCheckFunctionBodyRequest::OutputType swift::evaluateOrDefault<swift::TypeCheckFunctionBodyRequest>(swift::Evaluator&, swift::TypeCheckFunctionBodyRequest, swift::TypeCheckFunctionBodyRequest::OutputType) + 884
19 swift-frontend           0x0000000103950520 swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*) const + 608
20 swift-frontend           0x0000000103956988 llvm::Expected<swift::TypeCheckSourceFileRequest::OutputType> swift::Evaluator::getResultUncached<swift::TypeCheckSourceFileRequest>(swift::TypeCheckSourceFileRequest const&) + 664
21 swift-frontend           0x0000000103950240 swift::TypeCheckSourceFileRequest::OutputType swift::evaluateOrDefault<swift::TypeCheckSourceFileRequest>(swift::Evaluator&, swift::TypeCheckSourceFileRequest, swift::TypeCheckSourceFileRequest::OutputType) + 228
22 swift-frontend           0x00000001026e0854 swift::CompilerInstance::performSema() + 196
23 swift-frontend           0x00000001024d5634 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1352
24 swift-frontend           0x00000001024d36d0 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4968
25 swift-frontend           0x0000000102462e8c swift::mainEntry(int, char const**) + 2612
26 dyld                     0x000000018c10e0e0 start + 2360

Expected behavior

Only an error should be raised. The compiler should not crash.

Environment

swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0

macOS: 14.4.1 (23E224)

Additional information

It also happens on the Intel mac.

@RussBaz RussBaz added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. crash Bug: A crash, i.e., an abnormal termination of software triage needed This issue needs more specific labels labels May 16, 2024
@ktoso ktoso added compiler The Swift compiler in itself type checker Area → compiler: Semantic analysis triage needed This issue needs more specific labels Frontend Area → compiler: Frontend and removed triage needed This issue needs more specific labels labels May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software Frontend Area → compiler: Frontend triage needed This issue needs more specific labels type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

2 participants