默认类型参数化函数文字类参数

发布于 2024-08-25 22:21:22 字数 720 浏览 12 评论 0原文

这是一个预期的行为还是一个错误?考虑以下特征(无论是一个类,都没关系):

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

这是我所期望的:

scala> val p = new P[Int] {
     |     val inner = new Inner
     | }
p: java.lang.Object with P[Int]{def inner: this.Inner} = $anon$1@12192a9

scala> p.inner.f(5)
nope

但是这个?

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() {
                           ^

Is this an intended behavior or is it a bug? Consider the following trait (be it a class, doesn't matter):

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

This is what I would have expected:

scala> val p = new P[Int] {
     |     val inner = new Inner
     | }
p: java.lang.Object with P[Int]{def inner: this.Inner} = $anon$1@12192a9

scala> p.inner.f(5)
nope

But this?

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() {
                           ^

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谎言 2024-09-01 22:21:22

这似乎是一个错误,尽管是在嵌套类、抽象类型和默认参数之间相当模糊的交集处。您可以在 Scala 错误跟踪器 中提出问题单 - 我找不到现有的问题单描述这一点。

这是打字阶段之后的样子:

 ~: 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();
          ()
        }
      }
    }
  }
}

以及工作版本,没有扩展 Inner 的匿名内部类。

 ~: 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();
          ()
        }
      }
    }
  }
}

That appears to be a bug, albeit at a rather obscure intersection between nested classes, abstract types, and default parameters. You could raise a ticket in the Scala bug tracker -- I couldn't find an existing ticket describing this.

Here's how it looks after the typer phase:

 ~: 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();
          ()
        }
      }
    }
  }
}

And the working version, without the anonymous inner class extending Inner.

 ~: 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();
          ()
        }
      }
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文