Repository navigation
Request: Limit "Fields cannot be injected" to exact classes #3361
Description
How are you using the lua-language-server?
NeoVim
Which OS are you using?
Windows
What is the issue affecting?
Annotations
Expected Behaviour
The docs say:
Marking the class as (exact) means fields cannot be injected after the definition.
So when I use @class, I expect to not get any injection warnings unless I use (exact). I see this came up before in #2710, so I'd add: I should be able to get a warning for injections in exact classes while silencing warnings in non-exact classes.
Actual Behaviour
Any time I add a field outside of the constructor (and sometimes even ones that are defined in my class constructor), I get this warning:
Fields cannot be injected into the reference of
ClassXforfield_y. To do so, use---@classforinstance_z.
The @class annotation makes lua too strict. I'm using lua because I want to be able to inject fields.
Using annotations has multiple effects:
- It improves completion.
- It improves symbol lookups like goto definition.
- It does type checking.
But it's not great that adding annotations to get 1+2 results in tons of warnings from 3.
I understand that people may not want to add (exact) all over their codebase, but I don't want to add ---@field [any] any to all of mine.
I'd propose a change to diagnostic flags to allow independently controlling these two cases:
inject-field: suppress inject field diagnostic for non-exact classes.inject-field-exact: suppress inject field diagnostic for exact classes.
Reproduction steps
Using neovim and installed luals with Mason. Version: pkg:github/luals/lua-language-server@3.17.1
-- Stripped-down version of https://github.com/rxi/classic/blob/master/classic.lua with an annotation added to be close to real-world class usage.
--
-- classic
--
-- Copyright (c) 2014, rxi
--
-- This module is free software; you can redistribute it and/or modify it under
-- the terms of the MIT license. See LICENSE for details.
--- @class Object
local Object = {}
Object.__index = Object
function Object:new()
end
function Object:extend()
local cls = {}
for k, v in pairs(self) do
if k:find("__") == 1 then
cls[k] = v
end
end
cls.__index = cls
cls.super = self
setmetatable(cls, self)
return cls
end
function Object:__call(...)
local obj = setmetatable({}, self)
obj:new(...)
return obj
end
-- /end classic
--- @class Item : Object
local Item = Object:extend()
function Item:new(id, category)
self.id = id
self.category = category
self.count = 0
end
function Item:Print()
print("Item", self.id, self.category, self.count)
end
--- @param item Item
function FlagDebugItem(item)
item:Print() -- with the annotation, this completes. Yay!
item.is_cheater = true -- Warning :( "Fields cannot be injected into the reference of `Item` for `is_cheater`."
endIf I configure luals to add inject-field to the Lua.diagnostics.disable list, then the warning goes away. But the warning doesn't come back when I make Item an exact class with this annotation: --- @class (exact) Item : Object
Workaround: Add a fake field of any type:
--- @class Item : Object
--- @field [any] any
local Item = Object:extend()Additional Notes
No response
Log File
[WARN][2026-02-23 11:41:41] ...lsp/handlers.lua:564 "More than 100000 files have been scanned. The current scanned directory is `D:\\code\\project\\br`. Please see the [FAQ](https://luals.github.io/wiki/faq/#how-can-i-improve-startup-speeds) to see how you can include fewer files. It is also possible that your [configuration is incorrect](https://luals.github.io/wiki/faq#why-is-the-server-scanning-the-wrong-folder)."
[WARN][2026-02-23 14:32:31] .../lua/vim/lsp.lua:52 "method textDocument/typeDefinition is not supported by any of the servers registered for the current buffer"
[START][2026-02-23 15:29:24] LSP logging initiated
[ERROR][2026-02-23 15:29:24] ...m/lsp/client.lua:620 "LSP[lua_ls]" "Cannot find request with id 125 whilst attempting to cancel"
Activity
tomlau10 commentedon Feb 24, 2026
Although I am not maintainer (just a user/contributor), I don't think this would work based on my understanding of how
@classworks in this language server 😕.my understanding
The
inject-fieldwarning is saying that the server cannot allow some code to just modify the fields of a class, as otherwise it cannot do theundefined-fieldcheck properly:@fieldor actual field/method injection on a variable marked by@classundefined field=> because ... um all field injections are just allowed 😅
(exact)class, it simply limits the class definition to only@field/ method definition, but disallow injecting fields inside methodsin reply to the snippet in Reproduction steps
The problematic code lies in the last part:
itemis just an instance variable ofItemclassis_cheaterfield toItemclass=> such that you will not see
is_cheaterin auto complete for anotherItemobjectis_cheaterfield, you need to mark the variable with@class---@class Item; item = itemline is a bit dumb 🤦♂️As explained from above, adding
(exact)is totally a different thing 🙅♂️Because it will disallow fields that are defined just inside method, like in you case:
=> if you add
(exact)then these fields will not be injected=> you will then have to write them using
@fieldbefore you can use these fields=> which loses all the benefits of auto injection IMO
idbrii commentedon Mar 7, 2026
That seems like an understanding based on how it behaves and not the code? If it knows when fields are injected into a class (because it warns), then it could add those fields to the class definition and have a list of fields that can be accessed.
If that's true, the docs should make that clearer. (The definition sounds like definition of the Lua object, not the annotation.) Regardless, I think we should preserve the ability to warn about an exact class.