scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

Untupled parameters in context functions aren't provided as givens

Open coreywoodfield opened this issue 4 months ago • 7 comments

Compiler version

3.5.1

Minimized code

case class A(a: Int)

def foo(f: ((Ordering[A], Any)) ?=> Unit) = ()

// compiles: parameter untupling occurs for the ContextFunction
foo { (ordA, ordB) ?=>
  (0 to 5).map(A(_)).sorted(using ordA)
  // doesn't compile: ordA isn't provided as a given
  (0 to 5).map(A(_)).sorted
}

def bar(f: (Ordering[A], Any) ?=> Unit) = ()

bar { (ordA, ordB) ?=>
  // compiles: if no untupling takes place, all parameters are provided as givens
  (0 to 5).map(A(_)).sorted
}

Output

-- [E172] Type Error: .../Test.scala:9:29 
120 |    (0 to 5).map(A(_)).sorted
    |                             ^
    |No implicit Ordering defined for B..
    |I found:
    |
    |    scala.math.Ordering.comparatorToOrdering[B](
    |      /* missing */summon[java.util.Comparator[B]])
    |
    |But no implicit values were found that match type java.util.Comparator[B]
    |
    |where:    B is a type variable with constraint >: MultiServiceTest.this.A
    |.
    |
    |One of the following imports might make progress towards fixing the problem:
    |
    |  import scala.math.Ordering.comparatorToOrdering
    |  import scala.math.Ordering.ordered
    |
one error found

Expectation

I expected the parameters to be provided as givens whether or not the context function was subject to untupling. The context functions passed to foo and bar are identical except in body, so it's surprising that they don't function identically.

The reference on parameter untupling says

The tuple parameter is decomposed and its elements are passed directly to the underlying function.

which to me suggests that the "underlying function" shouldn't ever know that its parameters were untupled.

coreywoodfield avatar Oct 16 '24 21:10 coreywoodfield