Confusion about wildcard arguments in types

According to the documentation, C[_] is a shorthand for [X] =>> C[X] from Scala 3.2 onwards.

However, they don’t seem to behave identically:

trait B[T]

def foo[C[_] <: B[_], T]: C[T] = ???

def bar: Unit =
  foo[[X] =>> B[X], Int]
  foo[B[_], Int] // Error: Type argument B[?] does not conform to upper bound [_] =>> B[?]

It looks like B[_] is still interpreted as B[?]. However, that is not supposed to happen from Scala 3.2 onwards:

  1. In Scala 3.0, both _ and ? are legal names for wildcards.
  2. In Scala 3.1, _ is deprecated in favor of ? as a name for a wildcard. A -rewrite option is available to rewrite one to the other.
  3. In Scala 3.2, the meaning of _ changes from wildcard to placeholder for type parameter.

Am I missing something?

If not, is there a way to force proper behavior from the compiler, with some kind of “future” flag? These error messages are very confusing.

More compiler behavior that seems at odds with the documentation about type lambdas:

trait A
trait B[T] extends A
type F = [T] =>> A

// Shouldn't these all mean the same thing?
summon[B <:< F] // Kind error
summon[B[_] <:< F[_]]
summon[B[_] <:< ([T] =>> F[T])] // Kind error

// Should these not all mean the same thing?
class C[D <: F] // Error: type F takes parameters
class G[D[_] <: F[_]]
class E[D[_] <: ([T] =>> F[T])]

// These all compile, at least, so they hopefully mean the same thing.
C[B]
C[B[_]]
C[[T] =>> B[T]]

See also this discussion.

I submitted a bug report, as well as a PR to improve the documentation.

1 Like