From 9d8bda9eafd4ce3fbad8d750a213c06d41e7d396 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 20 Apr 2021 11:49:06 +0300 Subject: [PATCH] v.ast, v.checker: fix absent 'missing return' warning, when a function ended with a t.panic() call --- vlib/v/ast/table.v | 11 +++++++++++ vlib/v/checker/checker.v | 6 +++--- .../tests/function_missing_return_type.out | 7 +++++++ .../checker/tests/function_missing_return_type.vv | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 6cafd8ab94..d20a6105b7 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -431,6 +431,15 @@ pub fn (t &Table) find_type(name string) ?TypeSymbol { return none } +pub const invalid_type_symbol = &TypeSymbol{ + parent_idx: -1 + language: .v + mod: 'builtin' + kind: .placeholder + name: 'InvalidType' + cname: 'InvalidType' +} + [inline] pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol { // println('get_type_symbol $typ') @@ -441,6 +450,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol { // this should never happen t.panic('get_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`. ') + return ast.invalid_type_symbol } // get_final_type_symbol follows aliases until it gets to a "real" Type @@ -457,6 +467,7 @@ pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol { } // this should never happen t.panic('get_final_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`.') + return ast.invalid_type_symbol } [inline] diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index a064919618..291f213335 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2511,7 +2511,7 @@ pub fn (mut c Checker) check_or_expr(or_expr ast.OrExpr, ret_type ast.Type, expr fn is_expr_panic_or_exit(expr ast.Expr) bool { match expr { - ast.CallExpr { return expr.name in ['panic', 'exit'] } + ast.CallExpr { return !expr.is_method && expr.name in ['panic', 'exit'] } else { return false } } } @@ -6584,7 +6584,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { c.stmts(node.stmts) node.has_return = c.returns || has_top_return(node.stmts) if node.language == .v && !node.no_body && node.return_type != ast.void_type && !node.has_return - && node.name !in ['panic', 'exit'] { + && (node.is_method || node.name !in ['panic', 'exit']) { if c.inside_anon_fn { c.error('missing return at the end of an anonymous function', node.pos) } else { @@ -6605,7 +6605,7 @@ fn has_top_return(stmts []ast.Stmt) bool { } } else if stmt is ast.ExprStmt { if stmt.expr is ast.CallExpr { - if stmt.expr.name in ['panic', 'exit'] { + if !stmt.expr.is_method && stmt.expr.name in ['panic', 'exit'] { return true } } diff --git a/vlib/v/checker/tests/function_missing_return_type.out b/vlib/v/checker/tests/function_missing_return_type.out index 70c8c0ded1..73292af5ea 100644 --- a/vlib/v/checker/tests/function_missing_return_type.out +++ b/vlib/v/checker/tests/function_missing_return_type.out @@ -3,3 +3,10 @@ vlib/v/checker/tests/function_missing_return_type.vv:1:1: error: missing return | ~~~~~~~~~~ 2 | } 3 | +vlib/v/checker/tests/function_missing_return_type.vv:12:1: error: missing return at end of function `abc` + 10 | } + 11 | + 12 | fn (s Abc) abc() &int { + | ~~~~~~~~~~~~~~~~~~~~~ + 13 | if true { + 14 | return &s.x diff --git a/vlib/v/checker/tests/function_missing_return_type.vv b/vlib/v/checker/tests/function_missing_return_type.vv index adaf7b5a5d..74d8cc1e8d 100644 --- a/vlib/v/checker/tests/function_missing_return_type.vv +++ b/vlib/v/checker/tests/function_missing_return_type.vv @@ -1,6 +1,21 @@ fn h() int { } +struct Abc { + x int +} + +fn (s Abc) panic(message string) { + println('called ${@METHOD} with message: $message') +} + +fn (s Abc) abc() &int { + if true { + return &s.x + } + s.panic(@FN) +} + fn main() { d := h() println('$d')