Skip to content

Commit

Permalink
cgen: show more informative errors, instead of a `invalid type (typ=0…
Browse files Browse the repository at this point in the history
… idx=0)` verror panic
  • Loading branch information
spytheman committed Oct 30, 2020
1 parent 60659f1 commit 70cbf56
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 7 deletions.
1 change: 1 addition & 0 deletions vlib/v/ast/ast.v
Expand Up @@ -318,6 +318,7 @@ pub:
pub mut:
typ table.Type
is_tmp_autofree bool
pos token.Position
// tmp_name string // for autofree
}

Expand Down
6 changes: 4 additions & 2 deletions vlib/v/checker/checker.v
Expand Up @@ -1057,6 +1057,10 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
left_type := c.expr(call_expr.left)
is_generic := left_type.has_flag(.generic)
call_expr.left_type = left_type
// Set default values for .return_type & .receiver_type too,
// or there will be hard to diagnose 0 type panics in cgen.
call_expr.return_type = left_type
call_expr.receiver_type = left_type
left_type_sym := c.table.get_type_symbol(c.unwrap_generic(left_type))
method_name := call_expr.name
mut unknown_method_msg := 'unknown method: `${left_type_sym.source_name}.$method_name`'
Expand Down Expand Up @@ -1095,8 +1099,6 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
for arg in call_expr.args {
arg_type = c.expr(arg.expr)
}
call_expr.return_type = left_type
call_expr.receiver_type = left_type
if method_name == 'map' {
// check fn
c.check_map_and_filter(true, elem_typ, call_expr)
Expand Down
27 changes: 23 additions & 4 deletions vlib/v/gen/cgen.v
Expand Up @@ -2309,6 +2309,9 @@ fn (mut g Gen) expr(node ast.Expr) {
g.typeof_name(left)
return
}
if node.expr_type == 0 {
g.checker_bug('unexpected SelectorExpr.expr_type = 0', node.pos)
}
sym := g.table.get_type_symbol(node.expr_type)
if sym.kind == .array_fixed {
assert node.field_name == 'len'
Expand Down Expand Up @@ -3886,14 +3889,21 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
for i, field in struct_init.fields {
inited_fields[field.name] = i
if sym.info is table.Struct as struct_info {
tfield := struct_info.fields.filter(it.name == field.name)[0]
equal_fields := struct_info.fields.filter(it.name == field.name)
if equal_fields.len == 0 {
continue
}
tfield := equal_fields[0]
if tfield.embed_alias_for.len != 0 {
continue
}
}
if sym.kind != .struct_ {
field_name := c_name(field.name)
g.write('.$field_name = ')
if field.typ == 0 {
g.checker_bug('struct init, field.typ is 0', field.pos)
}
field_type_sym := g.table.get_type_symbol(field.typ)
mut cloned := false
if g.autofree && !field.typ.is_ptr() && field_type_sym.kind in [.array, .string] {
Expand Down Expand Up @@ -3931,7 +3941,11 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
// nr_fields = info.fields.len
for field in info.fields {
if sym.info is table.Struct as struct_info {
tfield := struct_info.fields.filter(it.name == field.name)[0]
equal_fields := struct_info.fields.filter(it.name == field.name)
if equal_fields.len == 0 {
continue
}
tfield := equal_fields[0]
if tfield.embed_alias_for.len != 0 {
continue
}
Expand Down Expand Up @@ -4132,8 +4146,13 @@ fn verror(s string) {
}

fn (g &Gen) error(s string, pos token.Position) {
p := if pos.line_nr == 0 { '?' } else { '${pos.line_nr + 1}' }
util.verror('$g.file.path:$p: cgen error', s)
ferror := util.formatted_error('cgen error:', s, g.file.path, pos)
eprintln(ferror)
exit(1)
}

fn (g &Gen) checker_bug(s string, pos token.Position) {
g.error('checker bug; $s', pos)
}

fn (mut g Gen) write_init_function() {
Expand Down
14 changes: 13 additions & 1 deletion vlib/v/gen/fn.v
Expand Up @@ -326,7 +326,10 @@ pub fn (g &Gen) unwrap_generic(typ table.Type) table.Type {
fn (mut g Gen) method_call(node ast.CallExpr) {
// TODO: there are still due to unchecked exprs (opt/some fn arg)
if node.left_type == 0 {
verror('method receiver type is 0, this means there are some uchecked exprs')
g.checker_bug('CallExpr.left_type is 0 in method_call', node.pos)
}
if node.receiver_type == 0 {
g.checker_bug('CallExpr.receiver_type is 0 in method_call', node.pos)
}
// mut receiver_type_name := g.cc_type(node.receiver_type)
// mut receiver_type_name := g.typ(node.receiver_type)
Expand Down Expand Up @@ -545,6 +548,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
// Handle `print(x)`
if is_print && node.args[0].typ != table.string_type { // && !free_tmp_arg_vars {
typ := node.args[0].typ
if typ == 0 {
g.checker_bug('print arg.typ is 0', node.pos)
}
mut styp := g.typ(typ)
sym := g.table.get_type_symbol(typ)
if typ.is_ptr() {
Expand Down Expand Up @@ -831,6 +837,9 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
arg_is_ptr := expected_type.is_ptr() || expected_type.idx() in table.pointer_type_idxs
expr_is_ptr := arg.typ.is_ptr() || arg.typ.idx() in table.pointer_type_idxs
if expected_type == 0 {
g.checker_bug('ref_or_deref_arg expected_type is 0', arg.pos)
}
exp_sym := g.table.get_type_symbol(expected_type)
if arg.is_mut && !arg_is_ptr {
g.write('&/*mut*/')
Expand All @@ -851,6 +860,9 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
}
}
if !g.is_json_fn {
if arg.typ == 0 {
g.checker_bug('ref_or_deref_arg arg.typ is 0', arg.pos)
}
arg_typ_sym := g.table.get_type_symbol(arg.typ)
expected_deref_type := if expected_type.is_ptr() { expected_type.deref() } else { expected_type }
is_sum_type := g.table.get_type_symbol(expected_deref_type).kind == .sum_type
Expand Down
1 change: 1 addition & 0 deletions vlib/v/parser/fn.v
Expand Up @@ -140,6 +140,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
share: table.sharetype_from_flags(is_shared, is_atomic)
expr: e
comments: comments
pos: p.tok.position()
}
if p.tok.kind != .rpar {
p.check(.comma)
Expand Down

0 comments on commit 70cbf56

Please sign in to comment.