checker: make struct_init check more robust

pull/4267/head
lutherwenxu 2020-04-06 23:39:52 +08:00 committed by GitHub
parent 4d5fe14968
commit e8b26b1b8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 29 additions and 11 deletions

View File

@ -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)