You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is quite an obscure problem but, but here is the issue. We have the following static default_config map which is initialized when the util file is sources like that
This seems like a good idea, until you realize that if the config_def.default_config config has no settings or init_options, the deep extend will simply copy by reference of the vim.empty_dict and not 'deep' copy it (same is applicable for {}). This means that the result of the deep extend will now carry not a copy of the default init_options or settings but the reference created from vim.emtpy_dict itself.
Now every subsequent deep_extend executed on the result of the above deep_extend (default_config) will extend the initial reference and not a copy / clone of it for settings or init_options.
This is something i noticed when i started passing around default configs without init_options, and having init_options be dynamically extending the current config after on_setup, where some configs would be coming in with properties from another unrelated server.
You would notice that extend2 has the property _extend_one on top of the newly attached _extend_two. Same goes for handlers table too. It would seem deep extend would not deep copy empty tables, which might cause unexpected side effects.
The solution i recommend is vim.fn.deepcopy or equivalent the default_config provided by nvim-lspconfig, to create a proper deep copy of all referenced tables.
lua local default_config = tbl_deep_extend('keep', config_def.default_config, vim.fn.deepcopy(util.default_config))
The text was updated successfully, but these errors were encountered:
asmodeus812
changed the title
Using vim.emtpy_dict in combination with deep_extend is breaking user configs
Using vim.emtpy_dict or empty table in combination with deep_extend is breaking user configs
Mar 18, 2024
Description
This is quite an obscure problem but, but here is the issue. We have the following static default_config map which is initialized when the util file is sources like that
Then in several places we deep_extend from user's config like that
This seems like a good idea, until you realize that if the
config_def.default_config
config has nosettings
orinit_options
, the deep extend will simply copy by reference of thevim.empty_dict
and not 'deep' copy it (same is applicable for{}
). This means that the result of the deep extend will now carry not a copy of the defaultinit_options
orsettings
but the reference created fromvim.emtpy_dict
itself.Now every subsequent deep_extend executed on the result of the above deep_extend (default_config) will extend the initial reference and not a copy / clone of it for
settings
orinit_options
.This is something i noticed when i started passing around default configs without init_options, and having init_options be dynamically extending the current config after on_setup, where some configs would be coming in with properties from another unrelated server.
Here is a reproduction steps on what is going on
You would notice that extend2 has the property
_extend_one
on top of the newly attached_extend_two
. Same goes for handlers table too. It would seem deep extend would not deep copy empty tables, which might cause unexpected side effects.The solution i recommend is
vim.fn.deepcopy
or equivalent the default_config provided by nvim-lspconfig, to create a proper deep copy of all referenced tables.lua local default_config = tbl_deep_extend('keep', config_def.default_config, vim.fn.deepcopy(util.default_config))
The text was updated successfully, but these errors were encountered: