mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
This commit is contained in:
parent
b60966cd10
commit
52cd6276b3
6 changed files with 58 additions and 0 deletions
|
@ -187,6 +187,11 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
&& c.table.sym(left_type).kind in [.array, .map, .struct]
|
||||
}
|
||||
if c.comptime.comptime_for_field_var != '' && mut left is ast.ComptimeSelector {
|
||||
if c.comptime.has_different_types && node.right[i].is_literal()
|
||||
&& !c.comptime.inside_comptime_if {
|
||||
c.error('mismatched types: check field type with \$if to avoid this problem',
|
||||
node.right[i].pos())
|
||||
}
|
||||
left_type = c.comptime.comptime_for_field_type
|
||||
c.expected_type = c.unwrap_generic(left_type)
|
||||
}
|
||||
|
|
|
@ -271,6 +271,8 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
|||
return
|
||||
}
|
||||
}
|
||||
has_different_types := fields.len > 1
|
||||
&& !fields.all(c.check_basic(it.typ, fields[0].typ))
|
||||
for field in fields {
|
||||
c.push_new_comptime_info()
|
||||
c.comptime.inside_comptime_for = true
|
||||
|
@ -283,6 +285,7 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
|||
c.type_resolver.update_ct_type(node.val_var, c.field_data_type)
|
||||
c.type_resolver.update_ct_type('${node.val_var}.typ', node.typ)
|
||||
c.comptime.comptime_for_field_type = field.typ
|
||||
c.comptime.has_different_types = has_different_types
|
||||
c.stmts(mut node.stmts)
|
||||
|
||||
unwrapped_expr_type := c.unwrap_generic(field.typ)
|
||||
|
@ -809,6 +812,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
|
|||
} else if cond.left in [ast.Ident, ast.SelectorExpr, ast.TypeNode] {
|
||||
// `$if method.type is string`
|
||||
c.expr(mut cond.left)
|
||||
c.comptime.inside_comptime_if = true
|
||||
if mut cond.left is ast.SelectorExpr && cond.right is ast.ComptimeType {
|
||||
comptime_type := cond.right as ast.ComptimeType
|
||||
if c.comptime.is_comptime_selector_type(cond.left) {
|
||||
|
@ -1075,6 +1079,8 @@ fn (mut c Checker) push_new_comptime_info() {
|
|||
c.type_resolver.info_stack << type_resolver.ResolverInfo{
|
||||
saved_type_map: c.type_resolver.type_map.clone()
|
||||
inside_comptime_for: c.comptime.inside_comptime_for
|
||||
inside_comptime_if: c.comptime.inside_comptime_if
|
||||
has_different_types: c.comptime.has_different_types
|
||||
comptime_for_variant_var: c.comptime.comptime_for_variant_var
|
||||
comptime_for_field_var: c.comptime.comptime_for_field_var
|
||||
comptime_for_field_type: c.comptime.comptime_for_field_type
|
||||
|
@ -1091,6 +1097,8 @@ fn (mut c Checker) pop_comptime_info() {
|
|||
old := c.type_resolver.info_stack.pop()
|
||||
c.type_resolver.type_map = old.saved_type_map.clone()
|
||||
c.comptime.inside_comptime_for = old.inside_comptime_for
|
||||
c.comptime.inside_comptime_if = old.inside_comptime_if
|
||||
c.comptime.has_different_types = old.has_different_types
|
||||
c.comptime.comptime_for_variant_var = old.comptime_for_variant_var
|
||||
c.comptime.comptime_for_field_var = old.comptime_for_field_var
|
||||
c.comptime.comptime_for_field_type = old.comptime_for_field_type
|
||||
|
|
|
@ -53,6 +53,10 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
mut skip_state := ComptimeBranchSkipState.unknown
|
||||
mut found_branch := false // Whether a matching branch was found- skip the rest
|
||||
mut is_comptime_type_is_expr := false // if `$if T is string`
|
||||
last_in_comptime_if := c.comptime.inside_comptime_if
|
||||
defer {
|
||||
c.comptime.inside_comptime_if = last_in_comptime_if
|
||||
}
|
||||
for i in 0 .. node.branches.len {
|
||||
mut branch := node.branches[i]
|
||||
if branch.cond is ast.ParExpr && !c.pref.translated && !c.file.is_translated {
|
||||
|
|
7
vlib/v/checker/tests/comptime_selector_assign.out
Normal file
7
vlib/v/checker/tests/comptime_selector_assign.out
Normal file
|
@ -0,0 +1,7 @@
|
|||
vlib/v/checker/tests/comptime_selector_assign.vv:18:24: error: mismatched types: check field type with $if to avoid this problem
|
||||
16 | typ.$(field.name) = 2
|
||||
17 | }
|
||||
18 | typ.$(field.name) = 3
|
||||
| ^
|
||||
19 | }
|
||||
20 | }
|
31
vlib/v/checker/tests/comptime_selector_assign.vv
Normal file
31
vlib/v/checker/tests/comptime_selector_assign.vv
Normal file
|
@ -0,0 +1,31 @@
|
|||
import x.json2 { Any, raw_decode }
|
||||
|
||||
struct Income {
|
||||
mut:
|
||||
email string
|
||||
code int
|
||||
}
|
||||
|
||||
pub fn structuring[T](res Any) T {
|
||||
mut typ := T{}
|
||||
res_map := res.as_map()
|
||||
|
||||
$for field in T.fields {
|
||||
if field.name in res_map {
|
||||
$if field.typ is int {
|
||||
typ.$(field.name) = 2
|
||||
}
|
||||
typ.$(field.name) = 3
|
||||
}
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
||||
fn main() {
|
||||
res := raw_decode('{
|
||||
"email": ["sdvsdv", "sds"],
|
||||
"code": 12
|
||||
}')!.as_map()
|
||||
|
||||
structuring[Income](res)
|
||||
}
|
|
@ -15,6 +15,9 @@ pub mut:
|
|||
comptime_loop_id int
|
||||
// $for
|
||||
inside_comptime_for bool
|
||||
// $if
|
||||
inside_comptime_if bool
|
||||
has_different_types bool
|
||||
// .variants
|
||||
comptime_for_variant_var string
|
||||
// .fields
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue