mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
table: make Table.type_to_str generate proper function type, not fn name (#6716)
This commit is contained in:
parent
a2fc19880a
commit
ca8d23acab
@ -1585,7 +1585,10 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok
|
||||
for imethod in inter_sym.methods {
|
||||
if method := typ_sym.find_method(imethod.name) {
|
||||
if !imethod.is_same_method_as(method) {
|
||||
c.error('`$styp` incorrectly implements method `$imethod.name` of interface `$inter_sym.source_name`, expected `${c.table.fn_to_str(imethod)}`',
|
||||
sig := c.table.fn_signature(imethod, {
|
||||
skip_receiver: true
|
||||
})
|
||||
c.error('`$styp` incorrectly implements method `$imethod.name` of interface `$inter_sym.source_name`, expected `$sig`',
|
||||
pos)
|
||||
return false
|
||||
}
|
||||
|
17
vlib/v/checker/tests/fn_var.out
Normal file
17
vlib/v/checker/tests/fn_var.out
Normal file
@ -0,0 +1,17 @@
|
||||
vlib/v/checker/tests/fn_var.vv:2:5: error: cannot assign to `f`: expected `fn (int) byte`, not `any_int`
|
||||
1 | mut f := fn(i int) byte {}
|
||||
2 | f = 4
|
||||
| ^
|
||||
3 | mut p := &f
|
||||
4 | p = &[f]
|
||||
vlib/v/checker/tests/fn_var.vv:4:5: error: cannot assign to `p`: expected `&fn (int) byte`, not `&[]fn (int) byte`
|
||||
2 | f = 4
|
||||
3 | mut p := &f
|
||||
4 | p = &[f]
|
||||
| ^
|
||||
5 | f = fn(mut a []int) {}
|
||||
vlib/v/checker/tests/fn_var.vv:5:5: error: cannot assign to `f`: expected `fn (int) byte`, not `fn (mut []int)`
|
||||
3 | mut p := &f
|
||||
4 | p = &[f]
|
||||
5 | f = fn(mut a []int) {}
|
||||
| ~~
|
5
vlib/v/checker/tests/fn_var.vv
Normal file
5
vlib/v/checker/tests/fn_var.vv
Normal file
@ -0,0 +1,5 @@
|
||||
mut f := fn(i int) byte {}
|
||||
f = 4
|
||||
mut p := &f
|
||||
p = &[f]
|
||||
f = fn(mut a []int) {}
|
@ -2389,21 +2389,15 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
}
|
||||
|
||||
// typeof(expr).name
|
||||
// Note: typeof() should be a type known at compile-time, not a string
|
||||
// sum types should not be handled dynamically
|
||||
fn (mut g Gen) typeof_name(node ast.TypeOf) {
|
||||
mut typ := node.expr_type
|
||||
if typ.has_flag(.generic) {
|
||||
typ = g.cur_generic_type
|
||||
}
|
||||
sym := g.table.get_type_symbol(typ)
|
||||
// TODO: fix table.type_to_str and use instead
|
||||
if sym.kind == .function {
|
||||
g.typeof_expr(node)
|
||||
} else {
|
||||
// Note: typeof() must be known at compile-time
|
||||
// sum types should not be handled dynamically
|
||||
s := g.table.type_to_str(typ)
|
||||
g.write('tos_lit("${util.strip_main_name(s)}")')
|
||||
}
|
||||
s := g.table.type_to_str(typ)
|
||||
g.write('tos_lit("${util.strip_main_name(s)}")')
|
||||
}
|
||||
|
||||
fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||
|
@ -839,7 +839,10 @@ pub fn (table &Table) type_to_str(t Type) string {
|
||||
}
|
||||
}
|
||||
.function {
|
||||
// do nothing, source_name is sufficient
|
||||
info := sym.info as FnType
|
||||
res = table.fn_signature(info.func, {
|
||||
type_only: true
|
||||
})
|
||||
}
|
||||
.map {
|
||||
if int(t) == map_type_idx {
|
||||
@ -889,18 +892,37 @@ pub fn (table &Table) type_to_str(t Type) string {
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (t &Table) fn_to_str(func &Fn) string {
|
||||
pub struct FnSignatureOpts {
|
||||
skip_receiver bool
|
||||
type_only bool
|
||||
}
|
||||
|
||||
pub fn (t &Table) fn_signature(func &Fn, opts FnSignatureOpts) string {
|
||||
mut sb := strings.new_builder(20)
|
||||
sb.write('${func.name}(')
|
||||
for i in 1 .. func.params.len {
|
||||
param := func.params[i]
|
||||
sb.write('$param.name')
|
||||
if i == func.params.len - 1 || func.params[i + 1].typ != param.typ {
|
||||
sb.write(' ${t.type_to_str(param.typ)}')
|
||||
}
|
||||
if i != func.params.len - 1 {
|
||||
if !opts.skip_receiver {
|
||||
sb.write('fn ')
|
||||
// TODO write receiver
|
||||
}
|
||||
if !opts.type_only {
|
||||
sb.write('$func.name')
|
||||
}
|
||||
sb.write('(')
|
||||
start := int(opts.skip_receiver)
|
||||
for i in start .. func.params.len {
|
||||
if i != start {
|
||||
sb.write(', ')
|
||||
}
|
||||
param := func.params[i]
|
||||
mut typ := param.typ
|
||||
if param.is_mut {
|
||||
typ = typ.deref()
|
||||
sb.write('mut ')
|
||||
}
|
||||
if !opts.type_only {
|
||||
sb.write('$param.name ')
|
||||
}
|
||||
styp := t.type_to_str(typ)
|
||||
sb.write('$styp')
|
||||
}
|
||||
sb.write(')')
|
||||
if func.return_type != void_type {
|
||||
|
@ -115,6 +115,7 @@ fn test_typeof_on_fn() {
|
||||
assert typeof(myfn3) == 'fn (int, string) byte'
|
||||
assert typeof(myfn4) == 'fn () i8'
|
||||
assert typeof(myfn).name == typeof(myfn)
|
||||
assert typeof(&myfn).name == '&fn (int) int'
|
||||
assert typeof(myfn2).name == typeof(myfn2)
|
||||
assert typeof(myfn3).name == typeof(myfn3)
|
||||
assert typeof(myfn4).name == typeof(myfn4)
|
||||
|
Loading…
Reference in New Issue
Block a user