Skip to content

Compiler.InitAssembly re-runs every top-level form on already-loaded assemblies #3

@skydread1

Description

@skydread1

Problem

MAGIC has two namespace-loading paths that do not share state about what is loaded:

  1. C# Assembly.LoadFrom + RT.TryLoadInitType via Nostrand.cs BootClojureAndNostrand, which bypasses clojure.core/load-lib.
  2. Clojure load-lib -> load-one -> -load-assembly, which is the only path that conjes onto *loaded-libs*.

The ns macro bridges them for non-core namespaces (each one self-registers as its ns form runs). clojure.core is handled by an explicit *loaded-libs* seed in core.clj (#2). But any stray Assembly.LoadFrom + InitAssembly on an already-loaded namespace would still re-run every top-level form in it, including the def of *load-paths* at magic-compiler/src/stdlib/clojure/core.clj ~line 5855. That re-runs the load-path reset and cascades into sub-namespace re-loads.

Compiler.InitAssembly in clojure-runtime/Clojure/CljCompiler/Compiler.cs (~line 1749) currently has no idempotency guard. It calls InvokeInitType unconditionally.

Suggestion

Track initialized init-types in a static HashSet<Type> in Compiler.cs. Short-circuit re-entry in InvokeInitType when the type has already been invoked. Pin down the bootstrap protocol so the *loaded-libs* seed in core.clj becomes redundant rather than load-bearing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions