Skip to content

v3: keep same-named types from using str methods of other modules - #28936

Merged
medvednikov merged 1 commit into
masterfrom
fix/json2-toml-any-name-clash
Sep 24, 2026
Merged

medvednikov merged 1 commit into
masterfrom
fix/json2-toml-any-name-clash

Conversation

@medvednikov

Copy link
Copy Markdown
Member

Summary

A program importing both toml and x.json2 failed to compile with V3:

import toml
import x.json2

struct TestStruct {
	key string
}

fn main() {
	t := toml.decode[TestStruct]('key = "val"')!
	println(t.str())
	println(json2.encode[TestStruct](t))
}
src.c: error: initializing 'json2__Any' with an expression of incompatible type 'toml__Any'
    json2__Any __return_array_value_8 = *(toml__Any*)(array_get(__return_array_5, __return_array_idx_7));

Root cause: toml.Any.string() falls back to a.str(), which stringifies the []Any variant. Method lookup then consults receiver_method_suffix_index, which is keyed by short receiver spellings ([]Any.str, Any.str). Only json2 declares such methods, so []toml.Any resolved to json2.[]Any.str and the transformer emitted an element-copy conversion from []toml.Any to []json2.Any. The same lookup also let bmod.Any pick amod.Any.str, and made an explicit toml_array.str() fail in the checker with cannot use receiver `[]toml.Any` as `[]json2.Any` .

Fix:

  • types: suffix_indexed_method_fits_receiver rejects a suffix-index hit when it was declared in a different module from the receiver's struct, sum type or enum. Arrays and maps are checked by their element/value type. The check applies in concrete_method_signature_key and in the checker's unique_receiver_method_suffix_match callers. Aliases, interfaces and structs with embedded fields keep the old lookup, because they can legitimately inherit methods declared in other modules (e.g. an embedded veb.Context).
  • transform: resolve_receiver_method_for_type applies the same check to its suffix match and to the declared_receiver_method fallback. The fallback is only rejected when the index shows another module registered the method. Bare receiver types declared in the current module (Any inside toml) are qualified before asking the checker, so they don't resolve through a stale checker module.

Validation

  • New vlib/v/tests/same_name_types_str_methods/:
    • Local modules withstr and nostr mirror json2.Any and toml.Any. The test covers sum type, array, map, struct and enum stringification (.str(), interpolation, a module-side .str() fallback).
    • toml_and_json2_test.v is the reported program.
    • Both fail on master (checker error / C compile error) and pass with this change.
  • ./v -silent test vlib/v/transform/: 17/17 pass.
  • ./v -silent test vlib/toml/ vlib/json2/: 106 passed, 1 skipped.
  • ./v -silent test vlib/v/types/: 30/31 pass. checker_ownership_alias_test.v hangs in the -d ownership prescan on master too, in other checkouts as well.
  • ./v -silent vlib/v/compiler_errors_test.v: 1720 passed. The one failure, anon_struct_private_field_err, also fails on master.
  • ./v -silent test vlib/v/tests/: 2285 passed, 13 failed. All 13 fail the same way on master: builtin_overflow_test, check_in_is_consistency_test, enum_bitfield_test, enum_from_generic_static_method_test, failing_tests_test, fn_call_mut_ref_args_test, fn_with_opt_or_res_of_multi_return_test, for_in_containers_of_fixed_array_test, for_in_ref_arr_test, struct_aligned_test, struct_heap_large_fixed_array_test, vls/goto_def_test, vls/autocomplete_module_test.

Importing both `toml` and `x.json2` failed to compile: `toml.Any.string()`
stringified its `[]Any` variant through `json2.[]Any.str`, emitting a copy
of `[]toml.Any` into `[]json2.Any` that the C compiler rejected.

Method lookup falls back to `receiver_method_suffix_index`, which is keyed
by short receiver spellings (`[]Any.str`, `Any.str`). When only one module
declares such a method, any same-named type from another module resolved to
it. Reject suffix-index hits whose declaring module differs from the module
of the receiver's struct, sum type or enum (arrays and maps use their
element/value type), in the checker and the transformer. Aliases,
interfaces and structs with embedded fields keep the old lookup, since they
can inherit methods from other modules. The transformer also qualifies bare
receiver types declared in the current module before asking the checker.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T12:41:15.800652Z 3df0eda Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@medvednikov

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 3df0edaea0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@medvednikov
medvednikov merged commit 1b68924 into master Sep 24, 2026
4 of 105 checks passed
@JalonSolov
JalonSolov deleted the fix/json2-toml-any-name-clash branch September 24, 2026 23:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant