Skip to content

Commit a6b2247

Browse files
committed
ok. final codex commit
1 parent ca57cbc commit a6b2247

10 files changed

Lines changed: 426 additions & 168 deletions

File tree

vlib/v/checker/assign.v

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,38 +32,46 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
3232
}
3333
for i, mut right in node.right {
3434
if right in [ast.ArrayInit, ast.CallExpr, ast.ComptimeCall, ast.DumpExpr, ast.IfExpr,
35-
ast.LockExpr, ast.MapInit, ast.MatchExpr, ast.ParExpr, ast.SelectorExpr,
36-
ast.StructInit] {
35+
ast.LockExpr, ast.MapInit, ast.MatchExpr, ast.ParExpr, ast.SelectorExpr, ast.StructInit] {
3736
if right in [ast.ArrayInit, ast.IfExpr, ast.MapInit, ast.MatchExpr, ast.StructInit]
3837
&& node.left.len == node.right.len && !is_decl
39-
&& node.left[i] in [ast.Ident, ast.SelectorExpr] && !node.left[i].is_blank_ident() {
38+
&& node.left[i] in [ast.Ident, ast.IndexExpr, ast.SelectorExpr]
39+
&& !node.left[i].is_blank_ident() {
4040
mut expr := node.left[i]
41+
old_is_index_assign := c.is_index_assign
42+
if expr is ast.IndexExpr {
43+
c.is_index_assign = true
44+
}
4145
c.expected_type = c.expr(mut expr)
46+
c.is_index_assign = old_is_index_assign
4247
}
4348
mut right_type := c.expr(mut right)
4449
if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr, ast.DumpExpr] {
4550
c.fail_if_unreadable(right, right_type, 'right-hand side of assignment')
4651
}
47-
right_type_sym := c.table.sym(right_type)
48-
// fixed array returns an struct, but when assigning it must be the array type
49-
if right_type_sym.info is ast.ArrayFixed {
50-
right_type = c.cast_fixed_array_ret(right_type, right_type_sym)
51-
}
5252
if i == 0 {
5353
right_first_type = right_type
5454
node.right_types = [
5555
c.check_expr_option_or_result_call(right, right_first_type),
5656
]
5757
}
58-
if right_type_sym.kind == .multi_return {
59-
if node.right.len > 1 {
60-
c.error('cannot use multi-value ${right_type_sym.name} in single-value context',
61-
right.pos())
58+
if right_type != 0 {
59+
right_type_sym := c.table.sym(right_type)
60+
// fixed array returns an struct, but when assigning it must be the array type
61+
if right_type_sym.info is ast.ArrayFixed {
62+
right_type = c.cast_fixed_array_ret(right_type, right_type_sym)
6263
}
63-
node.right_types = right_type_sym.mr_info().types.map(c.cast_fixed_array_ret(it,
64-
c.table.sym(it)))
65-
right_len = node.right_types.len
66-
} else if right_type == ast.void_type {
64+
if right_type_sym.kind == .multi_return {
65+
if node.right.len > 1 {
66+
c.error('cannot use multi-value ${right_type_sym.name} in single-value context',
67+
right.pos())
68+
}
69+
node.right_types = right_type_sym.mr_info().types.map(c.cast_fixed_array_ret(it,
70+
c.table.sym(it)))
71+
right_len = node.right_types.len
72+
}
73+
}
74+
if right_type == ast.void_type {
6775
right_len = 0
6876
if mut right is ast.IfExpr {
6977
last_branch := right.branches.last()
@@ -83,10 +91,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
8391
c.expected_type = node.right_types[i]
8492
}
8593
mut right_type := c.expr(mut right)
86-
right_type_sym := c.table.sym(right_type)
87-
// fixed array returns an struct, but when assigning it must be the array type
88-
if right_type_sym.info is ast.ArrayFixed {
89-
right_type = c.cast_fixed_array_ret(right_type, right_type_sym)
94+
if right_type != 0 {
95+
right_type_sym := c.table.sym(right_type)
96+
// fixed array returns an struct, but when assigning it must be the array type
97+
if right_type_sym.info is ast.ArrayFixed {
98+
right_type = c.cast_fixed_array_ret(right_type, right_type_sym)
99+
}
90100
}
91101
if i == 0 {
92102
right_first_type = right_type
@@ -115,6 +125,32 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
115125
}
116126
}
117127
if node.left.len != right_len {
128+
if right_len == 0 && right_first_type == ast.void_type {
129+
match right_first {
130+
ast.ArrayInit, ast.MapInit, ast.StructInit {
131+
if is_decl {
132+
for i, mut left in node.left {
133+
node.left_types << ast.void_type
134+
if mut left is ast.Ident {
135+
if left.info is ast.IdentVar {
136+
mut ident_var_info := left.info as ast.IdentVar
137+
ident_var_info.typ = ast.void_type
138+
left.info = ident_var_info
139+
if mut left.obj is ast.Var {
140+
left.obj.typ = ast.void_type
141+
}
142+
}
143+
}
144+
if i < node.right_types.len && node.right_types[i] == 0 {
145+
node.right_types[i] = ast.void_type
146+
}
147+
}
148+
}
149+
return
150+
}
151+
else {}
152+
}
153+
}
118154
if mut right_first is ast.CallExpr {
119155
if node.left_types.len > 0 && node.left_types[0] == ast.void_type {
120156
// If it's a void type, it's an unknown variable, already had an error earlier.

vlib/v/checker/containers.v

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,8 @@ fn (mut c Checker) array_fixed_has_unresolved_size(info &ast.ArrayFixed) bool {
504504
}
505505

506506
fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
507-
if c.table.cur_fn != unsafe { nil } && c.table.cur_concrete_types.len > 0
508-
&& node.typ != 0 && c.expected_type != ast.void_type {
507+
if c.table.cur_fn != unsafe { nil } && c.table.cur_concrete_types.len > 0 && node.typ != 0
508+
&& c.expected_type != ast.void_type {
509509
expected_map_type := c.expected_type.clear_option_and_result()
510510
if c.table.sym(expected_map_type).kind == .map && node.typ != expected_map_type {
511511
node.typ = expected_map_type
@@ -580,8 +580,10 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
580580
node.pos)
581581
c.error('cannot use type `any` here', node.pos)
582582
}
583-
if c.nr_errors == start_errors && info.key_type != ast.void_type
584-
&& !c.table.supports_map_key_type(info.key_type) {
583+
needs_explicit_key_check := c.expected_type == ast.void_type
584+
|| c.expected_type.clear_option_and_result() != node.typ
585+
if needs_explicit_key_check && c.nr_errors == start_errors && info.key_type != ast.void_type
586+
&& !info.key_type.has_flag(.generic) && !c.table.supports_map_key_type(info.key_type) {
585587
c.error('map key type `${c.table.sym(info.key_type).name}` not supported',
586588
node.pos)
587589
}
@@ -640,7 +642,7 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
640642
map_key_type = c.unwrap_generic(map_key_type)
641643
map_val_type = c.unwrap_generic(map_val_type)
642644
if c.nr_errors == start_errors && map_key_type != ast.void_type
643-
&& !c.table.supports_map_key_type(map_key_type) {
645+
&& !map_key_type.has_flag(.generic) && !c.table.supports_map_key_type(map_key_type) {
644646
c.error('map key type `${c.table.sym(map_key_type).name}` not supported',
645647
node.pos)
646648
}

vlib/v/checker/fn.v

Lines changed: 92 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ fn (mut c Checker) effective_fn_generic_names(node &ast.FnDecl) []string {
7474
if !node.is_method {
7575
return []string{}
7676
}
77-
if !node.receiver.typ.has_flag(.generic) && !c.type_has_unresolved_generic_parts(node.receiver.typ) {
77+
if !node.receiver.typ.has_flag(.generic)
78+
&& !c.type_has_unresolved_generic_parts(node.receiver.typ) {
7879
return []string{}
7980
}
8081
rec_sym := c.table.sym(c.unwrap_generic(node.receiver.typ))
@@ -89,6 +90,61 @@ fn (mut c Checker) effective_fn_generic_names(node &ast.FnDecl) []string {
8990
return c.table.generic_type_names(node.receiver.typ)
9091
}
9192

93+
fn (mut c Checker) receiver_requires_generic_names(node &ast.FnDecl) bool {
94+
if !node.is_method {
95+
return false
96+
}
97+
return node.receiver.typ.has_flag(.generic)
98+
}
99+
100+
fn (mut c Checker) check_receiver_decl_generic_type_names(node &ast.FnDecl) {
101+
if !node.is_method {
102+
return
103+
}
104+
receiver_sym := c.table.final_sym(node.receiver.typ)
105+
match receiver_sym.info {
106+
ast.Struct {
107+
if receiver_sym.info.generic_types.len > 0 && !node.receiver.typ.has_flag(.generic)
108+
&& receiver_sym.info.concrete_types.len == 0 {
109+
pure_sym_name := receiver_sym.embed_name()
110+
c.error('generic struct `${pure_sym_name}` in fn declaration must specify the generic type names, e.g. ${pure_sym_name}[T]',
111+
node.receiver.type_pos)
112+
}
113+
}
114+
ast.Interface {
115+
if receiver_sym.info.generic_types.len > 0 && !node.receiver.typ.has_flag(.generic)
116+
&& receiver_sym.info.concrete_types.len == 0 {
117+
pure_sym_name := receiver_sym.embed_name()
118+
c.error('generic interface `${pure_sym_name}` in fn declaration must specify the generic type names, e.g. ${pure_sym_name}[T]',
119+
node.receiver.type_pos)
120+
}
121+
}
122+
ast.SumType {
123+
if receiver_sym.info.generic_types.len > 0 && !node.receiver.typ.has_flag(.generic)
124+
&& receiver_sym.info.concrete_types.len == 0 {
125+
pure_sym_name := receiver_sym.embed_name()
126+
c.error('generic sumtype `${pure_sym_name}` in fn declaration must specify the generic type names, e.g. ${pure_sym_name}[T]',
127+
node.receiver.type_pos)
128+
}
129+
}
130+
else {}
131+
}
132+
}
133+
134+
fn (mut c Checker) check_receiver_decl_generic_name_mentions(node &ast.FnDecl) {
135+
if !node.is_method || !node.receiver.typ.has_flag(.generic) {
136+
return
137+
}
138+
generic_names := c.table.generic_type_names(node.receiver.typ)
139+
for name in generic_names {
140+
if name !in node.generic_names {
141+
fn_generic_names := node.generic_names.join(', ')
142+
c.error('generic type name `${name}` is not mentioned in fn `${node.name}[${fn_generic_names}]`',
143+
node.receiver.type_pos)
144+
}
145+
}
146+
}
147+
92148
fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
93149
// handle vls go to definition for method receiver types
94150
if c.pref.is_vls {
@@ -138,9 +194,36 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
138194
}
139195
}
140196
}
197+
mut need_generic_names := false
198+
if node.generic_names.len == 0 {
199+
if node.return_type.has_flag(.generic) {
200+
need_generic_names = true
201+
} else if c.receiver_requires_generic_names(node) {
202+
need_generic_names = true
203+
} else {
204+
for param in node.params {
205+
if param.typ.has_flag(.generic) {
206+
need_generic_names = true
207+
break
208+
}
209+
}
210+
}
211+
if need_generic_names {
212+
if node.is_method {
213+
c.add_error_detail('use `fn (r SomeType[T]) foo[T]() {`, not just `fn (r SomeType[T]) foo() {`')
214+
c.error('generic method declaration must specify generic type names',
215+
node.pos)
216+
} else {
217+
c.add_error_detail('use `fn foo[T](x T) {`, not just `fn foo(x T) {`')
218+
c.error('generic function declaration must specify generic type names',
219+
node.pos)
220+
}
221+
}
222+
}
223+
c.check_receiver_decl_generic_type_names(node)
224+
c.check_receiver_decl_generic_name_mentions(node)
141225
effective_generic_names := c.effective_fn_generic_names(node)
142-
if effective_generic_names.len > 0
143-
&& c.table.cur_concrete_types.len == 0 {
226+
if effective_generic_names.len > 0 && c.table.cur_concrete_types.len == 0 {
144227
// Just remember the generic function for now.
145228
// It will be processed later in c.post_process_generic_fns,
146229
// after all other normal functions are processed.
@@ -183,30 +266,6 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
183266
c.fn_scope = prev_fn_scope
184267
}
185268
// Check generics fn/method without generic type parameters
186-
mut need_generic_names := false
187-
if node.generic_names.len == 0 {
188-
if node.return_type.has_flag(.generic) {
189-
need_generic_names = true
190-
} else {
191-
for param in node.params {
192-
if param.typ.has_flag(.generic) {
193-
need_generic_names = true
194-
break
195-
}
196-
}
197-
}
198-
if need_generic_names {
199-
if node.is_method {
200-
c.add_error_detail('use `fn (r SomeType[T]) foo[T]() {`, not just `fn (r SomeType[T]) foo() {`')
201-
c.error('generic method declaration must specify generic type names',
202-
node.pos)
203-
} else {
204-
c.add_error_detail('use `fn foo[T](x T) {`, not just `fn foo(x T) {`')
205-
c.error('generic function declaration must specify generic type names',
206-
node.pos)
207-
}
208-
}
209-
}
210269
if node.language == .v && !c.is_builtin_mod && !node.is_anon {
211270
c.check_valid_snake_case(node.get_name(), 'function name', node.pos)
212271
if !node.is_method && node.mod == 'main' && node.short_name in c.table.builtin_pub_fns {
@@ -613,7 +672,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
613672
}
614673
c.expected_type = ast.void_type
615674
mut effective_cur_fn := unsafe { node }
616-
if c.table.cur_concrete_types.len > 0 && effective_generic_names.len == c.table.cur_concrete_types.len
675+
if c.table.cur_concrete_types.len > 0
676+
&& effective_generic_names.len == c.table.cur_concrete_types.len
617677
&& node.generic_names != effective_generic_names {
618678
effective_cur_fn = &ast.FnDecl{
619679
...*node
@@ -2368,10 +2428,12 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
23682428
}
23692429
}
23702430
if final_left_sym.kind == .array && array_builtin_methods_chk.matches(method_name)
2371-
&& (!left_sym.has_method(method_name) || use_builtin_array_sort) {
2431+
&& (!(left_sym.kind == .alias && left_sym.has_method(method_name))
2432+
|| use_builtin_array_sort) {
23722433
return c.array_builtin_method_call(mut node, left_type)
23732434
} else if final_left_sym.kind == .array_fixed
2374-
&& fixed_array_builtin_methods_chk.matches(method_name) && !left_sym.has_method(method_name) {
2435+
&& fixed_array_builtin_methods_chk.matches(method_name) && !(left_sym.kind == .alias
2436+
&& left_sym.has_method(method_name)) {
23752437
return c.fixed_array_builtin_method_call(mut node, left_type)
23762438
} else if final_left_sym.kind == .map && node.kind in [.clone, .keys, .values, .move, .delete]
23772439
&& !(left_sym.kind == .alias && left_sym.has_method(method_name)) {
@@ -3169,30 +3231,6 @@ fn (mut c Checker) post_process_generic_fns() ! {
31693231
for concrete_types in gtypes {
31703232
c.table.cur_concrete_types = concrete_types
31713233
mut concrete_fn := c.file.generic_fns[i]
3172-
original_generic_names := concrete_fn.generic_names.clone()
3173-
if concrete_fn.is_method && concrete_types.len > original_generic_names.len {
3174-
receiver_generic_names := c.table.generic_type_names(concrete_fn.receiver.typ)
3175-
if receiver_generic_names.len > 0 {
3176-
mut effective_generic_names := []string{cap: receiver_generic_names.len +
3177-
original_generic_names.len}
3178-
for name in receiver_generic_names {
3179-
if name !in effective_generic_names {
3180-
effective_generic_names << name
3181-
}
3182-
}
3183-
for name in original_generic_names {
3184-
if name !in effective_generic_names {
3185-
effective_generic_names << name
3186-
}
3187-
}
3188-
if effective_generic_names.len == concrete_types.len {
3189-
concrete_fn = &ast.FnDecl{
3190-
...*concrete_fn
3191-
generic_names: effective_generic_names
3192-
}
3193-
}
3194-
}
3195-
}
31963234
c.fn_decl(mut concrete_fn)
31973235
if concrete_fn.name in ['veb.run', 'veb.run_at', 'x.vweb.run', 'x.vweb.run_at',
31983236
'vweb.run', 'vweb.run_at'] {

0 commit comments

Comments
 (0)