-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Scala Wart about implicit () class parameters #14840
Conversation
Fixes scala#2576 As the discussion in scala#2576 shows, we still have some problems with the implicitly inserted empty parameter lists for class constructors. We do need that empty list to support syntax like `C()` and `new C()`. But it gets in the way if a class has using clauses. Example from the issue: ```scala class Bar(using x: Int)(y: String) given Int = ??? def test = new Bar("") ``` Here, an implicitly inserted `()` in front makes the last line fail. We'd need `new Bar()("")`. If a class has only using clauses as parameters we now insert a `()` at the end instead of at the start. That makes the example compile. For old-style implicit parameters we don't have a choice. We still need the `()` at the start since otherwise we'd change the meaning of calls with explicit arguments for the implicit parameters.
This is needed to ensure backwards Tasty compatibility
This currently fail with: MethodType(List(y), List(TypeRef(TermRef(TermRef(ThisType(TypeRef(NoPrefix,module class <root>)),object scala),Predef),String)), TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),class Bar)) (of class dotty.tools.dotc.core.Types$CachedMethodType) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readLengthTerm$1(TreeUnpickler.scala:1154) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readTerm(TreeUnpickler.scala:1313) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readLengthTerm$1(TreeUnpickler.scala:1137) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readTerm(TreeUnpickler.scala:1313) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.$anonfun$24(TreeUnpickler.scala:1138) at dotty.tools.tasty.TastyReader.until(TastyReader.scala:125) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readLengthTerm$1(TreeUnpickler.scala:1138) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readTerm(TreeUnpickler.scala:1313) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readIndexedStat(TreeUnpickler.scala:998) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readIndexedStats$$anonfun$1(TreeUnpickler.scala:1036) at dotty.tools.tasty.TastyReader.until(TastyReader.scala:125) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readIndexedStats(TreeUnpickler.scala:1036) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readStats(TreeUnpickler.scala:1040) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readLengthTerm$1(TreeUnpickler.scala:1166) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readTerm(TreeUnpickler.scala:1313) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readLengthTerm$1(TreeUnpickler.scala:1158) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.readTerm(TreeUnpickler.scala:1313) at dotty.tools.dotc.core.tasty.TreeUnpickler$TreeReader.createMemberSymbol$$anonfun$1(TreeUnpickler.scala:614) at dotty.tools.dotc.core.Annotations$.dotty$tools$dotc$core$Annotations$$anon$2$$_$$lessinit$greater$$anonfun$1(Annotations.scala:162) at dotty.tools.dotc.core.Annotations$LazyBodyAnnotation.tree(Annotations.scala:150) at dotty.tools.dotc.typer.Inliner$.bodyToInline(Inliner.scala:53) at dotty.tools.dotc.typer.Inliner$.inlineCall(Inliner.scala:157) at dotty.tools.dotc.transform.Inlining$InliningTreeMap.transform(Inlining.scala:70) at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform$$anonfun$1(Trees.scala:1494) at scala.collection.immutable.List.mapConserve(List.scala:472) at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1494) at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1388) at dotty.tools.dotc.ast.TreeMapWithImplicits.transform(TreeMapWithImplicits.scala:73) at dotty.tools.dotc.transform.Inlining$InliningTreeMap.transform(Inlining.scala:78) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformBlock$$anonfun$1$$anonfun$1(tpd.scala:1211) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.loop$2(tpd.scala:1193) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformStats(tpd.scala:1206) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformBlock(tpd.scala:1211) at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1402) at dotty.tools.dotc.ast.TreeMapWithImplicits.transform(TreeMapWithImplicits.scala:49) at dotty.tools.dotc.transform.Inlining$InliningTreeMap.transform(Inlining.scala:66) at dotty.tools.dotc.ast.TreeMapWithImplicits.transform(TreeMapWithImplicits.scala:56) at dotty.tools.dotc.transform.Inlining$InliningTreeMap.transform(Inlining.scala:64) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.loop$2(tpd.scala:1206) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformStats(tpd.scala:1206) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformStats(tpd.scala:1208) at dotty.tools.dotc.ast.TreeMapWithImplicits.transform(TreeMapWithImplicits.scala:64) at dotty.tools.dotc.transform.Inlining$InliningTreeMap.transform(Inlining.scala:64) at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1465) at dotty.tools.dotc.ast.TreeMapWithImplicits.transform(TreeMapWithImplicits.scala:73) at dotty.tools.dotc.transform.Inlining$InliningTreeMap.transform(Inlining.scala:64) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.loop$2(tpd.scala:1206) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformStats(tpd.scala:1206) at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformStats(tpd.scala:1208) at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1476) at dotty.tools.dotc.ast.TreeMapWithImplicits.transform(TreeMapWithImplicits.scala:73) at dotty.tools.dotc.transform.Inlining$InliningTreeMap.transform(Inlining.scala:78) at dotty.tools.dotc.transform.Inlining$$anon$2.transform(Inlining.scala:56) at dotty.tools.dotc.transform.MacroTransform.run(MacroTransform.scala:18) at dotty.tools.dotc.transform.Inlining.run(Inlining.scala:28)
@@ -1135,7 +1135,23 @@ class TreeUnpickler(reader: TastyReader, | |||
tpd.Super(qual, mixId, mixTpe.typeSymbol) | |||
case APPLY => | |||
val fn = readTerm() | |||
tpd.Apply(fn, until(end)(readTerm())) | |||
val args = until(end)(readTerm()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a commit to test backwards compatibility and when inlining a def from a previous compiler version, we crash when unpickling the arguments here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I handled only one part before (where all parameters are using clauses). Now the mixed case is handled as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The backwards compat support LGTM, but I think that forwards compat support via -scala-output-release will require more special-casing (new-style constructors need to be treated like old-style constructors when ctx.scalaRelease <= ScalaRelease.Release3_1
), I don't have time right now to dig into this but perhaps @prolativ could take a look? It could be a good case study for the planned discussion on -scala-output-release.
I don't know how to reconcile this with |
I think this can be merged now? |
so it looks like this has caused some inference issues: #15171 |
@odersky can you take a look at reproducer snipper from #15647 for tinkoff/phobos failure
As I understood your comment for this PR, code |
Yes, it's the other way round. This works as expected. |
Fixes #2576
As the discussion in #2576 shows, we still have some problems with the implicitly
inserted empty parameter lists for class constructors. We do need that empty list
to support syntax like
C()
andnew C()
. But it gets in the way if a class hasusing clauses. Example from the issue:
Here, an implicitly inserted
()
in front makes the last line fail. We'd neednew Bar()("")
.If a class has only using clauses as parameters we now insert a
()
at the endinstead of at the start. That makes the example compile.
For old-style implicit parameters we don't have a choice. We still need the
()
atthe start since otherwise we'd change the meaning of calls with explicit arguments
for the implicit parameters.