Skip to content

Commit 504b9dd

Browse files
authored
Merge pull request #11079 from dotty-staging/fix-#11020
Keep correct track of parameter counts in extension clauses
2 parents 3d64f51 + 5e1caf2 commit 504b9dd

File tree

6 files changed

+28
-21
lines changed

6 files changed

+28
-21
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ object desugar {
253253

254254
def addDefaultGetters(meth: DefDef)(using Context): Tree =
255255

256-
/** The longest prefix of parameter lists in =paramss whose total number of
256+
/** The longest prefix of parameter lists in paramss whose total number of
257257
* ValDefs does not exceed `n`
258258
*/
259259
def takeUpTo(paramss: List[ParamClause], n: Int): List[ParamClause] = paramss match

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3020,7 +3020,8 @@ object Parsers {
30203020
*/
30213021
def paramClauses(ofClass: Boolean = false,
30223022
ofCaseClass: Boolean = false,
3023-
givenOnly: Boolean = false): List[List[ValDef]] =
3023+
givenOnly: Boolean = false,
3024+
numLeadParams: Int = 0): List[List[ValDef]] =
30243025

30253026
def recur(firstClause: Boolean, nparams: Int): List[List[ValDef]] =
30263027
newLineOptWhenFollowedBy(LPAREN)
@@ -3039,7 +3040,7 @@ object Parsers {
30393040
else Nil
30403041
end recur
30413042

3042-
recur(firstClause = true, 0)
3043+
recur(firstClause = true, numLeadParams)
30433044
end paramClauses
30443045

30453046
/* -------- DEFS ------------------------------------------- */
@@ -3244,7 +3245,7 @@ object Parsers {
32443245
* DefSig ::= id [DefTypeParamClause] DefParamClauses
32453246
* | ExtParamClause [nl] [‘.’] id DefParamClauses
32463247
*/
3247-
def defDefOrDcl(start: Offset, mods: Modifiers): DefDef = atSpan(start, nameStart) {
3248+
def defDefOrDcl(start: Offset, mods: Modifiers, numLeadParams: Int = 0): DefDef = atSpan(start, nameStart) {
32483249

32493250
def scala2ProcedureSyntax(resultTypeStr: String) =
32503251
def toInsert =
@@ -3261,7 +3262,7 @@ object Parsers {
32613262

32623263
if (in.token == THIS) {
32633264
in.nextToken()
3264-
val vparamss = paramClauses()
3265+
val vparamss = paramClauses(numLeadParams = numLeadParams)
32653266
if (vparamss.isEmpty || vparamss.head.take(1).exists(_.mods.isOneOf(GivenOrImplicit)))
32663267
in.token match {
32673268
case LBRACKET => syntaxError("no type parameters allowed here")
@@ -3280,7 +3281,7 @@ object Parsers {
32803281
val ident = termIdent()
32813282
var name = ident.name.asTermName
32823283
val tparams = typeParamClauseOpt(ParamOwner.Def)
3283-
val vparamss = paramClauses()
3284+
val vparamss = paramClauses(numLeadParams = numLeadParams)
32843285
var tpt = fromWithinReturnType {
32853286
if in.token == COLONEOL then in.token = COLON
32863287
// a hack to allow
@@ -3568,24 +3569,23 @@ object Parsers {
35683569
val start = in.skipToken()
35693570
val tparams = typeParamClauseOpt(ParamOwner.Def)
35703571
val leadParamss = ListBuffer[List[ValDef]]()
3571-
var nparams = 0
3572+
def nparams = leadParamss.map(_.length).sum
35723573
while
35733574
val extParams = paramClause(nparams, prefix = true)
35743575
leadParamss += extParams
3575-
nparams += extParams.length
35763576
isUsingClause(extParams)
35773577
do ()
3578-
leadParamss ++= paramClauses(givenOnly = true)
3578+
leadParamss ++= paramClauses(givenOnly = true, numLeadParams = nparams)
35793579
if in.token == COLON then
35803580
syntaxError("no `:` expected here")
35813581
in.nextToken()
35823582
val methods =
35833583
if isDefIntro(modifierTokens) then
3584-
extMethod() :: Nil
3584+
extMethod(nparams) :: Nil
35853585
else
35863586
in.observeIndented()
35873587
newLineOptWhenFollowedBy(LBRACE)
3588-
if in.isNestedStart then inDefScopeBraces(extMethods())
3588+
if in.isNestedStart then inDefScopeBraces(extMethods(nparams))
35893589
else { syntaxError("Extension without extension methods"); Nil }
35903590
val result = atSpan(start)(ExtMethods(joinParams(tparams, leadParamss.toList), methods))
35913591
val comment = in.getDocComment(start)
@@ -3597,20 +3597,20 @@ object Parsers {
35973597

35983598
/** ExtMethod ::= {Annotation [nl]} {Modifier} ‘def’ DefDef
35993599
*/
3600-
def extMethod(): DefDef =
3600+
def extMethod(numLeadParams: Int): DefDef =
36013601
val start = in.offset
36023602
val mods = defAnnotsMods(modifierTokens)
36033603
accept(DEF)
3604-
defDefOrDcl(start, mods)
3604+
defDefOrDcl(start, mods, numLeadParams)
36053605

36063606
/** ExtMethods ::= ExtMethod | [nl] ‘{’ ExtMethod {semi ExtMethod ‘}’
36073607
*/
3608-
def extMethods(): List[DefDef] = checkNoEscapingPlaceholders {
3608+
def extMethods(numLeadParams: Int): List[DefDef] = checkNoEscapingPlaceholders {
36093609
val meths = new ListBuffer[DefDef]
36103610
val exitOnError = false
36113611
while !isStatSeqEnd && !exitOnError do
36123612
setLastStatOffset()
3613-
meths += extMethod()
3613+
meths += extMethod(numLeadParams)
36143614
acceptStatSepUnlessAtEnd(meths)
36153615
if meths.isEmpty then syntaxError("`def` expected")
36163616
meths.toList

language-server/test/dotty/tools/languageserver/CompletionTest.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class CompletionTest {
5858

5959
// TODO: Also add tests with concrete classes, where the completion will
6060
// include the constructor proxy companion
61-
61+
6262
@Test def importCompleteClassWithPrefix: Unit = {
6363
withSources(
6464
code"""object Foo { abstract class MyClass }""",
@@ -328,7 +328,7 @@ class CompletionTest {
328328
|given Baz = new Baz {}
329329
|extension (foo: Foo.type)(using Bar, Baz) def xxxx = 1
330330
|object Main { Foo.xx${m1} }""".withSource
331-
.completion(m1, Set(("xxxx", Method, "(using x$1: Bar, x$2: Baz): Int")))
331+
.completion(m1, Set(("xxxx", Method, "(using x$2: Bar, x$3: Baz): Int")))
332332
}
333333

334334
@Test def completeExtensionMethodFromExtenionWithMultipleUsingSections: Unit = {
@@ -339,7 +339,7 @@ class CompletionTest {
339339
|given Baz = new Baz {}
340340
|extension (foo: Foo.type)(using Bar)(using Baz) def xxxx = 1
341341
|object Main { Foo.xx${m1} }""".withSource
342-
.completion(m1, Set(("xxxx", Method, "(using x$1: Bar)(using x$2: Baz): Int")))
342+
.completion(m1, Set(("xxxx", Method, "(using x$2: Bar)(using x$3: Baz): Int")))
343343
}
344344

345345
@Test def completeInheritedExtensionMethod: Unit = {

tests/neg/i10901.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@
3838
|
3939
| Test.foo("abc")(/* missing */summon[C]) failed with
4040
|
41-
| no implicit argument of type C was found for parameter x$1 of method foo in object Test
41+
| no implicit argument of type C was found for parameter x$2 of method foo in object Test

tests/neg/i6183.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
| render(42) failed with
88
|
99
| Ambiguous overload. The overloaded alternatives of method render in object Test with types
10-
| [B](b: B)(using x$1: DummyImplicit): Char
10+
| [B](b: B)(using x$2: DummyImplicit): Char
1111
| [A](a: A): String
1212
| both match arguments ((42 : Int))
1313
-- [E051] Reference Error: tests/neg/i6183.scala:7:9 -------------------------------------------------------------------
1414
7 | Test.render(42) // error
1515
| ^^^^^^^^^^^
1616
| Ambiguous overload. The overloaded alternatives of method render in object Test with types
17-
| [B](b: B)(using x$1: DummyImplicit): Char
17+
| [B](b: B)(using x$2: DummyImplicit): Char
1818
| [A](a: A): String
1919
| both match arguments ((42 : Int))
2020

tests/pos/i11020.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
trait Bar
2+
trait Baz
3+
trait B[X]
4+
extension (using Bar)(s: String)(using Baz) def foo = ???
5+
extension (using Bar)(s: String) def bar(using Baz) = ???
6+
extension [T: B](s: T) def baz [U: B](x: Int) = ???
7+

0 commit comments

Comments
 (0)