@@ -287,11 +287,22 @@ 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
+ // 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)
291
295
292
296
def show (using Context ) = scopes.map(_.show).mkString(" [" , " ," , " ]" )
293
297
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))
295
306
296
307
def lookupSymbol (sym : Symbol )(using Heap .MutableData ) = scopes.map(_.valValue(sym)).join
297
308
@@ -728,6 +739,11 @@ class Objects(using Context @constructorOnly):
728
739
case fun : Fun =>
729
740
if klass.isOneOf(AbstractOrTrait ) && klass.baseClasses.exists(defn.isFunctionClass) then fun else Bottom
730
741
742
+ extension (thisV : ThisValue )
743
+ def toValueSet : ValueSet = thisV match
744
+ case ref : Ref => ValueSet (Set (ref))
745
+ case vs : ValueSet => vs
746
+
731
747
given Join [ScopeSet ] with
732
748
extension (a : ScopeSet )
733
749
def join (b : ScopeSet ): ScopeSet = ScopeSet (a.scopes ++ b.scopes)
@@ -870,6 +886,7 @@ class Objects(using Context @constructorOnly):
870
886
val cls = target.owner.enclosingClass.asClass
871
887
val ddef = target.defTree.asInstanceOf [DefDef ]
872
888
val meth = ddef.symbol
889
+ // println("Before resolving environment, cls = " + cls + ", meth = " + meth)
873
890
val (thisV : ThisValue , outerEnv) =
874
891
if meth.owner.enclosingMethod == cls.primaryConstructor then
875
892
// meth is top-level method, outer is a ref
@@ -1377,7 +1394,7 @@ class Objects(using Context @constructorOnly):
1377
1394
case OuterSelectName (_, _) =>
1378
1395
val current = qualifier.tpe.classSymbol
1379
1396
val target = expr.tpe.widenSingleton.classSymbol.asClass
1380
- withTrace(trace2) { resolveThis(target, qual) }
1397
+ withTrace(trace2) { resolveThis(target, qual. asInstanceOf [ ThisValue ] ) }
1381
1398
case _ =>
1382
1399
withTrace(trace2) { select(qual, expr.symbol, receiver = qualifier.tpe) }
1383
1400
@@ -1927,19 +1944,15 @@ class Objects(using Context @constructorOnly):
1927
1944
* @param scopeSet The scopes as the starting point.
1928
1945
*/
1929
1946
def resolveThisRecur (target : ClassSymbol , scopeSet : ScopeSet ): Contextual [ValueSet ] =
1947
+ // println("scopeSet = " + scopeSet)
1930
1948
if scopeSet == Env .NoEnv then
1931
1949
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 ]
1932
1954
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)
1943
1956
1944
1957
/** Resolve C.this that appear in `D.this`
1945
1958
*
@@ -1950,7 +1963,7 @@ class Objects(using Context @constructorOnly):
1950
1963
* Object access elision happens when the object access is used as a prefix
1951
1964
* in `new o.C` and `C` does not need an outer.
1952
1965
*/
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) {
1954
1967
if target.is(Flags .Package ) then
1955
1968
val error = " [Internal error] target cannot be packages, target = " + target + Trace .show
1956
1969
report.warning(error, Trace .position)
@@ -1960,7 +1973,7 @@ class Objects(using Context @constructorOnly):
1960
1973
if elideObjectAccess then ValueSet (Set (res))
1961
1974
else ValueSet (Set (accessObject(target)))
1962
1975
else
1963
- thisV match
1976
+ val resolveResult = thisV match
1964
1977
case Bottom => Bottom
1965
1978
case ref : Ref =>
1966
1979
resolveThisRecur(target, ScopeSet (Set (ref)))
@@ -1969,6 +1982,11 @@ class Objects(using Context @constructorOnly):
1969
1982
case _ =>
1970
1983
report.warning(" [Internal error] unexpected thisV = " + thisV + " , target = " + target.show + Trace .show, Trace .position)
1971
1984
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
1972
1990
}
1973
1991
1974
1992
/** Compute the outer value that corresponds to `tref.prefix`
0 commit comments