This is not optimization related. The infinite recursion can already be seen after SILGen.
The map closure in Error<>.equals directly calls Error.== which itself calls Error<>.equals:
// closure #1 in Error<>.equals(_:)
// Isolation: nonisolated
sil private [ossa] @$ss5ErrorP3nixSQRzrlE6equals33_99B4105BFEF8B89FB51B048E96307926LLySbsAA_pFSbxXEfU_ : $@convention(thin) <Self where Self : Equatable, Self : Error> (@in_guaranteed Self, @in_guaranteed Self) -> (@out Bool, @error_indirect Never) {
// %0 "$return_value" // user: %17
// %1 "$error"
// %2 "$0" // users: %14, %4
// %3 "self" // users: %11, %5
bb0(%0 : $*Bool, %1 : $*Never, %2 : $*Self, %3 : @closureCapture $*Self):
debug_value %2, let, name "$0", argno 1, expr op_deref // id: %4
debug_value %3, let, name "self", argno 2, expr op_deref // id: %5
%6 = metatype $@thick Self.Type // user: %14
%7 = alloc_stack $any Error // users: %16, %12, %10
%8 = alloc_existential_box $any Error, $Self // users: %10, %9
%9 = project_existential_box $Self in %8 // user: %11
store %8 to [init] %7 // id: %10
copy_addr %3 to [init] %9 // id: %11
%12 = load [take] %7 // users: %15, %14
// function_ref static Error.== infix(_:_:)
%13 = function_ref @$ss5ErrorP3nixE2eeoiySbx_sAA_ptFZ : $@convention(method) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @guaranteed any Error, @thick τ_0_0.Type) -> Bool // user: %14
%14 = apply %13<Self>(%2, %12, %6) : $@convention(method) <τ_0_0 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @guaranteed any Error, @thick τ_0_0.Type) -> Bool // user: %17
destroy_value %12 // id: %15
dealloc_stack %7 // id: %16
store %14 to [trivial] %0 // id: %17
%18 = tuple () // user: %19
return %18 // id: %19
} // end sil function '$ss5ErrorP3nixSQRzrlE6equals33_99B4105BFEF8B89FB51B048E96307926LLySbsAA_pFSbxXEfU_'
Whereas when wrapping in an identity function, the closure calls the witness method which does a simple struct compare:
// closure #1 in Error<>.equals(_:)
// Isolation: nonisolated
sil private [ossa] @$ss5ErrorP3nixSQRzrlE6equals33_E619977560B7C2782CE1898FF188B53DLLySbsAA_pFSbxXEfU_ : $@convention(thin) <Self where Self : Equatable, Self : Error> (@in_guaranteed Self, @in_guaranteed Self) -> (@out Bool, @error_indirect Never) {
// %0 "$return_value" // user: %14
// %1 "$error"
// %2 "$0" // users: %11, %4
// %3 "self" // users: %9, %5
bb0(%0 : $*Bool, %1 : $*Never, %2 : $*Self, %3 : @closureCapture $*Self):
debug_value %2, let, name "$0", argno 1, expr op_deref // id: %4
debug_value %3, let, name "self", argno 2, expr op_deref // id: %5
%6 = metatype $@thick Self.Type // user: %11
%7 = alloc_stack $Self // users: %13, %12, %11, %9
// function_ref identity<A>(_:)
%8 = function_ref @$s3nix8identityyxxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0 // user: %9
%9 = apply %8<Self>(%7, %3) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
%10 = witness_method $Self, #Equatable."==" : <Self where Self : Equatable, Self : ~Copyable, Self : ~Escapable> (Self.Type) -> (borrowing Self, borrowing Self) -> Bool : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable, τ_0_0 : ~Copyable, τ_0_0 : ~Escapable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool // user: %11
%11 = apply %10<Self>(%2, %7, %6) : $@convention(witness_method: Equatable) <τ_0_0 where τ_0_0 : Equatable, τ_0_0 : ~Copyable, τ_0_0 : ~Escapable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @thick τ_0_0.Type) -> Bool // user: %14
destroy_addr %7 // id: %12
dealloc_stack %7 // id: %13
store %11 to [trivial] %0 // id: %14
%15 = tuple () // user: %16
return %15 // id: %16
} // end sil function '$ss5ErrorP3nixSQRzrlE6equals33_E619977560B7C2782CE1898FF188B53DLLySbsAA_pFSbxXEfU_'