Skip to content

emmylua_check: 不确定是否要支持,@class 定义在 M 上,方法定义在独立的 mt 上 #1001

@myzhan

Description

@myzhan

让 AI 写了一个最小复现用例,不确定是否要支持这种情况,先发这里讨论一下。

-- EmmyLua Bug: @class 与 metatable 分离时,可选 @field 被推断为 nil
--
-- 当 @class 定义在 M 上,方法定义在独立的 mt 上,
-- 通过 setmetatable(obj, mt) + @return 关联时,
-- mt 方法中 self 的可选 @field(标注为 Type?)被推断为 nil,
-- 导致 `if field then` 被报 unnecessary-if (always falsy)。
--
-- 如果把 @class 直接定义在 mt 上,则不会报此警告。

-- ========== 会触发 bug 的写法 ==========
-- @class 定义在 M 上,mt 是独立 table

---@class Bug1.Rpc
---@field name string?
local M = {}

local mt = {}
mt.__index = mt

function mt:test()
    local name = self.name

    -- BUG: EmmyLua 报 unnecessary-if: this condition is always falsy
    -- name 应该是 string?,但 EmmyLua 认为它一定为 nil
    if name then
        print(name)
    end
end

---@return Bug1.Rpc
function M.new()
    return setmetatable({}, mt)
end

return M

-- ========== 不会触发 bug 的写法(对照组) ==========
-- @class 直接定义在 mt 上
--
-- local M2 = {}
--
-- ---@class Bug1.Rpc2
-- ---@field name string?
-- local mt2 = {}
-- mt2.__index = mt2
--
-- function mt2:test()
--     local name = self.name
--     if name then        -- 不会报 unnecessary-if
--         print(name)
--     end
-- end
--
-- ---@return Bug1.Rpc2
-- function M2.new()
--     return setmetatable({}, mt2)
-- end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions