Compiler should not crash and I don't know if this case matches any of the known issues. You should send a Bug Report.
Is the above a coding-style that is to be avoided (in a language like Swift)?
I'm afraid the answer for this question is Yes.
When Swift applies a protocol as a type constraint, it needs to infer the actual types of the associated types.
So, when you use Person protocol, Person.R needs to be inferred.
And, any arbitrary type conforming to Relationship can be Person.R, Swift needs to infer Person.R.P,
two types conforming to Person and Person.R.P may be different, so this makes an inifinite recursion, not mutual recursion:
Person.R.P, Person.R.P.R, Person.R.P.R.P, ...
You may already know, if you remove Hashable, you can write something like this:
protocol Relationship {
var source : Person { get }
var target : Person { get }
}
protocol Person {
var fullname : String { get set }
var relationships: [Relationship] {get}
}
If you want to make all actual implementation of Person and Relationship to be Hashable, you can make derived protocols and use them:
protocol PersonType: Person, Hashable {}
protocol RelationshipType: Relationship, Hashable {}
One more, you should consider if both type may be value types, when you define mutually dependent types.