Skip to content

Commit 43f8801

Browse files
committed
ok
1 parent cd568a7 commit 43f8801

8 files changed

Lines changed: 47 additions & 44 deletions

File tree

‎vlib/v/checker/check_types.v‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,10 @@ fn (mut c Checker) infer_fn_generic_types(func &ast.Fn, mut node ast.CallExpr) {
12631263
// Use param.typ (not param_infer_typ) to get the actual pointer
12641264
// count including mut lowering, so that e.g. `mut val T` with
12651265
// param.typ=&T correctly strips the pointer from the arg type.
1266-
if param.typ.nr_muls() > 0 && typ.nr_muls() > 0 && !arg.is_mut {
1266+
// For auto-deref vars passed as mut, skip stripping since their
1267+
// type already has the auto-deref pointer removed.
1268+
if param.typ.nr_muls() > 0 && typ.nr_muls() > 0
1269+
&& (!arg.is_mut || !arg.expr.is_auto_deref_var()) {
12671270
param_muls := param.typ.nr_muls()
12681271
arg_muls := typ.nr_muls()
12691272
typ = if arg_muls >= param_muls {

‎vlib/v/checker/interface.v‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -411,16 +411,22 @@ fn (mut c Checker) unwrap_generic_interface(typ ast.Type, interface_type ast.Typ
411411
}
412412
inferred_types << inferred_type
413413
}
414-
// add concrete types to method
415-
for imethod in inter_sym.info.methods {
416-
im_fkey := imethod.fkey()
417-
if c.table.register_fn_concrete_types(im_fkey, inferred_types) {
418-
c.need_recheck_generic_fns = true
419-
}
420-
if method := typ_sym.find_method_with_generic_parent(imethod.name) {
421-
if c.table.register_fn_concrete_types(method.fkey(), inferred_types) {
414+
// add concrete types to method, but only if at least one
415+
// inferred type is actually concrete (not still generic).
416+
// When all inferred types are generic (e.g. T -> T from
417+
// `implements`), registering them would cause a circular
418+
// recheck that fails to resolve field types.
419+
if !inferred_types.all(it.has_flag(.generic)) {
420+
for imethod in inter_sym.info.methods {
421+
im_fkey := imethod.fkey()
422+
if c.table.register_fn_concrete_types(im_fkey, inferred_types) {
422423
c.need_recheck_generic_fns = true
423424
}
425+
if method := typ_sym.find_method_with_generic_parent(imethod.name) {
426+
if c.table.register_fn_concrete_types(method.fkey(), inferred_types) {
427+
c.need_recheck_generic_fns = true
428+
}
429+
}
424430
}
425431
}
426432
result_type := c.table.unwrap_generic_type(interface_type, generic_names,
Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,21 @@
11
vlib/v/checker/tests/implements_generic_err.vv:12:31: error: missing generic type on IB
22
10 | }
3-
11 |
3+
11 |
44
12 | struct Foo1[T] implements IA, IB {
55
| ~~
66
13 | a int
77
14 | b T
88
vlib/v/checker/tests/implements_generic_err.vv:17:31: error: unknown generic type Y
99
15 | }
10-
16 |
10+
16 |
1111
17 | struct Foo2[T] implements IA, IB[Y] {
1212
| ~~
1313
18 | a int
1414
19 | b T
1515
vlib/v/checker/tests/implements_generic_err.vv:22:31: error: unknown generic type Y
1616
20 | }
17-
21 |
17+
21 |
1818
22 | struct Foo3[T] implements IA, IB[T,Y] {
1919
| ~~
2020
23 | a int
2121
24 | b T
22-
vlib/v/checker/tests/implements_generic_err.vv:28:2: error: `println` can not print void expressions
23-
26 |
24-
27 | fn (foo Foo1[T]) fa() {
25-
28 | println(foo.b)
26-
| ~~~~~~~~~~~~~~
27-
29 | }
28-
30 |
29-
vlib/v/checker/tests/implements_generic_err.vv:32:2: error: `println` can not print void expressions
30-
30 |
31-
31 | fn (foo Foo2[T]) fa() {
32-
32 | println(foo.b)
33-
| ~~~~~~~~~~~~~~
34-
33 | }
35-
34 |
36-
vlib/v/checker/tests/implements_generic_err.vv:36:2: error: `println` can not print void expressions
37-
34 |
38-
35 | fn (foo Foo3[T]) fa() {
39-
36 | println(foo.b)
40-
| ~~~~~~~~~~~~~~
41-
37 | }

‎vlib/v/gen/c/auto_str_methods.v‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin
11421142
funcprefix += ' ? _S("nil") : '
11431143
// struct, floats and ints have a special case through the _str function
11441144
if !ftyp_noshared.has_flag(.option)
1145-
&& sym.kind !in [.struct, .alias, .enum, .sum_type, .map, .interface]
1145+
&& sym.kind !in [.struct, .alias, .enum, .sum_type, .map, .interface, .bool]
11461146
&& !field.typ.is_int_valptr() && !field.typ.is_float_valptr() {
11471147
funcprefix += '*'
11481148
}
@@ -1266,7 +1266,8 @@ fn struct_auto_str_func(sym &ast.TypeSymbol, lang ast.Language, _field_type ast.
12661266
method_str = 'it${op}${final_field_name}${sufix}'
12671267
}
12681268
if sym.kind == .bool {
1269-
return '(${method_str} ? _S("true") : _S("false"))', false
1269+
deref_str := if field_type.is_ptr() { '*${method_str}' } else { method_str }
1270+
return '(${deref_str} ? _S("true") : _S("false"))', false
12701271
} else if (field_type.is_int_valptr() || field_type.is_float_valptr()) && !expects_ptr {
12711272
// ptr int can be "nil", so this needs to be casted to a string
12721273
if sym.kind == .f32 {

‎vlib/v/gen/c/cgen.v‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5268,14 +5268,12 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
52685268
} else if node.field_name in ['idx', 'unaliased_typ'] {
52695269
// `T.idx`, `T.unaliased_typ`, `typeof(expr).idx`, `typeof(expr).unalised_typ`
52705270
mut name_type := node.name_type
5271-
mut resolved_via_generic := false
52725271
if node.expr is ast.TypeOf {
52735272
if g.cur_fn != unsafe { nil } && g.cur_concrete_types.len > 0 {
52745273
resolved := g.resolve_typeof_in_generic(node.expr)
52755274
if resolved != 0 {
52765275
name_type = g.type_resolver.typeof_field_type(resolved,
52775276
node.field_name)
5278-
resolved_via_generic = true
52795277
} else {
52805278
name_type = g.type_resolver.typeof_field_type(g.type_resolver.typeof_type(node.expr.expr,
52815279
g.resolve_typeof_expr_type(node.expr.expr, name_type)),
@@ -5288,7 +5286,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
52885286
}
52895287
// For mut params (auto_deref), strip pointer so that
52905288
// typeof(mut_param).idx == typeof(val_param).idx
5291-
if !resolved_via_generic && node.expr.expr is ast.Ident {
5289+
if node.expr.expr is ast.Ident {
52925290
if node.expr.expr.obj is ast.Var {
52935291
if node.expr.expr.obj.is_auto_deref && name_type.is_ptr() {
52945292
name_type = name_type.deref()
@@ -6948,7 +6946,8 @@ fn (mut g Gen) ident(node ast.Ident) {
69486946
} else {
69496947
comptime_type
69506948
}
6951-
g.or_block(var_name, node.or_expr, or_return_type)
6949+
g.or_block(var_name, node.or_expr, g.or_type_with_auto_deref(node,
6950+
or_return_type))
69526951
g.writeln(stmt_str)
69536952
}
69546953
return
@@ -7019,7 +7018,7 @@ fn (mut g Gen) ident(node ast.Ident) {
70197018
} else {
70207019
node.info.typ
70217020
}
7022-
g.or_block(var_name, node.or_expr, or_return_type)
7021+
g.or_block(var_name, node.or_expr, g.or_type_with_auto_deref(node, or_return_type))
70237022
g.write(stmt_str)
70247023
}
70257024
if has_resolved_var {
@@ -7295,7 +7294,7 @@ fn (mut g Gen) ident(node ast.Ident) {
72957294
stmt_str := g.go_before_last_stmt().trim_space()
72967295
g.empty_line = true
72977296
var_opt := if is_auto_heap { '(*${name})' } else { name }
7298-
g.or_block(var_opt, node.or_expr, node.obj.typ)
7297+
g.or_block(var_opt, node.or_expr, g.or_type_with_auto_deref(node, node.obj.typ))
72997298
g.write(stmt_str)
73007299
}
73017300
}
@@ -9226,6 +9225,16 @@ fn (mut g Gen) gen_or_block_stmts(cvar_name string, cast_typ string, stmts []ast
92269225
// If the user is not using the option return value. We need to pass a temp var
92279226
// to access its fields (`.ok`, `.error` etc)
92289227
// `os.cp(...)` => `Option bool tmp = os__cp(...); if (tmp.state != 0) { ... }`
9228+
// For auto-deref option variables (e.g. `mut t ?&T`), ensure the
9229+
// `option_mut_param_t` flag is set so that `or_block` uses `->` instead of `.`.
9230+
fn (g &Gen) or_type_with_auto_deref(node ast.Ident, typ ast.Type) ast.Type {
9231+
if node.obj is ast.Var && node.obj.is_auto_deref && typ.has_flag(.option)
9232+
&& !typ.has_flag(.option_mut_param_t) {
9233+
return typ.set_flag(.option_mut_param_t)
9234+
}
9235+
return typ
9236+
}
9237+
92299238
// Returns the type of the last stmt
92309239
fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Type) {
92319240
cvar_name := c_name(var_name)

‎vlib/v/gen/c/fn.v‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,8 +2010,8 @@ fn (mut g Gen) gen_array_method_call(node ast.CallExpr, left_type ast.Type, left
20102010
if node.kind in [.pop_left, .pop] {
20112011
g.gen_arg_from_type(left_type, node.left)
20122012
} else {
2013-
if node.left_type.is_ptr() {
2014-
g.write2('(', '*'.repeat(node.left_type.nr_muls()))
2013+
if node.left_type.is_ptr() || node.left.is_auto_deref_var() {
2014+
g.write('(*')
20152015
g.expr(node.left)
20162016
g.write(')')
20172017
} else {

‎vlib/v/gen/c/for.v‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,11 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
395395
}
396396
mut styp := g.styp(node.val_type)
397397
mut val_sym := g.table.sym(node.val_type)
398-
op_field := g.dot_or_ptr(node.cond_type)
398+
op_field := if node.cond_type.is_ptr() || resolved_cond_expr.is_auto_deref_var() {
399+
'->'
400+
} else {
401+
g.dot_or_ptr(node.cond_type)
402+
}
399403

400404
mut cond_var := ''
401405
// Check if the cond has an or-block that unwraps the option

‎vlib/v/gen/c/index.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym ast.TypeSymbol) {
458458
if is_fn_index_call {
459459
g.write('(*')
460460
}
461-
if node.left_type.is_ptr() {
461+
if node.left_type.is_ptr() || node.left.is_auto_deref_var() {
462462
g.write('(*')
463463
g.expr(ast.Expr(node.left))
464464
g.write(')')

0 commit comments

Comments
 (0)