mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2026-04-30 19:09:26 +08:00
Fix #405: push_back() on script-created vector has no effect if vector_conversion is in effect (#663)
* Fix #405: push_back() on script-created vector has no effect with vector_conversion When both vector_type<T> and vector_conversion<T> are registered, the dispatch scoring treats all parameter mismatches equally. This causes the C++ push_back (for the converted type) to be selected over the built-in one when both have the same number of type differences. The converted function operates on a temporary copy of the vector, silently discarding the mutation. The fix deprioritizes overloads that require type conversion on the first parameter (the object/receiver), ensuring functions matching the receiver type exactly are always tried first. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Address review: remove issue references from comments, add round-trip conversion tests Requested by @lefticus in PR #663 review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: leftibot <leftibot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
92abd226a9
commit
255ff87f37
@ -798,6 +798,14 @@ namespace chaiscript {
|
|||||||
++numdiffs;
|
++numdiffs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprioritize functions whose first parameter (object/receiver) requires
|
||||||
|
// type conversion: conversions create temporaries, so mutations on the
|
||||||
|
// converted object are silently lost.
|
||||||
|
if (plist.size() > 1 && !func->get_param_types()[1].bare_equal(plist[0].get_type_info())) {
|
||||||
|
numdiffs = plist.size();
|
||||||
|
}
|
||||||
|
|
||||||
ordered_funcs.emplace_back(numdiffs, func.get());
|
ordered_funcs.emplace_back(numdiffs, func.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1437,6 +1437,68 @@ TEST_CASE("Issue #421 - Switch with type_conversion does not compare destroyed o
|
|||||||
})") == 0);
|
})") == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Regression test: push_back() on script-created vector has no effect when
|
||||||
|
// vector_conversion is in effect. The bug occurs because dispatch selects
|
||||||
|
// the C++ push_back for the converted type over the built-in one, operating
|
||||||
|
// on a temporary copy of the vector.
|
||||||
|
TEST_CASE("push_back on script vector with vector_conversion") {
|
||||||
|
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());
|
||||||
|
|
||||||
|
auto m = std::make_shared<chaiscript::Module>();
|
||||||
|
chaiscript::bootstrap::standard_library::vector_type<std::vector<std::string>>("VectorString", *m);
|
||||||
|
m->add(chaiscript::vector_conversion<std::vector<std::string>>());
|
||||||
|
chai.add(m);
|
||||||
|
|
||||||
|
// Register a C++ function that accepts the converted type, so we can
|
||||||
|
// verify that vector_conversion actually works for passing vectors
|
||||||
|
chai.add(chaiscript::fun([](const std::vector<std::string> &v) -> std::string {
|
||||||
|
std::string result;
|
||||||
|
for (const auto &s : v) {
|
||||||
|
if (!result.empty()) { result += ","; }
|
||||||
|
result += s;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}), "join_strings");
|
||||||
|
|
||||||
|
// push_back on an empty script-created vector must be visible
|
||||||
|
CHECK(chai.eval<bool>(
|
||||||
|
"auto x = [];"
|
||||||
|
"x.push_back(\"Hello\");"
|
||||||
|
"x.size() == 1"
|
||||||
|
));
|
||||||
|
|
||||||
|
// push_back on a vector with initial elements must grow correctly
|
||||||
|
CHECK(chai.eval<bool>(
|
||||||
|
"auto y = [\"a\", \"b\"];"
|
||||||
|
"y.push_back(\"c\");"
|
||||||
|
"y.push_back(\"d\");"
|
||||||
|
"y.size() == 4"
|
||||||
|
));
|
||||||
|
|
||||||
|
// Verify the actual content is preserved after push_back
|
||||||
|
CHECK(chai.eval<std::string>(
|
||||||
|
"auto z = [];"
|
||||||
|
"z.push_back(\"World\");"
|
||||||
|
"z[0]"
|
||||||
|
) == "World");
|
||||||
|
|
||||||
|
// Round-trip: build a vector in script, push_back elements, then pass it
|
||||||
|
// to a C++ function via vector_conversion and verify the contents
|
||||||
|
CHECK(chai.eval<std::string>(
|
||||||
|
"auto v = [\"one\", \"two\"];"
|
||||||
|
"v.push_back(\"three\");"
|
||||||
|
"join_strings(v)"
|
||||||
|
) == "one,two,three");
|
||||||
|
|
||||||
|
// Verify conversion works on a freshly created vector too
|
||||||
|
CHECK(chai.eval<std::string>(
|
||||||
|
"auto w = [];"
|
||||||
|
"w.push_back(\"hello\");"
|
||||||
|
"w.push_back(\"world\");"
|
||||||
|
"join_strings(w)"
|
||||||
|
) == "hello,world");
|
||||||
|
}
|
||||||
|
|
||||||
// Regression test for issue #607: AST_Node_Trace must be a complete type
|
// Regression test for issue #607: AST_Node_Trace must be a complete type
|
||||||
// when used in eval_error's std::vector<AST_Node_Trace> call_stack member.
|
// when used in eval_error's std::vector<AST_Node_Trace> call_stack member.
|
||||||
// This failed to compile with C++20 on clang/libc++ when AST_Node_Trace
|
// This failed to compile with C++20 on clang/libc++ when AST_Node_Trace
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user