mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
This commit is contained in:
parent
3bf8f4232a
commit
915ff40926
8 changed files with 54 additions and 4 deletions
|
@ -876,13 +876,20 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
|
|||
node.pos)
|
||||
}
|
||||
} else {
|
||||
// allow `t.$(field.name) = 0` where `t.$(field.name)` is a enum
|
||||
if c.comptime.comptime_for_field_var != '' && left is ast.ComptimeSelector {
|
||||
field_sym := c.table.sym(c.unwrap_generic(c.comptime.comptime_for_field_type))
|
||||
field_type := c.unwrap_generic(c.comptime.comptime_for_field_type)
|
||||
field_sym := c.table.sym(field_type)
|
||||
|
||||
// allow `t.$(field.name) = 0` where `t.$(field.name)` is a enum
|
||||
if field_sym.kind == .enum && !right_type.is_int() {
|
||||
c.error('enums can only be assigned `int` values', right.pos())
|
||||
}
|
||||
// disallow invalid `t.$(field.name)` type assignment
|
||||
if !c.check_types(field_type, right_type) && !(c.inside_x_matches_type
|
||||
|| field_sym.kind == .enum) {
|
||||
c.error('cannot assign to `${left}`: ${c.expected_msg(right_type,
|
||||
field_type)}', right.pos())
|
||||
}
|
||||
} else {
|
||||
if right_type_unwrapped != ast.void_type {
|
||||
if !var_option || (var_option && right_type_unwrapped != ast.none_type) {
|
||||
|
|
|
@ -89,6 +89,7 @@ pub mut:
|
|||
inside_fn_arg bool // `a`, `b` in `a.f(b)`
|
||||
inside_ct_attr bool // true inside `[if expr]`
|
||||
inside_x_is_type bool // true inside the Type expression of `if x is Type {`
|
||||
inside_x_matches_type bool // true inside the match branch of `match x.type { Type {} }`
|
||||
anon_struct_should_be_mut bool // true when `mut var := struct { ... }` is used
|
||||
inside_generic_struct_init bool
|
||||
inside_integer_literal_cast bool // true inside `int(123)`
|
||||
|
@ -192,6 +193,7 @@ fn (mut c Checker) reset_checker_state_at_start_of_new_file() {
|
|||
c.inside_fn_arg = false
|
||||
c.inside_ct_attr = false
|
||||
c.inside_x_is_type = false
|
||||
c.inside_x_matches_type = false
|
||||
c.inside_integer_literal_cast = false
|
||||
c.skip_flags = false
|
||||
c.fn_level = 0
|
||||
|
|
|
@ -274,6 +274,7 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
|||
has_different_types := fields.len > 1
|
||||
&& !fields.all(c.check_basic(it.typ, fields[0].typ))
|
||||
for field in fields {
|
||||
prev_inside_x_matches_type := c.inside_x_matches_type
|
||||
c.push_new_comptime_info()
|
||||
c.comptime.inside_comptime_for = true
|
||||
c.table.used_features.comptime_for = true
|
||||
|
@ -301,6 +302,7 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
|||
}
|
||||
}
|
||||
c.pop_comptime_info()
|
||||
c.inside_x_matches_type = prev_inside_x_matches_type
|
||||
}
|
||||
} else if node.typ != ast.void_type && c.table.generic_type_names(node.typ).len == 0
|
||||
&& sym.kind != .placeholder {
|
||||
|
|
|
@ -414,6 +414,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
|
|||
}
|
||||
continue
|
||||
}
|
||||
is_type_node := expr is ast.TypeNode
|
||||
match mut expr {
|
||||
ast.TypeNode {
|
||||
key = c.table.type_to_str(expr.typ)
|
||||
|
@ -438,6 +439,9 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
|
|||
c.error('match case `${key}` is handled more than once', branch.pos)
|
||||
}
|
||||
c.expected_type = node.cond_type
|
||||
if is_type_node {
|
||||
c.inside_x_matches_type = true
|
||||
}
|
||||
expr_type := c.expr(mut expr)
|
||||
if expr_type.idx() == 0 {
|
||||
// parser failed, stop checking
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
vlib/v/checker/tests/assign_enum_at_comptime.vv:13:21: error: enums can only be assigned `int` values
|
||||
11 |
|
||||
11 |
|
||||
12 | $for field in TestStruct.fields {
|
||||
13 | t.$(field.name) = '1'
|
||||
| ~~~
|
||||
14 | }
|
||||
15 | }
|
||||
15 | }
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/comptime_field_name_assign_incorrect_type_err.vv:11:25: error: cannot assign to `t.$(field.name)`: expected `int`, not `string`
|
||||
9 | mut t := T{}
|
||||
10 | $for field in T.fields {
|
||||
11 | t.$(field.name) = data[field.name]
|
||||
| ~~~~~~~~~~~~
|
||||
12 | }
|
||||
13 | return t
|
|
@ -0,0 +1,21 @@
|
|||
module main
|
||||
|
||||
struct Record {
|
||||
mut:
|
||||
f1 int
|
||||
}
|
||||
|
||||
fn map_data[T](data map[string]string) T {
|
||||
mut t := T{}
|
||||
$for field in T.fields {
|
||||
t.$(field.name) = data[field.name]
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut data := map[string]string{}
|
||||
data['f1'] = '123'
|
||||
t := map_data[Record](data)
|
||||
println('bug1 : ${t}')
|
||||
}
|
|
@ -5,3 +5,10 @@ vlib/v/checker/tests/comptime_selector_assign.vv:18:24: error: mismatched types:
|
|||
| ^
|
||||
19 | }
|
||||
20 | }
|
||||
vlib/v/checker/tests/comptime_selector_assign.vv:18:24: error: cannot assign to `typ.$(field.name)`: expected `string`, not `int literal`
|
||||
16 | typ.$(field.name) = 2
|
||||
17 | }
|
||||
18 | typ.$(field.name) = 3
|
||||
| ^
|
||||
19 | }
|
||||
20 | }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue