Using struct in nested module depends on position in file

I have code which tries to use a struct defined in a nested module. I get a compile error if I use the struct before the submodule, but not if I use the struct after the submodule.

It feels like a namespacing/aliasing issue, given how submodule definitions are supposed to implicitly set up an alias. But then why doesn’t the maual alias at the top of the file resolve the issue?

Code reproduced below, also available at https://repl.it/repls/JuicyUnnaturalAdministration#main.exs

defmodule Outer do
  alias Outer.Inner  # makes no difference if this exists or not

  # With `main/0` here, we get the error
  # "Outer.Inner.__struct__/1 is undefined"
  def main() do
    IO.inspect(%Inner{})
  end

  defmodule Inner do
    defstruct [foo: "hi"]
  end

  # Move the `main` definition here and it compiles.
end

You can not use a struct or require a module before its known to the compiler.

This is a limitation of the compiler.

1 Like

Interesting. The code below works, so the compiler is clearly capable of resolving certain kinds of “unknown” definitions after they’re used, at least in some situations.

defmodule Outer do
    def main() do
    IO.inspect(%__MODULE__{})
  end

  defstruct [foo: "hi"]
end

Because the compiler here knows, that it already is compiling the module that shall define the struct and will therefore continue its work until the struct gots defined and related macros, only then it will use those macros to expand what you have written in the function and finally create the modules byte code.