Repository navigation
interop: check the registry spelled on an any virtual parameter - #130
Merged
Merged
Conversation
The validate_method_parameter specializations in interop/std_any.hpp, interop/boost_any.hpp and interop/boost_type_erasure.hpp accepted every parameter of their shape unconditionally, so they never compared the registry spelled on one against the method's. Every other virtual parameter shape rejects a mismatch; this one took it silently, while still deciding the registry of a method that named none - so overriders registered against another registry landed in a different dispatch table, and the call reported no_overrider after initialize(). Those specializations were there only because the generic rule did not count a virtual_traits::vptr as a way to reach a v-table. It knew two of the three routes method::vptr tries, the ADL hook and a class the rtti policy deems polymorphic, and a type-erased value has neither. detail::has_vptr_source now names all three, in the order they are tried, so the generic rule covers the interop shapes and applies its registry check and affinity recheck to them. The eleven blanket specializations are gone; boost_type_erasure.hpp keeps the one that is a rejection rather than a blanket accept, an owning any<C, _self> passed by value. The spelling of the new route has to be the one method::vptr uses, `has_vptr<virtual_traits<T, R>, decltype(peek(declval<T>()))>`: the shorter `const virtual_type&` holds for ten of the eleven shapes and fails for `any<C, _self&>`. Stashing include/ brings the issue's reproducer back: it compiles there, and is now rejected with "registry mismatch: the parameter belongs to another registry", the message an ordinary carrier gets. The static_assert naming the routes gains the third; it keeps the substring the compile-fail test matches. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
An automated preview of the documentation is available at https://130.openmethod.prtest3.cppalliance.org/libs/openmethod/doc/html/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-10-13 21:51:13 UTC |
jll63
added a commit
to jll63/openmethod
that referenced
this pull request
Oct 17, 2026
Brings develop up to the interop fix (boostorg#130) and the has_vptr_fn rename (boostorg#131), so this branch builds on its own with the new name, and the two PRs can land in either order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(Written by Claude Code, on behalf of @jll63.)
Closes #123.
detail::validate_method_parameterfor theanyand Boost.TypeErasure interop headers took aParamRegistryand never compared it with the method's. Every other virtual parameter shape rejects a mismatch; this one accepted it silently — and the parameter is not inert, because it decides the registry of a method that names none. Overriders registered against another registry then land in a different dispatch table, and the call reportsno_overriderafterinitialize().One missing route, not twelve missing checks
The specializations were unconditional
std::true_type, which waved the registry check through as a side effect. They existed only because the generic rule did not count avirtual_traits::vptras a way to reach a v-table: it knew two of the three routesmethod::vptrtries — the ADLboost_openmethod_vptrhook, and a class therttipolicy deems polymorphic — and a type-erased value has neither.detail::has_vptr_sourcenow names all three, in the order they are tried. The generic rule then covers the interop shapes and applies its registry check and its affinity recheck to them. The eleven blanket specializations are gone, frominterop/std_any.hpp,interop/boost_any.hppandinterop/boost_type_erasure.hpp; the last keeps the one specialization that is a rejection rather than a blanket accept, an owningany<C, _self>passed by value.The spelling matters.
has_vptr<virtual_traits<T, R>, decltype(peek(declval<T>()))>is whatmethod::vptritself uses; the shorterconst virtual_type&holds for ten of the eleven shapes and fails forany<C, _self&>, whosevptrtakes the reference-boundany. A comment says so, because the shorter form is the obvious later "simplification".virtual_anyis unaffected: its specializations match a different shape,virtual_any<Any, Registry>&, and already compared.Behaviour
Rvirtual_<Animal&, R>— ordinary carriervirtual_<const std::any&, R>— interopvirtual_any<A, R>&An interop parameter is an ordinary carrier, so deciding the registry is the designed behaviour and stays. Only the missing check was a bug.
Tests
compile_fail_std_any_registry_mismatch.cpp— the shape none of the five existing registry-mismatch tests used. The diagnostic is the ordinary "registry mismatch: the parameter belongs to another registry", confirmed on GCC and Clang.test_dispatch_std_any.cppgainsstatic_asserts for the three routes, and for the parameter still deciding the registry of a method that names none.static_assertthat names the routes gains the third; it keeps the substringcompile_fail_non_polymorphic_virtual_parameter.cppmatches.CLAUDE.md's affinity table recorded this as an open bug, and is corrected.Control:
git stash push -- include/brings the issue's reproducer back. It compiles on develop and is rejected here.Verified locally:
-Wextra -Werror)Net 19 insertions against 56 deletions in
include/.🤖 Generated with Claude Code