Skip to content

Commit

Permalink
checker: fix assign check, when rechecking for another concrete type (v…
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Dec 20, 2024
1 parent 8f684c7 commit 052e5af
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 5 deletions.
12 changes: 11 additions & 1 deletion vlib/v/checker/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,17 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
node.right_types << c.check_expr_option_or_result_call(node.right[i],
right_type)
}
} else {
// on generic recheck phase it might be needed to resolve the rhs again
if i < node.right.len && c.comptime.has_comptime_expr(node.right[i]) {
mut expr := mut node.right[i]
old_inside_recheck := c.inside_recheck
c.inside_recheck = true
right_type := c.expr(mut expr)
node.right_types[i] = c.check_expr_option_or_result_call(node.right[i],
right_type)
c.inside_recheck = old_inside_recheck
}
}
mut right := if i < node.right.len { node.right[i] } else { node.right[0] }
mut right_type := node.right_types[i]
Expand Down Expand Up @@ -494,7 +505,6 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
if (left.is_map || left.is_farray) && left.is_setter {
left.recursive_mapset_is_setter(true)
}

right_type = c.comptime.get_type_or_default(right, right_type)
}
if mut left is ast.InfixExpr {
Expand Down
3 changes: 2 additions & 1 deletion vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub mut:
is_builtin_mod bool // true inside the 'builtin', 'os' or 'strconv' modules; TODO: remove the need for special casing this
is_just_builtin_mod bool // true only inside 'builtin'
is_generated bool // true for `@[generated] module xyz` .v files
inside_recheck bool // true when rechecking rhs assign statement
inside_unsafe bool // true inside `unsafe {}` blocks
inside_const bool // true inside `const ( ... )` blocks
inside_anon_fn bool // true inside `fn() { ... }()`
Expand Down Expand Up @@ -1774,7 +1775,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
}

if has_field {
is_used_outside := sym.mod != c.mod
is_used_outside := !c.inside_recheck && sym.mod != c.mod
if is_used_outside && !field.is_pub && sym.language != .c {
unwrapped_sym := c.table.sym(c.unwrap_generic(typ))
c.error('field `${unwrapped_sym.name}.${field_name}` is not public', node.pos)
Expand Down
12 changes: 12 additions & 0 deletions vlib/v/comptime/comptimeinfo.v
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ pub fn (mut ct ComptimeInfo) is_comptime_expr(node ast.Expr) bool {
|| node is ast.ComptimeSelector
}

// has_comptime_expr checks if the expr contains some comptime expr
@[inline]
pub fn (mut ct ComptimeInfo) has_comptime_expr(node ast.Expr) bool {
return (node is ast.Ident && node.ct_expr)
|| (node is ast.IndexExpr && ct.has_comptime_expr(node.left))
|| node is ast.ComptimeSelector
|| (node is ast.SelectorExpr && ct.has_comptime_expr(node.expr))
|| (node is ast.InfixExpr && (ct.has_comptime_expr(node.left)
|| ct.has_comptime_expr(node.right)))
}

// is_comptime checks if the node is related to a comptime marked variable
@[inline]
pub fn (mut ct ComptimeInfo) is_comptime(node ast.Expr) bool {
Expand Down Expand Up @@ -100,6 +111,7 @@ pub fn (mut ct ComptimeInfo) get_expr_type_or_default(node ast.Expr, default_typ
}

// get_type_or_default retries the comptime value if the AST node is related to comptime otherwise default_typ is returned
@[inline]
pub fn (mut ct ComptimeInfo) get_type_or_default(node ast.Expr, default_typ ast.Type) ast.Type {
match node {
ast.Ident {
Expand Down
44 changes: 44 additions & 0 deletions vlib/v/tests/generics/generic_selector_indexexpr_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module main

pub struct Vector[T] {
n int
values []T
}

pub fn Vector.new[T](v []T) Vector[T] {
return Vector[T]{
n: v.len
values: v
}
}

pub fn (v Vector[T]) str() string {
return v.values.str()
}

pub fn (v Vector[T]) + (u Vector[T]) Vector[T] {
assert v.n == u.n
return Vector[T]{
n: v.n
values: []T{len: v.n, init: T(v.values[index] + u.values[index])}
}
}

pub fn (v Vector[T]) dot(u Vector[T]) T {
assert v.n == u.n
mut sum := T(0)
for i in 0 .. v.n {
sum += v.values[i] * u.values[i]
}
return sum
}

fn test_main() {
v := Vector.new[f64]([1.0, 2, 3])
vdotv := v.dot(v)
assert vdotv == 14.0

u := Vector.new[int]([1, 2, 3])
udotu := u.dot(u)
assert udotu == 14
}
12 changes: 9 additions & 3 deletions vlib/x/json2/decoder2/decode_sumtype.v
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ fn (mut decoder Decoder) get_decoded_sumtype_workaround[T](initialized_sumtype T
if initialized_sumtype is v {
// workaround for auto generated function considering sumtype as array
unsafe {
mut val := initialized_sumtype
decoder.decode_value(mut val)!
return T(val)
$if initialized_sumtype is $map {
mut val := initialized_sumtype.clone()
decoder.decode_value(mut val)!
return T(val)
} $else {
mut val := initialized_sumtype
decoder.decode_value(mut val)!
return T(val)
}
}
}
}
Expand Down

0 comments on commit 052e5af

Please sign in to comment.