@@ -287,11 +287,19 @@ 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+ def isRefSet = scopes.forall(_.isRef)
291+
292+ def isEnvSet = scopes.forall(_.isEnv)
291293
292294 def show (using Context ) = scopes.map(_.show).mkString(" [" , " ," , " ]" )
293295
294- def toValueSet : ValueSet = ValueSet (scopes.asInstanceOf [Set [ValueElement ]])
296+ def toValueSet : ValueSet =
297+ assert(isRefSet, " Cannot convert scopeSet " + this .show + " to ValueSet!" )
298+ ValueSet (scopes.asInstanceOf [Set [ValueElement ]])
299+
300+ def partitionByClass (target : ClassSymbol ): (ScopeSet , ScopeSet ) =
301+ val (matchSet, unmatchSet) = scopes.partition(s => s.isRef && s.asRef.klass == target)
302+ (ScopeSet (matchSet), ScopeSet (unmatchSet))
295303
296304 def lookupSymbol (sym : Symbol )(using Heap .MutableData ) = scopes.map(_.valValue(sym)).join
297305
@@ -728,6 +736,11 @@ class Objects(using Context @constructorOnly):
728736 case fun : Fun =>
729737 if klass.isOneOf(AbstractOrTrait ) && klass.baseClasses.exists(defn.isFunctionClass) then fun else Bottom
730738
739+ extension (thisV : ThisValue )
740+ def toValueSet : ValueSet = thisV match
741+ case ref : Ref => ValueSet (Set (ref))
742+ case vs : ValueSet => vs
743+
731744 given Join [ScopeSet ] with
732745 extension (a : ScopeSet )
733746 def join (b : ScopeSet ): ScopeSet = ScopeSet (a.scopes ++ b.scopes)
@@ -1377,7 +1390,7 @@ class Objects(using Context @constructorOnly):
13771390 case OuterSelectName (_, _) =>
13781391 val current = qualifier.tpe.classSymbol
13791392 val target = expr.tpe.widenSingleton.classSymbol.asClass
1380- withTrace(trace2) { resolveThis(target, qual) }
1393+ withTrace(trace2) { resolveThis(target, qual. asInstanceOf [ ThisValue ] ) }
13811394 case _ =>
13821395 withTrace(trace2) { select(qual, expr.symbol, receiver = qualifier.tpe) }
13831396
@@ -1929,17 +1942,12 @@ class Objects(using Context @constructorOnly):
19291942 def resolveThisRecur (target : ClassSymbol , scopeSet : ScopeSet ): Contextual [ValueSet ] =
19301943 if scopeSet == Env .NoEnv then
19311944 Bottom
1945+ else if scopeSet.isRefSet then
1946+ val (matchSet, unmatchSet) = scopeSet.partitionByClass(target)
1947+ val resolveUnmatchSet = resolveThisRecur(target, unmatchSet.outers)
1948+ matchSet.toValueSet.join(resolveUnmatchSet).asInstanceOf [ValueSet ]
19321949 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)
1950+ resolveThisRecur(target, scopeSet.outers)
19431951
19441952 /** Resolve C.this that appear in `D.this`
19451953 *
@@ -1950,7 +1958,7 @@ class Objects(using Context @constructorOnly):
19501958 * Object access elision happens when the object access is used as a prefix
19511959 * in `new o.C` and `C` does not need an outer.
19521960 */
1953- def resolveThis (target : ClassSymbol , thisV : Value , elideObjectAccess : Boolean = false ): Contextual [ValueSet ] = log(" resolveThis target = " + target.show + " , this = " + thisV.show, printer, (_ : Value ).show) {
1961+ def resolveThis (target : ClassSymbol , thisV : ThisValue , elideObjectAccess : Boolean = false ): Contextual [ValueSet ] = log(" resolveThis target = " + target.show + " , this = " + thisV.show, printer, (_ : Value ).show) {
19541962 if target.is(Flags .Package ) then
19551963 val error = " [Internal error] target cannot be packages, target = " + target + Trace .show
19561964 report.warning(error, Trace .position)
@@ -1960,7 +1968,7 @@ class Objects(using Context @constructorOnly):
19601968 if elideObjectAccess then ValueSet (Set (res))
19611969 else ValueSet (Set (accessObject(target)))
19621970 else
1963- thisV match
1971+ val resolveResult = thisV match
19641972 case Bottom => Bottom
19651973 case ref : Ref =>
19661974 resolveThisRecur(target, ScopeSet (Set (ref)))
@@ -1969,6 +1977,11 @@ class Objects(using Context @constructorOnly):
19691977 case _ =>
19701978 report.warning(" [Internal error] unexpected thisV = " + thisV + " , target = " + target.show + Trace .show, Trace .position)
19711979 Bottom
1980+ if resolveResult == Bottom && thisV.filterClass(target) == thisV then
1981+ // `target` is not an outer class, but a parent class
1982+ thisV.toValueSet
1983+ else
1984+ resolveResult
19721985 }
19731986
19741987 /** Compute the outer value that corresponds to `tref.prefix`
0 commit comments