Skip to content

Commit

Permalink
Apply insertion for nilary case companion
Browse files Browse the repository at this point in the history
  • Loading branch information
som-snytt committed Feb 2, 2024
1 parent 4bcadd7 commit d8958d0
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 8 deletions.
12 changes: 8 additions & 4 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1125,12 +1125,15 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}

// if user wrote case companion C for expected function type, use C.apply or (C.apply _).tupled
def adaptApplyInsertion(): Tree =
def adaptApplyInsertion(): Tree = doAdaptApplyInsertion(retry = false)

def doAdaptApplyInsertion(retry: Boolean): Tree =
if (currentRun.isScala3Cross && !isPastTyper && tree.symbol != null && tree.symbol.isModule && tree.symbol.companion.isCase && isFunctionType(pt))
silent(_.typed(atPos(tree.pos)(Select(tree, nme.apply)))) match {
silent(_.typed(atPos(tree.pos)(Select(tree, nme.apply)), mode, if (retry) WildcardType else pt)) match {
case SilentResultValue(applicator) =>
val arity = definitions.functionArityFromType(applicator.tpe)
functionOrPfOrSamArgTypes(pt) match {
if (arity < 0) EmptyTree
else functionOrPfOrSamArgTypes(pt) match {
case arg :: Nil if definitions.isTupleType(arg) && arg.typeArgs.lengthCompare(arity) == 0 =>
val tupled = typed(atPos(tree.pos)(Select(applicator, nme.tupled)), mode, pt)
if (!tupled.isErroneous) {
Expand All @@ -1142,9 +1145,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case args if args.lengthCompare(arity) == 0 =>
val msg = s"The method `apply` is inserted. The auto insertion will be deprecated, please write `${tree.symbol.name}.apply` explicitly."
context.deprecationWarning(tree.pos, tree.symbol, msg, "2.13.13")
typed(atPos(tree.pos)(Select(tree, nme.apply)), mode, pt)
applicator
case _ => EmptyTree
}
case _ if !retry => doAdaptApplyInsertion(retry = true)
case _ => EmptyTree
}
else EmptyTree
Expand Down
2 changes: 1 addition & 1 deletion src/reflect/scala/reflect/internal/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ trait Definitions extends api.StandardDefinitions {
class VarArityClass(name: String, maxArity: Int, countFrom: Int = 0, init: Option[ClassSymbol] = None) extends VarArityClassApi {
private[this] val offset = countFrom - init.size
private def isDefinedAt(i: Int) = i < seq.length + offset && i >= offset
val seq: IndexedSeq[ClassSymbol] = (init ++: countFrom.to(maxArity).map { i => getRequiredClass("scala." + name + i) }).toVector
val seq: IndexedSeq[ClassSymbol] = (init ++: countFrom.to(maxArity).map(i => getRequiredClass(s"scala.$name$i"))).toVector
private[this] val symSet = new SymbolSet(seq.toList)
def contains(sym: Symbol): Boolean = symSet.contains(sym)
def apply(i: Int) = if (isDefinedAt(i)) seq(i - offset) else NoSymbol
Expand Down
19 changes: 16 additions & 3 deletions test/files/neg/t3664c.check
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
t3664c.scala:9: error: type mismatch;
t3664c.scala:13: error: type mismatch;
found : C.type
required: ((Int, Int, Int)) => C
def f(xs: List[(Int, Int, Int)]): List[C] = xs.map(C) // hard error
^
t3664c.scala:11: error: type mismatch;
t3664c.scala:15: error: type mismatch;
found : ((Int, Int)) => C
required: ((Int, Int, Int)) => C
def g(xs: List[(Int, Int, Int)]): List[C] = xs.map(C.tupled) // hard error
^
2 errors
t3664c.scala:17: error: type mismatch;
found : D.type
required: ((Int, Int)) => D
def d(xs: List[(Int, Int)]): List[D] = xs.map(D) // hard error
^
t3664c.scala:19: warning: An unapplied 0-arity method was eta-expanded (due to the expected type () => E), rather than applied to `()`.
Write E.apply() to invoke method apply, or change the expected type.
val e: () => E = E
^
t3664c.scala:19: warning: The method `apply` is inserted. The auto insertion will be deprecated, please write `E.apply` explicitly.
val e: () => E = E
^
2 warnings
3 errors
8 changes: 8 additions & 0 deletions test/files/neg/t3664c.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@

case class C(i: Int, j: Int)

abstract case class D(i: Int, j: Int)

case class E()

class Test {
def f(xs: List[(Int, Int, Int)]): List[C] = xs.map(C) // hard error

def g(xs: List[(Int, Int, Int)]): List[C] = xs.map(C.tupled) // hard error

def d(xs: List[(Int, Int)]): List[D] = xs.map(D) // hard error

val e: () => E = E
}

0 comments on commit d8958d0

Please sign in to comment.