@@ -27,6 +27,7 @@ import scala.collection.immutable.ListSet
2727import scala .collection .mutable
2828import scala .annotation .tailrec
2929import scala .annotation .constructorOnly
30+ import dotty .tools .dotc .core .Flags .AbstractOrTrait
3031
3132/** Check initialization safety of static objects
3233 *
@@ -203,6 +204,7 @@ object Objects:
203204
204205 /**
205206 * Represents a lambda expression
207+ * @param klass The enclosing class of the anonymous function's creation site
206208 */
207209 case class Fun (code : Tree , thisV : ThisValue , klass : ClassSymbol , env : Env .Data ) extends ValueElement :
208210 def show (using Context ) = " Fun(" + code.show + " , " + thisV.show + " , " + klass.show + " )"
@@ -599,6 +601,26 @@ object Objects:
599601
600602 case _ => a
601603
604+ def filterType (tpe : Type )(using Context ): Value =
605+ tpe match
606+ case t @ SAMType (_, _) if a.isInstanceOf [Fun ] => a // if tpe is SAMType and a is Fun, allow it
607+ case _ =>
608+ val baseClasses = tpe.baseClasses
609+ if baseClasses.isEmpty then a
610+ else filterClass(baseClasses.head) // could have called ClassSymbol, but it does not handle OrType and AndType
611+
612+ def filterClass (sym : Symbol )(using Context ): Value =
613+ if ! sym.isClass then a
614+ else
615+ val klass = sym.asClass
616+ a match
617+ case Cold => Cold
618+ case ref : Ref => if ref.klass.isSubClass(klass) then ref else Bottom
619+ case ValueSet (values) => values.map(v => v.filterClass(klass)).join
620+ case arr : OfArray => if defn.ArrayClass .isSubClass(klass) then arr else Bottom
621+ case fun : Fun =>
622+ if klass.isOneOf(AbstractOrTrait ) && klass.baseClasses.exists(defn.isFunctionClass) then fun else Bottom
623+
602624 extension (value : Ref | Cold .type )
603625 def widenRefOrCold (height : Int )(using Context ) : Ref | Cold .type = value.widen(height).asInstanceOf [ThisValue ]
604626
@@ -617,7 +639,7 @@ object Objects:
617639 * @param needResolve Whether the target of the call needs resolution?
618640 */
619641 def call (value : Value , meth : Symbol , args : List [ArgInfo ], receiver : Type , superType : Type , needResolve : Boolean = true ): Contextual [Value ] = log(" call " + meth.show + " , this = " + value.show + " , args = " + args.map(_.value.show), printer, (_ : Value ).show) {
620- value match
642+ value.filterClass(meth.owner) match
621643 case Cold =>
622644 report.warning(" Using cold alias. " + Trace .show, Trace .position)
623645 Bottom
@@ -733,7 +755,6 @@ object Objects:
733755 * @param args Arguments of the constructor call (all parameter blocks flatten to a list).
734756 */
735757 def callConstructor (value : Value , ctor : Symbol , args : List [ArgInfo ]): Contextual [Value ] = log(" call " + ctor.show + " , args = " + args.map(_.value.show), printer, (_ : Value ).show) {
736-
737758 value match
738759 case ref : Ref =>
739760 if ctor.hasSource then
@@ -768,7 +789,7 @@ object Objects:
768789 * @param needResolve Whether the target of the selection needs resolution?
769790 */
770791 def select (value : Value , field : Symbol , receiver : Type , needResolve : Boolean = true ): Contextual [Value ] = log(" select " + field.show + " , this = " + value.show, printer, (_ : Value ).show) {
771- value match
792+ value.filterClass(field.owner) match
772793 case Cold =>
773794 report.warning(" Using cold alias" , Trace .position)
774795 Bottom
@@ -839,12 +860,12 @@ object Objects:
839860 * @param rhsTyp The type of the right-hand side.
840861 */
841862 def assign (lhs : Value , field : Symbol , rhs : Value , rhsTyp : Type ): Contextual [Value ] = log(" Assign" + field.show + " of " + lhs.show + " , rhs = " + rhs.show, printer, (_ : Value ).show) {
842- lhs match
863+ lhs.filterClass(field.owner) match
843864 case fun : Fun =>
844865 report.warning(" [Internal error] unexpected tree in assignment, fun = " + fun.code.show + Trace .show, Trace .position)
845866
846867 case arr : OfArray =>
847- report.warning(" [Internal error] unexpected tree in assignment, array = " + arr.show + Trace .show, Trace .position)
868+ report.warning(" [Internal error] unexpected tree in assignment, array = " + arr.show + " field = " + field + Trace .show, Trace .position)
848869
849870 case Cold =>
850871 report.warning(" Assigning to cold aliases is forbidden. " + Trace .show, Trace .position)
@@ -876,8 +897,7 @@ object Objects:
876897 * @param args The arguments passsed to the constructor.
877898 */
878899 def instantiate (outer : Value , klass : ClassSymbol , ctor : Symbol , args : List [ArgInfo ]): Contextual [Value ] = log(" instantiating " + klass.show + " , outer = " + outer + " , args = " + args.map(_.value.show), printer, (_ : Value ).show) {
879- outer match
880-
900+ outer.filterClass(klass.owner) match
881901 case _ : Fun | _ : OfArray =>
882902 report.warning(" [Internal error] unexpected outer in instantiating a class, outer = " + outer.show + " , class = " + klass.show + " , " + Trace .show, Trace .position)
883903 Bottom
@@ -1091,6 +1111,9 @@ object Objects:
10911111 instantiate(outer, cls, ctor, args)
10921112 }
10931113
1114+ case TypeCast (elem, tpe) =>
1115+ eval(elem, thisV, klass).filterType(tpe)
1116+
10941117 case Apply (ref, arg :: Nil ) if ref.symbol == defn.InitRegionMethod =>
10951118 val regions2 = Regions .extend(expr.sourcePos)
10961119 if Regions .exists(expr.sourcePos) then
@@ -1549,7 +1572,7 @@ object Objects:
15491572 report.warning(" The argument should be a constant integer value" , arg)
15501573 res.widen(1 )
15511574 case _ =>
1552- res.widen(1 )
1575+ if res. isInstanceOf [ Fun ] then res.widen( 2 ) else res.widen(1 )
15531576
15541577 argInfos += ArgInfo (widened, trace.add(arg.tree), arg.tree)
15551578 }
0 commit comments