Documenting nested functions

I’m currently working on a project and I came across an issue with using nested functions.
In particular, I have a nested function that I want to document, and I am getting a warning about “replacing docs”.
This seems to only appear when the outer function is defined in a particular way.

The relevant code is in Docs.jl.

Minimal example:

module Mod
  """
  This is foo
  """
  foo() = begin
    """
    This is bar
    """
    function bar()
      println("world")
    end
    println("hello")
    bar()
  end
end

Mod.foo()
Mod.foo()

# hello
# world
# ┌ Warning: Replacing docs for `Main.Mod.bar :: Tuple{}` in module `Main.Mod`
# └ @ Base.Docs docs/Docs.jl:243
# hello
# world

Without outer function def:

module Mod
  """
  This is foo
  """
  function foo()
    """
    This is bar
    """
    function bar()
      println("world")
    end
    println("hello")
    bar()
  end
end

Mod.foo()
Mod.foo()

# hello
# world
# hello
# world

Is this behavior a bug? It seems like a fairly common use case, and seeing as the existing Docs.jl code suppresses the warning in other cases, it seems like nested functions would be a reasonable case to suppress the warning.

Also, why does the definition of the outer function affect the behavior? I thought that the 2 definition forms were identical.

5 Likes

Works fine if you replace begin with let. The difference between let and begin is that let introduces a scope.

I’m not sure if this is a bug or not (I suppose it is), but in any case I’d recommend always using the function syntax for defining a method. That way you get more granular source line info, relevant for code coverage, stack traces, debugging, etc.

2 Likes

But the method definition foo() = should introduce a scope already.

I agree that for multiline functions function is preferred, nevertheless this may be a bug. It is worth reporting, especially since @maxwell3025 isolated a nice concise MWE.

6 Likes