You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Creating a Dictionary or Set with an element type containing a type parameter pack consisting of only a single class type crashes the compiler in release builds
#73219
Open
lukaskollmer opened this issue
Apr 24, 2024
· 1 comment
lukaskollmer opened this issue
Apr 24, 2024
· 1 comment
Labels
bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.crashBug: A crash, i.e., an abnormal termination of softwaregenericsFeature: generic declarations and types
Attempting to create an instance of a Set or a Dictionary where the generic parameter (Element in the case of the Set, and Key in the case of the Dictionary) is a Hashable type that uses variadic generics and is passed a single class type as its type parameter pack, crashes the compiler in a release build. (Sometimes also depending on if the Set or Dictionary is created using a literal.)
See the example program below: it defines several variables (sets and dictionaries) with different parameters for the generic parameter, and using different ways of initialising the values (using a literal and using .init()).
When compiled with a debug build, the entire program will compile without any issues. But in a release build, the compiler will crash if the program contains at least one instantiation of Set or Dictionary where the Hashable generic parameter is HashableTuple<C>.
For some reason, this only happens when HashableTuple's parameter pack consists of a single class type. If a struct type is specified instead, or multiple class types, or a mix of class and struct types, everything seems to work just fine.
I also tried defining a custom type with a Hashable-constrained generic parameter that implements ExpressibleByArrayLiteral, but for some reason instantiating that instead of eg Set worked fine (ie, didn't crash the compiler).
Reproduction
func zip<eachT,eachU>(_ firsts:(repeat eachT), _ seconds:(repeat eachU))->(repeat (eachT,eachU)){return(repeat (each firsts,each seconds))}/// Determines if two tuples of arbitrary length are equal.func==<eachT:Equatable>(_ lhs:(repeat eachT), _ rhs:(repeat eachT))->Bool{letzipped=zip((repeat each lhs),(repeat each rhs))varequal= true
func imp<U:Equatable>(_ input:(U,U)){
equal = equal && input.0== input.1}
repeat imp(each zipped)return equal
}structHashableTuple<eachT:Hashable>:Hashable{varelements:(repeat eachT)func hash(into hasher:inoutHasher){(repeat (each elements).hash(into:&hasher))}staticfunc==(lhs:Self, rhs:Self)->Bool{return(repeat each lhs.elements)==(repeat each rhs.elements)}}classC:Hashable{func hash(into hasher:inoutHasher){
hasher.combine(ObjectIdentifier(self))}staticfunc==(lhs:C, rhs:C)->Bool{returnObjectIdentifier(lhs)==ObjectIdentifier(rhs)}}structS:Hashable{}// all of the following will fail (replace C with S, or add additional types to make it compile...)varset1:Set<HashableTuple<C>>=[]vardict1:[HashableTuple<C>:Void]=[:]// all of these are finevarset2:Set<HashableTuple<C>>=.init()vardict2:[HashableTuple<C>:Void]=.init()varset3:Set<HashableTuple<C,C>>=[]vardict3:[HashableTuple<C,C>:Void]=[:]
Stack dump
error: compile command failed due to signal 11 (use -v to see invocation)
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0. Program arguments: /Applications/Xcode-15.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -frontend -c -primary-file x.swift -target arm64-apple-macosx14.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -stack-check -sdk /Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk -color-diagnostics -O -new-driver-path /Applications/Xcode-15.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-driver -empty-abi-descriptor -resource-dir /Applications/Xcode-15.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift -module-name x -disable-clang-spi -target-sdk-version 14.4 -target-sdk-name macosx14.4 -external-plugin-path /Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/usr/lib/swift/host/plugins#/Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/usr/local/lib/swift/host/plugins#/Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib/swift/host/plugins#/Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/local/lib/swift/host/plugins#/Applications/Xcode-15.3.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -plugin-path /Applications/Xcode-15.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Applications/Xcode-15.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/lib/swift/host/plugins -enable-default-cmo -o /var/folders/72/gdk4ykgs6bdg2kds9pynlhzc0000gn/T/TemporaryDirectory.baPUSv/x-1.o
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 ExecuteSILPipelineRequest(Run pipelines { PrepareOptimizationPasses, EarlyModulePasses, HighLevel,Function+EarlyLoopOpt, HighLevel,Module+StackPromote, MidLevel,Function, ClosureSpecialize, LowLevel,Function, LateLoopOpt, SIL Debug Info Generator } on SIL for x)
4. While running pass #17655 SILFunctionTransform "DCE" on SILFunction "@$ss22__RawDictionaryStorageC4find_9hashValues10_HashTableV6BucketV6bucket_Sb5foundtx_SitSHRzlF1x13HashableTupleVyAK1CC_QPG_Tg5".
for <<debugloc at "<compiler-generated>":0:0>>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 0x000000010841ff3c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1 swift-frontend 0x000000010841f0f8 llvm::sys::RunSignalHandlers() + 112
2 swift-frontend 0x0000000108420544 SignalHandler(int) + 360
3 libsystem_platform.dylib 0x000000018cec5a24 _sigtramp + 56
4 swift-frontend 0x000000010381aacc (anonymous namespace)::DCE::markValueLive(swift::SILValue) + 424
5 swift-frontend 0x000000010381aacc (anonymous namespace)::DCE::markValueLive(swift::SILValue) + 424
6 swift-frontend 0x000000010381793c (anonymous namespace)::DCEPass::run() + 3788
7 swift-frontend 0x000000010375ba68 swift::SILPassManager::runFunctionPasses(unsigned int, unsigned int) + 3856
8 swift-frontend 0x0000000103754a0c swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 240
9 swift-frontend 0x0000000103791354 swift::SimpleRequest<swift::ExecuteSILPipelineRequest, std::__1::tuple<> (swift::SILPipelineExecutionDescriptor), (swift::RequestFlags)1>::evaluateRequest(swift::ExecuteSILPipelineRequest const&, swift::Evaluator&) + 56
10 swift-frontend 0x0000000103775184 llvm::Expected<swift::ExecuteSILPipelineRequest::OutputType> swift::Evaluator::getResultUncached<swift::ExecuteSILPipelineRequest>(swift::ExecuteSILPipelineRequest const&) + 476
11 swift-frontend 0x0000000103777e94 swift::runSILOptimizationPasses(swift::SILModule&) + 504
12 swift-frontend 0x0000000102f2d16c swift::CompilerInstance::performSILProcessing(swift::SILModule*) + 1224
13 swift-frontend 0x0000000102d1df98 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*) + 1128
14 swift-frontend 0x0000000102d1d444 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 608
15 swift-frontend 0x0000000102d21694 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1448
16 swift-frontend 0x0000000102d1f6d0 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4968
17 swift-frontend 0x0000000102caee8c swift::mainEntry(int, char const**) + 2612
18 dyld 0x000000018cb150e0 start + 2360
error: fatalError
Expected behavior
IMO this should compile just fine.
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
Additional information
i also tried this with the nightly compiler, which also crashed.
The text was updated successfully, but these errors were encountered:
lukaskollmer
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
Apr 24, 2024
Having looked into this a bit more (and spent some more time trying to work around this issue), it seems like this is in fact not caused by the use of set/dictionary literals, but rather is somehow directly related to the use of a single class type in the generic type parameter pack?
To provide some more context, the HashableTuple defined above is used as part of a memoize function:
func memoize<eachInput:Hashable,Output>(_ fn:@escaping(repeat eachInput)->Output)->(repeat eachInput)->Output{varcache:[HashableTuple<repeat eachInput>:Output]=.init()return{(input: repeat eachInput)->Outputinletkey=HashableTuple(elements:(repeat each input))// rest omitted bc not relevant}}
even though declaring and initializing a dict as a global variable using .init() works (as seen in the original post), it still fails when done within a function.
As with the initial issue, this seems to happen only if the type using a generic type parameter pack (HashableTuple in this case) is instantiated using only a single class type parameter.
Simply always adding an implicit trailing non-class type parameter to the pack (and thereby ensuring it never consists of only a single class type) seems to work around this issue:
privatestructEmptyStruct:Hashable{}func memoize<eachInput:Hashable,Output>(_ fn:@escaping(repeat eachInput)->Output)->(repeat eachInput)->Output{varcache:[HashableTuple<repeat eachInput,EmptyStruct>:Output]=[:]// <--return{(input: repeat eachInput)->Outputinletkey=HashableTuple(elements:(repeat each input,EmptyStruct()))// <--// rest omitted bc not relevant}}
lukaskollmer
changed the title
Creating a Dictionary or Set with an element type containing a type parameter pack via a literal crashes the compiler in release builds
Creating a Dictionary or Set with an element type containing a type parameter pack consisting of only a single class type crashes the compiler in release builds
Apr 24, 2024
bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.crashBug: A crash, i.e., an abnormal termination of softwaregenericsFeature: generic declarations and types
Description
Attempting to create an instance of a
Set
or aDictionary
where the generic parameter (Element
in the case of theSet
, andKey
in the case of theDictionary
) is a Hashable type that uses variadic generics and is passed a single class type as its type parameter pack, crashes the compiler in a release build. (Sometimes also depending on if the Set or Dictionary is created using a literal.)See the example program below: it defines several variables (sets and dictionaries) with different parameters for the generic parameter, and using different ways of initialising the values (using a literal and using
.init()
).When compiled with a debug build, the entire program will compile without any issues. But in a release build, the compiler will crash if the program contains at least one instantiation of
Set
orDictionary
where the Hashable generic parameter isHashableTuple<C>
.For some reason, this only happens when
HashableTuple
's parameter pack consists of a single class type. If a struct type is specified instead, or multiple class types, or a mix of class and struct types, everything seems to work just fine.I also tried defining a custom type with a Hashable-constrained generic parameter that implements ExpressibleByArrayLiteral, but for some reason instantiating that instead of eg Set worked fine (ie, didn't crash the compiler).
Reproduction
Stack dump
Expected behavior
IMO this should compile just fine.
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
Additional information
i also tried this with the nightly compiler, which also crashed.
The text was updated successfully, but these errors were encountered: