@@ -3479,14 +3479,9 @@ std::string Converter::GetUnsafeTypeAsString(clang::QualType qual_type) const {
34793479
34803480void Converter::ConvertVarInit (clang::QualType qual_type, clang::Expr *expr) {
34813481 if (qual_type->isReferenceType () && !IsReferenceType (expr)) {
3482- if (IsGlobalVar (expr)) {
3483- StrCat (" &raw" );
3484- StrCat (IsMut (qual_type) ? keyword_mut_ : keyword::kConst );
3485- } else {
3486- StrCat (token::kRef );
3487- if (IsMut (qual_type)) {
3488- StrCat (keyword_mut_);
3489- }
3482+ StrCat (token::kRef );
3483+ if (IsMut (qual_type)) {
3484+ StrCat (keyword_mut_);
34903485 }
34913486 }
34923487 if (qual_type->isFunctionPointerType ()) {
@@ -4179,12 +4174,35 @@ std::string Converter::ConvertIRFragment(
41794174 auto all_args = BuildUnifiedArgs (expr, args, num_args);
41804175
41814176 std::string result;
4182- for (auto &frag : fragments) {
4183- if (auto *t = std::get_if<TextFragment>(&frag)) {
4184- result += t->text ;
4185- } else if (auto *g = std::get_if<GenericFragment>(&frag)) {
4177+ for (size_t i = 0 ; i < fragments.size (); ++i) {
4178+ const auto &frag = fragments[i];
4179+ if (const auto *t = std::get_if<TextFragment>(&frag)) {
4180+ std::string text = t->text ;
4181+ // If this text fragment ends with a lone '&' (reference operator, not
4182+ // '&&' or '&mut') and the immediately following fragment is a placeholder
4183+ // for a global variable, upgrade '&' to '&raw const' or '&raw mut' to
4184+ // comply with Rust 2024's ban on shared references to mutable statics.
4185+ if (!text.empty () && text.back () == ' &' &&
4186+ (text.size () < 2 || text[text.size () - 2 ] != ' &' ) &&
4187+ i + 1 < fragments.size ()) {
4188+ if (const auto *next_ph =
4189+ std::get_if<PlaceholderFragment>(&fragments[i + 1 ])) {
4190+ auto next_idx = next_ph->n ;
4191+ if (next_idx < all_args.size () && IsGlobalVar (all_args[next_idx])) {
4192+ const auto *decl_ref = clang::dyn_cast<clang::DeclRefExpr>(
4193+ all_args[next_idx]->IgnoreImplicit ());
4194+ bool is_const =
4195+ decl_ref &&
4196+ decl_ref->getDecl ()->getType ().isConstQualified ();
4197+ text.pop_back (); // remove '&'
4198+ text += is_const ? " &raw const " : std::string (" &raw" ) + keyword_mut_;
4199+ }
4200+ }
4201+ }
4202+ result += text;
4203+ } else if (const auto *g = std::get_if<GenericFragment>(&frag)) {
41864204 result += Mapper::InstantiateTemplate (GetCalleeOrExpr (expr), g->n );
4187- } else if (auto *ph = std::get_if<PlaceholderFragment>(&frag)) {
4205+ } else if (const auto *ph = std::get_if<PlaceholderFragment>(&frag)) {
41884206 auto arg_idx = ph->n ;
41894207 assert (arg_idx < all_args.size ());
41904208 auto *arg = all_args[arg_idx];
@@ -4204,7 +4222,7 @@ std::string Converter::ConvertIRFragment(
42044222 .is_index_base = ph->is_index_base ,
42054223 };
42064224 result += ConvertPlaceholder (expr, arg, ph_ctx);
4207- } else if (auto *mc =
4225+ } else if (const auto *mc =
42084226 std::get_if<std::unique_ptr<MethodCallFragment>>(&frag)) {
42094227 result += ConvertMappedMethodCall (expr, **mc, args, num_args, ctx);
42104228 }
0 commit comments