المستوى المطلوب: متوسط — تحتاج تعرف أساسيات لغة برمجة فيها مؤشرات أو references (C/C++/Go/JavaScript)، ومش لازم تكون كتبت Rust قبل كده.
الـ Borrow Checker في Rust مش عقوبة، هو أمن مجاني للذاكرة بدون Garbage Collector. لو عمرك اتكسر تطبيقك بسبب null pointer أو use-after-free أو data race، Rust بتمنع التلاتة دول قبل ما الكود يكمّل compile. القصة كلها في 3 قواعد بس.
Rust Ownership: 3 قواعد بتمنع 70% من Memory Bugs قبل الـ Compile
المشكلة باختصار
عندك خياريّن في معظم اللغات. الأول: Garbage Collector زي Java أو Go، بياكل CPU عشوائيًا في pause times وبيخفي تكلفته في الـ runtime. الثاني: malloc وfree اليدوي زي C، سريع لكن طلقة في الرجل عند أول غلطة (use-after-free, double free, dangling pointer).
Microsoft Security Response Center نشرت في 2019 إن ~70% من CVEs الأمنية في منتجاتها كانت memory safety bugs. Google قالت في تقرير Android Security 2024 إن نسبة memory safety vulnerabilities في Android نزلت من 76% في 2019 لـ 24% في 2024 بعد ما بدأوا يكتبوا طبقات النظام بـ Rust بدل C++. الأرقام دي مش تسويق، دي اللي خلّت Linux Kernel 7.0 (نزل 12 أبريل 2026) يعتمد Rust كـ stable داخل الـ kernel.
Rust بتختار طريق ثالث: تمنع الغلطات وقت الـ compile، بدون runtime cost. القواعد بتشتغل عبر مفهوم اسمه Ownership.
مثال بسيط جدًا: مفتاح البيت
تخيل بيت معاه مفتاح واحد بس. لو معاك المفتاح، أنت "المالك"، تقدر تستخدم البيت كيف ما تشاء. لو ادّيت المفتاح لصاحبك، هو بقى المالك، وأنت ما تقدرش تدخل تاني إلا لما يردّه. تقدر "تعير" المفتاح لشخص علشان يبص بس على البيت ويرجعه (ده اسمه borrow)، لكن وأنت معيره ما تقدرش تعدّل في البيت في نفس الوقت. لو فيه كذا واحد عايز يبص (قراءة فقط)، تمام، اعمل نسخ متعددة من مفتاح القراءة. لكن لو واحد بيكتب وواحد بيقرا في نفس اللحظة، فيه احتمال تخبيص بيانات.
دي بالظبط فلسفة Ownership في Rust، الفرق إن الـ compiler هو اللي بيراقب القواعد بدل ما تعتمد على ذاكرتك.
التعريف العلمي: 3 قواعد ملزمة
- كل قيمة (value) ليها مالك واحد بس في أي لحظة من حياة البرنامج.
- لما المالك يخرج من نطاقه (scope)، القيمة بتتحرر تلقائيًا عن طريق دالة اسمها
drop. ده مش GC، ده deterministic destruction معروف وقت الـ compile. - تقدر تعمل borrow غير قابل للتعديل (
&T) كم ما تحب في نفس الوقت، أو borrow قابل للتعديل واحد فقط (&mut T)، لكن مش الاتنين معًا.
القاعدة التالتة هي اللي بتمنع data races في الكود متعدد الـ threads قبل ما يشتغل أصلًا. ده مكسب فعلي مش متوفر في C++ ولا Go.
كود Rust شغّال — Move Semantics
fn main() {
let s1 = String::from("hello");
let s2 = s1; // الملكية اتنقلت من s1 لـ s2 (move)
// println!("{}", s1); // ❌ غلطة compile: s1 ما بقاش valid
println!("{}", s2); // ✅ s2 هو المالك دلوقتي
} // s2 خرج من scope هنا، الذاكرة بتتحرر تلقائيًالو جربت السطر اللي فيه التعليق، الـ compiler هيرفض ويقولك بالحرف: "value borrowed here after move". مفيش فحص runtime، كل الفحص حصل وقت الـ compile. النتيجة: صفر تكلفة في الـ runtime، صفر null pointer dereference، صفر use-after-free.
مثال Borrow صح
fn print_length(s: &String) {
println!("الطول: {}", s.len());
} // s هنا reference، مش المالك. لما الدالة تنتهي، الـ reference بيتشال،
// لكن القيمة الأصلية ما تنحذفش.
fn main() {
let name = String::from("ahmed");
print_length(&name); // عيرت reference
println!("الاسم لسه موجود: {}", name); // ✅ شغّال
}مثال Borrow غلط (بيمنعه الـ compiler)
fn main() {
let mut data = vec![1, 2, 3];
let r1 = &mut data; // borrow قابل للتعديل
let r2 = &mut data; // ❌ غلطة: مش مسموح اتنين mutable في نفس الوقت
println!("{:?} {:?}", r1, r2);
}الـ compiler هيرفض ويوجّهك للحل. ده بيمنع data race مستحيل تلاقيه في C++ غير وقت ما الإنتاج يطفح.
Trade-offs: بتكسب إيه وبتخسر إيه
المكسب الأساسي: ذاكرة آمنة بدون GC، بدون runtime cost، مع دعم concurrency بأمان مضمون وقت الـ compile. حسب بنشمارك TechEmpower الأخير (Round 22)، Rust frameworks زي Actix و Axum بتخش في توب 5 في معظم الـ benchmarks، بـ latency أقل من Go بـ 30-50% في حالات الـ JSON serialization الثقيلة.
الثمن:
- منحنى تعلّم حاد. أول 2-3 أسابيع هتحارب الـ compiler. ده مش maybe، ده غالبًا فعلي، حتى للمحترفين.
- زمن compile أبطأ. مشروع متوسط في Rust بياخد ~45 ثانية في incremental build، نفس الحجم في Go بياخد ~12 ثانية. الفرق ده ثمن الـ static analysis اللي بيعمله الـ Borrow Checker.
- كود verbose في البداية. هتشوف
BoxوRcوArcوRefCell، وكل واحد له use case معين.
الافتراض المهم: المكسب ده يستاهل لو بتكتب أنظمة فيها concurrency حقيقي (web servers, databases, kernels)، أو كود حساس أمنيًا، أو كود متوقع يعيش 5+ سنين. لو بتكتب prototype لأسبوعين، الثمن أعلى من المكسب.
متى لا تستخدم Rust
- Prototyping سريع: Python أو TypeScript أسرع 5-10× في الكتابة الأولية. اشتغل بيهم لحد ما المنتج يثبت.
- فريق ما يقدرش يقعد 4-6 أسابيع للتعلم: الـ Borrow Checker مش بيدّي discount للـ deadlines.
- كود فيه graphs معقدة بـ cyclic references: ممكن في Rust، لكن هتحتاج
Rc<RefCell<T>>اللي بيحوّل جزء من الفحص لـ runtime. ساعتها فكر في Go. - تطبيقات Web CRUD بسيطة: Go أو Node.js هيوصلوك للنتيجة في ربع الوقت بكفاءة كافية لـ < 10K طلب/ثانية.
الخطوة التالية
افتح terminal واكتب cargo new ownership_demo، انسخ snippet الـ Move Semantics اللي فوق في src/main.rs، وحاول تعدّله بحيث s1 يفضل valid بعد ما s2 تاخد القيمة. هتلاقي 3 حلول: clone() (نسخة كاملة في الـ heap)، أو reference (&s1)، أو نوع بيدعم Copy زي i32. كل خيار له تكلفة مختلفة. الجلسة دي (30 دقيقة) هتفهّمك القواعد التلاتة أحسن من قراءة 200 صفحة كتاب.
المصادر
- The Rust Programming Language Book — الفصل الرابع: Understanding Ownership (
doc.rust-lang.org/book/ch04-00-understanding-ownership.html) - Microsoft Security Response Center: "A proactive approach to more secure code" — يوليو 2019
- Google Android Security Report 2024 — رابط رسمي عبر
security.googleblog.com - Linux Kernel 7.0 release notes — 12 أبريل 2026، إعلان دعم Rust كـ stable داخل الـ kernel
- TechEmpower Web Framework Benchmarks Round 22 (2025) — مقارنات Rust frameworks مع Go و Node.js
- Rust Reference: Ownership and Borrowing Semantics (
doc.rust-lang.org/reference)