Skip to content

Commit 1ab80f7

Browse files
authored
Merge pull request #10917 from dotty-staging/fix-#10871
Refine SAM handling in SuperAccessors.
2 parents 8fab91c + bac02cd commit 1ab80f7

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,23 @@ import dotty.tools.dotc.util.Spans.Span
2222
*
2323
* However, implicit function types do not count as SAM types.
2424
*/
25-
class ExpandSAMs extends MiniPhase {
26-
override def phaseName: String = "expandSAMs"
27-
28-
import ast.tpd._
25+
object ExpandSAMs:
26+
val name: String = "expandSAMs"
2927

3028
/** Is the SAMType `cls` also a SAM under the rules of the platform? */
3129
def isPlatformSam(cls: ClassSymbol)(using Context): Boolean =
3230
ctx.platform.isSam(cls)
3331

32+
def needsWrapperClass(tpe: Type)(using Context): Boolean =
33+
tpe.classSymbol match
34+
case cls: ClassSymbol => !isPlatformSam(cls) || cls == defn.PartialFunctionClass
35+
case _ => false
36+
37+
class ExpandSAMs extends MiniPhase:
38+
import ast.tpd._
39+
40+
override def phaseName: String = ExpandSAMs.name
41+
3442
override def transformBlock(tree: Block)(using Context): Tree = tree match {
3543
case Block(stats @ (fn: DefDef) :: Nil, Closure(_, fnRef, tpt)) if fnRef.symbol == fn.symbol =>
3644
tpt.tpe match {
@@ -41,7 +49,7 @@ class ExpandSAMs extends MiniPhase {
4149
case tpe @ SAMType(_) if tpe.isRef(defn.PartialFunctionClass) =>
4250
val tpe1 = checkRefinements(tpe, fn)
4351
toPartialFunction(tree, tpe1)
44-
case tpe @ SAMType(_) if isPlatformSam(tpe.classSymbol.asClass) =>
52+
case tpe @ SAMType(_) if ExpandSAMs.isPlatformSam(tpe.classSymbol.asClass) =>
4553
checkRefinements(tpe, fn)
4654
tree
4755
case tpe =>
@@ -176,5 +184,5 @@ class ExpandSAMs extends MiniPhase {
176184
case tpe =>
177185
tpe
178186
}
179-
}
187+
end ExpandSAMs
180188

compiler/src/dotty/tools/dotc/transform/PostTyper.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
411411
super.transform(selector),
412412
cases.mapConserve(tranformIgnoringBoundsCheck)
413413
)
414+
case Block(_, Closure(_, _, tpt)) if ExpandSAMs.needsWrapperClass(tpt.tpe) =>
415+
superAcc.withInvalidCurrentClass(super.transform(tree))
414416
case tree =>
415417
super.transform(tree)
416418
}

compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class SuperAccessors(thisPhase: DenotTransformer) {
3636

3737
import tpd._
3838

39-
4039
/** Some parts of trees will get a new owner in subsequent phases.
4140
* These are value class methods, which will become extension methods.
4241
* (By-name arguments used to be included also, but these
@@ -51,9 +50,9 @@ class SuperAccessors(thisPhase: DenotTransformer) {
5150
*/
5251
private var invalidEnclClass: Symbol = NoSymbol
5352

54-
private def withInvalidCurrentClass[A](trans: => A)(using Context): A = {
53+
def withInvalidCurrentClass[A](trans: => A)(using Context): A = {
5554
val saved = invalidEnclClass
56-
invalidEnclClass = ctx.owner
55+
invalidEnclClass = ctx.owner.enclosingClass
5756
try trans
5857
finally invalidEnclClass = saved
5958
}
@@ -156,12 +155,8 @@ class SuperAccessors(thisPhase: DenotTransformer) {
156155
}
157156
}
158157

159-
val needAccessor = name.isTermName && {
160-
mix.name.isEmpty && (clazz.is(Trait) || clazz != currentClass || !validCurrentClass) ||
161-
// SI-8803. If we access super[A] from an inner class (!= currentClass) or closure (validCurrentClass),
162-
// where A is the superclass we need an accessor.
163-
!mix.name.isEmpty && (clazz != currentClass || !validCurrentClass)
164-
}
158+
val needAccessor = name.isTermName && (
159+
clazz != currentClass || !validCurrentClass || mix.name.isEmpty && clazz.is(Trait))
165160

166161
if (needAccessor) atPhase(thisPhase.next)(superAccessorCall(sel, mix.name))
167162
else sel

tests/pos/i10871.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
trait A { def i = 1 }
2+
class B extends A {
3+
class C {
4+
val x = B.super.i // needs accessor
5+
}
6+
val f: Int => Int =
7+
_ => super.i // OK
8+
trait Sammy {
9+
def run(x: Int): Int
10+
}
11+
val s1: Sammy = (x: Int) => super.i // OK
12+
abstract class Sam {
13+
def run(x: Int): Int
14+
}
15+
val s2: Sam = (x: Int) => super.i // needs accessor
16+
val p: PartialFunction[Int, Int] = {
17+
case _ => super.i // needs accessor
18+
}
19+
}

0 commit comments

Comments
 (0)