-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add supports for type cast and filtering type for field and method owner in global initialization checker #19612
Changes from 2 commits
16ecedd
f091c4e
124f68b
113002b
8412f78
0a95653
36392fa
229062c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -599,6 +599,22 @@ object Objects: | |
|
||
case _ => a | ||
|
||
def filterType(tpe: Type)(using Context): Value = | ||
val baseClasses = tpe.baseClasses | ||
if baseClasses.isEmpty then a | ||
else filterClass(baseClasses.head) | ||
|
||
def filterClass(sym: Symbol)(using Context): Value = | ||
if !sym.isClass then a | ||
else | ||
val klass = sym.asClass | ||
a match | ||
case Cold => Cold | ||
case ref: Ref if ref.klass.isSubClass(klass) => ref | ||
case ref: Ref => Bottom | ||
case ValueSet(values) => values.map(v => v.filterClass(klass)).join | ||
case _ => a // TODO: could be more precise for OfArray; possibly add class information for Fun | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As discussed in the meeting, we can further filter |
||
|
||
extension (value: Ref | Cold.type) | ||
def widenRefOrCold(height : Int)(using Context) : Ref | Cold.type = value.widen(height).asInstanceOf[ThisValue] | ||
|
||
|
@@ -617,7 +633,7 @@ object Objects: | |
* @param needResolve Whether the target of the call needs resolution? | ||
*/ | ||
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) { | ||
value match | ||
value.filterClass(meth.owner) match | ||
case Cold => | ||
report.warning("Using cold alias. " + Trace.show, Trace.position) | ||
Bottom | ||
|
@@ -733,7 +749,6 @@ object Objects: | |
* @param args Arguments of the constructor call (all parameter blocks flatten to a list). | ||
*/ | ||
def callConstructor(value: Value, ctor: Symbol, args: List[ArgInfo]): Contextual[Value] = log("call " + ctor.show + ", args = " + args.map(_.value.show), printer, (_: Value).show) { | ||
|
||
value match | ||
case ref: Ref => | ||
if ctor.hasSource then | ||
|
@@ -768,7 +783,7 @@ object Objects: | |
* @param needResolve Whether the target of the selection needs resolution? | ||
*/ | ||
def select(value: Value, field: Symbol, receiver: Type, needResolve: Boolean = true): Contextual[Value] = log("select " + field.show + ", this = " + value.show, printer, (_: Value).show) { | ||
value match | ||
value.filterClass(field.owner) match | ||
case Cold => | ||
report.warning("Using cold alias", Trace.position) | ||
Bottom | ||
|
@@ -839,7 +854,7 @@ object Objects: | |
* @param rhsTyp The type of the right-hand side. | ||
*/ | ||
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) { | ||
lhs match | ||
lhs.filterClass(field.owner) match | ||
case fun: Fun => | ||
report.warning("[Internal error] unexpected tree in assignment, fun = " + fun.code.show + Trace.show, Trace.position) | ||
|
||
|
@@ -876,8 +891,7 @@ object Objects: | |
* @param args The arguments passsed to the constructor. | ||
*/ | ||
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) { | ||
outer match | ||
|
||
outer.filterClass(klass.owner) match | ||
case _ : Fun | _: OfArray => | ||
report.warning("[Internal error] unexpected outer in instantiating a class, outer = " + outer.show + ", class = " + klass.show + ", " + Trace.show, Trace.position) | ||
Bottom | ||
|
@@ -1091,6 +1105,9 @@ object Objects: | |
instantiate(outer, cls, ctor, args) | ||
} | ||
|
||
case TypeCast(elem, tpe) => | ||
eval(elem, thisV, klass).filterType(tpe) | ||
|
||
case Apply(ref, arg :: Nil) if ref.symbol == defn.InitRegionMethod => | ||
val regions2 = Regions.extend(expr.sourcePos) | ||
if Regions.exists(expr.sourcePos) then | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,6 +78,13 @@ object Util: | |
case _ => | ||
None | ||
|
||
object TypeCast: | ||
def unapply(tree: Tree)(using Context): Option[(Tree, Type)] = | ||
tree match | ||
case TypeApply(Select(qual, _), typeArg) if tree.symbol.isTypeCast => | ||
Some(qual, typeArg.head.tpe) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: It's better to change |
||
case _ => None | ||
|
||
def resolve(cls: ClassSymbol, sym: Symbol)(using Context): Symbol = log("resove " + cls + ", " + sym, printer, (_: Symbol).show): | ||
if sym.isEffectivelyFinal then sym | ||
else sym.matchingMember(cls.appliedRef) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
object A { | ||
val f: Int = 10 | ||
def m() = f | ||
} | ||
object B { | ||
val f: Int = g() | ||
def g(): Int = f // error | ||
} | ||
object C { | ||
val a: A.type | B.type = if ??? then A else B | ||
def cast[T](a: Any): T = a.asInstanceOf[T] | ||
val c: A.type = cast[A.type](a) // abstraction for c is {A, B} | ||
val d = c.f // treat as c.asInstanceOf[owner of f].f | ||
val e = c.m() // treat as c.asInstanceOf[owner of f].m() | ||
val c2: B.type = cast[B.type](a) | ||
val g = c2.f // no error here | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class A: | ||
var a = 20 | ||
|
||
class B: | ||
var b = 20 | ||
|
||
object O: | ||
val o: A | B = new A | ||
if o.isInstanceOf[A] then | ||
o.asInstanceOf[A].a += 1 | ||
else | ||
o.asInstanceOf[B].b += 1 // o.asInstanceOf[B] is treated as bottom | ||
o match | ||
case o: A => o.a += 1 | ||
case o: B => o.b += 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with other cases, I'd move the
if
inside the case body and combine with the following case.