Revise not updating functions

I am following the example here to redefine struct (by renaming it). But the function does not get recompiled with new type. I get the following error:

julia> MyPkg.processFoo(fs)
ERROR: MethodError: no method matching processFoo(::MyPkg.FooStruct2)

Closest candidates are:
  processFoo(::MyPkg.FooStruct1)
   @ MyPkg C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl:8

Stacktrace:
 [1] top-level scope
   @ REPL[21]:1

Revise version:

(@v1.10) pkg> status Revise
Status `C:\Users\adity\.julia\environments\v1.10\Project.toml`
⌃ [295af30f] Revise v3.5.3
Info Packages marked with ⌃ have new versions available and may be upgradable.

Julia version: 1.10

Did you do using Revise first? How are you loading MyPkg?

Hi Mark, Thanks for looking into this. I first generated MyPkg by generate MyPkg. Then devd it in the global environment by dev .\MyPkg. Then starting a fresh REPL session I first did using Revise and then using MyPkg. One thing to note is that I can update the function processFoo in the same session. Even the struct is getting updated. However, the function does not get recompiled for the new type.

Works now with Revise updated to v3.5.13.

1 Like

Sorry, I thought it worked. But the issue is still there. Am I doing something wrong? I think the issue is if the function is called with FooStruct1 and then FooStruct1 is changed to FooStruct2 and then the function is called with FooStruct2 a new method does not get compiled.I am attaching the complete REPL session

julia> 
PS C:\Users\adity\Desktop\MyPkg> julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.10.0 (2023-12-25)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using Revise

julia> using MyPkg
Precompiling MyPkg
  1 dependency successfully precompiled in 3 seconds

julia> a = MyPkg.FooStruct(1)
MyPkg.FooStruct1(1)

julia> MyPkg.processFoo(a)
[ Info: 1
Hello Mitali

julia> b = MyPkg.FooStruct(1,1)
┌ Error: Failed to revise C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl
│   exception =
│    invalid redefinition of constant MyPkg.FooStruct1
│    Stacktrace:
│     [1] top-level scope
│       @ C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl:3
│    Revise evaluation error at C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl:3
│ 
└ @ Revise C:\Users\adity\.julia\packages\Revise\FaTes\src\packagedef.jl:722
┌ Warning: The running code does not match the saved version for the following files:
│ 
│   C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl
│ 
│ If the error was due to evaluation order, it can sometimes be resolved by calling `Revise.retry()`.
│ Use Revise.errors() to report errors again. Only the first error in each file is shown.
│ Your prompt color may be yellow until the errors are resolved.
└ @ Revise C:\Users\adity\.julia\packages\Revise\FaTes\src\packagedef.jl:832
ERROR: MethodError: no method matching MyPkg.FooStruct1(::Int64, ::Int64)
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1

julia> Revise.retry()

julia> b = MyPkg.FooStruct(1,1)
MyPkg.FooStruct2(1, 1)

julia> MyPkg.processFoo(b)
ERROR: MethodError: no method matching processFoo(::MyPkg.FooStruct2)

Closest candidates are:
  processFoo(::MyPkg.FooStruct1)
   @ MyPkg C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl:9

Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

julia> MyPkg.processFoo(b)
ERROR: MethodError: no method matching processFoo(::MyPkg.FooStruct2)

Closest candidates are:
  processFoo(::MyPkg.FooStruct1)
   @ MyPkg C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl:9

Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

julia> MyPkg.processFoo(b)
ERROR: MethodError: no method matching processFoo(::MyPkg.FooStruct2)

Closest candidates are:
  processFoo(::MyPkg.FooStruct1)
   @ MyPkg C:\Users\adity\Desktop\MyPkg\src\MyPkg.jl:9

Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

julia> 

Why did the FooStruct1 definition change? Leave that alone. Create a new FooStruct2 definition.

1 Like

Try this sequence.

julia> write("Foo.jl", """
       struct FooStruct1
           bar::Int
       end
       FooStruct = FooStruct1
       function processFoo(foo::FooStruct)
           @info foo.bar
       end
       """)
116

julia> using Revise; Revise.includet("Foo.jl")

julia> processFoo(FooStruct(1))
[ Info: 1

julia> write("Foo.jl", """
       struct FooStruct2
           bar::Int
           str::String
       end
       FooStruct = FooStruct2
       function processFoo(foo::FooStruct)
           @info foo.bar
       end
       """)
132

julia> FooStruct = FooStruct2
FooStruct2

julia> write("Foo.jl", """
       struct FooStruct2
           bar::Int
           str::String
       end
       FooStruct = FooStruct2
       function processFoo(foo::FooStruct2)
           @info foo.bar foo.str
       end
       """)
141

julia> processFoo(FooStruct(1, "hello"))
┌ Info: 1
└   foo.str = "hello"
2 Likes

I am following the example here to redefine struct (by renaming it). In the example on that page the same type is updated. It is helpful in the initial stages when the type is still experimental.

Yes, but at some point you changed FooStruct1 without renaming it causing Revise to fail.

Were you able to run the exact sequence of commands that I just posted successfully?

1 Like

I had to start julia in admin mode to run it. And it runs successfully. But you have changed the signature of processFoo function. In the link above it is mentioned explicitly that it need not be changed.
Can you check if your shortened example works for you (I have removed the change in function signature):

julia> write("Foo.jl", """
       struct FooStruct1
           bar::Int
       end
       FooStruct = FooStruct1
       function processFoo(foo::FooStruct)
           @info foo.bar
       end
       """)
116

julia> using Revise; Revise.includet("Foo.jl")

julia> processFoo(FooStruct(1))
[ Info: 1

julia> write("Foo.jl", """
       struct FooStruct2
           bar::Int
           str::String
       end
       FooStruct = FooStruct2
       function processFoo(foo::FooStruct)
           @info foo.bar
       end
       """)
julia> processFoo(FooStruct(1, "hello"))
ERROR: MethodError: no method matching FooStruct1(::Int64, ::String)
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1

The problem with changing the function signature is there might be many functions across multiple files which use the type FooStruct. So editing everywhere is not very convenient.
One important point is that tests are failing for Revise at my end.

I’m not sure what that is about. Perhaps you need to cd to a directory where you have write permissions? What is pwd() when you start Julia?

You need to do FooStruct = FooStruct2 in the REPL. Revise is not going to update your local variables for you via includet. Notice the error here is with FooStruct1.

I agree that something does seem to be off because I do think this should work given the instructions.

julia> write("Foo.jl","""
       struct FooStruct1
           bar::Int
       end
       FooStruct = FooStruct1
       function processFoo(foo::FooStruct)
           @info foo.bar
       end
       """)
116

julia> using Revise; Revise.includet("Foo.jl")

julia> write("Foo.jl","""
       struct FooStruct2
           bar::Int
       end
       FooStruct = FooStruct2
       function processFoo(foo::FooStruct)
           @info foo.bar
       end
       """)
116

julia> FooStruct = FooStruct2
FooStruct2

julia> write("Foo.jl","""
       struct FooStruct2
           bar::Int
       end
       FooStruct = FooStruct2
       function processFoo(foo::FooStruct)
           @info foo.bar
       end
       """)
116

julia> processFoo(FooStruct(2))
ERROR: MethodError: no method matching processFoo(::FooStruct2)

Closest candidates are:
  processFoo(::FooStruct1)
   @ Main ~/Foo.jl:5

@tim.holy Something seems off here.

1 Like

Would something like this work for you? This is closer to what I actually do.

julia> using Pkg, Revise

julia> Pkg.generate("MyPkg")
  Generating  project MyPkg:
    MyPkg/Project.toml
    MyPkg/src/MyPkg.jl
Dict{String, Base.UUID} with 1 entry:
  "MyPkg" => UUID("69940cda-0c72-4a1a-ae0b-fd3109336fe8")

julia> cd("MyPkg")

julia> write("src/MyPkg.jl","""
       module MyPkg

       export FooStruct, processFoo

       abstract type AbstractFooStruct end
       struct FooStruct1 <: AbstractFooStruct
           bar::Int
       end
       FooStruct = FooStruct1
       function processFoo(foo::AbstractFooStruct)
           @info foo.bar
       end

       end
       """)
230

julia> Pkg.activate(".")
  Activating project at `~/blah/MyPkg`

julia> using MyPkg
  No Changes to `~/blah/MyPkg/Project.toml`
  No Changes to `~/blah/MyPkg/Manifest.toml`
Precompiling MyPkg
  1 dependency successfully precompiled in 2 seconds

julia> processFoo(FooStruct(1))
[ Info: 1

julia> write("src/MyPkg.jl","""
       module MyPkg

       export FooStruct, processFoo

       abstract type AbstractFooStruct end
       struct FooStruct2 <: AbstractFooStruct
           bar::Float64
       end
       FooStruct = FooStruct2
       function processFoo(foo::AbstractFooStruct)
           @info foo.bar
       end

       end
       """)
234

julia> FooStruct
MyPkg.FooStruct2

julia> processFoo(FooStruct(3.5))
[ Info: 3.5
1 Like

Yups. This will work. Thanks a lot…
Github Issue.