wbthomason / packer.nvim

A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config
MIT License
7.72k stars 262 forks source link

Cannot use a large part of the lua vim api within use -> config callback on recent commit. #1090

Closed Lazerbeak12345 closed 1 year ago

Lazerbeak12345 commented 1 year ago

Steps to reproduce

Use this as your config file:

-- Copied from bootstrap code in readme.
local ensure_packer = function()
  local fn = vim.fn
  local install_path = fn.stdpath('data')..'/site/pack/packer/start/packer.nvim'
  if fn.empty(fn.glob(install_path)) > 0 then
    fn.system({'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path})
    vim.cmd [[packadd packer.nvim]]
    return true
  end
  return false
end

local packer_bootstrap = ensure_packer()

return require('packer').startup(function(use)
  use{
    'wbthomason/packer.nvim',  -- This will work on any valid plugin
    config = function()
      vim.g.anyvarname = "any lua value"
    end
  }
  if packer_bootstrap then
    require('packer').sync()
  end
end)

Actual behaviour

Prints error message:

packer.nvim: Error running config for packer.nvim: [string "..."]:0: attempt to index upvalue '' (a nil value)

Expected behaviour

Behaves like a clean nvim session, with only the packer plugin and the appropriately set global variable.

packer files

See above.

packer log file File is empty.
packer compiled file ```lua -- Automatically generated packer.nvim plugin loader code if vim.api.nvim_call_function('has', {'nvim-0.5'}) ~= 1 then vim.api.nvim_command('echohl WarningMsg | echom "Invalid Neovim version for packer.nvim! | echohl None"') return end vim.api.nvim_command('packadd packer.nvim') local no_errors, error_msg = pcall(function() _G._packer = _G._packer or {} _G._packer.inside_compile = true local time local profile_info local should_profile = false if should_profile then local hrtime = vim.loop.hrtime profile_info = {} time = function(chunk, start) if start then profile_info[chunk] = hrtime() else profile_info[chunk] = (hrtime() - profile_info[chunk]) / 1e6 end end else time = function(chunk, start) end end local function save_profiles(threshold) local sorted_times = {} for chunk_name, time_taken in pairs(profile_info) do sorted_times[#sorted_times + 1] = {chunk_name, time_taken} end table.sort(sorted_times, function(a, b) return a[2] > b[2] end) local results = {} for i, elem in ipairs(sorted_times) do if not threshold or threshold and elem[2] > threshold then results[i] = elem[1] .. ' took ' .. elem[2] .. 'ms' end end if threshold then table.insert(results, '(Only showing plugins that took longer than ' .. threshold .. ' ms ' .. 'to load)') end _G._packer.profile_output = results end time([[Luarocks path setup]], true) local package_path_str = "/home/nate/.cache/nvim/packer_hererocks/2.1.0-beta3/share/lua/5.1/?.lua;/home/nate/.cache/nvim/packer_hererocks/2.1.0-beta3/share/lua/5.1/?/init.lua;/home/nate/.cache/nvim/packer_hererocks/2.1.0-beta3/lib/luarocks/rocks-5.1/?.lua;/home/nate/.cache/nvim/packer_hererocks/2.1.0-beta3/lib/luarocks/rocks-5.1/?/init.lua" local install_cpath_pattern = "/home/nate/.cache/nvim/packer_hererocks/2.1.0-beta3/lib/lua/5.1/?.so" if not string.find(package.path, package_path_str, 1, true) then package.path = package.path .. ';' .. package_path_str end if not string.find(package.cpath, install_cpath_pattern, 1, true) then package.cpath = package.cpath .. ';' .. install_cpath_pattern end time([[Luarocks path setup]], false) time([[try_loadstring definition]], true) local function try_loadstring(s, component, name) local success, result = pcall(loadstring(s), name, _G.packer_plugins[name]) if not success then vim.schedule(function() vim.api.nvim_notify('packer.nvim: Error running ' .. component .. ' for ' .. name .. ': ' .. result, vim.log.levels.ERROR, {}) end) end return result end time([[try_loadstring definition]], false) time([[Defining packer_plugins]], true) _G.packer_plugins = { ["packer.nvim"] = { config = { "\27LJ\2\n:\0\0\2\1\3\0\5-\0\0\0009\0\0\0'\1\2\0=\1\1\0K\0\1\0\0\0\17the var here\18asdfasdfafdsf\6g\0" }, loaded = true, path = "/home/nate/.local/share/nvim/site/pack/packer/start/packer.nvim", url = "https://github.com/wbthomason/packer.nvim" } } time([[Defining packer_plugins]], false) -- Config for: packer.nvim time([[Config for packer.nvim]], true) try_loadstring("\27LJ\2\n:\0\0\2\1\3\0\5-\0\0\0009\0\0\0'\1\2\0=\1\1\0K\0\1\0\0\0\17the var here\18asdfasdfafdsf\6g\0", "config", "packer.nvim") time([[Config for packer.nvim]], false) _G._packer.inside_compile = false if _G._packer.needs_bufread == true then vim.cmd("doautocmd BufRead") end _G._packer.needs_bufread = false if should_profile then save_profiles() end end) if not no_errors then error_msg = error_msg:gsub('"', '\\"') vim.api.nvim_command('echohl ErrorMsg | echom "Error in packer_compiled: '..error_msg..'" | echom "Please check your config for correctness" | echohl None') end ```
Lazerbeak12345 commented 1 year ago
vim.tbl_extend('keep',{},{})

also can cause this error message.

Lazerbeak12345 commented 1 year ago
function _G.anyValidName()
end

Functions added to _G can also cause this problem.

Lazerbeak12345 commented 1 year ago

Other things that can cause this issue below. As with earlier examples, must be within a config function. in my case, this config function is defined above the packer block, but inline works too, as shown in the first example.

Running vim.fns

vim.fn["vsnip#anonymous"](args.body)

Running commands:

vim.cmd.colorscheme'base16-default-dark'

getting vim.b's

print(vim.b.anyvarname)

Furthermore, defining a function in any way that isn't as a value causes an error:

local myfun = function ()
    print("this function works just fine, though has some oddities, such as sometimes appearing to be an object, but not consistantly")
end
function myotherfun()
    print("this function doesn't work. throws the error")
end
vanarok commented 1 year ago

silicon-2022-10-18-104058 silicon-2022-10-18-104043 I wanted to set mappings in config but it doesn't work. The plugin is initialized.

Lazerbeak12345 commented 1 year ago

That's interesting. In all of my testing I hadn't seen the bug triggered from within a plugin - it seemed as if plugins were immune to this, while code within the init.lua was where the problem is.

Lazerbeak12345 commented 1 year ago

Just retested this. My example might be faulty.

I'll redo it.

Lazerbeak12345 commented 1 year ago

nevermind. the testcase above works just fine. (ie bug is still present)

From testing, yes, this is to do with the compile thingy that packer does

wbthomason commented 1 year ago

This looks like the known limitation of loadstring/string.dump being incompatible with upvalues (i.e., captures). This is part of why we're removing the compile step in v2.

For some of the examples you gave, @Lazerbeak12345, you can use the string version of config instead, i.e. `config = [[vim.g.whatever = 'something']].

@vanarok I'm not convinced that you have the same issue as the original report, and would need more information to diagnose what's going on.

Lazerbeak12345 commented 1 year ago

thx! I'll reopen if that doesn't work? I've got 10 places in my vimrc to fix now..... :)

wbthomason commented 1 year ago

Yep - sorry for the limitation. If you need more examples, my dotfiles use config fairly heavily with a few workarounds for the upvalues issue. And we will be properly removing this limitation in v2.

Lazerbeak12345 commented 1 year ago

yeah, I was just starting to wonder. nvim_cmp is pretty config intensive. I really only came back to this issue bc my current workaround broke lol

wbthomason commented 1 year ago

Actually, I take this back - this is maybe weirder. It still feels like an upvalues problem, but can't be due to capturing vim from globals - first off, Lua doesn't capture globals, and second, I have this snippet in my config that works just fine:

 use {
    'lewis6991/hover.nvim',
    event = 'BufReadPost',
    config = function()
      require('hover').setup {
        init = function()
          require 'hover.providers.lsp'
        end,
      }

      vim.keymap.set('n', 'K', require('hover').hover, { desc = 'hover.nvim' })
      vim.keymap.set('n', 'gK', require('hover').hover_select, { desc = 'hover.nvim (select)' })
    end,
  }

@Lazerbeak12345 you said your original example, in isolation, reproduces the issue consistently?

Lazerbeak12345 commented 1 year ago

yes.

You'll have to, of course, ensure that there are no plugins, and etc. If you're having trouble recreating that, I suppose I could list the exact steps I'm using to do this. Works in multiple ways, including just nuking all nvim related files in my home dir. (BACK UP ANYTHING YOU WANT TO KEEP FIRST :wink:)

Lazerbeak12345 commented 1 year ago

seems to be duplicate of #683 (untested, but looks to be the same)

(link all the things)

And yes, I'm still affected by this. Waiting patiently for version 2 :)

Lazerbeak12345 commented 1 year ago

see also #351 #996