Skip to content

Commit e711f30

Browse files
committed
resolve #1280
1 parent a00de14 commit e711f30

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
## 3.4.1
44
* `NEW` settings:
55
* `type.weakNilCheck`
6+
* `CHG` allow type contravariance for `setmetatable` when initializing a class
7+
```lua
8+
---@class A
9+
local a = {}
10+
11+
---@class B: A
12+
local b = setmetatable({}, { __index = a }) -- OK!
13+
```
614
* `FIX` [#1256](https://github.com/sumneko/lua-language-server/issues/1256)
715
* `FIX` [#1257](https://github.com/sumneko/lua-language-server/issues/1257)
816
* `FIX` [#1267](https://github.com/sumneko/lua-language-server/issues/1267)

script/core/diagnostics/assign-type-mismatch.lua

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,20 @@ local function hasMarkType(source)
3030
return false
3131
end
3232

33+
---@param source parser.object
34+
---@return boolean
35+
local function hasMarkClass(source)
36+
if not source.bindDocs then
37+
return false
38+
end
39+
for _, doc in ipairs(source.bindDocs) do
40+
if doc.type == 'doc.class' then
41+
return true
42+
end
43+
end
44+
return false
45+
end
46+
3347
---@async
3448
return function (uri, callback)
3549
local state = files.getState(uri)
@@ -72,6 +86,18 @@ return function (uri, callback)
7286
if vm.canCastType(uri, varNode, valueNode) then
7387
return
7488
end
89+
90+
if value.type == 'select'
91+
and value.sindex == 1
92+
and value.vararg
93+
and value.vararg.type == 'call'
94+
and value.vararg.node.special == 'setmetatable'
95+
and hasMarkClass(source) then
96+
if vm.canCastType(uri, valueNode:copy():remove 'table', varNode) then
97+
return
98+
end
99+
end
100+
75101
callback {
76102
start = source.start,
77103
finish = source.finish,

script/vm/node.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ function mt:remove(name)
227227
or (c.type == 'doc.type.boolean' and name == 'false' and c[1] == false)
228228
or (c.type == 'doc.type.table' and name == 'table')
229229
or (c.type == 'doc.type.array' and name == 'table')
230-
or (c.type == 'doc.type.sign' and name == 'table')
230+
or (c.type == 'doc.type.sign' and name == 'table')
231231
or (c.type == 'doc.type.function' and name == 'function') then
232232
table.remove(self, index)
233233
self[c] = nil

test/diagnostics/type-check.lua

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,5 +631,38 @@ n = nb
631631
]]
632632
config.set(nil, 'Lua.type.weakNilCheck', false)
633633

634+
TEST [[
635+
---@class A
636+
local a = {}
637+
638+
---@class B: A
639+
local <!b!> = a
640+
]]
641+
642+
TEST [[
643+
---@class A
644+
local a = {}
645+
a.__index = a
646+
647+
---@class B: A
648+
local b = setmetatable({}, a)
649+
]]
650+
651+
TEST [[
652+
---@class A
653+
local a = {}
654+
655+
---@class B: A
656+
local b = setmetatable({}, {__index = a})
657+
]]
658+
659+
TEST [[
660+
---@class A
661+
local a = {}
662+
663+
---@class B
664+
local <!b!> = setmetatable({}, {__index = a})
665+
]]
666+
634667
config.remove(nil, 'Lua.diagnostics.disable', 'unused-local')
635668
config.remove(nil, 'Lua.diagnostics.disable', 'undefined-global')

0 commit comments

Comments
 (0)