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

Compilation error invoking overloaded function with explicit type parameter #10074

Open
scabug opened this issue Nov 21, 2016 · 8 comments
Open

Comments

@scabug
Copy link

scabug commented Nov 21, 2016

Trying to compile specified file results an error:
[error] The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ?
[error] a.overloadedF[Int]{

If you omit type parameter in method invocation or remove second overloaded function, everything works fine.

@scabug
Copy link
Author

scabug commented Nov 21, 2016

Imported From: https://issues.scala-lang.org/browse/SI-10074?orig=1
Reporter: Kirill Yankov (manonthegithub)
Affected Versions: 2.11.8, 2.12.0
See #9386
Attachments:

@scabug
Copy link
Author

scabug commented Nov 21, 2016

@SethTisue said:
minimized:

object A {
  f[Int]{case _ => 1}
  def f[T](f: Any => T) = ()
  def f[T](f: Any => T, v: Int) = ()
}

@scabug
Copy link
Author

scabug commented Nov 21, 2016

@SethTisue said:
If there's a bug here, is it that the version with the explicit type does compile, or is it that the version without the explicit type doesn't compile? I'd need to go over SLS 6.26 with a fine-tooth comb (along with SLS 8.5 which is mentioned in the error).

@scabug
Copy link
Author

scabug commented Nov 21, 2016

@som-snytt said:
I expected the shape test to allow arg typed with expected type, as if not overloaded.

But the behavior has history on its side.

$ scala29
Welcome to Scala version 2.9.3 (OpenJDK 64-Bit Server VM, Java 1.6.0_38).
Type in expressions to have them evaluated.
Type :help for more information.

scala> object Y {
     |   def f[A](g: PartialFunction[Any, A]): A = g(42)
     |   def f[A](i: Int, g: PartialFunction[Any, A]): A = g(i)
     | }
defined module Y

scala> Y.f { case _ => 17 }
res0: Int = 17

scala> Y.f[Int] { case _ => 17 }
<console>:9: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
              Y.f[Int] { case _ => 17 }
                       ^
<console>:9: error: overloaded method value f with alternatives:
  (i: Int,g: PartialFunction[Any,Int])Int <and>
  (g: PartialFunction[Any,Int])Int
 cannot be applied to (<error> => Int)
              Y.f[Int] { case _ => 17 }
                 ^

@scabug
Copy link
Author

scabug commented Nov 21, 2016

@som-snytt said:
Maybe too much typechecking happens during shape test. Linking another example of mechanics of overload resolution affecting the result.

@scabug
Copy link
Author

scabug commented Nov 22, 2016

@retronym said (edited on Nov 22, 2016 12:15:23 AM UTC):
Looks like an oversight in the implementation to me. Typer::preSelectOverloaded is responsible for filtering out alternatives based on arity (also based on the "shape type" of function literal arguments), but this is bypassed in this case.

      def preSelectOverloaded(fun: Tree): Tree = {
        if (fun.hasSymbolField && fun.symbol.isOverloaded) {

We have:

fun = A.this.f[Int] / TypeApply(Select(...., f), TypeTree(Int))
fun.hasSymbolField = false
fun.tpe = OverloadedType((f: Any => Int, v: Int)Unit <and> (f: Any => Int)Unit)
fun.fun.symbol.info = [T](f: Any => T, v: Int)Unit <and> (f: Any => T)Unit

After filtering, we can end up with a new symbol: either a single method symbol, or a new overloaded symbol with fewer alternatives. This needs to be assigned back to the tree fun. We can't just assign

The fix is conceptually easy enough ("generalize that code a little!") but there are a lot of details to line up. I took a hacky attempt at it : https://github.com/scala/scala/compare/2.12.x...retronym:ticket/10074?expand=1

but I'm not planning to pursue this right now.

@scabug
Copy link
Author

scabug commented Nov 22, 2016

Kirill Yankov (manonthegithub) said (edited on Nov 22, 2016 4:20:34 PM UTC):
I don't know the specifics if this is the same place in code or not, but overloading with curried params results the same problem, regardless of using or omitting type parameter...

object A{

  fun[Int]{
    case _ => 1
  }

  def fun[T](f: PartialFunction[Any, T]): T = {
    f(1)
  }

  def fun[T](v: Int)(f: PartialFunction[Any, T]) = {
    f(v)
  }

}

@som-snytt
Copy link

Partial progression from 2.12, M5, almost RC1:

$ scalac t10074.scala
t10074.scala:3: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
  f[Int] { case _ => 1 }
         ^
t10074.scala:3: error: overloaded method value f with alternatives:
  (v: Int)(g: PartialFunction[Any,Int])Int <and>
  (g: PartialFunction[Any,Int])Int
 cannot be applied to (<error> => Int)
  f[Int] { case _ => 1 }
   ^
t10074.scala:4: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
  m { case _ => 1 }
    ^
three errors found
$ scalacm t10074.scala
t10074.scala:3: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
  f[Int] { case _ => 1 }
         ^
t10074.scala:3: error: overloaded method value f with alternatives:
  (v: Int)(g: PartialFunction[Any,Int])Int <and>
  (g: PartialFunction[Any,Int])Int
 cannot be applied to (<error> => Int)
  f[Int] { case _ => 1 }
   ^
two errors found
$ ~/workspace/scala-2.13/build/pack/bin/scalac t10074.scala
t10074.scala:3: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: ?
  f[Int] { case _ => 1 }
         ^
one error found

where

$ cat t10074.scala

object X {
  f[Int] { case _ => 1 }
  m { case _ => 1 }

  def f[T](g: PartialFunction[Any, T]): T = g(1)
  def f[T](v: Int)(g: PartialFunction[Any, T]) = g(v)
  def m(g: PartialFunction[Any, Int]): Int = g(1)
  def m(v: Int)(g: PartialFunction[Any, Int]) = g(v)
}

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

2 participants