Skip to content

Commit

Permalink
Improve error messages for static errors on polymorphic functions
Browse files Browse the repository at this point in the history
  • Loading branch information
edubart committed Sep 30, 2020
1 parent 1678ae7 commit 1e58023
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 8 deletions.
8 changes: 7 additions & 1 deletion nelua/analyzer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ local function visitor_Call(context, node, argnodes, calleetype, calleesym, call
calleetype = nil
calleesym = nil
if knownallargs then
local polyeval = polycalleetype:eval_poly(polyargs)
local polyeval = polycalleetype:eval_poly(polyargs, node)
if polyeval and polyeval.node and polyeval.node.attr.type then
calleesym = polyeval.node.attr
calleetype = polyeval.node.attr.type
Expand Down Expand Up @@ -2232,7 +2232,13 @@ function visitors.FuncDef(context, node, polysymbol)
end
end
end
-- pop node and then push again to fix error message traceback
context:pop_node()
-- used to generate error messages
context:push_state().polysrcnode = polyeval.srcnode
context:traverse_node(polynode, symbol)
context:pop_state()
context:push_node(node)
assert(traits.is_symbol(polynode.attr))
end
end
Expand Down
4 changes: 4 additions & 0 deletions nelua/analyzercontext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ end
function AnalyzerContext:traceback()
local nodes = self.visiting_nodes
local ss = sstream()
local polysrcnode = self.state.polysrcnode
if polysrcnode then
ss:add(polysrcnode:format_message('from', 'polymorphic function instantiation'))
end
for i=1,#nodes-1 do
local node = nodes[i]
if node._astnode and node.tag ~= 'Block' then
Expand Down
10 changes: 6 additions & 4 deletions nelua/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1651,10 +1651,10 @@ function PolyFunctionType:get_poly_eval(args)
end
end

function PolyFunctionType:eval_poly(args)
function PolyFunctionType:eval_poly(args, srcnode)
local polyeval = self:get_poly_eval(args)
if not polyeval then
polyeval = { args = args }
polyeval = { args = args, srcnode = srcnode}
table.insert(self.evals, polyeval)
end
return polyeval
Expand Down Expand Up @@ -2115,7 +2115,8 @@ end

-- Checks if an attr can match a concept.
function ConceptType:get_convertible_from_attr(attr, _, argattrs)
local type, err = self.func(attr, argattrs)
local concept_eval_func = self.func -- alias to have better error messages
local type, err = concept_eval_func(attr, argattrs)
if type == true then -- concept returned true, use the incoming type
assert(attr.type)
type = attr.type
Expand Down Expand Up @@ -2222,7 +2223,8 @@ end

-- Evaluate a generic to a type by calling it's function defined in the preprocessor.
function GenericType:eval_type(params)
local ok, ret = except.trycall(self.func, table.unpack(params))
local generic_eval_func = self.func -- alias to have better error messages
local ok, ret = except.trycall(generic_eval_func, table.unpack(params))
if not ok then
-- the generic creation failed due to a lua error in preprocessor function
return nil, ret
Expand Down
6 changes: 3 additions & 3 deletions nelua/utils/errorer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ local function get_pretty_source_pos_errmsg(src, lineno, colno, errmsg, errname,
local errtraceback = ''

-- extract traceback from message, to move it to the end of the message
local tracebackpos = errmsg:find('stack traceback:', 1, true)
local tracebackpos = errmsg:find('%s*stack traceback%:')
if tracebackpos then
errtraceback = '\n' .. errmsg:sub(tracebackpos)
errmsg = errmsg:sub(1, tracebackpos)
errtraceback = errmsg:sub(tracebackpos)
errmsg = errmsg:sub(1, tracebackpos-1)
end

-- choose the color for the message
Expand Down
10 changes: 10 additions & 0 deletions nelua/visitorcontext.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ function VisitorContext:set_visitors(visitors)
self.default_visitor = visitors.default_visitor or traverser_default_visitor
end

function VisitorContext:push_node(node)
local nodes = self.visiting_nodes
nodes[#nodes + 1] = node
end

function VisitorContext:pop_node()
local nodes = self.visiting_nodes
nodes[#nodes] = nil
end

function VisitorContext:get_parent_node()
local nodes = self.visiting_nodes
return nodes[#nodes - 1]
Expand Down
9 changes: 9 additions & 0 deletions spec/08-runner_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,13 @@ mylib - terminate]])
os.remove('mylib_test')
end)

it("error tracebacks", function()
assert.run_error({'--eval',[[
local function f(x: auto)
## static_error('fail')
end
f(1)
]]}, "polymorphic function instantiation")
end)

end)

0 comments on commit 1e58023

Please sign in to comment.