Skip to content

Type parameter inference fails when it's only constrained by a wildcard #2397

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
olafurpg opened this issue May 8, 2017 · 3 comments
Closed

Comments

@olafurpg
Copy link
Contributor

olafurpg commented May 8, 2017

The following code compiles with Scala 2.x

package bar
import java.nio.file._
import java.util.stream.Collectors
object foo {
  Files.walk(Paths.get("")).collect(Collectors.toList[Path])
}

while dotc at commit 5093126 reports a type error

-- [E007] Type Mismatch Error: foo.scala:5:36 ----------------------------------
5 |  Files.walk(Paths.get("")).collect(Collectors.toList[Path])
  |                                    ^^^^^^^^^^^^^^^^^^^^^^^
  |       found:    java.util.stream.Collector[java.nio.file.Path, _,
  |         java.util.List[java.nio.file.Path]
  |       ]
  |       required: java.util.stream.Collector[_ >: java.nio.file.Path, A, R]
  |
  |       where:    A is a type variable
  |                 R is a type variable

one error found
@smarter
Copy link
Member

smarter commented May 8, 2017

You can make it work by using an intermediate variable:

import java.nio.file._
import java.util.stream.Collectors

object Test {
  val x = Collectors.toList[Path]
  Files.walk(Paths.get("")).collect(x)
}

The issue is with the second type parameter of collect, which is x.A here. We cannot give it a more precise type because in the return type of toList it's just a Java wildcard. If we don't use an intermediate variable then we just have no way of representing it. scalac represents it as ?0 but I don't know how that works under the hood.

@smarter
Copy link
Member

smarter commented May 8, 2017

I've managed to minimize it so that it doesn't depend on Java APIs, just wildcards:

class Foo[A]

object Test {
  def foo[T](x: Foo[T]) = x

  foo((new Foo[Int]: Foo[_]))
}
12 |  foo((new Foo[Int]: Foo[_]))
   |      ^^^^^^^^^^^^^^^^^^^^^^
   |      found:    Foo[_]
   |      required: Foo[T]
   |      
   |      where:    T is a type variable

@smarter smarter changed the title Type Mismatch Error calling java API Type parameter inference fails when it's only constrained by a wildcard May 8, 2017
@odersky
Copy link
Contributor

odersky commented May 9, 2017

It's fixed with #2402. scalac is different because there types with wildcards are existentials, and existentials are unpacked before usage. The ?0 you are seeing is a skolem constant arising from unpacking.

@smarter smarter closed this as completed in f11cc5e May 9, 2017
smarter added a commit that referenced this issue May 9, 2017
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