[pre-ANN] SimpleTypeChecker.jl : an experimental static type checker for C-style programming


The README in the repo should be self-explanatory. More details can be found there. In short, SimpleTypeChecker is an experimental Julia package designed to enforce C-style programming in Julia language. It works well if your code is only lightly templated. An error report from SimpleTypeChecker looks like this:

# join of union type is disallowed
function f8(y::Bool)
    if y
        x = 1.0
        x = 1
Checking MethodInstance for Main.MyTest.CaseTest.f8(::Bool)
 IfError: if type is enlarged
    x = 1
Previous type is Float64, /home/chenningcong/Documents/Code/juliaCode/SimpleTypeChecker/test/case.jl:59:9
Current type is Int64, /home/chenningcong/Documents/Code/juliaCode/SimpleTypeChecker/test/case.jl:61:9

Currently many features are missing, like macros and keywork functions. So it’s more appropriate to use SimpleTypeChecker to develop new codes so use of these features can be avoided in the beginning and won’t cause much trouble.

Comments are welcomed!


Major update to this package.

After some intense work to SimpleTypeChecker’s implementation, SimpleTypeChecker now supports more syntax (Sadly, inner function, closures and broadcast are still not supported…they are much harder to work around, even Julia’ builtin compiler has a hard time with them). The interface is mostly unchanged, See readme for more info and src/doc for supported syntax.

If your codes are mostly in C style and you are interested in using SimpleTypeChecker, you can open an issue on SimpleTypeChecker, I will use SimpleTypeChecker to scan your code base and find potential type instability problems. This is also a good opportunity to stress testing SimpleTypeChecker. If you are developing new codes, you can also give SimpleTypeChecker a try!

Sidenode and some personal thoughts :

  1. I benefited a lot from SimpleTypeChecker. I used it to check itself and this saved me a lot of time during development. One thing I noticed that many detected errors are actually quite trivial, like mistyped variable names or missing arguments for a function call. If people actually run the code without a checker, they will anyway encounter and then fix the error. From this, one may suspect that a static type checker might not be that helpful (I also held a similar view before the start of this project).

    However, I soonly found that I became quite dependent on the type checker and I couldn’t live without it. It’s so easy to make trivial mistakes especially when refactoring codes. Mistyped names are quite harmful when they located on some rare branches (so only after a long time program throws an UndefinedVariableError) . Besides, if I scan the codes frequently, then it’s easier to produce readable error report, because the proportion of modifed codes is much lower so errors are more localized. In contrast, if I use SimpleTypeChecker to scan some unchecked codebases, it may produce many errors and it’s hard to tell the real sources of problem (it also requires non-trivial modificaiton to the codebase).

  2. Julia programmers sometimes have different opinions on type stability for different reasons. For example, I checked codebases from https://github.com/JuliaMusic/PianoFingering.jl and find many type instability bugs. One of them is insufficient application of type parameters. For example, DataStructure.SortDict{K, V} is abstract, it has an additional third parameter Ord for key comparsion indeed. This impacts everywhere he uses this type as struct fields, though he never noticed that.

    After I suggested the author to change the code, he acknowledged it but said “This is not a big deal and abstract container is harmless”, because he preferred to save some typings.

    I think many type unstablities are unintended. They are created due to insufficient understanding of packages or Julia’s internals. People are lazy to fix the errors (or they simply don’t know) once their codes work unless they fully understand the harmness of them (for example, ahead of time compilation is blocked due to dynamic dispatch). So my current thought is that maybe the only way to prevent them is to avoid and force programmer to handle them at the very beginning.

    That’s why I develop this package, and I am looking forward for some feedbacks from community, because it’s unclear whether such philosophy is acceptable for the majority…