What does the Chapel compiler error "use of [symbol] before encountering its definition, type unknown" mean?

36 Views Asked by At

When compiling my Chapel program, I see an error message like:

myProgram.chpl:42: error: use of 'symbol' before encountering its definition, type unknown

but I am unsure what this means or what I should do to resolve it. Can someone help me decipher it?

1

There are 1 best solutions below

0
Brad On

This error message typically occurs when encountering a circularity while resolving the module-scope variables of a Chapel program.

As a very simple example, consider the following program which defines two modules, M and N, each of which defines a variable (a and b, respectively):

module M {
  use N;
  var a = 42;
  proc main() {
    writeln("In main(), a is ", a, " and b is ", b);
  }
}

module N {
  use M;
  var b = a;
}

The Chapel compiler will resolve this program as follows:

  • It starts by trying to resolve M because it is considered the program's main module due to the fact that it contains the main() procedure

  • It then sees that M depends on N due to its use N statement, so will defer resolving M until N is resolved

  • It then sees that N also depends on M due to its use M statement, but will note that it's already started to resolve M, so breaks the cycle by ignoring it and continuing to resolve N (similar to a depth-first search on a graph with cycles)

  • It then tries to resolve the type of module-scope variable b

  • It sees that b is initialized using a, so b's type will depend on a's

  • However, in looking up a's type, it finds that it doesn't know it yet since the resolution of M was deferred until N was resolved

  • This causes it to print out the error:

    testit.chpl:11: error: use of 'a' before encountering its definition, type unknown
    

Note that while we humans can look at this code and see "Well, a is clearly an integer, so b should be an integer as well, what's the problem?", the Chapel compiler's resolution machinery takes a much more constrained approach at present. And arguably this is reasonable because Chapel's definition says that N will be initialized before M since M is the main module and it depends on N. However, that would mean that the program would try to initialize b before initializing a which seems counter to the author's intent.

That said, the error message could definitely be improved for cases like this to explain more about how the compiler got to the statement in question and help users detangle their inter-module dependencies and orderings.

Please note that having a circular use chain between modules M and N is not the inherent source of the problem here, and is an important pattern that's used frequently in Chapel. Such circularities only become problematic when the variable initializations themselves rely on values or expressions that have not yet been resolved using the module resolution/initialization order.

Some potential ways to address errors like this include:

  • moving the interdependent variables into a single module (either one of the existing ones, or a new one designed to break the cycle)
  • breaking the circular dependence between the modules themselves (though again, this is not strictly required as long as the variable definitions can be ordered properly)