Skip to content

WIP Fix SIP-23 (Literal Types) #1599

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

Merged
merged 10 commits into from
Jan 25, 2020
42 changes: 24 additions & 18 deletions _sips/sips/2014-06-27-42.type.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,21 @@ Lightbend Scala compiler.
```

+ The `.type` singleton type forming operator can be applied to values of all subtypes of `Any`.
To prevent the compiler from widening our return type we assign to a final val.
```
def foo[T](t: T): t.type = t
foo(23) // result is 23: 23
final val bar = foo(23) // result is bar: 23
```

+ The presence of an upper bound of `Singleton` on a formal type parameter indicates that
singleton types should be inferred for type parameters at call sites.
singleton types should be inferred for type parameters at call sites. To help see this
we introduce type constructor `Id` to prevent the compiler from widening our return type.
```
def wide[T](t: T): T = t
wide(13) // result is 13: Int
def narrow[T <: Singleton](t: T): T = t
narrow(23) // result is 23: 23
type Id[A] = A
def wide[T](t: T): Id[T] = t
wide(23) // result is 23: Id[Int]
def narrow[T <: Singleton](t: T): Id[T] = t
narrow(23) // result is 23: Id[23]
```

+ Pattern matching against literal types and `isInstanceOf` tests are
Expand All @@ -109,15 +112,15 @@ Lightbend Scala compiler.
(1: Any) match {
case one: 1 => true
case _ => false
} // result is true
(1: Any).isInstanceOf[1] // result is true
} // result is true: Boolean
(1: Any).isInstanceOf[1] // result is true: Boolean
```

+ A `scala.ValueOf[T]` type class and corresponding `scala.Predef.valueOf[T]` operator has been
added yielding the unique value of types with a single inhabitant.
```
def foo[T](implicit v: ValueOf[T]): T = v.value
foo[13] // result is 13: 13
foo[13] // result is 13: Int
```


Expand Down Expand Up @@ -384,7 +387,7 @@ applications which work with large datasets.
Example,
```
def foo[T](t: T): t.type = t
foo(23) // result is 23: 23
final val bar = foo(23) // result is bar: 23
```

+ The presence of an upper bound of `Singleton` on a formal type parameter indicates that
Expand Down Expand Up @@ -469,12 +472,15 @@ applications which work with large datasets.

Example,
```
def wide[T](t: T): T = t
wide(13) // result is 13: Int
def narrow[T <: Singleton](t: T): T = t
narrow(23) // result is 23: 23
type Id[A] = A
def wide[T](t: T): Id[T] = t
wide(23) // result is 23: Id[Int]
def narrow[T <: Singleton](t: T): Id[T] = t
narrow(23) // result is 23: Id[23]
```

Note that we introduce the type constructor `Id` simply to avoid widening of the return type.

+ A `scala.ValueOf[T]` type class and corresponding `scala.Predef.valueOf[T]` operator has been
added yielding the unique value of types with a single inhabitant.

Expand All @@ -498,7 +504,7 @@ applications which work with large datasets.
Example,
```
def foo[T](implicit v: ValueOf[T]): T = v.value
foo[13] // result is 13: 13
foo[13] // result is 13: Int
```

A method `valueOf` is also added to `scala.Predef` analogously to existing operators such as
Expand All @@ -513,7 +519,7 @@ applications which work with large datasets.
object Foo
valueOf[Foo.type] // result is Foo: Foo.type

valueOf[23] // result is 23: 23
valueOf[23] // result is 23: Int
```

+ Pattern matching against literal types and `isInstanceOf` tests are
Expand All @@ -533,8 +539,8 @@ applications which work with large datasets.
(1: Any) match {
case one: 1 => true
case _ => false
} // result is true
(1: Any).isInstanceOf[1] // result is true
} // result is true: Boolean
(1: Any).isInstanceOf[1] // result is true: Boolean
```

Importantly, that doesn't include `asInstanceOf` as that is a user assertion to the compiler, with
Expand Down