Compiler crash with complex protocol with associated types (ConcreteTypeMatcher::verify(): Duplicate substitution AND Rewrite system exceeded concrete type nesting depth limit) #77099
When conforming to a complex protocol with (at least?) three associated types, where:
one associated type (say A) is unbounded
the other two associated types (say Param and Ret) are constrained to the protocol itself
there is a generic function over B in the form func fn<B>(param: Param) -> Ret where Param.A == (A) -> B, Ret.A == B
When the conformer itself is used as the substitution for Param and Ret, the compiler goes stuck for a bit and then crashes saying:
(there's more info after the stack trace)
error: compile command failed due to signal 6 (use -v to see invocation)
ConcreteTypeMatcher::verify(): Duplicate substitution
Abstract differences with LHS < RHS:
Abstract differences with RHS < LHS:
- τ_1_0 (#1) -> τ_0_0
- τ_1_0 (#3) -> τ_0_0
... lots and lots of this ...
- τ_1_0 (#65533) -> τ_0_0
- τ_1_0 (#65535) -> τ_0_0
Concrete differences with LHS < RHS:
Concrete differences with RHS < LHS:
Concrete conflicts:
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
(trace #1)
If I remove Param (which is on function parameter position) and replace it with the type (A) -> B, everything is ok. But if I replace Ret (which is on function return position) with B, the compiler crashes again but with a different error:
error: compile command failed due to signal 6 (use -v to see invocation)
Rewrite system exceeded concrete type nesting depth limit
Requirement machine for fresh signature < τ_0_0 τ_1_0 >
Rewrite system: {
- [Copyable].[Copyable] => [Copyable] [permanent]
- [Escapable].[Escapable] => [Escapable] [permanent]
- τ_1_0.[Copyable] => τ_1_0 [explicit]
- τ_1_0.[Escapable] => τ_1_0 [explicit]
- τ_0_0.[concrete: (τ_0_0) -> τ_1_0] => τ_0_0 [explicit] [subst↓]
- τ_0_0.[concrete: (@escaping (τ_0_0) -> τ_1_0) -> τ_1_0] => τ_0_0 [subst↓]
- τ_0_0.[concrete: (@escaping (@escaping (τ_0_0) -> τ_1_0) -> τ_1_0) -> τ_1_0] => τ_0_0 [subst↓]
- τ_0_0.[concrete: (@escaping (@escaping (@escaping (τ_0_0) -> τ_1_0) -> τ_1_0) -> τ_1_0) -> τ_1_0] => τ_0_0 [subst↓]
- τ_0_0.[concrete: (@escaping (@escaping (@escaping (@escaping (τ_0_0) -> τ_1_0) -> τ_1_0) -> τ_1_0) -> τ_1_0) -> τ_1_0] => τ_0_0 [subst↓]
... every row expands with one nested level per row until it gets massive! ...
Conformance paths: {
}
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
(trace #2)
Reproduction
protocol Crash {
associatedtype A
associatedtype Param: Crash
associatedtype Ret: Crash
func fn<B>(param: Param) -> Ret
where Param.A == (A) -> B, Ret.A == B
}
extension Optional: Crash {
typealias A = Wrapped
typealias Param = Optional
typealias Ret = Optional
func fn<B>(param: Param) -> Ret {
fatalError()
}
}
/* Also try to replace `Param` with `(A) -> B` and `Ret` with `B` */
I expected the compiler to not crash and give some info about why the code is wrong at high level (e.g. the issue is that the generic constraints are... under constrained, so there are infinite solutions available?), not in tau / substitution map terms.
Environment
swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)
Target: arm64-apple-macosx14.0
Description
When conforming to a complex protocol with (at least?) three associated types, where:
A
) is unboundedParam
andRet
) are constrained to the protocol itselfB
in the formfunc fn<B>(param: Param) -> Ret where Param.A == (A) -> B, Ret.A == B
When the conformer itself is used as the substitution for
Param
andRet
, the compiler goes stuck for a bit and then crashes saying:(there's more info after the stack trace)
If I remove
Param
(which is on function parameter position) and replace it with the type(A) -> B
, everything is ok. But if I replaceRet
(which is on function return position) withB
, the compiler crashes again but with a different error:Reproduction
Stack dump
Expected behavior
I expected the compiler to not crash and give some info about why the code is wrong at high level (e.g. the issue is that the generic constraints are... under constrained, so there are infinite solutions available?), not in tau / substitution map terms.
Environment
swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2) Target: arm64-apple-macosx14.0
Additional information
No response