Skip to content

Commit

Permalink
Fix enclosingClass from returning refinement classes
Browse files Browse the repository at this point in the history
Looking at how i20952 is compiled, the call

    ctx.owner.enclosingClass.derivesFrom(sym.owner)

in SuperAccessors (that I moved to ProtectedAccessors) accidentally
fails, because the refinement class returned as the enclosing class of
`val prog` doesn't derive from SuperClass.  But if the enclosing class
of `prog` returned is `trait Child` then no super accessor call is
necessary.
  • Loading branch information
dwijnand committed Aug 21, 2024
1 parent 18af52a commit 9a5c41a
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 6 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/cc/CaptureSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ sealed abstract class CaptureSet extends Showable:
*/
def accountsFor(x: CaptureRef)(using Context): Boolean =
if comparer.isInstanceOf[ExplainingTypeComparer] then // !!! DEBUG
reporting.trace.force(i"$this accountsFor $x, ${x.captureSetOfInfo}?", show = true):
reporting.trace(i"$this accountsFor $x, ${x.captureSetOfInfo}?", show = true):
elems.exists(_.subsumes(x))
|| !x.isMaxCapability && x.captureSetOfInfo.subCaptures(this, frozen = true).isOK
else
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1162,10 +1162,10 @@ object SymDenotations {
final def enclosingClass(using Context): Symbol = {
def enclClass(sym: Symbol, skip: Boolean): Symbol = {
def newSkip = sym.is(JavaStaticTerm)
if (!sym.exists)
if !sym.exists then
NoSymbol
else if (sym.isClass)
if (skip) enclClass(sym.owner, newSkip) else sym
else if sym.isClass then
if skip || sym.isRefinementClass then enclClass(sym.owner, newSkip) else sym
else
enclClass(sym.owner, skip || newSkip)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ object ProtectedAccessors {
/** Do we need a protected accessor for accessing sym from the current context's owner? */
def needsAccessor(sym: Symbol)(using Context): Boolean =
needsAccessorIfNotInSubclass(sym) &&
!ctx.owner.enclosingClass.derivesFrom(sym.owner)
!needsAccessorIsSubclass(sym)

def needsAccessorIsSubclass(sym: Symbol)(using Context): Boolean =
ctx.owner.enclosingClass.derivesFrom(sym.owner)
}

class ProtectedAccessors extends MiniPhase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class SuperAccessors(thisPhase: DenotTransformer) {
* Otherwise, we need to go through an accessor,
* which the implementing class will provide an implementation for.
*/
if ctx.owner.enclosingClass.derivesFrom(sym.owner) then
if ProtectedAccessors.needsAccessorIsSubclass(sym) then
if sym.is(JavaDefined) then
report.error(em"${ctx.owner} accesses protected $sym inside a concrete trait method: use super.${sel.name} instead", sel.srcPos)
sel
Expand Down
20 changes: 20 additions & 0 deletions tests/pos/i20952.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package object packer: // the super class needs to be in a different package
class SuperClass():
protected val problem: Any = ??? // needs to be protected

class SuperClass():
protected val problem: Any = ??? // needs to be protected

// type Target = SuperClass // passes
type Target = packer.SuperClass // error

trait Child extends Target:

val aliased: problem.type = problem
type Alias = problem.type

val newProblem: Any {val prog: problem.type} = ??? // error
val newProblem2: Any {val prog: Alias} = ??? // passes
val newProblem3: Any {val prog: aliased.type} = ??? // passes

class ChildImpl extends Target with Child // concrete implementation is needed

0 comments on commit 9a5c41a

Please sign in to comment.