2010-03-23 3 views
2

Est-ce un comportement prévu ou est-ce un bug? Considérons le trait suivant (que ce soit une classe, n'a pas d'importance):Paramètre de classe littéral de fonction par défaut paramétrée par type

trait P[T] { 
    class Inner(val f: T => Unit = _ => println("nope")) 
} 

Voilà ce que je me serais attendu:

scala> val p = new P[Int] { 
    |  val inner = new Inner 
    | } 
p: java.lang.Object with P[Int]{def inner: this.Inner} = [email protected] 

scala> p.inner.f(5) 
nope 

Mais cela?

scala> val p = new P[Int] { 
    |  val inner = new Inner() { 
    |   println("some primary constructor code in here") 
    |  } 
    | } 
<console>:6: error: type mismatch; 
found : (T) => Unit 
required: (Int) => Unit 
      val inner = new Inner() { 
         ^
+0

Donc, c'était un bug et il a été corrigé il y a environ deux semaines. –

Répondre

2

Cela semble être un bogue, bien qu'à une intersection plutôt obscure entre les classes imbriquées, les types abstraits et les paramètres par défaut. Vous pouvez lever un ticket dans la Scala bug tracker - Je n'ai pas trouvé de ticket décrivant cela.

Voilà comment il ressemble après la phase typer:

~: scala -nocompdaemon -Xprint:typer -e 'trait P[T] { class Inner(val f: T = null.asInstanceOf[T]) }; new P[Int] { new Inner(){} }' 
!!! 
discarding <script preamble> 
(fragment of scalacmd162105603941759154.scala):1: error: type mismatch; 
found : T 
required: Int 
trait P[T] { class Inner(val f: T = null.asInstanceOf[T]) }; new P[Int] { new Inner(){} } 
                      ^
[[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(); 
      () 
      }; 
      abstract trait P[T >: Nothing <: Any] extends java.lang.Object with ScalaObject { 
      def /*P*/$init$(): Unit = { 
      () 
      }; 
      class Inner extends java.lang.Object with ScalaObject { 
       <paramaccessor> private[this] val f: T = _; 
       <stable> <accessor> <paramaccessor> def f: T = Inner.this.f; 
       def this(f: T = null.asInstanceOf[T]): P.this.Inner = { 
       Inner.super.this(); 
       () 
       } 
      }; 
      final <synthetic> object Inner extends java.lang.Object with ScalaObject { 
       <synthetic> def init$default$1: T @scala.annotation.unchecked.uncheckedVariance = null.asInstanceOf[T]; 
       def this(): object P.this.Inner = { 
       Inner.super.this(); 
       () 
       } 
      } 
      }; 
      { 
      final class $anon extends java.lang.Object with this.P[Int] { 
       def this(): anonymous class $anon = { 
       $anon.super.this(); 
       () 
       }; 
       { 
       final class $anon extends $anon.this.Inner { 
        def this(): anonymous class $anon = { 
        $anon.super.this(P.this.Inner.<error: method init$default$1>); 
        () 
        }; 
        <empty> 
       }; 
       new $anon() 
       } 
      }; 
      new $anon() 
      } 
     }; 
     { 
      new $anon(); 
     () 
     } 
     } 
    } 
    } 
} 

Et la version de travail, sans la classe interne anonyme extension intérieure.

~: scala -nocompdaemon -Xprint:typer -e 'trait P[T] { class Inner(val f: T = null.asInstanceOf[T]) }; new P[Int] { new Inner() }' 
[[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(); 
      () 
      }; 
      abstract trait P[T >: Nothing <: Any] extends java.lang.Object with ScalaObject { 
      def /*P*/$init$(): Unit = { 
      () 
      }; 
      class Inner extends java.lang.Object with ScalaObject { 
       <paramaccessor> private[this] val f: T = _; 
       <stable> <accessor> <paramaccessor> def f: T = Inner.this.f; 
       def this(f: T = null.asInstanceOf[T]): P.this.Inner = { 
       Inner.super.this(); 
       () 
       } 
      }; 
      final <synthetic> object Inner extends java.lang.Object with ScalaObject { 
       <synthetic> def init$default$1: T @scala.annotation.unchecked.uncheckedVariance = null.asInstanceOf[T]; 
       def this(): object P.this.Inner = { 
       Inner.super.this(); 
       () 
       } 
      } 
      }; 
      { 
      final class $anon extends java.lang.Object with this.P[Int] { 
       def this(): anonymous class $anon = { 
       $anon.super.this(); 
       () 
       }; 
       new $anon.this.Inner($anon.this.Inner.init$default$1) 
      }; 
      new $anon() 
      } 
     }; 
     { 
      new $anon(); 
     () 
     } 
     } 
    } 
    } 
} 
Questions connexes