mirror of
https://github.com/vlang/v.git
synced 2025-09-15 10:27:19 -04:00
ast, parser, fmt: fix alias array no cast init (#20898)
This commit is contained in:
parent
cf7dcfe287
commit
1733dab29b
@ -1492,6 +1492,7 @@ pub mut:
|
||||
elem_type Type // element type
|
||||
init_type Type // init: value type
|
||||
typ Type // array type
|
||||
alias_type Type // alias type
|
||||
}
|
||||
|
||||
pub struct ArrayDecompose {
|
||||
|
@ -1710,7 +1710,11 @@ pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
|
||||
if node.exprs.len == 0 && node.typ != 0 && node.typ != ast.void_type {
|
||||
// `x := []string{}`
|
||||
f.mark_types_import_as_used(node.typ)
|
||||
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||
if node.alias_type != ast.void_type {
|
||||
f.write(f.table.type_to_str_using_aliases(node.alias_type, f.mod2alias))
|
||||
} else {
|
||||
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
|
||||
}
|
||||
f.write('{')
|
||||
if node.has_len {
|
||||
f.write('len: ')
|
||||
|
@ -6,10 +6,9 @@ module parser
|
||||
import v.ast
|
||||
import v.token
|
||||
|
||||
fn (mut p Parser) array_init(is_option bool) ast.ArrayInit {
|
||||
fn (mut p Parser) array_init(is_option bool, alias_array_type ast.Type) ast.ArrayInit {
|
||||
first_pos := p.tok.pos()
|
||||
mut last_pos := p.tok.pos()
|
||||
p.check(.lsbr)
|
||||
mut array_type := ast.void_type
|
||||
mut elem_type := ast.void_type
|
||||
mut elem_type_pos := first_pos
|
||||
@ -22,103 +21,112 @@ fn (mut p Parser) array_init(is_option bool) ast.ArrayInit {
|
||||
mut has_init := false
|
||||
mut has_index := false
|
||||
mut init_expr := ast.empty_expr
|
||||
if p.tok.kind == .rsbr {
|
||||
last_pos = p.tok.pos()
|
||||
// []typ => `[]` and `typ` must be on the same line
|
||||
line_nr := p.tok.line_nr
|
||||
p.next()
|
||||
// []string
|
||||
if p.tok.kind in [.name, .amp, .lsbr, .question, .key_shared] && p.tok.line_nr == line_nr {
|
||||
elem_type_pos = p.tok.pos()
|
||||
elem_type = p.parse_type()
|
||||
// this is set here because it's a known type, others could be the
|
||||
// result of expr so we do those in checker
|
||||
if elem_type != 0 {
|
||||
idx := p.table.find_or_register_array(elem_type)
|
||||
if elem_type.has_flag(.generic) {
|
||||
array_type = ast.new_type(idx).set_flag(.generic)
|
||||
} else {
|
||||
array_type = ast.new_type(idx)
|
||||
if alias_array_type == ast.void_type {
|
||||
p.check(.lsbr)
|
||||
if p.tok.kind == .rsbr {
|
||||
last_pos = p.tok.pos()
|
||||
// []typ => `[]` and `typ` must be on the same line
|
||||
line_nr := p.tok.line_nr
|
||||
p.next()
|
||||
// []string
|
||||
if p.tok.kind in [.name, .amp, .lsbr, .question, .key_shared]
|
||||
&& p.tok.line_nr == line_nr {
|
||||
elem_type_pos = p.tok.pos()
|
||||
elem_type = p.parse_type()
|
||||
// this is set here because it's a known type, others could be the
|
||||
// result of expr so we do those in checker
|
||||
if elem_type != 0 {
|
||||
idx := p.table.find_or_register_array(elem_type)
|
||||
if elem_type.has_flag(.generic) {
|
||||
array_type = ast.new_type(idx).set_flag(.generic)
|
||||
} else {
|
||||
array_type = ast.new_type(idx)
|
||||
}
|
||||
if is_option {
|
||||
array_type = array_type.set_flag(.option)
|
||||
}
|
||||
has_type = true
|
||||
}
|
||||
if is_option {
|
||||
array_type = array_type.set_flag(.option)
|
||||
}
|
||||
has_type = true
|
||||
}
|
||||
}
|
||||
last_pos = p.tok.pos()
|
||||
} else {
|
||||
// [1,2,3] or [const]u8
|
||||
old_inside_array_lit := p.inside_array_lit
|
||||
p.inside_array_lit = true
|
||||
pre_cmnts = p.eat_comments()
|
||||
for i := 0; p.tok.kind !in [.rsbr, .eof]; i++ {
|
||||
exprs << p.expr(0)
|
||||
ecmnts << p.eat_comments()
|
||||
if p.tok.kind == .comma {
|
||||
p.next()
|
||||
}
|
||||
ecmnts.last() << p.eat_comments()
|
||||
}
|
||||
p.inside_array_lit = old_inside_array_lit
|
||||
line_nr := p.tok.line_nr
|
||||
last_pos = p.tok.pos()
|
||||
p.check(.rsbr)
|
||||
if exprs.len == 1 && p.tok.line_nr == line_nr
|
||||
&& (p.tok.kind in [.name, .amp, .question, .key_shared]
|
||||
|| (p.tok.kind == .lsbr && p.is_array_type())) {
|
||||
// [100]u8
|
||||
elem_type = p.parse_type()
|
||||
if p.table.sym(elem_type).name == 'byte' {
|
||||
p.error('`byte` has been deprecated in favor of `u8`: use `[10]u8{}` instead of `[10]byte{}`')
|
||||
}
|
||||
last_pos = p.tok.pos()
|
||||
is_fixed = true
|
||||
if p.tok.kind == .lcbr {
|
||||
p.next()
|
||||
if p.tok.kind != .rcbr {
|
||||
pos := p.tok.pos()
|
||||
n := p.check_name()
|
||||
if n != 'init' {
|
||||
if is_fixed {
|
||||
p.error_with_pos('`len` and `cap` are invalid attributes for fixed array dimension',
|
||||
pos)
|
||||
} else {
|
||||
p.error_with_pos('expected `init:`, not `${n}`', pos)
|
||||
}
|
||||
return ast.ArrayInit{}
|
||||
}
|
||||
p.check(.colon)
|
||||
has_init = true
|
||||
has_index = p.handle_index_variable(mut init_expr)
|
||||
} else {
|
||||
// [1,2,3] or [const]u8
|
||||
old_inside_array_lit := p.inside_array_lit
|
||||
p.inside_array_lit = true
|
||||
pre_cmnts = p.eat_comments()
|
||||
for i := 0; p.tok.kind !in [.rsbr, .eof]; i++ {
|
||||
exprs << p.expr(0)
|
||||
ecmnts << p.eat_comments()
|
||||
if p.tok.kind == .comma {
|
||||
p.next()
|
||||
}
|
||||
ecmnts.last() << p.eat_comments()
|
||||
}
|
||||
p.inside_array_lit = old_inside_array_lit
|
||||
line_nr := p.tok.line_nr
|
||||
last_pos = p.tok.pos()
|
||||
p.check(.rsbr)
|
||||
if exprs.len == 1 && p.tok.line_nr == line_nr
|
||||
&& (p.tok.kind in [.name, .amp, .question, .key_shared]
|
||||
|| (p.tok.kind == .lsbr && p.is_array_type())) {
|
||||
// [100]u8
|
||||
elem_type = p.parse_type()
|
||||
if p.table.sym(elem_type).name == 'byte' {
|
||||
p.error('`byte` has been deprecated in favor of `u8`: use `[10]u8{}` instead of `[10]byte{}`')
|
||||
}
|
||||
last_pos = p.tok.pos()
|
||||
p.check(.rcbr)
|
||||
is_fixed = true
|
||||
if p.tok.kind == .lcbr {
|
||||
p.next()
|
||||
if p.tok.kind != .rcbr {
|
||||
pos := p.tok.pos()
|
||||
n := p.check_name()
|
||||
if n != 'init' {
|
||||
if is_fixed {
|
||||
p.error_with_pos('`len` and `cap` are invalid attributes for fixed array dimension',
|
||||
pos)
|
||||
} else {
|
||||
p.error_with_pos('expected `init:`, not `${n}`', pos)
|
||||
}
|
||||
return ast.ArrayInit{}
|
||||
}
|
||||
p.check(.colon)
|
||||
has_init = true
|
||||
has_index = p.handle_index_variable(mut init_expr)
|
||||
}
|
||||
last_pos = p.tok.pos()
|
||||
p.check(.rcbr)
|
||||
} else {
|
||||
modifier := if is_option { '?' } else { '' }
|
||||
p.warn_with_pos('use e.g. `x := ${modifier}[1]Type{}` instead of `x := ${modifier}[1]Type`',
|
||||
first_pos.extend(last_pos))
|
||||
}
|
||||
} else {
|
||||
if p.tok.kind == .not {
|
||||
last_pos = p.tok.pos()
|
||||
is_fixed = true
|
||||
has_val = true
|
||||
p.next()
|
||||
}
|
||||
if p.tok.kind == .not && p.tok.line_nr == p.prev_tok.line_nr {
|
||||
last_pos = p.tok.pos()
|
||||
p.error_with_pos('use e.g. `[1, 2, 3]!` instead of `[1, 2, 3]!!`',
|
||||
last_pos)
|
||||
p.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
if exprs.len == 0 && p.tok.kind != .lcbr && has_type {
|
||||
if !p.pref.is_fmt {
|
||||
modifier := if is_option { '?' } else { '' }
|
||||
p.warn_with_pos('use e.g. `x := ${modifier}[1]Type{}` instead of `x := ${modifier}[1]Type`',
|
||||
p.warn_with_pos('use `x := ${modifier}[]Type{}` instead of `x := ${modifier}[]Type`',
|
||||
first_pos.extend(last_pos))
|
||||
}
|
||||
} else {
|
||||
if p.tok.kind == .not {
|
||||
last_pos = p.tok.pos()
|
||||
is_fixed = true
|
||||
has_val = true
|
||||
p.next()
|
||||
}
|
||||
if p.tok.kind == .not && p.tok.line_nr == p.prev_tok.line_nr {
|
||||
last_pos = p.tok.pos()
|
||||
p.error_with_pos('use e.g. `[1, 2, 3]!` instead of `[1, 2, 3]!!`', last_pos)
|
||||
p.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
if exprs.len == 0 && p.tok.kind != .lcbr && has_type {
|
||||
if !p.pref.is_fmt {
|
||||
modifier := if is_option { '?' } else { '' }
|
||||
p.warn_with_pos('use `x := ${modifier}[]Type{}` instead of `x := ${modifier}[]Type`',
|
||||
first_pos.extend(last_pos))
|
||||
}
|
||||
} else {
|
||||
array_type = (p.table.sym(alias_array_type).info as ast.Alias).parent_type
|
||||
elem_type = p.table.sym(array_type).array_info().elem_type
|
||||
p.next()
|
||||
}
|
||||
mut has_len := false
|
||||
mut has_cap := false
|
||||
@ -170,6 +178,7 @@ fn (mut p Parser) array_init(is_option bool) ast.ArrayInit {
|
||||
mod: p.mod
|
||||
elem_type: elem_type
|
||||
typ: array_type
|
||||
alias_type: alias_array_type
|
||||
exprs: exprs
|
||||
ecmnts: ecmnts
|
||||
pre_cmnts: pre_cmnts
|
||||
|
@ -216,10 +216,10 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr {
|
||||
pos: pos
|
||||
}
|
||||
} else {
|
||||
node = p.array_init(false)
|
||||
node = p.array_init(false, ast.void_type)
|
||||
}
|
||||
} else {
|
||||
node = p.array_init(false)
|
||||
node = p.array_init(false, ast.void_type)
|
||||
}
|
||||
}
|
||||
.key_none {
|
||||
|
@ -2543,6 +2543,19 @@ fn (mut p Parser) is_generic_cast() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
fn (mut p Parser) alias_array_type() ast.Type {
|
||||
full_name := p.prepend_mod(p.tok.lit)
|
||||
if idx := p.table.type_idxs[full_name] {
|
||||
sym := p.table.sym(idx)
|
||||
if sym.info is ast.Alias {
|
||||
if p.table.sym(sym.info.parent_type).kind == .array {
|
||||
return idx
|
||||
}
|
||||
}
|
||||
}
|
||||
return ast.void_type
|
||||
}
|
||||
|
||||
@[direct_array_access]
|
||||
fn (mut p Parser) name_expr() ast.Expr {
|
||||
prev_tok_kind := p.prev_tok.kind
|
||||
@ -2840,7 +2853,13 @@ fn (mut p Parser) name_expr() ast.Expr {
|
||||
&& (!p.inside_match || (p.inside_select && prev_tok_kind == .arrow && lit0_is_capital))
|
||||
&& !p.inside_match_case && (!p.inside_if || p.inside_select)
|
||||
&& (!p.inside_for || p.inside_select) {
|
||||
return p.struct_init(p.mod + '.' + p.tok.lit, .normal, is_option) // short_syntax: false
|
||||
alias_array_type := p.alias_array_type()
|
||||
if alias_array_type != ast.void_type {
|
||||
return p.array_init(is_option, alias_array_type)
|
||||
} else {
|
||||
// `if a == Foo{} {...}` or `match foo { Foo{} {...} }`
|
||||
return p.struct_init(p.mod + '.' + p.tok.lit, .normal, is_option)
|
||||
}
|
||||
} else if p.peek_tok.kind == .lcbr
|
||||
&& ((p.inside_if && lit0_is_capital && p.tok.lit.len > 1 && !known_var && language == .v)
|
||||
|| (p.inside_match_case && p.tok.kind == .name && p.peek_tok.is_next_to(p.tok))) {
|
||||
@ -2957,7 +2976,7 @@ fn (mut p Parser) name_expr() ast.Expr {
|
||||
p.expr_mod = ''
|
||||
return node
|
||||
} else if is_option && p.tok.kind == .lsbr {
|
||||
return p.array_init(is_option)
|
||||
return p.array_init(is_option, ast.void_type)
|
||||
} else if !known_var && language == .v && p.peek_tok.kind == .dot && !p.pref.is_fmt {
|
||||
peek_tok2 := p.peek_token(2)
|
||||
peek_tok3 := p.peek_token(3)
|
||||
|
12
vlib/v/tests/alias_array_no_cast_init_test.v
Normal file
12
vlib/v/tests/alias_array_no_cast_init_test.v
Normal file
@ -0,0 +1,12 @@
|
||||
pub type Labels = [][]int
|
||||
|
||||
pub fn new_labels(width int, height int) Labels {
|
||||
mut labels := Labels{len: height, init: []int{len: width}}
|
||||
return labels
|
||||
}
|
||||
|
||||
fn test_alias_array_no_cast_init() {
|
||||
mut labels := new_labels(2, 2)
|
||||
println(labels)
|
||||
assert labels == [[0, 0], [0, 0]]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user