Repository navigation
Disable implicit conversions from JSON values - #17121
Conversation
|
cc @cameel |
|
Is this uncovering some problem in emscripten? Looking at the CI failure of |
7fadddc to
6a6783e
Compare
well, it is not an emscripten problem, but I would say a real one uncovered by this change. The ABI entries are sorted by comparing tuples of JSON values, and tuples use |
|
Interesting, thanks for analyzing the problem! |
yes, emscripten >= 4.0.0 should do it. it comes with llvm 19.1.6. which defines |
hmm it seems right, let me double check, thank you for the comment |
But, I’d still keep the fix, though. The old comparator only worked by accident of overload resolution, with implicit conversions on, Bumping emscripten seems worthwhile on its own, but I’d do it separately from this PR. wdyt? |
I agree now.
Oh, definitely. Updating emscripten is a quest on its own. I have been working through the versions slowly, it's on pause at the moment. |
blishko
left a comment
There was a problem hiding this comment.
I now support this change.
However, I am not convinced we need the extra comment. Opinions?
| // Compare the keys as strings: tuples compare JSON values with operator<=>, which, without | ||
| // three-way comparison support in nlohmann::json, resolves to comparing only their types. |
There was a problem hiding this comment.
I am not sure we need to mention the three-way comparison and its (lack of) support in nlohmann::json.
Such a comment can get outdated quickly.
Also, I am not sure what keys you mean here.
I am not sure we need a comment at all.
If anything, I would personally prefer the following:
// ABI entries are sorted based on their type and name.
There was a problem hiding this comment.
There is another site with the three-way comparison here
solidity/libsolidity/ast/ASTJsonExporter.cpp
Line 677 in bbfadd4
I think the better fix is to set JSON_HAS_THREE_WAY_COMPARISON=1 as compile flag and then update emscripten soon. I am fairly confident these are the only two sites but yeah, it's quite brittle to say the least. Any ordered container, sorting, and/or general comparison between json objects is potentially broken right now.
The test macro __cpp_lib_three_way_comparison that nlohmann json relies on is not set because of unrelated features not being ready yet (like chrono), the spaceship operator itself is available. To be extra safe we can lift the runtime fail to a compile time error:
static_assert(
std::same_as<decltype(std::declval<Json const&>() <=>
std::declval<Json const&>()), std::partial_ordering>
);
With emscripten >= 4.0.0 we can remove the define again if we agree to add it here.
Well, that’s a better fix. So this is addressed:
|
Converting a JSON value to another type can fail, so it should be visible at the call site. With JSON_USE_IMPLICIT_CONVERSIONS=0 such conversions need an explicit get<T>(). The one in StandardCompiler assigned an empty JSON object to a std::map of a freshly constructed struct and did nothing, so it is removed. Tuples, pairs and containers of JSON values compare them with operator<=>, which nlohmann::json only defines when the standard library reports three-way comparison support. The standard library of the emscripten build does not, and without implicit conversions <=> then resolves through the conversion to value_t and compares only the types of the values, which left the ABI unsorted there. Three-way comparison is therefore enabled explicitly, and a static assertion makes sure that <=> compares JSON values.
6a6783e to
0bb88b0
Compare
Defines
JSON_USE_IMPLICIT_CONVERSIONS=0for the whole build. Converting a JSON value to a C++ type can fail, so it should be visible at the call site as an explicitget<T>().The few implicit conversions this turned up are made explicit:
test/libevmasm/Assembler.cppandtest/libsolidity/StandardCompiler.cpp: fivestd::stringinitializations from JSON values.StandardCompiler::parseInput(): the lineret.sources = Json::object();assigned an empty JSON object to thestd::mapof a freshly constructed struct and did nothing, so it is removed.The macro only makes JSON-to-C++ conversions explicit. Conversions from C++ types to JSON through
to_json()remain implicit; nlohmann has no switch for those.Suggested in #16990 (comment)...