In your initial example you can break the cycle by introducing an auxiliary type inbetween GenT[A] and T,
trait GenT[A]
trait TAux { type A }
trait T extends TAux with GenT[TAux#A]
But from your motivating example I don't think you need to go down this route. The constraint you're after can be expressed directly using a refinement,
trait T { type A }
def foo[A0, S1 <: T { type A = A0 }, S2 <: T { type A = A0 }] ...
Also bear in mind that you can surface a type member as a type parameter via a type alias,
trait T { type A }
type TParam[A0] = T { type A = A0 }
def foo[A0, S1 <: TParam[A0], S2 <: TParam[A0]] ...
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…