Skip to content

Expressiveness shortcoming when composing functions over capturing data #16268

Open
@odersky

Description

@odersky

Compiler version

3.2.2-RC1

Minimized example

import language.experimental.captureChecking
class Tree
case class Thicket(trees: List[Tree]) extends Tree

def test1(segments: List[{*} Tree]) =
  val elems = segments flatMap { (t: {*} Tree) => t match // error
    case ts: Thicket => ts.trees.tail
    case t => Nil
  }
  elems

Output

5 |  val elems = segments flatMap { (t: {*} Tree) => t match // error
  |                               ^
  |                      Found:    ? ({*} Tree) -> ? IterableOnce[? Tree]
  |                      Required: (box {*} Tree) => IterableOnce[box ? Tree]
6 |    case ts: Thicket => ts.trees.tail
7 |    case t => Nil
8 |  }

Expectation

Not sure. The problem is that box adaptation refuses to work since the box is over the universal set {*}. To compare, the following program compiles OK:

def test3(c: {*} Any)(segments: List[{c} Tree]) =
  val elems = segments flatMap { (t: {c} Tree) => t match
    case ts: Thicket => ts.trees.tail
    case t => Nil
  }
  elems

Here box adaptation works since the required type is

(box {c} Tree) => IterableOnce[box ? Tree]

It seems reasonable that something like this should also work for {*}. If not, we seem to have a shortcoming in applying higher-order functions to data with universal capabilities. But I don't know at present what should be tweaked. Is it

  • the rules for box adapation, or
  • the way we propagate boxes into function types?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions