From 55f07c4dab8fbc46718992e8bfa5a555144c3ad4 Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 10 Jun 2022 17:56:28 +0200 Subject: [PATCH 1/3] Allow for unqualified `apply` as context functions Fixes #15414 --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 +++- tests/new/i15414.scala | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 tests/new/i15414.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index bdc6a03f6949..777d53d63ed9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3981,7 +3981,9 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer /** Convert constructor proxy reference to a new expression */ def newExpr = - val Select(qual, nme.apply) = tree: @unchecked + val qual = (tree: @unchecked) match + case Select(qual, nme.apply) => qual + case Ident(nme.apply) => This(tree.symbol.owner.asClass).withSpan(tree.span) val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false) val tpt = qual match case Ident(name) => diff --git a/tests/new/i15414.scala b/tests/new/i15414.scala new file mode 100644 index 000000000000..eaa7a540df8f --- /dev/null +++ b/tests/new/i15414.scala @@ -0,0 +1,4 @@ +class C() +object C { + val c = apply() +} \ No newline at end of file From 836118c2760fc658e1bd9fab7aea9b19e14dee9b Mon Sep 17 00:00:00 2001 From: odersky Date: Fri, 10 Jun 2022 19:17:44 +0200 Subject: [PATCH 2/3] Use qualifier in newExpr --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 777d53d63ed9..804702592a52 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3981,10 +3981,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer /** Convert constructor proxy reference to a new expression */ def newExpr = - val qual = (tree: @unchecked) match - case Select(qual, nme.apply) => qual - case Ident(nme.apply) => This(tree.symbol.owner.asClass).withSpan(tree.span) - val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false) + val qual = qualifier(tree) val tpt = qual match case Ident(name) => cpy.Ident(qual)(name.toTypeName) @@ -3992,6 +3989,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer cpy.Select(qual)(pre, name.toTypeName) case qual: This if qual.symbol.is(ModuleClass) => cpy.Ident(qual)(qual.symbol.name.sourceModuleName.toTypeName) + val tycon = tree.tpe.widen.finalResultType.underlyingClassRef(refinementOK = false) typed( untpd.Select( untpd.New(untpd.TypedSplice(tpt.withType(tycon))), From 3a51e88cba9f6e5878b681f99db5049ade5dd781 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 11 Jun 2022 10:43:21 +0200 Subject: [PATCH 3/3] Don't allow single apply's to be used as constructor proxies The previous commits allowed them but that caused runtime errors in Specs2 since `apply` was bound to something different from before. Since this is a weird corner case it's better not to allow it. As long as we do not crash we are good. The error message we get now is: constructor proxy `apply` cannot be used as a value which is also a bit strange, but since this is a truly weird corner case it's not worth it to finetune this. --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 8 ++++++-- tests/neg/i15414.scala | 4 ++++ tests/new/i15414.scala | 4 ---- 3 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 tests/neg/i15414.scala delete mode 100644 tests/new/i15414.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 804702592a52..2d51360bd321 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -3997,6 +3997,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer pt) .showing(i"convert creator $tree -> $result", typr) + def isApplyProxy(tree: Tree) = tree match + case Select(_, nme.apply) => tree.symbol.isAllOf(ApplyProxyFlags) + case _ => false + tree match { case _: MemberDef | _: PackageDef | _: Import | _: WithoutTypeOrPos[?] | _: Closure => tree case _ => tree.tpe.widen match { @@ -4012,7 +4016,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer adaptOverloaded(ref) } case poly: PolyType if !(ctx.mode is Mode.Type) => - if tree.symbol.isAllOf(ApplyProxyFlags) then newExpr + if isApplyProxy(tree) then newExpr else if pt.isInstanceOf[PolyProto] then tree else var typeArgs = tree match @@ -4026,7 +4030,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer readaptSimplified(handleStructural(tree)) else pt match { case pt: FunProto => - if tree.symbol.isAllOf(ApplyProxyFlags) then newExpr + if isApplyProxy(tree) then newExpr else adaptToArgs(wtp, pt) case pt: PolyProto if !wtp.isImplicitMethod => tryInsertApplyOrImplicit(tree, pt, locked)(tree) // error will be reported in typedTypeApply diff --git a/tests/neg/i15414.scala b/tests/neg/i15414.scala new file mode 100644 index 000000000000..9565276a5752 --- /dev/null +++ b/tests/neg/i15414.scala @@ -0,0 +1,4 @@ +class C() +object C { + val c = apply() // error +} \ No newline at end of file diff --git a/tests/new/i15414.scala b/tests/new/i15414.scala deleted file mode 100644 index eaa7a540df8f..000000000000 --- a/tests/new/i15414.scala +++ /dev/null @@ -1,4 +0,0 @@ -class C() -object C { - val c = apply() -} \ No newline at end of file