checker: tweak error messages for `or` block; use proper type names (#6377)

pull/6411/head
Nick Treleaven 2020-09-18 00:09:00 +01:00 committed by GitHub
parent f59b771c76
commit 14743458e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 12 deletions

View File

@ -262,6 +262,7 @@ pub mut:
return_type table.Type
}
// break, continue
pub struct BranchStmt {
pub:
tok token.Token

View File

@ -1509,12 +1509,6 @@ pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type
}
mut last_stmt := or_expr.stmts[stmts_len - 1]
if ret_type != table.void_type {
if !(last_stmt is ast.Return || last_stmt is ast.BranchStmt || last_stmt is ast.ExprStmt) {
expected_type_name := c.table.get_type_symbol(ret_type).name
c.error('last statement in the `or {}` block should return `$expected_type_name`',
or_expr.pos)
return
}
match mut last_stmt {
ast.ExprStmt {
last_stmt.typ = c.expr(last_stmt.expr)
@ -1523,8 +1517,8 @@ pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type
if type_fits || is_panic_or_exit {
return
}
type_name := c.table.get_type_symbol(last_stmt.typ).name
expected_type_name := c.table.get_type_symbol(ret_type).name
type_name := c.table.type_to_str(last_stmt.typ)
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.optional))
c.error('wrong return type `$type_name` in the `or {}` block, expected `$expected_type_name`',
last_stmt.pos)
return
@ -1536,9 +1530,14 @@ pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type
return
}
}
else {}
ast.Return {}
else {
expected_type_name := c.table.type_to_str(ret_type.clear_flag(.optional))
c.error('last statement in the `or {}` block should be an expression of type `$expected_type_name` or exit parent scope',
or_expr.pos)
return
}
}
return
}
}

View File

@ -0,0 +1,14 @@
vlib/v/checker/tests/or_err.vv:4:6: error: last statement in the `or {}` block should be an expression of type `&int` or exit parent scope
2 | return none
3 | }
4 | a := f() or {
| ~~~
5 | {}
6 | }
vlib/v/checker/tests/or_err.vv:11:2: error: wrong return type `rune` in the `or {}` block, expected `&int`
9 | }
10 | _ = f() or {
11 | `.`
| ~~~
12 | }
13 |

View File

@ -0,0 +1,13 @@
fn f() ?&int {
return none
}
a := f() or {
{}
}
_ = f() or {
a
}
_ = f() or {
`.`
}

View File

@ -24,14 +24,19 @@ pub enum Language {
js
}
// Represents a type that only needs an identifier, e.g. int, array_int.
// A pointer type `&T` would have a TypeSymbol `T`.
// Note: For a Type, use Table.type_to_str(typ) not TypeSymbol.name.
// Each TypeSymbol is entered into `Table.types`.
// See also: Table.get_type_symbol.
pub struct TypeSymbol {
pub:
parent_idx int
pub mut:
info TypeInfo
kind Kind
name string // the internal name of the type, i.e. `array_fixed_int_5`. See also .source_name below.
source_name string // the original source name of the type, i.e. `[5]int`. Do not use this for logic, but just for formatting/errors.
name string // the internal name of the type or underlying type, i.e. `array_fixed_int_5`. See also .source_name below.
source_name string // the original source name of the type, i.e. `[5]int`.
methods []Fn
mod string
is_public bool