Subject: Re: bug#19459: #:export does not honor the merge-generics contract

From: David Pirotte <[email-masked]>
Date: Thu, 23 Jun 2016 18:11:03 -0300

> > Hi Andy,
> >  
> >> > (define-module (a)
> >> >   #:use-module (oop goops)
> >> >   #:export (<a>
> >> > 	    !width
> >> > 	    get-width
> >> > 	    set-width))    
> >  
> >> Here you export four bindings: one class and three generics.  Those
> >> three generics have methods on <a>.  
> >  
> >> > (define-module (b)
> >> >   #:use-module (oop goops)
> >> >   #:use-module (a)    
> >  
> >> Here you import the previous four bindings.  
> >  
> >> >   #:export (<b>
> >> > 	    !width
> >> > 	    get-width
> >> > 	    set-width))    
> >  
> >> However here you declare that you are going to export four new
> >> bindings.
> >> ...  
> >
> > Under the exact circumstances of the original email, I disagree, see below.  
> 
> I see.  You were expecting for the dynamically setting the
> default-duplicate-binding-handler parameter to make a difference.

Yes, and it has to: with that setting, at any time in any module, there can be 1
and only 1 generic function for a given name:

	but as it is, right now, even with that setting, Guile is exporting
	'something' I did not ask to export, Guile is exporting a new binding,
	that I never asked to create [unless it would not be imported]

	from the (b) module perspective, I ask Guile to import (a), fill the generic
	functions with new methods, and export it, these generic functions, not new
	other ones

The symptom of the actual anomaly is very well expressed by my last sentence:

	"... last but not least, when a user imports (b) and run (make <b>), he is
	not himself calling set-width or get-width: exported or not, the code being
	run by make should run within the (b) module, and in the (b) module they can
	be only 1 generic function, with the method of (a) and the method of (b)..."

This should never raise an exception:

	scheme@(guile-user)> ,use (b)
	scheme@(guile-user)> (make <b>)

Currently it does if the user used #:export, it does not if he/she does not export

The problem is guile's module system, not GOOPS here

> However I think this is maybe not the right way to set this up; see
> reasoning in http://debbugs.gnu.org/cgi/bugreport.cgi?bug=20093.

	That is/was a totally different bug, but thanks for the fix! I disagree with
	the comment though, but I will pull, compile test it will take 1 or 2
	days... I hope it fixes it!

> However... I believe merge-generics is intended to merge duplicate
> imported bindings.  It does not provide a copy-on-write version of an
> imported generic, if that generic was not duplicated in the imports.
> There is no facility in GOOPS to do that, AFAIU.

It is a module bug, not a GOOPS bug, see my 'personal/local' fix: the problem is
that once the user uses #:export, guile's module system create a new binding, and it
should not ... [hence this confusion as well: as it is: the module must merge its
definition with the imported ones, even if it imported only 1 generic ... because of
a module bug...]

David