From 5db20438205b707e17288e56c607bf952295a686 Mon Sep 17 00:00:00 2001 From: Perfloop Agent Date: Mon, 2 Nov 2026 22:01:37 +0000 Subject: [PATCH 1/2] Test try_emplace argument evaluation and conditional construction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Perfloop Agent Signed-off-by: Tomás Senart --- tests/unit/map_try_emplace.cpp | 122 +++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 tests/unit/map_try_emplace.cpp diff --git a/tests/unit/map_try_emplace.cpp b/tests/unit/map_try_emplace.cpp new file mode 100644 index 000000000..bee6028e4 --- /dev/null +++ b/tests/unit/map_try_emplace.cpp @@ -0,0 +1,122 @@ +#include +#include +#include + +int calls = 0; +int made = 0; +int copies = 0; +int moves = 0; + +struct Item { + int value; + Item() : value(0) {} + Item(int value) : value(value) { ++made; } + Item(const Item &other) : value(other.value) { ++copies; } + Item(Item &&other) : value(other.value) { + ++moves; + other.value = -1; + } +}; + +Item &argument(Item &item) { + ++calls; + return item; +} + +struct RefItem { + int value; + RefItem() : value(0) {} + RefItem(int &counter, int amount) : value(counter += amount) { ++made; } +}; + +int &reference(int &counter) { + ++calls; + return counter; +} + +std::map global_map; +int global_key = 0; +int global_counter = 0; +int seed = (global_map[global_key] = 10, 0); +auto global_hit = global_map.try_emplace(global_key, ++global_counter); + +int main() { + bool ok = global_counter == 1 && !global_hit.second && + global_hit.first->second == 10; + int rows = 0; + for (int subset = 0; subset < 8; ++subset) { + for (int key = 0; key < 3; ++key) { + for (int initial = 0; initial < 3; ++initial) { + for (int post = 0; post < 2; ++post) { + std::map m; + int size = 0; + for (int k = 0; k < 3; ++k) { + if (subset & (1 << k)) { + m[k] = 10 + k; + ++size; + } + } + int counter = initial; + auto result = post ? m.try_emplace(key, counter++) + : m.try_emplace(key, ++counter); + bool hit = (subset & (1 << key)) != 0; + ok &= counter == initial + 1; + ok &= result.second == !hit; + bool found = result.first == m.find(key); + ok &= found; + ok &= result.first->first == key; + ok &= result.first->second == (hit ? 10 + key : initial + !post); + ok &= m.size() == size + !hit; + ++rows; + } + } + } + } + + std::map items; + int key = 0; + items.try_emplace(key, 10); + Item source(20); + made = copies = moves = 0; + auto hit = items.try_emplace(key, argument(source)); + ok &= calls == 1 && made == 0 && copies == 0 && moves == 0; + ok &= !hit.second && hit.first->second.value == 10; + auto move_hit = items.try_emplace(key, std::move(argument(source))); + ok &= calls == 2 && made == 0 && copies == 0 && moves == 0; + ok &= !move_hit.second && source.value == 20; + ++key; + auto copied = items.try_emplace(key, argument(source)); + ok &= calls == 3 && made == 0 && copies == 1 && moves == 0; + ok &= copied.second && copied.first->second.value == 20; + ++key; + auto moved = items.try_emplace(key, std::move(argument(source))); + ok &= calls == 4 && made == 0 && copies == 1 && moves == 1; + ok &= moved.second && moved.first->second.value == 20 && source.value == -1; + + std::map refs; + key = 0; + int counter = 0; + refs.try_emplace(key, counter, 5); + made = 0; + auto ref_hit = refs.try_emplace(key, reference(counter), 2); + ok &= calls == 5 && counter == 5 && made == 0 && !ref_hit.second; + ++key; + auto ref_new = refs.try_emplace(key, reference(counter), 2); + ok &= calls == 6 && counter == 7 && made == 1 && ref_new.second; + ok &= ref_hit.first->second.value == 5 && ref_new.first->second.value == 7; + + // A temporary argument is constructed on a hit, but is not moved from. + key = 0; + made = copies = moves = 0; + auto temporary_hit = items.try_emplace(key, Item(30)); + ok &= made == 1 && copies == 0 && moves == 0 && !temporary_hit.second; + ++key; + ++key; + ++key; + auto temporary_new = items.try_emplace(key, Item(40)); + ok &= made == 2 && copies == 0 && moves == 1 && temporary_new.second; + ok &= temporary_new.first->second.value == 40; + + printf("%d %d %d %d %d\n", rows, calls, made, copies, moves); + return ok ? 0 : 1; +} From def575b80b269e9138c2c5f0d79344990f293c1f Mon Sep 17 00:00:00 2001 From: Perfloop Agent Date: Mon, 2 Nov 2026 22:01:38 +0000 Subject: [PATCH 2/2] Evaluate try_emplace arguments before checking the key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Perfloop Agent Signed-off-by: Tomás Senart --- cpp2rust/converter/converter.cpp | 76 +- cpp2rust/converter/converter.h | 1 + cpp2rust/converter/models/boxed_vars.cpp | 33 +- .../converter/models/converter_refcount.cpp | 10 + cpp2rust/converter/translation_rule.cpp | 29 +- cpp2rust/converter/translation_rule.h | 5 +- docs/src/rules/ir.md | 5 +- rule-preprocessor/src/ir.rs | 2 + rule-preprocessor/src/syntactic.rs | 1 + tests/unit/map_try_emplace_lvalues.cpp | 88 +++ tests/unit/out/refcount/map_try_emplace.rs | 717 ++++++++++++++++++ .../out/refcount/map_try_emplace_lvalues.rs | 697 +++++++++++++++++ tests/unit/out/unsafe/map_try_emplace.rs | 421 ++++++++++ .../out/unsafe/map_try_emplace_lvalues.rs | 410 ++++++++++ 14 files changed, 2484 insertions(+), 11 deletions(-) create mode 100644 tests/unit/map_try_emplace_lvalues.cpp create mode 100644 tests/unit/out/refcount/map_try_emplace.rs create mode 100644 tests/unit/out/refcount/map_try_emplace_lvalues.rs create mode 100644 tests/unit/out/unsafe/map_try_emplace.rs create mode 100644 tests/unit/out/unsafe/map_try_emplace_lvalues.rs diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 993bcdca6..92bc8f0ed 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2697,6 +2697,10 @@ bool Converter::VisitCXXRewrittenBinaryOperator( } bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) { + if (expr->isAssignmentOp() && isAddrOf()) { + ConvertAssignmentRef(expr); + return false; + } if (expr->getOpcode() == clang::BO_Cmp) { EmitFresh(std::format("std::cmp::Ord::cmp(&({}), &({}))", ConvertRValue(expr->getLHS()), @@ -2717,6 +2721,52 @@ bool Converter::VisitBinaryOperator(clang::BinaryOperator *expr) { return false; } +void Converter::ConvertAssignmentRef(clang::BinaryOperator *expr) { + auto *lhs = expr->getLHS(); + auto *rhs = expr->getRHS(); + auto value = ConvertFreshRValue(rhs); + auto ptr = ConvertFreshObject(lhs); + auto loc = expr->getExprLoc(); + clang::DeclContext *context = curr_function_; + if (!context) { + context = + clang::BlockDecl::Create(ctx_, ctx_.getTranslationUnitDecl(), loc); + } + auto bind = [&](clang::QualType type) { + return clang::VarDecl::Create( + ctx_, context, loc, loc, &ctx_.Idents.get(NewTempName()), type, + ctx_.getTrivialTypeSourceInfo(type, loc), clang::SC_None); + }; + auto *left = bind(ctx_.getLValueReferenceType(lhs->getType())); + auto *right = bind(rhs->getType()); + bound_values_.insert(right); + auto ref = [&](clang::VarDecl *var) { + return clang::DeclRefExpr::Create(ctx_, {}, {}, var, false, loc, + var->getType().getNonReferenceType(), + clang::VK_LValue); + }; + expr->setLHS(ref(left)); + expr->setRHS(clang::ImplicitCastExpr::Create( + ctx_, rhs->getType(), clang::CK_LValueToRValue, ref(right), nullptr, + clang::VK_PRValue, clang::FPOptionsOverride())); + std::string assignment; + { + Buffer buf(*this); + PushExprKind push(*this, ExprKind::Void); + ConvertBinaryOperator(expr); + assignment = std::move(buf).str(); + } + expr->setLHS(lhs); + expr->setRHS(rhs); + // C++ evaluates the right operand before finding the place to write. Reuse + // the ordinary assignment conversion on the bound operands, then return the + // same place, without evaluating either operand again. + StrCat(std::format( + "match ({{ {0} }}, {1}) {{ ({2}, {3}) => {{ {4}; {3} }} }}", value, ptr, + GetNamedDeclAsString(right), GetNamedDeclAsString(left), assignment)); + MarkFresh(); +} + void Converter::ConvertBinaryOperator(clang::BinaryOperator *expr) { auto type = expr->getType(); auto *lhs = expr->getLHS(); @@ -2895,6 +2945,14 @@ bool Converter::ConvertIncAndDec(clang::UnaryOperator *expr) { if (!method) { return false; } + if (expr->isPrefix() && isAddrOf()) { + auto ptr = ConvertFreshObject(expr->getSubExpr()); + auto name = NewTempName(); + StrCat(std::format("{{ let {0} = {1}; (*{0}).{2}(); {0} }}", name, ptr, + method)); + MarkFresh(); + return true; + } { PushExprKind push(*this, ExprKind::LValue); Convert(expr->getSubExpr()); @@ -5137,8 +5195,13 @@ std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args, auto all_args = BuildUnifiedArgs(expr, args, num_args); auto bind = tgt_ir->argsToBind(ctx_, expr, all_args); std::vector values, names; - // The variables are local to the function. - for (size_t i = 0; curr_function_ && i < all_args.size(); ++i) { + // Bindings in a global initializer are local to the expansion too. + clang::DeclContext *binding_context = curr_function_; + if (!binding_context && tgt_ir->usesInit()) { + binding_context = clang::BlockDecl::Create( + ctx_, ctx_.getTranslationUnitDecl(), expr->getExprLoc()); + } + for (size_t i = 0; binding_context && i < all_args.size(); ++i) { if (!bind[i]) { continue; } @@ -5158,7 +5221,7 @@ std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args, auto var_type = by_value ? type : ctx_.getLValueReferenceType(type); auto loc = arg->getExprLoc(); auto *var = clang::VarDecl::Create( - ctx_, curr_function_, loc, loc, &ctx_.Idents.get(NewTempName()), + ctx_, binding_context, loc, loc, &ctx_.Idents.get(NewTempName()), var_type, ctx_.getTrivialTypeSourceInfo(var_type, loc), clang::SC_None); // The temporaries of a value, e.g., borrows, end with its block. if (by_value) { @@ -5170,8 +5233,15 @@ std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args, arg, ToString(ctx_.getPointerType(type)), convert_to)); } names.push_back((by_value ? "mut " : "") + GetNamedDeclAsString(var)); + // Preserve the value category used to forward an init argument to its + // constructor, in particular an rvalue that must be moved, not copied. all_args[i] = clang::DeclRefExpr::Create(ctx_, {}, {}, var, false, loc, type, clang::VK_LValue); + if (i >= tgt_ir->params.size() && arg->isXValue()) { + all_args[i] = clang::ImplicitCastExpr::Create( + ctx_, type, clang::CK_NoOp, all_args[i], nullptr, clang::VK_XValue, + clang::FPOptionsOverride()); + } if (by_value && !type->isRecordType()) { all_args[i] = clang::ImplicitCastExpr::Create( ctx_, type, clang::CK_LValueToRValue, all_args[i], nullptr, diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index e0560d8c4..136ed4dc5 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -506,6 +506,7 @@ class Converter : public clang::RecursiveASTVisitor { virtual bool VisitBinaryOperator(clang::BinaryOperator *expr); bool VisitCXXRewrittenBinaryOperator(clang::CXXRewrittenBinaryOperator *expr); + void ConvertAssignmentRef(clang::BinaryOperator *expr); virtual void ConvertBinaryOperator(clang::BinaryOperator *expr); // The value that the compound assignment expr assigns to its left operand, diff --git a/cpp2rust/converter/models/boxed_vars.cpp b/cpp2rust/converter/models/boxed_vars.cpp index 429584bca..cd7dd639f 100644 --- a/cpp2rust/converter/models/boxed_vars.cpp +++ b/cpp2rust/converter/models/boxed_vars.cpp @@ -237,11 +237,17 @@ class AddressTakenVisitor if (!rule) { return; } - // Variadic arguments are not considered. auto all_args = BuildUnifiedArgs(expr, args, num_args); auto bound = rule->argsToBind(ctx_, expr, all_args); - for (unsigned i = 0; i < all_args.size() && i < rule->params.size(); ++i) { + for (unsigned i = 0; i < all_args.size(); ++i) { if (bound[i]) { + if (all_args[i]->isGLValue()) { + AddAddressUse(all_args[i]); + } + continue; + } + // Unbound variadic arguments are not considered. + if (i >= rule->params.size()) { continue; } auto *arg = IgnoreNoOpCasts(all_args[i]); @@ -279,6 +285,29 @@ class AddressTakenVisitor } } + // A bound lvalue must stay addressable even when its evaluation also writes + // it, as in ++counter or counter = value. + void AddAddressUse(const clang::Expr *expr) { + expr = expr->IgnoreParenImpCasts(); + if (auto *ref = clang::dyn_cast(expr)) { + AddressTaken(ref->getDecl()); + } else if (auto *object = GetEnclosingObject(expr)) { + AddAddressUse(object); + } else if (auto *unary = clang::dyn_cast(expr); + unary && unary->isIncrementDecrementOp()) { + AddAddressUse(unary->getSubExpr()); + } else if (auto *binary = clang::dyn_cast(expr)) { + if (binary->isAssignmentOp()) { + AddAddressUse(binary->getLHS()); + } else if (binary->getOpcode() == clang::BO_Comma) { + AddAddressUse(binary->getRHS()); + } + } else if (auto *cond = clang::dyn_cast(expr)) { + AddAddressUse(cond->getTrueExpr()); + AddAddressUse(cond->getFalseExpr()); + } + } + void AddressTaken(const clang::ValueDecl *decl) { if (!IsUserDefinedDecl(decl)) { return; diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 800e452e4..fb8397350 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -909,6 +909,16 @@ bool ConverterRefCount::ConvertIncAndDec(clang::UnaryOperator *expr) { return false; } + if (expr->isPrefix() && isAddrOf()) { + auto ptr = ConvertFreshObject(sub_expr); + auto name = NewTempName(); + StrCat( + std::format("{{ let {0} = {1}; {0}.with_mut(|__v| __v.{2}()); {0} }}", + name, ptr, method)); + MarkFresh(); + return true; + } + auto str = ConvertLValue(sub_expr); if (!pending_deref_.empty()) { StrCat(pending_deref_.take(), ".with_mut(|__v| __v.", method, "())"); diff --git a/cpp2rust/converter/translation_rule.cpp b/cpp2rust/converter/translation_rule.cpp index f8b15d84e..ac02f9a5a 100644 --- a/cpp2rust/converter/translation_rule.cpp +++ b/cpp2rust/converter/translation_rule.cpp @@ -126,7 +126,8 @@ std::vector ParseBodyFragmentsJSON(const llvm::json::Array &arr) { } else if (frag_obj->get("va_args")) { result.push_back(VaArgsFragment{}); } else if (frag_obj->get("init")) { - result.push_back(InitFragment{}); + result.push_back( + InitFragment{frag_obj->getBoolean("conditional").value_or(false)}); } } return result; @@ -271,6 +272,18 @@ ExprRule::argsToBind(clang::ASTContext &ctx, const clang::Expr *expr, ++uses[ph->n]; } ++position; + } else if (auto *init = std::get_if(&frag)) { + // init constructs from the trailing arguments at this position, but + // their evaluation belongs to the call even when construction is skipped. + for (size_t i = params.size(); i < args.size(); ++i) { + if (uses[i]++ == 0) { + first[i] = position; + } + if (init->conditional) { + ++uses[i]; + } + ++position; + } } return false; }); @@ -280,7 +293,9 @@ ExprRule::argsToBind(clang::ASTContext &ctx, const clang::Expr *expr, std::vector bind(args.size()); bool bind_rest = false; unsigned next_first = position; - auto num_args = std::min(args.size(), params.size()); + bool init_args = usesInit(); + auto num_args = + init_args ? args.size() : std::min(args.size(), params.size()); for (auto k = num_args; k-- > 0;) { auto i = right_to_left ? num_args - 1 - k : k; auto *arg = args[i]; @@ -291,8 +306,10 @@ ExprRule::argsToBind(clang::ASTContext &ctx, const clang::Expr *expr, if (arg->HasSideEffects(ctx)) { // A temporary that a reference parameter is bound to would be // materialized before the call, out of order. - bind_rest |= uses[i] > 1 || takesTemporaryAddress(ctx, expr, i, arg) || - (uses[i] == 1 && first[i] > next_first); + bind_rest |= + uses[i] > 1 || + (i < params.size() && takesTemporaryAddress(ctx, expr, i, arg)) || + (uses[i] == 1 && first[i] > next_first); bind[i] = bind_rest; if (uses[i] == 1) { next_first = std::min(next_first, first[i]); @@ -309,6 +326,10 @@ ExprRule::argsToBind(clang::ASTContext &ctx, const clang::Expr *expr, bool ExprRule::takesAddress(clang::ASTContext &ctx, unsigned i, const clang::Expr *arg) const { + // An init pack forwards references to its arguments, not their values. + if (i >= params.size()) { + return usesInit(); + } return params[i].is_pointer() && !arg->getType()->isPointerType() && !RuleRegistry::MapsToPointer(ctx, arg->getType()); } diff --git a/cpp2rust/converter/translation_rule.h b/cpp2rust/converter/translation_rule.h index 17998c262..3a43fc494 100644 --- a/cpp2rust/converter/translation_rule.h +++ b/cpp2rust/converter/translation_rule.h @@ -49,6 +49,8 @@ struct VaArgsFragment { }; struct InitFragment { + bool conditional = false; + void dump() const; }; @@ -122,7 +124,8 @@ struct ExprRule { // evaluated once and in order: those with side effects that the body may // evaluate more than once, or after a later one, and those with side effects // evaluated before them. Values computed from others, which the body may - // evaluate more than once, are bound too. args are those of expr. + // evaluate more than once, are bound too. Arguments a conditional init would + // skip are bound without constructing init. args are those of expr. std::vector argsToBind(clang::ASTContext &ctx, const clang::Expr *expr, llvm::ArrayRef args) const; diff --git a/docs/src/rules/ir.md b/docs/src/rules/ir.md index 10dda2679..edbd85d7c 100644 --- a/docs/src/rules/ir.md +++ b/docs/src/rules/ir.md @@ -83,7 +83,10 @@ The fragment kinds are: result it emits the lvalue alone, so `p.first = 1.5` is `p.0 = 1.5` rather than `(*&mut p.0) = 1.5`. - `va_args`: the expansion point for a variadic tail. -- `init`: the value built from the call's trailing arguments. +- `init`: the value built from the call's trailing arguments. Its optional + `conditional` flag marks construction in a branch, loop, or closure. The + converter binds side-effectful arguments before entering such a rule body, + without making the construction unconditional. Every type in the Rules IR (in `params`, `return_type`, and type rules) is a `TypeInfo` object, the type text plus a set of flags: diff --git a/rule-preprocessor/src/ir.rs b/rule-preprocessor/src/ir.rs index e58ee2404..94e340933 100644 --- a/rule-preprocessor/src/ir.rs +++ b/rule-preprocessor/src/ir.rs @@ -182,6 +182,8 @@ pub enum BodyFragment { }, Init { init: std::marker::PhantomData<()>, + #[serde(default, skip_serializing_if = "std::ops::Not::not")] + conditional: bool, }, GenericCall { generic_call: GenericCallInner, diff --git a/rule-preprocessor/src/syntactic.rs b/rule-preprocessor/src/syntactic.rs index b564eb807..12581f091 100644 --- a/rule-preprocessor/src/syntactic.rs +++ b/rule-preprocessor/src/syntactic.rs @@ -248,6 +248,7 @@ impl<'a> FragmentCtx<'a> { self.flush_text(); self.fragments.push(BodyFragment::Init { init: std::marker::PhantomData, + conditional: Self::is_conditional(token), }); return; } diff --git a/tests/unit/map_try_emplace_lvalues.cpp b/tests/unit/map_try_emplace_lvalues.cpp new file mode 100644 index 000000000..94c7be800 --- /dev/null +++ b/tests/unit/map_try_emplace_lvalues.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +int made = 0; +int visits = 0; + +struct Item { + int value; + Item() : value(0) {} + Item(int &counter, int amount) : value(counter += amount) { ++made; } +}; + +std::map &receiver(std::map &m) { + ++visits; + return m; +} + +int &place(int &n) { + ++visits; + return n; +} + +int main() { + std::map m; + int key = 0, counter = 0; + m.try_emplace(key, counter, 3); + made = 0; + auto hit = receiver(m).try_emplace(key, ++place(counter), 2); + assert(counter == 4 && made == 0 && visits == 2 && !hit.second); + ++key; + auto inserted = m.try_emplace(key, ++counter, 2); + assert(counter == 7 && made == 1 && inserted.second); + auto assigned = m.try_emplace(key, counter = 9, 2); + assert(counter == 9 && made == 1 && !assigned.second); + ++key; + auto compound = m.try_emplace(key, counter += 4, 2); + assert(counter == 15 && made == 2 && compound.second); + assert(inserted.first->second.value == 7 && + compound.first->second.value == 15); + int array[2] = {0, 0}; + int index = 0; + ++key; + m.try_emplace(key, ++array[index++], 3); + assert(index == 1 && array[0] == 4 && made == 3); + ++key; + m.try_emplace(key, array[index++] = 5, 3); + assert(index == 2 && array[1] == 8 && made == 4); + m.try_emplace(key, counter = counter + 1, 3); + assert(counter == 16 && made == 4); + int a = 0, b = 0; + bool choose = false; + m.try_emplace(key, choose ? ++a : ++b, 3); + assert(a == 0 && b == 1 && made == 4); + choose = true; + m.try_emplace(key, choose ? ++a : ++b, 3); + assert(a == 1 && b == 1 && made == 4); + m.try_emplace(key, (counter++, counter), 3); + assert(counter == 17 && made == 4); + + // Keep the ordinary arithmetic conversions and wrapping of compound writes. + std::map unsigned_map; + unsigned n = ~0u; + auto wrapped = unsigned_map.try_emplace(key, n += 1); + assert(n == 0 && wrapped.first->second == 0); + unsigned char bytes[2] = {255, 0}; + index = 0; + ++key; + auto narrowed = unsigned_map.try_emplace(key, bytes[index++] += 2); + assert(index == 1 && bytes[0] == 1 && narrowed.first->second == 1); + + std::map pointers; + int *p = array; + auto pointer = pointers.try_emplace(key, p += 1); + assert(p == array + 1 && pointer.first->second == p); + + std::map strings; + std::string text = "value"; + strings.try_emplace(key, "original"); + auto string_hit = strings.try_emplace(key, std::move((++visits, text))); + assert(visits == 3 && !string_hit.second && text == "value"); + ++key; + auto string_new = strings.try_emplace(key, std::move((++visits, text))); + assert(visits == 4 && string_new.second && + string_new.first->second == "value"); + return 0; +} diff --git a/tests/unit/out/refcount/map_try_emplace.rs b/tests/unit/out/refcount/map_try_emplace.rs new file mode 100644 index 000000000..b876dceed --- /dev/null +++ b/tests/unit/out/refcount/map_try_emplace.rs @@ -0,0 +1,717 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +thread_local!( + pub static calls_0: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static made_1: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static copies_2: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static moves_3: Value = Rc::new(RefCell::new(0)); +); +#[derive(Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, CppFrom)] +#[cpp_from(i32, new_1, value)] +#[byte_size(4)] +pub struct Item { + #[offset(0)] + pub value: i32, +} +impl Item { + pub fn new_2() -> Self { + Self { value: 0 } + } + pub fn new_1(mut value: i32) -> Self { + let __this: Item = Self { value: value }; + (*made_1.with(Value::clone).borrow_mut()).prefix_inc(); + __this + } + pub fn copy_from(other: Ptr) -> Self { + let __this: Item = Self { + value: other.with(|__s| __s.value), + }; + (*copies_2.with(Value::clone).borrow_mut()).prefix_inc(); + __this + } + pub fn move_from(other: Ptr) -> Self { + let __this: Item = Self { + value: other.with(|__s| __s.value), + }; + (*moves_3.with(Value::clone).borrow_mut()).prefix_inc(); + field!(other, value).write(-1_i32); + __this + } +} +impl Clone for Item { + fn clone(&self) -> Self { + let __src: Value = Rc::new(RefCell::new(Item { + value: self.value.clone(), + })); + Item::copy_from(__src.as_pointer()) + } +} +impl Default for Item { + fn default() -> Self { + { Item::new_2() } + } +} +pub fn argument_4(item: Ptr) -> Ptr { + (*calls_0.with(Value::clone).borrow_mut()).prefix_inc(); + return (item).clone(); +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg)] +#[byte_size(4)] +pub struct RefItem { + #[offset(0)] + pub value: i32, +} +impl RefItem { + pub fn new_1() -> Self { + Self { value: 0 } + } + pub fn new_2(counter: Ptr, mut amount: i32) -> Self { + let __this: RefItem = Self { + value: { + { + let __rhs = { amount }; + counter.with_mut(|__v| *__v = *__v + __rhs) + }; + (counter.read()) + }, + }; + (*made_1.with(Value::clone).borrow_mut()).prefix_inc(); + __this + } +} +impl Default for RefItem { + fn default() -> Self { + { RefItem::new_1() } + } +} +pub fn reference_5(counter: Ptr) -> Ptr { + (*calls_0.with(Value::clone).borrow_mut()).prefix_inc(); + return (counter).clone(); +} +thread_local!( + pub static global_map_6: Value, Value)>> = + Rc::new(RefCell::new(Map::new())); +); +thread_local!( + pub static global_key_7: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static global_counter_8: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static seed_9: Value = Rc::new(RefCell::new({ + Map::subscript( + global_map_6.with(|v| v.as_pointer()), + global_key_7.with(|v| v.as_pointer()), + ) + .write(10); + 0 + })); +); +thread_local!( + pub static global_hit_10: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match ({ + let __tmp_1 = global_counter_8.with(|v| v.as_pointer()); + __tmp_1.with_mut(|__v| __v.prefix_inc()); + __tmp_1 + },) + { + (__tmp_0,) => { + let __inserted = global_map_6.with(|v| v.as_pointer()).with( + |__m: &Map, Value)>| { + __m.get(&global_key_7.with(|v| v.as_pointer())).is_none() + }, + ); + if __inserted { + Map::subscript( + global_map_6.with(|v| v.as_pointer()).clone(), + global_key_7.with(|v| v.as_pointer()).clone(), + ) + .write((__tmp_0.read())); + } + ( + Rc::new(RefCell::new(global_map_6.with(|v| v.as_pointer()).with( + |__m: &Map, Value)>| { + __m.find(&global_key_7.with(|v| v.as_pointer())) + }, + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); +); +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let mut ok: bool = ((global_counter_8.with(|rc| *rc.borrow()) == 1) + && (!(*(*global_hit_10.with(Value::clone).borrow()).1.borrow()))) + && ((*(*(*(*global_hit_10.with(Value::clone).borrow()).0.borrow()) + .iter_deref() + .upgrade() + .deref()) + .1 + .borrow()) + == 10); + let mut rows: i32 = 0; + let mut subset: i32 = 0; + 'loop_: while (subset < 8) { + let key: Value = Rc::new(RefCell::new(0)); + 'loop_: while ((*key.borrow()) < 3) { + let mut initial: i32 = 0; + 'loop_: while (initial < 3) { + let mut post: i32 = 0; + 'loop_: while (post < 2) { + let m: Value, Value)>> = + Rc::new(RefCell::new(Map::new())); + let mut size: i32 = 0; + let k: Value = Rc::new(RefCell::new(0)); + 'loop_: while ((*k.borrow()) < 3) { + if ((subset & (1 << (*k.borrow()))) != 0) { + let __rhs = (10 + (*k.borrow())); + Map::subscript(m.as_pointer(), k.as_pointer()).write(__rhs); + size.prefix_inc(); + } + (*k.borrow_mut()).prefix_inc(); + } + let counter: Value = Rc::new(RefCell::new(initial)); + let result: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new(if (post != 0) { + match (Rc::new(RefCell::new((*counter.borrow_mut()).postfix_inc())) + .as_pointer(),) + { + (__tmp_2,) => { + let __inserted = m.as_pointer().with( + |__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }, + ); + if __inserted { + Map::subscript( + m.as_pointer().clone(), + key.as_pointer().clone(), + ) + .write((__tmp_2.read())); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| { + __m.find(&key.as_pointer()) + }, + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + } + } else { + match ({ + let __tmp_4 = counter.as_pointer(); + __tmp_4.with_mut(|__v| __v.prefix_inc()); + __tmp_4 + },) + { + (__tmp_3,) => { + let __inserted = m.as_pointer().with( + |__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }, + ); + if __inserted { + Map::subscript( + m.as_pointer().clone(), + key.as_pointer().clone(), + ) + .write((__tmp_3.read())); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| { + __m.find(&key.as_pointer()) + }, + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + } + })); + let mut hit: bool = ((subset & (1 << (*key.borrow()))) != 0); + ok = { ((ok as i32) & (((*counter.borrow()) == (initial + 1)) as i32)) != 0 }; + ok = { + ((ok as i32) + & ((((*(*result.borrow()).1.borrow()) as i32) == (!(hit) as i32)) + as i32)) + != 0 + }; + let mut found: bool = (*(*result.borrow()).0.borrow()) + == m.as_pointer() + .with(|__m: &Map, Value)>| { + __m.find(&key.as_pointer()) + }); + ok = { ((ok as i32) & (found as i32)) != 0 }; + { + let rhs_0 = ((ok as i32) + & (((*(*(*(*result.borrow()).0.borrow()) + .iter_deref() + .upgrade() + .deref()) + .0 + .borrow()) + == (*key.borrow())) as i32)) + != 0; + ok = rhs_0 + }; + { + let rhs_0 = ((ok as i32) + & (((*(*(*(*result.borrow()).0.borrow()) + .iter_deref() + .upgrade() + .deref()) + .1 + .borrow()) + == (if hit { + (10 + (*key.borrow())) + } else { + (initial + (!(post != 0) as i32)) + })) as i32)) + != 0; + ok = rhs_0 + }; + { + let rhs_0 = ((ok as i32) + & (((*m.borrow()).len() == ((size + (!(hit) as i32)) as usize)) + as i32)) + != 0; + ok = rhs_0 + }; + rows.prefix_inc(); + post.prefix_inc(); + } + initial.prefix_inc(); + } + (*key.borrow_mut()).prefix_inc(); + } + subset.prefix_inc(); + } + let items: Value, Value)>> = Rc::new(RefCell::new(Map::new())); + let key: Value = Rc::new(RefCell::new(0)); + { + let __inserted = items + .as_pointer() + .with(|__m: &Map, Value)>| __m.get(&key.as_pointer()).is_none()); + if __inserted { + Map::subscript(items.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_1({ 10 })); + } + ( + Rc::new(RefCell::new(items.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + }; + let source: Value = Rc::new(RefCell::new(Item::new_1({ 20 }))); + made_1.with(|rc| { + *rc.borrow_mut() = { + copies_2.with(|rc| { + *rc.borrow_mut() = { + moves_3.with(|rc| *rc.borrow_mut() = 0); + moves_3.with(|rc| *rc.borrow()) + } + }); + copies_2.with(|rc| *rc.borrow()) + } + }); + let hit: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (({ argument_4(source.as_pointer()) }),) { + (__tmp_5,) => { + let __inserted = + items + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(items.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::copy_from({ (__tmp_5).clone() })); + } + ( + Rc::new(RefCell::new(items.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((calls_0.with(|rc| *rc.borrow()) == 1) && (made_1.with(|rc| *rc.borrow()) == 0)) + && (copies_2.with(|rc| *rc.borrow()) == 0)) + && (moves_3.with(|rc| *rc.borrow()) == 0)) as i32)) + != 0 + }; + { + let rhs_0 = ((ok as i32) + & (((!(*(*hit.borrow()).1.borrow())) + && ((*(*hit.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 10)) as i32)) + != 0; + ok = rhs_0 + }; + let move_hit: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (({ argument_4(source.as_pointer()) }),) { + (__tmp_6,) => { + let __inserted = + items + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(items.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::move_from({ (__tmp_6).clone() })); + } + ( + Rc::new(RefCell::new(items.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((calls_0.with(|rc| *rc.borrow()) == 2) && (made_1.with(|rc| *rc.borrow()) == 0)) + && (copies_2.with(|rc| *rc.borrow()) == 0)) + && (moves_3.with(|rc| *rc.borrow()) == 0)) as i32)) + != 0 + }; + ok = { + ((ok as i32) + & (((!(*(*move_hit.borrow()).1.borrow())) && ({ (*source.borrow()).value } == 20)) + as i32)) + != 0 + }; + (*key.borrow_mut()).prefix_inc(); + let copied: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (({ argument_4(source.as_pointer()) }),) { + (__tmp_7,) => { + let __inserted = + items + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(items.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::copy_from({ (__tmp_7).clone() })); + } + ( + Rc::new(RefCell::new(items.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((calls_0.with(|rc| *rc.borrow()) == 3) && (made_1.with(|rc| *rc.borrow()) == 0)) + && (copies_2.with(|rc| *rc.borrow()) == 1)) + && (moves_3.with(|rc| *rc.borrow()) == 0)) as i32)) + != 0 + }; + { + let rhs_0 = ((ok as i32) + & (((*(*copied.borrow()).1.borrow()) + && ((*(*copied.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 20)) as i32)) + != 0; + ok = rhs_0 + }; + (*key.borrow_mut()).prefix_inc(); + let moved: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (({ argument_4(source.as_pointer()) }),) { + (__tmp_8,) => { + let __inserted = + items + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(items.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::move_from({ (__tmp_8).clone() })); + } + ( + Rc::new(RefCell::new(items.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((calls_0.with(|rc| *rc.borrow()) == 4) && (made_1.with(|rc| *rc.borrow()) == 0)) + && (copies_2.with(|rc| *rc.borrow()) == 1)) + && (moves_3.with(|rc| *rc.borrow()) == 1)) as i32)) + != 0 + }; + { + let rhs_0 = ((ok as i32) + & ((((*(*moved.borrow()).1.borrow()) + && ((*(*moved.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 20)) + && ({ (*source.borrow()).value } == -1_i32)) as i32)) + != 0; + ok = rhs_0 + }; + let refs: Value, Value)>> = Rc::new(RefCell::new(Map::new())); + (*key.borrow_mut()) = 0; + let counter: Value = Rc::new(RefCell::new(0)); + { + let __inserted = refs + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(refs.as_pointer().clone(), key.as_pointer().clone()) + .write(RefItem::new_2({ counter.as_pointer() }, { 5 })); + } + ( + Rc::new(RefCell::new(refs.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + }; + made_1.with(|rc| *rc.borrow_mut() = 0); + let ref_hit: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (({ reference_5(counter.as_pointer()) }),) { + (__tmp_9,) => { + let __inserted = + refs.as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(refs.as_pointer().clone(), key.as_pointer().clone()) + .write(RefItem::new_2({ (__tmp_9).clone() }, { 2 })); + } + ( + Rc::new(RefCell::new(refs.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((calls_0.with(|rc| *rc.borrow()) == 5) && ((*counter.borrow()) == 5)) + && (made_1.with(|rc| *rc.borrow()) == 0)) + && (!(*(*ref_hit.borrow()).1.borrow()))) as i32)) + != 0 + }; + (*key.borrow_mut()).prefix_inc(); + let ref_new: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (({ reference_5(counter.as_pointer()) }),) { + (__tmp_10,) => { + let __inserted = + refs.as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(refs.as_pointer().clone(), key.as_pointer().clone()) + .write(RefItem::new_2({ (__tmp_10).clone() }, { 2 })); + } + ( + Rc::new(RefCell::new(refs.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((calls_0.with(|rc| *rc.borrow()) == 6) && ((*counter.borrow()) == 7)) + && (made_1.with(|rc| *rc.borrow()) == 1)) + && (*(*ref_new.borrow()).1.borrow())) as i32)) + != 0 + }; + { + let rhs_0 = ((ok as i32) + & ((((*(*ref_hit.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 5) + && ((*(*ref_new.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 7)) as i32)) + != 0; + ok = rhs_0 + }; + (*key.borrow_mut()) = 0; + made_1.with(|rc| { + *rc.borrow_mut() = { + copies_2.with(|rc| { + *rc.borrow_mut() = { + moves_3.with(|rc| *rc.borrow_mut() = 0); + moves_3.with(|rc| *rc.borrow()) + } + }); + copies_2.with(|rc| *rc.borrow()) + } + }); + let temporary_hit: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (Rc::new(RefCell::new(Item::new_1({ 30 }))).as_pointer(),) { + (__tmp_11,) => { + let __inserted = + items + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(items.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::move_from({ (__tmp_11).clone() })); + } + ( + Rc::new(RefCell::new(items.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((made_1.with(|rc| *rc.borrow()) == 1) + && (copies_2.with(|rc| *rc.borrow()) == 0)) + && (moves_3.with(|rc| *rc.borrow()) == 0)) + && (!(*(*temporary_hit.borrow()).1.borrow()))) as i32)) + != 0 + }; + (*key.borrow_mut()).prefix_inc(); + (*key.borrow_mut()).prefix_inc(); + (*key.borrow_mut()).prefix_inc(); + let temporary_new: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (Rc::new(RefCell::new(Item::new_1({ 40 }))).as_pointer(),) { + (__tmp_12,) => { + let __inserted = + items + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(items.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::move_from({ (__tmp_12).clone() })); + } + ( + Rc::new(RefCell::new(items.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + ok = { + ((ok as i32) + & (((((made_1.with(|rc| *rc.borrow()) == 2) + && (copies_2.with(|rc| *rc.borrow()) == 0)) + && (moves_3.with(|rc| *rc.borrow()) == 1)) + && (*(*temporary_new.borrow()).1.borrow())) as i32)) + != 0 + }; + { + let rhs_0 = ((ok as i32) + & (((*(*temporary_new.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 40) as i32)) + != 0; + ok = rhs_0 + }; + println!( + "{} {} {} {} {}", + rows, + calls_0.with(|rc| *rc.borrow()), + made_1.with(|rc| *rc.borrow()), + copies_2.with(|rc| *rc.borrow()), + moves_3.with(|rc| *rc.borrow()) + ); + return if ok { 0 } else { 1 }; +} +pub fn __cpp2rust_init_globals() { + let _ = calls_0.with(|_| ()); + let _ = made_1.with(|_| ()); + let _ = copies_2.with(|_| ()); + let _ = moves_3.with(|_| ()); + let _ = global_map_6.with(|_| ()); + let _ = global_key_7.with(|_| ()); + let _ = global_counter_8.with(|_| ()); + let _ = seed_9.with(|_| ()); + let _ = global_hit_10.with(|_| ()); +} diff --git a/tests/unit/out/refcount/map_try_emplace_lvalues.rs b/tests/unit/out/refcount/map_try_emplace_lvalues.rs new file mode 100644 index 000000000..08cb94568 --- /dev/null +++ b/tests/unit/out/refcount/map_try_emplace_lvalues.rs @@ -0,0 +1,697 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +thread_local!( + pub static made_0: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static visits_1: Value = Rc::new(RefCell::new(0)); +); +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg)] +#[byte_size(4)] +pub struct Item { + #[offset(0)] + pub value: i32, +} +impl Item { + pub fn new_1() -> Self { + Self { value: 0 } + } + pub fn new_2(counter: Ptr, mut amount: i32) -> Self { + let __this: Item = Self { + value: { + { + let __rhs = { amount }; + counter.with_mut(|__v| *__v = *__v + __rhs) + }; + (counter.read()) + }, + }; + (*made_0.with(Value::clone).borrow_mut()).prefix_inc(); + __this + } +} +impl Default for Item { + fn default() -> Self { + { Item::new_1() } + } +} +pub fn receiver_2( + m: Ptr, Value)>>, +) -> Ptr, Value)>> { + (*visits_1.with(Value::clone).borrow_mut()).prefix_inc(); + return (m).clone(); +} +pub fn place_3(n: Ptr) -> Ptr { + (*visits_1.with(Value::clone).borrow_mut()).prefix_inc(); + return (n).clone(); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let m: Value, Value)>> = Rc::new(RefCell::new(Map::new())); + let key: Value = Rc::new(RefCell::new(0)); + let counter: Value = Rc::new(RefCell::new(0)); + { + let __inserted = m + .as_pointer() + .with(|__m: &Map, Value)>| __m.get(&key.as_pointer()).is_none()); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ counter.as_pointer() }, { 3 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + }; + made_0.with(|rc| *rc.borrow_mut() = 0); + let hit: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (({ receiver_2(m.as_pointer()) }), { + let __tmp_2 = ({ place_3(counter.as_pointer()) }); + __tmp_2.with_mut(|__v| __v.prefix_inc()); + __tmp_2 + }) { + (__tmp_0, __tmp_1) => { + let __inserted = __tmp_0.with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(__tmp_0.clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_1).clone() }, { 2 })); + } + ( + Rc::new(RefCell::new(__tmp_0.with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + ((((*counter.borrow()) == 4) && (made_0.with(|rc| *rc.borrow()) == 0)) + && (visits_1.with(|rc| *rc.borrow()) == 2)) + && (!(*(*hit.borrow()).1.borrow())) + }) + ); + (*key.borrow_mut()).prefix_inc(); + let inserted: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match ({ + let __tmp_4 = counter.as_pointer(); + __tmp_4.with_mut(|__v| __v.prefix_inc()); + __tmp_4 + },) + { + (__tmp_3,) => { + let __inserted = + m.as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_3).clone() }, { 2 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + (((*counter.borrow()) == 7) && (made_0.with(|rc| *rc.borrow()) == 1)) + && (*(*inserted.borrow()).1.borrow()) + }) + ); + let assigned: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (match ({ 9 }, counter.as_pointer()) { + (__tmp_7, __tmp_6) => { + __tmp_6.write({ __tmp_7 }); + __tmp_6 + } + },) + { + (__tmp_5,) => { + let __inserted = + m.as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_5).clone() }, { 2 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + (((*counter.borrow()) == 9) && (made_0.with(|rc| *rc.borrow()) == 1)) + && (!(*(*assigned.borrow()).1.borrow())) + }) + ); + (*key.borrow_mut()).prefix_inc(); + let compound: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (match ({ 4 }, counter.as_pointer()) { + (__tmp_10, __tmp_9) => { + { + let __rhs = { __tmp_10 }; + __tmp_9.with_mut(|__v| *__v = *__v + __rhs) + }; + __tmp_9 + } + },) + { + (__tmp_8,) => { + let __inserted = + m.as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_8).clone() }, { 2 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + (((*counter.borrow()) == 15) && (made_0.with(|rc| *rc.borrow()) == 2)) + && (*(*compound.borrow()).1.borrow()) + }) + ); + assert!( + ({ + ((*(*inserted.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 7) + && ((*(*compound.borrow()).0.borrow()) + .iter_deref() + .with(|__s| (*({ __s }).1.borrow()).value) + == 15) + }) + ); + let array: Value> = Rc::new(RefCell::new(Box::new([0, 0]))); + let mut index: i32 = 0; + (*key.borrow_mut()).prefix_inc(); + match ({ + let __tmp_12 = (array.as_pointer() as Ptr).offset(index.postfix_inc()); + __tmp_12.with_mut(|__v| __v.prefix_inc()); + __tmp_12 + },) + { + (__tmp_11,) => { + let __inserted = m + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_11).clone() }, { 3 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }; + assert!( + ({ + ((index == 1) && ((*array.borrow())[(0) as usize] == 4)) + && (made_0.with(|rc| *rc.borrow()) == 3) + }) + ); + (*key.borrow_mut()).prefix_inc(); + match ( + match ( + { 5 }, + (array.as_pointer() as Ptr).offset(index.postfix_inc()), + ) { + (__tmp_15, __tmp_14) => { + __tmp_14.write({ __tmp_15 }); + __tmp_14 + } + }, + ) { + (__tmp_13,) => { + let __inserted = m + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_13).clone() }, { 3 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }; + assert!( + ({ + ((index == 2) && ((*array.borrow())[(1) as usize] == 8)) + && (made_0.with(|rc| *rc.borrow()) == 4) + }) + ); + match ( + match ({ ((*counter.borrow()) + 1) }, counter.as_pointer()) { + (__tmp_18, __tmp_17) => { + __tmp_17.write({ __tmp_18 }); + __tmp_17 + } + }, + ) { + (__tmp_16,) => { + let __inserted = m + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_16).clone() }, { 3 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }; + assert!(({ ((*counter.borrow()) == 16) && (made_0.with(|rc| *rc.borrow()) == 4) })); + let a: Value = Rc::new(RefCell::new(0)); + let b: Value = Rc::new(RefCell::new(0)); + let mut choose: bool = false; + match (if choose { + ({ + let __tmp_20 = a.as_pointer(); + __tmp_20.with_mut(|__v| __v.prefix_inc()); + __tmp_20 + }) + } else { + ({ + let __tmp_21 = b.as_pointer(); + __tmp_21.with_mut(|__v| __v.prefix_inc()); + __tmp_21 + }) + },) + { + (__tmp_19,) => { + let __inserted = m + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_19).clone() }, { 3 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }; + assert!( + ({ + (((*a.borrow()) == 0) && ((*b.borrow()) == 1)) && (made_0.with(|rc| *rc.borrow()) == 4) + }) + ); + choose = true; + match (if choose { + ({ + let __tmp_23 = a.as_pointer(); + __tmp_23.with_mut(|__v| __v.prefix_inc()); + __tmp_23 + }) + } else { + ({ + let __tmp_24 = b.as_pointer(); + __tmp_24.with_mut(|__v| __v.prefix_inc()); + __tmp_24 + }) + },) + { + (__tmp_22,) => { + let __inserted = m + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_22).clone() }, { 3 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }; + assert!( + ({ + (((*a.borrow()) == 1) && ((*b.borrow()) == 1)) && (made_0.with(|rc| *rc.borrow()) == 4) + }) + ); + match ({ + (*counter.borrow_mut()).postfix_inc(); + counter.as_pointer() + },) + { + (__tmp_25,) => { + let __inserted = m + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(m.as_pointer().clone(), key.as_pointer().clone()) + .write(Item::new_2({ (__tmp_25).clone() }, { 3 })); + } + ( + Rc::new(RefCell::new(m.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }; + assert!(({ ((*counter.borrow()) == 17) && (made_0.with(|rc| *rc.borrow()) == 4) })); + let unsigned_map: Value, Value)>> = Rc::new(RefCell::new(Map::new())); + let n: Value = Rc::new(RefCell::new(!0_u32)); + let wrapped: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match (match ({ 1_u32 }, n.as_pointer()) { + (__tmp_28, __tmp_27) => { + __tmp_27.write({ (__tmp_27.read()).wrapping_add(__tmp_28) }); + __tmp_27 + } + },) + { + (__tmp_26,) => { + let __inserted = + unsigned_map + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(unsigned_map.as_pointer().clone(), key.as_pointer().clone()) + .write((__tmp_26.read())); + } + ( + Rc::new(RefCell::new(unsigned_map.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + ((*n.borrow()) == 0_u32) + && ((*(*(*(*wrapped.borrow()).0.borrow()) + .iter_deref() + .upgrade() + .deref()) + .1 + .borrow()) + == 0_u32) + }) + ); + let bytes: Value> = Rc::new(RefCell::new(Box::new([255_u8, 0_u8]))); + index = 0; + (*key.borrow_mut()).prefix_inc(); + let narrowed: Value<( + Value, Value)>>, + Value, + )> = Rc::new(RefCell::new( + match ( + match ( + { 2 }, + (bytes.as_pointer() as Ptr).offset(index.postfix_inc()), + ) { + (__tmp_31, __tmp_30) => { + __tmp_30.write({ (((__tmp_30.read()) as i32) + __tmp_31) as u8 }); + __tmp_30 + } + }, + ) { + (__tmp_29,) => { + let __inserted = + unsigned_map + .as_pointer() + .with(|__m: &Map, Value)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(unsigned_map.as_pointer().clone(), key.as_pointer().clone()) + .write(((__tmp_29.read()) as u32)); + } + ( + Rc::new(RefCell::new(unsigned_map.as_pointer().with( + |__m: &Map, Value)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + ((index == 1) && (((*bytes.borrow())[(0) as usize] as i32) == 1)) + && ((*(*(*(*narrowed.borrow()).0.borrow()) + .iter_deref() + .upgrade() + .deref()) + .1 + .borrow()) + == 1_u32) + }) + ); + let pointers: Value, Value>)>> = + Rc::new(RefCell::new(Map::new())); + let p: Value> = Rc::new(RefCell::new((array.as_pointer() as Ptr))); + let pointer: Value<( + Value, Value>)>>, + Value, + )> = Rc::new(RefCell::new( + match (match ({ 1 }, p.as_pointer()) { + (__tmp_34, __tmp_33) => { + let __rhs = __tmp_34; + { + let _ptr = __tmp_33.clone(); + _ptr.write(_ptr.read() + __rhs) + }; + __tmp_33 + } + },) + { + (__tmp_32,) => { + let __inserted = + pointers + .as_pointer() + .with(|__m: &Map, Value>)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(pointers.as_pointer().clone(), key.as_pointer().clone()) + .write((__tmp_32.read())); + } + ( + Rc::new(RefCell::new(pointers.as_pointer().with( + |__m: &Map, Value>)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + ({ (*p.borrow()).clone() } == { (array.as_pointer() as Ptr).offset((1) as isize) }) + && ({ + (*(*(*(*pointer.borrow()).0.borrow()) + .iter_deref() + .upgrade() + .deref()) + .1 + .borrow()) + .clone() + } == { (*p.borrow()).clone() }) + }) + ); + let strings: Value, Value>)>> = Rc::new(RefCell::new(Map::new())); + let text: Value> = Rc::new(RefCell::new({ + let mut __bytes = Ptr::::from_string_literal(b"value").to_c_bytes(); + __bytes.push(0); + __bytes + })); + { + let __inserted = + strings + .as_pointer() + .with(|__m: &Map, Value>)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(strings.as_pointer().clone(), key.as_pointer().clone()).write({ + let mut __bytes = Ptr::::from_string_literal(b"original").to_c_bytes(); + __bytes.push(0); + __bytes + }); + } + ( + Rc::new(RefCell::new(strings.as_pointer().with( + |__m: &Map, Value>)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + }; + let string_hit: Value<( + Value, Value>)>>, + Value, + )> = Rc::new(RefCell::new( + match ({ + (*visits_1.with(Value::clone).borrow_mut()).prefix_inc(); + text.as_pointer() + },) + { + (__tmp_35,) => { + let __inserted = + strings + .as_pointer() + .with(|__m: &Map, Value>)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(strings.as_pointer().clone(), key.as_pointer().clone()) + .write(__tmp_35.with_mut(std::mem::take)); + } + ( + Rc::new(RefCell::new(strings.as_pointer().with( + |__m: &Map, Value>)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + ((visits_1.with(|rc| *rc.borrow()) == 3) && (!(*(*string_hit.borrow()).1.borrow()))) + && (Ptr::::from_string_literal(b"value").with_c_str(|__s| { + (*text.borrow())[..(*text.borrow()).len().saturating_sub(1)] == *__s + })) + }) + ); + (*key.borrow_mut()).prefix_inc(); + let string_new: Value<( + Value, Value>)>>, + Value, + )> = Rc::new(RefCell::new( + match ({ + (*visits_1.with(Value::clone).borrow_mut()).prefix_inc(); + text.as_pointer() + },) + { + (__tmp_36,) => { + let __inserted = + strings + .as_pointer() + .with(|__m: &Map, Value>)>| { + __m.get(&key.as_pointer()).is_none() + }); + if __inserted { + Map::subscript(strings.as_pointer().clone(), key.as_pointer().clone()) + .write(__tmp_36.with_mut(std::mem::take)); + } + ( + Rc::new(RefCell::new(strings.as_pointer().with( + |__m: &Map, Value>)>| __m.find(&key.as_pointer()), + ))), + Rc::new(RefCell::new(__inserted)), + ) + } + }, + )); + assert!( + ({ + ((visits_1.with(|rc| *rc.borrow()) == 4) && (*(*string_new.borrow()).1.borrow())) + && (match ((*(*(*string_new.borrow()).0.borrow()) + .iter_deref() + .upgrade() + .deref()) + .1 + .as_pointer(),) + { + (__tmp_37,) => Ptr::::from_string_literal(b"value").with_c_str(|__s| { + (*__tmp_37.upgrade().deref()) + [..(*__tmp_37.upgrade().deref()).len().saturating_sub(1)] + == *__s + }), + }) + }) + ); + return 0; +} +pub fn __cpp2rust_init_globals() { + let _ = made_0.with(|_| ()); + let _ = visits_1.with(|_| ()); +} diff --git a/tests/unit/out/unsafe/map_try_emplace.rs b/tests/unit/out/unsafe/map_try_emplace.rs new file mode 100644 index 000000000..2476a3260 --- /dev/null +++ b/tests/unit/out/unsafe/map_try_emplace.rs @@ -0,0 +1,421 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub static mut calls_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut made_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut copies_2: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut moves_3: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +#[repr(C)] +#[derive(VaArg, FnPtrArg, MoveCtorUnsafe, CppFromUnsafe)] +#[cpp_from(i32, new_1, value)] +pub struct Item { + pub value: i32, +} +impl Item { + pub unsafe fn new_2() -> Self { + let mut this = Self { value: 0 }; + this + } + pub unsafe fn new_1(mut value: i32) -> Self { + let mut this = Self { value: value }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)).prefix_inc(); + this + } + pub unsafe fn copy_from(other: *const Item) -> Self { + let mut this = Self { + value: (*other).value, + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)).prefix_inc(); + this + } + pub unsafe fn move_from(other: *mut Item) -> Self { + let mut this = Self { + value: (*other).value, + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)).prefix_inc(); + (*other).value = -1_i32; + this + } +} +impl Clone for Item { + fn clone(&self) -> Self { + unsafe { Item::copy_from(self as *const Item) } + } +} +impl Default for Item { + fn default() -> Self { + unsafe { Item::new_2() } + } +} +pub unsafe fn argument_4(item: *mut Item) -> *mut Item { + (*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)).prefix_inc(); + return item; +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg)] +pub struct RefItem { + pub value: i32, +} +impl RefItem { + pub unsafe fn new_1() -> Self { + let mut this = Self { value: 0 }; + this + } + pub unsafe fn new_2(counter: *mut i32, mut amount: i32) -> Self { + let mut this = Self { + value: { + (*counter) += amount; + (*counter) + }, + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)).prefix_inc(); + this + } +} +impl Default for RefItem { + fn default() -> Self { + unsafe { RefItem::new_1() } + } +} +pub unsafe fn reference_5(counter: *mut i32) -> *mut i32 { + (*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)).prefix_inc(); + return counter; +} +pub static mut global_map_6: std::cell::LazyCell> = + std::cell::LazyCell::new(|| unsafe { UnsafeMap::new() }); +pub static mut global_key_7: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut global_counter_8: std::cell::LazyCell = + std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut seed_9: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { + { + (*(*std::cell::LazyCell::force_mut(&mut *&raw mut global_map_6)) + .subscript(&(*std::cell::LazyCell::force_mut(&mut *&raw mut global_key_7)))) = 10; + 0 + } +}); +pub static mut global_hit_10: std::cell::LazyCell<(UnsafeBidirectionalIterator<(i32, i32)>, bool)> = + std::cell::LazyCell::new(|| unsafe { + match (({ + let __tmp_1 = &mut (*std::cell::LazyCell::force_mut(&mut *&raw mut global_counter_8)); + (*__tmp_1).prefix_inc(); + __tmp_1 + } as *mut i32),) + { + (__tmp_0,) => { + let __inserted = (*std::cell::LazyCell::force_mut(&mut *&raw mut global_map_6)) + .get(&(*std::cell::LazyCell::force_mut(&mut *&raw mut global_key_7))) + .is_none(); + if __inserted { + *(*std::cell::LazyCell::force_mut(&mut *&raw mut global_map_6)).subscript( + &(*std::cell::LazyCell::force_mut(&mut *&raw mut global_key_7)), + ) = (*__tmp_0); + } + ( + (*std::cell::LazyCell::force_mut(&mut *&raw mut global_map_6)) + .find(&(*std::cell::LazyCell::force_mut(&mut *&raw mut global_key_7))), + __inserted, + ) + } + } + }); +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut ok: bool = (((*std::cell::LazyCell::force_mut(&mut *&raw mut global_counter_8)) + == (1)) + && (!((*std::cell::LazyCell::force_mut(&mut *&raw mut global_hit_10)).1))) + && (((*(*std::cell::LazyCell::force_mut(&mut *&raw mut global_hit_10)) + .0 + .iter_deref()) + .1) == (10)); + let mut rows: i32 = 0; + let mut subset: i32 = 0; + 'loop_: while ((subset) < (8)) { + let mut key: i32 = 0; + 'loop_: while ((key) < (3)) { + let mut initial: i32 = 0; + 'loop_: while ((initial) < (3)) { + let mut post: i32 = 0; + 'loop_: while ((post) < (2)) { + let mut m: UnsafeMap = UnsafeMap::new(); + let mut size: i32 = 0; + let mut k: i32 = 0; + 'loop_: while ((k) < (3)) { + if (((subset) & ((1) << (k))) != 0) { + (*m.subscript(&k)) = ((10) + (k)); + size.prefix_inc(); + } + k.prefix_inc(); + } + let mut counter: i32 = initial; + let mut result: (UnsafeBidirectionalIterator<(i32, i32)>, bool) = if (post != 0) + { + match ((&mut counter.postfix_inc() as *mut i32),) { + (__tmp_2,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = (*__tmp_2); + } + (m.find(&key), __inserted) + } + } + } else { + match (({ + let __tmp_4 = &mut counter; + (*__tmp_4).prefix_inc(); + __tmp_4 + } as *mut i32),) + { + (__tmp_3,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = (*__tmp_3); + } + (m.find(&key), __inserted) + } + } + }; + let mut hit: bool = (((subset) & ((1) << (key))) != (0)); + ok = ((ok as i32) & (((counter) == ((initial) + (1))) as i32)) != 0; + ok = ((ok as i32) & (((result.1 as i32) == (!(hit) as i32)) as i32)) != 0; + let mut found: bool = result.0 == m.find(&key); + ok = ((ok as i32) & (found as i32)) != 0; + ok = ((ok as i32) & ((((*result.0.iter_deref()).0) == (key)) as i32)) != 0; + ok = ((ok as i32) + & ((((*result.0.iter_deref()).1) + == (if hit { + ((10) + (key)) + } else { + ((initial) + (!(post != 0) as i32)) + })) as i32)) + != 0; + ok = ((ok as i32) + & (((m.len()) == (((size) + (!(hit) as i32)) as usize)) as i32)) + != 0; + rows.prefix_inc(); + post.prefix_inc(); + } + initial.prefix_inc(); + } + key.prefix_inc(); + } + subset.prefix_inc(); + } + let mut items: UnsafeMap = UnsafeMap::new(); + let mut key: i32 = 0; + { + let __inserted = items.get(&key).is_none(); + if __inserted { + *items.subscript(&key) = Item::new_1({ 10 }); + } + (items.find(&key), __inserted) + }; + let mut source: Item = Item::new_1({ 20 }); + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) = { + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) = { + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) = 0; + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) + }; + let mut hit: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match (((unsafe { argument_4(&mut source) }) as *mut Item),) { + (__tmp_5,) => { + let __inserted = items.get(&key).is_none(); + if __inserted { + *items.subscript(&key) = Item::copy_from({ __tmp_5 }); + } + (items.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)) == (1)) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) == (0))) + as i32)) + != 0; + ok = ((ok as i32) & (((!(hit.1)) && (((*hit.0.iter_deref()).1.value) == (10))) as i32)) != 0; + let mut move_hit: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match (((unsafe { argument_4(&mut source) }) as *mut Item),) { + (__tmp_6,) => { + let __inserted = items.get(&key).is_none(); + if __inserted { + *items.subscript(&key) = Item::move_from({ __tmp_6 }); + } + (items.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)) == (2)) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) == (0))) + as i32)) + != 0; + ok = ((ok as i32) & (((!(move_hit.1)) && ((source.value) == (20))) as i32)) != 0; + key.prefix_inc(); + let mut copied: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match (((unsafe { argument_4(&mut source) }) as *mut Item),) { + (__tmp_7,) => { + let __inserted = items.get(&key).is_none(); + if __inserted { + *items.subscript(&key) = Item::copy_from({ __tmp_7 }); + } + (items.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)) == (3)) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) == (1))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) == (0))) + as i32)) + != 0; + ok = ((ok as i32) & (((copied.1) && (((*copied.0.iter_deref()).1.value) == (20))) as i32)) != 0; + key.prefix_inc(); + let mut moved: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match (((unsafe { argument_4(&mut source) }) as *mut Item),) { + (__tmp_8,) => { + let __inserted = items.get(&key).is_none(); + if __inserted { + *items.subscript(&key) = Item::move_from({ __tmp_8 }); + } + (items.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)) == (4)) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) == (1))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) == (1))) + as i32)) + != 0; + ok = ((ok as i32) + & ((((moved.1) && (((*moved.0.iter_deref()).1.value) == (20))) + && ((source.value) == (-1_i32))) as i32)) + != 0; + let mut refs: UnsafeMap = UnsafeMap::new(); + key = 0; + let mut counter: i32 = 0; + { + let __inserted = refs.get(&key).is_none(); + if __inserted { + *refs.subscript(&key) = RefItem::new_2({ &mut counter }, { 5 }); + } + (refs.find(&key), __inserted) + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) = 0; + let mut ref_hit: (UnsafeBidirectionalIterator<(i32, RefItem)>, bool) = + match (((unsafe { reference_5(&mut counter) }) as *mut i32),) { + (__tmp_9,) => { + let __inserted = refs.get(&key).is_none(); + if __inserted { + *refs.subscript(&key) = RefItem::new_2({ __tmp_9 }, { 2 }); + } + (refs.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)) == (5)) + && ((counter) == (5))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (0))) + && (!(ref_hit.1))) as i32)) + != 0; + key.prefix_inc(); + let mut ref_new: (UnsafeBidirectionalIterator<(i32, RefItem)>, bool) = + match (((unsafe { reference_5(&mut counter) }) as *mut i32),) { + (__tmp_10,) => { + let __inserted = refs.get(&key).is_none(); + if __inserted { + *refs.subscript(&key) = RefItem::new_2({ __tmp_10 }, { 2 }); + } + (refs.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)) == (6)) + && ((counter) == (7))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (1))) + && (ref_new.1)) as i32)) + != 0; + ok = ((ok as i32) + & (((((*ref_hit.0.iter_deref()).1.value) == (5)) + && (((*ref_new.0.iter_deref()).1.value) == (7))) as i32)) + != 0; + key = 0; + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) = { + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) = { + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) = 0; + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) + }; + let mut temporary_hit: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match ((&mut Item::new_1({ 30 }) as *mut Item),) { + (__tmp_11,) => { + let __inserted = items.get(&key).is_none(); + if __inserted { + *items.subscript(&key) = Item::move_from({ __tmp_11 }); + } + (items.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (1)) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) == (0))) + && (!(temporary_hit.1))) as i32)) + != 0; + key.prefix_inc(); + key.prefix_inc(); + key.prefix_inc(); + let mut temporary_new: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match ((&mut Item::new_1({ 40 }) as *mut Item),) { + (__tmp_12,) => { + let __inserted = items.get(&key).is_none(); + if __inserted { + *items.subscript(&key) = Item::move_from({ __tmp_12 }); + } + (items.find(&key), __inserted) + } + }; + ok = ((ok as i32) + & ((((((*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)) == (2)) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)) == (1))) + && (temporary_new.1)) as i32)) + != 0; + ok = ((ok as i32) & ((((*temporary_new.0.iter_deref()).1.value) == (40)) as i32)) != 0; + (unsafe { + libc::printf( + c"%d %d %d %d %d\n".as_ptr() as *const libc::c_char, + (rows), + (*std::cell::LazyCell::force_mut(&mut *&raw mut calls_0)), + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_1)), + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_2)), + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_3)), + ) + }); + return if ok { 0 } else { 1 }; +} +pub unsafe fn __cpp2rust_init_globals() { + std::cell::LazyCell::force(&*&raw const calls_0); + std::cell::LazyCell::force(&*&raw const made_1); + std::cell::LazyCell::force(&*&raw const copies_2); + std::cell::LazyCell::force(&*&raw const moves_3); + std::cell::LazyCell::force(&*&raw const global_map_6); + std::cell::LazyCell::force(&*&raw const global_key_7); + std::cell::LazyCell::force(&*&raw const global_counter_8); + std::cell::LazyCell::force(&*&raw const seed_9); + std::cell::LazyCell::force(&*&raw const global_hit_10); +} diff --git a/tests/unit/out/unsafe/map_try_emplace_lvalues.rs b/tests/unit/out/unsafe/map_try_emplace_lvalues.rs new file mode 100644 index 000000000..dbb641a34 --- /dev/null +++ b/tests/unit/out/unsafe/map_try_emplace_lvalues.rs @@ -0,0 +1,410 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub static mut made_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut visits_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg)] +pub struct Item { + pub value: i32, +} +impl Item { + pub unsafe fn new_1() -> Self { + let mut this = Self { value: 0 }; + this + } + pub unsafe fn new_2(counter: *mut i32, mut amount: i32) -> Self { + let mut this = Self { + value: { + (*counter) += amount; + (*counter) + }, + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)).prefix_inc(); + this + } +} +impl Default for Item { + fn default() -> Self { + unsafe { Item::new_1() } + } +} +pub unsafe fn receiver_2(m: *mut UnsafeMap) -> *mut UnsafeMap { + (*std::cell::LazyCell::force_mut(&mut *&raw mut visits_1)).prefix_inc(); + return m; +} +pub unsafe fn place_3(n: *mut i32) -> *mut i32 { + (*std::cell::LazyCell::force_mut(&mut *&raw mut visits_1)).prefix_inc(); + return n; +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut m: UnsafeMap = UnsafeMap::new(); + let mut key: i32 = 0; + let mut counter: i32 = 0; + { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ &mut counter }, { 3 }); + } + (m.find(&key), __inserted) + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) = 0; + let mut hit: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = match ( + ((unsafe { receiver_2(&mut m) }) as *mut UnsafeMap), + ({ + let __tmp_2 = (unsafe { place_3(&mut counter) }); + (*__tmp_2).prefix_inc(); + __tmp_2 + } as *mut i32), + ) { + (__tmp_0, __tmp_1) => { + let __inserted = (*__tmp_0).get(&key).is_none(); + if __inserted { + *(*__tmp_0).subscript(&key) = Item::new_2({ __tmp_1 }, { 2 }); + } + ((*__tmp_0).find(&key), __inserted) + } + }; + assert!( + ((((counter) == (4)) && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (0))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut visits_1)) == (2))) + && (!(hit.1)) + ); + key.prefix_inc(); + let mut inserted: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = match (({ + let __tmp_4 = &mut counter; + (*__tmp_4).prefix_inc(); + __tmp_4 + } as *mut i32),) + { + (__tmp_3,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_3 }, { 2 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + (((counter) == (7)) && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (1))) + && (inserted.1) + ); + let mut assigned: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match ((match ({ 9 }, &mut counter) { + (__tmp_7, __tmp_6) => { + (*__tmp_6) = __tmp_7; + __tmp_6 + } + } as *mut i32),) + { + (__tmp_5,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_5 }, { 2 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + (((counter) == (9)) && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (1))) + && (!(assigned.1)) + ); + key.prefix_inc(); + let mut compound: (UnsafeBidirectionalIterator<(i32, Item)>, bool) = + match ((match ({ 4 }, &mut counter) { + (__tmp_10, __tmp_9) => { + (*__tmp_9) += __tmp_10; + __tmp_9 + } + } as *mut i32),) + { + (__tmp_8,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_8 }, { 2 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + (((counter) == (15)) && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (2))) + && (compound.1) + ); + assert!( + (((*inserted.0.iter_deref()).1.value) == (7)) + && (((*compound.0.iter_deref()).1.value) == (15)) + ); + let mut array: [i32; 2] = [0, 0]; + let mut index: i32 = 0; + key.prefix_inc(); + match (({ + let __tmp_12 = &mut array[(index.postfix_inc()) as usize]; + (*__tmp_12).prefix_inc(); + __tmp_12 + } as *mut i32),) + { + (__tmp_11,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_11 }, { 3 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + (((index) == (1)) && ((array[(0) as usize]) == (4))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (3)) + ); + key.prefix_inc(); + match ((match ({ 5 }, &mut array[(index.postfix_inc()) as usize]) { + (__tmp_15, __tmp_14) => { + (*__tmp_14) = __tmp_15; + __tmp_14 + } + } as *mut i32),) + { + (__tmp_13,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_13 }, { 3 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + (((index) == (2)) && ((array[(1) as usize]) == (8))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (4)) + ); + match ((match ({ ((counter) + (1)) }, &mut counter) { + (__tmp_18, __tmp_17) => { + (*__tmp_17) = __tmp_18; + __tmp_17 + } + } as *mut i32),) + { + (__tmp_16,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_16 }, { 3 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + ((counter) == (16)) && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (4)) + ); + let mut a: i32 = 0; + let mut b: i32 = 0; + let mut choose: bool = false; + match ((if choose { + (&mut a.prefix_inc() as *mut i32) + } else { + (&mut b.prefix_inc() as *mut i32) + } as *mut i32),) + { + (__tmp_19,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_19 }, { 3 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + (((a) == (0)) && ((b) == (1))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (4)) + ); + choose = true; + match ((if choose { + (&mut a.prefix_inc() as *mut i32) + } else { + (&mut b.prefix_inc() as *mut i32) + } as *mut i32),) + { + (__tmp_20,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_20 }, { 3 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + (((a) == (1)) && ((b) == (1))) + && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (4)) + ); + match (({ + counter.postfix_inc(); + &mut counter + } as *mut i32),) + { + (__tmp_21,) => { + let __inserted = m.get(&key).is_none(); + if __inserted { + *m.subscript(&key) = Item::new_2({ __tmp_21 }, { 3 }); + } + (m.find(&key), __inserted) + } + }; + assert!( + ((counter) == (17)) && ((*std::cell::LazyCell::force_mut(&mut *&raw mut made_0)) == (4)) + ); + let mut unsigned_map: UnsafeMap = UnsafeMap::new(); + let mut n: u32 = !0_u32; + let mut wrapped: (UnsafeBidirectionalIterator<(i32, u32)>, bool) = + match ((match ({ 1_u32 }, &mut n) { + (__tmp_24, __tmp_23) => { + (*__tmp_23) = (*__tmp_23).wrapping_add(__tmp_24); + __tmp_23 + } + } as *mut u32),) + { + (__tmp_22,) => { + let __inserted = unsigned_map.get(&key).is_none(); + if __inserted { + *unsigned_map.subscript(&key) = (*__tmp_22); + } + (unsigned_map.find(&key), __inserted) + } + }; + assert!(((n) == (0_u32)) && (((*wrapped.0.iter_deref()).1) == (0_u32))); + let mut bytes: [u8; 2] = [255_u8, 0_u8]; + index = 0; + key.prefix_inc(); + let mut narrowed: (UnsafeBidirectionalIterator<(i32, u32)>, bool) = + match ((match ({ 2 }, &mut bytes[(index.postfix_inc()) as usize]) { + (__tmp_27, __tmp_26) => { + (*__tmp_26) = (((*__tmp_26) as i32) + __tmp_27) as u8; + __tmp_26 + } + } as *mut u8),) + { + (__tmp_25,) => { + let __inserted = unsigned_map.get(&key).is_none(); + if __inserted { + *unsigned_map.subscript(&key) = ((*__tmp_25) as u32); + } + (unsigned_map.find(&key), __inserted) + } + }; + assert!( + (((index) == (1)) && ((bytes[(0) as usize] as i32) == (1))) + && (((*narrowed.0.iter_deref()).1) == (1_u32)) + ); + let mut pointers: UnsafeMap = UnsafeMap::new(); + let mut p: *mut i32 = array.as_mut_ptr(); + let mut pointer: (UnsafeBidirectionalIterator<(i32, *mut i32)>, bool) = + match ((match ({ 1 }, &mut p) { + (__tmp_30, __tmp_29) => { + (*__tmp_29) = (*__tmp_29).wrapping_add(__tmp_30 as usize); + __tmp_29 + } + } as *mut *mut i32),) + { + (__tmp_28,) => { + let __inserted = pointers.get(&key).is_none(); + if __inserted { + *pointers.subscript(&key) = (*__tmp_28); + } + (pointers.find(&key), __inserted) + } + }; + assert!( + ((p) == (array.as_mut_ptr().offset((1) as isize))) + && (((*pointer.0.iter_deref()).1) == (p)) + ); + let mut strings: UnsafeMap)> = UnsafeMap::new(); + let mut text: Vec = std::slice::from_raw_parts( + c"value".as_ptr(), + (0..) + .take_while(|&i| *c"value".as_ptr().add(i) != 0) + .count() + + 1, + ) + .to_vec(); + { + let __inserted = strings.get(&key).is_none(); + if __inserted { + *strings.subscript(&key) = std::slice::from_raw_parts( + c"original".as_ptr(), + (0..) + .take_while(|&i| *c"original".as_ptr().add(i) != 0) + .count() + + 1, + ) + .to_vec(); + } + (strings.find(&key), __inserted) + }; + let mut string_hit: (UnsafeBidirectionalIterator<(i32, Vec)>, bool) = match (({ + (*std::cell::LazyCell::force_mut(&mut *&raw mut visits_1)).prefix_inc(); + &mut text + } + as *mut Vec),) + { + (__tmp_31,) => { + let __inserted = strings.get(&key).is_none(); + if __inserted { + *strings.subscript(&key) = std::mem::take(&mut (*__tmp_31)); + } + (strings.find(&key), __inserted) + } + }; + assert!( + (((*std::cell::LazyCell::force_mut(&mut *&raw mut visits_1)) == (3)) && (!(string_hit.1))) + && (text == { + std::slice::from_raw_parts( + c"value".as_ptr(), + (0..) + .take_while(|&i| *c"value".as_ptr().add(i) != 0) + .count() + + 1, + ) + .to_vec() + }) + ); + key.prefix_inc(); + let mut string_new: (UnsafeBidirectionalIterator<(i32, Vec)>, bool) = match (({ + (*std::cell::LazyCell::force_mut(&mut *&raw mut visits_1)).prefix_inc(); + &mut text + } + as *mut Vec),) + { + (__tmp_32,) => { + let __inserted = strings.get(&key).is_none(); + if __inserted { + *strings.subscript(&key) = std::mem::take(&mut (*__tmp_32)); + } + (strings.find(&key), __inserted) + } + }; + assert!( + (((*std::cell::LazyCell::force_mut(&mut *&raw mut visits_1)) == (4)) && (string_new.1)) + && ((*string_new.0.iter_deref()).1 == { + std::slice::from_raw_parts( + c"value".as_ptr(), + (0..) + .take_while(|&i| *c"value".as_ptr().add(i) != 0) + .count() + + 1, + ) + .to_vec() + }) + ); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() { + std::cell::LazyCell::force(&*&raw const made_0); + std::cell::LazyCell::force(&*&raw const visits_1); +}