Open swift-ci opened 6 years ago
Comment by Chris Eidhof (JIRA)
Here's a slightly larger example, in context: https://gist.github.com/chriseidhof/1b758b854ed72096490620a8d6128718
cc @DougGregor
It does indeed seem to be the conditional conformance that's problematic.
Slightly reduced:
protocol P1 {
func f()
}
protocol P2 {
associatedtype Rep
}
struct Rec<A: P2> {}
extension Rec: P1 where A.Rep: P1 {
func f() {}
}
struct Test: P2 {
typealias Rep = Rec<Test>
}
let value = Rec<Test>()
value.f()
The crash is infinite recursion:
...
frame #​75: 0x0000000102ce7acb swift`swift::GenericSignature::enumeratePairedRequirements(this=0x00000001160d6f98, fn=function_ref<bool (swift::Type, llvm::ArrayRef<swift::Requirement>)> @ 0x00007ffeef405f68)>) const at GenericSignature.cpp:447
frame #​76: 0x0000000102ce9f9a swift`swift::GenericSignature::getSubstitutionMap(this=0x00000001160d6f98, subs=swift::TypeSubstitutionFn @ 0x00007ffeef406060, lookupConformance=swift::LookupConformanceFn @ 0x00007ffeef406050)>, llvm::function_ref<llvm::Optional<swift::ProtocolConformanceRef> (swift::CanType, swift::Type, swift::ProtocolType*)>) const at GenericSignature.cpp:493
frame #​77: 0x0000000102e6b8be swift`swift::TypeBase::getContextSubstitutionMap(this=0x00000001160de500, module=0x0000000114820340, dc=0x00000001160ca9d0, genericEnv=0x0000000000000000) at Type.cpp:3325
frame #​78: 0x0000000102dde277 swift`swift::ModuleDecl::lookupConformance(this=0x0000000114820340, type=Type @ 0x00007ffeef406358, protocol=0x00000001160ca238) at Module.cpp:683
frame #​79: 0x0000000102e71c33 swift`swift::LookUpConformanceInModule::operator(this=0x00007ffeef4069f8, dependentType=CanType @ 0x00007ffeef406408, conformingReplacementType=Type @ 0x00007ffeef406400, conformedProtocol=0x00000001160cf070)(swift::CanType, swift::Type, swift::ProtocolType*) const at Type.cpp:2916
frame #​80: 0x0000000102e90635 swift`llvm::Optional<swift::ProtocolConformanceRef> llvm::function_ref<llvm::Optional<swift::ProtocolConformanceRef> (callable=140732912396792, params=CanType @ 0x00007ffeef406450, params=Type @ 0x00007ffeef406448, params=0x00000001160cf070)>::callback_fn<swift::LookUpConformanceInModule>(long, swift::CanType, swift::Type, swift::ProtocolType*) at STLExtras.h:98
frame #​81: 0x0000000102e7dc88 swift`llvm::function_ref<llvm::Optional<swift::ProtocolConformanceRef> (swift::CanType, swift::Type, swift::ProtocolType*)>::operator(this=0x00007ffeef4069a0, params=CanType @ 0x00007ffeef4064c0, params=Type @ 0x00007ffeef4064b8, params=0x00000001160cf070)(swift::CanType, swift::Type, swift::ProtocolType*) const at STLExtras.h:114
frame #​82: 0x0000000102ced90e swift`swift::GenericSignature::getSubstitutionMap(this=0x00007ffeef406968, depTy=Type @ 0x00007ffeef4065c8, reqs=ArrayRef<swift::Requirement> @ 0x00007ffeef4065b8)>, llvm::function_ref<llvm::Optional<swift::ProtocolConformanceRef> (swift::CanType, swift::Type, swift::ProtocolType*)>) const::$_6::operator()(swift::Type, llvm::ArrayRef<swift::Requirement>) const at GenericSignature.cpp:507
frame #​83: 0x0000000102ced67b swift`bool llvm::function_ref<bool (swift::Type, llvm::ArrayRef<swift::Requirement>)>::callback_fn<swift::GenericSignature::getSubstitutionMap(callable=140732912396648, params=Type @ 0x00007ffeef406678, params=ArrayRef<swift::Requirement> @ 0x00007ffeef406668)>, llvm::function_ref<llvm::Optional<swift::ProtocolConformanceRef> (swift::CanType, swift::Type, swift::ProtocolType*)>) const::$_6>(long, swift::Type, llvm::ArrayRef<swift::Requirement>) at STLExtras.h:98
frame #​84: 0x0000000102ce9dda swift`llvm::function_ref<bool (swift::Type, llvm::ArrayRef<swift::Requirement>)>::operator(this=0x00007ffeef4068b8, params=Type @ 0x00007ffeef4066d8, params=ArrayRef<swift::Requirement> @ 0x00007ffeef4066c8)(swift::Type, llvm::ArrayRef<swift::Requirement>) const at STLExtras.h:114
frame #​85: 0x0000000102ce7acb swift`swift::GenericSignature::enumeratePairedRequirements(this=0x00000001160d6f98, fn=function_ref<bool (swift::Type, llvm::ArrayRef<swift::Requirement>)> @ 0x00007ffeef4068b8)>) const at GenericSignature.cpp:447
...
frame #​35017: 0x0000000101b49ae8 swift`swift::CompilerInstance::parseAndCheckTypes(this=0x0000000114808600, implicitImports=0x00007ffeefbfb7c8) at Frontend.cpp:613
frame #​35018: 0x0000000101b4922c swift`swift::CompilerInstance::performSema(this=0x0000000114808600) at Frontend.cpp:459
frame #​35019: 0x00000001000dff76 swift`performCompile(Instance=0x0000000114808600, Invocation=0x00007ffeefbfcf00, Args=ArrayRef<const char *> @ 0x00007ffeefbfbb60, ReturnValue=0x00007ffeefbfc364, observer=0x0000000000000000, Stats=0x0000000000000000) at FrontendTool.cpp:889
frame #​35020: 0x00000001000de21e swift`swift::performFrontend(Args=ArrayRef<const char *> @ 0x00007ffeefbfc590, Argv0="/Users/huon/projects/swift/build/Ninja-DebugAssert/swift-macosx-x86_64/bin/swift", MainAddr=0x000000010000ae00, observer=0x0000000000000000) at FrontendTool.cpp:1782
Notes to future-fixer: the call is trying to build the SpecializedProtocolConformance for Rec<Test> : P1
, which needs to create a SubstitutionMap to substitute into the NormalProtocolConformance for Rec : P1
, but creating that SubstitutionMap means pulling out the ProtocolConformanceRefs for any requirements... including the A.Rep : Show
one. In this case, that requirement is exactly Rec<Test> : P1
, meaning the ProtocolConformanceRef needs to store exactly the SpecializedProtocolConformance we're in the middle of building! A possible approach is making SpecializedProtocolConformance construction lazier/staged: first create the conformance and then fill it in.
Also, this crashes even for non-direct recursion:
protocol P1 {
func f()
}
protocol P2 {
associatedtype Rep
}
struct Rec<A: P2> {}
extension Rec: P1 where A.Rep: P1 {
func f() {}
}
// create a circle
struct Step1: P2 { typealias Rep = Rec<Step2> }
struct Step2: P2 { typealias Rep = Rec<Step3> }
struct Step3: P2 { typealias Rep = Rec<Step4> }
struct Step4: P2 { typealias Rep = Rec<Step5> }
struct Step5: P2 { typealias Rep = Rec<Step6> }
struct Step6: P2 { typealias Rep = Rec<Step1> }
let value = Rec<Step1>()
value.f()
@swift-ci create
Still crashes, now with request evaluator spew:
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: unable to execute command: Illegal instruction: 4
<unknown>:0: error: compile command failed due to signal 4 (use -v to see invocation)
Related to https://github.com/apple/swift/issues/51259 and rdar://69901318
Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug, CompilerCrash, ConditionalConformance | |Assignee | @slavapestov | |Priority | Medium | md5: 59c72f96768a3e17927760f3da82c35dIssue Description:
I managed to crash the compiler without emitting an error message as I was experimenting with some conditional conformance stuff.
I tried to come up with a minimal example, and couldn't make it much shorter than this:
My feeling is that
extension Rec: Show where A.Rep: Show
is what made it break.