Skip to content

Type checking error when mixing inline defs, match types, and applied type constructors #8321

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
mpilquist opened this issue Feb 15, 2020 · 2 comments · Fixed by #17482
Closed

Comments

@mpilquist
Copy link
Contributor

mpilquist commented Feb 15, 2020

minimized code

scala> inline def concat[A <: Tuple, B <: Tuple](a: Option[A], b: Option[B]): Option[Tuple.Concat[A, B]] =
     |   a.zip(b).map(_ ++ _)
def concat
  [A <: Tuple, B <: Tuple]
    (a: Option[A], b: Option[B]): Option[Tuple.Concat[A, B]]

scala> concat(Some(1, 2), Some(3, 4)) // This should work
1 |concat(Some(1, 2), Some(3, 4))
  |^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |Found:    Int *: Int *: scala.Tuple.Concat[Unit, (Int, Int)]
  |Required: Int *: scala.Tuple.Concat[Int *: Unit, Singleton & (Int, Int)]
  | This location contains code that was inlined from rs$line$12:2

scala> inline def concat2[A <: Tuple, B <: Tuple](a: Option[A], b: Option[B]): Option[Tuple.Concat[A, B]] =
     |   a.zip(b).map((a, b) => (a ++ b).asInstanceOf[Tuple.Concat[A, B]])
def concat2
  [A <: Tuple, B <: Tuple]
    (a: Option[A], b: Option[B]): Option[Tuple.Concat[A, B]]

scala> concat2(Some(1, 2), Some(3, 4))
val res5: Option[(Int, Int, Int, Int)] = Some((1,2,3,4))

scala> inline def concat3[A <: Tuple, B <: Tuple](a: A, b: B): Tuple.Concat[A, B] =
     |   a ++ b
def concat3[A <: Tuple, B <: Tuple](a: A, b: B): Tuple.Concat[A, B]

scala> concat3((1, 2), (3, 4))
val res7: (Int, Int, Int, Int) = (1,2,3,4)

Both concat2 and concat3 work. Removing inline from concat also works.

@smarter
Copy link
Member

smarter commented Feb 27, 2020

  |Found:    Int *: Int *: scala.Tuple.Concat[Unit, (Int, Int)]
  |Required: Int *: scala.Tuple.Concat[Int *: Unit, Singleton & (Int, Int)]

When _ ++ _ gets inlined, its result is typed as Tuple.Concat[(Int, Int), that.type], which is a subtype of the expected type here, but TypeAssigner then widens that type (because that is a local binding of the inlined tree) to Tuple.Concat[(Int, Int), (Int, Int)] which no longer conforms to the expected type.

To fix that we need to:

@OlivierBlanvillain
Copy link
Contributor

I could reproduce the bug without match types by changing the return type of ++ to a covariant trait:

trait Concat1[X <: Tuple, +Y <: Tuple]

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

Successfully merging a pull request may close this issue.

4 participants