Skip to content

daslib should be strict about mutable globals (no_global_variables) #3615

Description

@aleksisch

CodeOfPolicies::no_global_variables rejects any non-const global, and the policy is program-wide: it applies to required modules too, not just to the file the host compiled. So an embedder that sets it cannot use a daslib module that holds mutable module state, and the failure lands on every module whose require graph reaches it:

error[30930]: variable 'nolint_consumed' is not a constant, which is disabled via option no_global_variables

A module that genuinely needs mutable state can say so with options no_global_variables = false, and 9 of them already do (ast.das, debugger.das, debug.das, json.das, quote.das, logger.das, lint_config.das, daspkg.das, rtti.das). The convention exists — it just is not enforced, so a module that gains its first mutable global silently becomes unusable for those hosts. That is what happened to rtti.das when LINT019 added its consumed-directive table: daslib/lint requires rtti, so every linted module started failing.

Right now 18 more daslib modules hold a module-scope var without declaring the option:

aot_cpp, ansi_colors, coverage, cpp_gen, decs, faker, fuzzer, heartbeat,
jobque_profile, linq_fold_common, profiler, regex, rst, rst_comment,
shader_lingua_franca, sql_boost, sql_migrate, sql_provider

Several are on the require path of widely used modules (regexregex_boost/rst/cpp_gen, decsdecs_boost/decs_state, linq_fold_common ← the whole linq_fold family, sql_providersql_boost/sql_linq/sql_migrate), so the same class of breakage is latent for anything that reaches them.

Proposal, in two parts:

  1. Treat "strict about globals" as a daslib contract: every module that needs mutable module state declares options no_global_variables = false. Mechanical, one line per module.
  2. Enforce it in CI by compiling the daslib module set with no_global_variables = true. A new mutable global without the declaration then fails upstream instead of in an embedder.

Flipping the CodeOfPolicies default looks less attractive: it would be a behavior change for every embedder, and ~130 files under tests/ plus ~40 under examples/ hold mutable globals, some of them deliberately exercising globals. Scoping the strictness to the shipped library surface gets the guarantee without that churn.

Happy to prepare the daslib pass and the CI step if the direction is agreeable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions