Skip to content
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

Type inference issue with 2.9.0.RC3 for arities 21 and 22, but not 1 to 20 #4545

Closed
scabug opened this issue May 4, 2011 · 7 comments
Closed
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented May 4, 2011

[Edited for brevity and accuracy.]

Compiles with 2.8.1, fails with 2.9.0.RC1 through current.

object Test {  
  def f[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T](table: Tuple20[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T])(fun: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => Unit) {
  }
  def g[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U](table: Tuple21[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U])(fun: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => Unit) {
  }

  def g20 = f(
    (  1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1)
  ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t)) => () }
  
  def g21 = g(
      (1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1)
  ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u)) => () }
}

Failure in rc:

c.scala:13: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: Function21[Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Unit]
  ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u)) => () }
    ^
one error found
@scabug
Copy link
Author

scabug commented May 4, 2011

Imported From: https://issues.scala-lang.org/browse/SI-4545?orig=1
Reporter: @bvenners
Other Milestones: 2.10.0
Attachments:

  • RC3Bug.scala (created on May 4, 2011 5:34:34 PM UTC, 26874 bytes)

@scabug
Copy link
Author

scabug commented May 4, 2011

@paulp said:
Fascinating bug. However it is in RC1. I'm pretty confident of that fact because I can reproduce the absence of the bug in 2.8.1, but all the rcs show the bug.

@scabug
Copy link
Author

scabug commented May 4, 2011

@paulp said:
Reduced by a couple orders of magnitude, and removing the red herrings of implicit conversions and overloaded varargs polymorphic applies, and changed to use a partial function because the error message is much clearer (and shorter.)

object Test {  
  def f[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T](table: Tuple20[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T])(fun: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => Unit) {
  }
  def g[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U](table: Tuple21[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U])(fun: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => Unit) {
  }

  def g20 = f(
    (  1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1)
  ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t)) => () }
  
  def g21 = g(
      (1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1)
  ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u)) => () }
}

This compiles in 2.8. In rc1 through current it fails:

c.scala:13: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: Function21[Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Unit]
  ) { case ((a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u)) => () }
    ^
one error found

@scabug
Copy link
Author

scabug commented May 10, 2011

@dragos said:
Adriaan, can you please have a look?

@scabug
Copy link
Author

scabug commented May 10, 2011

@adriaanm said:
classic off-by-one, I'd say (as well as the poster child for sane variable names):

now:

    def isFunctionType(tp: Type): Boolean = tp.normalize match {
      case TypeRef(_, sym, args) if args.nonEmpty =>
        val len = args.length
        len < MaxFunctionArity && sym == FunctionClass(len - 1)
      case _ =>
        false
    }

i claim this is more clear as well as correct:

    def isFunctionType(tp: Type): Boolean = tp.normalize match {
      case TypeRef(_, sym, args) if args.nonEmpty =>
        val arity = args.length - 1
        arity <= MaxFunctionArity && sym == FunctionClass(arity)
      case _ =>
        false
    }

@scabug
Copy link
Author

scabug commented May 12, 2011

@paulp said:
Replying to [comment:5 moors]:

classic off-by-one, I'd say (as well as the poster child for sane variable names):

But how will lenny respond to this blatant attempt to exclude him?

Now I see how creates a class "off-by-two" bug (as this fails at both 21 and 22.) One takes this:

  args.length - 1 <= MaxFunctionArity

And cleverly turns it into this:

val len = args.length
len < MaxFunctionArity

Adding one and changing from <= to < must cancel each other out, right?

At least the perpetrator of this was nobly trying to make things faster by eliminating some of the many calls to list.length. He deserves a medal, not your fencepost scorn.

@scabug
Copy link
Author

scabug commented Mar 30, 2012

@paulp said:
Fixed in 75e584bd0c , sorry it took so long.

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

No branches or pull requests

2 participants