Skip to content

Commit 16d9513

Browse files
authored
Update description of limitations (#996)
Closes #986
1 parent e9a591b commit 16d9513

File tree

2 files changed

+71
-37
lines changed

2 files changed

+71
-37
lines changed

docs/src/internals.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ end
162162
sizefloat(x::Float64) = 8
163163
```
164164

165-
If you replace the loop with `for T in (Float32, Float64)`, then Revise should delete the method for `Float16`. But this implies that Revise can deduce all the method-signatures created by this block, which essentially requires "simulating" the block that defines the methods. (In simple cases there are other approaches, but for [complex cases](https://github.com/JuliaLang/julia/blob/c7e4b9929b3b6ee89d47ce1320ef2de14c4ecf85/base/atomics.jl#L415-L430) stepping through the code seems to be the only viable answer.)
165+
If you replace the loop with `for T in (Float32, Float64)`, then Revise should delete the method for `Float16`. But this implies that Revise can deduce all the method-signatures created by this block, which essentially requires "simulating" the block that defines the methods. (In simple cases there are other approaches, but for complex cases stepping through the code seems to be the only viable answer.)
166166

167167
Because lowered code is far simpler than ordinary Julia code, it is much easier to interpret. Let's look briefly at a method definition:
168168

docs/src/limitations.md

Lines changed: 70 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
# Limitations
22

3-
There are some kinds of changes that Revise (or often, Julia itself) cannot automatically incorporate into a running Julia session:
3+
## Struct revision
44

5-
- changes to global bindings (but see below for struct definitions on Julia 1.12+)
6-
- conflicts between variables and functions sharing the same name
7-
- removal of `export`s
8-
9-
These kinds of changes require that you restart your Julia session.
10-
11-
## Struct revision (Julia 1.12+)
5+
### Struct revision is supported on Julia 1.12+
126

137
Starting with Julia 1.12, Revise can handle changes to struct definitions. When you modify
148
a struct, Revise will automatically re-evaluate the struct definition and any methods or
15-
types that depend on it.
16-
17-
For example, this now works:
9+
types that depend on it. For example:
1810

1911
```julia
2012
struct Inner
@@ -40,32 +32,10 @@ end
4032
Revise will redefine `Inner`, and also re-evaluate `Outer` (which uses `Inner`
4133
as a field type) and `print_value` (which references `Outer` in its signature).
4234

43-
## Binding revision is not yet supported
44-
45-
While struct revision is supported, more general "binding revision" is not yet implemented.
46-
Specifically, Revise does not track implicit dependencies between top-level bindings.
35+
On versions of Julia older than 1.12, Revise does not support changes to
36+
`struct` definitions. These require you to restart your session.
4737

48-
For example:
49-
50-
```julia
51-
MyVecType{T} = Vector{T} # changing this to AbstractVector{T} won't update A
52-
struct MyVec{T}
53-
v::MyVecType{T}
54-
end
55-
```
56-
57-
If you change `MyVecType{T}` from `Vector{T}` to `AbstractVector{T}`, the struct `A` will
58-
**not** be automatically re-evaluated because Revise does not track the dependency edge
59-
from `MyVecType` to `MyVec`. The same applies to `const` bindings and other global bindings
60-
that are referenced in type definitions.
61-
62-
Supporting this would require tracking implicit binding edges across all top-level code,
63-
which involves significant interpreter enhancements and is deferred to future work.
64-
This limitation also underlies [the issues with macros and generated functions](@ref other-limitations/macros-and-generated-functions) described below.
65-
66-
As a workaround, you can manually call [`revise`](@ref) to force re-evaluation of all definitions in `MyModule`, which will pick up the new bindings.
67-
68-
## Workaround for the struct revision issue before Julia 1.12
38+
### Workaround for the struct revision issue before Julia 1.12
6939

7040
On Julia versions prior to 1.12, struct definitions cannot be revised. During early stages of development,
7141
it's quite common to want to change type definitions.
@@ -182,6 +152,32 @@ julia> isconst(MyPkg, :FooStruct)
182152
true
183153
```
184154

155+
### Toplevel binding changes do not propagate
156+
157+
While struct revision is supported, some forms of "binding revision" do not work.
158+
Specifically, Revise does not track implicit dependencies between top-level bindings.
159+
160+
For example:
161+
162+
```julia
163+
MyVecType{T} = Vector{T} # changing this to AbstractVector{T} won't update A
164+
struct MyVec{T}
165+
v::MyVecType{T}
166+
end
167+
```
168+
169+
If you change `MyVecType{T}` from `Vector{T}` to `AbstractVector{T}`, the struct `A` will
170+
**not** be automatically re-evaluated because Revise does not track the dependency edge
171+
from `MyVecType` to `MyVec`. The same applies to `const` bindings and other global bindings
172+
that are referenced in type definitions.
173+
174+
Supporting this would require tracking implicit binding edges across all
175+
top-level code, which involves significant interpreter enhancements and may
176+
never happen. See the related case of [code that depends on data](@ref data)
177+
below.
178+
179+
As a workaround, you can manually call [`revise`](@ref) to force re-evaluation of all definitions in `MyModule`, which will pick up the new bindings.
180+
185181
## Other limitations
186182

187183
In addition, some situations may require special handling:
@@ -196,6 +192,39 @@ You may explicitly call `revise(MyModule)` to force reevaluating every definitio
196192
`MyModule`.
197193
Note that when a macro changes, you have to revise all of the modules that *use* it.
198194

195+
### [Code that depends on data](@id data)
196+
197+
Revise does not track dependencies on "data." For example, if your source code
198+
looks like
199+
200+
```julia
201+
tf = true
202+
if tf
203+
f() = 1
204+
else
205+
f() = 2
206+
end
207+
```
208+
209+
and you change `tf` to `false`, Revise will not update the definition of `f`.
210+
This is because there is no record of the fact that `f` depends on the value of `tf`.
211+
212+
This limitation does not affect code like this:
213+
214+
```julia
215+
if true
216+
f() = 1
217+
else
218+
f() = 2
219+
end
220+
```
221+
222+
In this case, changing `true` to `false` will redefine `f`, but only because
223+
it's part of the same expression and Revise will re-evaluate the expression.
224+
225+
The maintainers have no intention of ever "fixing" this limitation, as it would
226+
require adding enormous bloat to every session for very little actual benefit.
227+
199228
### Distributed computing (multiple workers) and anonymous functions
200229

201230
Revise supports changes to code in worker processes.
@@ -237,3 +266,8 @@ end # module
237266

238267
and the corresponding edit to the code would be to modify it to `greetcaller(x) = greet("Bar")`
239268
and `remotecall_fetch(greetcaller, p, 1)`.
269+
270+
### `include(mapexpr, filename)` is not supported
271+
272+
Julia supports the ability to modify source code after parsing and before evaluation.
273+
Supporting this is a TODO item but is not yet implemented.

0 commit comments

Comments
 (0)