[{"data":1,"prerenderedAt":2390},["ShallowReactive",2],{"page-\u002Frust\u002F25-unsafe-rust":3},{"id":4,"title":5,"body":6,"description":2383,"extension":2384,"meta":2385,"navigation":309,"path":2386,"seo":2387,"stem":2388,"__hash__":2389},"content\u002Frust\u002F25-unsafe-rust.md","25 — Unsafe Rust",{"type":7,"value":8,"toc":2339},"minimark",[9,13,26,70,77,84,166,177,214,226,230,338,368,373,386,390,485,494,550,559,565,625,637,682,687,751,761,765,858,864,871,998,1015,1022,1109,1129,1133,1236,1244,1248,1261,1281,1288,1293,1331,1334,1338,1392,1398,1402,1405,1477,1484,1492,1500,1504,1594,1617,1621,1625,1730,1736,1742,1790,1797,1863,1874,1893,1897,1903,1922,2028,2037,2072,2076,2185,2191,2260,2264,2295,2304,2308,2332,2335],[10,11,5],"h1",{"id":12},"_25-unsafe-rust",[14,15,16,20,21,25],"p",{},[17,18,19],"code",{},"unsafe"," lets you do things the compiler can't verify. It doesn't turn off the borrow checker — it adds five ",[22,23,24],"strong",{},"superpowers",":",[27,28,29,41,47,60,67],"ol",{},[30,31,32,33,36,37,40],"li",{},"Dereference raw pointers (",[17,34,35],{},"*const T",", ",[17,38,39],{},"*mut T",").",[30,42,43,44,46],{},"Call ",[17,45,19],{}," functions (including FFI).",[30,48,49,50,52,53,56,57,40],{},"Implement ",[17,51,19],{}," traits (e.g., ",[17,54,55],{},"Send","\u002F",[17,58,59],{},"Sync",[30,61,62,63,66],{},"Access\u002Fmutate ",[17,64,65],{},"static mut"," globals.",[30,68,69],{},"Access union fields.",[14,71,72,73,76],{},"The rest of Rust still applies (borrowing, types, lifetimes). Unsafe is a contract: ",[22,74,75],{},"you"," prove soundness; the compiler trusts you.",[78,79,81,83],"h2",{"id":80},"unsafe-blocks",[17,82,19],{}," Blocks",[85,86,88],"code-wrapper",{"language":87},"rust",[89,90,94],"pre",{"className":91,"code":92,"language":87,"meta":93,"style":93},"language-rust shiki shiki-themes github-light github-dark","let p: *const i32 = &5;\nunsafe {\n    println!(\"{}\", *p);\n}\n","",[17,95,96,131,139,160],{"__ignoreMap":93},[97,98,101,105,109,111,114,118,121,124,128],"span",{"class":99,"line":100},"line",1,[97,102,104],{"class":103},"svdQ7","let",[97,106,108],{"class":107},"ssxIu"," p",[97,110,25],{"class":103},[97,112,113],{"class":103}," *const",[97,115,117],{"class":116},"sIsaT"," i32",[97,119,120],{"class":103}," =",[97,122,123],{"class":103}," &",[97,125,127],{"class":126},"snvgF","5",[97,129,130],{"class":107},";\n",[97,132,134,136],{"class":99,"line":133},2,[97,135,19],{"class":103},[97,137,138],{"class":107}," {\n",[97,140,142,145,148,152,154,157],{"class":99,"line":141},3,[97,143,144],{"class":116},"    println!",[97,146,147],{"class":107},"(",[97,149,151],{"class":150},"sJ6F3","\"{}\"",[97,153,36],{"class":107},[97,155,156],{"class":103},"*",[97,158,159],{"class":107},"p);\n",[97,161,163],{"class":99,"line":162},4,[97,164,165],{"class":107},"}\n",[14,167,168,171,172,174,175,40],{},[17,169,170],{},"unsafe fn"," is a function whose body requires unsafe — calling it from safe code is allowed only in an ",[17,173,19],{}," block (or ",[17,176,170],{},[85,178,179],{"language":87},[89,180,182],{"className":91,"code":181,"language":87,"meta":93,"style":93},"unsafe fn dangerous() {}\nunsafe { dangerous(); }   \u002F\u002F OK\n",[17,183,184,197],{"__ignoreMap":93},[97,185,186,188,191,194],{"class":99,"line":100},[97,187,19],{"class":103},[97,189,190],{"class":103}," fn",[97,192,193],{"class":116}," dangerous",[97,195,196],{"class":107},"() {}\n",[97,198,199,201,204,207,210],{"class":99,"line":133},[97,200,19],{"class":103},[97,202,203],{"class":107}," { ",[97,205,206],{"class":116},"dangerous",[97,208,209],{"class":107},"(); }   ",[97,211,213],{"class":212},"sdCPZ","\u002F\u002F OK\n",[14,215,216,217,219,220,222,223,225],{},"In edition 2024+, calling ",[17,218,170],{}," inside ",[17,221,170],{}," also requires an explicit ",[17,224,19],{}," block (no longer implicit).",[78,227,229],{"id":228},"raw-pointers","Raw Pointers",[85,231,232],{"language":87},[89,233,235],{"className":91,"code":234,"language":87,"meta":93,"style":93},"let x = 5;\nlet p1: *const i32 = &x;        \u002F\u002F implicit coercion\nlet p2: *mut i32 = &mut x as *mut i32;\n\nunsafe { println!(\"{} {}\", *p1, *p2); }\n",[17,236,237,252,275,305,311],{"__ignoreMap":93},[97,238,239,241,244,247,250],{"class":99,"line":100},[97,240,104],{"class":103},[97,242,243],{"class":107}," x ",[97,245,246],{"class":103},"=",[97,248,249],{"class":126}," 5",[97,251,130],{"class":107},[97,253,254,256,259,261,263,265,267,269,272],{"class":99,"line":133},[97,255,104],{"class":103},[97,257,258],{"class":107}," p1",[97,260,25],{"class":103},[97,262,113],{"class":103},[97,264,117],{"class":116},[97,266,120],{"class":103},[97,268,123],{"class":103},[97,270,271],{"class":107},"x;        ",[97,273,274],{"class":212},"\u002F\u002F implicit coercion\n",[97,276,277,279,282,284,287,289,291,294,296,299,301,303],{"class":99,"line":141},[97,278,104],{"class":103},[97,280,281],{"class":107}," p2",[97,283,25],{"class":103},[97,285,286],{"class":103}," *mut",[97,288,117],{"class":116},[97,290,120],{"class":103},[97,292,293],{"class":103}," &mut",[97,295,243],{"class":107},[97,297,298],{"class":103},"as",[97,300,286],{"class":103},[97,302,117],{"class":116},[97,304,130],{"class":107},[97,306,307],{"class":99,"line":162},[97,308,310],{"emptyLinePlaceholder":309},true,"\n",[97,312,314,316,318,321,323,326,328,330,333,335],{"class":99,"line":313},5,[97,315,19],{"class":103},[97,317,203],{"class":107},[97,319,320],{"class":116},"println!",[97,322,147],{"class":107},[97,324,325],{"class":150},"\"{} {}\"",[97,327,36],{"class":107},[97,329,156],{"class":103},[97,331,332],{"class":107},"p1, ",[97,334,156],{"class":103},[97,336,337],{"class":107},"p2); }\n",[339,340,341,349,355,360],"ul",{},[30,342,343,345,346,348],{},[17,344,35],{}," (read-only) and ",[17,347,39],{}," (writable).",[30,350,351,352,354],{},"Can be created from any reference, even outside ",[17,353,19],{},".",[30,356,357,358,354],{},"Dereferencing requires ",[17,359,19],{},[30,361,362,363,56,365,367],{},"Not ",[17,364,55],{},[17,366,59],{}," by default.",[369,370,372],"h3",{"id":371},"validity-invariants","Validity Invariants",[14,374,375,376,378,379,382,383,354],{},"Reading a ",[17,377,35],{}," requires the pointer to point to a valid ",[17,380,381],{},"T"," (properly initialized, properly aligned). Dereferencing an uninitialized or misaligned pointer is ",[22,384,385],{},"undefined behavior (UB)",[78,387,389],{"id":388},"ffi","FFI",[85,391,392],{"language":87},[89,393,395],{"className":91,"code":394,"language":87,"meta":93,"style":93},"extern \"C\" {\n    fn abs(x: i32) -> i32;\n}\n\nfn main() {\n    unsafe { println!(\"{}\", abs(-5)); }\n}\n",[17,396,397,407,432,436,440,451,480],{"__ignoreMap":93},[97,398,399,402,405],{"class":99,"line":100},[97,400,401],{"class":103},"extern",[97,403,404],{"class":150}," \"C\"",[97,406,138],{"class":107},[97,408,409,412,415,418,420,422,425,428,430],{"class":99,"line":133},[97,410,411],{"class":103},"    fn",[97,413,414],{"class":116}," abs",[97,416,417],{"class":107},"(x",[97,419,25],{"class":103},[97,421,117],{"class":116},[97,423,424],{"class":107},") ",[97,426,427],{"class":103},"->",[97,429,117],{"class":116},[97,431,130],{"class":107},[97,433,434],{"class":99,"line":141},[97,435,165],{"class":107},[97,437,438],{"class":99,"line":162},[97,439,310],{"emptyLinePlaceholder":309},[97,441,442,445,448],{"class":99,"line":313},[97,443,444],{"class":103},"fn",[97,446,447],{"class":116}," main",[97,449,450],{"class":107},"() {\n",[97,452,454,457,459,461,463,465,467,470,472,475,477],{"class":99,"line":453},6,[97,455,456],{"class":103},"    unsafe",[97,458,203],{"class":107},[97,460,320],{"class":116},[97,462,147],{"class":107},[97,464,151],{"class":150},[97,466,36],{"class":107},[97,468,469],{"class":116},"abs",[97,471,147],{"class":107},[97,473,474],{"class":103},"-",[97,476,127],{"class":126},[97,478,479],{"class":107},")); }\n",[97,481,483],{"class":99,"line":482},7,[97,484,165],{"class":107},[14,486,487,488,490,491,25],{},"Calling C functions requires ",[17,489,19],{},". Functions can be marked ",[17,492,493],{},"extern \"C\"",[85,495,496],{"language":87},[89,497,499],{"className":91,"code":498,"language":87,"meta":93,"style":93},"#[no_mangle]\npub extern \"C\" fn add(a: i32, b: i32) -> i32 { a + b }\n",[17,500,501,506],{"__ignoreMap":93},[97,502,503],{"class":99,"line":100},[97,504,505],{"class":107},"#[no_mangle]\n",[97,507,508,511,514,516,518,521,524,526,528,531,533,535,537,539,541,544,547],{"class":99,"line":133},[97,509,510],{"class":103},"pub",[97,512,513],{"class":103}," extern",[97,515,404],{"class":150},[97,517,190],{"class":103},[97,519,520],{"class":116}," add",[97,522,523],{"class":107},"(a",[97,525,25],{"class":103},[97,527,117],{"class":116},[97,529,530],{"class":107},", b",[97,532,25],{"class":103},[97,534,117],{"class":116},[97,536,424],{"class":107},[97,538,427],{"class":103},[97,540,117],{"class":116},[97,542,543],{"class":107}," { a ",[97,545,546],{"class":103},"+",[97,548,549],{"class":107}," b }\n",[14,551,552,555,556,558],{},[17,553,554],{},"#[no_mangle]"," preserves the symbol name for C to call. ",[17,557,493],{}," sets the ABI.",[78,560,562,564],{"id":561},"unsafe-traits",[17,563,19],{}," Traits",[85,566,567],{"language":87},[89,568,570],{"className":91,"code":569,"language":87,"meta":93,"style":93},"unsafe trait TrustedIter {}\nunsafe impl TrustedIter for std::slice::Iter\u003C'static, u8> {}\n",[17,571,572,585],{"__ignoreMap":93},[97,573,574,576,579,582],{"class":99,"line":100},[97,575,19],{"class":103},[97,577,578],{"class":103}," trait",[97,580,581],{"class":116}," TrustedIter",[97,583,584],{"class":107}," {}\n",[97,586,587,589,592,594,597,600,603,606,608,611,614,617,619,622],{"class":99,"line":133},[97,588,19],{"class":103},[97,590,591],{"class":103}," impl",[97,593,581],{"class":116},[97,595,596],{"class":103}," for",[97,598,599],{"class":116}," std",[97,601,602],{"class":103},"::",[97,604,605],{"class":116},"slice",[97,607,602],{"class":103},[97,609,610],{"class":116},"Iter",[97,612,613],{"class":107},"\u003C'",[97,615,616],{"class":116},"static",[97,618,36],{"class":107},[97,620,621],{"class":116},"u8",[97,623,624],{"class":107},"> {}\n",[14,626,627,629,630,632,633,636],{},[17,628,55],{}," and ",[17,631,59],{}," are unsafe traits; the compiler auto-derives them, but you can opt in via ",[17,634,635],{},"unsafe impl"," if you've verified thread-safety.",[85,638,639],{"language":87},[89,640,642],{"className":91,"code":641,"language":87,"meta":93,"style":93},"struct MyType(*mut u8);\nunsafe impl Send for MyType {}     \u002F\u002F we promise the pointer is safe to move to another thread\n",[17,643,644,663],{"__ignoreMap":93},[97,645,646,649,652,654,657,660],{"class":99,"line":100},[97,647,648],{"class":103},"struct",[97,650,651],{"class":116}," MyType",[97,653,147],{"class":107},[97,655,656],{"class":103},"*mut",[97,658,659],{"class":116}," u8",[97,661,662],{"class":107},");\n",[97,664,665,667,669,672,674,676,679],{"class":99,"line":133},[97,666,19],{"class":103},[97,668,591],{"class":103},[97,670,671],{"class":116}," Send",[97,673,596],{"class":103},[97,675,651],{"class":116},[97,677,678],{"class":107}," {}     ",[97,680,681],{"class":212},"\u002F\u002F we promise the pointer is safe to move to another thread\n",[78,683,685],{"id":684},"static-mut",[17,686,65],{},[85,688,689],{"language":87},[89,690,692],{"className":91,"code":691,"language":87,"meta":93,"style":93},"static mut COUNTER: u32 = 0;\n\nfn incr() {\n    unsafe { COUNTER += 1; }\n}\n",[17,693,694,716,720,729,747],{"__ignoreMap":93},[97,695,696,698,701,704,706,709,711,714],{"class":99,"line":100},[97,697,616],{"class":103},[97,699,700],{"class":103}," mut",[97,702,703],{"class":126}," COUNTER",[97,705,25],{"class":103},[97,707,708],{"class":116}," u32",[97,710,120],{"class":103},[97,712,713],{"class":126}," 0",[97,715,130],{"class":107},[97,717,718],{"class":99,"line":133},[97,719,310],{"emptyLinePlaceholder":309},[97,721,722,724,727],{"class":99,"line":141},[97,723,444],{"class":103},[97,725,726],{"class":116}," incr",[97,728,450],{"class":107},[97,730,731,733,735,738,741,744],{"class":99,"line":162},[97,732,456],{"class":103},[97,734,203],{"class":107},[97,736,737],{"class":126},"COUNTER",[97,739,740],{"class":103}," +=",[97,742,743],{"class":126}," 1",[97,745,746],{"class":107},"; }\n",[97,748,749],{"class":99,"line":313},[97,750,165],{"class":107},[339,752,753,758],{},[30,754,755,756,354],{},"Reading\u002Fwriting requires ",[17,757,19],{},[30,759,760],{},"No synchronization — use atomics instead.",[78,762,764],{"id":763},"unions","Unions",[85,766,767],{"language":87},[89,768,770],{"className":91,"code":769,"language":87,"meta":93,"style":93},"union Value {\n    int_val: i32,\n    float_val: f32,\n}\n\nlet v = Value { int_val: 5 };\nunsafe { println!(\"{}\", v.float_val); }   \u002F\u002F ⚠️ UB if int_val was the active field\n",[17,771,772,782,794,806,810,814,835],{"__ignoreMap":93},[97,773,774,777,780],{"class":99,"line":100},[97,775,776],{"class":103},"union",[97,778,779],{"class":116}," Value",[97,781,138],{"class":107},[97,783,784,787,789,791],{"class":99,"line":133},[97,785,786],{"class":107},"    int_val",[97,788,25],{"class":103},[97,790,117],{"class":116},[97,792,793],{"class":107},",\n",[97,795,796,799,801,804],{"class":99,"line":141},[97,797,798],{"class":107},"    float_val",[97,800,25],{"class":103},[97,802,803],{"class":116}," f32",[97,805,793],{"class":107},[97,807,808],{"class":99,"line":162},[97,809,165],{"class":107},[97,811,812],{"class":99,"line":313},[97,813,310],{"emptyLinePlaceholder":309},[97,815,816,818,821,823,825,828,830,832],{"class":99,"line":453},[97,817,104],{"class":103},[97,819,820],{"class":107}," v ",[97,822,246],{"class":103},[97,824,779],{"class":116},[97,826,827],{"class":107}," { int_val",[97,829,25],{"class":103},[97,831,249],{"class":126},[97,833,834],{"class":107}," };\n",[97,836,837,839,841,843,845,847,850,852,855],{"class":99,"line":482},[97,838,19],{"class":103},[97,840,203],{"class":107},[97,842,320],{"class":116},[97,844,147],{"class":107},[97,846,151],{"class":150},[97,848,849],{"class":107},", v",[97,851,354],{"class":103},[97,853,854],{"class":107},"float_val); }   ",[97,856,857],{"class":212},"\u002F\u002F ⚠️ UB if int_val was the active field\n",[14,859,860,861,863],{},"Unions overlap memory; reading the inactive field is UB. Reading requires ",[17,862,19],{},". Useful for FFI\u002FC interop; otherwise use enums.",[78,865,867,870],{"id":866},"maybeuninitt-uninitialized-memory",[17,868,869],{},"MaybeUninit\u003CT>"," — Uninitialized Memory",[85,872,873],{"language":87},[89,874,876],{"className":91,"code":875,"language":87,"meta":93,"style":93},"use std::mem::MaybeUninit;\n\nlet mut mu: MaybeUninit\u003CVec\u003Cu8>> = MaybeUninit::uninit();\nunsafe { mu.write(Vec::new()); }\nlet v: Vec\u003Cu8> = unsafe { mu.assume_init() };\n",[17,877,878,897,901,940,964],{"__ignoreMap":93},[97,879,880,883,885,887,890,892,895],{"class":99,"line":100},[97,881,882],{"class":103},"use",[97,884,599],{"class":116},[97,886,602],{"class":103},[97,888,889],{"class":116},"mem",[97,891,602],{"class":103},[97,893,894],{"class":116},"MaybeUninit",[97,896,130],{"class":107},[97,898,899],{"class":99,"line":133},[97,900,310],{"emptyLinePlaceholder":309},[97,902,903,905,907,910,912,915,918,921,923,925,928,930,932,934,937],{"class":99,"line":141},[97,904,104],{"class":103},[97,906,700],{"class":103},[97,908,909],{"class":107}," mu",[97,911,25],{"class":103},[97,913,914],{"class":116}," MaybeUninit",[97,916,917],{"class":107},"\u003C",[97,919,920],{"class":116},"Vec",[97,922,917],{"class":107},[97,924,621],{"class":116},[97,926,927],{"class":107},">> ",[97,929,246],{"class":103},[97,931,914],{"class":116},[97,933,602],{"class":103},[97,935,936],{"class":116},"uninit",[97,938,939],{"class":107},"();\n",[97,941,942,944,947,949,952,954,956,958,961],{"class":99,"line":162},[97,943,19],{"class":103},[97,945,946],{"class":107}," { mu",[97,948,354],{"class":103},[97,950,951],{"class":116},"write",[97,953,147],{"class":107},[97,955,920],{"class":116},[97,957,602],{"class":103},[97,959,960],{"class":116},"new",[97,962,963],{"class":107},"()); }\n",[97,965,966,968,971,973,976,978,980,983,985,988,990,992,995],{"class":99,"line":313},[97,967,104],{"class":103},[97,969,970],{"class":107}," v",[97,972,25],{"class":103},[97,974,975],{"class":116}," Vec",[97,977,917],{"class":107},[97,979,621],{"class":116},[97,981,982],{"class":107},"> ",[97,984,246],{"class":103},[97,986,987],{"class":103}," unsafe",[97,989,946],{"class":107},[97,991,354],{"class":103},[97,993,994],{"class":116},"assume_init",[97,996,997],{"class":107},"() };\n",[14,999,1000,1002,1003,1007,1008,1010,1011,1014],{},[17,1001,869],{}," is the safe way to ",[1004,1005,1006],"em",{},"hold"," uninitialized memory; reading it requires ",[17,1009,19],{},". The standard alternative to uninitialized ",[17,1012,1013],{},"mem::uninitialized"," (deprecated).",[78,1016,1018,1021],{"id":1017},"manuallydropt-suppress-drop",[17,1019,1020],{},"ManuallyDrop\u003CT>"," — Suppress Drop",[85,1023,1024],{"language":87},[89,1025,1027],{"className":91,"code":1026,"language":87,"meta":93,"style":93},"use std::mem::ManuallyDrop;\nlet s = ManuallyDrop::new(String::from(\"hi\"));\n\u002F\u002F s's destructor won't run; manual cleanup needed\nunsafe { drop(ManuallyDrop::into_inner(s)) };   \u002F\u002F no, into_inner extracts\n",[17,1028,1029,1046,1080,1085],{"__ignoreMap":93},[97,1030,1031,1033,1035,1037,1039,1041,1044],{"class":99,"line":100},[97,1032,882],{"class":103},[97,1034,599],{"class":116},[97,1036,602],{"class":103},[97,1038,889],{"class":116},[97,1040,602],{"class":103},[97,1042,1043],{"class":116},"ManuallyDrop",[97,1045,130],{"class":107},[97,1047,1048,1050,1053,1055,1058,1060,1062,1064,1067,1069,1072,1074,1077],{"class":99,"line":133},[97,1049,104],{"class":103},[97,1051,1052],{"class":107}," s ",[97,1054,246],{"class":103},[97,1056,1057],{"class":116}," ManuallyDrop",[97,1059,602],{"class":103},[97,1061,960],{"class":116},[97,1063,147],{"class":107},[97,1065,1066],{"class":116},"String",[97,1068,602],{"class":103},[97,1070,1071],{"class":116},"from",[97,1073,147],{"class":107},[97,1075,1076],{"class":150},"\"hi\"",[97,1078,1079],{"class":107},"));\n",[97,1081,1082],{"class":99,"line":141},[97,1083,1084],{"class":212},"\u002F\u002F s's destructor won't run; manual cleanup needed\n",[97,1086,1087,1089,1091,1094,1096,1098,1100,1103,1106],{"class":99,"line":162},[97,1088,19],{"class":103},[97,1090,203],{"class":107},[97,1092,1093],{"class":116},"drop",[97,1095,147],{"class":107},[97,1097,1043],{"class":116},[97,1099,602],{"class":103},[97,1101,1102],{"class":116},"into_inner",[97,1104,1105],{"class":107},"(s)) };   ",[97,1107,1108],{"class":212},"\u002F\u002F no, into_inner extracts\n",[14,1110,1111,1113,1114,1116,1117,1120,1121,1124,1125,1128],{},[17,1112,1020],{}," wraps a ",[17,1115,381],{}," and disables its ",[17,1118,1119],{},"Drop",". Use ",[17,1122,1123],{},"ManuallyDrop::into_inner"," to recover the value, or ",[17,1126,1127],{},"unsafe { ManuallyDrop::take(&mut md) }"," to extract without dropping.",[78,1130,1132],{"id":1131},"splitting-borrows-safely","Splitting Borrows Safely",[85,1134,1135],{"language":87},[89,1136,1138],{"className":91,"code":1137,"language":87,"meta":93,"style":93},"let mut v = vec![1, 2, 3, 4];\nlet slice: &mut [i32] = &mut v[..];\nlet (left, right) = slice.split_at_mut(2);\n\u002F\u002F left = &mut [1, 2], right = &mut [3, 4]\n",[17,1139,1140,1177,1209,1231],{"__ignoreMap":93},[97,1141,1142,1144,1146,1148,1150,1153,1156,1159,1161,1164,1166,1169,1171,1174],{"class":99,"line":100},[97,1143,104],{"class":103},[97,1145,700],{"class":103},[97,1147,820],{"class":107},[97,1149,246],{"class":103},[97,1151,1152],{"class":116}," vec!",[97,1154,1155],{"class":107},"[",[97,1157,1158],{"class":126},"1",[97,1160,36],{"class":107},[97,1162,1163],{"class":126},"2",[97,1165,36],{"class":107},[97,1167,1168],{"class":126},"3",[97,1170,36],{"class":107},[97,1172,1173],{"class":126},"4",[97,1175,1176],{"class":107},"];\n",[97,1178,1179,1181,1184,1186,1188,1191,1194,1197,1199,1201,1204,1207],{"class":99,"line":133},[97,1180,104],{"class":103},[97,1182,1183],{"class":107}," slice",[97,1185,25],{"class":103},[97,1187,293],{"class":103},[97,1189,1190],{"class":107}," [",[97,1192,1193],{"class":116},"i32",[97,1195,1196],{"class":107},"] ",[97,1198,246],{"class":103},[97,1200,293],{"class":103},[97,1202,1203],{"class":107}," v[",[97,1205,1206],{"class":103},"..",[97,1208,1176],{"class":107},[97,1210,1211,1213,1216,1218,1220,1222,1225,1227,1229],{"class":99,"line":141},[97,1212,104],{"class":103},[97,1214,1215],{"class":107}," (left, right) ",[97,1217,246],{"class":103},[97,1219,1183],{"class":107},[97,1221,354],{"class":103},[97,1223,1224],{"class":116},"split_at_mut",[97,1226,147],{"class":107},[97,1228,1163],{"class":126},[97,1230,662],{"class":107},[97,1232,1233],{"class":99,"line":162},[97,1234,1235],{"class":212},"\u002F\u002F left = &mut [1, 2], right = &mut [3, 4]\n",[14,1237,1238,1240,1241,1243],{},[17,1239,1224],{}," is internally ",[17,1242,19],{}," because the compiler can't prove disjointness, but it's a safe API.",[78,1245,1247],{"id":1246},"unsafe-code-soundness","Unsafe Code Soundness",[14,1249,1250,1251,1253,1254,1257,1258,1260],{},"A piece of ",[17,1252,19],{}," code is ",[22,1255,1256],{},"sound"," if safe code can't trigger UB through its public API. Writing sound ",[17,1259,19],{}," requires:",[339,1262,1263,1266,1272,1275],{},[30,1264,1265],{},"Reasoning about aliasing, alignment, lifetimes, initialization, thread-safety.",[30,1267,1268,1269,40],{},"Documenting invariants (",[17,1270,1271],{},"\u002F\u002F SAFETY: ...",[30,1273,1274],{},"Considering all possible inputs.",[30,1276,1277,1278,1280],{},"Not leaking ",[17,1279,19],{}," to safe callers.",[14,1282,1283,1284,1287],{},"Miri (",[17,1285,1286],{},"cargo +nightly miri test",") is a tool that detects UB in unsafe code at runtime — use it.",[78,1289,1291],{"id":1290},"miri",[17,1292,1290],{},[85,1294,1296],{"language":1295},"bash",[89,1297,1300],{"className":1298,"code":1299,"language":1295,"meta":93,"style":93},"language-bash shiki shiki-themes github-light github-dark","rustup +nightly component add miri\ncargo +nightly miri test\n",[17,1301,1302,1318],{"__ignoreMap":93},[97,1303,1304,1307,1310,1313,1315],{"class":99,"line":100},[97,1305,1306],{"class":116},"rustup",[97,1308,1309],{"class":150}," +nightly",[97,1311,1312],{"class":150}," component",[97,1314,520],{"class":150},[97,1316,1317],{"class":150}," miri\n",[97,1319,1320,1323,1325,1328],{"class":99,"line":133},[97,1321,1322],{"class":116},"cargo",[97,1324,1309],{"class":150},[97,1326,1327],{"class":150}," miri",[97,1329,1330],{"class":150}," test\n",[14,1332,1333],{},"Miri interprets your code and catches many UB forms (invalid pointer arithmetic, unaligned access, data races in some cases, use of uninitialized memory). Doesn't catch all bugs but catches many.",[78,1335,1337],{"id":1336},"common-sources-of-ub","Common Sources of UB",[339,1339,1340,1343,1346,1349,1352,1357,1360,1366,1372,1382],{},[30,1341,1342],{},"Dereferencing a NULL, dangling, or misaligned pointer.",[30,1344,1345],{},"Reading uninitialized memory as a typed value.",[30,1347,1348],{},"Reading a union's inactive field.",[30,1350,1351],{},"Data races (concurrent reads + writes to the same memory without synchronization).",[30,1353,1354,1355,40],{},"Mutating immutable data (via ",[17,1356,19],{},[30,1358,1359],{},"Calling a function with the wrong ABI.",[30,1361,1362,1363,1365],{},"Violating the ",[17,1364,1119],{}," ordering or skipping destructors of owned data.",[30,1367,1368,1369,1371],{},"Integer overflow in ",[17,1370,19],{}," (e.g., pointer arithmetic that wraps).",[30,1373,1374,1375,1378,1379,40],{},"Unwinding across FFI boundaries (set ",[17,1376,1377],{},"panic = \"abort\""," or use ",[17,1380,1381],{},"catch_unwind",[30,1383,1384,1385,1388,1389,40],{},"Constructing invalid enum values (e.g., transmuting a number to ",[17,1386,1387],{},"Option\u003CNonNull\u003CT>>"," that creates ",[17,1390,1391],{},"Some(null)",[78,1393,1395,1397],{"id":1394},"unsafe-patterns",[17,1396,19],{}," Patterns",[369,1399,1401],{"id":1400},"safe-abstractions-over-unsafe","Safe Abstractions over Unsafe",[14,1403,1404],{},"The idiomatic way: expose a safe API, do the unsafe internally:",[85,1406,1407],{"language":87},[89,1408,1410],{"className":91,"code":1409,"language":87,"meta":93,"style":93},"pub fn first_byte(s: &str) -> u8 {\n    let ptr = s.as_ptr();\n    unsafe { *ptr }   \u002F\u002F SAFETY: ptr is valid (s is a valid &str)\n}\n",[17,1411,1412,1439,1459,1473],{"__ignoreMap":93},[97,1413,1414,1416,1418,1421,1424,1426,1428,1431,1433,1435,1437],{"class":99,"line":100},[97,1415,510],{"class":103},[97,1417,190],{"class":103},[97,1419,1420],{"class":116}," first_byte",[97,1422,1423],{"class":107},"(s",[97,1425,25],{"class":103},[97,1427,123],{"class":103},[97,1429,1430],{"class":116},"str",[97,1432,424],{"class":107},[97,1434,427],{"class":103},[97,1436,659],{"class":116},[97,1438,138],{"class":107},[97,1440,1441,1444,1447,1449,1452,1454,1457],{"class":99,"line":133},[97,1442,1443],{"class":103},"    let",[97,1445,1446],{"class":107}," ptr ",[97,1448,246],{"class":103},[97,1450,1451],{"class":107}," s",[97,1453,354],{"class":103},[97,1455,1456],{"class":116},"as_ptr",[97,1458,939],{"class":107},[97,1460,1461,1463,1465,1467,1470],{"class":99,"line":141},[97,1462,456],{"class":103},[97,1464,203],{"class":107},[97,1466,156],{"class":103},[97,1468,1469],{"class":107},"ptr }   ",[97,1471,1472],{"class":212},"\u002F\u002F SAFETY: ptr is valid (s is a valid &str)\n",[97,1474,1475],{"class":99,"line":162},[97,1476,165],{"class":107},[14,1478,1479,1480,1483],{},"Comment with ",[17,1481,1482],{},"\u002F\u002F SAFETY:"," explaining why each unsafe operation is sound.",[369,1485,1487,56,1490],{"id":1486},"unsafe-impl-sendsync",[17,1488,1489],{},"unsafe impl Send",[17,1491,59],{},[14,1493,1494,1495,56,1497,1499],{},"Only when you've verified the type can be safely transferred\u002Fshared across threads. Usually because the inner is ",[17,1496,55],{},[17,1498,59],{}," via raw pointer you control.",[369,1501,1503],{"id":1502},"reusing-raw-memory","Reusing Raw Memory",[85,1505,1506],{"language":87},[89,1507,1509],{"className":91,"code":1508,"language":87,"meta":93,"style":93},"let mut buf: Vec\u003Cu8> = Vec::with_capacity(100);\nlet ptr = buf.as_mut_ptr() as *mut u64;\nunsafe { *ptr = 5; }   \u002F\u002F ⚠️ requires valid alignment and within capacity\n",[17,1510,1511,1546,1573],{"__ignoreMap":93},[97,1512,1513,1515,1517,1520,1522,1524,1526,1528,1530,1532,1534,1536,1539,1541,1544],{"class":99,"line":100},[97,1514,104],{"class":103},[97,1516,700],{"class":103},[97,1518,1519],{"class":107}," buf",[97,1521,25],{"class":103},[97,1523,975],{"class":116},[97,1525,917],{"class":107},[97,1527,621],{"class":116},[97,1529,982],{"class":107},[97,1531,246],{"class":103},[97,1533,975],{"class":116},[97,1535,602],{"class":103},[97,1537,1538],{"class":116},"with_capacity",[97,1540,147],{"class":107},[97,1542,1543],{"class":126},"100",[97,1545,662],{"class":107},[97,1547,1548,1550,1552,1554,1556,1558,1561,1564,1566,1568,1571],{"class":99,"line":133},[97,1549,104],{"class":103},[97,1551,1446],{"class":107},[97,1553,246],{"class":103},[97,1555,1519],{"class":107},[97,1557,354],{"class":103},[97,1559,1560],{"class":116},"as_mut_ptr",[97,1562,1563],{"class":107},"() ",[97,1565,298],{"class":103},[97,1567,286],{"class":103},[97,1569,1570],{"class":116}," u64",[97,1572,130],{"class":107},[97,1574,1575,1577,1579,1581,1584,1586,1588,1591],{"class":99,"line":141},[97,1576,19],{"class":103},[97,1578,203],{"class":107},[97,1580,156],{"class":103},[97,1582,1583],{"class":107},"ptr ",[97,1585,246],{"class":103},[97,1587,249],{"class":126},[97,1589,1590],{"class":107},"; }   ",[97,1592,1593],{"class":212},"\u002F\u002F ⚠️ requires valid alignment and within capacity\n",[14,1595,1596,1599,1600,36,1602,1605,1606,1609,1610,1613,1614,354],{},[17,1597,1598],{},"Vec\u003Cu8>"," allocations are aligned to ",[17,1601,621],{},[22,1603,1604],{},"not"," ",[17,1607,1608],{},"u64",". To get a properly-aligned buffer, use ",[17,1611,1612],{},"Vec\u003Cu64>"," directly or ",[17,1615,1616],{},"alloc::alloc_aligned",[78,1618,1620],{"id":1619},"ffi-patterns","FFI Patterns",[369,1622,1624],{"id":1623},"owning-foreign-memory","Owning Foreign Memory",[85,1626,1627],{"language":87},[89,1628,1630],{"className":91,"code":1629,"language":87,"meta":93,"style":93},"struct Buffer(*mut u8, usize);\nimpl Drop for Buffer {\n    fn drop(&mut self) {\n        unsafe { free(self.0) }\n    }\n}\nunsafe impl Send for Buffer {}\n",[17,1631,1632,1652,1666,1684,1707,1712,1716],{"__ignoreMap":93},[97,1633,1634,1636,1639,1641,1643,1645,1647,1650],{"class":99,"line":100},[97,1635,648],{"class":103},[97,1637,1638],{"class":116}," Buffer",[97,1640,147],{"class":107},[97,1642,656],{"class":103},[97,1644,659],{"class":116},[97,1646,36],{"class":107},[97,1648,1649],{"class":116},"usize",[97,1651,662],{"class":107},[97,1653,1654,1657,1660,1662,1664],{"class":99,"line":133},[97,1655,1656],{"class":103},"impl",[97,1658,1659],{"class":116}," Drop",[97,1661,596],{"class":103},[97,1663,1638],{"class":116},[97,1665,138],{"class":107},[97,1667,1668,1670,1673,1675,1678,1681],{"class":99,"line":141},[97,1669,411],{"class":103},[97,1671,1672],{"class":116}," drop",[97,1674,147],{"class":107},[97,1676,1677],{"class":103},"&mut",[97,1679,1680],{"class":126}," self",[97,1682,1683],{"class":107},") {\n",[97,1685,1686,1689,1691,1694,1696,1699,1701,1704],{"class":99,"line":162},[97,1687,1688],{"class":103},"        unsafe",[97,1690,203],{"class":107},[97,1692,1693],{"class":116},"free",[97,1695,147],{"class":107},[97,1697,1698],{"class":126},"self",[97,1700,354],{"class":103},[97,1702,1703],{"class":126},"0",[97,1705,1706],{"class":107},") }\n",[97,1708,1709],{"class":99,"line":313},[97,1710,1711],{"class":107},"    }\n",[97,1713,1714],{"class":99,"line":453},[97,1715,165],{"class":107},[97,1717,1718,1720,1722,1724,1726,1728],{"class":99,"line":482},[97,1719,19],{"class":103},[97,1721,591],{"class":103},[97,1723,671],{"class":116},[97,1725,596],{"class":103},[97,1727,1638],{"class":116},[97,1729,584],{"class":107},[14,1731,1732,1733,1735],{},"RAII: the constructor allocates, ",[17,1734,1119],{}," deallocates.",[369,1737,1739,1741],{"id":1738},"extern-c-block-with-variadics",[17,1740,493],{}," Block with Variadics",[85,1743,1744],{"language":87},[89,1745,1747],{"className":91,"code":1746,"language":87,"meta":93,"style":93},"extern \"C\" {\n    fn printf(fmt: *const u8, ...) -> i32;\n}\n",[17,1748,1749,1757,1786],{"__ignoreMap":93},[97,1750,1751,1753,1755],{"class":99,"line":100},[97,1752,401],{"class":103},[97,1754,404],{"class":150},[97,1756,138],{"class":107},[97,1758,1759,1761,1764,1767,1769,1771,1773,1775,1778,1780,1782,1784],{"class":99,"line":133},[97,1760,411],{"class":103},[97,1762,1763],{"class":116}," printf",[97,1765,1766],{"class":107},"(fmt",[97,1768,25],{"class":103},[97,1770,113],{"class":103},[97,1772,659],{"class":116},[97,1774,36],{"class":107},[97,1776,1777],{"class":103},"...",[97,1779,424],{"class":107},[97,1781,427],{"class":103},[97,1783,117],{"class":116},[97,1785,130],{"class":107},[97,1787,1788],{"class":99,"line":141},[97,1789,165],{"class":107},[369,1791,1793,1796],{"id":1792},"link-attributes",[17,1794,1795],{},"link"," Attributes",[85,1798,1799],{"language":87},[89,1800,1802],{"className":91,"code":1801,"language":87,"meta":93,"style":93},"#[link(name = \"crypto\")]\nextern \"C\" {\n    fn sha256(input: *const u8, len: usize) -> *mut u8;\n}\n",[17,1803,1804,1817,1825,1859],{"__ignoreMap":93},[97,1805,1806,1809,1811,1814],{"class":99,"line":100},[97,1807,1808],{"class":107},"#[link(name ",[97,1810,246],{"class":103},[97,1812,1813],{"class":150}," \"crypto\"",[97,1815,1816],{"class":107},")]\n",[97,1818,1819,1821,1823],{"class":99,"line":133},[97,1820,401],{"class":103},[97,1822,404],{"class":150},[97,1824,138],{"class":107},[97,1826,1827,1829,1832,1835,1837,1839,1841,1844,1846,1849,1851,1853,1855,1857],{"class":99,"line":141},[97,1828,411],{"class":103},[97,1830,1831],{"class":116}," sha256",[97,1833,1834],{"class":107},"(input",[97,1836,25],{"class":103},[97,1838,113],{"class":103},[97,1840,659],{"class":116},[97,1842,1843],{"class":107},", len",[97,1845,25],{"class":103},[97,1847,1848],{"class":116}," usize",[97,1850,424],{"class":107},[97,1852,427],{"class":103},[97,1854,286],{"class":103},[97,1856,659],{"class":116},[97,1858,130],{"class":107},[97,1860,1861],{"class":99,"line":162},[97,1862,165],{"class":107},[78,1864,1866,36,1868,36,1871],{"id":1865},"no_mangle-export_name-link_name",[17,1867,554],{},[17,1869,1870],{},"#[export_name]",[17,1872,1873],{},"#[link_name]",[339,1875,1876,1881,1887],{},[30,1877,1878,1880],{},[17,1879,554],{},": keep the function's name as-is in the symbol table.",[30,1882,1883,1886],{},[17,1884,1885],{},"#[export_name = \"foo\"]",": rename the exported symbol.",[30,1888,1889,1892],{},[17,1890,1891],{},"#[link_name = \"...\"]",": rename the symbol you're linking against.",[78,1894,1896],{"id":1895},"bindgen","Bindgen",[14,1898,1899,1900,1902],{},"Use ",[17,1901,1895],{}," to auto-generate Rust FFI bindings from C headers:",[85,1904,1906],{"language":1905},"toml",[89,1907,1910],{"className":1908,"code":1909,"language":1905,"meta":93,"style":93},"language-toml shiki shiki-themes github-light github-dark","[build-dependencies]\nbindgen = \"0.69\"\n",[17,1911,1912,1917],{"__ignoreMap":93},[97,1913,1914],{"class":99,"line":100},[97,1915,1916],{},"[build-dependencies]\n",[97,1918,1919],{"class":99,"line":133},[97,1920,1921],{},"bindgen = \"0.69\"\n",[85,1923,1924],{"language":87},[89,1925,1927],{"className":91,"code":1926,"language":87,"meta":93,"style":93},"\u002F\u002F build.rs\nfn main() {\n    let bindings = bindgen::Builder::default()\n        .header(\"wrapper.h\")\n        .generate().unwrap();\n    bindings.write_to_file(\"src\u002Fbindings.rs\").unwrap();\n}\n",[17,1928,1929,1934,1942,1967,1983,2000,2024],{"__ignoreMap":93},[97,1930,1931],{"class":99,"line":100},[97,1932,1933],{"class":212},"\u002F\u002F build.rs\n",[97,1935,1936,1938,1940],{"class":99,"line":133},[97,1937,444],{"class":103},[97,1939,447],{"class":116},[97,1941,450],{"class":107},[97,1943,1944,1946,1949,1951,1954,1956,1959,1961,1964],{"class":99,"line":141},[97,1945,1443],{"class":103},[97,1947,1948],{"class":107}," bindings ",[97,1950,246],{"class":103},[97,1952,1953],{"class":116}," bindgen",[97,1955,602],{"class":103},[97,1957,1958],{"class":116},"Builder",[97,1960,602],{"class":103},[97,1962,1963],{"class":116},"default",[97,1965,1966],{"class":107},"()\n",[97,1968,1969,1972,1975,1977,1980],{"class":99,"line":162},[97,1970,1971],{"class":103},"        .",[97,1973,1974],{"class":116},"header",[97,1976,147],{"class":107},[97,1978,1979],{"class":150},"\"wrapper.h\"",[97,1981,1982],{"class":107},")\n",[97,1984,1985,1987,1990,1993,1995,1998],{"class":99,"line":313},[97,1986,1971],{"class":103},[97,1988,1989],{"class":116},"generate",[97,1991,1992],{"class":107},"()",[97,1994,354],{"class":103},[97,1996,1997],{"class":116},"unwrap",[97,1999,939],{"class":107},[97,2001,2002,2005,2007,2010,2012,2015,2018,2020,2022],{"class":99,"line":453},[97,2003,2004],{"class":107},"    bindings",[97,2006,354],{"class":103},[97,2008,2009],{"class":116},"write_to_file",[97,2011,147],{"class":107},[97,2013,2014],{"class":150},"\"src\u002Fbindings.rs\"",[97,2016,2017],{"class":107},")",[97,2019,354],{"class":103},[97,2021,1997],{"class":116},[97,2023,939],{"class":107},[97,2025,2026],{"class":99,"line":482},[97,2027,165],{"class":107},[78,2029,2031,2033,2034],{"id":2030},"extern-c-vs-extern-rust",[17,2032,493],{}," vs ",[17,2035,2036],{},"extern \"Rust\"",[14,2038,2039,2040,2042,2043,2045,2046,36,2049,2052,2053,2055,2056,2059,2060,36,2063,36,2066,36,2069,354],{},"The default ABI is ",[17,2041,2036],{}," (not stable to name explicitly until 1.86+). C ABI is ",[17,2044,493],{},". Other ABIs: ",[17,2047,2048],{},"stdcall",[17,2050,2051],{},"system"," (Windows: ",[17,2054,2048],{}," on x86, ",[17,2057,2058],{},"C"," on x64), ",[17,2061,2062],{},"aapcs",[17,2064,2065],{},"fastcall",[17,2067,2068],{},"win64",[17,2070,2071],{},"sysv64",[78,2073,2075],{"id":2074},"edge-cases","Edge Cases",[339,2077,2078,2092,2103,2111,2119,2132,2144,2166],{},[30,2079,2080,2085,2086,2089,2090,354],{},[22,2081,2082,2084],{},[17,2083,19],{}," doesn't disable the borrow checker",": you still can't have aliasing ",[17,2087,2088],{},"&mut T"," even with ",[17,2091,19],{},[30,2093,2094,2099,2100,2102],{},[22,2095,2096,2098],{},[17,2097,170],{}," body has implicit unsafe in pre-2024 editions",": 2024 changes this — explicit ",[17,2101,19],{}," blocks required inside.",[30,2104,2105,2110],{},[22,2106,2107],{},[17,2108,2109],{},"std::mem::transmute",": reinterprets bytes as another type. Extremely dangerous (size\u002Fvalidity\u002Falignment). Avoid; use specific methods.",[30,2112,2113,2118],{},[22,2114,2115],{},[17,2116,2117],{},"std::mem::transmute_copy",": reads bytes from one place as another type — also very dangerous.",[30,2120,2121,2128,2129,354],{},[22,2122,2123,629,2125],{},[17,2124,19],{},[17,2126,2127],{},"async",": async unsafe functions are unstable; you can wrap blocking unsafe calls in ",[17,2130,2131],{},"spawn_blocking",[30,2133,2134,2139,2140,2143],{},[22,2135,2136,2138],{},[17,2137,65],{}," races",": undetectable by ",[17,2141,2142],{},"cargo test"," in many cases; use atomics.",[30,2145,2146,2156,2157,2159,2160,2162,2163,354],{},[22,2147,2148,56,2151,629,2154],{},[17,2149,2150],{},"Cell",[17,2152,2153],{},"RefCell",[17,2155,55],{},": not ",[17,2158,59],{},", but they are ",[17,2161,55],{}," if ",[17,2164,2165],{},"T: Send",[30,2167,2168,2173,2174,2177,2178,2180,2181,2184],{},[22,2169,2170,2171],{},"Pin and ",[17,2172,19],{},": implementing your own ",[17,2175,2176],{},"Future"," requires ",[17,2179,19],{}," because of ",[17,2182,2183],{},"Pin"," invariants.",[78,2186,2188,2190],{"id":2187},"unsafe-anti-patterns",[17,2189,19],{}," Anti-Patterns",[339,2192,2193,2208,2217,2232,2247],{},[30,2194,2195,2200,2201,2204,2205,2207],{},[22,2196,2197],{},[17,2198,2199],{},"unsafe impl Send for Rc\u003CT>",": ",[17,2202,2203],{},"Rc"," has a non-atomic refcount; making it ",[17,2206,55],{}," causes data races.",[30,2209,2210,2216],{},[22,2211,2212,2213,2215],{},"Bare ",[17,2214,39],{}," in public API",": exposes raw pointer semantics; wrap in a safe abstraction.",[30,2218,2219,2225,2226,56,2229,354],{},[22,2220,2221,2224],{},[17,2222,2223],{},"transmute"," for type conversions",": use ",[17,2227,2228],{},"From",[17,2230,2231],{},"TryFrom",[30,2233,2234,2242,2243,2246],{},[22,2235,2236,2238,2239],{},[17,2237,170],{}," returning ",[17,2240,2241],{},"&'static T"," without ",[17,2244,2245],{},"'static"," input: usually lies.",[30,2248,2249,2200,2252,2255,2256,2259],{},[22,2250,2251],{},"Assuming pointer alignment",[17,2253,2254],{},"&[u8]"," is aligned to 1; casting to ",[17,2257,2258],{},"&u64"," is UB unless you check.",[78,2261,2263],{"id":2262},"when-to-use-unsafe","When to Use Unsafe",[339,2265,2266,2269,2281,2284,2287],{},[30,2267,2268],{},"FFI to C.",[30,2270,2271,2272,36,2274,36,2277,2280],{},"Implementing low-level collections (",[17,2273,920],{},[17,2275,2276],{},"HashMap",[17,2278,2279],{},"VecDeque"," internals).",[30,2282,2283],{},"Performance-critical code that can't be expressed safely (rare; usually the compiler is fine).",[30,2285,2286],{},"Interfacing with the OS (syscalls).",[30,2288,2289,2290,56,2292,2294],{},"Implementing ",[17,2291,55],{},[17,2293,59],{}," for a wrapper you control.",[14,2296,2297,2298,1120,2301,2303],{},"Most Rust code is ",[22,2299,2300],{},"fully safe",[17,2302,19],{}," sparingly; confine it to small, well-reviewed modules.",[78,2305,2307],{"id":2306},"summary","Summary",[14,2309,2310,2312,2313,2316,2317,2319,2320,2323,2324,56,2326,2328,2329,2331],{},[17,2311,19],{}," gives you five superpowers; the rest of Rust still applies. Aim for ",[22,2314,2315],{},"safe abstractions",": do the unsafe internally, expose a safe API, document ",[17,2318,1482],{}," invariants. Use ",[17,2321,2322],{},"Miri"," to catch UB. ",[17,2325,894],{},[17,2327,1043],{}," are safer than the legacy uninitialized-memory APIs. Confine ",[17,2330,19],{}," to small audited surfaces.",[14,2333,2334],{},"Next: FFI deep dive.",[2336,2337,2338],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}",{"title":93,"searchDepth":133,"depth":133,"links":2340},[2341,2343,2346,2347,2349,2350,2351,2353,2355,2356,2357,2358,2359,2366,2373,2375,2376,2378,2379,2381,2382],{"id":80,"depth":133,"text":2342},"unsafe Blocks",{"id":228,"depth":133,"text":229,"children":2344},[2345],{"id":371,"depth":141,"text":372},{"id":388,"depth":133,"text":389},{"id":561,"depth":133,"text":2348},"unsafe Traits",{"id":684,"depth":133,"text":65},{"id":763,"depth":133,"text":764},{"id":866,"depth":133,"text":2352},"MaybeUninit\u003CT> — Uninitialized Memory",{"id":1017,"depth":133,"text":2354},"ManuallyDrop\u003CT> — Suppress Drop",{"id":1131,"depth":133,"text":1132},{"id":1246,"depth":133,"text":1247},{"id":1290,"depth":133,"text":1290},{"id":1336,"depth":133,"text":1337},{"id":1394,"depth":133,"text":2360,"children":2361},"unsafe Patterns",[2362,2363,2365],{"id":1400,"depth":141,"text":1401},{"id":1486,"depth":141,"text":2364},"unsafe impl Send\u002FSync",{"id":1502,"depth":141,"text":1503},{"id":1619,"depth":133,"text":1620,"children":2367},[2368,2369,2371],{"id":1623,"depth":141,"text":1624},{"id":1738,"depth":141,"text":2370},"extern \"C\" Block with Variadics",{"id":1792,"depth":141,"text":2372},"link Attributes",{"id":1865,"depth":133,"text":2374},"#[no_mangle], #[export_name], #[link_name]",{"id":1895,"depth":133,"text":1896},{"id":2030,"depth":133,"text":2377},"extern \"C\" vs extern \"Rust\"",{"id":2074,"depth":133,"text":2075},{"id":2187,"depth":133,"text":2380},"unsafe Anti-Patterns",{"id":2262,"depth":133,"text":2263},{"id":2306,"depth":133,"text":2307},"unsafe lets you do things the compiler can't verify. It doesn't turn off the borrow checker — it adds five superpowers:","md",{},"\u002Frust\u002F25-unsafe-rust",{"title":5,"description":2383},"rust\u002F25-unsafe-rust","5RRKu1mRylaBWmaIyQNXqcP1VamhuUeGFv_l7v9jFAM",1785944093269]