ast, parser, checker: fix generic struct field with default struct value (#13158)
parent
7fbd856bf8
commit
155f897270
|
@ -405,6 +405,7 @@ pub:
|
|||
pub mut:
|
||||
unresolved bool
|
||||
pre_comments []Comment
|
||||
typ_str string
|
||||
typ Type
|
||||
update_expr Expr
|
||||
update_expr_type Type
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!'
|
||||
}
|
Loading…
Reference in New Issue