Skip to content

Commit 562f9d7

Browse files
committed
Recognize capture related syntax and names only under -Ycc
Only under -Ycc: - recognize -> and ?-> as function types, - recognize {...} T as a capturing type, - recognize `scala.*` as a value
1 parent 2e7c363 commit 562f9d7

File tree

6 files changed

+59
-44
lines changed

6 files changed

+59
-44
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ class Definitions {
11521152
}
11531153
}
11541154

1155-
/** Extractor for function types representing by-name parameters, of the form
1155+
/** Extractor for context function types representing by-name parameters, of the form
11561156
* `() ?=> T`.
11571157
* Under -Ycc, this becomes `() ?-> T` or `{r1, ..., rN} () ?-> T`.
11581158
*/
@@ -1977,7 +1977,8 @@ class Definitions {
19771977
this.initCtx = ctx
19781978
if (!isInitialized) {
19791979
// force initialization of every symbol that is synthesized or hijacked by the compiler
1980-
val forced = syntheticCoreClasses ++ syntheticCoreMethods ++ ScalaValueClasses() ++ List(JavaEnumClass, captureRoot)
1980+
val forced = syntheticCoreClasses ++ syntheticCoreMethods ++ ScalaValueClasses()
1981+
++ (JavaEnumClass :: (if ctx.settings.Ycc.value then captureRoot :: Nil else Nil))
19811982

19821983
isInitialized = true
19831984
}

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

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ object Parsers {
188188

189189
def isIdent = in.isIdent
190190
def isIdent(name: Name) = in.isIdent(name)
191+
def isPureArrow(name: Name): Boolean = ctx.settings.Ycc.value && isIdent(name)
192+
def isPureArrow: Boolean = isPureArrow(nme.PUREARROW) || isPureArrow(nme.PURECTXARROW)
191193
def isErased = isIdent(nme.erased) && in.erasedEnabled
192194
def isSimpleLiteral =
193195
simpleLiteralTokens.contains(in.token)
@@ -427,7 +429,7 @@ object Parsers {
427429
*/
428430
def convertToParams(tree: Tree): List[ValDef] =
429431
val mods =
430-
if in.token == CTXARROW || in.isIdent(nme.PURECTXARROW)
432+
if in.token == CTXARROW || isPureArrow(nme.PURECTXARROW)
431433
then Modifiers(Given)
432434
else EmptyModifiers
433435
tree match
@@ -958,23 +960,28 @@ object Parsers {
958960
isArrowIndent()
959961
else false
960962

963+
/** Under -Ycc: is the following token sequuence a capture set `{ref1, ..., refN}`
964+
* followed by a token that can start a type?
965+
*/
961966
def followingIsCaptureSet(): Boolean =
962-
val lookahead = in.LookaheadScanner()
963-
def followingIsTypeStart() =
964-
lookahead.nextToken()
965-
canStartInfixTypeTokens.contains(lookahead.token)
966-
|| lookahead.token == LBRACKET
967-
def recur(): Boolean =
968-
(lookahead.isIdent || lookahead.token == THIS) && {
967+
ctx.settings.Ycc.value && {
968+
val lookahead = in.LookaheadScanner()
969+
def followingIsTypeStart() =
969970
lookahead.nextToken()
970-
if lookahead.token == COMMA then
971+
canStartInfixTypeTokens.contains(lookahead.token)
972+
|| lookahead.token == LBRACKET
973+
def recur(): Boolean =
974+
(lookahead.isIdent || lookahead.token == THIS) && {
971975
lookahead.nextToken()
972-
recur()
973-
else
974-
lookahead.token == RBRACE && followingIsTypeStart()
975-
}
976-
lookahead.nextToken()
977-
if lookahead.token == RBRACE then followingIsTypeStart() else recur()
976+
if lookahead.token == COMMA then
977+
lookahead.nextToken()
978+
recur()
979+
else
980+
lookahead.token == RBRACE && followingIsTypeStart()
981+
}
982+
lookahead.nextToken()
983+
if lookahead.token == RBRACE then followingIsTypeStart() else recur()
984+
}
978985

979986
/* --------- OPERAND/OPERATOR STACK --------------------------------------- */
980987

@@ -1431,20 +1438,26 @@ object Parsers {
14311438
def captureRef(): Tree =
14321439
if in.token == THIS then simpleRef() else termIdent()
14331440

1441+
/** CaptureSet ::= `{` CaptureRef {`,` CaptureRef} `}` -- under -Ycc
1442+
*/
1443+
def captureSet(): List[Tree] = inBraces {
1444+
if in.token == RBRACE then Nil else commaSeparated(captureRef)
1445+
}
1446+
14341447
/** Type ::= FunType
14351448
* | HkTypeParamClause ‘=>>’ Type
14361449
* | FunParamClause ‘=>>’ Type
14371450
* | MatchType
14381451
* | InfixType
1439-
* | CaptureSet Type
1452+
* | CaptureSet Type -- under -Ycc
14401453
* FunType ::= (MonoFunType | PolyFunType)
1441-
* MonoFunType ::= FunTypeArgs (‘=>’ | ‘?=>’ | ‘->’ | ‘?->’ ) Type
1442-
* PolyFunType ::= HKTypeParamClause ('=>' | ‘->’_) Type
1454+
* MonoFunType ::= FunTypeArgs (‘=>’ | ‘?=>’) Type
1455+
* | (‘->’ | ‘?->’ ) Type -- under -Ycc
1456+
* PolyFunType ::= HKTypeParamClause '=>' Type
1457+
* | HKTypeParamClause ‘->’ Type -- under -Ycc
14431458
* FunTypeArgs ::= InfixType
14441459
* | `(' [ [ ‘[using]’ ‘['erased'] FunArgType {`,' FunArgType } ] `)'
14451460
* | '(' [ ‘[using]’ ‘['erased'] TypedFunParam {',' TypedFunParam } ')'
1446-
* CaptureSet ::= `{` CaptureRef {`,` CaptureRef} `}`
1447-
* CaptureRef ::= Ident
14481461
*/
14491462
def typ(): Tree =
14501463
val start = in.offset
@@ -1453,17 +1466,16 @@ object Parsers {
14531466
val paramSpan = Span(start, in.lastOffset)
14541467
atSpan(start, in.offset) {
14551468
var token = in.token
1456-
if in.isIdent(nme.PUREARROW) then
1469+
if isPureArrow(nme.PUREARROW) then
14571470
token = ARROW
1458-
else if in.isIdent(nme.PURECTXARROW) then
1471+
else if isPureArrow(nme.PURECTXARROW) then
14591472
token = CTXARROW
14601473
else if token == TLARROW then
14611474
if !imods.flags.isEmpty || params.isEmpty then
14621475
syntaxError(em"illegal parameter list for type lambda", start)
14631476
token = ARROW
14641477
else if ctx.settings.Ycc.value then
14651478
// `=>` means impure function under -Ycc whereas `->` is a regular function.
1466-
// Without -Ycc they both mean regular function.
14671479
imods |= Impure
14681480

14691481
if token == CTXARROW then
@@ -1514,7 +1526,7 @@ object Parsers {
15141526
commaSeparatedRest(t, funArgType)
15151527
}
15161528
accept(RPAREN)
1517-
if isValParamList || in.isArrow || in.isPureArrow then
1529+
if isValParamList || in.isArrow || isPureArrow then
15181530
functionRest(ts)
15191531
else {
15201532
val ts1 = ts.mapConserve { t =>
@@ -1538,7 +1550,7 @@ object Parsers {
15381550
val tparams = typeParamClause(ParamOwner.TypeParam)
15391551
if (in.token == TLARROW)
15401552
atSpan(start, in.skipToken())(LambdaTypeTree(tparams, toplevelTyp()))
1541-
else if (in.token == ARROW || in.isIdent(nme.PUREARROW)) {
1553+
else if (in.token == ARROW || isPureArrow(nme.PUREARROW)) {
15421554
val arrowOffset = in.skipToken()
15431555
val body = toplevelTyp()
15441556
atSpan(start, arrowOffset) {
@@ -1562,7 +1574,7 @@ object Parsers {
15621574
case MATCH => matchType(t)
15631575
case FORSOME => syntaxError(ExistentialTypesNoLongerSupported()); t
15641576
case _ =>
1565-
if isIdent(nme.PUREARROW) || isIdent(nme.PURECTXARROW) then
1577+
if isPureArrow then
15661578
functionRest(t :: Nil)
15671579
else
15681580
if (imods.is(Erased) && !t.isInstanceOf[FunctionWithMods])
@@ -1625,7 +1637,7 @@ object Parsers {
16251637

16261638
def infixTypeRest(t: Tree): Tree =
16271639
infixOps(t, canStartInfixTypeTokens, refinedTypeFn, Location.ElseWhere, ParseKind.Type,
1628-
isOperator = !followingIsVararg() && !isIdent(nme.PUREARROW) && !isIdent(nme.PURECTXARROW))
1640+
isOperator = !followingIsVararg() && !isPureArrow)
16291641

16301642
/** RefinedType ::= WithType {[nl] Refinement}
16311643
*/
@@ -1864,7 +1876,7 @@ object Parsers {
18641876
}
18651877

18661878
def paramTypeOf(core: () => Tree): Tree =
1867-
if in.token == ARROW || isIdent(nme.PUREARROW) then
1879+
if in.token == ARROW || isPureArrow(nme.PUREARROW) then
18681880
val isImpure = in.token == ARROW
18691881
val tp = atSpan(in.skipToken()) { ByNameTypeTree(core()) }
18701882
if isImpure && ctx.settings.Ycc.value then ImpureByNameTypeTree(tp) else tp
@@ -1974,10 +1986,6 @@ object Parsers {
19741986
CapturingTypeTree(captureSet(), infixType())
19751987
else infixType()
19761988

1977-
def captureSet(): List[Tree] = inBraces {
1978-
if in.token == RBRACE then Nil else commaSeparated(captureRef)
1979-
}
1980-
19811989
/* ----------- EXPRESSIONS ------------------------------------------------ */
19821990

19831991
/** Does the current conditional expression continue after
@@ -4074,8 +4082,6 @@ object Parsers {
40744082
* |
40754083
* EnumStat ::= TemplateStat
40764084
* | Annotations Modifiers EnumCase
4077-
* SelfType ::= id [‘:’ [CaptureSet] InfixType] ‘=>’
4078-
* | ‘this’ ‘:’ [CaptureSet] InfixType ‘=>’
40794085
*/
40804086
def templateStatSeq(): (ValDef, List[Tree]) = checkNoEscapingPlaceholders {
40814087
val stats = new ListBuffer[Tree]

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ object Scanners {
8888

8989
def isArrow =
9090
token == ARROW || token == CTXARROW
91-
92-
def isPureArrow =
93-
isIdent(nme.PUREARROW) || isIdent(nme.PURECTXARROW)
9491
}
9592

9693
abstract class ScannerCommon(source: SourceFile)(using Context) extends CharArrayReader with TokenData {

tests/neg/cc-only-defs.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
trait Test {
2+
3+
val x: Int -> Int // error
4+
val y: Int ?-> Int // error
5+
6+
val z: *.type // error
7+
8+
val b: ImpureFuntion1[Int, Int] // error
9+
10+
val a: {z} String // error
11+
} // error

tests/neg/multiLineOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ val x = 1
55
val b1 = {
66
22
77
* 22 // ok
8-
*/*one more*/22 // error: end of statement expected
8+
*/*one more*/22 // error: end of statement expected // error: not found: *
99
}
1010

1111
val b2: Boolean = {

tests/neg/t5702-neg-bad-and-wild.check

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@
3838
| x is already defined as value x
3939
|
4040
| Note that overloaded methods must all be defined in the same group of toplevel definitions
41-
-- [E127] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:12:20 ---------------------------------------------------
41+
-- [E006] Not Found Error: tests/neg/t5702-neg-bad-and-wild.scala:12:20 ------------------------------------------------
4242
12 | case List(1, _*3,) => // error: pattern expected // error
4343
| ^
44-
| * cannot be used as an extractor in a pattern because it lacks an unapply or unapplySeq method
44+
| Not found: *
4545
|
4646
| longer explanation available when compiling with `-explain`
47-
-- [E127] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:13:20 ---------------------------------------------------
47+
-- [E006] Not Found Error: tests/neg/t5702-neg-bad-and-wild.scala:13:20 ------------------------------------------------
4848
13 | case List(1, _*3:) => // error // error
4949
| ^
50-
| * cannot be used as an extractor in a pattern because it lacks an unapply or unapplySeq method
50+
| Not found: *
5151
|
5252
| longer explanation available when compiling with `-explain`
5353
-- [E045] Cyclic Error: tests/neg/t5702-neg-bad-and-wild.scala:23:19 ---------------------------------------------------

0 commit comments

Comments
 (0)