Skip to content

Commit 900ffc4

Browse files
committed
Parsing of term lambdas
1 parent 34b312b commit 900ffc4

File tree

8 files changed

+60
-0
lines changed

8 files changed

+60
-0
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,11 @@ object Trees {
669669
type ThisTree[-T >: Untyped] = LambdaTypeTree[T]
670670
}
671671

672+
case class TermLambdaTypeTree[-T >: Untyped] private[ast] (params: List[ValDef[T]], body: Tree[T])(implicit @constructorOnly src: SourceFile)
673+
extends TypTree[T] {
674+
type ThisTree[-T >: Untyped] = TermLambdaTypeTree[T]
675+
}
676+
672677
/** [bound] selector match { cases } */
673678
case class MatchTypeTree[-T >: Untyped] private[ast] (bound: Tree[T], selector: Tree[T], cases: List[CaseDef[T]])(implicit @constructorOnly src: SourceFile)
674679
extends TypTree[T] {
@@ -964,6 +969,7 @@ object Trees {
964969
type RefinedTypeTree = Trees.RefinedTypeTree[T]
965970
type AppliedTypeTree = Trees.AppliedTypeTree[T]
966971
type LambdaTypeTree = Trees.LambdaTypeTree[T]
972+
type TermLambdaTypeTree = Trees.TermLambdaTypeTree[T]
967973
type MatchTypeTree = Trees.MatchTypeTree[T]
968974
type ByNameTypeTree = Trees.ByNameTypeTree[T]
969975
type TypeBoundsTree = Trees.TypeBoundsTree[T]
@@ -1135,6 +1141,10 @@ object Trees {
11351141
case tree: LambdaTypeTree if (tparams eq tree.tparams) && (body eq tree.body) => tree
11361142
case _ => finalize(tree, untpd.LambdaTypeTree(tparams, body)(sourceFile(tree)))
11371143
}
1144+
def TermLambdaTypeTree(tree: Tree)(params: List[ValDef], body: Tree)(implicit ctx: Context): TermLambdaTypeTree = tree match {
1145+
case tree: TermLambdaTypeTree if (params eq tree.params) && (body eq tree.body) => tree
1146+
case _ => finalize(tree, untpd.TermLambdaTypeTree(params, body)(sourceFile(tree)))
1147+
}
11381148
def MatchTypeTree(tree: Tree)(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit ctx: Context): MatchTypeTree = tree match {
11391149
case tree: MatchTypeTree if (bound eq tree.bound) && (selector eq tree.selector) && (cases eq tree.cases) => tree
11401150
case _ => finalize(tree, untpd.MatchTypeTree(bound, selector, cases)(sourceFile(tree)))
@@ -1293,6 +1303,10 @@ object Trees {
12931303
inContext(localCtx) {
12941304
cpy.LambdaTypeTree(tree)(transformSub(tparams), transform(body))
12951305
}
1306+
case TermLambdaTypeTree(params, body) =>
1307+
inContext(localCtx) {
1308+
cpy.TermLambdaTypeTree(tree)(transformSub(params), transform(body))
1309+
}
12961310
case MatchTypeTree(bound, selector, cases) =>
12971311
cpy.MatchTypeTree(tree)(transform(bound), transform(selector), transformSub(cases))
12981312
case ByNameTypeTree(result) =>
@@ -1422,6 +1436,10 @@ object Trees {
14221436
inContext(localCtx) {
14231437
this(this(x, tparams), body)
14241438
}
1439+
case TermLambdaTypeTree(params, body) =>
1440+
inContext(localCtx) {
1441+
this(this(x, params), body)
1442+
}
14251443
case MatchTypeTree(bound, selector, cases) =>
14261444
this(this(this(x, bound), selector), cases)
14271445
case ByNameTypeTree(result) =>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
377377
def RefinedTypeTree(tpt: Tree, refinements: List[Tree])(implicit src: SourceFile): RefinedTypeTree = new RefinedTypeTree(tpt, refinements)
378378
def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit src: SourceFile): AppliedTypeTree = new AppliedTypeTree(tpt, args)
379379
def LambdaTypeTree(tparams: List[TypeDef], body: Tree)(implicit src: SourceFile): LambdaTypeTree = new LambdaTypeTree(tparams, body)
380+
def TermLambdaTypeTree(params: List[ValDef], body: Tree)(implicit src: SourceFile): TermLambdaTypeTree = new TermLambdaTypeTree(params, body)
380381
def MatchTypeTree(bound: Tree, selector: Tree, cases: List[CaseDef])(implicit src: SourceFile): MatchTypeTree = new MatchTypeTree(bound, selector, cases)
381382
def ByNameTypeTree(result: Tree)(implicit src: SourceFile): ByNameTypeTree = new ByNameTypeTree(result)
382383
def TypeBoundsTree(lo: Tree, hi: Tree, alias: Tree = EmptyTree)(implicit src: SourceFile): TypeBoundsTree = new TypeBoundsTree(lo, hi, alias)

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,7 @@ object Parsers {
13601360

13611361
/** Type ::= FunType
13621362
* | HkTypeParamClause ‘=>>’ Type
1363+
* | ‘(’ TypedFunParams ‘)’ ‘=>>’ Type
13631364
* | MatchType
13641365
* | InfixType
13651366
* FunType ::= (MonoFunType | PolyFunType)
@@ -1374,6 +1375,16 @@ object Parsers {
13741375
var imods = Modifiers()
13751376
def functionRest(params: List[Tree]): Tree =
13761377
atSpan(start, in.offset) {
1378+
if in.token == TLARROW then
1379+
if !imods.flags.isEmpty || params.isEmpty then
1380+
syntaxError(em"illegal parameter list for type lambda", start)
1381+
in.token = ARROW
1382+
else
1383+
for case ValDef(_, tpt: ByNameTypeTree, _) <- params do
1384+
syntaxError(em"parameter of type lambda may not be call-by-name", tpt.span)
1385+
in.nextToken()
1386+
return TermLambdaTypeTree(params.asInstanceOf[List[ValDef]], typ())
1387+
13771388
if in.token == CTXARROW then
13781389
in.nextToken()
13791390
imods |= Given

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
486486
changePrec(GlobalPrec) {
487487
tparamsText(tparams) ~ " =>> " ~ toText(body)
488488
}
489+
case TermLambdaTypeTree(params, body) =>
490+
changePrec(GlobalPrec) {
491+
paramsText(params) ~ " =>> " ~ toText(body)
492+
}
489493
case MatchTypeTree(bound, sel, cases) =>
490494
changePrec(GlobalPrec) {
491495
toText(sel) ~ keywordStr(" match ") ~ blockText(cases) ~

compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,5 +146,9 @@ object ErrorReporting {
146146
else ""
147147
}
148148

149+
def dependentStr =
150+
"""Term-dependent types are experimental,
151+
|they must be enabled with a `experimental.dependent` language import or setting""".stripMargin
152+
149153
def err(using Context): Errors = new Errors
150154
}

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,14 @@ class Typer extends Namer
15781578
}
15791579

15801580
def typedAppliedTypeTree(tree: untpd.AppliedTypeTree)(using Context): Tree = {
1581+
tree.args match
1582+
case arg :: _ if arg.isTerm =>
1583+
if dependentEnabled then
1584+
return errorTree(tree, i"Not yet implemented: T(...)")
1585+
else
1586+
return errorTree(tree, dependentStr)
1587+
case _ =>
1588+
15811589
val tpt1 = typed(tree.tpt, AnyTypeConstructorProto)(using ctx.retractMode(Mode.Pattern))
15821590
val tparams = tpt1.tpe.typeParams
15831591
if (tparams.isEmpty) {
@@ -1654,6 +1662,12 @@ class Typer extends Namer
16541662
assignType(cpy.LambdaTypeTree(tree)(tparams1, body1), tparams1, body1)
16551663
}
16561664

1665+
def typedTermLambdaTypeTree(tree: untpd.TermLambdaTypeTree)(using Context): Tree =
1666+
if dependentEnabled then
1667+
errorTree(tree, i"Not yet implemented: (...) =>> ...")
1668+
else
1669+
errorTree(tree, dependentStr)
1670+
16571671
def typedMatchTypeTree(tree: untpd.MatchTypeTree, pt: Type)(using Context): Tree = {
16581672
val bound1 =
16591673
if (tree.bound.isEmpty && isFullyDefined(pt, ForceDegree.none)) TypeTree(pt)
@@ -2369,6 +2383,7 @@ class Typer extends Namer
23692383
case tree: untpd.RefinedTypeTree => typedRefinedTypeTree(tree)
23702384
case tree: untpd.AppliedTypeTree => typedAppliedTypeTree(tree)
23712385
case tree: untpd.LambdaTypeTree => typedLambdaTypeTree(tree)(using ctx.localContext(tree, NoSymbol).setNewScope)
2386+
case tree: untpd.TermLambdaTypeTree => typedTermLambdaTypeTree(tree)(using ctx.localContext(tree, NoSymbol).setNewScope)
23722387
case tree: untpd.MatchTypeTree => typedMatchTypeTree(tree, pt)
23732388
case tree: untpd.ByNameTypeTree => typedByNameTypeTree(tree)
23742389
case tree: untpd.TypeBoundsTree => typedTypeBoundsTree(tree, pt)

tests/neg/deptypes-badsyntax.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
type Bad1[T] = () =>> Array[T] // error

tests/neg/deptypes.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
type Vec[T] = (n: Int) =>> Array[T] // error: needs to be enabled
3+
val x: Vec[Int](10) = ??? // error: needs to be enabled
4+
val n = 10
5+
type T = Vec[String](n) // error: needs to be enabled

0 commit comments

Comments
 (0)