Revise and structure-local functions

Consider the following (pointless) module:

module ReviseCrash

struct Blah
  a::Int

  function Blah()
    return new(), x->f1()
  end

  function f1()
    return 3
  end
end

function f2()
  return 1
end

end

The constructor Blah returns the structure local function f1 (as a second return value). This code works without causing errors (in 1.5.3 and earlier)

Now using Revise poduces errors, using Revise.includet:
ERROR: UndefVarError: f1 not defined
“using ReviseCrash” and changing the file:

Error: Failed to revise /home/fieker/ReviseCrash.jl
│ exception =
│ UndefVarError: f1 not defined
│ top-level scope at /home/fieker/ReviseCrash.jl:3
│ Revise evaluation error at /home/fieker/ReviseCrash.jl:3

└ @ Revise ~/.julia/packages/Revise/moD4B/src/packagedef.jl:707
┌ Warning: The running code does not match the saved version for the following files:

│ /home/fieker/ReviseCrash.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 ~/.julia/packages/Revise/moD4B/src/packagedef.jl:805

Question:

  • is this illegal Julia code (that somehow passes)
  • a bug in Revise

Thanks
Claus

I think defining a function with a different name from the struct is not valid code. I cannot see how to call that function in any way:

julia> struct A
         A() = 1
       end

julia> A()
1

julia> struct B
         f() = 1
       end

julia> f()
ERROR: UndefVarError: f not defined
Stacktrace:
 [1] top-level scope at REPL[4]:1

julia> B()
ERROR: MethodError: no method matching B()
Stacktrace:
 [1] top-level scope at REPL[6]:1

Revise is detecting that error while parsing the file, but the error will appear if you try to do anything with the struct.

Do you have an example where that could work or be useful?

Yep, I have and it’s working as intended. The function f1 is visibale and available to the inner constructor Blah. In general I can move the function out of the struct - but then it becomes visible to anyone…

My “usage” is essentially:

struct Inner
  f1::Function
end

struct Outer
  I::Inner
  x::Any
  function Outer(x)
    return new(Inner(t->f1(t), x)
 end
 function f1(t::Type1)
   ...
  end
  function f1(t::Type2)
    ...
  end
end

The point of this was to have several different methods f1, neatly all wrapped up inside the struct.

I can move all of this out of the struct, but the question still remains:

  • is this legal?
  • if so is this a Revise bug?
  • if not: it probably should error…
    This “technique” is also neat to “hide” finalizers inside the struct as well.
1 Like

I think this is legal, but not common. Thus Revise might not be designed for it.