@@ -183,9 +183,24 @@ bool ConverterRefCount::VisitIncompleteArrayType(
183183}
184184
185185bool ConverterRefCount::VisitReferenceType (clang::ReferenceType *type) {
186+ auto pointee_type = type->getPointeeType ();
187+ if (pointee_type->isArrayType ()) {
188+ // A reference to an array decays straight to a pointer to its first
189+ // element, the same way a by-value array parameter would, instead of
190+ // going through a pointer to the whole boxed array.
191+ auto element_type = pointee_type->getAsArrayTypeUnsafe ()->getElementType ();
192+ PushConversionKind push1 (*this , ConversionKind::Ptr,
193+ !element_type->isArrayType ());
194+ PushConversionKind push2 (*this , ConversionKind::FullRefCount,
195+ element_type->isArrayType ());
196+ StrCat (" Ptr<" );
197+ Convert (element_type);
198+ StrCat (token::kGt );
199+ return false ;
200+ }
186201 PushConversionKind push (*this , ConversionKind::Pointee);
187202 StrCat (" Ptr<" );
188- Convert (type-> getPointeeType () );
203+ Convert (pointee_type );
189204 StrCat (token::kGt );
190205 return false ;
191206}
@@ -321,18 +336,43 @@ std::string ConverterRefCount::ConvertFreshLValue(clang::Expr *expr) {
321336 return std::format (" ({}).clone()" , std::move (str));
322337}
323338
324- std::string ConverterRefCount::ConvertObject (clang::Expr *expr) {
339+ std::string ConverterRefCount::ConvertObject (clang::Expr *expr,
340+ ObjectShape shape) {
325341 PushExprKind push (*this , ExprKind::Object);
342+ auto saved_shape = std::exchange (object_shape_, shape);
326343 auto str = ToString (expr);
327- if (expr->getType ()->isPointerType ()) {
328- computed_expr_type_ = ComputedExprType::FreshPointer;
329- return std::format (" {}.to_strong().as_pointer()" , std::move (str));
344+ object_shape_ = saved_shape;
345+ if (shape == ObjectShape::Element && expr->getType ()->isPointerType ()) {
346+ auto pointee = expr->getType ()->getPointeeType ();
347+ if (IsBoxedType (pointee) || pointee->isArrayType ()) {
348+ computed_expr_type_ = ComputedExprType::FreshPointer;
349+ return std::format (" {}.decay()" , std::move (str));
350+ }
330351 }
331352 return str;
332353}
333354
334- std::string ConverterRefCount::ConvertFreshObject (clang::Expr *expr) {
335- auto str = ConvertObject (expr);
355+ std::string
356+ ConverterRefCount::ConvertFreshObject (clang::Expr *expr,
357+ std::string_view target_ptr_type) {
358+ auto shape = ObjectShape::Whole;
359+ if (!target_ptr_type.empty ()) {
360+ auto type = expr->getType ().getNonReferenceType ();
361+ auto pointee = type->isPointerType () ? type->getPointeeType () : type;
362+ if (IsBoxedType (pointee) || pointee->isArrayType ()) {
363+ auto normalize = [](std::string s) {
364+ std::erase (s, ' ' );
365+ for (size_t pos; (pos = s.find (" ::<" )) != std::string::npos;)
366+ s.erase (pos, 2 );
367+ return s;
368+ };
369+ if (normalize (std::string (target_ptr_type)) ==
370+ normalize (ConvertPtrType (pointee))) {
371+ shape = ObjectShape::Element;
372+ }
373+ }
374+ }
375+ auto str = ConvertObject (expr, shape);
336376 if (isFresh ()) {
337377 return str;
338378 }
@@ -878,15 +918,10 @@ bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
878918 return false ;
879919 }
880920
881- // std::vector<T>& gets converted to Ptr<vec<T>>
882- // So we need to make a pointer to the vector itself
883- if (isObject ()) {
884- if (IsBoxedType (ref->getPointeeType ()) ||
885- ref->getPointeeType ()->isArrayType ()) {
886- StrCat (str, " .to_strong().as_pointer()" );
887- computed_expr_type_ = ComputedExprType::FreshPointer;
888- return false ;
889- }
921+ if (isObject () && WantsElementPtr () && IsBoxedType (ref->getPointeeType ())) {
922+ StrCat (str, " .decay()" );
923+ computed_expr_type_ = ComputedExprType::FreshPointer;
924+ return false ;
890925 }
891926
892927 // references are not boxed
@@ -1174,8 +1209,10 @@ bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
11741209 return false ;
11751210 }
11761211
1177- if (isObject ()) {
1178- StrCat (std::format (" {}.to_strong().as_pointer()" , std::move (str)));
1212+ if (isObject () && WantsElementPtr () && ref &&
1213+ IsBoxedType (ref->getPointeeType ())) {
1214+ StrCat (std::format (" {}.decay()" , std::move (str)));
1215+ computed_expr_type_ = ComputedExprType::FreshPointer;
11791216 return false ;
11801217 }
11811218
@@ -1281,7 +1318,7 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
12811318
12821319 if (pointee_type && abstract_structs_.contains (GetID (pointee_type))) {
12831320 PushConversionKind push (*this , ConversionKind::Unboxed);
1284- StrCat (std::format (" ( {}.to_strong() as Value <{}>).as_pointer_dyn( )" ,
1321+ StrCat (std::format (" {}.to_dyn:: <{}>(|w| w )" ,
12851322 ToString (sub_expr->IgnoreCasts ()),
12861323 ConvertPointeeType (expr->getType ())));
12871324 computed_expr_type_ = ComputedExprType::FreshPointer;
@@ -1309,10 +1346,10 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
13091346 // smart enough to pick the right specialization
13101347 PushConversionKind push (*this , ConversionKind::Unboxed);
13111348 PushParen paren (*this );
1312- StrCat (IsReferenceType (sub_expr) ? ConvertObject (sub_expr)
1313- : ConvertPointer ( sub_expr),
1314- keyword::kAs , ToString (expr->getType ()));
1315- computed_expr_type_ = ComputedExprType::FreshPointer;
1349+ StrCat (ConvertPointer (sub_expr));
1350+ if (! IsReferenceType ( sub_expr)) {
1351+ StrCat ( keyword::kAs , ToString (expr->getType ()));
1352+ }
13161353 return false ;
13171354 }
13181355 }
@@ -1899,7 +1936,8 @@ bool ConverterRefCount::VisitCXXForRangeStmtVector(
18991936 StrCat (" 'loop_:" );
19001937 StrCat (keyword::kFor ,
19011938 stmt->getLoopVariable ()->getType ().isConstQualified () ? " " : " mut" ,
1902- loop_var_name, keyword::kIn , ConvertObject (stmt->getRangeInit ()));
1939+ loop_var_name, keyword::kIn ,
1940+ ConvertObject (stmt->getRangeInit (), ObjectShape::Element));
19031941 StrCat (keyword::kAs , ConvertPtrType (stmt->getRangeInit ()->getType ()));
19041942
19051943 PushBrace brace (*this );
@@ -1941,7 +1979,8 @@ bool ConverterRefCount::VisitCXXForRangeStmtString(
19411979 StrCat (" 'loop_:" );
19421980 StrCat (keyword::kFor ,
19431981 stmt->getLoopVariable ()->getType ().isConstQualified () ? " " : " mut" ,
1944- loop_var_name, keyword::kIn , ConvertObject (stmt->getRangeInit ()));
1982+ loop_var_name, keyword::kIn ,
1983+ ConvertObject (stmt->getRangeInit (), ObjectShape::Element));
19451984 StrCat (" .to_string_iterator() as StringIterator<" ,
19461985 ToString (loop_var->getType ().getNonReferenceType ()), ' >' );
19471986
@@ -2196,8 +2235,7 @@ std::string ConverterRefCount::ConvertVarInitValue(clang::QualType qual_type,
21962235 ctx_.getAsArrayType (
21972236 expr->IgnoreParens ()->IgnoreImplicit ()->getType ())
21982237 ->getElementType ());
2199- return std::format (" Ptr::<Box<[{}]>>::from_string_literal_array({})" ,
2200- code_unit,
2238+ return std::format (" Ptr::<{}>::from_string_literal({})" , code_unit,
22012239 ToString (expr->IgnoreParens ()->IgnoreImplicit ()));
22022240 }
22032241 return std::format (" ({} as {})" , ConvertFreshPointer (expr),
@@ -2409,11 +2447,12 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
24092447
24102448 if (isLValue ()) {
24112449 PushConversionKind push_ck (*this , ConversionKind::Unboxed);
2412- pending_deref_.set (std::format (" ({} as {}).offset({})" ,
2413- ConvertObject (expr->getArg (0 )),
2414- ConvertPtrType (expr->getArg (0 )->getType ()),
2415- ConvertSubscriptIndex (expr->getArg (1 ))),
2416- /* fresh=*/ true , expr);
2450+ pending_deref_.set (
2451+ std::format (" ({} as {}).offset({})" ,
2452+ ConvertObject (expr->getArg (0 ), ObjectShape::Element),
2453+ ConvertPtrType (expr->getArg (0 )->getType ()),
2454+ ConvertSubscriptIndex (expr->getArg (1 ))),
2455+ /* fresh=*/ true , expr);
24172456 break ;
24182457 }
24192458
@@ -2430,7 +2469,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
24302469
24312470 PushConversionKind push (*this , ConversionKind::Unboxed);
24322471 StrCat (std::format (" ({} as {}).offset({})" ,
2433- ConvertObject (expr->getArg (0 )),
2472+ ConvertObject (expr->getArg (0 ), ObjectShape::Element ),
24342473 ConvertPtrType (expr->getArg (0 )->getType ()),
24352474 ConvertSubscriptIndex (expr->getArg (1 ))));
24362475
@@ -2611,11 +2650,10 @@ void ConverterRefCount::ConvertDeref(clang::Expr *expr) {
26112650 }
26122651 }
26132652
2614- if (isObject ()) {
2615- if (IsBoxedType (pointee_type) || pointee_type->isArrayType ()) {
2616- StrCat (" .to_strong().as_pointer()" );
2617- computed_expr_type_ = ComputedExprType::FreshPointer;
2618- }
2653+ if (isObject () && WantsElementPtr () &&
2654+ (IsBoxedType (pointee_type) || pointee_type->isArrayType ())) {
2655+ StrCat (" .decay()" );
2656+ computed_expr_type_ = ComputedExprType::FreshPointer;
26192657 }
26202658}
26212659
0 commit comments