2015-10-15 10 views
8

ho gerarchia tipo semplice a Scala:malinteso con controlli di tipo a Scala

trait A { 
    trait A1 
} 

object B extends A { 
    case object B1 extends A1 
} 

object C extends A { 
    case object C1 extends A1 
} 

E, Userò questi tipi del genere:

def get(): Any = C.C1 

get() match { 
    case _: B.A1 => println("B") 
    case _: C.A1 => println("C") 
    case _: A#A1 => println("Any") 
} 

Sorprendentemente, mi sto B stampato (mi aspettavo C).

Perché il compilatore considera C.C1 come istanza di B.A1?

+0

Credo che questo è un problema di tipo cancellazione, provare 'scalac -Xprint: erasure', il vostro pattern match ottenere compilato per' A.A1' –

+0

@ Zoltán http: //www.scala- lang.org/files/archive/spec/2.11/03-types.html#equivalence –

+0

@HerringtonDarkholme Non penso che questi siano [tipi composti] (http://www.scala-lang.org/old/node/ 110), ma [tipi dipendenti dal percorso] (http://stackoverflow.com/questions/5581836/why-does-scala-have-path-dependent-types). In ogni caso, la mia ipotesi è sbagliata. –

risposta

5

Questo è un bug noto.

scalac fa generare un avviso per questo usando il flag -unchecked:

warning: The outer reference in this type test cannot be checked at run time. 
      case _: B.A1 => println("B") 
       ^

Così adesso, B.A1 e C.A1 appaiono lo stesso al compilatore nel match modello, perché non controlla il riferimento esterno a B o C.

Vedere questo related discussion.

E SI-4440

+0

Sembra decisamente un bug nel compilatore. Ci ho pensato, ma ho deciso che mi manca qualcosa. Mi piace molto Scala e spero che questo problema venga risolto nelle versioni future. –

+0

Tuttavia, non sono riuscito a ottenere questo avviso, mentre giocavo con il flag '-unchecked'. Provato Scala 2.10.5 e 2.11.7. –

+0

Non l'ho capito nel REPL, ma l'ho fatto se ho inserito lo stesso codice in un file scala e compilato con scalac. –