Recompilation avoidance questions

Ömer Sinan Ağacan omeragacan at gmail.com
Tue Apr 21 10:37:38 UTC 2020


Hi all,

I'm currently reading the "recompilation avoidance" wiki page [1], and I have a
few questions about the current design.

The wiki page says (in the paragraph "Suppose the change to D ...") if a module
B re-exports x from module D, changing x in D does not cause any changes in B's
interface.

I'm wondering why this is the case. To me this doesn't make sense. Anything that
can potentially effect users of B should be a part of B's interface. This
includes re-exports. I don't understand why there is a difference between normal
exports and re-exports. As far as users of the module concerned there's no
difference. So I'd expect any changes in re-exports to make a difference in B's
interface.

The wiki page says (in "Why not do (1)", where (1) refers to making D.x part of
B's interface) that this is because sometimes changes in D.x should not cause
recompiling B's users. I don't understand why (1) would cause this problem. If
we make x a part of B, as if it's defined in B, similar to how we can avoid
recompilation of users of B when a definition of B changes but the interface is
the same, we could avoid recompiling users when D.x changes.

For example,

    -- B.hs
    module B where

    b = 123123

    -- Main.hs
    import B

    main = print b


    $ ghc-stage1 Main.hs
    [1 of 2] Compiling B                ( B.hs, B.o )
    [2 of 2] Compiling Main             ( Main.hs, Main.o )
    Linking Main ...

Now if I update B and recompile I'll only link Main, won't recompile it:

    -- B.hs
    module B where

    b = 123123 + 12308

    $ ghc-stage1 Main.hs
    [1 of 2] Compiling B                ( B.hs, B.o )
    Linking Main ...

Now suppose B.b was a re-export from D. I don't understand why changing it in D
would cause recompiling Main if we make b a part of B's interface. I think what
would happen is: because D's interface hash won't change we won't recompile B.
No problems at all.

Finally, I'm a bit confused about this part

> To ensure that A is recompiled, we therefore have two options:
> ...
> (2) arrange to touch B.hi and C.hi even if they haven't changed.

I don't understand how touching is relevant, as far as I understand touching
can't force recompilation. Example:

    $ ghc-stage1 Main.hs
    [1 of 3] Compiling A                ( A.hs, A.o )
    [2 of 3] Compiling B                ( B.hs, B.o )
    [3 of 3] Compiling Main             ( Main.hs, Main.o )
    Linking Main ...
    $ touch A.hi
    $ ghc-stage1 Main.hs
    $ touch B.hi
    $ ghc-stage1 Main.hs

Am I missing anything?

Thanks,

Ömer

[1]: https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/recompilation-avoidance


More information about the ghc-devs mailing list