@@ -338,49 +338,21 @@ pub fn (mut c Checker) interface_decl(decl ast.InterfaceDecl) {
338
338
c.check_valid_pascal_case (decl.name, 'interface name' , decl.pos)
339
339
for method in decl.methods {
340
340
c.check_valid_snake_case (method.name, 'method name' , method.pos)
341
+ if method.return_type != table.Type (0 ) {
342
+ c.ensure_type_exists (method.return_type, method.pos) or { return }
343
+ }
344
+ for param in method.params {
345
+ c.ensure_type_exists (param.typ, param.pos) or { return }
346
+ }
341
347
}
342
- // TODO: copy pasta from StructDecl
343
348
for i, field in decl.fields {
344
349
c.check_valid_snake_case (field.name, 'field name' , field.pos)
345
- sym := c.table. get_type_symbol (field.typ)
350
+ c. ensure_type_exists (field.typ, field.pos) or { return }
346
351
for j in 0 .. i {
347
352
if field.name == decl.fields[j].name {
348
353
c.error ('field name `$field.name ` duplicate' , field.pos)
349
354
}
350
355
}
351
- if sym.kind == .placeholder && ! sym.name.starts_with ('C.' ) {
352
- c.error (util.new_suggestion (sym.name, c.table.known_type_names ()).say ('unknown type `$sym.name `' ),
353
- field.type_pos)
354
- }
355
- // Separate error condition for `int_literal` and `float_literal` because `util.suggestion` may give different
356
- // suggestions due to f32 comparision issue.
357
- if sym.kind in [.int_literal, .float_literal] {
358
- msg := if sym.kind == .int_literal {
359
- 'unknown type `$sym.name `.\n Did you mean `int`?'
360
- } else {
361
- 'unknown type `$sym.name `.\n Did you mean `f64`?'
362
- }
363
- c.error (msg, field.type_pos)
364
- }
365
- if sym.kind == .array {
366
- array_info := sym.array_info ()
367
- elem_sym := c.table.get_type_symbol (array_info.elem_type)
368
- if elem_sym.kind == .placeholder {
369
- c.error (util.new_suggestion (elem_sym.name, c.table.known_type_names ()).say ('unknown type `$elem_sym.name `' ),
370
- field.type_pos)
371
- }
372
- }
373
- if sym.kind == .map {
374
- info := sym.map_info ()
375
- key_sym := c.table.get_type_symbol (info.key_type)
376
- value_sym := c.table.get_type_symbol (info.value_type)
377
- if key_sym.kind == .placeholder {
378
- c.error ('unknown type `$key_sym.name `' , field.type_pos)
379
- }
380
- if value_sym.kind == .placeholder {
381
- c.error ('unknown type `$value_sym.name `' , field.type_pos)
382
- }
383
- }
384
356
}
385
357
}
386
358
@@ -407,6 +379,7 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) {
407
379
}
408
380
}
409
381
for i, field in decl.fields {
382
+ c.ensure_type_exists (field.typ, field.type_pos) or { return }
410
383
if decl.language == .v {
411
384
c.check_valid_snake_case (field.name, 'field name' , field.pos)
412
385
}
@@ -416,45 +389,12 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) {
416
389
c.error ('field name `$field.name ` duplicate' , field.pos)
417
390
}
418
391
}
419
- if sym.kind == .placeholder && decl.language != .c && ! sym.name.starts_with ('C.' ) {
420
- c.error (util.new_suggestion (sym.name, c.table.known_type_names ()).say ('unknown type `$sym.name `' ),
421
- field.type_pos)
422
- }
423
- // Separate error condition for `int_literal` and `float_literal` because `util.suggestion` may give different
424
- // suggestions due to f32 comparision issue.
425
- if sym.kind in [.int_literal, .float_literal] {
426
- msg := if sym.kind == .int_literal {
427
- 'unknown type `$sym.name `.\n Did you mean `int`?'
428
- } else {
429
- 'unknown type `$sym.name `.\n Did you mean `f64`?'
430
- }
431
- c.error (msg, field.type_pos)
432
- }
433
- if sym.kind == .array {
434
- array_info := sym.array_info ()
435
- elem_sym := c.table.get_type_symbol (array_info.elem_type)
436
- if elem_sym.kind == .placeholder {
437
- c.error (util.new_suggestion (elem_sym.name, c.table.known_type_names ()).say ('unknown type `$elem_sym.name `' ),
438
- field.type_pos)
439
- }
440
- }
441
392
if sym.kind == .struct_ {
442
393
info := sym.info as table.Struct
443
394
if info.is_heap && ! field.typ.is_ptr () {
444
395
struct_sym.info.is_heap = true
445
396
}
446
397
}
447
- if sym.kind == .map {
448
- info := sym.map_info ()
449
- key_sym := c.table.get_type_symbol (info.key_type)
450
- value_sym := c.table.get_type_symbol (info.value_type)
451
- if key_sym.kind == .placeholder {
452
- c.error ('unknown type `$key_sym.name `' , field.type_pos)
453
- }
454
- if value_sym.kind == .placeholder {
455
- c.error ('unknown type `$value_sym.name `' , field.type_pos)
456
- }
457
- }
458
398
if field.has_default_expr {
459
399
c.expected_type = field.typ
460
400
field_expr_type := c.expr (field.default_expr)
@@ -509,10 +449,8 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
509
449
struct_init.typ = c.expected_type
510
450
}
511
451
}
512
- if struct_init.typ == 0 {
513
- c.error ('unknown type' , struct_init.pos)
514
- }
515
452
utyp := c.unwrap_generic (struct_init.typ)
453
+ c.ensure_type_exists (utyp, struct_init.pos) or { }
516
454
type_sym := c.table.get_type_symbol (utyp)
517
455
if type_sym.kind == .sum_type && struct_init.fields.len == 1 {
518
456
sexpr := struct_init.fields[0 ].expr.str ()
@@ -1107,14 +1045,8 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
1107
1045
}
1108
1046
ast.SelectorExpr {
1109
1047
// retrieve table.Field
1110
- if expr.expr_type == 0 {
1111
- c.error ('0 type in SelectorExpr' , expr.pos)
1112
- return '' , pos
1113
- }
1114
- mut typ_sym := c.table.get_type_symbol (c.unwrap_generic (expr.expr_type))
1115
- if mut typ_sym.info is table.Alias {
1116
- typ_sym = c.table.get_type_symbol (typ_sym.info.parent_type)
1117
- }
1048
+ c.ensure_type_exists (expr.expr_type, expr.pos) or { return '' , pos }
1049
+ mut typ_sym := c.table.get_final_type_symbol (c.unwrap_generic (expr.expr_type))
1118
1050
match typ_sym.kind {
1119
1051
.struct_ {
1120
1052
struct_info := typ_sym.info as table.Struct
@@ -1874,9 +1806,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
1874
1806
gts := c.table.get_type_symbol (call_expr.generic_types[0 ])
1875
1807
nrt := '$rts.name <$gts.name >'
1876
1808
idx := c.table.type_idxs[nrt]
1877
- if idx == 0 {
1878
- c.error ('unknown type: $nrt ' , call_expr.pos)
1879
- }
1809
+ c.ensure_type_exists (idx, call_expr.pos) or { }
1880
1810
call_expr.return_type = table.new_type (idx).derive (f.return_type)
1881
1811
}
1882
1812
}
@@ -4278,10 +4208,8 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
4278
4208
cond_type := c.expr (node.cond)
4279
4209
// we setting this here rather than at the end of the method
4280
4210
// since it is used in c.match_exprs() it saves checking twice
4281
- node.cond_type = cond_type
4282
- if cond_type == 0 {
4283
- c.error ('compiler bug: match 0 cond type' , node.pos)
4284
- }
4211
+ node.cond_type = c.table.mktyp (cond_type)
4212
+ c.ensure_type_exists (node.cond_type, node.pos) or { return table.void_type }
4285
4213
cond_type_sym := c.table.get_type_symbol (cond_type)
4286
4214
if cond_type_sym.kind ! in [.interface_, .sum_type] {
4287
4215
node.is_sum_type = false
@@ -5661,17 +5589,10 @@ fn (mut c Checker) sql_stmt(mut node ast.SqlStmt) table.Type {
5661
5589
defer {
5662
5590
c.inside_sql = false
5663
5591
}
5664
- sym := c.table.get_type_symbol (node.table_expr.typ)
5665
- if node.table_expr.typ == 0 {
5666
- c.error ('orm: unknown type `$sym.name `' , node.pos)
5667
- }
5668
- if sym.kind == .placeholder {
5669
- c.error ('orm: unknown type `$sym.name `' , node.pos)
5670
- return table.void_type
5671
- }
5672
- c.cur_orm_ts = sym
5673
- info := sym.info as table.Struct
5592
+ c.ensure_type_exists (node.table_expr.typ, node.pos) or { return table.void_type }
5674
5593
table_sym := c.table.get_type_symbol (node.table_expr.typ)
5594
+ c.cur_orm_ts = table_sym
5595
+ info := table_sym.info as table.Struct
5675
5596
fields := c.fetch_and_verify_orm_fields (info, node.table_expr.pos, table_sym.name)
5676
5597
mut sub_structs := map [int ]ast.SqlStmt{}
5677
5598
for f in fields.filter (c.table.types[int (it .typ)].kind == .struct_) {
@@ -5788,19 +5709,11 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
5788
5709
if node.language == .v {
5789
5710
// Make sure all types are valid
5790
5711
for arg in node.params {
5791
- sym := c.table.get_type_symbol (arg.typ)
5792
- if sym.kind == .placeholder
5793
- || (sym.kind in [table.Kind.int_literal, .float_literal] && ! c.is_builtin_mod) {
5794
- c.error ('unknown type `$sym.name `' , node.pos)
5795
- }
5712
+ c.ensure_type_exists (arg.typ, node.pos) or { return }
5796
5713
}
5797
5714
}
5798
5715
if node.return_type != table.Type (0 ) {
5799
- return_sym := c.table.get_type_symbol (node.return_type)
5800
- if node.language == .v && return_sym.kind in [.placeholder, .int_literal, .float_literal]
5801
- && return_sym.language == .v {
5802
- c.error ('unknown type `$return_sym.name `' , node.pos)
5803
- }
5716
+ c.ensure_type_exists (node.return_type, node.pos) or { return }
5804
5717
if node.language == .v && node.is_method && node.name == 'str' {
5805
5718
if node.return_type != table.string_type {
5806
5719
c.error ('.str() methods should return `string`' , node.pos)
@@ -5949,3 +5862,41 @@ fn (mut c Checker) trace(fbase string, message string) {
5949
5862
println ('> c.trace | ${fbase:-10s} | $message ' )
5950
5863
}
5951
5864
}
5865
+
5866
+ fn (mut c Checker) ensure_type_exists (typ table.Type, pos token.Position) ? {
5867
+ if typ == 0 {
5868
+ c.error ('unknown type' , pos)
5869
+ }
5870
+ sym := c.table.get_type_symbol (typ)
5871
+ match sym.kind {
5872
+ .placeholder {
5873
+ if sym.language == .v && ! sym.name.starts_with ('C.' ) {
5874
+ c.error (util.new_suggestion (sym.name, c.table.known_type_names ()).say ('unknown type `$sym.name `' ),
5875
+ pos)
5876
+ return none
5877
+ }
5878
+ }
5879
+ .int_literal, .float_literal {
5880
+ // Separate error condition for `int_literal` and `float_literal` because `util.suggestion` may give different
5881
+ // suggestions due to f32 comparision issue.
5882
+ if ! c.is_builtin_mod {
5883
+ msg := if sym.kind == .int_literal {
5884
+ 'unknown type `$sym.name `.\n Did you mean `int`?'
5885
+ } else {
5886
+ 'unknown type `$sym.name `.\n Did you mean `f64`?'
5887
+ }
5888
+ c.error (msg, pos)
5889
+ return none
5890
+ }
5891
+ }
5892
+ .array {
5893
+ c.ensure_type_exists ((sym.info as table.Array ).elem_type, pos) ?
5894
+ }
5895
+ .map {
5896
+ info := sym.info as table.Map
5897
+ c.ensure_type_exists (info.key_type, pos) ?
5898
+ c.ensure_type_exists (info.value_type, pos) ?
5899
+ }
5900
+ else {}
5901
+ }
5902
+ }
0 commit comments