checker: fix generics call with reference arg (fix #9817 #9818) (#9830)

pull/9833/head
yuyi 2021-04-21 11:40:11 +08:00 committed by GitHub
parent 953057ef35
commit 51258923d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 3 deletions

View File

@ -1058,8 +1058,9 @@ pub fn (mut t Table) resolve_generic_by_names(generic_type Type, generic_names [
// This is used for resolving the generic return type of CallExpr white `unwrap_generic` is used to resolve generic usage in FnDecl.
pub fn (mut t Table) resolve_generic_by_types(generic_type Type, generic_types []Type, concrete_types []Type) ?Type {
mut sym := t.get_type_symbol(generic_type)
if generic_type in generic_types {
index := generic_types.index(generic_type)
gtype := generic_type.set_nr_muls(0) // resolve &T &&T
if gtype in generic_types {
index := generic_types.index(gtype)
typ := concrete_types[index]
return typ.derive(generic_type).clear_flag(.generic)
} else if sym.kind == .array {

View File

@ -508,6 +508,10 @@ pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallEx
if arg.expr.is_auto_deref_var() {
to_set = to_set.deref()
}
// resolve &T &&T ...
if param.typ.nr_muls() > 0 && to_set.nr_muls() > 0 {
to_set = to_set.set_nr_muls(0)
}
// If the parent fn param is a generic too
if to_set.has_flag(.generic) {
to_set = c.unwrap_generic(to_set)

View File

@ -844,7 +844,8 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
fn (mut p Parser) check_fn_mutable_arguments(typ ast.Type, pos token.Position) {
sym := p.table.get_type_symbol(typ)
if sym.kind in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] {
if sym.kind in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_,
.generic_struct_inst, .sum_type] {
return
}
if typ.is_ptr() || typ.is_pointer() {

View File

@ -0,0 +1,26 @@
struct MyStruct<T> {
mut:
pos int
buffer []&T
}
fn (mut s MyStruct<T>) add<T>(e &T) bool {
s.buffer[0] = e
return true
}
fn fill(mut s MyStruct<i64>) {
s.add(&i64(123))
}
fn test_generics_call_with_reference_arg() {
mut s := MyStruct<i64>{
pos: 1
buffer: []&i64{len: 2}
}
fill(mut s)
println(s.pos)
assert s.pos == 1
println(s.buffer.len)
assert s.buffer.len == 2
}