Subject: Re: bug#20093: master: setting merge-generics duplicate-binding-handler @ expand time raises an error

From: David Pirotte <[email-masked]>
Date: Sun, 3 Jul 2016 01:57:49 -0300

Hi Andy,

> This was interesting -- turned out that GOOPS imports `map' from (srfi
> srfi-1), and it's also there from (guile-user).  SRFI-1 specified it via
> #:replace so all is well, no warnings.  However merge-generics is itself
> a generic which needs `map' to dispatch over its types (at first) and
> then that recurses, leading to badness.

Thanks, it fixed the bug wrt the example of the original message, but it seems it
introduced a new bug, see below.

> But, you say, I only specified the duplicates handler after loading
> goops!  Well indeed, but if a module didn't specify #:duplicates, its
> duplicates handling was implicitly dynamically scoped to whatever the
> current default-duplicates-handlers were.  That seems bogus to me: the
> module declares its imports and exports and a lack of a declaration of
> #:duplicates indicates that the module is implicitly specifying the
> duplicate handlers that are described in the manual.

> In master I have changed the `default-duplicate-binding-handler' to
> simply access the handlers for the current module, as that seems to be
> the correct thing.  Let me know how it goes!  Closing as done but let's
> follow up :)

This is a big problem for me, so I partially locally reverted that part of
the patch, plus, I patch guild so it does this before anything else:

	(eval-when (expand load eval)
	  (use-modules (oop goops))
	  (default-duplicate-binding-handler
	    '(merge-generics replace warn-override-core warn last)))

This worked well with guile-2.0 [guild patched the same way I mean], but raises a
bug using guild from 2.2, that I can reproduce even not reverting anything from your
fix:

	if you patch guild the same way, just to try, then try to compile any file that
	does even not use goops, it raises the same error

As an example, let's create a reexport.scm [based on guile-gnome
glib/gnome/gw/support/modules.scm]

;; reexport.scm starts here
(define-module (reexport)
  #:export (re-export-public-interface))

(define-macro (re-export-public-interface . args)
  "Re-export the public interface of a module or modules. Invoked as
@code{(re-export-public-interface (mod1) (mod2)...)}."
  (if (null? args)
      '(if #f #f)
      `(begin
	 ,@(map (lambda (mod)
		  (or (list? mod)
		      (error "Invalid module specification" mod))
		  `(module-use! (module-public-interface (current-module))
				(resolve-interface ',mod)))
		args))))
;; reexport.scm ends here

Then let's try to compile it using the patched guild as mentioned above:

david@capac:~/gnu/grip/git/grip 5 $ which guild
/opt2/bin/guild
david@capac:~/gnu/grip/git/grip 6 $ guild compile reexport.scm 
;;; note: source file /opt2/bin/guild
;;;       newer than compiled /home/david/.cache/guile/ccache/2.2-LE-8-3.9/opt2/bin/guild.go
;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
;;;       or pass the --no-auto-compile argument to disable.
;;; compiling /opt2/bin/guild
;;; WARNING: compilation of /opt2/bin/guild failed:
;;; ERROR: No applicable method for #<<generic> merge-generics (3)> in call (merge-generics #<directory (guild) 266d750> format #<interface (guile) 2645ea0> #<procedure 26f8920 at ice-9/format.scm:1609:9 (destination format-string . args) | (deprecated-format-string-only)> #<autoload (ice-9 format) 28fc000> #<procedure 26f8920 at ice-9/format.scm:1609:9 (destination format-string . args) | (deprecated-format-string-only)> #f #f)
Backtrace:
In ice-9/eval.scm:
   710:20 19 (primitive-eval (define (main args) (if (# (# #)) #) #))
In ice-9/psyntax.scm:
  1199:22 18 (expand-top-sequence ((define (main args) (if (…) …) …)) …)
In ice-9/boot-9.scm:
   224:17 17 (map1 (#<procedure 2926550 at ice-9/psyntax.scm:1116:3…>))
In ice-9/psyntax.scm:
  1374:12 16 (_)
  1754:11 15 (lp (#(syntax-object (if (defined? (quote #)) #) # …) …) …)
  1644:45 14 (parse _ _ _ _ _ _ _)
In ice-9/boot-9.scm:
   224:17 13 (map1 (((("placeholder" placeholder) ("…" . #) …) . #) …))
In ice-9/psyntax.scm:
  1374:12 12 (_ _ _)
  1449:23 11 (_ _ _)
In ice-9/boot-9.scm:
   224:29 10 (map1 ((quote system-error) (lambda () (setlocale …)) #))
   224:29  9 (map1 ((lambda () (setlocale LC_ALL "")) (lambda # #)))
   224:17  8 (map1 ((lambda args (format (current-error-port) # #))))
In ice-9/psyntax.scm:
  1754:11  7 (lp ((format (current-error-port) "warning: failed…" …)) …)
  1577:33  6 (parse (((("placeholder" placeholder) ("…" . #) …) . #)) …)
  1298:27  5 (syntax-type (format (current-error-port) "warning:…" …) …)
  1282:39  4 (syntax-type format (("placeholder" placeholder) # # …) …)
   302:24  3 (resolve-identifier _ _ (("placeholder" placeholder) …) …)
In unknown file:
           2 (module-variable #<directory (guild) 266d750> format)
In oop/goops.scm:
   1437:4  1 (cache-miss #<directory (guild) 266d750> format #<inte…> …)
In unknown file:
           0 (scm-error goops-error #f "No applicable method for ~S…" …)

ERROR: In procedure scm-error:
ERROR: No applicable method for #<<generic> merge-generics (3)> in call (merge-generics #<directory (guild) 266d750> format #<interface (guile) 2645ea0> #<procedure 26f8920 at ice-9/format.scm:1609:9 (destination format-string . args) | (deprecated-format-string-only)> #<interface (ice-9 format) 26f5b40> #<procedure 26f8920 at ice-9/format.scm:1609:9 (destination format-string . args) | (deprecated-format-string-only)> #f #f)
david@capac:~/gnu/grip/git/grip 7 $ 

NOW, let's ask guild to use --no-auto-compile

#!/bin/sh
# -*- scheme -*-
exec ${GUILE:-/opt2/bin/guile} --no-auto-compile -e '(@@ (guild) main)' -s "$0" "$@"
!#
... ...
 And try again:

david@capac:~/gnu/grip/git/grip 8 $ guild compile reexport.scm 
;;; note: source file /opt2/bin/guild
;;;       newer than compiled /home/david/.cache/guile/ccache/2.2-LE-8-3.9/opt2/bin/guild.go
Backtrace:
In ice-9/eval.scm:
   710:20 19 (primitive-eval (define (main args) (if (# (# #)) #) #))
In ice-9/psyntax.scm:
  1199:22 18 (expand-top-sequence ((define (main args) (if (…) …) …)) …)
In ice-9/boot-9.scm:
   224:17 17 (map1 (#<procedure 1ac7640 at ice-9/psyntax.scm:1116:3…>))
In ice-9/psyntax.scm:
  1374:12 16 (_)
  1754:11 15 (lp (#(syntax-object (if (defined? (quote #)) #) # …) …) …)
  1644:45 14 (parse _ _ _ _ _ _ _)
In ice-9/boot-9.scm:
   224:17 13 (map1 (((("placeholder" placeholder) ("…" . #) …) . #) …))
In ice-9/psyntax.scm:
  1374:12 12 (_ _ _)
  1449:23 11 (_ _ _)
In ice-9/boot-9.scm:
   224:29 10 (map1 ((quote system-error) (lambda () (setlocale …)) #))
   224:29  9 (map1 ((lambda () (setlocale LC_ALL "")) (lambda # #)))
   224:17  8 (map1 ((lambda args (format (current-error-port) # #))))
In ice-9/psyntax.scm:
  1754:11  7 (lp ((format (current-error-port) "warning: failed…" …)) …)
  1577:33  6 (parse (((("placeholder" placeholder) ("…" . #) …) . #)) …)
  1298:27  5 (syntax-type (format (current-error-port) "warning:…" …) …)
  1282:39  4 (syntax-type format (("placeholder" placeholder) # # …) …)
   302:24  3 (resolve-identifier _ _ (("placeholder" placeholder) …) …)
In unknown file:
           2 (module-variable #<directory (guild) 1b76750> format)
In oop/goops.scm:
   1437:4  1 (cache-miss #<directory (guild) 1b76750> format #<inte…> …)
In unknown file:
           0 (scm-error goops-error #f "No applicable method for ~S…" …)

ERROR: In procedure scm-error:
ERROR: No applicable method for #<<generic> merge-generics (3)> in call (merge-generics #<directory (guild) 1b76750> format #<interface (guile) 1b4eea0> #<procedure 1c81cc0 at ice-9/format.scm:1609:9 (destination format-string . args) | (deprecated-format-string-only)> #<autoload (ice-9 format) 1c60630> #<procedure 1c81cc0 at ice-9/format.scm:1609:9 (destination format-string . args) | (deprecated-format-string-only)> #f #f)
david@capac:~/gnu/grip/git/grip 9 $ 

BUT THIS Works:fine, in case it gives you come idea [it raises a warning though, is
this warning expected?]

david@capac:~/alto/projects/guile-tests/goops 3 $ guile
GNU Guile 2.1.3.52-8a087
Copyright (C) 1995-2016 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> ,use (oop goops)
scheme@(guile-user)> (default-duplicate-binding-handler
    '(merge-generics replace warn-override-core warn last))

;;; warning: unknown warning type `macro-use-before-definition'
$1 = (#<<generic> merge-generics (3)> #<procedure replace (module name int1 val1 int2 val2 var val)> #<procedure warn-override-core (module name int1 val1 int2 val2 var val)> #<procedure warn (module name int1 val1 int2 val2 var val)> #<procedure last (module name int1 val1 int2 val2 var val)>)

scheme@(guile-user)> ,use (system base compile)
scheme@(guile-user)> (compile-file "/home/david/gnu/grip/git/grip/reexport.scm")
;;; warning: unknown warning type `macro-use-before-definition'
$2 = "/home/david/.cache/guile/ccache/2.2-LE-8-3.9/usr/alto/projects/gnu/grip/git/grip/reexport.scm.go"
scheme@(guile-user)> 

Sorry for the long email!
I hope you can help!

Cheers,
David