Skip to content

Commit 5e08d34

Browse files
committed
Remove redundant check for extension methods from Parsers and port errors of the Desugar check to the new scheme
1 parent b7539ee commit 5e08d34

14 files changed

+143
-26
lines changed

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -930,21 +930,24 @@ object desugar {
930930

931931
def makeExtensionDef(mdef: Tree, tparams: List[TypeDef], leadingParams: List[ValDef],
932932
givenParamss: List[List[ValDef]])(using ctx: Context): Tree = {
933-
val allowed = "allowed here, since collective parameters are given"
934933
mdef match {
935934
case mdef: DefDef =>
936935
if (mdef.mods.is(Extension)) {
937-
ctx.error(em"No extension method $allowed", mdef.sourcePos)
936+
ctx.error(NoExtensionMethodAllowed(mdef), mdef.sourcePos)
938937
mdef
938+
} else {
939+
if (tparams.nonEmpty && mdef.tparams.nonEmpty) then
940+
ctx.error(ExtensionMethodCannotHaveTypeParams(mdef), mdef.tparams.head.sourcePos)
941+
mdef
942+
else cpy.DefDef(mdef)(
943+
tparams = tparams ++ mdef.tparams,
944+
vparamss = leadingParams :: givenParamss ::: mdef.vparamss
945+
).withMods(mdef.mods | Extension)
939946
}
940-
else cpy.DefDef(mdef)(
941-
tparams = tparams ++ mdef.tparams,
942-
vparamss = leadingParams :: givenParamss ::: mdef.vparamss
943-
).withMods(mdef.mods | Extension)
944947
case mdef: Import =>
945948
mdef
946949
case mdef =>
947-
ctx.error(em"Only methods $allowed", mdef.sourcePos)
950+
ctx.error(ExtensionCanOnlyHaveDefs(mdef), mdef.sourcePos)
948951
mdef
949952
}
950953
}

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3470,17 +3470,6 @@ object Parsers {
34703470
Template(constr, parents, Nil, EmptyValDef, Nil)
34713471
}
34723472

3473-
def checkExtensionMethod(tparams: List[Tree], stat: Tree): Unit = stat match {
3474-
case stat: DefDef =>
3475-
if stat.mods.is(Extension) then
3476-
syntaxError(i"no extension method allowed here since leading parameter was already given", stat.span)
3477-
else if tparams.nonEmpty && stat.tparams.nonEmpty then
3478-
syntaxError(i"extension method cannot have type parameters since some were already given previously",
3479-
stat.tparams.head.span)
3480-
case stat =>
3481-
syntaxError(i"extension clause can only define methods", stat.span)
3482-
}
3483-
34843473
/** GivenDef ::= [GivenSig] [‘_’ ‘<:’] Type ‘=’ Expr
34853474
* | [GivenSig] ConstrApps [TemplateBody]
34863475
* GivenSig ::= [id] [DefTypeParamClause] {UsingParamClauses} ‘as’
@@ -3541,7 +3530,6 @@ object Parsers {
35413530
possibleTemplateStart()
35423531
if !in.isNestedStart then syntaxError("Extension without extension methods")
35433532
val templ = templateBodyOpt(makeConstructor(tparams, extParams :: givenParamss), Nil, Nil)
3544-
templ.body.foreach(checkExtensionMethod(tparams, _))
35453533
val edef = ModuleDef(name, templ)
35463534
finalizeDef(edef, addFlag(mods, Given), start)
35473535
}

compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ enum ErrorMessageID extends java.lang.Enum[ErrorMessageID] {
158158
ModifierRedundantForObjectsID,
159159
TypedCaseDoesNotExplicitlyExtendTypedEnumID,
160160
IllegalRedefinitionOfStandardKindID,
161+
NoExtensionMethodAllowedID,
162+
ExtensionMethodCannotHaveTypeParamsID,
163+
ExtensionCanOnlyHaveDefsID,
161164
UnexpectedPatternForSummonFromID
162165

163166
def errorNumber = ordinal - 2

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,6 +2470,42 @@ object messages {
24702470
|""".stripMargin
24712471
}
24722472

2473+
case class NoExtensionMethodAllowed(mdef: untpd.DefDef)(implicit ctx: Context)
2474+
extends Message(NoExtensionMethodAllowedID) {
2475+
val kind: String = "Syntax"
2476+
val msg: String = em"No extension method allowed here, since collective parameters are given"
2477+
2478+
val explanation: String =
2479+
em"""|Extension method:
2480+
| `${mdef}`
2481+
|is defined inside an extension clause which has collective parameters.
2482+
|""".stripMargin
2483+
}
2484+
2485+
case class ExtensionMethodCannotHaveTypeParams(mdef: untpd.DefDef)(implicit ctx: Context)
2486+
extends Message(ExtensionMethodCannotHaveTypeParamsID) {
2487+
val kind: String = "Syntax"
2488+
val msg: String = i"Extension method cannot have type parameters since some were already given previously"
2489+
2490+
val explanation: String =
2491+
em"""|Extension method:
2492+
| `${mdef}`
2493+
|has type parameters `[${mdef.tparams.map(_.show).mkString(",")}]`, while the extension clause has
2494+
|it's own type parameters. Please consider moving these to the extension clause's type parameter list.
2495+
|""".stripMargin
2496+
}
2497+
2498+
case class ExtensionCanOnlyHaveDefs(mdef: untpd.Tree)(implicit ctx: Context)
2499+
extends Message(ExtensionCanOnlyHaveDefsID) {
2500+
val kind: String = "Syntax"
2501+
val msg: String = em"Only methods allowed here, since collective parameters are given"
2502+
2503+
val explanation: String =
2504+
em"""Extension clauses can only have `def`s
2505+
| `${mdef.show}` is not a valid expression here.
2506+
|""".stripMargin
2507+
}
2508+
24732509
case class UnexpectedPatternForSummonFrom(tree: Tree[_])(implicit ctx: Context)
24742510
extends Message(UnexpectedPatternForSummonFromID) {
24752511
val kind: String = "Syntax"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ trait Applications extends Compatibility {
10761076
msgs match
10771077
case msg :: Nil =>
10781078
msg.contained match
1079-
case messages.NotAMember(_, nme.unapply, _, _) => return notAnExtractor(tree)
1079+
case NotAMember(_, nme.unapply, _, _) => return notAnExtractor(tree)
10801080
case _ =>
10811081
case _ =>
10821082
msgs.foreach(ctx.reporter.report)

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,4 +1839,58 @@ class ErrorMessagesTests extends ErrorMessagesTest {
18391839
assertEquals("Unexpected pattern for summonFrom. Expected `x: T` or `_`", errorMsg)
18401840
assertEquals("given x @ String", x.show)
18411841
}
1842+
1843+
@Test def extensionMethodsNotAllowed =
1844+
checkMessagesAfter(RefChecks.name) {
1845+
"""object Test {
1846+
| extension on[T] (t: T) {
1847+
| def (c: T).f: T = ???
1848+
| }
1849+
|}
1850+
""".stripMargin
1851+
}
1852+
.expect { (ictx, messages)
1853+
implicit val ctx: Context = ictx
1854+
assertMessageCount(1, messages)
1855+
val errorMsg = messages.head.msg
1856+
val NoExtensionMethodAllowed(x) :: Nil = messages
1857+
assertEquals("No extension method allowed here, since collective parameters are given", errorMsg)
1858+
assertEquals("def (c: T) f: T = ???", x.show)
1859+
}
1860+
1861+
@Test def extensionMethodTypeParamsNotAllowed =
1862+
checkMessagesAfter(RefChecks.name) {
1863+
"""object Test {
1864+
| extension on[T] (t: T) {
1865+
| def f[U](u: U): T = ???
1866+
| }
1867+
|}
1868+
""".stripMargin
1869+
}
1870+
.expect { (ictx, messages)
1871+
implicit val ctx: Context = ictx
1872+
assertMessageCount(1, messages)
1873+
val errorMsg = messages.head.msg
1874+
val ExtensionMethodCannotHaveTypeParams(x) :: Nil = messages
1875+
assertEquals("Extension method cannot have type parameters since some were already given previously", errorMsg)
1876+
assertEquals("def f[U](u: U): T = ???", x.show)
1877+
}
1878+
1879+
@Test def extensionMethodCanOnlyHaveDefs =
1880+
checkMessagesAfter(RefChecks.name) {
1881+
"""object Test {
1882+
| extension on[T] (t: T) {
1883+
| val v: T = t
1884+
| }
1885+
|}
1886+
""".stripMargin
1887+
}
1888+
.expect { (ictx, messages)
1889+
implicit val ctx: Context = ictx
1890+
assertMessageCount(1, messages)
1891+
val errorMsg = messages.head.msg
1892+
val ExtensionCanOnlyHaveDefs(x) :: Nil = messages
1893+
assertEquals("Only methods allowed here, since collective parameters are given", errorMsg)
1894+
assertEquals("val v: T = t", x.show)
1895+
}
18421896
}

tests/neg/SummonFrom.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
-- [E150] Syntax Error: tests/neg/SummonFrom.scala:4:7 -----------------------------------------------------------------
1+
-- [E153] Syntax Error: tests/neg/SummonFrom.scala:4:7 -----------------------------------------------------------------
22
4 | case x => ??? // error
33
| ^
44
| Unexpected pattern for summonFrom. Expected `x: T` or `_`
55

66
longer explanation available when compiling with `-explain`
7-
-- [E150] Syntax Error: tests/neg/SummonFrom.scala:8:7 -----------------------------------------------------------------
7+
-- [E153] Syntax Error: tests/neg/SummonFrom.scala:8:7 -----------------------------------------------------------------
88
8 | case x@String => ??? // error
99
| ^^^^^^^^
1010
| Unexpected pattern for summonFrom. Expected `x: T` or `_`
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- [E151] Syntax Error: tests/neg/extension-cannot-have-type.scala:3:10 ------------------------------------------------
2+
3 | def f[U](u: U): T = ??? // error : extension method cannot have type params
3+
| ^
4+
| Extension method cannot have type parameters since some were already given previously
5+
6+
longer explanation available when compiling with `-explain`
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test {
2+
extension on[T] (t: T) {
3+
def f[U](u: U): T = ??? // error : extension method cannot have type params
4+
}
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- [E150] Syntax Error: tests/neg/extension-method-not-allowed.scala:3:8 -----------------------------------------------
2+
3 | def (c: T).f: T = ??? // error : No extension method allowed here
3+
| ^^^^^^^^^^^^^^^^^^^^^
4+
| No extension method allowed here, since collective parameters are given
5+
6+
longer explanation available when compiling with `-explain`
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test {
2+
extension on[T] (t: T) {
3+
def (c: T).f: T = ??? // error : No extension method allowed here
4+
}
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-- [E152] Syntax Error: tests/neg/extensions-can-only-have-defs.scala:3:8 ----------------------------------------------
2+
3 | val v: T = ??? // error : extensions can only have defs
3+
| ^^^^^^^^^^^^^^
4+
| Only methods allowed here, since collective parameters are given
5+
6+
longer explanation available when compiling with `-explain`
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
object Test {
2+
extension on[T] (t: T) {
3+
val v: T = ??? // error : extensions can only have defs
4+
}
5+
}

tests/neg/i6900.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ object Test2 {
44
extension on [A](a: A):
55
def foo[C]: C => A = _ => a // error: extension method cannot have type parameters
66

7-
1.foo.foo
7+
1.foo.foo // error: foo is undefined
88

99
// ... but have to pass 2 parameters
10-
1.foo.foo[Any => Int, String]
11-
1.foo[Int, String].foo
12-
1.foo[Int, String].foo[String => Int, String]
10+
1.foo.foo[Any => Int, String] // error: foo is undefined
11+
1.foo[Int, String].foo // error: foo is undefined
12+
1.foo[Int, String].foo[String => Int, String] // error: foo is undefined
1313

1414
}
1515

0 commit comments

Comments
 (0)