mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
parent
e8e75251b4
commit
f31a3b4250
@ -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() {
|
||||
// Check if we are making a comparison between two different types of
|
||||
// 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)
|
||||
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_is_generic := left_type.has_flag(.generic)
|
||||
mut rec_concrete_types := []ast.Type{}
|
||||
if rec_sym.info is ast.Struct {
|
||||
rec_concrete_types = rec_sym.info.concrete_types.clone()
|
||||
if rec_is_generic && node.concrete_types.len == 0
|
||||
&& method.generic_names.len == rec_sym.info.generic_types.len {
|
||||
node.concrete_types = rec_sym.info.generic_types
|
||||
} else if !rec_is_generic && rec_sym.info.concrete_types.len > 0
|
||||
&& node.concrete_types.len > 0
|
||||
&& rec_sym.info.concrete_types.len + node.concrete_types.len == method.generic_names.len {
|
||||
t_concrete_types := node.concrete_types.clone()
|
||||
node.concrete_types = rec_sym.info.concrete_types
|
||||
node.concrete_types << t_concrete_types
|
||||
match rec_sym.info {
|
||||
ast.Struct, ast.SumType, ast.Interface {
|
||||
rec_concrete_types = rec_sym.info.concrete_types.clone()
|
||||
if rec_is_generic && node.concrete_types.len == 0
|
||||
&& method.generic_names.len == rec_sym.info.generic_types.len {
|
||||
node.concrete_types = rec_sym.info.generic_types
|
||||
} else if !rec_is_generic && rec_sym.info.concrete_types.len > 0
|
||||
&& node.concrete_types.len > 0
|
||||
&& rec_sym.info.concrete_types.len + node.concrete_types.len == method.generic_names.len {
|
||||
t_concrete_types := node.concrete_types.clone()
|
||||
node.concrete_types = rec_sym.info.concrete_types
|
||||
node.concrete_types << t_concrete_types
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
mut concrete_types := []ast.Type{}
|
||||
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_utyp := c.table.resolve_generic_to_concrete(got_arg_typ, method.generic_names,
|
||||
method_concrete_types)
|
||||
{
|
||||
got_arg_typ = got_utyp
|
||||
if c.table.cur_fn != unsafe { nil } && c.table.cur_concrete_types.len > 0 {
|
||||
got_arg_typ = c.unwrap_generic(got_arg_typ)
|
||||
} 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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user