我从辅助类构造函数文章中复制了以下代码,粘贴到 Scastie 中,更改class为trait并将 Scala 版本设置为 3.1.0:
val DefaultCrustSize = 12\nval DefaultCrustType = "THIN"\n\n// the primary constructor\ntrait Pizza (var crustSize: Int, var crustType: String) {\n\n // one-arg auxiliary constructor\n def this(crustSize: Int) = {\n this(crustSize, DefaultCrustType)\n }\n\n // one-arg auxiliary constructor\n def this(crustType: String) = {\n this(DefaultCrustSize, crustType)\n }\n\n // zero-arg auxiliary constructor\n def this() = {\n this(DefaultCrustSize, DefaultCrustType)\n }\n\n override def toString = s"A $crustSize inch pizza with a $crustType crust"\n\n}\nRun Code Online (Sandbox Code Playgroud)\n这是结果。它给出以下错误:
\norg.scalameta.invariants.InvariantFailedException: invariant failed:\nwhen verifying scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Template](templ)(scala.meta.Tree.classifiable[scala.meta.Template]).is[Template.Quasi](Template.this.Quasi.ClassifierClass[scala.meta.Template]).||(templ.stats.forall(((x$9: scala.meta.Stat) => scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Stat](x$9)(scala.meta.Tree.classifiable[scala.meta.Stat]).is[Ctor](scala.meta.Ctor.ClassifierClass[scala.meta.Stat]).`unary_!`)))\nfound that scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Template](templ)(scala.meta.Tree.classifiable[scala.meta.Template]).is[Template.Quasi](Template.this.Quasi.ClassifierClass[scala.meta.Template]) is false\nand also templ.stats.forall(((x$9: scala.meta.Stat) => scala.meta.classifiers.`package`.XtensionClassifiable[scala.meta.Stat](x$9)(scala.meta.Tree.classifiable[scala.meta.Stat]).is[Ctor](scala.meta.Ctor.ClassifierClass[scala.meta.Stat]).`unary_!`)) is false\nwhere Template = scala.meta.Template$@7759c8f1\nwhere templ = {\n\n // one-arg auxiliary constructor\n def this(crustSize: Int) = {\n this(crustSize, DefaultCrustType)\n }\n\n // one-arg auxiliary constructor\n def this(crustType: String) = {\n this(DefaultCrustSize, crustType)\n }\n\n // zero-arg auxiliary constructor\n def this() = {\n this(DefaultCrustSize, DefaultCrustType)\n }\n\n override def toString = s"A $crustSize inch pizza with a $crustType crust"\n\n}\n at org.scalameta.invariants.InvariantFailedException$.raise(Exceptions.scala:19)\n at scala.meta.Defn$Trait$.internal$247(Trees.scala:432)\n at scala.meta.Defn$Trait$.apply(Trees.scala:425)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$traitDef$1(ScalametaParser.scala:4592)\n at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n at scala.meta.internal.parsers.ScalametaParser.traitDef(ScalametaParser.scala:4570)\n at scala.meta.internal.parsers.ScalametaParser.tmplDef(ScalametaParser.scala:4548)\n at scala.meta.internal.parsers.ScalametaParser.defOrDclOrSecondaryCtor(ScalametaParser.scala:4201)\n at scala.meta.internal.parsers.ScalametaParser.nonLocalDefOrDcl(ScalametaParser.scala:4172)\n at scala.meta.internal.parsers.ScalametaParser$$anonfun$templateStat$1$1.applyOrElse(ScalametaParser.scala:5120)\n at scala.meta.internal.parsers.ScalametaParser$$anonfun$templateStat$1$1.applyOrElse(ScalametaParser.scala:5114)\n at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:35)\n at scala.meta.internal.parsers.ScalametaParser.statSeq(ScalametaParser.scala:5057)\n at scala.meta.internal.parsers.ScalametaParser.templateStats(ScalametaParser.scala:5130)\n at scala.meta.internal.parsers.ScalametaParser.templateStatSeq(ScalametaParser.scala:5110)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$templateBody$1(ScalametaParser.scala:4945)\n at scala.meta.internal.parsers.ScalametaParser.inBraces(ScalametaParser.scala:800)\n at scala.meta.internal.parsers.ScalametaParser.templateBody(ScalametaParser.scala:4945)\n at scala.meta.internal.parsers.ScalametaParser.templateBodyOpt(ScalametaParser.scala:4953)\n at scala.meta.internal.parsers.ScalametaParser.template(ScalametaParser.scala:4887)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$template$1(ScalametaParser.scala:4906)\n at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n at scala.meta.internal.parsers.ScalametaParser.template(ScalametaParser.scala:4891)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$templateOpt$1(ScalametaParser.scala:4931)\n at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n at scala.meta.internal.parsers.ScalametaParser.templateOpt(ScalametaParser.scala:4923)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$objectDef$1(ScalametaParser.scala:4682)\n at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n at scala.meta.internal.parsers.ScalametaParser.objectDef(ScalametaParser.scala:4674)\n at scala.meta.internal.parsers.ScalametaParser.tmplDef(ScalametaParser.scala:4558)\n at scala.meta.internal.parsers.ScalametaParser.topLevelTmplDef(ScalametaParser.scala:4540)\n at scala.meta.internal.parsers.ScalametaParser$$anonfun$topStat$1.applyOrElse(ScalametaParser.scala:5079)\n at scala.meta.internal.parsers.ScalametaParser$$anonfun$topStat$1.applyOrElse(ScalametaParser.scala:5067)\n at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:35)\n at scala.meta.internal.parsers.ScalametaParser.statSeq(ScalametaParser.scala:5057)\n at scala.meta.internal.parsers.ScalametaParser.topStatSeq(ScalametaParser.scala:5066)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$batchSource$1(ScalametaParser.scala:5297)\n at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n at scala.meta.internal.parsers.ScalametaParser.batchSource(ScalametaParser.scala:5256)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$source$1(ScalametaParser.scala:5239)\n at scala.meta.internal.parsers.ScalametaParser.atPos(ScalametaParser.scala:888)\n at scala.meta.internal.parsers.ScalametaParser.autoPos(ScalametaParser.scala:922)\n at scala.meta.internal.parsers.ScalametaParser.source(ScalametaParser.scala:5238)\n at scala.meta.internal.parsers.ScalametaParser.entrypointSource(ScalametaParser.scala:5244)\n at scala.meta.internal.parsers.ScalametaParser.$anonfun$parseSource$2(ScalametaParser.scala:143)\n at scala.meta.internal.parsers.ScalametaParser.parseRule(ScalametaParser.scala:53)\n at scala.meta.internal.parsers.ScalametaParser.parseSource(ScalametaParser.scala:143)\n at scala.meta.parsers.Parse$.$anonfun$parseSource$1(Parse.scala:29)\n at scala.meta.internal.parsers.ScalametaParser$$anon$264.apply(ScalametaParser.scala:5308)\n at scala.meta.parsers.Api$XtensionParseDialectInput.parse(Api.scala:25)\n at scala.meta.parsers.Api$XtensionParseInputLike.parse(Api.scala:14)\n at com.olegych.scastie.instrumentation.Instrument$.apply(Instrument.scala:199)\n at com.olegych.scastie.instrumentation.InstrumentedInputs$.apply(InstrumentedInputs.scala:23)\n at com.olegych.scastie.sbt.SbtProcess$$anonfun$4.applyOrElse(SbtProcess.scala:191)\n at com.olegych.scastie.sbt.SbtProcess$$anonfun$4.applyOrElse(SbtProcess.scala:177)\n at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:35)\n at akka.actor.FSM.processEvent(FSM.scala:707)\n at akka.actor.FSM.processEvent$(FSM.scala:704)\n at com.olegych.scastie.sbt.SbtProcess.processEvent(SbtProcess.scala:64)\n at akka.actor.FSM.akka$actor$FSM$$processMsg(FSM.scala:701)\n at akka.actor.FSM$$anonfun$receive$1.applyOrElse(FSM.scala:695)\n at akka.actor.Actor.aroundReceive(Actor.scala:539)\n at akka.actor.Actor.aroundReceive$(Actor.scala:537)\n at com.olegych.scastie.sbt.SbtProcess.aroundReceive(SbtProcess.scala:64)\n at akka.actor.ActorCell.receiveMessage(ActorCell.scala:614)\n at akka.actor.ActorCell.invoke(ActorCell.scala:583)\n at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:268)\n at akka.dispatch.Mailbox.run(Mailbox.scala:229)\n at akka.dispatch.Mailbox.exec(Mailbox.scala:241)\n at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)\n at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)\n at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)\n at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)\nRun Code Online (Sandbox Code Playgroud)\n为什么?为什么它在第 1 行之后,这看起来完全没问题,当我删除其余部分时它就被接受了?“不变失败”是否意味着它是编译器中的错误?(在这种情况下,许多其他编译器会在消息中添加鼓励报告的信息。)
\n主要问题:
\ntrait关于参数的文档仅提到trait parameters, not trait constructors:
\n\nScala 3 允许特征具有参数,就像类具有参数一样。
\n
它还链接到原始 SIP 文档以供参考:
\n\n\n有关更多信息,请参阅Scala SIP 25.
\n
在SIP-25\xc2\xa0\xe2\x80\x93trait参数中,它显示 [粗体 emphasis mine]:
\n\n在
\nClassDeftraits中,我们仍然不允许辅助构造函数.
然而,这个限制并没有体现在语法摘要中,它实际上并没有区分classes 和traits syntactically. So, the restriction is purely one of documentation, not syntax specification.
所以,回答你的问题:
\n\n\n为什么?
\n
因为你的代码在语法上是有效的,但在语义上是无效的,而 ScalaMeta 似乎并不期望这种特定类型的语义无效。
\n\n\n为什么它在第 1 行之后,这看起来完全没问题,当我删除其余部分时它就被接受了?“不变失败”是否意味着它是编译器中的错误?(在这种情况下,许多其他编译器会在消息中添加鼓励报告的内容。)
\n
这显然不是编译器中的错误,因为异常不是在编译器中抛出的,而是在 ScalaMeta 中抛出的。
\n\n\n主要问题:
\n\n
\n- 特征中是否允许使用次要(或辅助 \xe2\x80\x93 IIUC 这两个术语,这两个术语显然可以互换使用,意思相同)?
\n
不可以。SIP-25 明确不允许它们。
\n