Skip to content

Commit f2b15d0

Browse files
committed
checker, cgen: fix more issues
1 parent edbe430 commit f2b15d0

2 files changed

Lines changed: 21 additions & 13 deletions

File tree

vlib/v/checker/checker.v

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,9 +1408,16 @@ fn (mut c Checker) fail_if_immutable_to_mutable(left_type ast.Type, right_type a
14081408
}
14091409
match right {
14101410
ast.CastExpr {
1411-
if c.table.final_sym(c.unwrap_generic(right.typ)).kind == .interface {
1412-
mut expr := right.expr
1413-
c.fail_if_immutable(mut expr)
1411+
iface_sym := c.table.final_sym(c.unwrap_generic(right.typ))
1412+
if iface_sym.kind == .interface && iface_sym.info is ast.Interface {
1413+
// Only fail if the interface has mutable fields; casting an immutable
1414+
// reference to a read-only interface is safe because no mutation is
1415+
// possible through the interface.
1416+
has_mut_fields := iface_sym.info.fields.any(it.is_mut)
1417+
if has_mut_fields {
1418+
mut expr := right.expr
1419+
c.fail_if_immutable(mut expr)
1420+
}
14141421
}
14151422
}
14161423
ast.Ident {

vlib/v/gen/c/cgen.v

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2072,10 +2072,6 @@ fn (mut g Gen) cc_type(typ ast.Type, is_prefix_struct bool) string {
20722072
}
20732073
}
20742074
}
2075-
if sym.kind == .enum && sym.info is ast.Enum && sym.info.is_typedef {
2076-
// @[typedef] enums are defined in a C header; use the original name without module prefix.
2077-
styp = sym.name.all_after_last('.')
2078-
}
20792075
return styp
20802076
}
20812077

@@ -2923,10 +2919,19 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
29232919
}
29242920
}
29252921
}
2922+
// For @[heap] variables, the C-level variable is already a pointer
2923+
// even though the V-level type is a value type, so account for
2924+
// that extra indirection when computing how many '&' to add.
2925+
extra_muls := if expr is ast.Ident && g.resolved_ident_is_auto_heap(expr)
2926+
&& !expr_typ.is_ptr() {
2927+
1
2928+
} else {
2929+
0
2930+
}
29262931
if !expr.is_literal() && expr_typ != ast.nil_type
2927-
&& ret_typ.nr_muls() > expr_typ.nr_muls()
2932+
&& ret_typ.nr_muls() > expr_typ.nr_muls() + extra_muls
29282933
&& !ret_typ.has_flag(.option_mut_param_t) {
2929-
g.write('&'.repeat(ret_typ.nr_muls() - expr_typ.nr_muls()))
2934+
g.write('&'.repeat(ret_typ.nr_muls() - expr_typ.nr_muls() - extra_muls))
29302935
} else if ret_typ.has_flag(.option_mut_param_t) {
29312936
if expr_typ.is_ptr() {
29322937
if ret_typ.nr_muls() < expr_typ.nr_muls() {
@@ -6291,10 +6296,6 @@ fn (mut g Gen) debugger_stmt(node ast.DebuggerStmt) {
62916296
}
62926297

62936298
fn (mut g Gen) enum_decl(node ast.EnumDecl) {
6294-
// @[typedef] enums are already defined in a C header, don't redefine them.
6295-
if node.attrs.contains('typedef') {
6296-
return
6297-
}
62986299
enum_name := util.no_dots(node.name)
62996300
is_flag := node.is_flag
63006301
// Explicit-size enums are emitted as typedef + defines, so all C compilers

0 commit comments

Comments
 (0)