Skip to content

Commit 1b4b390

Browse files
committed
Disallow use of PolyFunction trait in class parents
Users should only write lambdas. Fixes #10075
1 parent c81673c commit 1b4b390

20 files changed

+99
-17
lines changed

Diff for: compiler/src/dotty/tools/dotc/transform/PostTyper.scala

+1
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ class PostTyper extends MacroTransform with InfoTransformer { thisPhase =>
370370
val callTrace = ref(call.symbol)(using ctx.withSource(pos.source)).withSpan(pos.span)
371371
cpy.Inlined(tree)(callTrace, transformSub(bindings), transform(expansion)(using inlineContext(tree)))
372372
case templ: Template =>
373+
Checking.checkPolyFunctionExtension(templ)
373374
withNoCheckNews(templ.parents.flatMap(newPart)) {
374375
forwardParamAccessors(templ)
375376
synthMbr.addSyntheticMembers(

Diff for: compiler/src/dotty/tools/dotc/typer/Checking.scala

+8
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,14 @@ object Checking {
849849
def reportNoRefinements(pos: SrcPos) =
850850
report.error("PolyFunction subtypes must refine the apply method", pos)
851851
}.traverse(tree)
852+
853+
/** Check that users do not extend the `PolyFunction` trait.
854+
* We only allow compiler generated `PolyFunction`s.
855+
*/
856+
def checkPolyFunctionExtension(templ: Template)(using Context): Unit =
857+
templ.parents.find(_.tpe.derivesFrom(defn.PolyFunctionClass)) match
858+
case Some(parent) => report.error(s"`PolyFunction` marker trait is reserved for compiler generated refinements", parent.srcPos)
859+
case None =>
852860
}
853861

854862
trait Checking {

Diff for: tests/run/erased-15.scala renamed to tests/neg/erased-15.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ object Test {
1212
}
1313
}
1414

15-
class Foo extends PolyFunction {
15+
class Foo extends PolyFunction { // error
1616
def apply(erased x: Int): Int = {
1717
println("Foo.apply")
1818
42

Diff for: tests/neg/i10075.check

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
-- Error: tests/neg/i10075.scala:8:24 ----------------------------------------------------------------------------------
2+
8 |trait PolyTrait extends PolyFunction // error
3+
| ^^^^^^^^^^^^
4+
| `PolyFunction` marker trait is reserved for compiler generated refinements
5+
-- Error: tests/neg/i10075.scala:10:24 ---------------------------------------------------------------------------------
6+
10 |class PolyClass extends PolyTrait { // error
7+
| ^^^^^^^^^
8+
| `PolyFunction` marker trait is reserved for compiler generated refinements
9+
-- Error: tests/neg/i10075.scala:14:26 ---------------------------------------------------------------------------------
10+
14 |object PolyObject extends PolyFunction // error
11+
| ^^^^^^^^^^^^
12+
| `PolyFunction` marker trait is reserved for compiler generated refinements
13+
-- Error: tests/neg/i10075.scala:2:14 ----------------------------------------------------------------------------------
14+
2 |val foo = new PolyFunction { } // error
15+
| ^^^^^^^^^^^^
16+
| `PolyFunction` marker trait is reserved for compiler generated refinements
17+
-- Error: tests/neg/i10075.scala:3:14 ----------------------------------------------------------------------------------
18+
3 |val bar = new PolyFunction { def bar = 23 } // error
19+
| ^^^^^^^^^^^^
20+
| `PolyFunction` marker trait is reserved for compiler generated refinements
21+
-- Error: tests/neg/i10075.scala:4:14 ----------------------------------------------------------------------------------
22+
4 |val baz = new PolyFunction { def apply = 23 } // error
23+
| ^^^^^^^^^^^^
24+
| `PolyFunction` marker trait is reserved for compiler generated refinements
25+
-- Error: tests/neg/i10075.scala:5:14 ----------------------------------------------------------------------------------
26+
5 |val qux = new PolyFunction { def apply[T] = 47 } // error
27+
| ^^^^^^^^^^^^
28+
| `PolyFunction` marker trait is reserved for compiler generated refinements
29+
-- Error: tests/neg/i10075.scala:6:15 ----------------------------------------------------------------------------------
30+
6 |val quxx = new PolyFunction { def apply[T](x: T): T = x } // error
31+
| ^^^^^^^^^^^^
32+
| `PolyFunction` marker trait is reserved for compiler generated refinements

Diff for: tests/neg/i10075.scala

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
val poly = [T] => (x: T) => x
2+
val foo = new PolyFunction { } // error
3+
val bar = new PolyFunction { def bar = 23 } // error
4+
val baz = new PolyFunction { def apply = 23 } // error
5+
val qux = new PolyFunction { def apply[T] = 47 } // error
6+
val quxx = new PolyFunction { def apply[T](x: T): T = x } // error
7+
8+
trait PolyTrait extends PolyFunction // error
9+
10+
class PolyClass extends PolyTrait { // error
11+
def apply[T](x: T): T = x
12+
}
13+
14+
object PolyObject extends PolyFunction // error

Diff for: tests/neg/i10369.scala

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
type Upgrade[T] = T match
2+
case Int => Double
3+
case Char => String
4+
case Boolean => Boolean
5+
6+
val upgrade: [t] => t => Upgrade[t] = new PolyFunction: // error
7+
def apply[T](x: T): Upgrade[T] = x match
8+
case x: Int => x.toDouble
9+
case x: Char => x.toString
10+
case x: Boolean => !x
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
def test = polyFun(1)
22

33
def polyFun: PolyFunction { def apply(x: Int): Int } =
4-
new PolyFunction { def apply(x: Int): Int = x + 1 }
4+
new PolyFunction { def apply(x: Int): Int = x + 1 } // error

Diff for: tests/neg/i18302b.check

+4
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
3 |def polyFun: PolyFunction { def apply(x: Int)(y: Int): Int } = // error
33
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44
|Implementation restriction: PolyFunction apply must have exactly one parameter list and optionally type arguments. No by-name nor varags are allowed.
5+
-- Error: tests/neg/i18302b.scala:4:6 ----------------------------------------------------------------------------------
6+
4 | new PolyFunction: // error
7+
| ^^^^^^^^^^^^
8+
| `PolyFunction` marker trait is reserved for compiler generated refinements

Diff for: tests/neg/i18302b.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
def test = polyFun(1)(2)
22

33
def polyFun: PolyFunction { def apply(x: Int)(y: Int): Int } = // error
4-
new PolyFunction:
4+
new PolyFunction: // error
55
def apply(x: Int)(y: Int): Int = x + y

Diff for: tests/neg/i18302c.check

+4
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
4 |def polyFun: PolyFunction { def foo(x: Int): Int } = // error
33
| ^^^^^^^^^^^^^^^^^^^^
44
| PolyFunction only supports apply method refinements
5+
-- Error: tests/neg/i18302c.scala:5:6 ----------------------------------------------------------------------------------
6+
5 | new PolyFunction { def foo(x: Int): Int = x + 1 } // error
7+
| ^^^^^^^^^^^^
8+
| `PolyFunction` marker trait is reserved for compiler generated refinements

Diff for: tests/neg/i18302c.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ import scala.reflect.Selectable.reflectiveSelectable
22

33
def test = polyFun.foo(1)
44
def polyFun: PolyFunction { def foo(x: Int): Int } = // error
5-
new PolyFunction { def foo(x: Int): Int = x + 1 }
5+
new PolyFunction { def foo(x: Int): Int = x + 1 } // error

Diff for: tests/neg/i18302d.check

+4
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@
22
1 |def polyFun: PolyFunction { def apply: Int } = // error
33
| ^^^^^^^^^^^^^^
44
|Implementation restriction: PolyFunction apply must have exactly one parameter list and optionally type arguments. No by-name nor varags are allowed.
5+
-- Error: tests/neg/i18302d.scala:2:6 ----------------------------------------------------------------------------------
6+
2 | new PolyFunction { def apply: Int = 1 } // error
7+
| ^^^^^^^^^^^^
8+
| `PolyFunction` marker trait is reserved for compiler generated refinements

Diff for: tests/neg/i18302d.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
def polyFun: PolyFunction { def apply: Int } = // error
2-
new PolyFunction { def apply: Int = 1 }
2+
new PolyFunction { def apply: Int = 1 } // error

Diff for: tests/neg/i18302e.check

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
1 |def polyFun: PolyFunction { } = // error
33
| ^^^^^^^^^^^^^^^^^
44
| PolyFunction subtypes must refine the apply method
5+
-- Error: tests/neg/i18302e.scala:2:6 ----------------------------------------------------------------------------------
6+
2 | new PolyFunction { } // error
7+
| ^^^^^^^^^^^^
8+
| `PolyFunction` marker trait is reserved for compiler generated refinements
59
-- Error: tests/neg/i18302e.scala:4:15 ---------------------------------------------------------------------------------
610
4 |def polyFun(f: PolyFunction { }) = () // error
711
| ^^^^^^^^^^^^^^^^^

Diff for: tests/neg/i18302e.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
def polyFun: PolyFunction { } = // error
2-
new PolyFunction { }
2+
new PolyFunction { } // error
33

44
def polyFun(f: PolyFunction { }) = () // error

Diff for: tests/neg/i18302f.check

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
1 |def polyFun: PolyFunction = // error
33
| ^^^^^^^^^^^^
44
| PolyFunction subtypes must refine the apply method
5+
-- Error: tests/neg/i18302f.scala:2:6 ----------------------------------------------------------------------------------
6+
2 | new PolyFunction { } // error
7+
| ^^^^^^^^^^^^
8+
| `PolyFunction` marker trait is reserved for compiler generated refinements
59
-- Error: tests/neg/i18302f.scala:4:16 ---------------------------------------------------------------------------------
610
4 |def polyFun2(a: PolyFunction) = () // error
711
| ^^^^^^^^^^^^
@@ -10,3 +14,7 @@
1014
6 |val polyFun3: PolyFunction = // error
1115
| ^^^^^^^^^^^^
1216
| PolyFunction subtypes must refine the apply method
17+
-- Error: tests/neg/i18302f.scala:7:6 ----------------------------------------------------------------------------------
18+
7 | new PolyFunction { } // error
19+
| ^^^^^^^^^^^^
20+
| `PolyFunction` marker trait is reserved for compiler generated refinements

Diff for: tests/neg/i18302f.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
def polyFun: PolyFunction = // error
2-
new PolyFunction { }
2+
new PolyFunction { } // error
33

44
def polyFun2(a: PolyFunction) = () // error
55

66
val polyFun3: PolyFunction = // error
7-
new PolyFunction { }
7+
new PolyFunction { } // error

Diff for: tests/neg/i18302j.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
def polyFunByName: PolyFunction { def apply(thunk: => Int): Int } = // error
2-
new PolyFunction { def apply(thunk: => Int): Int = 1 }
2+
new PolyFunction { def apply(thunk: => Int): Int = 1 } // error
33

44
def polyFunVarArgs: PolyFunction { def apply(args: Int*): Int } = // error
5-
new PolyFunction { def apply(thunk: Int*): Int = 1 }
5+
new PolyFunction { def apply(thunk: Int*): Int = 1 } // error

Diff for: tests/pos/i10369.scala

-6
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@ type Upgrade[T] = T match
33
case Char => String
44
case Boolean => Boolean
55

6-
val upgrade: [t] => t => Upgrade[t] = new PolyFunction:
7-
def apply[T](x: T): Upgrade[T] = x match
8-
case x: Int => x.toDouble
9-
case x: Char => x.toString
10-
case x: Boolean => !x
11-
126
val upgrade2: [t] => t => Upgrade[t] = [t] => (x: t) => x match
137
case x: Int => x.toDouble
148
case x: Char => x.toString

Diff for: tests/run/erased-15.check

-1
This file was deleted.

0 commit comments

Comments
 (0)