checker: add a check for `x := math.sin<f64>(0)`

pull/6841/head
Delyan Angelov 2020-11-15 11:13:35 +02:00
parent 1ead130eed
commit f995aa35ea
6 changed files with 30 additions and 0 deletions

View File

@ -306,6 +306,7 @@ pub mut:
return_type table.Type
should_be_skipped bool
generic_type table.Type // TODO array, to support multiple types
generic_list_pos token.Position
free_receiver bool // true if the receiver expression needs to be freed
// autofree_pregen string
// autofree_vars []AutofreeArgVar

View File

@ -1595,6 +1595,9 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
}
}
}
if call_expr.generic_type.is_full() && !f.is_generic {
c.error('a non generic function called like a generic one', call_expr.generic_list_pos)
}
if f.is_generic {
return call_expr.return_type
}

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/generics_non_generic_fn_called_like_a_generic_one.vv:4:15: error: a non generic function called like a generic one
2 |
3 | fn main() {
4 | x := math.sin<f64>(1.0)
| ~~~~~
5 | println(x)
6 | }

View File

@ -0,0 +1,6 @@
import math
fn main() {
x := math.sin<f64>(1.0)
println(x)
}

View File

@ -27,12 +27,14 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
or_kind = .block
}
mut generic_type := table.void_type
mut generic_list_pos := p.tok.position()
if p.tok.kind == .lt {
// `foo<int>(10)`
p.next() // `<`
p.expr_mod = ''
generic_type = p.parse_type()
p.check(.gt) // `>`
generic_list_pos = generic_list_pos.extend(p.prev_tok.position())
// In case of `foo<T>()`
// T is unwrapped and registered in the checker.
if !generic_type.has_flag(.generic) {
@ -98,6 +100,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
pos: pos
language: language
generic_type: generic_type
generic_list_pos: generic_list_pos
or_block: ast.OrExpr{
stmts: or_stmts
kind: or_kind

View File

@ -106,6 +106,16 @@ pub fn (t Type) idx() int {
return u16(t) & 0xffff
}
[inline]
pub fn (t Type) is_void() bool {
return t == void_type
}
[inline]
pub fn (t Type) is_full() bool {
return t != 0 && t != void_type
}
// return nr_muls for `t`
[inline]
pub fn (t Type) nr_muls() int {