Skip to content

Commit 5b24a15

Browse files
authored
Merge branch 'master' into sp/fix-nospec-kwarg
2 parents f054572 + 4f45e40 commit 5b24a15

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

src/type_inf.jl

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ function infer_type(binding::Binding, scope, state)
3333
end
3434

3535
function infer_type_assignment_rhs(binding, state, scope)
36+
is_destructuring = false
37+
lhs = binding.val.args[1]
3638
rhs = binding.val.args[2]
3739
if is_loop_iter_assignment(binding.val)
3840
settype!(binding, infer_eltype(rhs))
@@ -43,13 +45,24 @@ function infer_type_assignment_rhs(binding, state, scope)
4345
end
4446
else
4547
if CSTParser.is_func_call(rhs)
48+
if CSTParser.istuple(lhs)
49+
if CSTParser.isparameters(lhs.args[1])
50+
is_destructuring = true
51+
else
52+
return
53+
end
54+
end
4655
callname = CSTParser.get_name(rhs)
4756
if isidentifier(callname)
4857
resolve_ref(callname, scope, state)
4958
if hasref(callname)
5059
rb = get_root_method(refof(callname), state.server)
5160
if (rb isa Binding && (CoreTypes.isdatatype(rb.type) || rb.val isa SymbolServer.DataTypeStore)) || rb isa SymbolServer.DataTypeStore
52-
settype!(binding, rb)
61+
if is_destructuring
62+
infer_destructuring_type(binding, rb)
63+
else
64+
settype!(binding, rb)
65+
end
5366
end
5467
end
5568
end
@@ -94,6 +107,26 @@ function infer_type_assignment_rhs(binding, state, scope)
94107
end
95108
end
96109

110+
function infer_destructuring_type(binding, rb::SymbolServer.DataTypeStore)
111+
assigned_name = CSTParser.get_name(binding.val)
112+
for (fieldname, fieldtype) in zip(rb.val.fieldnames, rb.val.types)
113+
if fieldname == assigned_name
114+
settype!(binding, fieldtype)
115+
return
116+
end
117+
end
118+
end
119+
function infer_destructuring_type(binding::Binding, rb::EXPR)
120+
assigned_name = string(to_codeobject(binding.name))
121+
scope = scopeof(rb)
122+
names = scope.names
123+
if haskey(names, assigned_name)
124+
b = names[assigned_name]
125+
settype!(binding, b.type)
126+
end
127+
end
128+
infer_destructuring_type(binding, rb::Binding) = infer_destructuring_type(binding, rb.val)
129+
97130
function infer_type_decl(binding, state, scope)
98131
t = binding.val.args[2]
99132
if isidentifier(t)

test/runtests.jl

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ f(arg) = arg
190190
# @test parse_and_pass("function f(x::Int) x end")[1][2][3].binding.t == StaticLint.getsymbolserver(server)["Core"].vals["Function"]
191191
let cst = parse_and_pass("""
192192
struct T end
193-
function f(x::T) x end""")
193+
function f(x::T) x end
194+
""")
194195
@test StaticLint.CoreTypes.isdatatype(bindingof(cst.args[1]).type)
195196
@test StaticLint.CoreTypes.isfunction(bindingof(cst.args[2]).type)
196197
@test bindingof(cst.args[2].args[1].args[2]).type == bindingof(cst.args[1])
@@ -199,7 +200,8 @@ f(arg) = arg
199200
let cst = parse_and_pass("""
200201
struct T end
201202
T() = 1
202-
function f(x::T) x end""")
203+
function f(x::T) x end
204+
""")
203205
@test StaticLint.CoreTypes.isdatatype(bindingof(cst.args[1]).type)
204206
@test StaticLint.CoreTypes.isfunction(bindingof(cst.args[3]).type)
205207
@test bindingof(cst.args[3].args[1].args[2]).type == bindingof(cst.args[1])
@@ -208,7 +210,8 @@ f(arg) = arg
208210

209211
let cst = parse_and_pass("""
210212
struct T end
211-
t = T()""")
213+
t = T()
214+
""")
212215
@test StaticLint.CoreTypes.isdatatype(bindingof(cst.args[1]).type)
213216
@test bindingof(cst.args[2].args[1]).type == bindingof(cst.args[1])
214217
end
@@ -222,7 +225,8 @@ f(arg) = arg
222225
import ..B
223226
B.x
224227
end
225-
end""")
228+
end
229+
""")
226230
@test refof(cst.args[1].args[3].args[2].args[3].args[2].args[2].args[1]) == bindingof(cst[1].args[3].args[1].args[3].args[1].args[1])
227231
end
228232

@@ -235,7 +239,8 @@ f(arg) = arg
235239
end
236240
function f(arg::T1)
237241
arg.field.x
238-
end""");
242+
end
243+
""");
239244
@test refof(cst.args[3].args[2].args[1].args[1].args[1]) == bindingof(cst.args[3].args[1].args[2])
240245
@test refof(cst.args[3].args[2].args[1].args[1].args[2].args[1]) == bindingof(cst.args[2].args[3].args[1])
241246
@test refof(cst.args[3].args[2].args[1].args[2].args[1]) == bindingof(cst.args[1].args[3].args[1])
@@ -342,6 +347,21 @@ f(arg) = arg
342347
@test refof(cst[3][3][1]) !== nothing
343348
@test refof(cst[3][3][2]) !== nothing
344349
end
350+
351+
let cst = parse_and_pass("""
352+
struct Foo
353+
x::DataType
354+
y::Float64
355+
end
356+
(;x, y) = Foo(1,2)
357+
x
358+
y
359+
""")
360+
mx = cst.args[3].meta
361+
@test mx.ref.type.name.name.name == :DataType
362+
my = cst.args[4].meta
363+
@test my.ref.type.name.name.name == :Float64
364+
end
345365
end
346366

347367
@testset "macros" begin

0 commit comments

Comments
 (0)