-
Notifications
You must be signed in to change notification settings - Fork 111
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
[WIP] Fix struct/const revision #894
base: master
Are you sure you want to change the base?
Conversation
I think that's a valid way to say it, but just to clarify, nothing about the type object itself changes, just the name by which you have to access it
yes
I don't understand what you're asking
It lists all cross-module edges to get everything, you also need to iterate all methods in the same module as the binding.
In the fullness of time, the correct way to implement Revise is to run the toplevel expressions in a non-standard evaluation mode that tracks dependency edges for any evaluated constants. However, that should maybe wait until after the JuliaLowering changes and the interpreter rewrite. I think your proposed strategy is reasonable in the meantime although not fully complete. |
e1a5084
to
3f878e3
Compare
I was wondering whether some kind of callback in there could be helpful in short-circuiting the process of determining which methoddefs need to be re-evaluated, but if it's not called then that won't help. From what I can tell, that's not going to work anyway because it only traverses the module containing the type definition. But your comment
seems to be what I was looking for. This seems fairly straightforward, thanks for the excellent groundwork. |
No, there's no edges of any kind for signatures. You need to scan the entire system. However, an earlier version of that code did the same whole-system scan, so you can steal some code for whole-system scanning. |
I added a cross-module test (the julia> b = convert(Core.Binding, GlobalRef(StructConst, :Point))
Binding StructConst.Point
40743:∞ - constant binding to StructConst.Point
40598:40742 - constant binding to @world(StructConst.Point, 40598:40742)
1:0 - backdated constant binding to @world(StructConst.Point, 40598:40742)
1:0 - backdated constant binding to @world(StructConst.Point, 40598:40742)
julia> b.backedges
ERROR: UndefRefError: access to undefined reference
Stacktrace:
[1] getproperty(x::Core.Binding, f::Symbol)
@ Base ./Base_compiler.jl:55
[2] top-level scope
@ REPL[6]:1 so I don't think I understand what
really means. It also doesn't populate if I add struct PointWrapper
p::StructConst.Point
end to that module. I understand that I have to traverse the whole system, I'm just curious about what |
There's two kinds of edges that are tracked there. One is explicit import/using. The other is to lowered code of method definitions (but only after the first inference). At no point is an edge ever added for an evaluation of a binding, only for compilation of code that references the binding. |
Just to cross-check:
yields a backedge for the julia> e = only(b.backedges)
Binding StructConstUser.Point
40598:∞ - explicit `using` from StructConst.Point
1:0 - undefined binding - guard entry |
The aim here is to provide full support for struct/const revision. This first commit just adds simple tests, but it already reveals something that needs to be addressed: when a
struct
gets revised, methods defined for thatstruct
aren't automatically re-evaluated for the new type. Specifically, in the added tests, after revising the definition ofPoint
we getand there is no defined method for a currently-valid
StructConst.Point
.@Keno, if you have a moment, let me check my understanding of the current situation:
invalidate_code_for_globalref!
is not called?)binding.backedges
to list everything that uses this bindingPresumably, waiting to do the last step as the last stage of a revision would be wise, as it is possible that more than one struct will be revised at the same time, and one might as well do each evaluation only once.