دستور الملكية
Rust

مرجع سريع بعد إتمام المنهج — ليست مادة تعليمية، لا شرح فيها، فقط تذكير بالصياغة. لكل مفهوم هنا شرح كامل في إقليمه (مذكور بين قوسين).

الربط والأنواع (٠٠)

let x = 5;                      // ثابت
let mut y = 5;                  // قابل للتعديل
let x: i64 = 5;                 // نوع صريح
const MAX: u32 = 100_000;       // ثابت زمن-ترجمة، بلا استنتاج، إلزامي النوع
static G: i32 = 10;             // عمر 'static، عنوان ذاكرة ثابت واحد
i8..i128, u8..u128, usize, isize, f32, f64, bool, char (4 بايت، Unicode scalar)

تعبيرات (٠٠)

let y = { let a = 3; a * a };           // كتلة = تعبير
let g = if s >= 90 { "A" } else { "B" }; // if تعبير
let v = loop { break 7; };               // loop تعبير، break يحمل قيمة
for i in 0..10 {}   // نصف مفتوح
for i in 0..=10 {}  // مغلق

ملكية واستعارة (٠١، ٠٢)

let s2 = s1;              // نقل (move) — s1 ميتة إن لم تكن Copy
let s2 = s1.clone();      // نسخ عميق صريح
fn f(x: &T)                // استعارة قراءة
fn f(x: &mut T)             // استعارة حصرية
&v[a..b]                   // شريحة (slice)، &str لشرائح النص

أعمار (٠٥)

fn f<'a>(x: &'a str, y: &'a str) -> &'a str
struct S<'a> { r: &'a str }
&'static str          // يعيش طوال البرنامج (.rodata أو مُصرَّح)
T: 'static             // T لا يحوي مراجع أقصر من 'static

قواعد الحذف: (١) كل مُدخَل مرجعي يأخذ عمره الخاص. (٢) مُدخَل مرجعي واحد ⇒ يُعطى للمخرجات كلها. (٣) وجود &self/&mut self ⇒ عمره للمخرجات.

enum / Option / Result / match (٠٣)

enum Shape { Circle(f64), Rect(f64, f64) }
match s { Shape::Circle(r) => .., Shape::Rect(w, h) => .. }   // إلزامي شامل
if let Some(x) = opt { .. }
let v = might_fail()?;                 // تُنشر الخطأ مبكرًا
fn main() -> Result<(), Box<dyn std::error::Error>> { .. }
.unwrap() / .expect("msg") / .unwrap_or(default) / .map(f) / .and_then(f)

traits / generics (٠٤)

trait Shape { fn area(&self) -> f64; fn name(&self) -> &str { "shape" } }
impl Shape for Circle { fn area(&self) -> f64 { .. } }
fn f<T: PartialOrd>(list: &[T]) -> &T          // static — monomorphized
fn f(x: &impl Shape)                            // سكّر لنفس الشيء
fn f(shapes: &[Box<dyn Shape>])                 // dynamic — vtable
#[derive(Debug, Clone, PartialEq, PartialOrd)]

إغلاقات ومنتِجات (٠٦)

let f = |x: i32| x + 1;               // يُستنتج Fn/FnMut/FnOnce من الجسم
let f = move || { /* يملك ما التقطه */ };
fn make() -> impl Fn(i32) -> i32       // static
fn make() -> Box<dyn Fn(i32) -> i32>   // dynamic

trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; }
v.iter().enumerate().filter(|(_, x)| ..).map(|(i, x)| ..).collect::<Vec<_>>();
v.iter().fold(0, |acc, x| acc + x);
s.chars() / s.char_indices() / s.bytes() / s.lines() / s.split_whitespace()

مؤشرات ذكية (٠٧)

النوعماذا يحلالقيد
Box<T>تمليك على heap، حجم ثابت للأنواع العودية/dynمالك واحد فقط
Rc<T>ملكية مشتركة (خيط واحد)&T فقط، غير Send
RefCell<T>تعديل داخلي، فحص وقت تشغيلpanic عند تعارض الاستعارات
Weak<T>مرجع لا يُحتسَب في العدّاديكسر دوائر Rc
let cell = RefCell::new(5);
*cell.borrow_mut() += 1;
Rc::clone(&x)  /  Rc::strong_count(&x)  /  Rc::downgrade(&x)  /  weak.upgrade()

تزامن (٠٨)

خيط واحدعدة خيوط
Rc<T>Arc<T>
RefCell<T>Mutex<T> (أو RwLock<T>)
let h = thread::spawn(move || { .. });   // يشترط 'static + Send
h.join().unwrap();
let data = Arc::new(Mutex::new(v));
data.lock().unwrap().push(x);             // .lock() تُرجع Result (تسمّم)
let (tx, rx) = std::sync::mpsc::channel();
tx.send(v).unwrap();  /  rx.recv().unwrap();

unsafe (٠٩)

القدرات الخمس فقط: إلغاء إشارة مؤشر خام، نداء unsafe fn، الوصول لـ static mut، تطبيق unsafe trait، الوصول لحقول union.

let r = &x as *const i32;              // إنشاء: آمن
unsafe { *r }                           // إلغاء إشارة: يحتاج unsafe
unsafe { alloc(layout) } / dealloc(ptr, layout) / realloc(..)
std::ptr::write(ptr, val)  /  std::ptr::read(ptr)  /  ptr.add(i)
NonNull::dangling()  /  std::mem::size_of::<T>()  /  align_of::<T>()

async (١٠)

trait Future { type Output; fn poll(&mut self, cx: &mut Context) -> Poll<Self::Output>; }
async fn f() -> T { let x = other().await; x }   // سكّر فوق Future يدوي

#[tokio::main]
async fn main() {
    let l = tokio::net::TcpListener::bind(addr).await.unwrap();
    loop {
        let (sock, _) = l.accept().await.unwrap();
        tokio::spawn(async move { handle(sock).await; });
    }
}

تحذير: لا تحتفظ بـ std::sync::MutexGuard عبر .await — استعمل tokio::sync::Mutex أو أنهِ نطاق القفل قبل أي .await.

أوامر cargo الأساسية

cargo new <name>        # مشروع جديد
cargo run                # بناء + تشغيل
cargo check              # فحص أنواع بلا توليد ثنائية (سريع)
cargo build --release    # بناء محسَّن (overflow يلتفّ لا يُفزِّع)
cargo clippy              # ناقد اصطلاحي
cargo fmt                 # تنسيق موحَّد
cargo test                # الاختبارات
rustup doc --std          # وثائق std بلا إنترنت
cargo +nightly miri run   # كشف UB ديناميكيًا (يحتاج nightly)