Skip to content

Commit fc34c1a

Browse files
committed
Disable variance checks in default getters
This matches what Scala 2 does and is needed to compile geny in the community build which does: def count(f: A => Boolean = ((_: Any) => true)) This happened to work before the previous commit because the inferred type of the getter was `Any => Boolean`. See the added testcase for a justification of the relaxed variance checking.
1 parent 6fde5c1 commit fc34c1a

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ class VarianceChecker(using Context) {
194194
def sym = tree.symbol
195195
// No variance check for private/protected[this] methods/values.
196196
def skip = !sym.exists
197-
|| sym.name.is(InlineAccessorName) // TODO: should we exclude all synthetic members?
197+
|| sym.name.is(InlineAccessorName)
198+
|| sym.name.is(DefaultGetterName) // see default-getter-variance.scala
198199
|| sym.isAllOf(LocalParamAccessor) // local class parameters are construction only
199200
|| sym.is(TypeParam) && sym.owner.isClass // already taken care of in primary constructor of class
200201
try tree match {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Foo[+A] {
2+
def count(f: A => Boolean = _ => true): Unit = {}
3+
// The preceding line is valid, even though the generated default getter
4+
// has type `A => Boolean` which wouldn't normally pass variance checks
5+
// because it's equivalent to the following overloads which are valid:
6+
def count2(f: A => Boolean): Unit = {}
7+
def count2(): Unit = count(_ => true)
8+
}
9+
10+
class Bar1[+A] extends Foo[A] {
11+
override def count(f: A => Boolean): Unit = {}
12+
// This reasoning extends to overrides:
13+
override def count2(f: A => Boolean): Unit = {}
14+
}
15+
16+
class Bar2[+A] extends Foo[A] {
17+
override def count(f: A => Boolean = _ => true): Unit = {}
18+
// ... including overrides which also override the default getter:
19+
override def count2(f: A => Boolean): Unit = {}
20+
override def count2(): Unit = count(_ => true)
21+
}
22+
23+
// This can be contrasted with the need for variance checks in
24+
// `protected[this] methods (cf tests/neg/t7093.scala),
25+
// default getters do not have the same problem since they cannot
26+
// appear in arbitrary contexts.

0 commit comments

Comments
 (0)