@@ -287,11 +287,22 @@ class Objects(using Context @constructorOnly):
287287 def toScopeSet : ScopeSet = ScopeSet (values.asInstanceOf [Set [Scope ]])
288288
289289 case class ScopeSet (scopes : Set [Scope ]):
290- assert(scopes.forall(_.isRef) || scopes.forall(_.isEnv), " All scopes should have the same type!" )
290+ // assert(scopes.forall(_.isRef) || scopes.forall(_.isEnv), "All scopes should have the same type!")
291+
292+ def isRefSet = scopes.forall(_.isRef)
293+
294+ def isEnvSet = scopes.forall(_.isEnv)
291295
292296 def show (using Context ) = scopes.map(_.show).mkString(" [" , " ," , " ]" )
293297
294- def toValueSet : ValueSet = ValueSet (scopes.asInstanceOf [Set [ValueElement ]])
298+ def toValueSet : ValueSet =
299+ assert(isRefSet, " Cannot convert scopeSet " + this .show + " to ValueSet!" )
300+ ValueSet (scopes.asInstanceOf [Set [ValueElement ]])
301+
302+ def partitionByClass (target : ClassSymbol ): (ScopeSet , ScopeSet ) =
303+ // assert(isRefSet, "Invalid partition on scopeSet " + this.show)
304+ val (matchSet, unmatchSet) = scopes.partition(s => s.isRef && s.asRef.klass == target)
305+ (ScopeSet (matchSet), ScopeSet (unmatchSet))
295306
296307 def lookupSymbol (sym : Symbol )(using Heap .MutableData ) = scopes.map(_.valValue(sym)).join
297308
@@ -728,6 +739,11 @@ class Objects(using Context @constructorOnly):
728739 case fun : Fun =>
729740 if klass.isOneOf(AbstractOrTrait ) && klass.baseClasses.exists(defn.isFunctionClass) then fun else Bottom
730741
742+ extension (thisV : ThisValue )
743+ def toValueSet : ValueSet = thisV match
744+ case ref : Ref => ValueSet (Set (ref))
745+ case vs : ValueSet => vs
746+
731747 given Join [ScopeSet ] with
732748 extension (a : ScopeSet )
733749 def join (b : ScopeSet ): ScopeSet = ScopeSet (a.scopes ++ b.scopes)
@@ -870,6 +886,7 @@ class Objects(using Context @constructorOnly):
870886 val cls = target.owner.enclosingClass.asClass
871887 val ddef = target.defTree.asInstanceOf [DefDef ]
872888 val meth = ddef.symbol
889+ // println("Before resolving environment, cls = " + cls + ", meth = " + meth)
873890 val (thisV : ThisValue , outerEnv) =
874891 if meth.owner.enclosingMethod == cls.primaryConstructor then
875892 // meth is top-level method, outer is a ref
@@ -1377,7 +1394,7 @@ class Objects(using Context @constructorOnly):
13771394 case OuterSelectName (_, _) =>
13781395 val current = qualifier.tpe.classSymbol
13791396 val target = expr.tpe.widenSingleton.classSymbol.asClass
1380- withTrace(trace2) { resolveThis(target, qual) }
1397+ withTrace(trace2) { resolveThis(target, qual. asInstanceOf [ ThisValue ] ) }
13811398 case _ =>
13821399 withTrace(trace2) { select(qual, expr.symbol, receiver = qualifier.tpe) }
13831400
@@ -1927,19 +1944,15 @@ class Objects(using Context @constructorOnly):
19271944 * @param scopeSet The scopes as the starting point.
19281945 */
19291946 def resolveThisRecur (target : ClassSymbol , scopeSet : ScopeSet ): Contextual [ValueSet ] =
1947+ // println("scopeSet = " + scopeSet)
19301948 if scopeSet == Env .NoEnv then
19311949 Bottom
1950+ else if scopeSet.isRefSet then
1951+ val (matchSet, unmatchSet) = scopeSet.partitionByClass(target)
1952+ val resolveUnmatchSet = resolveThisRecur(target, unmatchSet.outers)
1953+ matchSet.toValueSet.join(resolveUnmatchSet).asInstanceOf [ValueSet ]
19321954 else
1933- val head = scopeSet.scopes.head
1934- if head.isInstanceOf [Ref ] then
1935- val klass = head.asInstanceOf [Ref ].klass
1936- assert(scopeSet.scopes.forall(_.asInstanceOf [Ref ].klass == klass), " Multiple possible outer class?" )
1937- if klass == target then
1938- scopeSet.toValueSet
1939- else
1940- resolveThisRecur(target, scopeSet.outers)
1941- else
1942- resolveThisRecur(target, scopeSet.outers)
1955+ resolveThisRecur(target, scopeSet.outers)
19431956
19441957 /** Resolve C.this that appear in `D.this`
19451958 *
@@ -1950,7 +1963,7 @@ class Objects(using Context @constructorOnly):
19501963 * Object access elision happens when the object access is used as a prefix
19511964 * in `new o.C` and `C` does not need an outer.
19521965 */
1953- def resolveThis (target : ClassSymbol , thisV : Value , elideObjectAccess : Boolean = false ): Contextual [ValueSet ] = log(" resolveThis target = " + target.show + " , this = " + thisV.show, printer, (_ : Value ).show) {
1966+ def resolveThis (target : ClassSymbol , thisV : ThisValue , elideObjectAccess : Boolean = false ): Contextual [ValueSet ] = log(" resolveThis target = " + target.show + " , this = " + thisV.show, printer, (_ : Value ).show) {
19541967 if target.is(Flags .Package ) then
19551968 val error = " [Internal error] target cannot be packages, target = " + target + Trace .show
19561969 report.warning(error, Trace .position)
@@ -1960,7 +1973,7 @@ class Objects(using Context @constructorOnly):
19601973 if elideObjectAccess then ValueSet (Set (res))
19611974 else ValueSet (Set (accessObject(target)))
19621975 else
1963- thisV match
1976+ val resolveResult = thisV match
19641977 case Bottom => Bottom
19651978 case ref : Ref =>
19661979 resolveThisRecur(target, ScopeSet (Set (ref)))
@@ -1969,6 +1982,11 @@ class Objects(using Context @constructorOnly):
19691982 case _ =>
19701983 report.warning(" [Internal error] unexpected thisV = " + thisV + " , target = " + target.show + Trace .show, Trace .position)
19711984 Bottom
1985+ if resolveResult == Bottom && thisV.filterClass(target) == thisV then
1986+ // `target` is not an outer class, but a parent class
1987+ thisV.toValueSet
1988+ else
1989+ resolveResult
19721990 }
19731991
19741992 /** Compute the outer value that corresponds to `tref.prefix`
0 commit comments