Skip to content

Commit a64f53f

Browse files
committed
Allow given in constructor applications
1 parent 190c7f4 commit a64f53f

File tree

4 files changed

+79
-14
lines changed

4 files changed

+79
-14
lines changed

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

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -575,22 +575,26 @@ object Parsers {
575575
}
576576
else recur(operand())
577577
}
578-
else if (in.token == GIVEN) {
578+
else if (in.token == GIVEN && !isType) {
579579
val top1 = reduceStack(base, top, minInfixPrec, leftAssoc = true, nme.WITHkw, isType)
580580
assert(opStack `eq` base)
581-
val app = atSpan(startOffset(top1), in.offset) {
582-
in.nextToken()
583-
val args = if (in.token == LPAREN) parArgumentExprs() else operand() :: Nil
584-
Apply(top, args)
585-
}
586-
app.pushAttachment(ApplyGiven, ())
587-
recur(app)
581+
recur(applyGiven(top1, operand))
588582
}
589583
else reduceStack(base, top, minPrec, leftAssoc = true, in.name, isType)
590584

591585
recur(first)
592586
}
593587

588+
def applyGiven(t: Tree, operand: () => Tree): Tree = {
589+
val app = atSpan(startOffset(t), in.offset) {
590+
in.nextToken()
591+
val args = if (in.token == LPAREN) parArgumentExprs() else operand() :: Nil
592+
Apply(t, args)
593+
}
594+
app.pushAttachment(ApplyGiven, ())
595+
app
596+
}
597+
594598
/* -------- IDENTIFIERS AND LITERALS ------------------------------------------- */
595599

596600
/** Accept identifier and return its name as a term name. */
@@ -2710,13 +2714,43 @@ object Parsers {
27102714

27112715
/* -------- TEMPLATES ------------------------------------------- */
27122716

2713-
/** ConstrApp ::= SimpleType {ParArgumentExprs}
2717+
/** SimpleConstrApp ::= AnnotType {ParArgumentExprs}
2718+
* ConstrApp ::= SimpleConstrApp
2719+
* | ‘(’ SimpleConstrApp {‘given’ (PrefixExpr | ParArgumentExprs)} ‘)’
27142720
*/
27152721
val constrApp: () => Tree = () => {
2716-
// Using Ident(nme.ERROR) to avoid causing cascade errors on non-user-written code
2717-
val t = rejectWildcardType(annotType(), fallbackTree = Ident(nme.ERROR))
2718-
if (in.token == LPAREN) parArgumentExprss(wrapNew(t))
2719-
else t
2722+
2723+
def isAnnotType(t: Tree) = t match {
2724+
case _: Ident
2725+
| _: Select
2726+
| _: AppliedTypeTree
2727+
| _: Tuple
2728+
| _: Parens
2729+
| _: RefinedTypeTree
2730+
| _: SingletonTypeTree
2731+
| _: TypSplice
2732+
| _: Annotated => true
2733+
case _ => false
2734+
}
2735+
2736+
def givenArgs(t: Tree): Tree = {
2737+
if (in.token == GIVEN) givenArgs(applyGiven(t, prefixExpr)) else t
2738+
}
2739+
2740+
if (in.token == LPAREN)
2741+
inParens {
2742+
val t = toplevelTyp()
2743+
if (isAnnotType(t))
2744+
if (in.token == LPAREN) givenArgs(parArgumentExprss(wrapNew(t)))
2745+
else if (in.token == GIVEN) givenArgs(wrapNew(t))
2746+
else t
2747+
else Parens(t)
2748+
}
2749+
else {
2750+
val t = rejectWildcardType(annotType(), fallbackTree = Ident(nme.ERROR))
2751+
// Using Ident(nme.ERROR) to avoid causing cascade errors on non-user-written code
2752+
if (in.token == LPAREN) parArgumentExprss(wrapNew(t)) else t
2753+
}
27202754
}
27212755

27222756
/** ConstrApps ::= ConstrApp {‘with’ ConstrApp} (to be deprecated in 3.1)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2591,6 +2591,8 @@ class Typer extends Namer
25912591
tree
25922592
else if (wtp.isContextual)
25932593
adaptNoArgs(wtp) // insert arguments implicitly
2594+
else if (tree.symbol.isPrimaryConstructor && tree.symbol.info.firstParamTypes.isEmpty)
2595+
readapt(tree.appliedToNone) // insert () to primary constructors
25942596
else
25952597
errorTree(tree, em"Missing arguments for $methodStr")
25962598
case _ => tryInsertApplyOrImplicit(tree, pt, locked) {

tests/neg/parser-stability-25.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ class D extends (Int => 1) {
1111
}
1212

1313
class Wrap(x: Int)
14-
class E extends (Wrap)( // error
14+
class E extends (Wrap)( // error // error
1515
// error

tests/pos/given-constrapps.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
class TC
2+
val tc = TC()
3+
class C given (x: TC) {
4+
assert(x eq tc)
5+
}
6+
class C2(n: Int) given (x: TC) given List[TC] {
7+
assert(x eq tc)
8+
the[List[TC]].foreach(t => assert(t eq tc))
9+
10+
def this() given TC given List[TC] = this(1)
11+
}
12+
13+
class D extends (C given tc)
14+
class D2 extends (C2(1) given tc given Nil)
15+
16+
class Foo given TC {
17+
assert(the[TC] != null)
18+
}
19+
20+
object Test extends App {
21+
new (C given tc)
22+
new (C() given tc)
23+
new (C given tc) {}
24+
new (C2(1) given tc given List(tc))
25+
new (C2(1) given tc given List(tc)) {}
26+
new (C2() given tc given List(tc))
27+
def foo given TC = ()
28+
foo given tc
29+
}

0 commit comments

Comments
 (0)