swiftlang / swift

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

Key path + variadic generics crash #73690

Open vanvoorden opened 3 months ago

vanvoorden commented 3 months ago

Description

import Observation

@Observable final class Repeater<each Parameter, Output> {
  let parameter: (repeat each Parameter)
  var output: Output

  init(
    parameter: (repeat each Parameter),
    output: Output
  ) {
    self.parameter = parameter
    self.output = output
  }
}

let repeater = Repeater(parameter: (1, 2, 3), output: 4)
repeater.output = 5

This is a runtime crash from the 5.10 toolchain and a compiler crash from the 6.0 toolchain.

Here is the runtime crash when building from 5.10 and running on macOS 14.5:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xfffffffffffffffa)
    frame #0: 0x00000001a673c52c libswiftCore.dylib`(anonymous namespace)::DecodedMetadataBuilder::beginPackExpansion(swift::MetadataOrPack) + 228
    frame #1: 0x00000001a6732c04 libswiftCore.dylib`swift::Demangle::__runtime::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::__runtime::Node*, unsigned int, bool) + 1412
    frame #2: 0x00000001a6736c3c libswiftCore.dylib`swift::Demangle::__runtime::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeGenericArgs(swift::Demangle::__runtime::Node*, unsigned int, __swift::__runtime::llvm::SmallVectorImpl<swift::MetadataOrPack>&) + 132
    frame #3: 0x00000001a6732da4 libswiftCore.dylib`swift::Demangle::__runtime::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::__runtime::Node*, unsigned int, bool) + 1828
    frame #4: 0x00000001a672f55c libswiftCore.dylib`swift_getTypeByMangledNodeImpl(swift::MetadataRequest, swift::Demangle::__runtime::Demangler&, swift::Demangle::__runtime::Node*, void const* const*, std::__1::function<void const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 892
    frame #5: 0x00000001a672f100 libswiftCore.dylib`swift_getTypeByMangledNode + 836
    frame #6: 0x00000001a672fbb0 libswiftCore.dylib`swift_getTypeByMangledNameImpl(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<void const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 1172
    frame #7: 0x00000001a6729a84 libswiftCore.dylib`swift_getTypeByMangledName + 836
    frame #8: 0x00000001a6729578 libswiftCore.dylib`swift_getTypeByMangledNameInEnvironment + 176
    frame #9: 0x00000001a64b7e1c libswiftCore.dylib`Swift._resolveKeyPathGenericArgReference(_: Swift.UnsafeRawPointer, genericEnvironment: Swift.Optional<Swift.UnsafeRawPointer>, arguments: Swift.Optional<Swift.UnsafeRawPointer>) -> Swift.UnsafeRawPointer + 268
    frame #10: 0x00000001a64b84f4 libswiftCore.dylib`generic specialization <Swift.GetKeyPathClassAndInstanceSizeFromPattern> of Swift._walkKeyPathPattern<τ_0_0 where τ_0_0: Swift.KeyPathPatternVisitor>(_: Swift.UnsafeRawPointer, walker: inout τ_0_0) -> () + 124
    frame #11: 0x00000001a64b7928 libswiftCore.dylib`Swift._getKeyPathClassAndInstanceSizeFromPattern(Swift.UnsafeRawPointer, Swift.UnsafeRawPointer) -> (keyPathClass: Swift.AnyKeyPath.Type, rootType: Any.Type, size: Swift.Int, alignmentMask: Swift.Int) + 72
    frame #12: 0x00000001a64b76d4 libswiftCore.dylib`Swift._swift_getKeyPath(pattern: Swift.UnsafeMutableRawPointer, arguments: Swift.UnsafeRawPointer) -> Swift.UnsafeRawPointer + 160
  * frame #13: 0x00000001000025b8 RepeaterDemo`Repeater.output.setter(newValue=5, self=<unavailable>) at @__swiftmacro_12RepeaterDemo0A0C6output18ObservationTrackedfMa_.swift:11:29
    frame #14: 0x000000010000242c RepeaterDemo`main at main.swift:20:17
    frame #15: 0x00000001962fa0e0 dyld`start + 2360

Here is the compiler crash when building from 6.0:

1.  Apple Swift version 6.0-dev (LLVM 5b202efbc95a8bf, Swift a17d360d1cc66ab)
2.  Compiling with effective version 5.10
3.  While evaluating request IRGenRequest(IR Generation for file "/Users/rick/Desktop/RepeaterDemo/Sources/main.swift")
4.  While emitting IR SIL function "@$s12RepeaterDemo0A0C6outputq_vs".
 for setter for output (at /Users/rick/Desktop/RepeaterDemo/Sources/main.swift:8:7)
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           0x000000010a2db808 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x000000010a2d9fd4 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x000000010a2dbe50 SignalHandler(int) + 304
3  libsystem_platform.dylib 0x00000001966b3584 _sigtramp + 56
4  libsystem_pthread.dylib  0x0000000196682c20 pthread_kill + 288
5  libsystem_c.dylib        0x000000019658fa30 abort + 180
6  libsystem_c.dylib        0x000000019658ed20 err + 0
7  swift-frontend           0x000000010a37f128 clang::CodeGen::ConstantInitFuture llvm::function_ref<clang::CodeGen::ConstantInitFuture (swift::irgen::ConstantInitBuilder&)>::callback_fn<swift::irgen::IRGenModule::getAddrOfGenericEnvironment(swift::CanGenericSignature)::$_7>(long, swift::irgen::ConstantInitBuilder&) (.cold.5) + 0
8  swift-frontend           0x0000000105310884 clang::CodeGen::ConstantInitFuture llvm::function_ref<clang::CodeGen::ConstantInitFuture (swift::irgen::ConstantInitBuilder&)>::callback_fn<swift::irgen::IRGenModule::getAddrOfGenericEnvironment(swift::CanGenericSignature)::$_7>(long, swift::irgen::ConstantInitBuilder&) + 784
9  swift-frontend           0x000000010541024c swift::irgen::IRGenModule::getAddrOfStringForMetadataRef(llvm::StringRef, unsigned int, bool, llvm::function_ref<clang::CodeGen::ConstantInitFuture (swift::irgen::ConstantInitBuilder&)>) + 232
10 swift-frontend           0x0000000105309a0c swift::irgen::IRGenModule::getAddrOfGenericEnvironment(swift::CanGenericSignature) + 388
11 swift-frontend           0x00000001052c0528 swift::irgen::IRGenModule::getAddrOfKeyPathPattern(swift::KeyPathPattern*, swift::SILLocation) + 636
12 swift-frontend           0x00000001053ad334 (anonymous namespace)::IRGenSILFunction::visitSILBasicBlock(swift::SILBasicBlock*) + 21292
13 swift-frontend           0x00000001053a6e6c (anonymous namespace)::IRGenSILFunction::emitSILFunction() + 9220
14 swift-frontend           0x00000001053a44d4 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 1604
15 swift-frontend           0x000000010524700c swift::irgen::IRGenerator::emitGlobalTopLevel(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&) + 740
16 swift-frontend           0x0000000105356aa8 swift::IRGenRequest::evaluate(swift::Evaluator&, swift::IRGenDescriptor) const + 2172
17 swift-frontend           0x00000001053a3984 swift::GeneratedModule swift::SimpleRequest<swift::IRGenRequest, swift::GeneratedModule (swift::IRGenDescriptor), (swift::RequestFlags)9>::callDerived<0ul>(swift::Evaluator&, std::__1::integer_sequence<unsigned long, 0ul>) const + 200
18 swift-frontend           0x000000010535f15c swift::IRGenRequest::OutputType swift::Evaluator::getResultUncached<swift::IRGenRequest, swift::IRGenRequest::OutputType swift::evaluateOrFatal<swift::IRGenRequest>(swift::Evaluator&, swift::IRGenRequest)::'lambda'()>(swift::IRGenRequest const&, swift::IRGenRequest::OutputType swift::evaluateOrFatal<swift::IRGenRequest>(swift::Evaluator&, swift::IRGenRequest)::'lambda'()) + 212
19 swift-frontend           0x0000000105358b0c swift::performIRGeneration(swift::FileUnit*, swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::GlobalVariable**) + 208
20 swift-frontend           0x0000000104e6d380 generateIR(swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, llvm::GlobalVariable*&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>) + 156
21 swift-frontend           0x0000000104e69624 performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 1416
22 swift-frontend           0x0000000104e68ac8 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 612
23 swift-frontend           0x0000000104e79d38 withSemanticAnalysis(swift::CompilerInstance&, swift::FrontendObserver*, llvm::function_ref<bool (swift::CompilerInstance&)>, bool) + 160
24 swift-frontend           0x0000000104e6b0ec performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 708
25 swift-frontend           0x0000000104e6a058 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 2384
26 swift-frontend           0x0000000104c84350 swift::mainEntry(int, char const**) + 3096
27 dyld                     0x00000001962fa0e0 start + 2360

Reproduction

import Observation

@Observable final class Repeater<each Parameter, Output> {
  let parameter: (repeat each Parameter)
  var output: Output

  init(
    parameter: (repeat each Parameter),
    output: Output
  ) {
    self.parameter = parameter
    self.output = output
  }
}

let repeater = Repeater(parameter: (1, 2, 3), output: 4)
repeater.output = 5

Stack dump

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xfffffffffffffffa)
    frame #0: 0x00000001a673c52c libswiftCore.dylib`(anonymous namespace)::DecodedMetadataBuilder::beginPackExpansion(swift::MetadataOrPack) + 228
    frame #1: 0x00000001a6732c04 libswiftCore.dylib`swift::Demangle::__runtime::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::__runtime::Node*, unsigned int, bool) + 1412
    frame #2: 0x00000001a6736c3c libswiftCore.dylib`swift::Demangle::__runtime::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeGenericArgs(swift::Demangle::__runtime::Node*, unsigned int, __swift::__runtime::llvm::SmallVectorImpl<swift::MetadataOrPack>&) + 132
    frame #3: 0x00000001a6732da4 libswiftCore.dylib`swift::Demangle::__runtime::TypeDecoder<(anonymous namespace)::DecodedMetadataBuilder>::decodeMangledType(swift::Demangle::__runtime::Node*, unsigned int, bool) + 1828
    frame #4: 0x00000001a672f55c libswiftCore.dylib`swift_getTypeByMangledNodeImpl(swift::MetadataRequest, swift::Demangle::__runtime::Demangler&, swift::Demangle::__runtime::Node*, void const* const*, std::__1::function<void const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 892
    frame #5: 0x00000001a672f100 libswiftCore.dylib`swift_getTypeByMangledNode + 836
    frame #6: 0x00000001a672fbb0 libswiftCore.dylib`swift_getTypeByMangledNameImpl(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<void const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 1172
    frame #7: 0x00000001a6729a84 libswiftCore.dylib`swift_getTypeByMangledName + 836
    frame #8: 0x00000001a6729578 libswiftCore.dylib`swift_getTypeByMangledNameInEnvironment + 176
    frame #9: 0x00000001a64b7e1c libswiftCore.dylib`Swift._resolveKeyPathGenericArgReference(_: Swift.UnsafeRawPointer, genericEnvironment: Swift.Optional<Swift.UnsafeRawPointer>, arguments: Swift.Optional<Swift.UnsafeRawPointer>) -> Swift.UnsafeRawPointer + 268
    frame #10: 0x00000001a64b84f4 libswiftCore.dylib`generic specialization <Swift.GetKeyPathClassAndInstanceSizeFromPattern> of Swift._walkKeyPathPattern<τ_0_0 where τ_0_0: Swift.KeyPathPatternVisitor>(_: Swift.UnsafeRawPointer, walker: inout τ_0_0) -> () + 124
    frame #11: 0x00000001a64b7928 libswiftCore.dylib`Swift._getKeyPathClassAndInstanceSizeFromPattern(Swift.UnsafeRawPointer, Swift.UnsafeRawPointer) -> (keyPathClass: Swift.AnyKeyPath.Type, rootType: Any.Type, size: Swift.Int, alignmentMask: Swift.Int) + 72
    frame #12: 0x00000001a64b76d4 libswiftCore.dylib`Swift._swift_getKeyPath(pattern: Swift.UnsafeMutableRawPointer, arguments: Swift.UnsafeRawPointer) -> Swift.UnsafeRawPointer + 160
  * frame #13: 0x00000001000025b8 RepeaterDemo`Repeater.output.setter(newValue=5, self=<unavailable>) at @__swiftmacro_12RepeaterDemo0A0C6output18ObservationTrackedfMa_.swift:11:29
    frame #14: 0x000000010000242c RepeaterDemo`main at main.swift:20:17
    frame #15: 0x00000001962fa0e0 dyld`start + 2360

Expected behavior

let repeater = Repeater(parameter: (1, 2, 3), output: 4)
repeater.output = 5

Observable class compiles and updates at runtime with no crash.

Environment

Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Apple Swift version 6.0-dev (LLVM 5b202efbc95a8bf, Swift a17d360d1cc66ab)

Xcode 15.4 macOS 14.5

Additional information

No response

vanvoorden commented 3 months ago

@phausler hi! would you have any ability to help triage this? would you have any ideas if this looks like something we could maybe have a fix for later this year when 6.0 is released? thanks!

phausler commented 3 months ago

This is a failure associated with key paths not observation per-se.

vanvoorden commented 3 months ago

@slavapestov Does this look related to what landed in https://github.com/apple/swift/pull/67124? Would you have any ability to help triage this? Thanks!

vanvoorden commented 2 months ago

@AnthonyLatsis Would you have any idea if this looks like something we might be able to have a fix for when 6.0 launches later this year? Would you have any time to help triage this? Thanks!

AnthonyLatsis commented 2 months ago

Hi, Rick,

I can definitely help triage this, but I am not familiar enough with the crash site to tell how challenging the problem is. @slavapestov may have a better idea:

Assertion failed: (metadata.GenericPackArguments.empty() && "We don't support packs here yet"), function operator(), file GenProto.cpp, line 4349
AnthonyLatsis commented 2 months ago

Reduced:

struct Foo<each T> {
  let foo: Int

  func test() {
    let kp = \Self.foo
  }
}
slavapestov commented 2 months ago

Yeah, keypaths don't support parameter packs yet. It would take a fair amount of work but certainly should be fixed at some point.

vanvoorden commented 2 months ago
struct Foo<each T> {
  let storage: Storage

  init(foo: Int) {
    self.storage = Storage(foo: foo)
  }

  func test() {
    let _ = self.storage.test()
  }
}

struct Storage {
  let foo: Int

  func test() {
    let kp = \Self.foo
  }
}

Foo<Int>(foo: 0).test()

I'm unblocked (for now) since my use case makes it possible to factor my keypath access out of the outer type (that is generic across a pack).