Skip to content

Commit 27a4d8f

Browse files
authored
Make right assoc ext method fwd refs error (#21641)
Fixes #16815
2 parents f647651 + f684bac commit 27a4d8f

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

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

+16-4
Original file line numberDiff line numberDiff line change
@@ -1099,8 +1099,8 @@ object desugar {
10991099
paramss match
11001100
case rightParam :: paramss1 => // `rightParam` must have a single parameter and without `given` flag
11011101

1102-
def badRightAssoc(problem: String) =
1103-
report.error(em"right-associative extension method $problem", mdef.srcPos)
1102+
def badRightAssoc(problem: String, pos: SrcPos) =
1103+
report.error(em"right-associative extension method $problem", pos)
11041104
extParamss ++ mdef.paramss
11051105

11061106
rightParam match
@@ -1116,11 +1116,23 @@ object desugar {
11161116
//
11171117
// If you change the names of the clauses below, also change them in right-associative-extension-methods.md
11181118
val (leftTyParamsAndLeadingUsing, leftParamAndTrailingUsing) = extParamss.span(isUsingOrTypeParamClause)
1119+
1120+
val names = (for ps <- mdef.paramss; p <- ps yield p.name).toSet[Name]
1121+
1122+
val tt = new untpd.UntypedTreeTraverser:
1123+
def traverse(tree: Tree)(using Context): Unit = tree match
1124+
case tree: Ident if names.contains(tree.name) =>
1125+
badRightAssoc(s"cannot have a forward reference to ${tree.name}", tree.srcPos)
1126+
case _ => traverseChildren(tree)
1127+
1128+
for ts <- leftParamAndTrailingUsing; t <- ts do
1129+
tt.traverse(t)
1130+
11191131
leftTyParamsAndLeadingUsing ::: rightTyParams ::: rightParam :: leftParamAndTrailingUsing ::: paramss1
11201132
else
1121-
badRightAssoc("cannot start with using clause")
1133+
badRightAssoc("cannot start with using clause", mdef.srcPos)
11221134
case _ =>
1123-
badRightAssoc("must start with a single parameter")
1135+
badRightAssoc("must start with a single parameter", mdef.srcPos)
11241136
case _ =>
11251137
// no value parameters, so not an infix operator.
11261138
extParamss ++ mdef.paramss

tests/neg/i16815.check

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-- Error: tests/neg/i16815.scala:3:37 ----------------------------------------------------------------------------------
2+
3 |extension [C1 >: Chain <: Chain](c2: c1.Tail) // error
3+
| ^^
4+
| right-associative extension method cannot have a forward reference to c1
5+
-- Error: tests/neg/i16815.scala:6:24 ----------------------------------------------------------------------------------
6+
6 |extension [C1](c2: (C1, C2)) // error
7+
| ^^
8+
| right-associative extension method cannot have a forward reference to C2
9+
-- Error: tests/neg/i16815.scala:9:19 ----------------------------------------------------------------------------------
10+
9 |extension [C1](c2: C2) // error
11+
| ^^
12+
| right-associative extension method cannot have a forward reference to C2
13+
-- Error: tests/neg/i16815.scala:12:24 ---------------------------------------------------------------------------------
14+
12 |extension [C1](c2: (C1, C2, C3)) // error // error
15+
| ^^
16+
| right-associative extension method cannot have a forward reference to C2
17+
-- Error: tests/neg/i16815.scala:12:28 ---------------------------------------------------------------------------------
18+
12 |extension [C1](c2: (C1, C2, C3)) // error // error
19+
| ^^
20+
| right-associative extension method cannot have a forward reference to C3
21+
-- Error: tests/neg/i16815.scala:15:48 ---------------------------------------------------------------------------------
22+
15 |extension [C1](str: String)(using z: (str.type, C2)) // error
23+
| ^^
24+
| right-associative extension method cannot have a forward reference to C2
25+
-- Error: tests/neg/i16815.scala:19:31 ---------------------------------------------------------------------------------
26+
19 |extension [D1 <: Int](D2: (D1, D2)) // error
27+
| ^^
28+
| right-associative extension method cannot have a forward reference to D2

tests/neg/i16815.scala

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
trait Chain { type Tail <: Chain }
2+
3+
extension [C1 >: Chain <: Chain](c2: c1.Tail) // error
4+
def ra1_:[C2 <: C1](c1: C1): C2 = ???
5+
6+
extension [C1](c2: (C1, C2)) // error
7+
def ra2_:[C2 <: C1](c1: (C1, C2)): C2 = ???
8+
9+
extension [C1](c2: C2) // error
10+
def ra3_:[C2 <: C1](c1: C1): C2 = ???
11+
12+
extension [C1](c2: (C1, C2, C3)) // error // error
13+
def ra4_:[C2 <: C1, C3 <: C1](c1: (C1, C2)): C2 = ???
14+
15+
extension [C1](str: String)(using z: (str.type, C2)) // error
16+
def ra5_:[C2 <: Int](c1: C1): C2 = ???
17+
18+
type D2 = String
19+
extension [D1 <: Int](D2: (D1, D2)) // error
20+
def sa2_:[D2 <: D1](D1: (D1, D2)): D2 = ???

0 commit comments

Comments
 (0)