> I thought I cannot get void-variable issue for declared dynamically bound
> variables.

Your assumption is wrong. Dynamically bound (or “special” in other Lisps)
variables can be unbound. In fact if you declare it like (taken from
`haskell-indentation.el`):

<!-- language-all: lang-el -->

    (defvar implicit-layout-active) ;; is "off-side" rule active?

You are declaring variable `implicit-layout-active` without setting its
value. We can read about it in doc-string:

> defvar is a special form in ‘C source code’.<br>
>
> (defvar SYMBOL &optional INITVALUE DOCSTRING)
>
> …
>
> The optional argument INITVALUE is evaluated, and used to set SYMBOL, only
> if SYMBOL's value is void.  If SYMBOL is buffer-local, its default value
> is what is set; buffer-local values are not affected.  **If INITVALUE is
> missing, SYMBOL's value is not set.**

This answers your question: you've defined a dynamic variable and have not
set its value. Obviously your code doesn't `let` bind it in some case and
thus you get the error.

----

As for your comment that `(defvar implicit-layout-active)` is the same as
`(defvar implicit-layout-active nil)` — you should check better. A few
things to consider:

1. When your test suite evaluates `(require 'haskell-indentation)` which
   module does it load: where you supply default value or “older” byte
   compiled version installed via package manager?

2. Also note that `defvar` only sets value if variable is currently unbound
   (this is not actual issue in your case, just a word of caution).

Having said all this I can evaluate

    (defvar implicit-layout-active nil)

and the dynamic variable is bound:

    (boundp implicit-layout-active) ⇒ t

Now if I run your test case I get:

    F haskell-indentation-check-23
        should not fail when seeing comments
        (ert-test-failed
         ((should
           (equal
            (cons
             (list ... ...)
             (haskell-indentation-find-indentations))
            current))
          :form
          (equal
           ((3 2))
           ((3 2)
            0))
          :value nil :explanation
          (proper-lists-of-different-length 1 2
                                            ((3 2))
                                            ((3 2)
                                             0)
                                            first-mismatch-at 1)))