Skip to content

Commit c79edf1

Browse files
authored
Merge pull request #3394 from RomanSpector/fix/bitwise-operator-inference
fix: type inference for bitwise operators on integer variables
2 parents 67c26f3 + f8d4b74 commit c79edf1

4 files changed

Lines changed: 39 additions & 4 deletions

File tree

changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<!-- Add all new changes here. They will be moved under a version at release -->
55
* `CHG` Modified the `ResolveRequire` function to pass the source URI as a third argument.
66
* `CHG` Improved the output of test failures during development
7+
* `FIX` Fix type inference for bitwise operators (`<<`, `>>`, `&`, `|`, `~`) on integer variables
8+
* `FIX` Fix constant value computation for chained bitwise expressions in hover tooltips
79
* `FIX` Support Lua 5.5 prefix local attributes such as `local <close>x` and `local <const>x`
810

911
## 3.17.1

script/vm/operator.lua

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ vm.OP_UNARY_MAP = util.revertMap(unaryMap)
5858
vm.OP_BINARY_MAP = util.revertMap(binaryMap)
5959
vm.OP_OTHER_MAP = util.revertMap(otherMap)
6060

61+
---@param source parser.object
62+
---@return uri, vm.infer, vm.infer
63+
local function getOperandInfers(source)
64+
return guide.getUri(source), vm.getInfer(source[1]), vm.getInfer(source[2])
65+
end
66+
6167
---@param operators parser.object[]
6268
---@param op string
6369
---@param value? parser.object
@@ -267,6 +273,13 @@ vm.binarySwitch = util.switch()
267273
end
268274
if node then
269275
vm.setNode(source, node)
276+
return
277+
end
278+
-- Bitwise ops on integers always produce integer
279+
local uri, infer1, infer2 = getOperandInfers(source)
280+
if infer1:hasType(uri, 'integer')
281+
and infer2:hasType(uri, 'integer') then
282+
vm.setNode(source, vm.declareGlobal('type', 'integer'))
270283
end
271284
end
272285
end)
@@ -386,9 +399,7 @@ vm.binarySwitch = util.switch()
386399
[1] = a .. b,
387400
})
388401
else
389-
local uri = guide.getUri(source)
390-
local infer1 = vm.getInfer(source[1])
391-
local infer2 = vm.getInfer(source[2])
402+
local uri, infer1, infer2 = getOperandInfers(source)
392403
if (
393404
infer1:hasType(uri, 'integer')
394405
or infer1:hasType(uri, 'number')

script/vm/value.lua

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ function vm.getInteger(v)
118118
end
119119
local node = vm.compileNode(v)
120120
local result
121+
local hasNonInteger = false
121122
for n in node:eachObject() do
122123
if n.type == 'integer' then
123124
if result then
@@ -135,7 +136,18 @@ function vm.getInteger(v)
135136
end
136137
elseif n.type ~= 'local'
137138
and n.type ~= 'global' then
138-
return nil
139+
hasNonInteger = true
140+
end
141+
end
142+
if hasNonInteger then
143+
result = nil
144+
end
145+
-- If value not found via compiled node, try the local's
146+
-- definition value directly (tracer may not preserve literals)
147+
if result == nil and v.type == 'getlocal' then
148+
local loc = v.node
149+
if loc and loc.value then
150+
return vm.getInteger(loc.value)
139151
end
140152
end
141153
return result

test/type_inference/common.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,16 @@ TEST 'integer' [[
146146
<?x?> = 1 << 2
147147
]]
148148

149+
TEST 'integer' [[
150+
local a = 1 << 20
151+
local <?b?> = a << 1
152+
]]
153+
154+
TEST 'integer' [[
155+
local a = 1 << 20
156+
local <?b?> = (a << 1) - 1
157+
]]
158+
149159
TEST 'unknown' [[
150160
<?x?> = a .. b
151161
]]

0 commit comments

Comments
 (0)