@@ -89,23 +89,24 @@ static bool IsTrivialValue(const clang::Expr *expr) {
8989// Whether expr accesses a field of a struct that is stored in the struct.
9090static bool IsFieldAccess (const clang::Expr *expr) {
9191 auto *member = clang::dyn_cast<clang::MemberExpr>(expr);
92- auto *field =
93- member ? clang::dyn_cast<clang::FieldDecl>(member->getMemberDecl ())
94- : nullptr ;
92+ auto *field = member
93+ ? clang::dyn_cast<clang::FieldDecl>(member->getMemberDecl ())
94+ : nullptr ;
9595 return field && IsTranslatedStruct (field->getParent ()) &&
9696 !field->getType ()->isReferenceType ();
9797}
9898
9999// Whether the field holds a Value of its own, instead of being stored in the
100- // struct. Vectors are, so that pointers to their elements, and to the fields
101- // of those, point into the vector and not the struct.
102- static bool IsValueField (clang::ASTContext &ctx,
103- const clang::ValueDecl *decl) {
100+ // struct. Arrays and vectors are, so that pointers to their elements, and to
101+ // the fields of those, point into the array and not the struct.
102+ static bool IsValueField (clang::ASTContext &ctx, const clang::ValueDecl *decl) {
104103 auto *field = clang::dyn_cast<clang::FieldDecl>(decl);
105- return field && IsTranslatedStruct (field->getParent ()) &&
106- !field->getType ()->isReferenceType () &&
107- Mapper::Map (ctx, field->getType ().getUnqualifiedType ())
108- .starts_with (" Vec<" );
104+ if (!field || !IsTranslatedStruct (field->getParent ())) {
105+ return false ;
106+ }
107+ auto type = field->getType ();
108+ return !type->isReferenceType () &&
109+ (type->isConstantArrayType () || IsBoxedType (ctx, type));
109110}
110111
111112// Whether evaluating expr reads a field of a struct, and hence borrows the
@@ -596,15 +597,9 @@ std::string ConverterRefCount::GetShallowCopy(const clang::RecordDecl *decl,
596597 auto name = GetNamedDeclAsString (field);
597598 auto type = field->getType ();
598599 auto value = std::format (" {}.{}" , src, name);
600+ // Value fields are shared.
599601 if (auto *record = type->getAsRecordDecl (); IsTranslatedStruct (record)) {
600602 value = GetShallowCopy (record, value);
601- } else if (auto *arr = ctx_.getAsConstantArrayType (type);
602- arr && IsTranslatedStruct (
603- arr->getElementType ()->getAsRecordDecl ())) {
604- auto elem = std::format (" __e{}" , src.size ());
605- value = std::format (
606- " {}.iter().map(|{}| {}).collect()" , value, elem,
607- GetShallowCopy (arr->getElementType ()->getAsRecordDecl (), elem));
608603 } else {
609604 value += " .clone()" ;
610605 }
@@ -684,8 +679,14 @@ void ConverterRefCount::AddCloneTrait(const clang::RecordDecl *decl) {
684679 PushBrace init_brace (*this );
685680 for (auto *field : decl->fields ()) {
686681 auto name = GetNamedDeclAsString (field);
687- StrCat (std::format (" {}: {}," , name,
688- GetDeepCopy (field->getType (), " self." + name)));
682+ StrCat (std::format (
683+ " {}: {}," , name,
684+ IsValueField (ctx_, field)
685+ ? std::format (
686+ " Rc::new(RefCell::new({}))" ,
687+ GetDeepCopy (field->getType (),
688+ std::format (" (*self.{}.borrow())" , name)))
689+ : GetDeepCopy (field->getType (), " self." + name)));
689690 }
690691 return ;
691692 }
@@ -809,9 +810,12 @@ void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) {
809810 for (auto *field : decl->fields ()) {
810811 auto byte_off = layout.getFieldOffset (idx) / 8 ;
811812 auto byte_size = ctx_.getTypeSize (field->getType ()) / 8 ;
812- StrCat (std::format (" self.{}.to_bytes(&mut buf[{}..{}]);" ,
813- GetNamedDeclAsString (field), byte_off,
814- byte_off + byte_size));
813+ auto name = GetNamedDeclAsString (field);
814+ StrCat (std::format (" {}.to_bytes(&mut buf[{}..{}]);" ,
815+ IsValueField (ctx_, field)
816+ ? std::format (" (*self.{}.borrow())" , name)
817+ : " self." + name,
818+ byte_off, byte_off + byte_size));
815819 ++idx;
816820 }
817821 }
@@ -825,13 +829,14 @@ void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) {
825829 for (auto *field : decl->fields ()) {
826830 auto byte_off = layout.getFieldOffset (idx) / 8 ;
827831 auto byte_size = ctx_.getTypeSize (field->getType ()) / 8 ;
828- PushConversionKind push (*this , IsValueField (ctx_, field)
829- ? ConversionKind::FullRefCount
830- : ConversionKind::Pointee);
831- StrCat (std::format (" {}: <{}>::from_bytes(&buf[{}..{}])," ,
832- GetNamedDeclAsString (field),
833- ToString (field->getType ()), byte_off,
834- byte_off + byte_size));
832+ PushConversionKind push (*this , ConversionKind::Pointee);
833+ auto value = std::format (" <{}>::from_bytes(&buf[{}..{}])" ,
834+ ToString (field->getType ()), byte_off,
835+ byte_off + byte_size);
836+ if (IsValueField (ctx_, field)) {
837+ value = std::format (" Rc::new(RefCell::new({}))" , value);
838+ }
839+ StrCat (std::format (" {}: {}," , GetNamedDeclAsString (field), value));
835840 ++idx;
836841 }
837842 }
@@ -2045,8 +2050,7 @@ bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) {
20452050std::string ConverterRefCount::ConvertRecordPlace (clang::MemberExpr *expr,
20462051 bool mut) {
20472052 auto *base = expr->getBase ();
2048- if (clang::isa<clang::CXXThisExpr>(base->IgnoreCasts ()) &&
2049- !ThisIsRustPtr ()) {
2053+ if (clang::isa<clang::CXXThisExpr>(base->IgnoreCasts ()) && !ThisIsRustPtr ()) {
20502054 return std::string (keyword::kSelfValue );
20512055 }
20522056 if (expr->isArrow ()) {
@@ -2084,11 +2088,12 @@ static bool IsCloneSource(const clang::Expr *expr) {
20842088 }
20852089 }
20862090 auto *ref = clang::dyn_cast<clang::DeclRefExpr>(expr);
2087- auto *param = ref ? clang::dyn_cast<clang::ParmVarDecl>(ref->getDecl ())
2088- : nullptr ;
2089- auto *ctor = param ? clang::dyn_cast<clang::CXXConstructorDecl>(
2090- param->getDeclContext ())
2091- : nullptr ;
2091+ auto *param =
2092+ ref ? clang::dyn_cast<clang::ParmVarDecl>(ref->getDecl ()) : nullptr ;
2093+ auto *ctor =
2094+ param
2095+ ? clang::dyn_cast<clang::CXXConstructorDecl>(param->getDeclContext ())
2096+ : nullptr ;
20922097 return ctor && ctor->isCopyConstructor () && ctor->isDefaulted () &&
20932098 param->getName ().empty ();
20942099}
@@ -2196,8 +2201,7 @@ ConverterRefCount::FindStructPtr(clang::Expr *place, bool mut) {
21962201 }
21972202}
21982203
2199- std::optional<std::string>
2200- ConverterRefCount::ConvertInStructPtr (
2204+ std::optional<std::string> ConverterRefCount::ConvertInStructPtr (
22012205 clang::Expr *place, bool mut, llvm::function_ref<std::string()> convert) {
22022206 auto sp = FindStructPtr (place, mut);
22032207 if (!sp || sp->nested ) {
@@ -2232,21 +2236,8 @@ std::string ConverterRefCount::ConvertFieldPointer(clang::MemberExpr *expr) {
22322236 } else {
22332237 base_ptr = ConvertPointer (base);
22342238 }
2235- auto str = std::format (" field_ptr!({}, {})" , base_ptr,
2236- GetNamedDeclAsString (expr->getMemberDecl ()));
2237-
2238- // Pointers to arrays and containers either point to the whole object or
2239- // to its elements. The type is inferred from the context, like for
2240- // `as_pointer()`, unless we know which one is wanted.
2241- if (isObject ()) {
2242- auto field_type = expr->getMemberDecl ()->getType ();
2243- if (WantsElementPtr ()) {
2244- return std::format (" ({} as {})" , str, ConvertPtrType (field_type));
2245- }
2246- PushConversionKind push (*this , ConversionKind::Pointee);
2247- return std::format (" ({} as Ptr<{}>)" , str, ToString (field_type));
2248- }
2249- return str;
2239+ return std::format (" field_ptr!({}, {})" , base_ptr,
2240+ GetNamedDeclAsString (expr->getMemberDecl ()));
22502241}
22512242
22522243void ConverterRefCount::ConvertFieldAccess (clang::MemberExpr *expr) {
@@ -2256,8 +2247,8 @@ void ConverterRefCount::ConvertFieldAccess(clang::MemberExpr *expr) {
22562247
22572248 if (field_type->isReferenceType ()) {
22582249 // The field holds a pointer to the referenced object.
2259- auto str = std::format ( " {}.{} " , ConvertRecordPlace (expr, /* mut= */ false ),
2260- name);
2250+ auto str =
2251+ std::format ( " {}.{} " , ConvertRecordPlace (expr, /* mut= */ false ), name);
22612252 if (isAddrOf ()) {
22622253 StrCat (str);
22632254 computed_expr_type_ = ComputedExprType::Pointer;
@@ -2274,9 +2265,9 @@ void ConverterRefCount::ConvertFieldAccess(clang::MemberExpr *expr) {
22742265 auto sp = FindStructPtr (expr);
22752266 if (!sp || sp->nested ) {
22762267 auto *object = expr->getBase ()->IgnoreParenImpCasts ();
2277- bool borrows = !field_places_. contains (expr) && ! IsCloneSource (object) &&
2278- !(clang::isa<clang::CXXThisExpr> (object) &&
2279- !ThisIsRustPtr ());
2268+ bool borrows =
2269+ !field_places_. contains (expr) && ! IsCloneSource (object) &&
2270+ !(clang::isa<clang::CXXThisExpr>(object) && !ThisIsRustPtr ());
22802271 PushBrace block (*this , borrows && isAddrOf ());
22812272 ConvertFieldPlace (expr, ConvertValueField (expr));
22822273 return ;
@@ -2344,8 +2335,8 @@ void ConverterRefCount::ConvertFieldPlace(clang::MemberExpr *expr,
23442335 computed_expr_type_ = ComputedExprType::FreshPointer;
23452336 return ;
23462337 }
2347- StrCat (std::format ( " (*{}.{}()) " , place,
2348- isRValue () ? " borrow" : " borrow_mut" ));
2338+ StrCat (
2339+ std::format ( " (*{}.{}()) " , place, isRValue () ? " borrow" : " borrow_mut" ));
23492340 SetValueFreshness (expr->getType ());
23502341}
23512342
@@ -3038,9 +3029,8 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
30383029 break ;
30393030
30403031 case clang::OverloadedOperatorKind::OO_Subscript: {
3041- if (ConvertWithHoistedIndex (expr, expr->getArg (0 ), expr->getArg (1 ), [&] {
3042- ConvertCXXOperatorCallExpr (expr);
3043- })) {
3032+ if (ConvertWithHoistedIndex (expr, expr->getArg (0 ), expr->getArg (1 ),
3033+ [&] { ConvertCXXOperatorCallExpr (expr); })) {
30443034 break ;
30453035 }
30463036
@@ -3423,8 +3413,7 @@ bool ConverterRefCount::IsReferenceType(const clang::Expr *expr) const {
34233413}
34243414
34253415// Collects the ways placeholder `n` is accessed in `fragments`.
3426- static void
3427- CollectPlaceholderAccesses (
3416+ static void CollectPlaceholderAccesses (
34283417 const std::vector<TranslationRule::BodyFragment> &fragments, unsigned n,
34293418 std::vector<TranslationRule::Access> &accesses) {
34303419 for (const auto &frag : fragments) {
@@ -3487,7 +3476,7 @@ std::optional<std::string> ConverterRefCount::ConvertOnFieldReceiver(
34873476 auto sp = receiver_ph.access != TranslationRule::Access::kMove &&
34883477 !receiver->getType ()->isPointerType () &&
34893478 !RuleRegistry::ParamIsPointer (ctx_, GetCalleeOrExpr (expr),
3490- receiver_ph.n )
3479+ receiver_ph.n )
34913480 ? FindStructPtr (receiver, receiver_ph.access !=
34923481 TranslationRule::Access::kBorrow )
34933482 : std::nullopt ;
@@ -3823,14 +3812,15 @@ ConverterRefCount::DestroyMembers(const clang::CXXRecordDecl *decl) {
38233812 auto *elem =
38243813 field->getType ()->getBaseElementTypeUnsafe ()->getAsCXXRecordDecl ();
38253814 assert (elem);
3815+ // The array is a Value of its own.
38263816 out += std::format (
3827- " {{ let __p: Ptr<{3}> = field_ptr!( self, {0}) ; for __i in "
3828- " 0..__p.len() {{ {2}::{1}(&__p.offset(__i as isize)); }} }}\n " ,
3817+ " {{ let __p: Ptr<{3}> = self.with(|__s| __s. {0}.as_pointer()) ; for "
3818+ " __i in 0..__p.len() {{ {2}::{1}(&__p.offset(__i as isize)); }} }}\n " ,
38293819 name, kDestructorName , TraitName (elem), GetRecordName (elem));
38303820 } else {
3831- out += std::format (
3832- " {2}::{1}(&field_ptr!(self, {0})); \n " , name, kDestructorName ,
3833- TraitName (field->getType ()->getAsCXXRecordDecl ()));
3821+ out += std::format (" {2}::{1}(&field_ptr!(self, {0})); \n " , name,
3822+ kDestructorName ,
3823+ TraitName (field->getType ()->getAsCXXRecordDecl ()));
38343824 }
38353825 }
38363826 return out;
0 commit comments