Skip to content

fix(lint): warn on private state capture#9411

Draft
onthebed wants to merge 3 commits intomarimo-team:mainfrom
onthebed:clawoss/fix/9407-code-execution-ordering
Draft

fix(lint): warn on private state capture#9411
onthebed wants to merge 3 commits intomarimo-team:mainfrom
onthebed:clawoss/fix/9407-code-execution-ordering

Conversation

@onthebed
Copy link
Copy Markdown

📝 Summary

Closes #9407.

Add a runtime lint warning for top-level functions and classes that capture private cell-local variables from the same cell. This surfaces execution-order-dependent patterns like cached closures without changing runtime behavior.

📋 Pre-Review Checklist

  • For large changes, or changes that affect the public API: this change was discussed or approved through an issue, on Discord, or the community discussions
  • Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
  • Video or media evidence is provided for any visual changes (optional).

✅ Merge Checklist

  • I have read the contributor guidelines.
  • Documentation has been updated where applicable, including docstrings for API changes.
  • Tests have been added for the changes made.

Verification

  • uv run --group test pytest tests/_lint/test_private_state_capture.py -q
  • uv run --group test pytest tests/_lint/test_run_check.py tests/_lint/test_validate_graph.py tests/_lint/test_json_formatter.py::TestJSONFormatterIntegration::test_run_check_json_format_with_issues -q
  • uv run --group test ruff check marimo/_lint/rules/runtime/private_state_capture.py marimo/_lint/rules/runtime/__init__.py tests/_lint/test_private_state_capture.py

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Apr 28, 2026 7:57am

Request Review

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="marimo/_lint/rules/runtime/private_state_capture.py">

<violation number="1" location="marimo/_lint/rules/runtime/private_state_capture.py:61">
P2: Exclude self-references from `private_refs`; recursive private definitions are currently misreported as capturing private state.</violation>

<violation number="2" location="marimo/_lint/rules/runtime/private_state_capture.py:67">
P2: Use unmangled definition names for diagnostics; current output can leak internal mangled names and degrade line/column accuracy for private defs.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Linter as Lint Runner
    participant Graph as DirectedGraph
    participant Rule as NEW: PrivateStateCaptureRule
    participant Ctx as RuleContext
    participant DB as Diagnostic Store

    Note over Linter,DB: Runtime Linting Process

    Linter->>Graph: get_graph()
    Graph-->>Linter: notebook dependency graph

    Linter->>Rule: validate_graph(graph, context)
    
    loop For each Cell in graph
        Rule->>Rule: Inspect variable_data
        
        loop For each Variable (Function/Class)
            Rule->>Rule: Extract required_refs
            
            alt NEW: Check for private capture
                Rule->>Rule: is_mangled_local(ref, cell_id)
                
                opt Ref is private cell-local
                    Rule->>Rule: unmangle_local(ref)
                    Rule->>Ctx: _get_variable_line_info(cell_id, var_name)
                    Ctx-->>Rule: line, column
                    
                    Rule->>Ctx: NEW: add_diagnostic(Diagnostic)
                    Ctx->>DB: Store MR004 warning
                end
            end
        end
    end

    Linter->>DB: get_diagnostics()
    DB-->>Linter: List[Diagnostic]
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

if not private_refs:
continue

line, column = self._get_variable_line_info(
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Use unmangled definition names for diagnostics; current output can leak internal mangled names and degrade line/column accuracy for private defs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At marimo/_lint/rules/runtime/private_state_capture.py, line 67:

<comment>Use unmangled definition names for diagnostics; current output can leak internal mangled names and degrade line/column accuracy for private defs.</comment>

<file context>
@@ -0,0 +1,90 @@
+                    if not private_refs:
+                        continue
+
+                    line, column = self._get_variable_line_info(
+                        cell_id, variable_name, ctx
+                    )
</file context>
Fix with Cubic

{
unmangle_local(ref, cell_id).name
for ref in variable_data.required_refs
if is_mangled_local(ref, cell_id)
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Exclude self-references from private_refs; recursive private definitions are currently misreported as capturing private state.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At marimo/_lint/rules/runtime/private_state_capture.py, line 61:

<comment>Exclude self-references from `private_refs`; recursive private definitions are currently misreported as capturing private state.</comment>

<file context>
@@ -0,0 +1,90 @@
+                        {
+                            unmangle_local(ref, cell_id).name
+                            for ref in variable_data.required_refs
+                            if is_mangled_local(ref, cell_id)
+                        }
+                    )
</file context>
Fix with Cubic

Copy link
Copy Markdown
Collaborator

@dmadisetti dmadisetti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to move this back to draft. I captures the specific case but not general.

return _cache[x] + 1
res = x * x
_cache[x] = res
return res
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't an issue if it's called within the cell


- value: The value of the `UIElement`.
- value: The current value of the `UIElement`. Read-only; it reflects
frontend state and can't be assigned directly. If you need to
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert these doc changes?

if x in _cache:
return _cache[x] + 1
_cache[x] = x * x
return _cache[x]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this is fixated on the specific report but not really addressing the general issue. I think that this in a single cell is actually fine.

Title should probably be: MR004: Cross cell variable mutation.

Here are things that the rule should catch:


a = []
b = set()
a.append(value) # I think we can hardcode for known types
b.add(1234)
a[0] = 123 # __setindex__

Or mutation cross cell from closures

   cache = {} # doesn't have to be private !
    def square(x):
        if x in cache:
            return cache[x] + 1
        cache[x] = x * x
        return cache[x]
square(1) # the error would be here

@dmadisetti dmadisetti marked this pull request as draft April 28, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code Execution Ordering Dependence

2 participants