[{"data":1,"prerenderedAt":2155},["ShallowReactive",2],{"page-\u002Frust\u002F24-macros":3},{"id":4,"title":5,"body":6,"description":16,"extension":2149,"meta":2150,"navigation":225,"path":2151,"seo":2152,"stem":2153,"__hash__":2154},"content\u002Frust\u002F24-macros.md","24 — Macros",{"type":7,"value":8,"toc":2117},"minimark",[9,13,17,39,44,74,81,87,259,264,338,346,525,529,650,661,665,686,690,693,828,833,879,885,889,910,914,933,939,948,953,1104,1113,1117,1233,1237,1244,1276,1280,1288,1296,1308,1435,1438,1471,1475,1634,1636,1673,1677,1758,1762,1809,1812,1816,1850,1854,1922,1925,1929,2025,2030,2057,2060,2064,2067,2081,2084,2088,2110,2113],[10,11,5],"h1",{"id":12},"_24-macros",[14,15,16],"p",{},"Macros generate code at compile time. Rust has two kinds:",[18,19,20,33],"ol",{},[21,22,23,27,28,32],"li",{},[24,25,26],"strong",{},"Declarative macros"," (",[29,30,31],"code",{},"macro_rules!","): pattern-matching code generators.",[21,34,35,38],{},[24,36,37],{},"Procedural macros",": real Rust functions that consume\u002Fproduce token streams (custom derive, attribute, function-like).",[40,41,43],"h2",{"id":42},"why-macros","Why Macros?",[45,46,47,58,61,64],"ul",{},[21,48,49,50,53,54,57],{},"Variadic arguments (",[29,51,52],{},"println!",", ",[29,55,56],{},"vec!",").",[21,59,60],{},"Compile-time string interpolation (format strings are checked).",[21,62,63],{},"Reducing boilerplate (derive macros).",[21,65,66,67,70,71,57],{},"DSLs (",[29,68,69],{},"html!"," in ",[29,72,73],{},"yew",[14,75,76,77,80],{},"Macros run ",[24,78,79],{},"before"," the type checker — they expand into AST, which is then type-checked.",[40,82,84,85],{"id":83},"declarative-macros-macro_rules","Declarative Macros: ",[29,86,31],{},[88,89,91],"code-wrapper",{"language":90},"rust",[92,93,97],"pre",{"className":94,"code":95,"language":90,"meta":96,"style":96},"language-rust shiki shiki-themes github-light github-dark","macro_rules! vec_of {\n    ($($x:expr),*) => {{\n        let mut v = Vec::new();\n        $( v.push($x); )*\n        v\n    }};\n}\n\nlet v = vec_of!(1, 2, 3);\n","",[29,98,99,114,150,177,202,208,214,220,227],{"__ignoreMap":96},[100,101,104,107,110],"span",{"class":102,"line":103},"line",1,[100,105,31],{"class":106},"sIsaT",[100,108,109],{"class":106}," vec_of",[100,111,113],{"class":112},"ssxIu"," {\n",[100,115,117,120,124,127,129,132,135,138,141,144,147],{"class":102,"line":116},2,[100,118,119],{"class":112},"    (",[100,121,123],{"class":122},"svdQ7","$",[100,125,126],{"class":112},"(",[100,128,123],{"class":122},[100,130,131],{"class":112},"x",[100,133,134],{"class":122},":",[100,136,137],{"class":112},"expr),",[100,139,140],{"class":122},"*",[100,142,143],{"class":112},") ",[100,145,146],{"class":122},"=>",[100,148,149],{"class":112}," {{\n",[100,151,153,156,159,162,165,168,171,174],{"class":102,"line":152},3,[100,154,155],{"class":122},"        let",[100,157,158],{"class":122}," mut",[100,160,161],{"class":112}," v ",[100,163,164],{"class":122},"=",[100,166,167],{"class":106}," Vec",[100,169,170],{"class":122},"::",[100,172,173],{"class":106},"new",[100,175,176],{"class":112},"();\n",[100,178,180,183,186,189,192,194,196,199],{"class":102,"line":179},4,[100,181,182],{"class":122},"        $",[100,184,185],{"class":112},"( v",[100,187,188],{"class":122},".",[100,190,191],{"class":106},"push",[100,193,126],{"class":112},[100,195,123],{"class":122},[100,197,198],{"class":112},"x); )",[100,200,201],{"class":122},"*\n",[100,203,205],{"class":102,"line":204},5,[100,206,207],{"class":112},"        v\n",[100,209,211],{"class":102,"line":210},6,[100,212,213],{"class":112},"    }};\n",[100,215,217],{"class":102,"line":216},7,[100,218,219],{"class":112},"}\n",[100,221,223],{"class":102,"line":222},8,[100,224,226],{"emptyLinePlaceholder":225},true,"\n",[100,228,230,233,235,237,240,242,246,248,251,253,256],{"class":102,"line":229},9,[100,231,232],{"class":122},"let",[100,234,161],{"class":112},[100,236,164],{"class":122},[100,238,239],{"class":106}," vec_of!",[100,241,126],{"class":112},[100,243,245],{"class":244},"snvgF","1",[100,247,53],{"class":112},[100,249,250],{"class":244},"2",[100,252,53],{"class":112},[100,254,255],{"class":244},"3",[100,257,258],{"class":112},");\n",[260,261,263],"h3",{"id":262},"macro-syntax","Macro Syntax",[45,265,266,272,317,331],{},[21,267,268,271],{},[29,269,270],{},"$name",": a \"metavariable\".",[21,273,274,53,277,53,280,53,283,53,286,53,289,53,292,53,295,53,298,53,301,53,304,53,307,53,310,53,313,316],{},[29,275,276],{},":expr",[29,278,279],{},":ident",[29,281,282],{},":ty",[29,284,285],{},":tt",[29,287,288],{},":item",[29,290,291],{},":pat",[29,293,294],{},":stmt",[29,296,297],{},":literal",[29,299,300],{},":vis",[29,302,303],{},":lifetime",[29,305,306],{},":block",[29,308,309],{},":path",[29,311,312],{},":meta",[29,314,315],{},":expr_2021"," — fragment types.",[21,318,319,322,323,326,327,330],{},[29,320,321],{},"$(...)*"," repeats zero or more; ",[29,324,325],{},"$(...)+"," repeats one or more; ",[29,328,329],{},"$(...)?"," optional.",[21,332,333,334,337],{},"Multiple arms separated by ",[29,335,336],{},";",", first match wins (top to bottom).",[260,339,341,342,345],{"id":340},"example-a-hashmap-macro","Example: a ",[29,343,344],{},"hashmap!"," macro",[88,347,348],{"language":90},[92,349,351],{"className":94,"code":350,"language":90,"meta":96,"style":96},"macro_rules! hashmap {\n    ($( $key:expr => $val:expr ),* $(,)?) => {{\n        let mut m = std::collections::HashMap::new();\n        $(\n            m.insert($key, $val);\n        )*\n        m\n    }};\n}\nlet m = hashmap!(\"a\" => 1, \"b\" => 2);\n",[29,352,353,362,410,440,447,469,476,481,485,489],{"__ignoreMap":96},[100,354,355,357,360],{"class":102,"line":103},[100,356,31],{"class":106},[100,358,359],{"class":106}," hashmap",[100,361,113],{"class":112},[100,363,364,366,368,371,373,376,378,381,383,386,389,391,394,396,398,401,404,406,408],{"class":102,"line":116},[100,365,119],{"class":112},[100,367,123],{"class":122},[100,369,370],{"class":112},"( ",[100,372,123],{"class":122},[100,374,375],{"class":112},"key",[100,377,134],{"class":122},[100,379,380],{"class":112},"expr ",[100,382,146],{"class":122},[100,384,385],{"class":122}," $",[100,387,388],{"class":112},"val",[100,390,134],{"class":122},[100,392,393],{"class":112},"expr ),",[100,395,140],{"class":122},[100,397,385],{"class":122},[100,399,400],{"class":112},"(,)",[100,402,403],{"class":122},"?",[100,405,143],{"class":112},[100,407,146],{"class":122},[100,409,149],{"class":112},[100,411,412,414,416,419,421,424,426,429,431,434,436,438],{"class":102,"line":152},[100,413,155],{"class":122},[100,415,158],{"class":122},[100,417,418],{"class":112}," m ",[100,420,164],{"class":122},[100,422,423],{"class":106}," std",[100,425,170],{"class":122},[100,427,428],{"class":106},"collections",[100,430,170],{"class":122},[100,432,433],{"class":106},"HashMap",[100,435,170],{"class":122},[100,437,173],{"class":106},[100,439,176],{"class":112},[100,441,442,444],{"class":102,"line":179},[100,443,182],{"class":122},[100,445,446],{"class":112},"(\n",[100,448,449,452,454,457,459,461,464,466],{"class":102,"line":204},[100,450,451],{"class":112},"            m",[100,453,188],{"class":122},[100,455,456],{"class":106},"insert",[100,458,126],{"class":112},[100,460,123],{"class":122},[100,462,463],{"class":112},"key, ",[100,465,123],{"class":122},[100,467,468],{"class":112},"val);\n",[100,470,471,474],{"class":102,"line":210},[100,472,473],{"class":112},"        )",[100,475,201],{"class":122},[100,477,478],{"class":102,"line":216},[100,479,480],{"class":112},"        m\n",[100,482,483],{"class":102,"line":222},[100,484,213],{"class":112},[100,486,487],{"class":102,"line":229},[100,488,219],{"class":112},[100,490,492,494,496,498,501,503,507,510,513,515,518,520,523],{"class":102,"line":491},10,[100,493,232],{"class":122},[100,495,418],{"class":112},[100,497,164],{"class":122},[100,499,500],{"class":106}," hashmap!",[100,502,126],{"class":112},[100,504,506],{"class":505},"sJ6F3","\"a\"",[100,508,509],{"class":122}," =>",[100,511,512],{"class":244}," 1",[100,514,53],{"class":112},[100,516,517],{"class":505},"\"b\"",[100,519,509],{"class":122},[100,521,522],{"class":244}," 2",[100,524,258],{"class":112},[260,526,528],{"id":527},"repetition-specifiers","Repetition Specifiers",[88,530,531],{"language":90},[92,532,534],{"className":94,"code":533,"language":90,"meta":96,"style":96},"macro_rules! sum {\n    ($($x:expr),*) => { 0 $(+ $x)* };\n    ($first:expr $(, $rest:expr)*) => { $first $(+ $rest)* };\n}\n",[29,535,536,545,590,646],{"__ignoreMap":96},[100,537,538,540,543],{"class":102,"line":103},[100,539,31],{"class":106},[100,541,542],{"class":106}," sum",[100,544,113],{"class":112},[100,546,547,549,551,553,555,557,559,561,563,565,567,570,573,575,577,580,582,585,587],{"class":102,"line":116},[100,548,119],{"class":112},[100,550,123],{"class":122},[100,552,126],{"class":112},[100,554,123],{"class":122},[100,556,131],{"class":112},[100,558,134],{"class":122},[100,560,137],{"class":112},[100,562,140],{"class":122},[100,564,143],{"class":112},[100,566,146],{"class":122},[100,568,569],{"class":112}," { ",[100,571,572],{"class":244},"0",[100,574,385],{"class":122},[100,576,126],{"class":112},[100,578,579],{"class":122},"+",[100,581,385],{"class":122},[100,583,584],{"class":112},"x)",[100,586,140],{"class":122},[100,588,589],{"class":112}," };\n",[100,591,592,594,596,599,601,603,605,608,610,613,615,618,620,622,624,626,628,631,633,635,637,639,642,644],{"class":102,"line":152},[100,593,119],{"class":112},[100,595,123],{"class":122},[100,597,598],{"class":112},"first",[100,600,134],{"class":122},[100,602,380],{"class":112},[100,604,123],{"class":122},[100,606,607],{"class":112},"(, ",[100,609,123],{"class":122},[100,611,612],{"class":112},"rest",[100,614,134],{"class":122},[100,616,617],{"class":112},"expr)",[100,619,140],{"class":122},[100,621,143],{"class":112},[100,623,146],{"class":122},[100,625,569],{"class":112},[100,627,123],{"class":122},[100,629,630],{"class":112},"first ",[100,632,123],{"class":122},[100,634,126],{"class":112},[100,636,579],{"class":122},[100,638,385],{"class":122},[100,640,641],{"class":112},"rest)",[100,643,140],{"class":122},[100,645,589],{"class":112},[100,647,648],{"class":102,"line":179},[100,649,219],{"class":112},[14,651,652,653,656,657,660],{},"Two arms handle empty\u002Fone\u002Fmany. The first arm matches the empty case (sum of nothing = 0). The ",[29,654,655],{},"$(+ $x)*"," expands to ",[29,658,659],{},"+ $x"," repeated.",[260,662,664],{"id":663},"fragment-capturing-and-follow-rules","Fragment Capturing and Follow Rules",[14,666,667,668,670,671,673,674,670,676,678,679,681,682,685],{},"Each fragment type has rules about what can follow it (because the parser is ambiguous otherwise). E.g., ",[29,669,276],{}," followed by ",[29,672,146],{}," is OK, but ",[29,675,276],{},[29,677,336],{}," is not (because ",[29,680,336],{}," could be part of the expression). Common workaround: use ",[29,683,684],{},"$(,)?"," for trailing commas.",[260,687,689],{"id":688},"hygiene","Hygiene",[14,691,692],{},"Macro-introduced identifiers don't collide with caller identifiers:",[88,694,695],{"language":90},[92,696,698],{"className":94,"code":697,"language":90,"meta":96,"style":96},"macro_rules! swap {\n    ($a:expr, $b:expr) => {\n        let tmp = $a;     \u002F\u002F 'tmp' is hygienic — won't clash with caller's tmp\n        $a = $b;\n        $b = tmp;\n    };\n}\nlet mut a = 1; let mut b = 2;\nswap!(a, b);\n",[29,699,700,709,737,755,769,781,786,790,820],{"__ignoreMap":96},[100,701,702,704,707],{"class":102,"line":103},[100,703,31],{"class":106},[100,705,706],{"class":106}," swap",[100,708,113],{"class":112},[100,710,711,713,715,718,720,723,725,728,730,733,735],{"class":102,"line":116},[100,712,119],{"class":112},[100,714,123],{"class":122},[100,716,717],{"class":112},"a",[100,719,134],{"class":122},[100,721,722],{"class":112},"expr, ",[100,724,123],{"class":122},[100,726,727],{"class":112},"b",[100,729,134],{"class":122},[100,731,732],{"class":112},"expr) ",[100,734,146],{"class":122},[100,736,113],{"class":112},[100,738,739,741,744,746,748,751],{"class":102,"line":152},[100,740,155],{"class":122},[100,742,743],{"class":112}," tmp ",[100,745,164],{"class":122},[100,747,385],{"class":122},[100,749,750],{"class":112},"a;     ",[100,752,754],{"class":753},"sdCPZ","\u002F\u002F 'tmp' is hygienic — won't clash with caller's tmp\n",[100,756,757,759,762,764,766],{"class":102,"line":179},[100,758,182],{"class":122},[100,760,761],{"class":112},"a ",[100,763,164],{"class":122},[100,765,385],{"class":122},[100,767,768],{"class":112},"b;\n",[100,770,771,773,776,778],{"class":102,"line":204},[100,772,182],{"class":122},[100,774,775],{"class":112},"b ",[100,777,164],{"class":122},[100,779,780],{"class":112}," tmp;\n",[100,782,783],{"class":102,"line":210},[100,784,785],{"class":112},"    };\n",[100,787,788],{"class":102,"line":216},[100,789,219],{"class":112},[100,791,792,794,796,799,801,803,806,808,810,813,815,817],{"class":102,"line":222},[100,793,232],{"class":122},[100,795,158],{"class":122},[100,797,798],{"class":112}," a ",[100,800,164],{"class":122},[100,802,512],{"class":244},[100,804,805],{"class":112},"; ",[100,807,232],{"class":122},[100,809,158],{"class":122},[100,811,812],{"class":112}," b ",[100,814,164],{"class":122},[100,816,522],{"class":244},[100,818,819],{"class":112},";\n",[100,821,822,825],{"class":102,"line":229},[100,823,824],{"class":106},"swap!",[100,826,827],{"class":112},"(a, b);\n",[260,829,831],{"id":830},"macro_export",[29,832,830],{},[88,834,835],{"language":90},[92,836,838],{"className":94,"code":837,"language":90,"meta":96,"style":96},"#[macro_export]\nmacro_rules! my_macro {\n    ($x:expr) => { \u002F* ... *\u002F };\n}\n",[29,839,840,845,854,875],{"__ignoreMap":96},[100,841,842],{"class":102,"line":103},[100,843,844],{"class":112},"#[macro_export]\n",[100,846,847,849,852],{"class":102,"line":116},[100,848,31],{"class":106},[100,850,851],{"class":106}," my_macro",[100,853,113],{"class":112},[100,855,856,858,860,862,864,866,868,870,873],{"class":102,"line":152},[100,857,119],{"class":112},[100,859,123],{"class":122},[100,861,131],{"class":112},[100,863,134],{"class":122},[100,865,732],{"class":112},[100,867,146],{"class":122},[100,869,569],{"class":112},[100,871,872],{"class":753},"\u002F* ... *\u002F",[100,874,589],{"class":112},[100,876,877],{"class":102,"line":179},[100,878,219],{"class":112},[14,880,881,884],{},[29,882,883],{},"#[macro_export]"," makes the macro available crate-wide and externally (placed at crate root, regardless of where it's defined).",[260,886,888],{"id":887},"re-exporting","Re-Exporting",[88,890,891],{"language":90},[92,892,894],{"className":94,"code":893,"language":90,"meta":96,"style":96},"pub use crate::my_macro;\n",[29,895,896],{"__ignoreMap":96},[100,897,898,901,904,907],{"class":102,"line":103},[100,899,900],{"class":122},"pub",[100,902,903],{"class":122}," use",[100,905,906],{"class":122}," crate::",[100,908,909],{"class":112},"my_macro;\n",[260,911,913],{"id":912},"importing","Importing",[88,915,916],{"language":90},[92,917,919],{"className":94,"code":918,"language":90,"meta":96,"style":96},"use my_crate::my_macro;\n",[29,920,921],{"__ignoreMap":96},[100,922,923,926,929,931],{"class":102,"line":103},[100,924,925],{"class":122},"use",[100,927,928],{"class":106}," my_crate",[100,930,170],{"class":122},[100,932,909],{"class":112},[14,934,935,936,938],{},"In edition 2018+, macros are imported via ",[29,937,925],{}," like any item.",[40,940,942,944,945,947],{"id":941},"vec-and-println-internals",[29,943,56],{}," and ",[29,946,52],{}," Internals",[14,949,950,952],{},[29,951,56],{}," matches several patterns:",[88,954,955],{"language":90},[92,956,958],{"className":94,"code":957,"language":90,"meta":96,"style":96},"macro_rules! vec {\n    () => ($crate::Vec::new());\n    ($elem:expr; $n:expr) => ($crate::vec::from_elem($elem, $n));\n    ($($x:expr),+ $(,)?) => ([$($x),+].into_iter().collect());\n}\n",[29,959,960,969,991,1040,1100],{"__ignoreMap":96},[100,961,962,964,967],{"class":102,"line":103},[100,963,31],{"class":106},[100,965,966],{"class":106}," vec",[100,968,113],{"class":112},[100,970,971,974,976,978,981,984,986,988],{"class":102,"line":116},[100,972,973],{"class":112},"    () ",[100,975,146],{"class":122},[100,977,27],{"class":112},[100,979,980],{"class":122},"$crate::",[100,982,983],{"class":106},"Vec",[100,985,170],{"class":122},[100,987,173],{"class":106},[100,989,990],{"class":112},"());\n",[100,992,993,995,997,1000,1002,1005,1007,1010,1012,1014,1016,1018,1020,1023,1025,1028,1030,1032,1035,1037],{"class":102,"line":152},[100,994,119],{"class":112},[100,996,123],{"class":122},[100,998,999],{"class":112},"elem",[100,1001,134],{"class":122},[100,1003,1004],{"class":112},"expr; ",[100,1006,123],{"class":122},[100,1008,1009],{"class":112},"n",[100,1011,134],{"class":122},[100,1013,732],{"class":112},[100,1015,146],{"class":122},[100,1017,27],{"class":112},[100,1019,980],{"class":122},[100,1021,1022],{"class":106},"vec",[100,1024,170],{"class":122},[100,1026,1027],{"class":106},"from_elem",[100,1029,126],{"class":112},[100,1031,123],{"class":122},[100,1033,1034],{"class":112},"elem, ",[100,1036,123],{"class":122},[100,1038,1039],{"class":112},"n));\n",[100,1041,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1066,1068,1071,1073,1075,1077,1080,1082,1085,1087,1090,1093,1095,1098],{"class":102,"line":179},[100,1043,119],{"class":112},[100,1045,123],{"class":122},[100,1047,126],{"class":112},[100,1049,123],{"class":122},[100,1051,131],{"class":112},[100,1053,134],{"class":122},[100,1055,137],{"class":112},[100,1057,579],{"class":122},[100,1059,385],{"class":122},[100,1061,400],{"class":112},[100,1063,403],{"class":122},[100,1065,143],{"class":112},[100,1067,146],{"class":122},[100,1069,1070],{"class":112}," ([",[100,1072,123],{"class":122},[100,1074,126],{"class":112},[100,1076,123],{"class":122},[100,1078,1079],{"class":112},"x),",[100,1081,579],{"class":122},[100,1083,1084],{"class":112},"]",[100,1086,188],{"class":122},[100,1088,1089],{"class":106},"into_iter",[100,1091,1092],{"class":112},"()",[100,1094,188],{"class":122},[100,1096,1097],{"class":106},"collect",[100,1099,990],{"class":112},[100,1101,1102],{"class":102,"line":204},[100,1103,219],{"class":112},[14,1105,1106,1108,1109,1112],{},[29,1107,52],{}," parses the format string and expands into ",[29,1110,1111],{},"std::io::_print(format_args!(...))",". Format args are validated at compile time.",[40,1114,1116],{"id":1115},"common-built-in-macros","Common Built-in Macros",[45,1118,1119,1141,1148,1162,1176,1199,1219,1227],{},[21,1120,1121,53,1123,53,1126,53,1129,53,1132,53,1135,53,1138],{},[29,1122,52],{},[29,1124,1125],{},"eprintln!",[29,1127,1128],{},"print!",[29,1130,1131],{},"eprint!",[29,1133,1134],{},"format!",[29,1136,1137],{},"write!",[29,1139,1140],{},"writeln!",[21,1142,1143,53,1145],{},[29,1144,56],{},[29,1146,1147],{},"format_args!",[21,1149,1150,53,1153,53,1156,53,1159],{},[29,1151,1152],{},"panic!",[29,1154,1155],{},"unreachable!",[29,1157,1158],{},"todo!",[29,1160,1161],{},"unimplemented!",[21,1163,1164,53,1167,53,1170,53,1173],{},[29,1165,1166],{},"assert!",[29,1168,1169],{},"assert_eq!",[29,1171,1172],{},"assert_ne!",[29,1174,1175],{},"debug_assert!",[21,1177,1178,53,1181,53,1184,53,1187,53,1190,53,1193,53,1196],{},[29,1179,1180],{},"matches!",[29,1182,1183],{},"cfg!",[29,1185,1186],{},"env!",[29,1188,1189],{},"option_env!",[29,1191,1192],{},"include!",[29,1194,1195],{},"include_str!",[29,1197,1198],{},"include_bytes!",[21,1200,1201,53,1204,53,1207,53,1210,53,1213,53,1216],{},[29,1202,1203],{},"concat!",[29,1205,1206],{},"stringify!",[29,1208,1209],{},"file!",[29,1211,1212],{},"line!",[29,1214,1215],{},"column!",[29,1217,1218],{},"module_path!",[21,1220,1221,53,1224],{},[29,1222,1223],{},"cfg",[29,1225,1226],{},"cfg_attr",[21,1228,1229,53,1231],{},[29,1230,1137],{},[29,1232,1140],{},[40,1234,1236],{"id":1235},"procedural-macros","Procedural Macros",[14,1238,1239,1240,1243],{},"Procedural macros run real Rust code (a separate crate of type ",[29,1241,1242],{},"proc-macro = true","). Three flavors:",[18,1245,1246,1259,1268],{},[21,1247,1248,1251,1252,1255,1256,188],{},[24,1249,1250],{},"Function-like"," (custom ",[29,1253,1254],{},"macro!"," syntax): ",[29,1257,1258],{},"custom_macro!(...)",[21,1260,1261,1264,1265,188],{},[24,1262,1263],{},"Derive",": ",[29,1266,1267],{},"#[derive(MyTrait)]",[21,1269,1270,1264,1273,188],{},[24,1271,1272],{},"Attribute",[29,1274,1275],{},"#[my_attr]",[260,1277,1279],{"id":1278},"setup","Setup",[92,1281,1286],{"className":1282,"code":1284,"language":1285},[1283],"language-text","my_crate\u002F\n├── Cargo.toml           # the user-facing crate\n└── my_crate_derive\u002F     # the proc-macro crate\n    └── Cargo.toml       # [lib] proc-macro = true\n","text",[29,1287,1284],{"__ignoreMap":96},[14,1289,1290,1291,70,1293,188],{},"Proc-macro crates must be separate and have ",[29,1292,1242],{},[29,1294,1295],{},"[lib]",[260,1297,1299,1300,1303,1304,1307],{"id":1298},"function-like-example-using-synquote","Function-Like Example (using ",[29,1301,1302],{},"syn","\u002F",[29,1305,1306],{},"quote",")",[88,1309,1310],{"language":90},[92,1311,1313],{"className":94,"code":1312,"language":90,"meta":96,"style":96},"\u002F\u002F my_crate_derive\u002Fsrc\u002Flib.rs\nuse proc_macro::TokenStream;\nuse quote::quote;\nuse syn::{parse_macro_input, ItemStruct};\n\n#[proc_macro]\npub fn make_hello(_item: TokenStream) -> TokenStream {\n    \"fn hello() { println!(\\\"hi\\\"); }\".parse().unwrap()\n}\n",[29,1314,1315,1320,1334,1346,1364,1368,1373,1400,1431],{"__ignoreMap":96},[100,1316,1317],{"class":102,"line":103},[100,1318,1319],{"class":753},"\u002F\u002F my_crate_derive\u002Fsrc\u002Flib.rs\n",[100,1321,1322,1324,1327,1329,1332],{"class":102,"line":116},[100,1323,925],{"class":122},[100,1325,1326],{"class":106}," proc_macro",[100,1328,170],{"class":122},[100,1330,1331],{"class":106},"TokenStream",[100,1333,819],{"class":112},[100,1335,1336,1338,1341,1343],{"class":102,"line":152},[100,1337,925],{"class":122},[100,1339,1340],{"class":106}," quote",[100,1342,170],{"class":122},[100,1344,1345],{"class":112},"quote;\n",[100,1347,1348,1350,1353,1355,1358,1361],{"class":102,"line":179},[100,1349,925],{"class":122},[100,1351,1352],{"class":106}," syn",[100,1354,170],{"class":122},[100,1356,1357],{"class":112},"{parse_macro_input, ",[100,1359,1360],{"class":106},"ItemStruct",[100,1362,1363],{"class":112},"};\n",[100,1365,1366],{"class":102,"line":204},[100,1367,226],{"emptyLinePlaceholder":225},[100,1369,1370],{"class":102,"line":210},[100,1371,1372],{"class":112},"#[proc_macro]\n",[100,1374,1375,1377,1380,1383,1386,1388,1391,1393,1396,1398],{"class":102,"line":216},[100,1376,900],{"class":122},[100,1378,1379],{"class":122}," fn",[100,1381,1382],{"class":106}," make_hello",[100,1384,1385],{"class":112},"(_item",[100,1387,134],{"class":122},[100,1389,1390],{"class":106}," TokenStream",[100,1392,143],{"class":112},[100,1394,1395],{"class":122},"->",[100,1397,1390],{"class":106},[100,1399,113],{"class":112},[100,1401,1402,1405,1408,1411,1413,1416,1418,1421,1423,1425,1428],{"class":102,"line":222},[100,1403,1404],{"class":505},"    \"fn hello() { println!(",[100,1406,1407],{"class":244},"\\\"",[100,1409,1410],{"class":505},"hi",[100,1412,1407],{"class":244},[100,1414,1415],{"class":505},"); }\"",[100,1417,188],{"class":122},[100,1419,1420],{"class":106},"parse",[100,1422,1092],{"class":112},[100,1424,188],{"class":122},[100,1426,1427],{"class":106},"unwrap",[100,1429,1430],{"class":112},"()\n",[100,1432,1433],{"class":102,"line":229},[100,1434,219],{"class":112},[14,1436,1437],{},"Usage:",[88,1439,1440],{"language":90},[92,1441,1443],{"className":94,"code":1442,"language":90,"meta":96,"style":96},"use my_crate_derive::make_hello;\nmake_hello!();\nhello();\n",[29,1444,1445,1457,1464],{"__ignoreMap":96},[100,1446,1447,1449,1452,1454],{"class":102,"line":103},[100,1448,925],{"class":122},[100,1450,1451],{"class":106}," my_crate_derive",[100,1453,170],{"class":122},[100,1455,1456],{"class":112},"make_hello;\n",[100,1458,1459,1462],{"class":102,"line":116},[100,1460,1461],{"class":106},"make_hello!",[100,1463,176],{"class":112},[100,1465,1466,1469],{"class":102,"line":152},[100,1467,1468],{"class":106},"hello",[100,1470,176],{"class":112},[260,1472,1474],{"id":1473},"derive-example","Derive Example",[88,1476,1477],{"language":90},[92,1478,1480],{"className":94,"code":1479,"language":90,"meta":96,"style":96},"#[proc_macro_derive(Hello)]\npub fn derive_hello(input: TokenStream) -> TokenStream {\n    let input = parse_macro_input!(input as ItemStruct);\n    let name = &input.ident;\n    let expanded = quote! {\n        impl #name {\n            fn hello() { println!(\"Hello from {}\", stringify!(#name)); }\n        }\n    };\n    expanded.into()\n}\n",[29,1481,1482,1493,1517,1541,1561,1575,1583,1608,1613,1617,1629],{"__ignoreMap":96},[100,1483,1484,1487,1490],{"class":102,"line":103},[100,1485,1486],{"class":112},"#[proc_macro_derive(",[100,1488,1489],{"class":106},"Hello",[100,1491,1492],{"class":112},")]\n",[100,1494,1495,1497,1499,1502,1505,1507,1509,1511,1513,1515],{"class":102,"line":116},[100,1496,900],{"class":122},[100,1498,1379],{"class":122},[100,1500,1501],{"class":106}," derive_hello",[100,1503,1504],{"class":112},"(input",[100,1506,134],{"class":122},[100,1508,1390],{"class":106},[100,1510,143],{"class":112},[100,1512,1395],{"class":122},[100,1514,1390],{"class":106},[100,1516,113],{"class":112},[100,1518,1519,1522,1525,1527,1530,1533,1536,1539],{"class":102,"line":152},[100,1520,1521],{"class":122},"    let",[100,1523,1524],{"class":112}," input ",[100,1526,164],{"class":122},[100,1528,1529],{"class":106}," parse_macro_input!",[100,1531,1532],{"class":112},"(input ",[100,1534,1535],{"class":122},"as",[100,1537,1538],{"class":106}," ItemStruct",[100,1540,258],{"class":112},[100,1542,1543,1545,1548,1550,1553,1556,1558],{"class":102,"line":179},[100,1544,1521],{"class":122},[100,1546,1547],{"class":112}," name ",[100,1549,164],{"class":122},[100,1551,1552],{"class":122}," &",[100,1554,1555],{"class":112},"input",[100,1557,188],{"class":122},[100,1559,1560],{"class":112},"ident;\n",[100,1562,1563,1565,1568,1570,1573],{"class":102,"line":204},[100,1564,1521],{"class":122},[100,1566,1567],{"class":112}," expanded ",[100,1569,164],{"class":122},[100,1571,1572],{"class":106}," quote!",[100,1574,113],{"class":112},[100,1576,1577,1580],{"class":102,"line":210},[100,1578,1579],{"class":122},"        impl",[100,1581,1582],{"class":112}," #name {\n",[100,1584,1585,1588,1591,1594,1596,1598,1601,1603,1605],{"class":102,"line":216},[100,1586,1587],{"class":122},"            fn",[100,1589,1590],{"class":106}," hello",[100,1592,1593],{"class":112},"() { ",[100,1595,52],{"class":106},[100,1597,126],{"class":112},[100,1599,1600],{"class":505},"\"Hello from {}\"",[100,1602,53],{"class":112},[100,1604,1206],{"class":106},[100,1606,1607],{"class":112},"(#name)); }\n",[100,1609,1610],{"class":102,"line":222},[100,1611,1612],{"class":112},"        }\n",[100,1614,1615],{"class":102,"line":229},[100,1616,785],{"class":112},[100,1618,1619,1622,1624,1627],{"class":102,"line":491},[100,1620,1621],{"class":112},"    expanded",[100,1623,188],{"class":122},[100,1625,1626],{"class":106},"into",[100,1628,1430],{"class":112},[100,1630,1632],{"class":102,"line":1631},11,[100,1633,219],{"class":112},[14,1635,1437],{},[88,1637,1638],{"language":90},[92,1639,1641],{"className":94,"code":1640,"language":90,"meta":96,"style":96},"#[derive(Hello)]\nstruct Foo;\nFoo::hello();\n",[29,1642,1643,1652,1662],{"__ignoreMap":96},[100,1644,1645,1648,1650],{"class":102,"line":103},[100,1646,1647],{"class":112},"#[derive(",[100,1649,1489],{"class":106},[100,1651,1492],{"class":112},[100,1653,1654,1657,1660],{"class":102,"line":116},[100,1655,1656],{"class":122},"struct",[100,1658,1659],{"class":106}," Foo",[100,1661,819],{"class":112},[100,1663,1664,1667,1669,1671],{"class":102,"line":152},[100,1665,1666],{"class":106},"Foo",[100,1668,170],{"class":122},[100,1670,1468],{"class":106},[100,1672,176],{"class":112},[260,1674,1676],{"id":1675},"derive-with-helper-attributes","Derive with Helper Attributes",[88,1678,1679],{"language":90},[92,1680,1682],{"className":94,"code":1681,"language":90,"meta":96,"style":96},"#[proc_macro_derive(Hello, attributes(hello_name))]\npub fn derive_hello(input: TokenStream) -> TokenStream { \u002F* ... *\u002F }\n\n\u002F\u002F user:\n#[derive(Hello)]\n#[hello_name = \"Bar\"]\nstruct Foo;\n",[29,1683,1684,1693,1720,1724,1729,1737,1750],{"__ignoreMap":96},[100,1685,1686,1688,1690],{"class":102,"line":103},[100,1687,1486],{"class":112},[100,1689,1489],{"class":106},[100,1691,1692],{"class":112},", attributes(hello_name))]\n",[100,1694,1695,1697,1699,1701,1703,1705,1707,1709,1711,1713,1715,1717],{"class":102,"line":116},[100,1696,900],{"class":122},[100,1698,1379],{"class":122},[100,1700,1501],{"class":106},[100,1702,1504],{"class":112},[100,1704,134],{"class":122},[100,1706,1390],{"class":106},[100,1708,143],{"class":112},[100,1710,1395],{"class":122},[100,1712,1390],{"class":106},[100,1714,569],{"class":112},[100,1716,872],{"class":753},[100,1718,1719],{"class":112}," }\n",[100,1721,1722],{"class":102,"line":152},[100,1723,226],{"emptyLinePlaceholder":225},[100,1725,1726],{"class":102,"line":179},[100,1727,1728],{"class":753},"\u002F\u002F user:\n",[100,1730,1731,1733,1735],{"class":102,"line":204},[100,1732,1647],{"class":112},[100,1734,1489],{"class":106},[100,1736,1492],{"class":112},[100,1738,1739,1742,1744,1747],{"class":102,"line":210},[100,1740,1741],{"class":112},"#[hello_name ",[100,1743,164],{"class":122},[100,1745,1746],{"class":505}," \"Bar\"",[100,1748,1749],{"class":112},"]\n",[100,1751,1752,1754,1756],{"class":102,"line":216},[100,1753,1656],{"class":122},[100,1755,1659],{"class":106},[100,1757,819],{"class":112},[260,1759,1761],{"id":1760},"attribute-macros","Attribute Macros",[88,1763,1764],{"language":90},[92,1765,1767],{"className":94,"code":1766,"language":90,"meta":96,"style":96},"#[proc_macro_attribute]\npub fn log_calls(attr: TokenStream, item: TokenStream) -> TokenStream { \u002F* ... *\u002F }\n",[29,1768,1769,1774],{"__ignoreMap":96},[100,1770,1771],{"class":102,"line":103},[100,1772,1773],{"class":112},"#[proc_macro_attribute]\n",[100,1775,1776,1778,1780,1783,1786,1788,1790,1793,1795,1797,1799,1801,1803,1805,1807],{"class":102,"line":116},[100,1777,900],{"class":122},[100,1779,1379],{"class":122},[100,1781,1782],{"class":106}," log_calls",[100,1784,1785],{"class":112},"(attr",[100,1787,134],{"class":122},[100,1789,1390],{"class":106},[100,1791,1792],{"class":112},", item",[100,1794,134],{"class":122},[100,1796,1390],{"class":106},[100,1798,143],{"class":112},[100,1800,1395],{"class":122},[100,1802,1390],{"class":106},[100,1804,569],{"class":112},[100,1806,872],{"class":753},[100,1808,1719],{"class":112},[14,1810,1811],{},"Receives both the attribute arguments and the item being annotated.",[260,1813,1815],{"id":1814},"helper-crates","Helper Crates",[45,1817,1818,1823,1832,1838,1844],{},[21,1819,1820,1822],{},[29,1821,1302],{},": parse Rust syntax.",[21,1824,1825,1827,1828,1831],{},[29,1826,1306],{},": build TokenStreams with ",[29,1829,1830],{},"quote!"," macro.",[21,1833,1834,1837],{},[29,1835,1836],{},"proc-macro2",": works with stable Rust (proc_macro types are unstable-only).",[21,1839,1840,1843],{},[29,1841,1842],{},"darling",": ergonomic derive attribute parsing.",[21,1845,1846,1849],{},[29,1847,1848],{},"proc-macro-error",": better error reporting.",[40,1851,1853],{"id":1852},"built-in-derives","Built-in Derives",[88,1855,1856],{"language":90},[92,1857,1859],{"className":94,"code":1858,"language":90,"meta":96,"style":96},"#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]\nstruct Foo { \u002F* ... *\u002F }\n",[29,1860,1861,1910],{"__ignoreMap":96},[100,1862,1863,1865,1868,1870,1873,1875,1878,1880,1883,1885,1888,1890,1893,1895,1898,1900,1903,1905,1908],{"class":102,"line":103},[100,1864,1647],{"class":112},[100,1866,1867],{"class":106},"Debug",[100,1869,53],{"class":112},[100,1871,1872],{"class":106},"Clone",[100,1874,53],{"class":112},[100,1876,1877],{"class":106},"Copy",[100,1879,53],{"class":112},[100,1881,1882],{"class":106},"PartialEq",[100,1884,53],{"class":112},[100,1886,1887],{"class":106},"Eq",[100,1889,53],{"class":112},[100,1891,1892],{"class":106},"PartialOrd",[100,1894,53],{"class":112},[100,1896,1897],{"class":106},"Ord",[100,1899,53],{"class":112},[100,1901,1902],{"class":106},"Hash",[100,1904,53],{"class":112},[100,1906,1907],{"class":106},"Default",[100,1909,1492],{"class":112},[100,1911,1912,1914,1916,1918,1920],{"class":102,"line":116},[100,1913,1656],{"class":122},[100,1915,1659],{"class":106},[100,1917,569],{"class":112},[100,1919,872],{"class":753},[100,1921,1719],{"class":112},[14,1923,1924],{},"These are built into the compiler.",[40,1926,1928],{"id":1927},"macro-pitfalls","Macro Pitfalls",[45,1930,1931,1937,1943,1954,1965,1978,1988,1997,2008,2017],{},[21,1932,1933,1936],{},[24,1934,1935],{},"Order of arms",": declarative macros match top-to-bottom. Specific patterns must come before general ones.",[21,1938,1939,1942],{},[24,1940,1941],{},"Hygiene surprises",": macro-introduced variables are isolated; sometimes you want unhygienic behavior (rare).",[21,1944,1945,1264,1948,1950,1951,1953],{},[24,1946,1947],{},"Expression vs statement fragments",[29,1949,276],{}," captures the whole expression and double-evaluates if used multiple times. Use a ",[29,1952,232],{}," binding inside the macro to evaluate once.",[21,1955,1956,1264,1959,1961,1962,57],{},[24,1957,1958],{},"Recursion",[29,1960,31],{}," recursion is limited (default 64 deep; can be raised via ",[29,1963,1964],{},"#![recursion_limit = \"256\"]",[21,1966,1967,1264,1970,1973,1974,1977],{},[24,1968,1969],{},"Debugging macros",[29,1971,1972],{},"cargo expand"," (install with ",[29,1975,1976],{},"cargo install cargo-expand",") shows the expanded code.",[21,1979,1980,1983,1984,1987],{},[24,1981,1982],{},"Compile time",": heavy macros (especially proc-macros like ",[29,1985,1986],{},"serde",") slow compilation.",[21,1989,1990,1996],{},[24,1991,1992,1995],{},[29,1993,1994],{},"proc-macro"," crate isolation",": a proc-macro crate can't export anything else; it's a separate compilation unit.",[21,1998,1999,1264,2002,2004,2005,2007],{},[24,2000,2001],{},"Span info",[29,2003,1830],{},"'s default spans can produce confusing errors. Use ",[29,2006,1302],{},"'s spans carefully.",[21,2009,2010,2016],{},[24,2011,2012,2013],{},"Macro in ",[29,2014,2015],{},"pub use",": ensure you re-export macros from a top-level module.",[21,2018,2019,2024],{},[24,2020,2021,2023],{},[29,2022,883],{}," placement",": places the macro at the crate root regardless of where it's defined.",[40,2026,2028],{"id":2027},"cargo-expand",[29,2029,1972],{},[88,2031,2033],{"language":2032},"bash",[92,2034,2037],{"className":2035,"code":2036,"language":2032,"meta":96,"style":96},"language-bash shiki shiki-themes github-light github-dark","cargo install cargo-expand\ncargo expand\n",[29,2038,2039,2050],{"__ignoreMap":96},[100,2040,2041,2044,2047],{"class":102,"line":103},[100,2042,2043],{"class":106},"cargo",[100,2045,2046],{"class":505}," install",[100,2048,2049],{"class":505}," cargo-expand\n",[100,2051,2052,2054],{"class":102,"line":116},[100,2053,2043],{"class":106},[100,2055,2056],{"class":505}," expand\n",[14,2058,2059],{},"Prints the post-macro-expansion source. Invaluable for debugging declarative and proc-macros.",[40,2061,2063],{"id":2062},"when-to-use-a-macro-vs-a-function","When to Use a Macro vs a Function",[14,2065,2066],{},"Use a macro when:",[45,2068,2069,2072,2075,2078],{},[21,2070,2071],{},"You need variadic arguments.",[21,2073,2074],{},"You need to take types as arguments.",[21,2076,2077],{},"You need to generate code based on structure (e.g., derive).",[21,2079,2080],{},"You need compile-time string parsing (format strings).",[14,2082,2083],{},"Otherwise, use a function (simpler, easier to debug, type-checks better).",[40,2085,2087],{"id":2086},"summary","Summary",[45,2089,2090,2096,2102,2107],{},[21,2091,2092,2093,2095],{},"Declarative macros (",[29,2094,31],{},") pattern-match and emit code; hygiene prevents name collisions.",[21,2097,2098,2099,2101],{},"Proc-macros (separate ",[29,2100,1242],{}," crate) write real code: derive, attribute, function-like.",[21,2103,2104,2106],{},[29,2105,1972],{}," is essential for debugging.",[21,2108,2109],{},"Use macros sparingly — they're powerful but add compile-time cost and complexity.",[14,2111,2112],{},"Next: Unsafe Rust.",[2114,2115,2116],"style",{},"html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}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 .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":96,"searchDepth":116,"depth":116,"links":2118},[2119,2120,2132,2134,2135,2144,2145,2146,2147,2148],{"id":42,"depth":116,"text":43},{"id":83,"depth":116,"text":2121,"children":2122},"Declarative Macros: macro_rules!",[2123,2124,2126,2127,2128,2129,2130,2131],{"id":262,"depth":152,"text":263},{"id":340,"depth":152,"text":2125},"Example: a hashmap! macro",{"id":527,"depth":152,"text":528},{"id":663,"depth":152,"text":664},{"id":688,"depth":152,"text":689},{"id":830,"depth":152,"text":830},{"id":887,"depth":152,"text":888},{"id":912,"depth":152,"text":913},{"id":941,"depth":116,"text":2133},"vec! and println! Internals",{"id":1115,"depth":116,"text":1116},{"id":1235,"depth":116,"text":1236,"children":2136},[2137,2138,2140,2141,2142,2143],{"id":1278,"depth":152,"text":1279},{"id":1298,"depth":152,"text":2139},"Function-Like Example (using syn\u002Fquote)",{"id":1473,"depth":152,"text":1474},{"id":1675,"depth":152,"text":1676},{"id":1760,"depth":152,"text":1761},{"id":1814,"depth":152,"text":1815},{"id":1852,"depth":116,"text":1853},{"id":1927,"depth":116,"text":1928},{"id":2027,"depth":116,"text":1972},{"id":2062,"depth":116,"text":2063},{"id":2086,"depth":116,"text":2087},"md",{},"\u002Frust\u002F24-macros",{"title":5,"description":16},"rust\u002F24-macros","D8yY_qBDfpg9hBT3yAzdbmZioODQIRlSvCmkm54ThOg",1785944093267]