Bogdan Vakulenko
Bogdan Vakulenko

Reputation: 3390

Type inference on abstract type member

val s1: ({type T <: String})#T = "some string" // failed

val s2: ({type T = String})#T = "some string" // compiled

Why first line failed to compile? Why T can't be a string there?

Edit:

Simplified case without lambdas.(Not sure if that is exactly the same from type system perspective)

trait K {
  type T <: String
  val s1:T = "some string" // failed
}

Edit 2 :

one more case

type  K  = {type T <: String}

val s1:K#T = "some string" // failed

def test(in: K#T):K#T = in // can be used as output type as well

Upvotes: 0

Views: 92

Answers (3)

Dmytro Mitin
Dmytro Mitin

Reputation: 51658

k.T is a path-dependent type. It can be different for every instance k of K.

trait K {
  type T <: String
  val s1: T /*= "some string"*/
}

object K1 extends K {
  override type T = Null
  override val s1 = null
}

object K2 extends K {
  override type T = Nothing
  override val s1 = ???
}

object K3 extends K {
  override type T = String with Int
  override val s1 = ???
}


object K4 extends K {
  override type T = shapeless.Witness.`"some other string"`.T
  override val s1 = "some other string"
}

object K5 extends K {
  // K5.T is abstract
  override val s1 = ???
}

object K6 extends K {
  // K6.T is abstract but different from K5.T
  override val s1 = ???
}

Upvotes: 2

Alexey Romanov
Alexey Romanov

Reputation: 170735

The issue is not that T can't be a string, but that it can potentially be something else, to which a string can't be assigned (e.g. Null or Nothing).

Upvotes: 2

jwvh
jwvh

Reputation: 51271

I believe it has to do with the variance relationship to the return (result) type.

Notice that T is accepted as an input String ...

def s3[T <: String](s:T) = "some string" // T as input
s3("blah")  //input T = String

... but not as an output String.

def s3[T <: String](s:T):T = "some string" // fails to compile
//                      ^^^

But reverse the T-to-String relationship and this works ...

def s3[T >: String](s:T):T = "some string" // T as input and output
s3("blah")

... and so does this.

val s1: ({type T >: String})#T = "some string" // good

Upvotes: 4

Related Questions