@@ -287,11 +287,19 @@ class Objects(using Context @constructorOnly):
287
287
def toScopeSet : ScopeSet = ScopeSet (values.asInstanceOf [Set [Scope ]])
288
288
289
289
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)
291
293
292
294
def show (using Context ) = scopes.map(_.show).mkString(" [" , " ," , " ]" )
293
295
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))
295
303
296
304
def lookupSymbol (sym : Symbol )(using Heap .MutableData ) = scopes.map(_.valValue(sym)).join
297
305
@@ -728,6 +736,11 @@ class Objects(using Context @constructorOnly):
728
736
case fun : Fun =>
729
737
if klass.isOneOf(AbstractOrTrait ) && klass.baseClasses.exists(defn.isFunctionClass) then fun else Bottom
730
738
739
+ extension (thisV : ThisValue )
740
+ def toValueSet : ValueSet = thisV match
741
+ case ref : Ref => ValueSet (Set (ref))
742
+ case vs : ValueSet => vs
743
+
731
744
given Join [ScopeSet ] with
732
745
extension (a : ScopeSet )
733
746
def join (b : ScopeSet ): ScopeSet = ScopeSet (a.scopes ++ b.scopes)
@@ -1377,7 +1390,7 @@ class Objects(using Context @constructorOnly):
1377
1390
case OuterSelectName (_, _) =>
1378
1391
val current = qualifier.tpe.classSymbol
1379
1392
val target = expr.tpe.widenSingleton.classSymbol.asClass
1380
- withTrace(trace2) { resolveThis(target, qual) }
1393
+ withTrace(trace2) { resolveThis(target, qual. asInstanceOf [ ThisValue ] ) }
1381
1394
case _ =>
1382
1395
withTrace(trace2) { select(qual, expr.symbol, receiver = qualifier.tpe) }
1383
1396
@@ -1929,17 +1942,12 @@ class Objects(using Context @constructorOnly):
1929
1942
def resolveThisRecur (target : ClassSymbol , scopeSet : ScopeSet ): Contextual [ValueSet ] =
1930
1943
if scopeSet == Env .NoEnv then
1931
1944
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 ]
1932
1949
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)
1943
1951
1944
1952
/** Resolve C.this that appear in `D.this`
1945
1953
*
@@ -1950,7 +1958,7 @@ class Objects(using Context @constructorOnly):
1950
1958
* Object access elision happens when the object access is used as a prefix
1951
1959
* in `new o.C` and `C` does not need an outer.
1952
1960
*/
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) {
1954
1962
if target.is(Flags .Package ) then
1955
1963
val error = " [Internal error] target cannot be packages, target = " + target + Trace .show
1956
1964
report.warning(error, Trace .position)
@@ -1960,7 +1968,7 @@ class Objects(using Context @constructorOnly):
1960
1968
if elideObjectAccess then ValueSet (Set (res))
1961
1969
else ValueSet (Set (accessObject(target)))
1962
1970
else
1963
- thisV match
1971
+ val resolveResult = thisV match
1964
1972
case Bottom => Bottom
1965
1973
case ref : Ref =>
1966
1974
resolveThisRecur(target, ScopeSet (Set (ref)))
@@ -1969,6 +1977,11 @@ class Objects(using Context @constructorOnly):
1969
1977
case _ =>
1970
1978
report.warning(" [Internal error] unexpected thisV = " + thisV + " , target = " + target.show + Trace .show, Trace .position)
1971
1979
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
1972
1985
}
1973
1986
1974
1987
/** Compute the outer value that corresponds to `tref.prefix`
0 commit comments