Rust / دليل حلول تحريري
حل E0499 وE0502: الاستعارات المتداخلة
تتبّع آخر استعمال لكل مرجع وافصل القراءة والتعديل واستخدم واجهات آمنة لإثبات انفصال المناطق.
قاعدة معرفة للقراءة فقط · بلا تعليقات عامة
تعرّف على الأعراض
يبلغ E0499 عادة عن استعارة تعديل ثانية مع استعمال الحصرية الأولى، ويبلغ E0502 عن تداخل مشتركة وقابلة للتعديل. تبين المواقع الأصل والتعارض والاستعمال اللاحق. هذه أخطاء ترجمة لا تقارير سباق تنفيذ.
قد يعرف المبرمج اختلاف فهرسين ولا تثبت الفهرسة العادية انفصالهما للفاحص. وقد يتعارض عرض محفوظ عبر push ولو بدت السعة كافية. شخّص علاقة المراجع لا سعة مرصودة.
افهم الأسباب المحتملة
- تسمح الاستعارة الآمنة بالمراقبة المشتركة أو التعديل الحصري وفق قواعدها. ليس المرجع المعدّل مجرد مؤشر كتابة يتعايش اعتباطيًا مع غيره. قد تستمر الاستعارة حتى آخر استخدام فلا يزيل إدراج عبارات مستقلة التعارض.
- قد يخلط التصميم القراءة والتعديل بلا حاجة أو يحتاج واجهة تثبت الانفصال. توفر clone لقطة مطلوبة، لكن التحويل الخام ينقل الالتزامات إلى unsafe وليس إصلاحًا عاديًا. وRefCell نموذج فحص تنفيذي قد يرفض التداخل أيضًا.
تتبّع الوصول الحصري المتزامن
يحفظ المثال المرفوض مرجعَي تعديل من المصفوفة قبل استعمالهما. لا تنفذه أو تختلق ناتجه. لا تعرض الفهرسة إثبات شرائح منفصلة رغم اختلاف صفر وواحد. افحص الحاجة للاستعمال معًا؛ فالتحديث المتتابع أبسط إذا لم تلزم عملية مشتركة.
fn main() {
let mut values = [1u32, 2];
let first = &mut values[0];
let second = &mut values[1];
println!("{first} {second}");
}
مرفوض عمدًا برمز E0499؛ افحص المواقع دون تشغيل.
استخدام إثبات انفصال آمن
تفحص split_at_mut الحد وتعيد شريحتين لا تتداخلان. يعدل التصحيح عنصرًا من كل جانب ويقرأ الأصل بعد انتهاء الاستعارتين. يبقى اختيار حدود وفهارس صالحة على المستدعي. إذا لم تلزم المراجع معًا فعدّل values[0] وvalues[1] بعبارتين. اختر ما يوضح الخاصية المقصودة.
fn main() {
let mut values = [1u32, 2];
let (left, right) = values.split_at_mut(1);
left[0] += 10;
right[0] += 20;
println!("{:?}", values);
}
[11, 22]
ينتج التقسيم عنصرًا بكل جانب، ويصح التعديلان وتطبع القراءة اللاحقة أحد عشر واثنين وعشرين.
إنهاء المراقبة قبل التعديل البنيوي
بالنسبة إلى E0502 قدّم آخر قراءة أو احسب ملخصًا مملوكًا أولًا. يستخدم المقتطف view بعد push فلا تنتهي الاستعارة مبكرًا. تسمح طباعتها قبل push بالتعديل حين تزول الحاجة. إذا لزمت لقطة لاحقة فامتلكها واحسب كلفة النسخ. لا تجعل كتلة حول التعديل المرجع المطلوب صالحًا.
fn main() {
let mut text = String::from("lab");
let view = &text;
text.push('!');
println!("{view}");
}
مرفوض عمدًا برمز E0502؛ تمدد القراءة الأخيرة الاستعارة المشتركة.
تحقق من نجاح الإصلاح
ترجم وشغّل المصحح بإصدار 2024؛ سطره [11, 22]. اختبر حدود التقسيم صفرًا والطول حيث يناسب مع معالجة الفراغ قبل الفهرسة. افحص المقتطفات المرفوضة ترجمة فقط لرموزها ولا تجعلها اختبارات تنفيذ.
في إصلاح القراءة ثم الكتابة أبقِ اختبارًا ينفذ التعديل المطلوب ويفحص النتيجة المملوكة. قد يخفي نجاح الترجمة وحده حذف تحديث لازم بالخطأ.
امنع تكرار المشكلة
- قصّر مرحلتي القراءة والتعديل وتجنب مراجع العناصر عبر التغيير البنيوي واستخدم واجهات الانفصال الآمنة. راجع آخر استعمال قبل إضافة استنساخ أو تعديل داخلي.