ast, parser, checker: fix generic struct field with default struct value (#13158)
parent
7fbd856bf8
commit
155f897270
|
@ -405,6 +405,7 @@ pub:
|
||||||
pub mut:
|
pub mut:
|
||||||
unresolved bool
|
unresolved bool
|
||||||
pre_comments []Comment
|
pre_comments []Comment
|
||||||
|
typ_str string
|
||||||
typ Type
|
typ Type
|
||||||
update_expr Expr
|
update_expr Expr
|
||||||
update_expr_type Type
|
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
|
// Check uninitialized refs/sum types
|
||||||
for field in info.fields {
|
for i, field in info.fields {
|
||||||
if field.has_default_expr || field.name in inited_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
|
continue
|
||||||
}
|
}
|
||||||
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !node.has_update_expr
|
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()
|
mut expr := ast.empty_expr()
|
||||||
if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
||||||
// `foo(key:val, key2:val2)`
|
// `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 {
|
} else {
|
||||||
expr = p.expr(0)
|
expr = p.expr(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2288,11 +2288,11 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
return map_init
|
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
|
} else if p.peek_tok.kind == .lcbr && p.inside_if && lit0_is_capital && !known_var
|
||||||
&& language == .v {
|
&& language == .v {
|
||||||
// if a == Foo{} {...}
|
// 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) {
|
} else if p.peek_tok.kind == .dot && (lit0_is_capital && !known_var && language == .v) {
|
||||||
// T.name
|
// T.name
|
||||||
if p.is_generic_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()
|
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() }
|
typ := if short_syntax { ast.void_type } else { p.parse_type() }
|
||||||
p.expr_mod = ''
|
p.expr_mod = ''
|
||||||
|
@ -416,6 +416,7 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
|
||||||
p.is_amp = saved_is_amp
|
p.is_amp = saved_is_amp
|
||||||
return ast.StructInit{
|
return ast.StructInit{
|
||||||
unresolved: typ.has_flag(.generic)
|
unresolved: typ.has_flag(.generic)
|
||||||
|
typ_str: typ_str
|
||||||
typ: typ
|
typ: typ
|
||||||
fields: fields
|
fields: fields
|
||||||
update_expr: update_expr
|
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