From e8b26b1b8dfd1e0b7fb4f862fc91e4a986067fa9 Mon Sep 17 00:00:00 2001 From: lutherwenxu Date: Mon, 6 Apr 2020 23:39:52 +0800 Subject: [PATCH] checker: make struct_init check more robust --- vlib/v/checker/checker.v | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index bddfb94aa5..989cbd58eb 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -89,20 +89,38 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { } mut inited_fields := []string for i, expr in struct_init.exprs { + if is_short_syntax && i >= info.fields.len { + // It doesn't make sense to check for fields that don't exist. + // We should just stop here. + break + } // struct_field info. field_name := if is_short_syntax { info.fields[i].name } else { struct_init.fields[i] } - mut field := info.fields[i] - inited_fields << field_name - mut found_field := false - for f in info.fields { - if f.name == field_name { - field = f - found_field = true - break - } + if field_name in inited_fields { + c.error('struct init: duplicate field `$field_name` for struct `$typ_sym.name`', struct_init.pos) + continue } - if !found_field { - c.error('struct init: no such field `$field_name` for struct `$typ_sym.name`', struct_init.pos) + inited_fields << field_name + mut field := if is_short_syntax { + info.fields[i] + } else { + // There is no guarantee that `i` will not be out of bounds of `info.fields` + // So we just use an empty field as placeholder here. + table.Field{} + } + if !is_short_syntax { + mut found_field := false + for f in info.fields { + if f.name == field_name { + field = f + found_field = true + break + } + } + if !found_field { + c.error('struct init: no such field `$field_name` for struct `$typ_sym.name`', struct_init.pos) + continue + } } c.expected_type = field.typ expr_type := c.expr(expr)