swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.51k stars 10.35k forks source link

swift-frontend crash when pattern matching a generic consumed noncopyable enum #70727

Open adamkuipers opened 9 months ago

adamkuipers commented 9 months ago

Description

When pattern matching a generic noncopyable enum, the nightly toolchain's swift-frontend crashes. The Xcode 15.1 default toolchain just hangs indefinitely.

If the enum is not generic with a copyable type (e.g., Int) then the code compiles as expected.

If the enum is not generic with a noncopyable type (e.g., struct NoCopy: ~Copyable {}) the the compiler fails with the following:

❯ /Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend -frontend -c LinkedHashMap.swift
LinkedHashMap.swift:23:20: error: copy of noncopyable typed value. This is a compiler bug. Please file a bug with a small example of the bug
    case .some(let v): return v

I came to this error while debugging a what I presume to be another and related ownership compiler bug. Where there would be a partial consumption error pointed to the take() callsite.

Reproduction

enum Box<T>: ~Copyable {
  case some(T)
  case none

  mutating func take() -> Self {
    let old = self
    self = .none
    return old
  }
}

private final class BoxedNode<T> {
  private var box: Box<T>

  init(_ v: T) {
    box = .some(v)
  }

  func consume() -> T {
    switch box.take() {
    case .some(let v): return v
    case .none: fatalError()
    }
  }
}

Build with $NIGHTLY_TOOLCHAIN/swift-frontend -frontend -c LinkedHashMap.swift

As mentioned in the description, if built with a release toolchain (e.g., Xcode default) it just hangs indefinitely.

Stack dump

❯  $TOOLCHAINS/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend -frontend -c LinkedHashMap.swift
Assertion failed: (allSet(filterBitVector, start, next)), function constructFilteredProjections, file FieldSensitivePrunedLiveness.cpp, line 392.
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0.  Program arguments: /Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend -frontend -c LinkedHashMap.swift
1.  Apple Swift version 5.11-dev (LLVM 13124099c3f0229, Swift d6871edc839adec)
2.  Compiling with the current language version
3.  While evaluating request ExecuteSILPipelineRequest(Run pipelines { Mandatory Diagnostic Passes + Enabling Optimization Passes } on SIL for LinkedHashMap)
4.  While running pass #113 SILFunctionTransform "MoveOnlyChecker" on SILFunction "@$s13LinkedHashMap9BoxedNode33_4F2CFA6E40CBEF0A9B941127FADABDE0LLC7consumexyF".
 for 'consume()' (at LinkedHashMap.swift:19:3)
 #0 0x0000000105ab486c (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10561c86c)
 #1 0x0000000105ab2fc8 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10561afc8)
 #2 0x0000000105ab4ebc (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10561cebc)
 #3 0x0000000180c85a24 (/usr/lib/system/libsystem_platform.dylib+0x18046da24)
 #4 0x0000000180c55cc0 (/usr/lib/system/libsystem_pthread.dylib+0x18043dcc0)
 #5 0x0000000180b61a40 (/usr/lib/system/libsystem_c.dylib+0x180349a40)
 #6 0x0000000180b60d30 (/usr/lib/system/libsystem_c.dylib+0x180348d30)
 #7 0x0000000105dea3ec (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x1059523ec)
 #8 0x0000000101429d28 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100f91d28)
 #9 0x000000010142a0ec (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100f920ec)
#10 0x0000000100ee31fc (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100a4b1fc)
#11 0x0000000100ed2b0c (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100a3ab0c)
#12 0x0000000100ecc904 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100a34904)
#13 0x0000000100ef82d4 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100a602d4)
#14 0x0000000100f53a38 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100abba38)
#15 0x0000000100f546d8 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100abc6d8)
#16 0x0000000100f5af14 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100ac2f14)
#17 0x0000000100f51bf4 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100ab9bf4)
#18 0x0000000100f51b7c (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100ab9b7c)
#19 0x0000000100f94ef0 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100afcef0)
#20 0x0000000100f7ca70 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100ae4a70)
#21 0x0000000100f51de4 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100ab9de4)
#22 0x0000000100f7fa58 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100ae7a58)
#23 0x0000000100824980 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10038c980)
#24 0x000000010063502c (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10019d02c)
#25 0x000000010063494c (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10019c94c)
#26 0x0000000100643f80 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x1001abf80)
#27 0x0000000100637320 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10019f320)
#28 0x00000001006362e4 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x10019e2e4)
#29 0x00000001004cfce0 (/Users/akuipers/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swift-frontend+0x100037ce0)
#30 0x00000001808d50e0 
[1]    70632 abort       -frontend -c LinkedHashMap.swift

Expected behavior

I'd expect this to compile. If my understanding of noncopyable types is correct then there should be no ownership issues, just as how it succeeds if one replaces T with Int.

Environment

❯ $TOOLCHAINS/swift-DEVELOPMENT-SNAPSHOT-2023-12-21-a.xctoolchain/usr/bin/swiftc -version
Apple Swift version 5.11-dev (LLVM 13124099c3f0229, Swift d6871edc839adec)
Target: arm64-apple-macosx14.0

Additional information

No response

tbkka commented 9 months ago

CC: @jckarter @kavon

adamkuipers commented 9 months ago

Possibly related, here is the first bug I was debugging before I discovered the crash:

struct Node<Value>: ~Copyable {
    var next: NodePointer<Value>
    var prev: NodePointer<Value>
    var value: Value
}

enum MaybeNode<Value>: ~Copyable {
    case some(Node<Value>)
    case none

    mutating func take() -> Self {
        let old = self
        self = .none
        return old
    }
}

final class NodePointer<Value> {
    var node: MaybeNode<Value>

    init(_ node: consuming Node<Value>) {
        self.node = .some(node)
    }

    func consume() -> Node<Value> {
        guard case .some(let node) = node.take() else {
            fatalError("Can't consumed value already taken.")
        }
        return node
    }
}

This fails to compile giving the following message:

swift:26:43: error: cannot partially consume 'unknown'
        guard case .some(let node) = node.take() else {
                                          ^
error: fatalError

Like the crash, this builds fine when the types are not generic