Skip to content

Commit 80e6432

Browse files
committed
Allow with in front of type refinements
1 parent edddda1 commit 80e6432

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

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

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,21 @@ object Parsers {
357357
accept(SEMI)
358358
}
359359

360+
def acceptNested(): Unit =
361+
if in.token != LBRACE && in.token != INDENT then
362+
syntaxError(i"indented definitions or `{' expected")
363+
364+
/** Under -language:Scala2 or -old-syntax, flag
365+
*
366+
* extends p1 with new p1 with t1 with
367+
* p2 p2 t2
368+
*
369+
* as a migration warning or error since that means something else under significant indentation.
370+
*/
371+
def checkNotWithAtEOL(): Unit =
372+
if (in.isScala2Mode || in.oldSyntax) && in.isAfterLineEnd then
373+
in.errorOrMigrationWarning("`with` cannot be followed by new line, place at beginning of next line instead")
374+
360375
def rewriteNotice(additionalOption: String = "") = {
361376
val optionStr = if (additionalOption.isEmpty) "" else " " ++ additionalOption
362377
i"\nThis construct can be rewritten automatically under$optionStr -rewrite."
@@ -1254,8 +1269,7 @@ object Parsers {
12541269
def possibleTemplateStart(): Unit =
12551270
if in.token == WITH then
12561271
in.nextToken()
1257-
if in.token != LBRACE && in.token != INDENT then
1258-
syntaxError(i"indented definitions or `{' expected")
1272+
acceptNested()
12591273
else if silentTemplateIdent then
12601274
in.observeIndented()
12611275
newLineOptWhenFollowedBy(LBRACE)
@@ -1402,7 +1416,7 @@ object Parsers {
14021416
makeParameter(name, typ(), mods | Param)
14031417
}
14041418

1405-
/** InfixType ::= RefinedType {id [nl] refinedType}
1419+
/** InfixType ::= RefinedType {id [nl] RefinedType}
14061420
*/
14071421
def infixType(): Tree = infixTypeRest(refinedType())
14081422

@@ -1413,7 +1427,7 @@ object Parsers {
14131427
def infixTypeRest(t: Tree): Tree =
14141428
infixOps(t, canStartTypeTokens, refinedType, isType = true, isOperator = !isPostfixStar)
14151429

1416-
/** RefinedType ::= WithType {Annotation | [nl] Refinement}
1430+
/** RefinedType ::= WithType {[nl | `with'] Refinement}
14171431
*/
14181432
val refinedType: () => Tree = () => refinedTypeRest(withType())
14191433

@@ -1429,12 +1443,16 @@ object Parsers {
14291443
def withType(): Tree = withTypeRest(annotType())
14301444

14311445
def withTypeRest(t: Tree): Tree =
1432-
if (in.token == WITH) {
1433-
if (ctx.settings.strict.value)
1434-
deprecationWarning(DeprecatedWithOperator())
1446+
if in.token == WITH then
1447+
val withOffset = in.offset
14351448
in.nextToken()
1436-
makeAndType(t, withType())
1437-
}
1449+
if in.token == LBRACE || in.token == INDENT then
1450+
t
1451+
else
1452+
checkNotWithAtEOL()
1453+
if (ctx.settings.strict.value)
1454+
deprecationWarning(DeprecatedWithOperator(), withOffset)
1455+
makeAndType(t, withType())
14381456
else t
14391457

14401458
/** AnnotType ::= SimpleType {Annotation}
@@ -3434,14 +3452,7 @@ object Parsers {
34343452
in.nextToken()
34353453
if templateCanFollow && (in.token == LBRACE || in.token == INDENT) then Nil
34363454
else
3437-
if (in.isScala2Mode || in.oldSyntax) && in.isAfterLineEnd then
3438-
// Disallow
3439-
//
3440-
// extends p1 with
3441-
// p2
3442-
//
3443-
// since that means something else under significant indentation
3444-
in.errorOrMigrationWarning("`with` cannot be followed by new line, place at beginning of next line instead")
3455+
checkNotWithAtEOL()
34453456
constrApps(commaOK, templateCanFollow)
34463457
else if commaOK && in.token == COMMA then
34473458
in.nextToken()

docs/docs/internals/syntax.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ FunArgTypes ::= InfixType
151151
TypedFunParam ::= id ‘:’ Type
152152
MatchType ::= InfixType `match` TypeCaseClauses
153153
InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2)
154-
RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds)
154+
RefinedType ::= WithType {[nl | ‘with’] Refinement} RefinedTypeTree(t, ds)
155155
WithType ::= AnnotType {‘with’ AnnotType} (deprecated)
156156
AnnotType ::= SimpleType {Annotation} Annotated(t, annot)
157157
SimpleType ::= SimpleType TypeArgs AppliedTypeTree(t, args)

0 commit comments

Comments
 (0)