Typechecker: Don't throw away cast node locations
The Pallene to Lua translator needs the source code location of our type cast node so we should not
throw them away in an optimization.
@@ -26,8 +26,7 @@ local util = require "pallene.util"
-- We also make some adjustments to the AST:
--
-- * We convert qualified identifiers such as `io.write` from ast.Var.Dot to a flat ast.Var.Name.
--- * We add explicit ast.Exp.Cast nodes where there is an implicit upcast or downcast.
--- * We remove redundant ast.Exp.Cast nodes.
+-- * We insert explicit ast.Exp.Cast nodes where there is an implicit upcast or downcast.
-- * We insert ast.Exp.ExtraRet nodes to represent additional return values from functions.
-- * We insert an explicit call to tofloat in some arithmetic operations. For example int + float.
-- * We add an explicit +1 or +1.0 step in numeric for loops without a loop step.
@@ -828,8 +827,22 @@ function Checker:check_exp_synthesize(exp)
error("not implemented")
elseif tag == "ast.Exp.Cast" then
- local dst_t = self:from_ast_type(exp.target)
- return self:check_exp_verify(exp.exp, dst_t, "cast expression")
+ exp._type = self:from_ast_type(exp.target)
+ exp.exp = self:check_exp_verify(exp.exp, exp._type, "cast expression")
+
+ -- We check the child expression with verify instead of synthesize because Pallene cases
+ -- also act as type annotations for things like empty array literals: ({} as {value}).
+ -- However, this means that the call to verify almost always inserts a redundant cast node.
+ -- To keep the --dump-checker output clean, we get rid of it. By the way, the Pallene to
+ -- Lua translator cares that we remove the inner one instead of the outer one because the
+ -- outer one has source locations and the inner one doesn't.
+ while
+ exp.exp._tag == 'ast.Exp.Cast' and
+ exp.exp.target == false and
+ types.equals(exp.exp._type, exp._type)
+ do
+ exp.exp = exp.exp.exp
+ end
elseif tag == "ast.Exp.Paren" then
exp.exp = self:check_exp_synthesize(exp.exp)
