GNU bug report logs - #67788
[PATCH] records: Check for missing mandatory innate fields when inheriting.

Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.

Package: guix-patches; Reported by: Skyler Ferris <skyvine@HIDDEN>; Keywords: patch; dated Mon, 11 Dec 2023 22:10:02 UTC; Maintainer for guix-patches is guix-patches@HIDDEN.

Message received at 67788 <at> debbugs.gnu.org:


Received: (at 67788) by debbugs.gnu.org; 13 Jan 2024 19:00:53 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Sat Jan 13 14:00:53 2024
Received: from localhost ([127.0.0.1]:41090 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rOjFU-0007sq-9a
	for submit <at> debbugs.gnu.org; Sat, 13 Jan 2024 14:00:53 -0500
Received: from mail-40131.protonmail.ch ([185.70.40.131]:31133)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rOjFS-0007fe-AK
 for 67788 <at> debbugs.gnu.org; Sat, 13 Jan 2024 14:00:51 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1705172445; x=1705431645;
 bh=Dm4OsjoBQF0pB43gNCoKEC/2EYDpAKE8Nl+oxqxhPrQ=;
 h=Date:To:From:Cc:Subject:Message-ID:Feedback-ID:From:To:Cc:Date:
 Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector;
 b=H2Uz5pY2K/rxDzFNwmd+HtQ3W9Kbm8MZXz6naXAhC72+dF2qERthCWv+xQaP+H3uF
 crK6dg1htwqC0/NH9xj5sKeCfe/hTnMDUGnDM3CW7utwfyN5WxeVnSsIsheD0nIsOl
 zYZsif+uysSySGrZ0ahW56KgT5YBi7vpadFLP4S+WIKId/YEPMwAUD/7uby8ce4GCH
 ch+LcU7+aV/tqENFKQxQrrZKAQPnQl2NYHGQjAsMfA9VovQtSNtMKWkSsJHt7nUfRM
 f2ku/Xzg7QqjZONDqPpRh2r+eEH6+MldHC9FrzcxLbtsKfHVz71wocQp3XFlwOKlhB
 /oMlTomrGWr+g==
Date: Sat, 13 Jan 2024 19:00:34 +0000
To: 67788 <at> debbugs.gnu.org
From: skyvine@HIDDEN
Subject: Re: doc: Add documentation for define-record-type*
Message-ID: <43d0fdc9635394538ffee724beebe885d357bc59.1703713111.git.skyvine@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 67788
Cc: Skyler Ferris <skyvine@HIDDEN>
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

From: Skyler Ferris <skyvine@HIDDEN>

I wrote this documentation by using the docstring in guix/record.scm as a
starting point and expanding on it/reformatting on it to be appropriate
for inclusion in a manual.

* doc/guix.texi: Add sections describing the typical
usage and API for define-record-type*

Change-Id: I19e7220553d10652c794e6e0172b2c9ee961f54f
---
# This version of the patch updates the commit message to explain that I
# wrote the documentation by using the docstring in guix/records.scm as
# a starting point. This process seemed appropriate to me because it is
# being incorporated into the same project for the same purpose. Most of
# the commit is new content, but some of it is shared with the docstring
# - for example the "thing" struct definition and the explanation of
# struct fields. I think that it is useful for the manual and the
# docstrings to share content when appropriate to avoid accidentally
# communicating contradictory ideas to different audiences, but the
# relationship should still be acknowledged. If there is a more formal
# manner in which I should indicate this please let me know and I will
# be happy to update the commit. This version does not change anything
# other than the commit message.
 doc/contributing.texi |   1 -
 doc/guix.texi         | 274 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 274 insertions(+), 1 deletion(-)

diff --git a/doc/contributing.texi b/doc/contributing.texi
index 7337f4bd58..d920b2589a 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -1313,7 +1313,6 @@ Data Types and Pattern Matching
 notably the fact that it is hard to read, error-prone, and a hindrance
 to proper type error reports.
=20
-@findex define-record-type*
 @findex match-record
 @cindex pattern matching
 Guix code should define appropriate data types (for instance, using
diff --git a/doc/guix.texi b/doc/guix.texi
index e61a893af9..3cb15eeca3 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -12606,6 +12606,280 @@ G-Expressions
 @code{(*approximate*)}, but this may change.
 @end deffn
=20
+@node Records in Guix
+@section Records in Guix
+Guix uses @code{define-record-type*} to define structures with a lispy for=
mat.
+Packages, operating systems, etc are all defined with
+@code{define-record-type*} facilities. If one was using this facility to
+define preferences for a text editor, it might look like this:
+
+@lisp
+;; The only valid emulation modes are the symbol 'emacs, the symbol 'vim, =
or
+;; the boolean #f. As a convenience to the user, if they pass in a string
+;; first convert it to a symbol and accept it if it is valid.
+(define (sanitize-emulation-mode value)
+  (let ((symbolized-value (cond ((not value)     #f)
+                                ((string? value) (string->symbol value))
+                                (#t              value))))
+    (unless (or (not symbolized-value)
+                (eq? symbolized-value 'emacs)
+                (eq? symbolized-value 'vim))
+      (throw 'bad-emulation-made
+             (format #f "Unrecognized emulation mode: ~s" value)))
+    symbolized-value))
+
+(define-record-type*
+  <editor-preferences> editor-preferences make-editor-preferences
+  editor-preferences? this-editor-preferences
+  (background-color editor-preferences-background-color
+                    (default "000000"))
+  (text-color       editor-preferences-text-color
+                    (default "FFFFFF"))
+  (emulation-mode   editor-preferences-emulation-mode
+                    (default #f)
+                    (sanitize sanitize-emulation-mode)))
+@end lisp
+
+A user could then define their preferences like this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (background-color "222222")
+    (emulation-mode   'vim)))
+@end lisp
+
+The value contained in @code{my-preferences} contains a custom
+@code{background-color} and @code{emulation-mode}, but keeps the default
+@code{text-color} (@code{"FFFFFF"}). If an invalid @code{emulation-mode} h=
ad
+been specified, for example if the user passed in @code{"vi"} instead of
+@code{"vim"}, @code{sanitize-emulation-mode} would immediately throw an er=
ror.
+
+The program can access values like this:
+
+@lisp
+(editor-preferences-background-color my-preferences)
+@result{} "222222"
+(editor-preferences-text-color my-preferences)
+@result{} "FFFFFF"
+(editor-preferences-emulation-mode my-preferences)
+@result{} 'vim
+@end lisp
+
+There is no way to define setters (all instances are immutable).
+
+@node Record Inheritance
+@subsection Record Inheritance
+It is also possible to inherit from previously defined instances when crea=
ting
+new ones. Continuing with the editor example, someone might want to base t=
heir
+preferences on their friend's preferences but customize a value:
+
+@lisp
+(define friends-preferences
+  (editor-preferences
+    (inherit my-preferences)
+    (emulation-mode 'emacs)))
+@end lisp
+
+This keeps the same @code{background-color} and @code{text-color} that are
+contained in @code{my-preferences} but changes the @code{emulation-mode} t=
o
+be @code{'emacs} instead of @code{'vim}.
+
+Sometimes it does not make sense for a field to be inherited. Suppose that=
 the
+@code{<editor-preferences>} type is updated to contain a username so that =
a
+friendly greeting can be displayed when the program starts up:
+
+@lisp
+;; Usernames must be strings. It would be strange to pass a username as a
+;; symbol, so throw an error in case the user meant to pass in a variable'=
s
+;; value instead of a literal symbol.
+(define (sanitize-username value)
+  (unless (string? value)
+    (throw 'bad-username
+           (format #f "Usernames must be strings! Got: ~s" value)))
+  value)
+
+(define (sanitize-emulation-mode value)
+  (let ((symbolized-value (cond ((not value)     #f)
+                                ((string? value) (string->symbol value))
+                                (#t              value))))
+    (unless (or (not symbolized-value)
+                (eq? symbolized-value 'emacs)
+                (eq? symbolized-value 'vim))
+      (throw 'bad-emulation-made
+             (format #f "Unrecognized emulation mode: ~s" value)))
+    symbolized-value))
+
+(define-record-type*
+  <editor-preferences> editor-preferences make-editor-preferences
+  editor-preferences? this-editor-preferences
+  (username         editor-preferences-username
+                    (innate)
+                    (sanitize sanitize-username))
+  (background-color editor-preferences-background-color
+                    (default "000000"))
+  (text-color       editor-preferences-text-color
+                    (default "FFFFFF"))
+  (emulation-mode   editor-preferences-emulation-mode
+                    (default #f)
+                    (sanitize sanitize-emulation-mode)))
+@end lisp
+
+There are a couple of differences in the new @code{username} field compare=
d to
+the fields we looked at earlier. It is marked as @code{innate}, which mean=
s
+that it will not be inherited. For example, consider what would happen if =
we
+tried to define new instances like this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (username         "my-username")
+    (background-color "222222")
+    (emulation-mode   'vim)))
+
+(define friends-preferences
+  (editor-preferences
+    (inherit my-preferences)
+    (emulation-mode 'emacs)))
+@end lisp
+
+While the @code{friends-preferences} instance still inherits the values fo=
r
+@code{background-color} and @code{text-color}, it will not inherit the val=
ue
+for @code{username}. Furthermore, as the @code{username} field does not de=
fine
+a default value the attempted creation of @code{friends-preferences} will
+actually throw an error. Instead, we could do this:
+
+@lisp
+(define my-preferences
+  (editor-preferences
+    (username         "my-username")
+    (background-color "222222")
+    (emulation-mode   'vim)))
+
+(define friends-preferences
+  (editor-preferences
+    (inherit        my-preferences)
+    (username       "friends-username")
+    (emulation-mode 'emacs)))
+@end lisp
+
+@node @code{define-record-type*} Reference
+@subsection @code{define-record-type*} Reference
+@defmac define-record-type* name syntactic-constructor constructor predica=
te this-identifier fields ...
+
+Define a new record type and associated helpers.
+
+@table @var
+@item name
+A symbol used to name the type, as would normally be provided to a plain
+@code{define-record-type} form. For example, @code{<package>}.
+
+@item syntactic-constructor
+A symbol that will be used to define the user-facing constructor. For exam=
ple,
+the symbol @code{package} is the syntactic constructor for the @code{<pack=
age>}
+structure.
+
+@item constructor
+A symbol that will be used to define the traditional constructor. It is us=
ed in
+the implementation of the syntactic constructor, but will not typically be=
 used
+elsewhere. The traditional @code{make-name} (for example, @code{make-packa=
ge})
+is a fine value to use here.
+
+@item predicate
+A symbol that will be used to test if a value is an instance of this recor=
d.
+For example, @code{package?}.
+
+@item this-identifier
+This symbol can be used when defining fields that need to refer to the str=
uct
+that contains them. For an example of this, see the @code{thunked} field
+property, below.
+
+@item fields
+A set of field specifiers which take the following form:
+
+@lisp
+(field-name field-getter properties ...)
+@end lisp
+
+Each of the properties must have one of the following forms:
+
+@table @code
+@item (default @var{value})
+Defines the default value for the field, if the user does not specify one =
using
+the syntactic constructor.
+
+@item (innate)
+Fields marked as innate will not be inherited from parent objects (see
+Instantiating Records, below, for details of object inheritance).
+
+@item (sanitize @var{proc})
+The value given by the user will be passed into @var{proc} before being st=
ored
+in the object. For example, consider this struct definition:
+
+@lisp
+(define-record-type* <thing> thing make-thing
+  thing?
+  this-thing
+  (name  thing-name
+         (sanitize (lambda (value)
+                     (cond ((string? value) value)
+                           ((symbol? value) (symbol->string value))
+                           (else (throw 'bad! value)))))))
+@end lisp
+
+When creating @code{thing} instances either a string or a symbol can be
+supplied but it will always be stored as a string:
+
+@lisp
+(string? (thing-name (thing (name "some-name"))))
+@result{} #t
+(string? (thing-name (thing (name 'some-name))))
+@result{} #t
+(thing (name 1994))
+@result{} Throw to key `bad!' with args `(1994)'.
+@end lisp
+
+@item (thunked)
+Fields marked as @code{thunked} will actually compute the field's value in=
 the
+current dynamic extent which is useful when referring to fluids in a field=
's
+value. Furthermore, that thunk can access the record it belongs to via the
+@code{this-identifier}. For example:
+
+@lisp
+(define-record-type* <rectangle> rectangle make-rectangle
+  rectangle?
+  this-rectangle
+  (width  rectangle-width)
+  (height rectangle-height)
+  (area rectangle-area (thunked)
+                       (default (* (rectangle-width  this-rectangle)
+                                   (rectangle-height this-rectangle)))))
+
+(define base-rectangle
+  (rectangle
+    (width  2)
+    (height 4)))
+
+(define derived-rectangle
+  (rectangle
+    (inherit base)
+    (width   6)))
+
+(rectangle-area base-rectangle)
+@result{} 8
+
+(rectangle-area derived-rectangle
+@result{} 24
+@end lisp
+
+@item (delayed)
+Fields marked as @code{delayed} are similar to @code{thunked} fields, exce=
pt
+that they are effectively wrapped in a @code{(delay @dots{})} form. Note t=
hat
+delayed fields cannot use @code{this-identifier}.
+@end table
+@end table
+@end defmac
+
 @node Invoking guix repl
 @section Invoking @command{guix repl}
=20
--=20
2.41.0






Information forwarded to guix-patches@HIDDEN:
bug#67788; Package guix-patches. Full text available.

Message received at 67788 <at> debbugs.gnu.org:


Received: (at 67788) by debbugs.gnu.org; 28 Dec 2023 02:05:28 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Dec 27 21:05:28 2023
Received: from localhost ([127.0.0.1]:38183 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rIfm4-0007uL-CR
	for submit <at> debbugs.gnu.org; Wed, 27 Dec 2023 21:05:28 -0500
Received: from mail-40134.protonmail.ch ([185.70.40.134]:23759)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rIfm2-0007u8-KP
 for 67788 <at> debbugs.gnu.org; Wed, 27 Dec 2023 21:05:27 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1703729121; x=1703988321;
 bh=P0ubQj/ubqoxJZ53UZi9m4kPrbhqGaiWKNagVGPkpBI=;
 h=Date:To:From:Subject:Message-ID:In-Reply-To:References:
 Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID:
 Message-ID:BIMI-Selector;
 b=IAERKg0TQ5faxdGVmlrmb1VGB5ccHbBmDYWUsunXUvprjZGlRinrhzv1JoUqRR2Ub
 suMHjQHDkf1cstM9dz70XUEcwPRNSwGBkRjUWCI8Jo60VhUjX+vSAhQFEP7RLrhIqX
 NGTJiKbUymR9jtWdgLTMwZ8uYRLxogUtTHoYCbidTSupEpKUPjR1jNOpyLGJccnWzM
 gi3e+kk5zOfcldhlgzAGY9SBVmfNB3eiKixh0Dxq9hOrIZO2FpnO7DeYVHEqwPxBCC
 lglkCKIiQrN6EkI+ST0lz3016BBs3yGLxYtSB19YomwiHK0qE0Aok4eP4WTf/XqOWF
 49H4ounr4kHQg==
Date: Thu, 28 Dec 2023 02:05:16 +0000
To: 67788 <at> debbugs.gnu.org
From: Skyler Ferris <skyvine@HIDDEN>
Subject: Re: records: Check for missing mandatory innate fields when,
 inheriting.
Message-ID: <d8ece7cc-1b3a-440b-bc4a-f6c9e4a45d6b@HIDDEN>
In-Reply-To: <aabc0db6-418f-4d2f-8528-00c44ec5d234@HIDDEN>
References: <aabc0db6-418f-4d2f-8528-00c44ec5d234@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 67788
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

It looks like this update has the some non-breaking space problem that=20
also occurred on the other patch I updated, 87786. I'll send a fixed=20
version once I am able.





Information forwarded to guix-patches@HIDDEN:
bug#67788; Package guix-patches. Full text available.

Message received at 67788 <at> debbugs.gnu.org:


Received: (at 67788) by debbugs.gnu.org; 28 Dec 2023 00:31:24 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Wed Dec 27 19:31:24 2023
Received: from localhost ([127.0.0.1]:38102 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rIeJ2-0006XZ-2L
	for submit <at> debbugs.gnu.org; Wed, 27 Dec 2023 19:31:24 -0500
Received: from mail-4322.protonmail.ch ([185.70.43.22]:57875)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rIeIz-0006Q6-W0
 for 67788 <at> debbugs.gnu.org; Wed, 27 Dec 2023 19:31:22 -0500
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=protonmail.com;
 s=protonmail3; t=1703723476; x=1703982676;
 bh=Er58yMHg0xcrWVUmZeu1WLbmedDfbUG9f8BkyJclMDg=;
 h=Date:To:From:Subject:Message-ID:Feedback-ID:From:To:Cc:Date:
 Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector;
 b=tZee5fCym6LkFfheXt2vwt7bkM9A+VGlVnHnVYm/NqpY1DoBjz2ifXBTc34ZIb2+N
 aJsbivwLCvqLzz9WWEgAIVjmPET9p6tSa3uCIlYvqIBfRL95TPPPVmqrJuA5CojNZT
 6RpvxLxKIWeYTi3QpljXXu/gSvdr/bDbVgIKGiS68ncLFxH82KyiG61XNzDUB3iwuV
 sjYlw+lQUBxtfDFivPJIY3LGt3YO6EFMrbxXltWqDRnMEFxpAH/94q0CnPW/GgWmKQ
 y3MZzM9ws0KYxGtY2cBVdk76kaRUE+79NjcnnGFH+I6MB5T5wyYz/U2fErg4df2D9T
 NS1CqrC20vxNg==
Date: Thu, 28 Dec 2023 00:30:56 +0000
To: 67788 <at> debbugs.gnu.org
From: Skyler Ferris <skyvine@HIDDEN>
Subject: Re: records: Check for missing mandatory innate fields when,
 inheriting.
Message-ID: <aabc0db6-418f-4d2f-8528-00c44ec5d234@HIDDEN>
Feedback-ID: 40635331:user:proton
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
X-Spam-Score: -0.0 (/)
X-Debbugs-Envelope-To: 67788
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -1.0 (-)

his gives the user a more helpful error message if they inherit from
another instance but forget to supply a value for a field which is
innate and has no default.

* guix/records.scm (record-inheritance): Check for missing innate fields

Change-Id: I08b898d8da551af50aa5b0b60187dcad8d259bc1
---
# This version of the commit addse a test case which confirms that
# theuseful commit message is given. It is based on the test immediately
# above it, which checks for the error message in the non-innate case.
#
# Additionally, I can now confirm that all tests pass with this commit.
# The failures I noted previously were indeed environmental problems and
# have been resolved locally (and were unrelated to the commit).
 =C2=A0guix/records.scm=C2=A0 |=C2=A0 9 +++++++++
 =C2=A0tests/records.scm | 18 ++++++++++++++++++
 =C2=A02 files changed, 27 insertions(+)

diff --git a/guix/records.scm b/guix/records.scm
index f4d12a861d..109c5cf4dc 100644
--- a/guix/records.scm
+++ b/guix/records.scm
@@ -161,6 +161,15 @@ (define-syntax make-syntactic-constructor
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (record-error 'name s "extraneous field initializers =
~a"
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unexpected)))

+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ;; Make sure =
all mandatory and innate fields are included.
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (let* ((field=
s=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (map (compose=
 car syntax->datum)=20
field+value))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (optional=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 (map (compose car syntax->datum)=20
'defaults))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (mandatory=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 (lset-difference eq? '(expected=20
...) optional))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (mandatory+innate (lset-intersection eq? =
mandatory=20
'innate))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (missing=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 (lset-difference eq?=20
mandatory+innate fields)))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 (when (pair? missing)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 (record-error 'name s "missing field initializers ~a"=20
missing)))
+
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 #`(make=
-struct/no-tail type
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 #,@(map (lambda (field index)
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 (or (field-inherited-value field)
diff --git a/tests/records.scm b/tests/records.scm
index 5464892d3b..39f4bfdf9c 100644
--- a/tests/records.scm
+++ b/tests/records.scm
@@ -402,6 +402,24 @@ (define (location-alist loc)
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (string=
-match "missing .*initialize.*baz" message)
 =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (equal?=
 form '(foo))))))

+(test-assert "define-record-type* & innate & missing initializers"
+=C2=A0 (catch 'syntax-error
+=C2=A0=C2=A0=C2=A0 (lambda ()
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (eval '(begin
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 (define-record-type* <foo> foo make-foo
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 foo?
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 (bar foo-bar (default 42))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 (baz foo-baz (innate)))
+
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 (let ((base (foo (bar #t) (baz #t))))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 (foo (inherit base))))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (test-m=
odule))
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 #f)
+=C2=A0=C2=A0=C2=A0 (lambda (key proc message location form . args)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (and (eq? proc 'foo)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (string-match=
 "missing .*initialize.*baz" message)
+=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (equal? form =
'(foo (inherit base)))))))
+
 =C2=A0(test-assert "define-record-type* & extra initializers"
 =C2=A0=C2=A0 (catch 'syntax-error
 =C2=A0=C2=A0=C2=A0=C2=A0 (lambda ()

base-commit: fe86819d8bde674766659c22b215d3a689a8026e
--=20
2.41.0







Information forwarded to guix-patches@HIDDEN:
bug#67788; Package guix-patches. Full text available.

Message received at submit <at> debbugs.gnu.org:


Received: (at submit) by debbugs.gnu.org; 11 Dec 2023 22:09:55 +0000
From debbugs-submit-bounces <at> debbugs.gnu.org Mon Dec 11 17:09:55 2023
Received: from localhost ([127.0.0.1]:54847 helo=debbugs.gnu.org)
	by debbugs.gnu.org with esmtp (Exim 4.84_2)
	(envelope-from <debbugs-submit-bounces <at> debbugs.gnu.org>)
	id 1rCoTL-0004Ky-An
	for submit <at> debbugs.gnu.org; Mon, 11 Dec 2023 17:09:55 -0500
Received: from lists.gnu.org ([2001:470:142::17]:49848)
 by debbugs.gnu.org with esmtp (Exim 4.84_2)
 (envelope-from <skyvine@HIDDEN>) id 1rCoTJ-0004Kl-8W
 for submit <at> debbugs.gnu.org; Mon, 11 Dec 2023 17:09:53 -0500
Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <skyvine@HIDDEN>)
 id 1rCoSw-0005nB-Ri
 for guix-patches@HIDDEN; Mon, 11 Dec 2023 17:09:31 -0500
Received: from c-24-143-119-132.customer.broadstripe.net ([24.143.119.132]
 helo=localhost)
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <skyvine@HIDDEN>)
 id 1rCoSs-00066R-J9
 for guix-patches@HIDDEN; Mon, 11 Dec 2023 17:09:30 -0500
Received: from [127.0.0.1] (helo=localhost.localdomain)
 by localhost with esmtp (Exim 4.96.1)
 (envelope-from <skyvine@HIDDEN>) id 1rCoSp-0006Vx-1N;
 Mon, 11 Dec 2023 14:09:22 -0800
From: Skyler Ferris <skyvine@HIDDEN>
To: guix-patches@HIDDEN
Subject: [PATCH] records: Check for missing mandatory innate fields when
 inheriting.
Date: Mon, 11 Dec 2023 14:09:19 -0800
Message-ID: <5a0f596c5bbcc75e3ca50d37066f42baca354236.1702330063.git.skyvine@HIDDEN>
X-Mailer: git-send-email 2.41.0
MIME-Version: 1.0
X-Debbugs-Cc: Christopher Baines <guix@HIDDEN>, Josselin Poiret <dev@HIDDEN>, Ludovic Courtès <ludo@HIDDEN>, Mathieu Othacehe <othacehe@HIDDEN>, Ricardo Wurmus <rekado@HIDDEN>, Simon Tournier <zimon.toutoune@HIDDEN>, Tobias Geerinckx-Rice <me@HIDDEN>
Content-Transfer-Encoding: 8bit
Received-SPF: softfail client-ip=24.143.119.132;
 envelope-from=skyvine@HIDDEN; helo=localhost
X-Spam_score_int: 72
X-Spam_score: 7.2
X-Spam_bar: +++++++
X-Spam_report: (7.2 / 5.0 requ) BAYES_00=-1.9, FREEMAIL_FROM=0.001,
 FSL_HELO_NON_FQDN_1=0.001, HELO_LOCALHOST=3.828, KHOP_HELO_FCRDNS=0.26,
 RCVD_IN_PBL=3.335, RDNS_DYNAMIC=0.982, SPF_SOFTFAIL=0.665,
 SPOOFED_FREEMAIL=0.001,
 T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no
X-Spam_action: reject
X-Spam-Score: 1.0 (+)
X-Debbugs-Envelope-To: submit
Cc: Skyler Ferris <skyvine@HIDDEN>
X-BeenThere: debbugs-submit <at> debbugs.gnu.org
X-Mailman-Version: 2.1.18
Precedence: list
List-Id: <debbugs-submit.debbugs.gnu.org>
List-Unsubscribe: <https://debbugs.gnu.org/cgi-bin/mailman/options/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=unsubscribe>
List-Archive: <https://debbugs.gnu.org/cgi-bin/mailman/private/debbugs-submit/>
List-Post: <mailto:debbugs-submit <at> debbugs.gnu.org>
List-Help: <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=help>
List-Subscribe: <https://debbugs.gnu.org/cgi-bin/mailman/listinfo/debbugs-submit>, 
 <mailto:debbugs-submit-request <at> debbugs.gnu.org?subject=subscribe>
Errors-To: debbugs-submit-bounces <at> debbugs.gnu.org
Sender: "Debbugs-submit" <debbugs-submit-bounces <at> debbugs.gnu.org>
X-Spam-Score: -0.0 (/)

This gives the user a more helpful error message if they inherit from
another instance but forget to supply a value for a field which is
innate and has no default.

* guix/records.scm (record-inheritance): Check for missing innate fields

Change-Id: I08b898d8da551af50aa5b0b60187dcad8d259bc1
---
This fixes issue #67785 by providing the same error message that is
provided when the value is not inherited.

After applying this patch `make check` had one failure, which seems to
be unrelated. It was the test "pypi->guix-package, no wheel"; for some
reason, the download of the wheel file failed. All other tests, in
particular the tests in `tests/records.scm`, passed.

I additionally manually inspected the values computed in the `let*`
against a type that contained 4 fields, for each combination of
mandatory/non-mandatory and optional/non-optional, and they contained
the expected values.

 guix/records.scm | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/guix/records.scm b/guix/records.scm
index f4d12a861d..109c5cf4dc 100644
--- a/guix/records.scm
+++ b/guix/records.scm
@@ -161,6 +161,15 @@ (define-syntax make-syntactic-constructor
                (record-error 'name s "extraneous field initializers ~a"
                              unexpected)))
 
+           ;; Make sure all mandatory and innate fields are included.
+           (let* ((fields           (map (compose car syntax->datum) field+value))
+                  (optional         (map (compose car syntax->datum) 'defaults))
+                  (mandatory        (lset-difference eq? '(expected ...) optional))
+                  (mandatory+innate (lset-intersection eq? mandatory 'innate))
+                  (missing          (lset-difference eq? mandatory+innate fields)))
+             (when (pair? missing)
+               (record-error 'name s "missing field initializers ~a" missing)))
+
            #`(make-struct/no-tail type
                           #,@(map (lambda (field index)
                                     (or (field-inherited-value field)

base-commit: 2b782f67266b42bb40015bd23ce2443be2f9b01f
-- 
2.41.0





Acknowledgement sent to Skyler Ferris <skyvine@HIDDEN>:
New bug report received and forwarded. Copy sent to guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, rekado@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN. Full text available.
Report forwarded to guix@HIDDEN, dev@HIDDEN, ludo@HIDDEN, othacehe@HIDDEN, rekado@HIDDEN, zimon.toutoune@HIDDEN, me@HIDDEN, guix-patches@HIDDEN:
bug#67788; Package guix-patches. Full text available.
Please note: This is a static page, with minimal formatting, updated once a day.
Click here to see this page with the latest information and nicer formatting.
Last modified: Sat, 20 Jan 2024 12:30:02 UTC

GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997 nCipher Corporation Ltd, 1994-97 Ian Jackson.