J'ai rencontré une erreur de vérification des caractères que je n'ai pas pu comprendre. Deux morceaux de code sont identiques, mais un seul compile. Le compilateur donne un message d'erreur totalement inutile :
error : type arguments [I] do not conform to type DY's type parameter bounds [I < : Sample.this.Y]
Le code en question :
trait Sample {
type X
type DX[I <: X] <: X
type Y = Aux[X]
type DY[I <: Y] <: Y
type Z = Bux[X]
type DZ[I <: Z] <: Z
type DW[I <: Z#C] <: Z#C
}
type Aux[I] = Sample { type X = I }
trait Dep {
type B
type C = Aux[B]
}
type Bux[A] = Dep { type B = A }
type UseX[I <: S#X, S <: Sample] = S#DX[I] // ok
type UseY[I <: S#Y, S <: Sample] = S#DY[I] // fails
type UseZ[I <: S#Z, S <: Sample] = S#DZ[I] // ok
type UseW[I <: S#Z#C, S <: Sample] = S#DW[I] // fails
Pourquoi je ne pouvais pas référencer le type lui-même ?
Mise à jour
Je reste aussi confus que lorsque j'ai écrit la question. Mais j'ai quand même réussi à tromper le compilateur pour qu'il fasse son travail. Et cela n'a fait qu'accroître ma confusion.
Le problème est que les arguments de même type sont acceptés ou rejetés sur la base de la liaison de type. Si le type lié est le même que l'argument (introduisant ainsi une récursion), il est rejeté. Mais si j'enveloppe la récursion dans un type, il est accepté normalement. Donc, tout ce dont j'ai besoin, c'est de relayer l'appel à la récursion.
trait Sample {
type X
type Y = Aux[X]
type Z = Bux[X]
type DY[I <: Y] <: Y
type DD[I <: Z] = DY[I#C]
}
type UseY[I <: S#Y, S <: Sample] = S#DY[I] // still fails
type UseD[I <: S#Z, S <: Sample] = S#DD[I] // miraculously works
Mais cela nécessite d'envelopper chaque appel au niveau du type dans la balise Bux
type d'emballage.