Subject: Additional context for #76376 - gexp / canonicalize-path

From: Ryan Sundberg <[email-masked]>
Date: Mon, 17 Feb 2025 14:18:05 -0800

Hello team,

This is a patch for a "deep" bug in Guix gexp processing which evokes in 
circumstances when using g-expressions to build things that try to 
create module closures with code that is referenced in the current 
environment via symlink.

It can manifest in difficult to comprehend errors, such as "no code for 
module: (guix utils)` when guix/utils.scm is correctly defined in the 
load path of the program and exists (but it is a symlink, such as by 
using `guix shell` to load another guix environment, e.g. where the 
shell imports a different guix itself).

In my use case, I was using `guix` to build raw os disk images with my 
own set of customized packages and services when this bug blocked me at 
a dead stop.

The root cause of this after much complex debugging, tracing, and 
reading helped me to identify the bug report from Ludo at 
https://issues.guix.gnu.org/73275 and understand the dangling symlink 
issue. What happens here, and what this patch fixes, is that the 
`interned-file` procedure will not follow symlinks, and will intern a 
symlink if it is told to. In most scenarios this is harmless as the 
symlinks intersect to something (e.g. guix/utils.scm) which is already 
in the profile anyways, so the bug is dormant.
However, in other cases, it is possible to create a dangling symlink 
here when `imported-modules` references a file which is a symlink on the 
Guile %load-path, and `interned-file` in this line of gexp.scm can 
intern a dangling symlink.

This patch closes that possibility by canonicalizing the path of the 
interned file before loading it into the module closure path, so that 
`imported-modules` will never import a dangling symlink to a guile file 
used by a module-closure.

--Ryan