Skip to content

Commit e6b7e3d

Browse files
committed
Better error message for polytypes wrapping capturing types
A type like [X] -> A ->{c} B is currently not allowed since it expands to a PolyType wrapping a CapturingType and we have an implementation restriction that requires PolyTypes to wrap only FunctionTypes. It would be great if we could lift that implementation restriction. Until we do so, we should have a better error message, which is commit implements.
1 parent ebbd685 commit e6b7e3d

File tree

3 files changed

+33
-20
lines changed

3 files changed

+33
-20
lines changed

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

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,22 @@ object Parsers {
518518
tree
519519
}
520520

521+
def makePolyFunction(tparams: List[Tree], body: Tree,
522+
kind: String, errorTree: => Tree,
523+
start: Offset, arrowOffset: Offset): Tree =
524+
atSpan(start, arrowOffset):
525+
getFunction(body) match
526+
case None =>
527+
syntaxError(em"Implementation restriction: polymorphic function ${kind}s must have a value parameter", arrowOffset)
528+
errorTree
529+
case Some(Function(_, _: CapturesAndResult)) =>
530+
// A function tree like this will be desugared
531+
// into a capturing type in the typer.
532+
syntaxError(em"Implementation restriction: polymorphic function types cannot wrap function types that have capture sets", arrowOffset)
533+
errorTree
534+
case Some(f) =>
535+
PolyFunction(tparams, body)
536+
521537
/* --------------- PLACEHOLDERS ------------------------------------------- */
522538

523539
/** The implicit parameters introduced by `_` in the current expression.
@@ -1539,11 +1555,6 @@ object Parsers {
15391555
private def getFunction(tree: Tree): Option[Function] = tree match {
15401556
case Parens(tree1) => getFunction(tree1)
15411557
case Block(Nil, tree1) => getFunction(tree1)
1542-
case Function(_, _: CapturesAndResult) =>
1543-
// A function tree like this will be desugared
1544-
// into a capturing type in the typer,
1545-
// so None is returned.
1546-
None
15471558
case t: Function => Some(t)
15481559
case _ => None
15491560
}
@@ -1757,13 +1768,7 @@ object Parsers {
17571768
else if in.token == ARROW || isPureArrow(nme.PUREARROW) then
17581769
val arrowOffset = in.skipToken()
17591770
val body = toplevelTyp(nestedIntoOK(in.token))
1760-
atSpan(start, arrowOffset):
1761-
getFunction(body) match
1762-
case Some(f) =>
1763-
PolyFunction(tparams, body)
1764-
case None =>
1765-
syntaxError(em"Implementation restriction: polymorphic function types must have a value parameter", arrowOffset)
1766-
Ident(nme.ERROR.toTypeName)
1771+
makePolyFunction(tparams, body, "type", Ident(nme.ERROR.toTypeName), start, arrowOffset)
17671772
else
17681773
accept(TLARROW)
17691774
typ()
@@ -2360,14 +2365,7 @@ object Parsers {
23602365
val tparams = typeParamClause(ParamOwner.Type)
23612366
val arrowOffset = accept(ARROW)
23622367
val body = expr(location)
2363-
atSpan(start, arrowOffset) {
2364-
getFunction(body) match
2365-
case Some(f) =>
2366-
PolyFunction(tparams, f)
2367-
case None =>
2368-
syntaxError(em"Implementation restriction: polymorphic function literals must have a value parameter", arrowOffset)
2369-
errorTermTree(arrowOffset)
2370-
}
2368+
makePolyFunction(tparams, body, "literal", errorTermTree(arrowOffset), start, arrowOffset)
23712369
case _ =>
23722370
val saved = placeholderParams
23732371
placeholderParams = Nil
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Error: tests/neg-custom-args/captures/polyCaptures.scala:4:22 -------------------------------------------------------
2+
4 |val runOpsCheck: [C^] -> (ops: List[() ->{C^} Unit]) ->{C^} Unit = runOps // error
3+
| ^
4+
| Implementation restriction: polymorphic function types cannot wrap function types that have capture sets
5+
-- Error: tests/neg-custom-args/captures/polyCaptures.scala:5:23 -------------------------------------------------------
6+
5 |val runOpsCheck2: [C^] => (ops: List[() ->{C^} Unit]) ->{C^} Unit = runOps // error
7+
| ^
8+
| Implementation restriction: polymorphic function types cannot wrap function types that have capture sets
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Box[X](val elem: X)
2+
3+
val runOps = [C^] => (b: Box[() ->{C^} Unit]) => b.elem()
4+
val runOpsCheck: [C^] -> (ops: List[() ->{C^} Unit]) ->{C^} Unit = runOps // error
5+
val runOpsCheck2: [C^] => (ops: List[() ->{C^} Unit]) ->{C^} Unit = runOps // error
6+
7+

0 commit comments

Comments
 (0)