-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Rewrite resolveThis in global init checker #23282
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
Conversation
798fd49 to
1e0eb9f
Compare
|
|
||
| case class ScopeSet(scopes: Set[Scope]): | ||
| assert(scopes.forall(_.isRef) || scopes.forall(_.isEnv), "All scopes should have the same type!") | ||
| def isRefSet = scopes.forall(_.isRef) |
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.
Should we keep an assertion that isRefSet || isEnvSet?
| case _ => | ||
| report.warning("[Internal error] unexpected thisV = " + thisV + ", target = " + target.show + Trace.show, Trace.position) | ||
| Bottom | ||
| if resolveResult == Bottom && thisV.filterClass(target) == thisV then |
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.
Is it possible that target could be a parent class of an outer class?
|
Here's an example of a class A {
var x = 42
def change = (x = 44)
class B {
val i = 5
def fooz = A.this.x // if this is an instance of class C, does A.this resolve to the C outer or to the B outer ???
def fooz2 = A.this.x
class D {
def bar = fooz
def bar2 = fooz2
}
}
}
class AA extends A {
def foo = {
//val y = 43
val a = if(*) new A else new AAA
class C /*outer AA*/ extends a.B /*outer A or AAA*/ {
override val i = 6
override def fooz2 = x
}
val bb: B = if(false) new a.B else new C
val d = new bb.D
d.bar // reads AA.x
d.bar2 // reads AA.x
}
}
d --outer-> {B or C} --outer-> {A or foo} --outer --> {A} |
1e0eb9f to
8b89ae9
Compare
|
@olhotak @liufengyun I have added two rather complex tests, feel free to run them with scala-cli.
|
|
The second test |
It's not clear why The following comment might help: scala3/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala Lines 1207 to 1216 in 0be2091
|
8b89ae9 to
f2f9df3
Compare
|
[test_scala2_library_tasty] |
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.
LGTM, I only have a few minor comments for consideration.
| * valsMap = sym -> val // maps variables to their values | ||
| * outersMap = sym -> ScopeSet // maps the possible outer scopes for a corresponding (parent) class | ||
| * heap.MutableData = Scope -> (valsMap, outersMap) // heap is mutable | ||
| * Config ::= (thisV: Value, scope: Scope, Heap, EnvMap) |
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.
Is it possible for scope in Config to be Ref? The same question for Fun.
These are the only place where the type Scope appears. If we can remove one concept, that would be nice (Occam's razor).
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.
Minor: regarding the name LocalEnv, maybe we can use something like EnvAddr or EnvRef?
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.
Is it possible for
scopeinConfigto beRef? The same question forFun.These are the only place where the type
Scopeappears. If we can remove one concept, that would be nice (Occam's razor).
When evaluating the field initializers, the scope in Config would be Ref; the same holds when creating a Fun in a field initializer
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.
Minor: regarding the name
LocalEnv, maybe we can use something likeEnvAddrorEnvRef?
Has renamed it to EnvRef
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.
When evaluating the field initializers, the scope in Config would be Ref; the same holds when creating a Fun in a field initializer
Thanks for explaining. In later PRs, we can consider creating an empty Env with the primary constructor for evaluating field initializers if that works.
| def initVar(field: Symbol, value: Value)(using Context, EnvMap.EnvMapMutableData) = log("Initialize " + field.show + " = " + value + " for " + this, printer) { | ||
| assert(field.is(Flags.Mutable), "Field is not mutable: " + field.show) | ||
| EnvMap.writeJoinVal(this, field, value) | ||
| } |
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.
Minor (for future): Given that Var and Val have same logic, we can consider generalize a little the code.
f2f9df3 to
b1d5eae
Compare
|
Does anyone know why Test CLI Launchers failed? Should I push again? |
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.
LGTM now. @EnzeXing we can merge when you think you're done with @liufengyun 's minor comments.
It timed out. I restarted the job. |
b1d5eae to
414bd24
Compare
|
I've addressed Fengyun's comments, and I think it's ready to be merged |
This PR resolves bugs in the redesigned global initialization checker; specifically, it now correctly resolves the value of
parent.thisin a child class, and removes the assertions that fail in community build projects[test_scala2_library_tasty]