Skip to content

fix: shallow copy in store.mutate via vim.tbl_extend#333

Merged
sudo-tee merged 2 commits intomainfrom
copilot/fix-deepcopy-issue-in-mutate
Mar 18, 2026
Merged

fix: shallow copy in store.mutate via vim.tbl_extend#333
sudo-tee merged 2 commits intomainfrom
copilot/fix-deepcopy-issue-in-mutate

Conversation

Copy link
Contributor

Copilot AI commented Mar 18, 2026

M.mutate was using vim.deepcopy to snapshot state before mutation, which causes problems with certain table structures (issue #331).

Change

Replace deep copy with a shallow copy using vim.tbl_extend:

-- before
local old = vim.deepcopy(current)

-- after
local old = vim.tbl_extend('force', {}, current)
Original prompt

In lua/opencode/state/store.lua, there is an issue with vim.deepcopy in the M.mutate function which causes problems (resolves issue #331).

Please replace the vim.deepcopy call in M.mutate with a shallow copy using vim.tbl_extend.

Specifically, change this line:

local old = vim.deepcopy(current)

To:

local old = vim.tbl_extend('force', {}, current)

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: #331

There is an issue with deepcopy in mutate in store.lua. can you replace it with a shallow copy .

Assistant: I found the mutate function in lua/opencode/state/store.lua. Currently, it uses vim.deepcopy which can be expensive and cause issues for certain table structures:

function M.mutate(key, mutator)
  if _state[key] == nil then
    _state[key] = {} --[[@as std.RawGet<OpencodeStateData, K>]]
  end

  if type(_state[key]) ~= 'table' then
    error('State key is not a table: ' .. key)
  end

  local current = _state[key]
  local old = vim.deepcopy(current) -- Deep copy here
  mutator(current)
  queue_emit(key, current, old)
  return current
end

To replace it with a shallow copy, you can iterate over the table's key-value pairs or use vim.tbl_extend (if it's a dictionary-like table). A safe approach for both arrays and dictionaries is a simple loop:

function M.mutate(key, mutator)
  if _state[key] == nil then
    _state[key] = {} --[[@as std.RawGet<OpencodeStateData, K>]]
  end

  if type(_state[key]) ~= 'table' then
    error('State key is not a table: ' .. key)
  end

  local current = _state[key]
  
  -- Shallow copy replacement
  local old = {}
  for k, v in pairs(current) do
    old[k] = v
  end

  mutator(current)
  queue_emit(key, current, old)
  return current
end

If you would like me to create a pull request to make this change for you on the sudo-tee/opencode.nvim repository, just let me know!

User: No use vim.tbl extend

Assistant: Got it! You can use vim.tbl_extend with the 'force' behavior to create a shallow copy into a new empty table.

Here is the updated mutate function using vim.tbl_extend:

function M.mutate(key, mutator)
  if _state[key] == nil then
    _state[key] = {} --[[@as std.RawGet<OpencodeStateData, K>]]
  end

  if type(_state[key]) ~= 'table' then
    error('State key is not a table: ' .. key)
  end

  local current = _state[key]
  
  -- Shallow copy using vim.tbl_extend
  local old = vim.tbl_extend('force', {}, current)
  
  mutator(current)
  queue_emit(key, current, old)
  return current
end

If you'd like me to open a pull request to apply this fix to the sudo-tee/opencode.nvim repository and resolve issue #331, just let me know!

User: Yes open a PR please

Assistant: We're currently waiting for your response in the dialog to accept or reject the creation of this pull request.

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: sudo-tee <342110+sudo-tee@users.noreply.github.com>
@sudo-tee sudo-tee marked this pull request as ready for review March 18, 2026 22:06
Copilot AI changed the title [WIP] Fix deepcopy issue in mutate function by using shallow copy fix: shallow copy in store.mutate via vim.tbl_extend Mar 18, 2026
Copilot AI requested a review from sudo-tee March 18, 2026 22:07
@sudo-tee sudo-tee merged commit 138299d into main Mar 18, 2026
10 checks passed
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.

2 participants