ast, parser, checker: fix generic struct field with default struct value (#13158)

pull/13164/head
yuyi 2022-01-14 04:25:25 +08:00 committed by GitHub
parent 7fbd856bf8
commit 155f897270
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 6 deletions

View File

@ -405,6 +405,7 @@ pub:
pub mut:
unresolved bool
pre_comments []Comment
typ_str string
typ Type
update_expr Expr
update_expr_type Type

View File

@ -325,8 +325,17 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
}
}
// Check uninitialized refs/sum types
for field in info.fields {
if field.has_default_expr || field.name in inited_fields {
for i, field in info.fields {
if field.name in inited_fields {
continue
}
if field.has_default_expr {
if field.default_expr is ast.StructInit && field.default_expr_typ == 0 {
idx := c.table.find_type_idx(field.default_expr.typ_str)
if idx != 0 {
info.fields[i].default_expr_typ = ast.new_type(idx)
}
}
continue
}
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !node.has_update_expr

View File

@ -126,7 +126,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
mut expr := ast.empty_expr()
if p.tok.kind == .name && p.peek_tok.kind == .colon {
// `foo(key:val, key2:val2)`
expr = p.struct_init(true) // short_syntax:true
expr = p.struct_init(p.mod + '.' + p.tok.lit, true) // short_syntax:true
} else {
expr = p.expr(0)
}

View File

@ -2288,11 +2288,11 @@ pub fn (mut p Parser) name_expr() ast.Expr {
p.check(.rcbr)
return map_init
}
return p.struct_init(false) // short_syntax: false
return p.struct_init(p.mod + '.' + p.tok.lit, false) // short_syntax: false
} else if p.peek_tok.kind == .lcbr && p.inside_if && lit0_is_capital && !known_var
&& language == .v {
// if a == Foo{} {...}
return p.struct_init(false)
return p.struct_init(p.mod + '.' + p.tok.lit, false)
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
// T.name
if p.is_generic_name() {

View File

@ -335,7 +335,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
}
}
fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
fn (mut p Parser) struct_init(typ_str string, short_syntax bool) ast.StructInit {
first_pos := (if short_syntax && p.prev_tok.kind == .lcbr { p.prev_tok } else { p.tok }).position()
typ := if short_syntax { ast.void_type } else { p.parse_type() }
p.expr_mod = ''
@ -416,6 +416,7 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
p.is_amp = saved_is_amp
return ast.StructInit{
unresolved: typ.has_flag(.generic)
typ_str: typ_str
typ: typ
fields: fields
update_expr: update_expr

View File

@ -0,0 +1,22 @@
module main
struct None {}
type OptError = None | string
struct Opt<T> {
value T
error OptError = None{}
}
struct MessageModify {
text Opt<string>
}
fn test_generic_struct_field_with_default_struct_value() {
edit_query := MessageModify{Opt<string>{
value: 'Hello there!'
}}
println(edit_query)
assert edit_query.text.value == 'Hello there!'
}