checker: check if the type in `as` exists, skip void type errors

pull/5387/head
Alexander Medvednikov 2020-06-19 11:15:15 +02:00
parent 5a6d440f68
commit ef36520509
3 changed files with 37 additions and 25 deletions

View File

@ -96,11 +96,11 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool {
// TODO: there is a bug when casting sumtype the other way if its pointer // TODO: there is a bug when casting sumtype the other way if its pointer
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)` // so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
// if got_type_sym.kind == .sum_type { // if got_type_sym.kind == .sum_type {
// sum_info := got_type_sym.info as table.SumType // sum_info := got_type_sym.info as table.SumType
// // TODO: handle `match SumType { &PtrVariant {} }` currently just checking base // // TODO: handle `match SumType { &PtrVariant {} }` currently just checking base
// if expected.set_nr_muls(0) in sum_info.variants { // if expected.set_nr_muls(0) in sum_info.variants {
// return true // return true
// } // }
// } // }
if exp_type_sym.kind == .sum_type { if exp_type_sym.kind == .sum_type {
sum_info := exp_type_sym.info as table.SumType sum_info := exp_type_sym.info as table.SumType
@ -133,10 +133,12 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool {
[inline] [inline]
fn (c &Checker) check_shift(left_type, right_type table.Type, left_pos, right_pos token.Position) table.Type { fn (c &Checker) check_shift(left_type, right_type table.Type, left_pos, right_pos token.Position) table.Type {
if !left_type.is_int() { if !left_type.is_int() {
c.error('cannot shift type ${c.table.get_type_symbol(right_type).name} into non-integer type ${c.table.get_type_symbol(left_type).name}', left_pos) c.error('cannot shift type ${c.table.get_type_symbol(right_type).name} into non-integer type ${c.table.get_type_symbol(left_type).name}',
left_pos)
return table.void_type return table.void_type
} else if !right_type.is_int() { } else if !right_type.is_int() {
c.error('cannot shift non-integer type ${c.table.get_type_symbol(right_type).name} into type ${c.table.get_type_symbol(left_type).name}', right_pos) c.error('cannot shift non-integer type ${c.table.get_type_symbol(right_type).name} into type ${c.table.get_type_symbol(left_type).name}',
right_pos)
return table.void_type return table.void_type
} }
return left_type return left_type
@ -269,9 +271,8 @@ pub fn (c &Checker) get_default_fmt(ftyp, typ table.Type) byte {
return `p` return `p`
} else { } else {
sym := c.table.get_type_symbol(ftyp) sym := c.table.get_type_symbol(ftyp)
if ftyp in [table.string_type, table.bool_type] || sym.kind in if ftyp in [table.string_type, table.bool_type] || sym.kind in [.enum_, .array, .array_fixed,
[.enum_, .array, .array_fixed, .struct_, .map] || ftyp.has_flag(.optional) || .struct_, .map] || ftyp.has_flag(.optional) || sym.has_method('str') {
sym.has_method('str') {
return `s` return `s`
} else { } else {
return `_` return `_`
@ -292,8 +293,10 @@ pub fn (c &Checker) string_inter_lit(mut node ast.StringInterLiteral) table.Type
if fmt == `_` { // set default representation for type if none has been given if fmt == `_` { // set default representation for type if none has been given
fmt = c.get_default_fmt(ftyp, typ) fmt = c.get_default_fmt(ftyp, typ)
if fmt == `_` { if fmt == `_` {
c.error('no known default format for type `${c.table.get_type_name(ftyp)}`', if typ != table.void_type {
c.error('no known default format for type `${c.table.get_type_name(ftyp)}`',
node.fmt_poss[i]) node.fmt_poss[i])
}
} else { } else {
node.fmts[i] = fmt node.fmts[i] = fmt
node.need_fmts[i] = false node.need_fmts[i] = false
@ -305,13 +308,12 @@ pub fn (c &Checker) string_inter_lit(mut node ast.StringInterLiteral) table.Type
if node.pluss[i] && !typ.is_number() { if node.pluss[i] && !typ.is_number() {
c.error('plus prefix only allowd for numbers', node.fmt_poss[i]) c.error('plus prefix only allowd for numbers', node.fmt_poss[i])
} }
if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) || if (typ.is_unsigned() && fmt !in [`u`, `x`, `X`, `o`, `c`]) || (typ.is_signed() &&
(typ.is_signed() && fmt !in [`d`, `x`, `X`, `o`, `c`]) || fmt !in [`d`, `x`, `X`, `o`, `c`]) || (typ.is_any_int() && fmt !in [`d`, `c`, `x`, `X`, `o`,
(typ.is_any_int() && fmt !in [`d`, `c`, `x`, `X`, `o`, `u`, `x`, `X`, `o`]) || `u`, `x`, `X`, `o`]) || (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) || (typ.is_pointer() &&
(typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) || fmt !in [`p`, `x`, `X`]) || (typ.is_string() && fmt != `s`) || (typ.idx() in [table.i64_type_idx,
(typ.is_pointer() && fmt !in [`p`, `x`, `X`]) || table.f64_type_idx
(typ.is_string() && fmt != `s`) || ] && fmt == `c`) {
(typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`) {
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`', c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
node.fmt_poss[i]) node.fmt_poss[i])
} }

View File

@ -780,8 +780,8 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
c.error('type mismatch, should use `$elem_sym.name[]`', arg_expr.position()) c.error('type mismatch, should use `$elem_sym.name[]`', arg_expr.position())
} }
} else { } else {
if arg_sym.kind != elem_sym.kind && ((elem_sym.kind == .int && arg_sym.kind != .any_int) || if arg_sym.kind != elem_sym.kind && ((elem_sym.kind == .int && arg_sym.kind !=
(elem_sym.kind == .f64 && arg_sym.kind != .any_float)) { .any_int) || (elem_sym.kind == .f64 && arg_sym.kind != .any_float)) {
c.error('type mismatch, should use `$elem_sym.name`', arg_expr.position()) c.error('type mismatch, should use `$elem_sym.name`', arg_expr.position())
} }
} }
@ -838,8 +838,10 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
if exp_arg_sym.kind == .string && got_arg_sym.has_method('str') { if exp_arg_sym.kind == .string && got_arg_sym.has_method('str') {
continue continue
} }
c.error('cannot use type `$got_arg_sym.str()` as type `$exp_arg_sym.str()` in argument ${i+1} to `${left_type_sym.name}.$method_name`', if got_arg_typ != table.void_type {
call_expr.pos) c.error('cannot use type `$got_arg_sym.str()` as type `$exp_arg_sym.str()` in argument ${i+1} to `${left_type_sym.name}.$method_name`',
call_expr.pos)
}
} }
} }
// TODO: typ optimize.. this node can get processed more than once // TODO: typ optimize.. this node can get processed more than once
@ -1207,7 +1209,9 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
return field.typ return field.typ
} }
if sym.kind != .struct_ { if sym.kind != .struct_ {
c.error('`$sym.name` is not a struct', selector_expr.pos) if sym.kind != .placeholder {
c.error('`$sym.name` is not a struct', selector_expr.pos)
}
} else { } else {
c.error('type `$sym.name` has no field or method `$field_name`', selector_expr.pos) c.error('type `$sym.name` has no field or method `$field_name`', selector_expr.pos)
} }
@ -1731,7 +1735,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
} }
value_type := c.table.value_type(typ) value_type := c.table.value_type(typ)
if value_type == table.void_type || typ.has_flag(.optional) { if value_type == table.void_type || typ.has_flag(.optional) {
c.error('for in: cannot index `${c.table.type_to_str(typ)}`', it.cond.position()) if typ != table.void_type {
c.error('for in: cannot index `${c.table.type_to_str(typ)}`', it.cond.position())
}
} }
it.cond_type = typ it.cond_type = typ
it.kind = sym.kind it.kind = sym.kind
@ -1849,6 +1855,10 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
type_sym := c.table.get_type_symbol(node.typ) type_sym := c.table.get_type_symbol(node.typ)
if expr_type_sym.kind == .sum_type { if expr_type_sym.kind == .sum_type {
info := expr_type_sym.info as table.SumType info := expr_type_sym.info as table.SumType
if type_sym.kind == .placeholder {
// Unknown type used in the right part of `as`
c.error('unknown type `$type_sym.name`', node.pos)
}
if node.typ !in info.variants { if node.typ !in info.variants {
c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos) c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos)
// c.error('only $info.variants can be casted to `$typ`', it.pos) // c.error('only $info.variants can be casted to `$typ`', it.pos)

View File

@ -310,7 +310,7 @@ pub fn (mut g Gen) write_typeof_functions() {
g.writeln('// >> typeof() support for sum types') g.writeln('// >> typeof() support for sum types')
for typ in g.table.types { for typ in g.table.types {
if typ.kind == .sum_type { if typ.kind == .sum_type {
sum_info := typ.info as table.SumType sum_info := typ.info as table.SumTypee
tidx := g.table.find_type_idx(typ.name) tidx := g.table.find_type_idx(typ.name)
g.writeln('char * v_typeof_sumtype_${tidx}(int sidx) { /* $typ.name */ ') g.writeln('char * v_typeof_sumtype_${tidx}(int sidx) { /* $typ.name */ ')
g.writeln(' switch(sidx) {') g.writeln(' switch(sidx) {')