From db550eba8fa1ade3cc5bb876a6143d6fa3c35792 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 11 Mar 2026 12:29:52 +0300 Subject: [PATCH] checker: C compilation error with shared struct (fixes #25160) --- vlib/v/ast/table.v | 26 ++++++++++++++++++- .../shared_receiver_mut_interface_err.out | 8 ++++++ .../shared_receiver_mut_interface_err.vv | 17 ++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 vlib/v/checker/tests/shared_receiver_mut_interface_err.out create mode 100644 vlib/v/checker/tests/shared_receiver_mut_interface_err.vv diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index a43a3fb95..1dd70f9ef 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -252,13 +252,18 @@ pub fn (t &Table) is_same_method(f &Fn, func &Fn) string { if lsym.language == .js && rsym.language == .js { return '' } + has_unexpected_sharetype := f.params[i].is_shared != func.params[i].is_shared + || f.params[i].is_atomic != func.params[i].is_atomic has_unexpected_mutability := !f.params[i].is_mut && func.params[i].is_mut - if has_unexpected_type || has_unexpected_mutability { + if has_unexpected_type || has_unexpected_sharetype || has_unexpected_mutability { exps := t.type_to_str(f.params[i].typ) gots := t.type_to_str(func.params[i].typ) if has_unexpected_type { return 'expected `${exps}`, not `${gots}` for parameter ${i}' + } else if has_unexpected_sharetype { + return 'expected `${t.param_type_with_specifier(f.params[i], i == 0)}`, not `${t.param_type_with_specifier(func.params[i], + i == 0)}` for parameter ${i}' } else { return 'expected `${exps}` which is immutable, not `mut ${gots}`' } @@ -267,6 +272,25 @@ pub fn (t &Table) is_same_method(f &Fn, func &Fn) string { return '' } +fn (t &Table) param_type_with_specifier(p Param, is_receiver bool) string { + mut parts := []string{} + if p.is_mut { + parts << 'mut' + } + if p.is_shared { + parts << 'shared' + } + if p.is_atomic { + parts << 'atomic' + } + mut ptyp := p.typ.clear_flags(.shared_f, .atomic_f) + if is_receiver && ptyp.is_ptr() { + ptyp = ptyp.deref() + } + parts << t.type_to_str(ptyp) + return parts.join(' ') +} + pub fn (t &Table) find_fn(name string) ?Fn { if f := t.fns[name] { return f diff --git a/vlib/v/checker/tests/shared_receiver_mut_interface_err.out b/vlib/v/checker/tests/shared_receiver_mut_interface_err.out new file mode 100644 index 000000000..2d6584693 --- /dev/null +++ b/vlib/v/checker/tests/shared_receiver_mut_interface_err.out @@ -0,0 +1,8 @@ +vlib/v/checker/tests/shared_receiver_mut_interface_err.vv:16:19: error: `Input` incorrectly implements method `event` of interface `Handler`: expected `mut Handler`, not `mut shared Input` for parameter 0 + 14 | fn main() { + 15 | mut input := Input{} + 16 | take_handler(mut input) + | ~~~~~ + 17 | } +Details: main.Handler has `fn event(mut x main.Handler)` + main.Input has `fn event(mut input shared main.Input)` diff --git a/vlib/v/checker/tests/shared_receiver_mut_interface_err.vv b/vlib/v/checker/tests/shared_receiver_mut_interface_err.vv new file mode 100644 index 000000000..9fe388e3b --- /dev/null +++ b/vlib/v/checker/tests/shared_receiver_mut_interface_err.vv @@ -0,0 +1,17 @@ +module main + +interface Handler { +mut: + event() +} + +struct Input {} + +fn (shared input Input) event() {} + +fn take_handler(mut _ Handler) {} + +fn main() { + mut input := Input{} + take_handler(mut input) +} -- 2.39.5