LuaLS / LuaLS/lua-language-server

Feature Request: Typestate / Self-Type Refinement for Method Calls

オープン
#3,407 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

主要言語
Lua
スター
4.4k
フォーク
442
PR マージ指標
30日以内にマージされた PR はありません

説明

Problem

Lua is a highly dynamic language, and many real-world Lua frameworks mutate object capabilities at runtime.

This pattern is especially common in:

  • game engines
  • UI frameworks
  • ECS architectures
  • builder APIs
  • runtime mixin systems
  • userdata bindings from native engines

Currently, LuaLS/LuaCats cannot properly express:

"after calling this method, self now has additional capabilities/methods"

This becomes a major DX limitation for frameworks that dynamically extend objects.


Real-world Example

Consider a UI framework where all elements start as a generic UIElement.

---@class UIElement
local UIElement = {}

Calling:

element:setupUIImage()

injects image-related functionality into the element at runtime:

element:setImage(...)

However, LuaLS still sees element as only UIElement.

The only current workaround is manual casting:

element:setupUIImage()

---@cast element UIImage
element:setImage(material)

This works technically, but becomes repetitive and hurts DX significantly in large codebases.


Comparison to TypeScript

TypeScript supports type refinement after method calls through assertion signatures such as:

asserts this is SomeType

This allows APIs to safely refine object types after capability-changing methods.

A good real-world example is discord.js, where Interaction objects can be refined into subtypes through methods like:

interaction.isButton()
interaction.isChatInputCommand()

After refinement, TypeScript understands the new subtype automatically.

Lua frameworks often use similar runtime patterns, but LuaLS currently cannot model them.


Proposed Solution

Introduce a LuaCats annotation for self-type refinement / capability injection.

Possible syntax examples:

---@injects UIImage
function UIElement:setupUIImage() end

or:

---@mutates self UIImage
function UIElement:setupUIImage() end

or:

---@becomes UIImage
function UIElement:setupUIImage() end

Expected Behavior

After:

element:setupUIImage()

LuaLS would understand:

element :: UIElement & UIImage

allowing:

element:setImage(...)

without requiring manual casts.


Why This Matters

This would greatly improve support for:

  • dynamic Lua architectures
  • runtime capability injection
  • engine bindings
  • UI frameworks
  • builder APIs
  • fluent APIs
  • mixin systems

while keeping Lua's dynamic nature intact.

This feature would also reduce:

  • repetitive ---@cast
  • noisy annotations
  • inaccurate supersets in base classes
  • degraded autocomplete quality

Additional Notes

This feature does not need to become full typestate analysis or advanced dependent typing.

Even a pragmatic flow-sensitive refinement system limited to:

  • direct method calls
  • current scope
  • explicit annotations only

would already provide massive DX improvements.


Example Use Case

---@class UIImage
---@field setImage fun(self: UIImage, material: string)

---@class UIElement

---@injects UIImage
function UIElement:setupUIImage() end

local element = UIElement.new()

element:setupUIImage()

element:setImage("icon")

Expected:

  • autocomplete works
  • diagnostics recognize setImage
  • no manual cast required

Thanks for all the amazing work on LuaLS and LuaCats.
This would significantly improve tooling support for dynamic Lua patterns commonly used in real-world frameworks and game engines.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

Issue では実装ファイルやテストは指定されていません。まず、LuaLS が現在、明示的な ---@cast とメソッド呼び出しをどのように扱っているかを確認し、続いて提案されている絞り込みの範囲を評価してください: 直接呼び出し、現在のスコープ、明示的なアノテーション。完了の条件は、手動の cast なしで、フローに応じた capability の絞り込み、オートコンプリート、診断が機能する、確定したアノテーション設計ができていることです。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
lua
領域
devtools
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。