Quand @uncheckedVariance nécessaire à Scala, et pourquoi est-il utilisé dans GenericTraversableTemplate?

StackOverflow https://stackoverflow.com/questions/2454281

Question

@uncheckedVariance peut être utilisé pour combler l'écart entre le site de déclaration de Scala annotations de la variance et génériques invariantes de Java.

scala> import java.util.Comparator    
import java.util.Comparator

scala> trait Foo[T] extends Comparator[T]
defined trait Foo

scala> trait Foo[-T] extends Comparator[T]     
<console>:5: error: contravariant type T occurs in invariant position in type [-T]java.lang.Object with java.util.Comparator[T] of trait Foo
       trait Foo[-T] extends Comparator[T]
             ^

scala> import annotation.unchecked._    
import annotation.unchecked._

scala> trait Foo[-T] extends Comparator[T @uncheckedVariance]    
defined trait Foo

Ce que dit java.util.Comparator est naturellement contre-variante, qui est le paramètre de type T apparaît dans les paramètres et jamais dans un type de retour.

Cela pose la question: pourquoi est-il aussi utilisé dans la bibliothèque de collections Scala qui ne s'étend pas d'interfaces Java

trait GenericTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance]

Quelles sont les utilisations valides pour cette annotation?

Était-ce utile?

La solution

Le problème est que GenericTraversableTemplate est utilisé deux fois: une fois pour les collections mutables (où son paramètre de type doit être invariante), et une fois pour les collections immuables (où covariance est toujours roi)

.

Les typable de GenericTraversableTemplate en supposant que soit covariance ou invariance pour le paramètre de type. Cependant, quand nous héritons dans un trait muable, nous devons prendre invariance. A l'inverse, nous aimerions covariance dans une sous-classe immuable.

Puisque nous ne pouvons pas abstraite sur l'annotation de la variance (encore ;-)) en GenericTraversableTemplate, de sorte que nous aurions pu instancié à l'une en fonction de la sous-classe, nous devons recourir à la coulée (@uncheckVariance est essentiellement une sorte -jeter). Pour en savoir plus, je vous recommande ma thèse (désolé ;-)) ou notre récent

Les « attributs sont des types » idée est expliquée bien par Edsko de Vries dans le contexte des types d'unicité.

  

Unicité Saisie simplifiée ,   Edsko de Vries, Rinus Plasmeijer, et David Abrahamson.   Dans Olaf Chitil, Zoltán Horváth et Viktória Zsók (Eds.):   IFL 2007, LNCS 5083, pp. 201-218, 2008.

     

Résumé: Nous présentons un type unique   système qui est plus simple que les deux   Propre et le système unique de   système que nous avons proposé précédemment. Le nouveau   système de type est facile à   mettre en œuvre et ajouter aux éléments existants   compilateurs, et peuvent facilement être étendues   avec des fonctionnalités avancées telles que plus   types rang et imprédicativité. nous   décrire notre mise en œuvre à Morrow,   un langage fonctionnel expérimental   avec ces deux caractéristiques. Enfin nous   prouver la solidité du type à noyau   système par rapport à la   appel par besoin lambda-calcul.

I trouvé un autre moment où @uncheckedVariance est utilisé - la méthode de synthèse qui retourne la valeur par défaut pour un paramètre d'un type abstrait:

M:\>scala -Xprint:typer -e "class C { def p[T >: Null](t: T = null) = t }"
[[syntax trees at end of typer]]// Scala source: (virtual file)
package <empty> {
  final object Main extends java.lang.Object with ScalaObject {
    def this(): object Main = {
      Main.super.this();
      ()
    };
    def main(argv: Array[String]): Unit = {
      val args: Array[String] = argv;
      {
        final class $anon extends scala.AnyRef {
          def this(): anonymous class $anon = {
            $anon.super.this();
            ()
          };
          class C extends java.lang.Object with ScalaObject {
            <synthetic> def p$default$1[T >: Null <: Any]: Null @scala.annotation.unchecked.uncheckedVariance = null;
            def this(): this.C = {
              C.super.this();
              ()
            };
            def p[T >: Null <: Any](t: T = null): T = t
          }
        };
        {
          new $anon();
          ()
        }
      }
    }
  }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top