~~~Additionally, if there are any associated fennel.friend suggestions (I don't think there are any that can currently come from `import-macros`, but there's a new assert I'm about to merge that will), the suggestion is emitted twice.~~~
## UPDATE
This problem is much simpler than it first appears: any errors coming from an `assert-compile` call that originated from a macro that has suggestions matching the provided error message will result in any friend.fnl suggestions to be printed twice. This includes the ones in `require-macros` when it's being invoked by `import-macros`.
## User macro repro
```fennel
;; can use any message that has a match in `friend.fnl`
(macro oops [s] (assert-compile false "unable to bind (.*)" s) "unreachable")
(oops)
```
Error output:
```
(oops asdf)
Compile error: Compile error in unknown:2:0
Compile error in unknown:2:6
unable to bind (.*)
(oops asdf)
* Try replacing the (.*) with an identifier.
stack traceback:
[C]: in function 'error'
/usr/local/bin/fennel:3728: in function 'fennel.friend.assert-compile'
/usr/local/bin/fennel:2464: in function 'fennel.compiler.assert'
[string "local function _1_(s)..."]:2: in function <[string "local function _1_(s)..."]:1>
(...tail calls...)
[C]: in function 'xpcall'
/usr/local/bin/fennel:2972: in function 'fennel.compiler.macroexpand'
/usr/local/bin/fennel:3159: in function 'fennel.compiler.compile1'
/usr/local/bin/fennel:3456: in function 'fennel.compiler.compile'
[C]: in function 'pcall'
/usr/local/bin/fennel:864: in function </usr/local/bin/fennel:842>
(...tail calls...)
/usr/local/bin/fennel:907: in function 'fennel.repl'
(...tail calls...)
[C]: in ?
* Try replacing the (.*)
(oops asdf)
* Try replacing the (.*) with an identifier.
stack traceback:
[C]: in function 'error'
/usr/local/bin/fennel:3728: in function 'fennel.friend.assert-compile'
/usr/local/bin/fennel:2464: in function 'fennel.compiler.assert'
[string "local function _1_(s)..."]:2: in function <[string "local function _1_(s)..."]:1>
(...tail calls...)
[C]: in function 'xpcall'
/usr/local/bin/fennel:2972: in function 'fennel.compiler.macroexpand'
/usr/local/bin/fennel:3159: in function 'fennel.compiler.compile1'
/usr/local/bin/fennel:3456: in function 'fennel.compiler.compile'
[C]: in function 'pcall'
/usr/local/bin/fennel:864: in function </usr/local/bin/fennel:842>
(...tail calls...)
/usr/local/bin/fennel:907: in function 'fennel.repl'
(...tail calls...)
[C]: in ? with an identifier.
```
## culprit: macroexpand
`macroexpand` is using `pcall` to invoke macros to expand the AST, and then running `(assert-compile ok ...)` to verify successful expansion.
The upside to doing this is that we get the friendly suggestions even for any `assert` calls within the macro itself, and it highlights the entire macro call.
The downside is we lose the ability to highlight more granular areas of a macro call (such as a sym being where it shouldn't , etc), and there's little benefit to `assert-compile` being in the compiler scope.
Ideally we can find a way for `friend.assert-compile` (and `assert-compile` ingeneral) to detect nesting and dedupe the output.
For an example of the double-suggestions from
fennel.friend
, here's a repro for an assert I just added torequire-macros
(and the reason I spotted this), present in currentmain
and the upcoming 1.2.0 release:
bad-macro.fnl
:(fn i-am-not-a-table [] "This won't work with import-macros" :oops)Running
(import-macros bad :bad-macro)Outputs:
Compile error in unknown:1:0 Compile error in unknown:1:15 expected macros to be table (import-macros bad :bad-macro) * Try ensuring your macro definitions return a table. * Try ensuring your macro definitions return a table.
EDITED: This was a red herring! See edited bug description.