mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42: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]
|
&& 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.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
|
left_type = c.comptime.comptime_for_field_type
|
||||||
c.expected_type = c.unwrap_generic(left_type)
|
c.expected_type = c.unwrap_generic(left_type)
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,6 +271,8 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
has_different_types := fields.len > 1
|
||||||
|
&& !fields.all(c.check_basic(it.typ, fields[0].typ))
|
||||||
for field in fields {
|
for field in fields {
|
||||||
c.push_new_comptime_info()
|
c.push_new_comptime_info()
|
||||||
c.comptime.inside_comptime_for = true
|
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, c.field_data_type)
|
||||||
c.type_resolver.update_ct_type('${node.val_var}.typ', node.typ)
|
c.type_resolver.update_ct_type('${node.val_var}.typ', node.typ)
|
||||||
c.comptime.comptime_for_field_type = field.typ
|
c.comptime.comptime_for_field_type = field.typ
|
||||||
|
c.comptime.has_different_types = has_different_types
|
||||||
c.stmts(mut node.stmts)
|
c.stmts(mut node.stmts)
|
||||||
|
|
||||||
unwrapped_expr_type := c.unwrap_generic(field.typ)
|
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] {
|
} else if cond.left in [ast.Ident, ast.SelectorExpr, ast.TypeNode] {
|
||||||
// `$if method.type is string`
|
// `$if method.type is string`
|
||||||
c.expr(mut cond.left)
|
c.expr(mut cond.left)
|
||||||
|
c.comptime.inside_comptime_if = true
|
||||||
if mut cond.left is ast.SelectorExpr && cond.right is ast.ComptimeType {
|
if mut cond.left is ast.SelectorExpr && cond.right is ast.ComptimeType {
|
||||||
comptime_type := cond.right as ast.ComptimeType
|
comptime_type := cond.right as ast.ComptimeType
|
||||||
if c.comptime.is_comptime_selector_type(cond.left) {
|
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{
|
c.type_resolver.info_stack << type_resolver.ResolverInfo{
|
||||||
saved_type_map: c.type_resolver.type_map.clone()
|
saved_type_map: c.type_resolver.type_map.clone()
|
||||||
inside_comptime_for: c.comptime.inside_comptime_for
|
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_variant_var: c.comptime.comptime_for_variant_var
|
||||||
comptime_for_field_var: c.comptime.comptime_for_field_var
|
comptime_for_field_var: c.comptime.comptime_for_field_var
|
||||||
comptime_for_field_type: c.comptime.comptime_for_field_type
|
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()
|
old := c.type_resolver.info_stack.pop()
|
||||||
c.type_resolver.type_map = old.saved_type_map.clone()
|
c.type_resolver.type_map = old.saved_type_map.clone()
|
||||||
c.comptime.inside_comptime_for = old.inside_comptime_for
|
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_variant_var = old.comptime_for_variant_var
|
||||||
c.comptime.comptime_for_field_var = old.comptime_for_field_var
|
c.comptime.comptime_for_field_var = old.comptime_for_field_var
|
||||||
c.comptime.comptime_for_field_type = old.comptime_for_field_type
|
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 skip_state := ComptimeBranchSkipState.unknown
|
||||||
mut found_branch := false // Whether a matching branch was found- skip the rest
|
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`
|
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 {
|
for i in 0 .. node.branches.len {
|
||||||
mut branch := node.branches[i]
|
mut branch := node.branches[i]
|
||||||
if branch.cond is ast.ParExpr && !c.pref.translated && !c.file.is_translated {
|
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
|
comptime_loop_id int
|
||||||
// $for
|
// $for
|
||||||
inside_comptime_for bool
|
inside_comptime_for bool
|
||||||
|
// $if
|
||||||
|
inside_comptime_if bool
|
||||||
|
has_different_types bool
|
||||||
// .variants
|
// .variants
|
||||||
comptime_for_variant_var string
|
comptime_for_variant_var string
|
||||||
// .fields
|
// .fields
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue