Skip to content

Commit 82ed8f9

Browse files
committed
Fix parsing of argTypes
1 parent a36ca95 commit 82ed8f9

File tree

3 files changed

+31
-13
lines changed

3 files changed

+31
-13
lines changed

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

+21-6
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import config.SourceVersion.*
3535
import config.SourceVersion
3636
import dotty.tools.dotc.config.MigrationVersion
3737
import dotty.tools.dotc.util.chaining.*
38-
import dotty.tools.dotc.config.Feature.ccEnabled
3938

4039
object Parsers {
4140

@@ -225,13 +224,23 @@ object Parsers {
225224
def isCapKw = Feature.ccEnabled && isIdent(nme.cap)
226225
// 'cap type' ?
227226
def isCapTypeKw = isCapKw && in.lookahead.token == TYPE
227+
// Are the next two tokens 'cap type'?
228+
def isCapTypeKwNext = {
229+
if Feature.ccEnabled then
230+
val lookahead = in.LookaheadScanner()
231+
lookahead.nextToken()
232+
val res = lookahead.isIdent(nme.cap) && lookahead.lookahead.token == TYPE
233+
res
234+
else false
235+
}
228236
def isSimpleLiteral =
229237
simpleLiteralTokens.contains(in.token)
230238
|| isIdent(nme.raw.MINUS) && numericLitTokens.contains(in.lookahead.token)
231239
def isLiteral = literalTokens contains in.token
232240
def isNumericLit = numericLitTokens contains in.token
233241
def isTemplateIntro = templateIntroTokens contains in.token
234242
def isDclIntro = dclIntroTokens contains in.token
243+
def isDclIntroNext = dclIntroTokens contains in.lookahead.token
235244
def isStatSeqEnd = in.isNestedEnd || in.token == EOF || in.token == RPAREN
236245
def mustStartStat = mustStartStatTokens contains in.token
237246

@@ -1922,7 +1931,7 @@ object Parsers {
19221931
refinedTypeRest(atSpan(startOffset(t)) {
19231932
RefinedTypeTree(rejectWildcardType(t), refinement(indentOK = true))
19241933
})
1925-
else if Feature.ccEnabled && in.isIdent(nme.UPARROW) && isCaptureUpArrow then // TODO remove
1934+
else if Feature.ccEnabled && in.isIdent(nme.UPARROW) && isCaptureUpArrow then
19261935
atSpan(t.span.start):
19271936
in.nextToken()
19281937
if in.token == LBRACE
@@ -2179,13 +2188,19 @@ object Parsers {
21792188
* NamesAndTypes ::= NameAndType {‘,’ NameAndType}
21802189
* NameAndType ::= id ':' Type
21812190
*/
2182-
def argTypes(namedOK: Boolean, wildOK: Boolean, tupleOK: Boolean): List[Tree] = //TOOD grammar doc
2183-
def withWildCard(gen: => Tree) =
2191+
def argTypes(namedOK: Boolean, wildOK: Boolean, tupleOK: Boolean): List[Tree] = //TODO grammar doc
2192+
inline def wildCardCheck(inline gen: Tree): Tree =
21842193
val t = gen
21852194
if wildOK then t else rejectWildcardType(t)
21862195

2187-
def argType() = withWildCard(typ())
2188-
def argOrCapType() = withWildCard(if in.token == LBRACE then concreteCapsType(captureSet()) else typ())
2196+
def argType() = wildCardCheck:
2197+
typ()
2198+
2199+
def argOrCapType() = wildCardCheck:
2200+
if Feature.ccEnabled && in.token == LBRACE && !isDclIntroNext && !isCapTypeKwNext then // is this a capture set and not a refinement type?
2201+
// This case is ambiguous w.r.t. an Object literal {}. But since CC is enabled, we probably expect it to designate the empty set
2202+
concreteCapsType(captureSet())
2203+
else typ()
21892204

21902205
def namedArgType() =
21912206
atSpan(in.offset):

tests/neg-custom-args/captures/i22005.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ import caps.*
44
class IO
55
class File(io: IO^)
66

7-
class Handler[C^]:
8-
def f(file: File^): File^{C^} = file // error
9-
def g(@consume file: File^{C^}): File^ = file // ok
7+
class Handler[cap C]:
8+
def f(file: File^): File^{C} = file // error
9+
def g(@consume file: File^{C}): File^ = file // ok

tests/pos-custom-args/captures/cap-paramlists5.scala

+7-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import language.experimental.namedTypeArguments
33

44
def test2 =
55
val x: Any^ = ???
6-
def foo[cap A, cap B >: {A}, T](x: Int) = 1
7-
foo[{x}, {x}, Int](0)
8-
// foo[cap A = {x}, cap B = {x}](0)
9-
// foo[cap A = {x}](0)
6+
def foo[cap A, cap B >: {A}, T, U](x: Int) = 1
7+
//foo[{x}, {x}, Int](0) // TODO will not work for {x} in first arg
8+
foo[{}, {}, { def bar: Int }, { cap type D = {x} }](0)
9+
trait Foo { cap type D }
10+
foo[{}, {}, Foo, Foo](0)
11+
// foo[cap A = {x}, cap B = {x}](0)
12+
// foo[cap A = {x}](0)

0 commit comments

Comments
 (0)