Subject: Re: bug#75879: with-parameters does not work generally for packages

From: David Elsing <[email-masked]>
Date: Mon, 17 Feb 2025 18:59:19 +0000

Hi Ludo',

Ludovic Courtès <[email-masked]> writes:

> Something just came to mind: the object cache.  The cache is keyed by
> object + system + target + grafts?; if there’s anything that influences
> what the object lowers to, changes are the object->derivation mapping is
> already cached and that other thing will be ignored.

Oh that's true, this is an additional problem. Would it make sense to
add the parameters passed to `with-parameters' to the keys used in
`mcached'? Then the parameters would have to be passed around quite a
bit however...
Alternatively, would it be possible to query the fluids with
`current-dynamic-state' instead and use that for the keys in `mcached'?
I don't see any way to inspect a dynamic state though.

> That’s a problem generally speaking with using ‘with-parameters’ with
> parameters other than ‘%current-system’, ‘%current-target-system’, and
> ‘%graft?’.

I think `with-parameters' only works for `%current-system' and
`%current-target-system', not for `%graft?': When setting `%graft?' to
#f in the second `with-parameters' wrapping in
`graft-derivation/shallow', it still evaluates to the same derivation as
with `%graft?' set to #t.

> I wonder if it’s the only thing at play here though.

No, attached is a simplified example without a package using a record
(named <test>) with a (thunked) field. Removing the `mcached' calls in
(guix gexp) results in the same derivation. I think this is because
`lower-object' returns a monadic procedure, which does not keep the
fluids set by `with-parameters', so when the (thunked) field is
evaluated, the parameter has changed.

Maybe it would be good to pass the parameters from the gexp compiler of
<parameterized> to `lower-object' as additional argument and use
`with-fluids*' there (just before `lower' is called)? This worked for
the <test> record defined in the attachment, but not for a package, I
guess because of the expander? I'm not sure how to pass the parameters
in that case though.

Best,
David

(use-modules
 (guix gexp)
 (guix monads)
 (guix records)
 (guix store)
 (guix utils))

(define-record-type* <test>
  test make-test
  test?
  this-test
  (field test-field (thunked)))

(define* (test->derivation test)
  (with-monad %store-monad
   (gexp->derivation
    "test"
    #~(let ((port (open-file #$output "w")))
        (display
         (string-append #$(test-field test) "\n") port)
        (close-port port)))))

(define-gexp-compiler (test-compiler (test <test>) system target)
  (test->derivation test))

(define %param
  (make-parameter "A"))

(define testvalue
  (test
   (field (%param))))

(%param "B")

(define testvalue2
  (with-parameters
      ((%param "C"))
    testvalue))

(%param "D")

testvalue2