Skip to content

Commit

Permalink
Allow autotupling if fn's param is a type param (#21741)
Browse files Browse the repository at this point in the history
Fixes #21682
  • Loading branch information
odersky authored Nov 13, 2024
2 parents bed0e86 + 9d2aeac commit 7243053
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 1 deletion.
14 changes: 13 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2237,7 +2237,19 @@ trait Applications extends Compatibility {

def isCorrectUnaryFunction(alt: TermRef): Boolean =
val formals = params(alt)
formals.length == 1 && ptIsCorrectProduct(formals.head, args)
formals.length == 1 && {
formals.head match
case formal: TypeParamRef =>
// While `formal` isn't a tuple type of the correct arity,
// it's a type parameter (a method type parameter presumably)
// so check its bounds allow for a tuple type of the correct arity.
// See i21682 for an example.
val tup = defn.tupleType(args.map(v => if v.tpt.isEmpty then WildcardType else typedAheadType(v.tpt).tpe))
val TypeBounds(lo, hi) = formal.paramInfo
lo <:< tup && tup <:< hi
case formal =>
ptIsCorrectProduct(formal, args)
}

val numArgs = args.length
if numArgs > 1
Expand Down
15 changes: 15 additions & 0 deletions tests/pos/i21682.1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
sealed abstract class Gen[+T1]
given [T2]: Conversion[T2, Gen[T2]] = ???

trait Show[T3]
given Show[Boolean] = ???
given [A1: Show, B1: Show, C1: Show]: Show[(A1, B1, C1)] = ???

object ForAll:
def apply[A2: Show, B2](f: A2 => B2): Unit = ???
def apply[A3: Show, B3: Show, C3](f: (A3, B3) => C3): Unit = ???
def apply[A4: Show, B4](gen: Gen[A4])(f: A4 => B4): Unit = ???

@main def Test =
ForAll: (b1: Boolean, b2: Boolean, b3: Boolean) =>
???
7 changes: 7 additions & 0 deletions tests/pos/i21682.2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
object ForAll:
def apply[A1, B](f: A1 => B): Unit = ???
def apply[A1, A2, B](f: (A1, A2) => B): Unit = ???

@main def Test =
ForAll: (b1: Boolean, b2: Boolean, b3: Boolean) =>
???
4 changes: 4 additions & 0 deletions tests/pos/i21682.3.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Test:
def foo[A1 >: (Nothing, Boolean, Nothing) <: (Any, Boolean, Any), B](f: A1 => B): Unit = ???
def test(): Unit =
val res4 = this.foo((b1: Boolean, b2: Boolean, b3: Boolean) => ???)

0 comments on commit 7243053

Please sign in to comment.