diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 8d33f9a7b1..36df60b2fb 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -405,6 +405,7 @@ pub: pub mut: unresolved bool pre_comments []Comment + typ_str string typ Type update_expr Expr update_expr_type Type diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 44afaf77be..42d158b435 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -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 diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index e3c839c23d..aaefac7c30 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -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) } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index d8bc533684..8f7aa9d55b 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -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() { diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 5960f17122..334eec0a0b 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -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 diff --git a/vlib/v/tests/generics_struct_field_with_default_struct_value_test.v b/vlib/v/tests/generics_struct_field_with_default_struct_value_test.v new file mode 100644 index 0000000000..a4b97b4931 --- /dev/null +++ b/vlib/v/tests/generics_struct_field_with_default_struct_value_test.v @@ -0,0 +1,22 @@ +module main + +struct None {} + +type OptError = None | string + +struct Opt { + value T + error OptError = None{} +} + +struct MessageModify { + text Opt +} + +fn test_generic_struct_field_with_default_struct_value() { + edit_query := MessageModify{Opt{ + value: 'Hello there!' + }} + println(edit_query) + assert edit_query.text.value == 'Hello there!' +}