Skip to content

Commit f79c8b2

Browse files
authored
Merge pull request #6558 from dotty-staging/change-tl-syntax
Use =>> for type lambdas
2 parents af7a49f + a01851d commit f79c8b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+148
-145
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -819,13 +819,13 @@ object desugar {
819819

820820
/** Expand
821821
*
822-
* <mods> opaque type T = [Xs] => R
822+
* <mods> opaque type T = [Xs] =>> R
823823
*
824824
* to
825825
*
826826
* <mods> opaque type T = T.T
827827
* synthetic object T {
828-
* synthetic opaque type T >: [Xs] => R
828+
* synthetic opaque type T >: [Xs] =>> R
829829
* }
830830
*
831831
* The generated companion object will later (in Namer) be merged with the user-defined

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ object Parsers {
851851
def toplevelTyp(): Tree = rejectWildcardType(typ())
852852

853853
/** Type ::= FunTypeMods FunArgTypes `=>' Type
854-
* | HkTypeParamClause `->' Type
854+
* | HkTypeParamClause `=>>' Type
855855
* | InfixType
856856
* FunArgTypes ::= InfixType
857857
* | `(' [ FunArgType {`,' FunArgType } ] `)'
@@ -922,9 +922,9 @@ object Parsers {
922922
else if (in.token == LBRACKET) {
923923
val start = in.offset
924924
val tparams = typeParamClause(ParamOwner.TypeParam)
925-
if (in.token == ARROW)
925+
if (in.token == TLARROW)
926926
atSpan(start, in.skipToken())(LambdaTypeTree(tparams, toplevelTyp()))
927-
else { accept(ARROW); typ() }
927+
else { accept(TLARROW); typ() }
928928
}
929929
else infixType()
930930

compiler/src/dotty/tools/dotc/parsing/Tokens.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,13 +195,15 @@ object Tokens extends TokensCommon {
195195
final val SUPERTYPE = 81; enter(SUPERTYPE, ">:")
196196
final val HASH = 82; enter(HASH, "#")
197197
final val VIEWBOUND = 84; enter(VIEWBOUND, "<%")
198-
final val QUOTE = 85; enter(QUOTE, "'")
198+
final val TLARROW = 85; enter(TLARROW, "=>>")
199+
200+
final val QUOTE = 86; enter(QUOTE, "'")
199201

200202
/** XML mode */
201203
final val XMLSTART = 96; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate
202204

203205
final val alphaKeywords: TokenSet = tokenRange(IF, MACRO)
204-
final val symbolicKeywords: TokenSet = tokenRange(USCORE, VIEWBOUND)
206+
final val symbolicKeywords: TokenSet = tokenRange(USCORE, TLARROW)
205207
final val keywords: TokenSet = alphaKeywords | symbolicKeywords
206208

207209
final val allTokens: TokenSet = tokenRange(minToken, maxToken)

compiler/test-resources/repl/i6474

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
scala> object Foo1 { type T[+A] = (A, Int) }
22
// defined object Foo1
3-
scala> object Foo2 { type T[+A] = [+B] => (A, B) }
3+
scala> object Foo2 { type T[+A] = [+B] =>> (A, B) }
44
// defined object Foo2
5-
scala> object Foo3 { type T[+A] = [+B] => [C] => (A, B) }
5+
scala> object Foo3 { type T[+A] = [+B] =>> [C] =>> (A, B) }
66
// defined object Foo3
77
scala> ((1, 2): Foo1.T[Int]): Foo1.T[Any]
88
val res0: (Any, Int) = (1,2)
@@ -14,7 +14,7 @@ scala> (1, 2): Foo3.T[Int][Int]
1414
| Missing type parameter for Foo3.T[Int][Int]
1515
scala> ((1, 2): Foo3.T[Int][Int][Int]): Foo3.T[Any][Int][Int]
1616
val res2: (Any, Int) = (1,2)
17-
scala> object Foo3 { type T[A] = [B] => [C] => (A, B) }
17+
scala> object Foo3 { type T[A] = [B] =>> [C] =>> (A, B) }
1818
// defined object Foo3
1919
scala> ((1, 2): Foo3.T[Int][Int][Int])
2020
val res3: (Int, Int) = (1,2)

docs/blog/_posts/2018-04-27-eighth-dotty-milestone-release.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ def foo[T](x: T) = x match {
6868
Normally type parameters in Scala are partitioned into kinds. First-level types are types of values.
6969
Higher-kinded types are type constructors such as `List` or `Map`. The kind of a type is indicated
7070
by the top type of which it is a subtype. Normal types are subtypes of `Any`, covariant single
71-
argument type constructors such as List are subtypes of `[+X] => Any`, and the `Map` type
72-
constructor is a subtype of `[X, +Y] => Any`.
71+
argument type constructors such as List are subtypes of `[+X] =>> Any`, and the `Map` type
72+
constructor is a subtype of `[X, +Y] =>> Any`.
7373

7474
Sometimes we would like to have type parameters that can have more than one kind, for instance to
7575
define an implicit value that works for parameters of any kind. This is now possible through a form
@@ -87,7 +87,7 @@ legal:
8787
f[Int]
8888
f[List]
8989
f[Map]
90-
f[[X] => String]
90+
f[[X] =>> String]
9191
```
9292

9393
**Note**: This feature is considered experimental and is only enabled under a compiler flag

docs/docs/internals/syntax.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ package private protected override return super sealed then
9999
throw trait true try type val var while
100100
with yield
101101
: = <- => <: :> # @
102+
=>>
102103
```
103104

104105
### Soft keywords
@@ -139,7 +140,7 @@ ClassQualifier ::= ‘[’ id ‘]’
139140
### Types
140141
```ebnf
141142
Type ::= { ‘erased’ | ‘given’} FunArgTypes ‘=>’ Type Function(ts, t)
142-
| HkTypeParamClause ‘=>’ Type TypeLambda(ps, t)
143+
| HkTypeParamClause ‘=>>’ Type TypeLambda(ps, t)
143144
| MatchType
144145
| InfixType
145146
FunArgTypes ::= InfixType

docs/docs/reference/contextual/typeclasses.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ implied ListMonad for Monad[List] {
5555
List(x)
5656
}
5757

58-
implied ReaderMonad[Ctx] for Monad[[X] => Ctx => X] {
58+
implied ReaderMonad[Ctx] for Monad[[X] =>> Ctx => X] {
5959
def (r: Ctx => A) flatMap [A, B] (f: A => Ctx => B): Ctx => B =
6060
ctx => f(r(ctx))(ctx)
6161
def pure[A](x: A): Ctx => A =

docs/docs/reference/new-types/type-lambdas-spec.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ title: "Type Lambdas - More Details"
66
## Syntax
77

88
```
9-
Type ::= ... | HkTypeParamClause ‘=>’ Type
9+
Type ::= ... | HkTypeParamClause ‘=>>’ Type
1010
HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
1111
HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (Id[HkTypeParamClause] | ‘_’) TypeBounds
1212
TypeBounds ::= [‘>:’ Type] [‘<:’ Type]
1313
```
1414

1515
### Type Checking
1616

17-
A type lambda such `[X] => F[X]` defines a function from types to types. The parameter(s) may carry bounds and variance annotations.
18-
If a parameter is is bounded, as in `[X >: L <: H] => F[X]` it is checked that arguments to the parameters conform to the bounds `L` and `H`.
17+
A type lambda such `[X] =>> F[X]` defines a function from types to types. The parameter(s) may carry bounds and variance annotations.
18+
If a parameter is is bounded, as in `[X >: L <: H] =>> F[X]` it is checked that arguments to the parameters conform to the bounds `L` and `H`.
1919
Only the upper bound `H` can be F-bounded, i.e. `X` can appear in it.
2020

2121
A variance annotation on a parameter indicates a subtyping relationship on type instances. For instance, given
2222
```scala
23-
type TL1 = [+A] => F[A]
24-
type TL2 = [-A] => F[A]
23+
type TL1 = [+A] =>> F[A]
24+
type TL2 = [-A] =>> F[A]
2525
```
2626
and two types `S <: T`, we have
2727
```scala
@@ -37,8 +37,8 @@ It is checked that variance annotations on parameters of type lambdas are respec
3737

3838
Assume two type lambdas
3939
```scala
40-
type TL1 = [v1 X >: L1 <: U1] => R1
41-
type TL2 = [v2 X >: L2 <: U2] => R2
40+
type TL1 = [v1 X >: L1 <: U1] =>> R1
41+
type TL2 = [v2 X >: L2 <: U2] =>> R2
4242
```
4343
where `v1` and `v2` are optional variance annotations: `+`, `-`, or absent.
4444
Then `TL1 <: TL2`, if
@@ -51,7 +51,7 @@ Then `TL1 <: TL2`, if
5151
Here we have relied on alpha renaming to bring match the two bound types `X`.
5252

5353
A partially applied type constructor such as `List` is assumed to be equivalent to
54-
its eta expansion. I.e, `List = [+X] => List[X]`. This allows type constructors
54+
its eta expansion. I.e, `List = [+X] =>> List[X]`. This allows type constructors
5555
to be compared with type lambdas.
5656

5757
## Relationship with Parameterized Type Definitions
@@ -62,7 +62,7 @@ type T[X] = R
6262
```
6363
is regarded as a shorthand for an unparameterized definition with a type lambda as right-hand side:
6464
```scala
65-
type T = [X] => R
65+
type T = [X] =>> R
6666
```
6767

6868
A parameterized abstract type
@@ -71,19 +71,19 @@ type T[X] >: L <: U
7171
```
7272
is regarded as shorthand for an unparameterized abstract type with type lambdas as bounds.
7373
```scala
74-
type T >: ([X] => L) <: ([X] => U)
74+
type T >: ([X] =>> L) <: ([X] =>> U)
7575
```
7676
However, if `L` is `Nothing` it is not parameterized, since `Nothing` is treated as a bottom type for all kinds. For instance,
7777
```scala
7878
type T[-X] <: X => ()
7979
```
8080
is expanded to
8181
```scala
82-
type T >: Nothing <: ([-X] => X => ())
82+
type T >: Nothing <: ([-X] =>> X => ())
8383
```
8484
instead of
8585
```scala
86-
type T >: ([X] => Nothing) <: ([-X] => X => ())
86+
type T >: ([X] =>> Nothing) <: ([-X] =>> X => ())
8787
```
8888

8989
The same expansions apply to type parameters. E.g.
@@ -92,7 +92,7 @@ The same expansions apply to type parameters. E.g.
9292
```
9393
is treated as a shorthand for
9494
```scala
95-
[F >: Nothing <: [X] => Coll[X]]
95+
[F >: Nothing <: [X] =>> Coll[X]]
9696
```
9797

9898
**Note**: The decision to treat `Nothing` as universal bottom type is provisional, and might be changed afer further discussion.
@@ -103,7 +103,7 @@ is treated as a shorthand for
103103

104104
The body of a type lambda can again be a type lambda. Example:
105105
```scala
106-
type TL = [X] => [Y] => (X, Y)
106+
type TL = [X] =>> [Y] =>> (X, Y)
107107
```
108108
Currently, no special provision is made to infer type arguments to such curried type lambdas. This is left for future work.
109109

docs/docs/reference/new-types/type-lambdas.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ title: "Type Lambdas"
66
A _type lambda_ lets one express a higher-kinded type directly, without
77
a type definition.
88

9-
[+X, Y] => Map[Y, X]
9+
[+X, Y] =>> Map[Y, X]
1010

1111
For instance, the type above defines a binary type constructor, with a
1212
covariant parameter `X` and a non-variant parameter `Y`. The
@@ -19,6 +19,6 @@ definition or declaration such as
1919
is a shorthand for a plain type definition with a type-lambda as its
2020
right-hand side:
2121

22-
type T = [X] => (X, X)
22+
type T = [X] =>> (X, X)
2323

2424
[More details](./type-lambdas-spec.html)

docs/docs/reference/other-new-features/kind-polymorphism.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ title: "Kind Polymorphism"
55

66
Normally type parameters in Scala are partitioned into _kinds_. First-level types are types of values. Higher-kinded types are type constructors
77
such as `List` or `Map`. The kind of a type is indicated by the top type of which it is a subtype. Normal types are subtypes of `Any`,
8-
covariant single argument type constructors such as `List` are subtypes of `[+X] => Any`, and the `Map` type constructor is
9-
a subtype of `[X, +Y] => Any`.
8+
covariant single argument type constructors such as `List` are subtypes of `[+X] =>> Any`, and the `Map` type constructor is
9+
a subtype of `[X, +Y] =>> Any`.
1010

11-
A type can be used only as prescribed by its kind. Subtypes of `Any` cannot be applied to type arguments whereas subtypes of `[X] => Any`
11+
A type can be used only as prescribed by its kind. Subtypes of `Any` cannot be applied to type arguments whereas subtypes of `[X] =>> Any`
1212
_must_ be applied to a type argument, unless they are passed to type parameters of the same kind.
1313

1414
Sometimes we would like to have type parameters that can have more than one kind, for instance to define an implicit
@@ -25,7 +25,7 @@ The actual type arguments of `f` can then be types of arbitrary kinds. So the fo
2525
f[Int]
2626
f[List]
2727
f[Map]
28-
f[[X] => String]
28+
f[[X] =>> String]
2929
```
3030

3131
We call type parameters and abstract types with an `AnyKind` upper bound _any-kinded types_`.

tests/neg/anykind.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ object AnyKinds {
1212
}
1313

1414
f[Int] // OK
15-
f[[X] => X] // OK
15+
f[[X] =>> X] // OK
1616
f[Nothing] // OK
1717

1818
def g[X <: Any]: Any = {

tests/neg/anykind2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ object AnyKinds {
66
}
77

88
f[Int] // OK
9-
f[[X] => X] // OK
9+
f[[X] =>> X] // OK
1010
f[Nothing] // OK
1111

1212
def g[X <: Any]: Any = {

tests/neg/enum-tparams.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ object Test {
1111
type Id[_]
1212

1313
enum E[F[_], G[_]] {
14-
case C1() extends E[[X] => X, Id]
15-
case C2() extends E[[F] => F, Id]
16-
case C3() extends E[[X] => { type Y = F[Int] }, Id]
17-
case C4() extends E[[X] => { type F = Int }, Id]
18-
case C5() extends E[[F] => G[Int], Id]
14+
case C1() extends E[[X] =>> X, Id]
15+
case C2() extends E[[F] =>> F, Id]
16+
case C3() extends E[[X] =>> { type Y = F[Int] }, Id]
17+
case C4() extends E[[X] =>> { type F = Int }, Id]
18+
case C5() extends E[[F] =>> G[Int], Id]
1919
}
2020

2121
Opt.S[Int](1) // OK

tests/neg/existentials.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
object TestList {
22

3-
var x: ([X] => List[List[X]])[_] = List(List(1)) // error: unreducible
4-
var y: ([X] => List[Seq[X]])[_] = List(List(1)) // error: unreducible
3+
var x: ([X] =>> List[List[X]])[_] = List(List(1)) // error: unreducible
4+
var y: ([X] =>> List[Seq[X]])[_] = List(List(1)) // error: unreducible
55

66
x = x
77
y = y
@@ -15,8 +15,8 @@ object TestList {
1515
}
1616
object TestSet {
1717

18-
var x: ([Y] => Set[Set[Y]])[_] = Set(Set("a")) // error: unreducible
19-
var y: ([Y] => Set[Iterable[Y]])[_] = Set(Set("a")) // error: unreducible
18+
var x: ([Y] =>> Set[Set[Y]])[_] = Set(Set("a")) // error: unreducible
19+
var y: ([Y] =>> Set[Iterable[Y]])[_] = Set(Set("a")) // error: unreducible
2020

2121
x = x
2222
y = y
@@ -36,14 +36,14 @@ class TestX {
3636
def cmp: T => Boolean = (x == _)
3737
}
3838

39-
val x: ([Y] => C[C[Y]])[_] = new C(new C("a")) // error: unreducible
39+
val x: ([Y] =>> C[C[Y]])[_] = new C(new C("a")) // error: unreducible
4040

4141
type CC[X] = C[C[X]]
4242
val y: CC[_] = ??? // error: unreducible
4343

4444
type D[X] <: C[X]
4545

46-
type DD = [X] => D[D[X]]
46+
type DD = [X] =>> D[D[X]]
4747
val z: DD[_] = ??? // error: unreducible
4848

4949
val g = x.get

tests/neg/i1181c.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This program compiles with Dotty using refined types for application, but
22
// does not compile with native applications. The reason is that in previous
3-
// Dotty the parameter reference to the lambda [X, Y] => Foo[X, Y] was a TypeRef
3+
// Dotty the parameter reference to the lambda [X, Y] =>> Foo[X, Y] was a TypeRef
44
// which could be selected for partial application. But now the type lambda gets
55
// substituted directly, which prevents that conversion. The program compiles
66
// if the type lambda is replaced by a type alias (see pos/i1181c.scala).
@@ -13,7 +13,7 @@ trait Bar[DD[_,_]] {
1313
object Test {
1414
type F[X, Y] = Foo[X]
1515

16-
trait Baz extends Bar[[X,Y] => Foo[X]] {
16+
trait Baz extends Bar[[X,Y] =>> Foo[X]] {
1717
def foo[M[_,_]](x: M[Int, Int]) = x
1818

1919
foo(x) // error: found: Foo[Int](Baz.this.x) required: M[Int, Int]

tests/neg/i2151.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
trait Test {
2-
type Nil = [K] => K
3-
type StrangeCons[H, Tail <: [H, A] => H] = Tail[H, H]
2+
type Nil = [K] =>> K
3+
type StrangeCons[H, Tail <: [H, A] =>> H] = Tail[H, H]
44

55
def list: StrangeCons[Int, Nil] // error
66
}

tests/neg/i2232.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ object Cats {
33
implicit def trivial[A]: Trivial[A] = new Trivial[A] { }
44

55
type Obj[C[_[_[_], _[_, _]]]] =
6-
[A] => C[({type l[c0[_], c1[_, _]] = c0[A] })#l]
6+
[A] =>> C[({type l[c0[_], c1[_, _]] = c0[A] })#l]
77
type Cat[C[_[_[_], _[_, _]]]] =
8-
[A, B] => C[({type l[c0[_], c1[_, _]] = c1[A, B]})#l]
8+
[A, B] =>> C[({type l[c0[_], c1[_, _]] = c1[A, B]})#l]
99

1010
trait Category[C[_[_[_], _[_, _]]]] {
1111
type -> = Cats.Cat[C]

tests/neg/i3452.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ object Test {
33

44
trait TC[A]
55

6-
implicit def case1[F[_]](implicit t: => TC[F[Any]]): TC[Tuple2K[[_] => Any, F, Any]] = ???
6+
implicit def case1[F[_]](implicit t: => TC[F[Any]]): TC[Tuple2K[[_] =>> Any, F, Any]] = ???
77
implicit def case2[A, F[_]](implicit r: TC[F[Any]]): TC[A] = ???
88

99
implicitly[TC[Int]] // error

0 commit comments

Comments
 (0)