Hi all,

Mario noticed that quite a few eggs broke after the keyword CR was
merged.  I had a look and it seems to be that many of them break
because of either bind (14 reverse dependencies) or foreigners (11
broken reverse dependencies), and they both do something to load
already compiled code at compile time.

It turns out that when this happens, and the compiled code being
executed inside the compiler registers an lf[] which refers to
a keyword, *and* that keyword had been interned already (typically
in the source which causes the compiled code to be loaded *afterwards*),
you'll get a weird error that says:

  Error: during expansion of (import ...) - bad argument type - not
     a symbol: #:destructor

Or something like it.

The minimal repo case I can come up with is:

$ cat foo-code.scm
(print #:foo)

$ cat test.scm
(begin-for-syntax (load "foo-code.so"))
(print #:foo)

$ csc -s foo-code.scm
$ csc test.scm

The fix is relatively straightforward, see attached patch.  It just
changes the check_ call to a predicate check for symbol or keyword.

Cheers,
Peter
From 788c29951582802eb351ae8773d75e0828cabb53 Mon Sep 17 00:00:00 2001
From: Peter Bex <[email protected]>
Date: Fri, 24 May 2019 22:23:20 +0200
Subject: [PATCH] Fix obscure bug triggered by marking keywords persistable

When a keyword has already been read at runtime, and then compiled
code is invoked which calls C_h_intern_kw, the keyword will already
exist.  This is when it is marked as persistent because there's an
lf[] referring to it, so it can't be garbage collected.

The C_i_persist_symbol() call would then bail out because the offered
object is not a symbol but a keyword (the check was done with
C_i_check_symbol).

This caused several eggs depending on "foreigners" to break, because
it exports a macro in the import library which happens to use a
keyword.
---
 runtime.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/runtime.c b/runtime.c
index 8a51fd82..30620a22 100644
--- a/runtime.c
+++ b/runtime.c
@@ -2442,7 +2442,13 @@ C_regparm C_word C_fcall C_i_persist_symbol(C_word sym)
   C_word bucket;
   C_SYMBOL_TABLE *stp;
 
-  C_i_check_symbol(sym);
+  /* Normally, this will get called with a symbol, but in
+   * C_h_intern_kw we may call it with keywords too.
+   */
+  if(!C_truep(C_i_symbolp(sym)) && !C_truep(C_i_keywordp(sym))) {
+    error_location = C_SCHEME_FALSE;
+    barf(C_BAD_ARGUMENT_TYPE_NO_SYMBOL_ERROR, NULL, sym);
+  }
 
   for(stp = symbol_table_list; stp != NULL; stp = stp->next) {
     bucket = lookup_bucket(sym, stp);
-- 
2.11.0

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Chicken-hackers mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/chicken-hackers

Reply via email to