Skip to content

Match type on Functions #13800

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Adam-Vandervorst opened this issue Oct 23, 2021 · 2 comments
Closed

Match type on Functions #13800

Adam-Vandervorst opened this issue Oct 23, 2021 · 2 comments
Assignees

Comments

@Adam-Vandervorst
Copy link

Adam-Vandervorst commented Oct 23, 2021

Compiler version

3.0.2

3.1.0 makes the Scala plugin for Idea think it needs Scala 2 syntax, where can I report this?

Minimized code

// bound for Function in feature request
// type of domain and codomain for Function in feature request
type Domain[F] <: Tuple = F match
  case Function1[r, _] => Tuple1[r]
  case Function2[r1, r2, _] => Tuple2[r1, r2]
  case Function3[r1, r2, r3, _] => Tuple3[r1, r2, r3]

@main def m = 
  val f: Int => Int = _*2
  val g: (Int, Int) => Int = _*_
  val h: (Boolean, Int, Int) => Int = if _ then _ else _
  val a: Domain[f.type] = Tuple1(3)
  val b: Domain[g.type] = Tuple2(3, 4)
  val c: Domain[h.type] = Tuple3(false, 5, 6)

  // println(f.tupled(b)) in feature request
  println(g.tupled(b))
  println(h.tupled(c))

Output

Found:    (Int, Int)
Required: Domain[(g : (Int, Int) => Int)]
  val b: Domain[g.type] = Tuple2(3, 4)

Found:    (Boolean, Int, Int)
Required: Domain[(h : (Boolean, Int, Int) => Int)]
  val c: Domain[h.type] = Tuple3(false, 5, 6)

Found:    (b : Domain[(g : (Int, Int) => Int)])
Required: (Int, Int)
  println(g.tupled(b))

Found:    (c : Domain[(h : (Boolean, Int, Int) => Int)])
Required: (Boolean, Int, Int)
  println(h.tupled(c))

Expectation

To run. Sadly with the uninformative error messages I can not say much more.
Changing the order in the match type changes which cases error, so I guess it's all matching to the first case.

The feature requests I'm referring to (that would avoid this snag) is lampepfl/dotty-feature-requests#246.


EDIT: Add def in code example

@odersky
Copy link
Contributor

odersky commented Oct 24, 2021

The example is not even syntactically correct. If I fix the syntax error for @main m and run it I also see something different:

-- [E007] Type Mismatch Error: test.scala:11:32 --------------------------------
11 |  val b: Domain[g.type] = Tuple2(3, 4)
   |                          ^^^^^^^^^^^^
   |            Found:    (Int, Int)
   |            Required: Domain[(g : (Int, Int) => Int)]
   |
   |            Note: a match type could not be fully reduced:
   |
   |              trying to reduce  Domain[(g : (Int, Int) => Int)]
   |              failed since selector  (g : (Int, Int) => Int)
   |              does not match  case r => _ => Tuple1[r]
   |              and cannot be shown to be disjoint from it either.
   |              Therefore, reduction cannot advance to the remaining cases
   |
   |                case (r1, r2) => _ => (r1, r2)
   |                case (r1, r2, r3) => _ => (r1, r2, r3)

longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: test.scala:13:32 --------------------------------
13 |  val c: Domain[h.type] = Tuple3(false, 5, 6)
   |                          ^^^^^^^^^^^^^^^^^^^
   |            Found:    (Boolean, Int, Int)
   |            Required: Domain[(h : (Boolean, Int, Int) => Int)]
   |
   |            Note: a match type could not be fully reduced:
   |
   |              trying to reduce  Domain[(h : (Boolean, Int, Int) => Int)]
   |              failed since selector  (h : (Boolean, Int, Int) => Int)
   |              does not match  case r => _ => Tuple1[r]
   |              and cannot be shown to be disjoint from it either.
   |              Therefore, reduction cannot advance to the remaining cases
   |
   |                case (r1, r2) => _ => (r1, r2)
   |                case (r1, r2, r3) => _ => (r1, r2, r3)

longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: test.scala:16:19 --------------------------------
16 |  println(g.tupled(b))
   |                   ^
   |                   Found:    (b : Domain[(g : (Int, Int) => Int)])
   |                   Required: (Int, Int)

longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: test.scala:17:19 --------------------------------
17 |  println(h.tupled(c))
   |                   ^
   |                Found:    (c : Domain[(h : (Boolean, Int, Int) => Int)])
   |                Required: (Boolean, Int, Int)

longer explanation available when compiling with `-explain`

To run. Sadly with the uninformative error messages I can not say much more.

Did the explanations not show up in your test? That could point to a problem in IntelliJ's setup.

The explanations make sense. Functions are traits that can be inherited arbitrarily. In particular, it is possible that an object inherits function types with different arities at the same time. So the compiler is correct to reject this.

@odersky odersky closed this as completed Oct 24, 2021
@Adam-Vandervorst
Copy link
Author

Adam-Vandervorst commented Oct 25, 2021

@odersky IntelliJ's Idea indeed did hide the elaborate explanation that comes after Note:.

Does

it is possible that an object inherits function types with different arities at the same time.

correspond to

and cannot be shown to be disjoint from it either.

in the compiler's note?
I would like to read up more about it, specifically why this forms a problem.


Is there any way in which Domain can be mimicked (without adding it natively)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants