mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
@@ -267,7 +267,10 @@ pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type,
|
|||||||
if got_typ_sym.symbol_name_except_generic() == expected_typ_sym.symbol_name_except_generic() {
|
if got_typ_sym.symbol_name_except_generic() == expected_typ_sym.symbol_name_except_generic() {
|
||||||
// Check if we are making a comparison between two different types of
|
// Check if we are making a comparison between two different types of
|
||||||
// the same type like `Type<int> and &Type<>`
|
// the same type like `Type<int> and &Type<>`
|
||||||
if (got.is_ptr() != expected.is_ptr()) || !c.check_same_module(got, expected) {
|
if (got.is_ptr() != expected.is_ptr())
|
||||||
|
|| !c.check_same_module(got, expected)
|
||||||
|
|| (!got.is_ptr() && !expected.is_ptr()
|
||||||
|
&& got_typ_sym.name != expected_typ_sym.name) {
|
||||||
got_typ_str, expected_typ_str := c.get_string_names_of(got, expected)
|
got_typ_str, expected_typ_str := c.get_string_names_of(got, expected)
|
||||||
return error('cannot use `$got_typ_str` as `$expected_typ_str`')
|
return error('cannot use `$got_typ_str` as `$expected_typ_str`')
|
||||||
}
|
}
|
||||||
|
@@ -1428,18 +1428,21 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||||||
rec_sym := c.table.final_sym(node.left_type)
|
rec_sym := c.table.final_sym(node.left_type)
|
||||||
rec_is_generic := left_type.has_flag(.generic)
|
rec_is_generic := left_type.has_flag(.generic)
|
||||||
mut rec_concrete_types := []ast.Type{}
|
mut rec_concrete_types := []ast.Type{}
|
||||||
if rec_sym.info is ast.Struct {
|
match rec_sym.info {
|
||||||
rec_concrete_types = rec_sym.info.concrete_types.clone()
|
ast.Struct, ast.SumType, ast.Interface {
|
||||||
if rec_is_generic && node.concrete_types.len == 0
|
rec_concrete_types = rec_sym.info.concrete_types.clone()
|
||||||
&& method.generic_names.len == rec_sym.info.generic_types.len {
|
if rec_is_generic && node.concrete_types.len == 0
|
||||||
node.concrete_types = rec_sym.info.generic_types
|
&& method.generic_names.len == rec_sym.info.generic_types.len {
|
||||||
} else if !rec_is_generic && rec_sym.info.concrete_types.len > 0
|
node.concrete_types = rec_sym.info.generic_types
|
||||||
&& node.concrete_types.len > 0
|
} else if !rec_is_generic && rec_sym.info.concrete_types.len > 0
|
||||||
&& rec_sym.info.concrete_types.len + node.concrete_types.len == method.generic_names.len {
|
&& node.concrete_types.len > 0
|
||||||
t_concrete_types := node.concrete_types.clone()
|
&& rec_sym.info.concrete_types.len + node.concrete_types.len == method.generic_names.len {
|
||||||
node.concrete_types = rec_sym.info.concrete_types
|
t_concrete_types := node.concrete_types.clone()
|
||||||
node.concrete_types << t_concrete_types
|
node.concrete_types = rec_sym.info.concrete_types
|
||||||
|
node.concrete_types << t_concrete_types
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else {}
|
||||||
}
|
}
|
||||||
mut concrete_types := []ast.Type{}
|
mut concrete_types := []ast.Type{}
|
||||||
for concrete_type in node.concrete_types {
|
for concrete_type in node.concrete_types {
|
||||||
@@ -1644,12 +1647,16 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if got_arg_typ.has_flag(.generic) {
|
if got_arg_typ.has_flag(.generic) {
|
||||||
if got_utyp := c.table.resolve_generic_to_concrete(got_arg_typ, method.generic_names,
|
if c.table.cur_fn != unsafe { nil } && c.table.cur_concrete_types.len > 0 {
|
||||||
method_concrete_types)
|
got_arg_typ = c.unwrap_generic(got_arg_typ)
|
||||||
{
|
|
||||||
got_arg_typ = got_utyp
|
|
||||||
} else {
|
} else {
|
||||||
continue
|
if got_utyp := c.table.resolve_generic_to_concrete(got_arg_typ,
|
||||||
|
method.generic_names, method_concrete_types)
|
||||||
|
{
|
||||||
|
got_arg_typ = got_utyp
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
vlib/v/checker/tests/generics_method_sumtype_arg_mismatch.vv:56:13: error: cannot use `Maybe<string>` as `Maybe<int>` in argument 1 to `Maybe<int>.or`
|
||||||
|
54 | b := some('abc')
|
||||||
|
55 |
|
||||||
|
56 | c := a.@or(b)
|
||||||
|
| ^
|
||||||
|
57 | println(c)
|
||||||
|
58 | }
|
58
vlib/v/checker/tests/generics_method_sumtype_arg_mismatch.vv
Normal file
58
vlib/v/checker/tests/generics_method_sumtype_arg_mismatch.vv
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
struct None {}
|
||||||
|
|
||||||
|
pub type Maybe<T> = None | T
|
||||||
|
|
||||||
|
pub fn (m Maybe<T>) str<T>() string {
|
||||||
|
return if m is T {
|
||||||
|
x := m as T
|
||||||
|
'Some($x)'
|
||||||
|
} else {
|
||||||
|
'Noth'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn some<T>(v T) Maybe<T> {
|
||||||
|
return Maybe<T>(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noth<T>() Maybe<T> {
|
||||||
|
return Maybe<T>(None{})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (m Maybe<T>) is_some<T>() bool {
|
||||||
|
return match m {
|
||||||
|
None { false }
|
||||||
|
T { true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (m Maybe<T>) is_noth<T>() bool {
|
||||||
|
return match m {
|
||||||
|
None { true }
|
||||||
|
T { false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (m Maybe<T>) @or<T>(m2 Maybe<T>) Maybe<T> {
|
||||||
|
return match m {
|
||||||
|
None {
|
||||||
|
match m2 {
|
||||||
|
None { None{} }
|
||||||
|
T { m2 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T {
|
||||||
|
m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
a := some(123)
|
||||||
|
b := some('abc')
|
||||||
|
|
||||||
|
c := a.@or(b)
|
||||||
|
println(c)
|
||||||
|
}
|
Reference in New Issue
Block a user