rust-lang / rust-lang/rust-analyzer

Debug restart recompilation stopped working

Open
#21,082 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
16.9k
Forks
2.2k
Avg merge
1d 12h
Merged PRs (30d)
72

Description

Problem Description

The debug restart recompilation feature (implemented in PR #17923, merged Sep 27, 2024) has stopped working. When pressing the restart button (⟳) while debugging Rust tests, the code is no longer recompiled, causing the debugger to use stale binaries even after code changes.

Root Cause

PR #17923 implemented the feature by listening to the onDidTerminateDebugSession event to detect when a debug session was restarting:

vscode.debug.onDidTerminateDebugSession((session) => {
    if (activeDebugSessionIds.includes(session.id)) {
        // Recompile on restart
    }
});

However, VS Code's debug API behavior has changed (likely in a recent VS Code update). The onDidTerminateDebugSession event no longer fires when the restart button is clicked - it only fires when a session is fully terminated/stopped.

Impact

Users who modify code during a debug session and press restart will see:

  • Old variable values in the debugger
  • Outdated code behavior
  • Breakpoints may not align with the actual source
  • Confusing debugging experience requiring manual stop + re-run

Why This Happened

VS Code uses the Debug Adapter Protocol (DAP) for communication between the editor and debug adapters. When restart is triggered:

Before (working):

  1. User clicks restart button
  2. onDidTerminateDebugSession event fires
  3. Extension recompiles
  4. Session restarts with new binary

Now (broken):

  1. User clicks restart button
  2. DAP sends restart command directly to debug adapter
  3. onDidTerminateDebugSession does NOT fire
  4. Session restarts with cached/stale binary

The debug adapter caches the binary and symbols, so even if we tried to recompile asynchronously, the restart would use the old data.

Attempted Solutions

I tested several approaches:

  1. Wait for onDidTerminateDebugSession - No longer fires on restart
  2. Check binary modification time - Debug adapter caches symbols regardless
  3. Send invalidate request to debug adapter - Not supported by all adapters
  4. Intercept DAP restart command - Working solution (PR #21081)

Solution (PR #21081)

Use DebugAdapterTracker.onWillReceiveMessage to intercept the DAP restart command before it reaches the debug adapter:

vscode.debug.registerDebugAdapterTrackerFactory("*", {
    createDebugAdapterTracker(session) {
        return {
            onWillReceiveMessage: async (message) => {
                if (message.command === "restart") {
                    // Stop session (clears cache)
                    await vscode.debug.stopDebugging(session);
                    // Recompile with progress notification
                    await recompile(session);
                    // Start fresh session
                    await vscode.debug.startDebugging(session.workspaceFolder, session.configuration);
                }
            }
        };
    }
});

The stop → recompile → fresh start sequence is necessary because debug adapters cache binaries/symbols. A simple restart would continue using stale data.

Related Issues

  • Original feature request: #17901
  • Original implementation: #17923 (merged Sep 27, 2024)
  • Fix for broken behavior: #21081 (current PR)

Testing

Reproduced on:

  • VS Code 1.95+
  • CodeLLDB 1.10+
  • rust-analyzer latest

The fix has been tested with:

  • ✅ Single restart after code changes
  • ✅ Multiple consecutive restarts
  • ✅ Error handling for compilation failures
  • ✅ Progress notifications during recompilation
  • ✅ Unit tests for DAP message interception
  • ✅ Integration test documentation

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the debug adapter tracker and the onWillReceiveMessage restart entry point described in the issue. Review the unit tests for DAP message interception and the integration-test documentation; done means restart handles recompilation, repeated restarts, and compilation failures without using stale binaries.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, typescript, vscode
Domain
devtools, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.