checker,cgen: stabilise generic method handling (fix a source code ordering issue)
parent
b3161b05a3
commit
e256f1b2aa
|
@ -488,6 +488,7 @@ pub mut:
|
|||
return_type_pos token.Position // `string` in `fn (u User) name() string` position
|
||||
has_return bool
|
||||
should_be_skipped bool // true, when -skip-unused could not find any usages of that function, starting from main + other known used functions
|
||||
ninstances int // 0 for generic functions with no concrete instances
|
||||
has_await bool // 'true' if this function uses JS.await
|
||||
//
|
||||
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
|
||||
|
|
|
@ -291,7 +291,7 @@ pub fn (mut c Checker) check_files(ast_files []&ast.File) {
|
|||
c.timers.start('checker_post_process_generic_fns')
|
||||
last_file := c.file
|
||||
// post process generic functions. must be done after all files have been
|
||||
// checked, to eunsure all generic calls are processed as this information
|
||||
// checked, to ensure all generic calls are processed as this information
|
||||
// is needed when the generic type is auto inferred from the call argument
|
||||
// Check more times if there are more new registered fn concrete types
|
||||
for {
|
||||
|
@ -4831,7 +4831,11 @@ fn (mut c Checker) post_process_generic_fns() {
|
|||
for i in 0 .. c.file.generic_fns.len {
|
||||
mut node := c.file.generic_fns[i]
|
||||
c.mod = node.mod
|
||||
for concrete_types in c.table.fn_generic_types[node.name] {
|
||||
gtypes := c.table.fn_generic_types[node.name]
|
||||
$if trace_post_process_generic_fns ? {
|
||||
eprintln('> post_process_generic_fns $node.mod | $node.name | $gtypes')
|
||||
}
|
||||
for concrete_types in gtypes {
|
||||
c.table.cur_concrete_types = concrete_types
|
||||
c.fn_decl(mut node)
|
||||
if node.name == 'vweb.run' {
|
||||
|
@ -4843,6 +4847,11 @@ fn (mut c Checker) post_process_generic_fns() {
|
|||
}
|
||||
}
|
||||
c.table.cur_concrete_types = []
|
||||
$if trace_post_process_generic_fns ? {
|
||||
if node.generic_names.len > 0 {
|
||||
eprintln(' > fn_decl node.name: $node.name | generic_names: $node.generic_names | ninstances: $node.ninstances')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,10 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
|||
// have a chance to populate c.table.fn_generic_types with
|
||||
// the correct concrete types.
|
||||
c.file.generic_fns << node
|
||||
c.need_recheck_generic_fns = true
|
||||
return
|
||||
}
|
||||
node.ninstances++
|
||||
// save all the state that fn_decl or inner statements/expressions
|
||||
// could potentially modify, since functions can be nested, due to
|
||||
// anonymous function support, and ensure that it is restored, when
|
||||
|
|
|
@ -4855,6 +4855,10 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
|||
has_semicolon = true
|
||||
}
|
||||
} else if node.exprs.len >= 1 {
|
||||
if node.types.len == 0 {
|
||||
g.checker_bug('node.exprs.len == $node.exprs.len && node.types.len == 0',
|
||||
node.pos)
|
||||
}
|
||||
// normal return
|
||||
return_sym := g.table.sym(node.types[0])
|
||||
expr0 := node.exprs[0]
|
||||
|
|
|
@ -32,6 +32,12 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
|||
if node.should_be_skipped {
|
||||
return
|
||||
}
|
||||
if node.ninstances == 0 && node.generic_names.len > 0 {
|
||||
$if trace_generics ? {
|
||||
eprintln('skipping generic fn with no concrete instances: $node.mod $node.name')
|
||||
}
|
||||
return
|
||||
}
|
||||
if !g.is_used_by_main(node) {
|
||||
return
|
||||
}
|
||||
|
@ -82,7 +88,8 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
|
|||
if node.is_main {
|
||||
g.has_main = true
|
||||
}
|
||||
is_backtrace := node.name.starts_with('backtrace') // TODO PERF remove this from here
|
||||
// TODO PERF remove this from here
|
||||
is_backtrace := node.name.starts_with('backtrace')
|
||||
&& node.name in ['backtrace_symbols', 'backtrace', 'backtrace_symbols_fd']
|
||||
if is_backtrace {
|
||||
g.write('\n#ifndef __cplusplus\n')
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
struct Foo<T> {
|
||||
x int
|
||||
}
|
||||
|
||||
fn (f Foo<T>) pop() {
|
||||
println('hey')
|
||||
}
|
||||
|
||||
struct Bar<T> {
|
||||
y int
|
||||
}
|
||||
|
||||
// NB: Bar.foo before Bar.pop, should not cause a V compiler panic
|
||||
fn (b Bar<T>) foo() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
fn (b Bar<T>) pop() {
|
||||
println(b.foo())
|
||||
}
|
||||
|
||||
// fn dummy() { println(Bar<int>{}) }
|
||||
|
||||
fn test_foo() {
|
||||
dump(Foo<int>{})
|
||||
assert true
|
||||
}
|
Loading…
Reference in New Issue