[{"data":1,"prerenderedAt":3820},["ShallowReactive",2],{"page-\u002Frust\u002F30-design-patterns":3},{"id":4,"title":5,"body":6,"description":30,"extension":3814,"meta":3815,"navigation":153,"path":3816,"seo":3817,"stem":3818,"__hash__":3819},"content\u002Frust\u002F30-design-patterns.md","30 — Design Patterns",{"type":7,"value":8,"toc":3784},"minimark",[9,13,231,398,648,968,1183,1480,1595,1858,2054,2200,2445,2601,2791,2969,3094,3306,3780],[10,11,5],"h1",{"id":12},"_30-design-patterns",[14,15,17,22,140,190],"question-wrapper",{"language":16},"rust",[18,19,21],"h3",{"id":20},"q1-what-is-the-defining-structural-feature-of-the-builder-pattern-as-commonly-written-in-rust","Q1. What is the defining structural feature of the builder pattern as commonly written in Rust?",[23,24,25],"code-wrapper",{"language":16},[26,27,31],"pre",{"className":28,"code":29,"language":16,"meta":30,"style":30},"language-rust shiki shiki-themes github-light github-dark","let req = RequestBuilder::new(\"https:\u002F\u002Fapi.example.com\")\n    .method(\"POST\")\n    .header(\"Content-Type\", \"application\u002Fjson\")\n    .timeout_secs(30)\n    .build()?;\n","",[32,33,34,70,86,107,123],"code",{"__ignoreMap":30},[35,36,39,43,47,50,54,57,60,63,67],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"svdQ7","let",[35,44,46],{"class":45},"ssxIu"," req ",[35,48,49],{"class":41},"=",[35,51,53],{"class":52},"sIsaT"," RequestBuilder",[35,55,56],{"class":41},"::",[35,58,59],{"class":52},"new",[35,61,62],{"class":45},"(",[35,64,66],{"class":65},"sJ6F3","\"https:\u002F\u002Fapi.example.com\"",[35,68,69],{"class":45},")\n",[35,71,73,76,79,81,84],{"class":37,"line":72},2,[35,74,75],{"class":41},"    .",[35,77,78],{"class":52},"method",[35,80,62],{"class":45},[35,82,83],{"class":65},"\"POST\"",[35,85,69],{"class":45},[35,87,89,91,94,96,99,102,105],{"class":37,"line":88},3,[35,90,75],{"class":41},[35,92,93],{"class":52},"header",[35,95,62],{"class":45},[35,97,98],{"class":65},"\"Content-Type\"",[35,100,101],{"class":45},", ",[35,103,104],{"class":65},"\"application\u002Fjson\"",[35,106,69],{"class":45},[35,108,110,112,115,117,121],{"class":37,"line":109},4,[35,111,75],{"class":41},[35,113,114],{"class":52},"timeout_secs",[35,116,62],{"class":45},[35,118,120],{"class":119},"snvgF","30",[35,122,69],{"class":45},[35,124,126,128,131,134,137],{"class":37,"line":125},5,[35,127,75],{"class":41},[35,129,130],{"class":52},"build",[35,132,133],{"class":45},"()",[35,135,136],{"class":41},"?",[35,138,139],{"class":45},";\n",[141,142,145,168,178,184],"ul",{"className":143},[144],"contains-task-list",[146,147,150,155,156,159,160,163,164,167],"li",{"className":148},[149],"task-list-item",[151,152],"input",{"disabled":153,"type":154},true,"checkbox"," A separate builder struct accumulates configuration through chained methods that each consume and return ",[32,157,158],{},"self"," (or ",[32,161,162],{},"&mut self","), with a final ",[32,165,166],{},"build()"," that validates and produces the target type",[146,169,171,173,174,177],{"className":170},[149],[151,172],{"disabled":153,"type":154}," A struct that implements ",[32,175,176],{},"Default"," and is mutated directly via public fields",[146,179,181,183],{"className":180},[149],[151,182],{"disabled":153,"type":154}," A macro that generates a constructor accepting every field as a positional argument",[146,185,187,189],{"className":186},[149],[151,188],{"disabled":153,"type":154}," A trait that all configurable types must implement, with no separate builder struct involved",[191,192,193,197,207],"details",{},[194,195,196],"summary",{},"Show Answer",[198,199,200,204,205],"p",{},[201,202,203],"strong",{},"Answer:"," A — a separate builder struct with chained methods and a final validating ",[32,206,166],{},[198,208,209,212,213,216,217,219,220,223,224,101,227,230],{},[201,210,211],{},"Explanation:"," The builder pattern exists in Rust largely because the language has no named\u002Fdefault function arguments — chained ",[32,214,215],{},".method(...)"," calls on a dedicated builder struct simulate that ergonomics while letting each step be independently optional, and ",[32,218,166],{}," gives a single place to validate combinations and return ",[32,221,222],{},"Result"," for invalid configurations. Direct public-field mutation skips validation and locks in field names\u002Ftypes as public API forever. A positional-argument macro reintroduces the exact problem builders solve (unreadable call sites, fragile argument order). A trait-only approach without a separate accumulating struct doesn't match how the pattern is idiomatically structured in the ecosystem (e.g. ",[32,225,226],{},"reqwest::RequestBuilder",[32,228,229],{},"std::process::Command",").",[14,232,233,241,309,350],{"language":16},[18,234,236,237,240],{"id":235},"q2-what-core-problem-does-the-newtype-pattern-struct-metersf64-solve","Q2. What core problem does the newtype pattern (",[32,238,239],{},"struct Meters(f64);",") solve?",[23,242,243],{"language":16},[26,244,246],{"className":28,"code":245,"language":16,"meta":30,"style":30},"struct Meters(f64);\nstruct Feet(f64);\n\nfn distance_traveled(m: Meters) -> Meters { m }\n",[32,247,248,264,277,282],{"__ignoreMap":30},[35,249,250,253,256,258,261],{"class":37,"line":38},[35,251,252],{"class":41},"struct",[35,254,255],{"class":52}," Meters",[35,257,62],{"class":45},[35,259,260],{"class":52},"f64",[35,262,263],{"class":45},");\n",[35,265,266,268,271,273,275],{"class":37,"line":72},[35,267,252],{"class":41},[35,269,270],{"class":52}," Feet",[35,272,62],{"class":45},[35,274,260],{"class":52},[35,276,263],{"class":45},[35,278,279],{"class":37,"line":88},[35,280,281],{"emptyLinePlaceholder":153},"\n",[35,283,284,287,290,293,296,298,301,304,306],{"class":37,"line":109},[35,285,286],{"class":41},"fn",[35,288,289],{"class":52}," distance_traveled",[35,291,292],{"class":45},"(m",[35,294,295],{"class":41},":",[35,297,255],{"class":52},[35,299,300],{"class":45},") ",[35,302,303],{"class":41},"->",[35,305,255],{"class":52},[35,307,308],{"class":45}," { m }\n",[141,310,312,321,330,336],{"className":311},[144],[146,313,315,317,318,320],{"className":314},[149],[151,316],{"disabled":153,"type":154}," It creates a distinct type at compile time so values with the same underlying representation (e.g. two ",[32,319,260],{},"s meaning different units) cannot be accidentally interchanged",[146,322,324,326,327,329],{"className":323},[149],[151,325],{"disabled":153,"type":154}," It reduces the runtime memory footprint of ",[32,328,260],{}," by removing unused precision bits",[146,331,333,335],{"className":332},[149],[151,334],{"disabled":153,"type":154}," It's required by the compiler any time a struct has exactly one field",[146,337,339,341,342,345,346,349],{"className":338},[149],[151,340],{"disabled":153,"type":154}," It automatically implements ",[32,343,344],{},"Add"," and ",[32,347,348],{},"Sub"," for the wrapped type",[191,351,352,354,359],{},[194,353,196],{},[198,355,356,358],{},[201,357,203],{}," A — creates a distinct compile-time type so same-representation values with different meanings can't be mixed up accidentally",[198,360,361,363,364,363,367,345,370,373,374,376,377,380,381,383,384,387,388,391,392,394,395,397],{},[201,362,211],{}," ",[201,365,366],{},"Safety:",[32,368,369],{},"Meters(f64)",[32,371,372],{},"Feet(f64)"," share an identical runtime layout (a single ",[32,375,260],{},", and with ",[32,378,379],{},"#[repr(transparent)]"," even guaranteed ABI-identical to ",[32,382,260],{},") but are different types to the compiler — passing a ",[32,385,386],{},"Feet"," where ",[32,389,390],{},"Meters"," is expected is a compile error, catching unit-confusion bugs (the kind that famously destroyed the Mars Climate Orbiter) at compile time instead of production. It has zero effect on runtime memory representation\u002Fprecision — the wrapper is typically free at runtime (a compile-time-only distinction). It's a voluntary pattern, not a compiler requirement for single-field structs (plenty of single-field structs aren't newtypes in this sense). And trait impls like ",[32,393,344],{},"\u002F",[32,396,348],{}," are never automatic — they must be explicitly implemented (or derived, where applicable) for the new type; wrapping a value implements nothing by itself.",[14,399,400,404,561,605],{"language":16},[18,401,403],{"id":402},"q3-the-newtype-pattern-is-also-used-to-work-around-rusts-orphan-rule-which-scenario-is-a-correct-use-of-newtype-for-this-purpose","Q3. The newtype pattern is also used to work around Rust's orphan rule. Which scenario is a correct use of newtype for this purpose?",[23,405,406],{"language":16},[26,407,409],{"className":28,"code":408,"language":16,"meta":30,"style":30},"use std::fmt;\n\nstruct Wrapper(Vec\u003CString>);\n\nimpl fmt::Display for Wrapper {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"[{}]\", self.0.join(\", \"))\n    }\n}\n",[32,410,411,424,428,449,453,474,516,549,555],{"__ignoreMap":30},[35,412,413,416,419,421],{"class":37,"line":38},[35,414,415],{"class":41},"use",[35,417,418],{"class":52}," std",[35,420,56],{"class":41},[35,422,423],{"class":45},"fmt;\n",[35,425,426],{"class":37,"line":72},[35,427,281],{"emptyLinePlaceholder":153},[35,429,430,432,435,437,440,443,446],{"class":37,"line":88},[35,431,252],{"class":41},[35,433,434],{"class":52}," Wrapper",[35,436,62],{"class":45},[35,438,439],{"class":52},"Vec",[35,441,442],{"class":45},"\u003C",[35,444,445],{"class":52},"String",[35,447,448],{"class":45},">);\n",[35,450,451],{"class":37,"line":109},[35,452,281],{"emptyLinePlaceholder":153},[35,454,455,458,461,463,466,469,471],{"class":37,"line":125},[35,456,457],{"class":41},"impl",[35,459,460],{"class":52}," fmt",[35,462,56],{"class":41},[35,464,465],{"class":52},"Display",[35,467,468],{"class":41}," for",[35,470,434],{"class":52},[35,472,473],{"class":45}," {\n",[35,475,477,480,482,484,487,489,492,494,497,499,501,504,506,508,510,512,514],{"class":37,"line":476},6,[35,478,479],{"class":41},"    fn",[35,481,460],{"class":52},[35,483,62],{"class":45},[35,485,486],{"class":41},"&",[35,488,158],{"class":119},[35,490,491],{"class":45},", f",[35,493,295],{"class":41},[35,495,496],{"class":41}," &mut",[35,498,460],{"class":52},[35,500,56],{"class":41},[35,502,503],{"class":52},"Formatter",[35,505,300],{"class":45},[35,507,303],{"class":41},[35,509,460],{"class":52},[35,511,56],{"class":41},[35,513,222],{"class":52},[35,515,473],{"class":45},[35,517,519,522,525,528,530,532,535,538,541,543,546],{"class":37,"line":518},7,[35,520,521],{"class":52},"        write!",[35,523,524],{"class":45},"(f, ",[35,526,527],{"class":65},"\"[{}]\"",[35,529,101],{"class":45},[35,531,158],{"class":119},[35,533,534],{"class":41},".",[35,536,537],{"class":119},"0.",[35,539,540],{"class":52},"join",[35,542,62],{"class":45},[35,544,545],{"class":65},"\", \"",[35,547,548],{"class":45},"))\n",[35,550,552],{"class":37,"line":551},8,[35,553,554],{"class":45},"    }\n",[35,556,558],{"class":37,"line":557},9,[35,559,560],{"class":45},"}\n",[141,562,564,584,590,596],{"className":563},[144],[146,565,567,569,570,573,574,577,578,580,581,583],{"className":566},[149],[151,568],{"disabled":153,"type":154}," Wrapping a foreign type (",[32,571,572],{},"Vec\u003CString>",", from ",[32,575,576],{},"std",") in a local tuple struct so you can implement a foreign trait (",[32,579,465],{},", also from ",[32,582,576],{},") on the local wrapper, since neither the trait nor the raw type is local",[146,585,587,589],{"className":586},[149],[151,588],{"disabled":153,"type":154}," Wrapping a local struct so you can implement a local trait on it, which would otherwise be impossible",[146,591,593,595],{"className":592},[149],[151,594],{"disabled":153,"type":154}," Using newtype to bypass the borrow checker's mutable-aliasing rules",[146,597,599,601,602,604],{"className":598},[149],[151,600],{"disabled":153,"type":154}," The orphan rule doesn't apply to ",[32,603,465],{},", so no wrapper is needed here at all",[191,606,607,609,614],{},[194,608,196],{},[198,610,611,613],{},[201,612,203],{}," A — wrap the foreign type locally so the impl target (the wrapper) is local, satisfying the orphan rule for the foreign trait",[198,615,616,363,618,621,622,625,626,628,629,631,632,634,635,638,639,394,641,644,645,647],{},[201,617,211],{},[201,619,620],{},"Idiom:"," The orphan rule blocks ",[32,623,624],{},"impl Display for Vec\u003CString>"," directly because neither ",[32,627,465],{}," nor ",[32,630,439],{}," is defined in your crate — both are foreign. Wrapping ",[32,633,572],{}," in a local tuple struct ",[32,636,637],{},"Wrapper"," makes the impl target local, satisfying \"at least one of trait or type must be local,\" even though the trait itself remains foreign. Implementing a local trait on a local type was never blocked by the orphan rule in the first place (that's always allowed), so option B describes a non-problem. Newtype has nothing to do with borrow-checker aliasing rules — those are governed by ",[32,640,486],{},[32,642,643],{},"&mut"," reference rules, unrelated to type wrapping. And ",[32,646,465],{}," is subject to the orphan rule exactly like any other foreign trait; there's no special exemption.",[14,649,650,654,870,920],{"language":16},[18,651,653],{"id":652},"q4-what-does-the-typestate-pattern-encode-and-how-does-it-typically-prevent-misuse-at-compile-time","Q4. What does the typestate pattern encode, and how does it typically prevent misuse at compile time?",[23,655,656],{"language":16},[26,657,659],{"className":28,"code":658,"language":16,"meta":30,"style":30},"struct Locked;\nstruct Unlocked;\n\nstruct Door\u003CState> {\n    _state: std::marker::PhantomData\u003CState>,\n}\n\nimpl Door\u003CLocked> {\n    fn unlock(self, _key: &str) -> Door\u003CUnlocked> { Door { _state: std::marker::PhantomData } }\n}\n\nimpl Door\u003CUnlocked> {\n    fn open(self) -> Door\u003CUnlocked> { println!(\"opened\"); self }\n}\n",[32,660,661,670,679,683,698,724,728,732,745,802,807,812,825,865],{"__ignoreMap":30},[35,662,663,665,668],{"class":37,"line":38},[35,664,252],{"class":41},[35,666,667],{"class":52}," Locked",[35,669,139],{"class":45},[35,671,672,674,677],{"class":37,"line":72},[35,673,252],{"class":41},[35,675,676],{"class":52}," Unlocked",[35,678,139],{"class":45},[35,680,681],{"class":37,"line":88},[35,682,281],{"emptyLinePlaceholder":153},[35,684,685,687,690,692,695],{"class":37,"line":109},[35,686,252],{"class":41},[35,688,689],{"class":52}," Door",[35,691,442],{"class":45},[35,693,694],{"class":52},"State",[35,696,697],{"class":45},"> {\n",[35,699,700,703,705,707,709,712,714,717,719,721],{"class":37,"line":125},[35,701,702],{"class":45},"    _state",[35,704,295],{"class":41},[35,706,418],{"class":52},[35,708,56],{"class":41},[35,710,711],{"class":52},"marker",[35,713,56],{"class":41},[35,715,716],{"class":52},"PhantomData",[35,718,442],{"class":45},[35,720,694],{"class":52},[35,722,723],{"class":45},">,\n",[35,725,726],{"class":37,"line":476},[35,727,560],{"class":45},[35,729,730],{"class":37,"line":518},[35,731,281],{"emptyLinePlaceholder":153},[35,733,734,736,738,740,743],{"class":37,"line":551},[35,735,457],{"class":41},[35,737,689],{"class":52},[35,739,442],{"class":45},[35,741,742],{"class":52},"Locked",[35,744,697],{"class":45},[35,746,747,749,752,754,756,759,761,764,767,769,771,773,775,778,781,784,787,789,791,793,795,797,799],{"class":37,"line":557},[35,748,479],{"class":41},[35,750,751],{"class":52}," unlock",[35,753,62],{"class":45},[35,755,158],{"class":119},[35,757,758],{"class":45},", _key",[35,760,295],{"class":41},[35,762,763],{"class":41}," &",[35,765,766],{"class":52},"str",[35,768,300],{"class":45},[35,770,303],{"class":41},[35,772,689],{"class":52},[35,774,442],{"class":45},[35,776,777],{"class":52},"Unlocked",[35,779,780],{"class":45},"> { ",[35,782,783],{"class":52},"Door",[35,785,786],{"class":45}," { _state",[35,788,295],{"class":41},[35,790,418],{"class":52},[35,792,56],{"class":41},[35,794,711],{"class":52},[35,796,56],{"class":41},[35,798,716],{"class":52},[35,800,801],{"class":45}," } }\n",[35,803,805],{"class":37,"line":804},10,[35,806,560],{"class":45},[35,808,810],{"class":37,"line":809},11,[35,811,281],{"emptyLinePlaceholder":153},[35,813,815,817,819,821,823],{"class":37,"line":814},12,[35,816,457],{"class":41},[35,818,689],{"class":52},[35,820,442],{"class":45},[35,822,777],{"class":52},[35,824,697],{"class":45},[35,826,828,830,833,835,837,839,841,843,845,847,849,852,854,857,860,862],{"class":37,"line":827},13,[35,829,479],{"class":41},[35,831,832],{"class":52}," open",[35,834,62],{"class":45},[35,836,158],{"class":119},[35,838,300],{"class":45},[35,840,303],{"class":41},[35,842,689],{"class":52},[35,844,442],{"class":45},[35,846,777],{"class":52},[35,848,780],{"class":45},[35,850,851],{"class":52},"println!",[35,853,62],{"class":45},[35,855,856],{"class":65},"\"opened\"",[35,858,859],{"class":45},"); ",[35,861,158],{"class":119},[35,863,864],{"class":45}," }\n",[35,866,868],{"class":37,"line":867},14,[35,869,560],{"class":45},[141,871,873,887,897,910],{"className":872},[144],[146,874,876,878,879,882,883,886],{"className":875},[149],[151,877],{"disabled":153,"type":154}," It encodes an object's runtime state as distinct types (often via a generic parameter), so methods only valid in a given state are only defined on that state's type — calling ",[32,880,881],{},"open()"," on a ",[32,884,885],{},"Door\u003CLocked>"," is a compile error, not a runtime check",[146,888,890,892,893,896],{"className":889},[149],[151,891],{"disabled":153,"type":154}," It stores the current state as an enum field and uses a ",[32,894,895],{},"match"," inside every method to check validity at runtime",[146,898,900,902,903,394,906,909],{"className":899},[149],[151,901],{"disabled":153,"type":154}," It's a synonym for the state machine pattern implemented purely with ",[32,904,905],{},"if",[32,907,908],{},"else"," branches",[146,911,913,915,916,919],{"className":912},[149],[151,914],{"disabled":153,"type":154}," It requires ",[32,917,918],{},"unsafe"," to transition between states since ownership must be forcibly reinterpreted",[191,921,922,924,929],{},[194,923,196],{},[198,925,926,928],{},[201,927,203],{}," A — states become distinct types, so only valid-for-that-state methods exist, and invalid transitions fail to compile",[198,930,931,363,933,935,936,345,938,941,942,945,946,101,948,951,952,954,955,958,959,961,962,964,965,967],{},[201,932,211],{},[201,934,366],{}," In the typestate pattern, ",[32,937,885],{},[32,939,940],{},"Door\u003CUnlocked>"," are different types with non-overlapping method sets (",[32,943,944],{},"unlock"," only exists on ",[32,947,885],{},[32,949,950],{},"open"," only on ",[32,953,940],{},"), so attempting ",[32,956,957],{},"Door\u003CLocked>::open()"," is a \"no method named ",[32,960,950],{}," found\" compile error — the illegal transition is caught before the program ever runs, unlike the described enum-plus-runtime-",[32,963,895],{}," approach (option B), which is a valid but strictly weaker pattern (it moves the same check to runtime, where a forgotten branch panics or misbehaves in production instead of failing the build). It's related to but distinct from a general state machine (which typestate implements specifically via the type system, not just any state-tracking technique), and it requires no ",[32,966,918],{}," — transitions are ordinary by-value moves consuming the old-state value and returning a new-state value.",[14,969,970,978,1074,1129],{"language":16},[18,971,973,974,977],{"id":972},"q5-what-guarantee-does-raii-resource-acquisition-is-initialization-via-drop-provide-in-rust","Q5. What guarantee does RAII (Resource Acquisition Is Initialization) via ",[32,975,976],{},"Drop"," provide in Rust?",[23,979,980],{"language":16},[26,981,983],{"className":28,"code":982,"language":16,"meta":30,"style":30},"struct FileGuard {\n    file: std::fs::File,\n}\n\nimpl Drop for FileGuard {\n    fn drop(&mut self) {\n        println!(\"closing file\");\n    }\n}\n",[32,984,985,994,1016,1020,1024,1037,1054,1066,1070],{"__ignoreMap":30},[35,986,987,989,992],{"class":37,"line":38},[35,988,252],{"class":41},[35,990,991],{"class":52}," FileGuard",[35,993,473],{"class":45},[35,995,996,999,1001,1003,1005,1008,1010,1013],{"class":37,"line":72},[35,997,998],{"class":45},"    file",[35,1000,295],{"class":41},[35,1002,418],{"class":52},[35,1004,56],{"class":41},[35,1006,1007],{"class":52},"fs",[35,1009,56],{"class":41},[35,1011,1012],{"class":52},"File",[35,1014,1015],{"class":45},",\n",[35,1017,1018],{"class":37,"line":88},[35,1019,560],{"class":45},[35,1021,1022],{"class":37,"line":109},[35,1023,281],{"emptyLinePlaceholder":153},[35,1025,1026,1028,1031,1033,1035],{"class":37,"line":125},[35,1027,457],{"class":41},[35,1029,1030],{"class":52}," Drop",[35,1032,468],{"class":41},[35,1034,991],{"class":52},[35,1036,473],{"class":45},[35,1038,1039,1041,1044,1046,1048,1051],{"class":37,"line":476},[35,1040,479],{"class":41},[35,1042,1043],{"class":52}," drop",[35,1045,62],{"class":45},[35,1047,643],{"class":41},[35,1049,1050],{"class":119}," self",[35,1052,1053],{"class":45},") {\n",[35,1055,1056,1059,1061,1064],{"class":37,"line":518},[35,1057,1058],{"class":52},"        println!",[35,1060,62],{"class":45},[35,1062,1063],{"class":65},"\"closing file\"",[35,1065,263],{"class":45},[35,1067,1068],{"class":37,"line":551},[35,1069,554],{"class":45},[35,1071,1072],{"class":37,"line":557},[35,1073,560],{"class":45},[141,1075,1077,1095,1110,1118],{"className":1076},[144],[146,1078,1080,1082,1083,1086,1087,1090,1091,1094],{"className":1079},[149],[151,1081],{"disabled":153,"type":154}," Cleanup code in ",[32,1084,1085],{},"drop()"," runs automatically when the value goes out of scope, whether via normal control flow, an early ",[32,1088,1089],{},"return",", or an unwinding panic (barring ",[32,1092,1093],{},"std::mem::forget"," or a process abort)",[146,1096,1098,363,1100,1102,1103,1106,1107],{"className":1097},[149],[151,1099],{"disabled":153,"type":154},[32,1101,1085],{}," only runs if the program exits normally via ",[32,1104,1105],{},"main"," returning ",[32,1108,1109],{},"Ok(())",[146,1111,1113,363,1115,1117],{"className":1112},[149],[151,1114],{"disabled":153,"type":154},[32,1116,1085],{}," must be called manually by the programmer; Rust does not call it automatically",[146,1119,1121,363,1123,1125,1126],{"className":1120},[149],[151,1122],{"disabled":153,"type":154},[32,1124,1085],{}," runs at a nondeterministic time chosen by the garbage collector, similar to Java's ",[32,1127,1128],{},"finalize()",[191,1130,1131,1133,1145],{},[194,1132,196],{},[198,1134,1135,1137,1138,1140,1141,1144],{},[201,1136,203],{}," A — ",[32,1139,1085],{}," runs automatically at scope exit through normal flow, early return, or unwinding, with only ",[32,1142,1143],{},"mem::forget","\u002Fabort as exceptions",[198,1146,1147,363,1149,1151,1152,1154,1155,1158,1159,1161,1162,1165,1166,1106,1168,1171,1172,1175,1176,1179,1180,1182],{},[201,1148,211],{},[201,1150,366],{}," Rust has deterministic, scope-based destruction (no garbage collector) — the compiler inserts a call to ",[32,1153,1085],{}," at every point a value's owning scope ends, including early returns and (during unwinding, not ",[32,1156,1157],{},"panic = \"abort\""," builds) stack unwinding from a panic, which is what makes RAII reliable for releasing locks, closing files, and flushing buffers even in error paths. The two real escape hatches are ",[32,1160,1093],{}," (explicitly suppresses the drop) and process abort\u002F",[32,1163,1164],{},"SIGKILL"," (no unwinding happens at all). It is not tied to ",[32,1167,1105],{},[32,1169,1170],{},"Ok",", is very much automatic (that's the entire point of RAII — no explicit ",[32,1173,1174],{},".close()"," call needed, unlike C's manual ",[32,1177,1178],{},"fclose","), and has nothing to do with garbage collection or Java's notoriously non-deterministic, sometimes-never-called ",[32,1181,1128],{}," — Rust's timing is fully deterministic and scope-derived.",[14,1184,1185,1189,1389,1433],{"language":16},[18,1186,1188],{"id":1187},"q6-in-the-visitor-pattern-implemented-via-a-rust-enum-rather-than-the-classic-oop-double-dispatch-visitor-how-is-visiting-different-node-types-typically-expressed","Q6. In the visitor pattern implemented via a Rust enum (rather than the classic OOP double-dispatch visitor), how is \"visiting different node types\" typically expressed?",[23,1190,1191],{"language":16},[26,1192,1194],{"className":28,"code":1193,"language":16,"meta":30,"style":30},"enum Expr {\n    Num(f64),\n    Add(Box\u003CExpr>, Box\u003CExpr>),\n    Mul(Box\u003CExpr>, Box\u003CExpr>),\n}\n\nfn eval(e: &Expr) -> f64 {\n    match e {\n        Expr::Num(n) => *n,\n        Expr::Add(l, r) => eval(l) + eval(r),\n        Expr::Mul(l, r) => eval(l) * eval(r),\n    }\n}\n",[32,1195,1196,1206,1218,1245,1268,1272,1276,1301,1309,1331,1357,1381,1385],{"__ignoreMap":30},[35,1197,1198,1201,1204],{"class":37,"line":38},[35,1199,1200],{"class":41},"enum",[35,1202,1203],{"class":52}," Expr",[35,1205,473],{"class":45},[35,1207,1208,1211,1213,1215],{"class":37,"line":72},[35,1209,1210],{"class":52},"    Num",[35,1212,62],{"class":45},[35,1214,260],{"class":52},[35,1216,1217],{"class":45},"),\n",[35,1219,1220,1223,1225,1228,1230,1233,1236,1238,1240,1242],{"class":37,"line":88},[35,1221,1222],{"class":52},"    Add",[35,1224,62],{"class":45},[35,1226,1227],{"class":52},"Box",[35,1229,442],{"class":45},[35,1231,1232],{"class":52},"Expr",[35,1234,1235],{"class":45},">, ",[35,1237,1227],{"class":52},[35,1239,442],{"class":45},[35,1241,1232],{"class":52},[35,1243,1244],{"class":45},">),\n",[35,1246,1247,1250,1252,1254,1256,1258,1260,1262,1264,1266],{"class":37,"line":109},[35,1248,1249],{"class":52},"    Mul",[35,1251,62],{"class":45},[35,1253,1227],{"class":52},[35,1255,442],{"class":45},[35,1257,1232],{"class":52},[35,1259,1235],{"class":45},[35,1261,1227],{"class":52},[35,1263,442],{"class":45},[35,1265,1232],{"class":52},[35,1267,1244],{"class":45},[35,1269,1270],{"class":37,"line":125},[35,1271,560],{"class":45},[35,1273,1274],{"class":37,"line":476},[35,1275,281],{"emptyLinePlaceholder":153},[35,1277,1278,1280,1283,1286,1288,1290,1292,1294,1296,1299],{"class":37,"line":518},[35,1279,286],{"class":41},[35,1281,1282],{"class":52}," eval",[35,1284,1285],{"class":45},"(e",[35,1287,295],{"class":41},[35,1289,763],{"class":41},[35,1291,1232],{"class":52},[35,1293,300],{"class":45},[35,1295,303],{"class":41},[35,1297,1298],{"class":52}," f64",[35,1300,473],{"class":45},[35,1302,1303,1306],{"class":37,"line":551},[35,1304,1305],{"class":41},"    match",[35,1307,1308],{"class":45}," e {\n",[35,1310,1311,1314,1316,1319,1322,1325,1328],{"class":37,"line":557},[35,1312,1313],{"class":52},"        Expr",[35,1315,56],{"class":41},[35,1317,1318],{"class":52},"Num",[35,1320,1321],{"class":45},"(n) ",[35,1323,1324],{"class":41},"=>",[35,1326,1327],{"class":41}," *",[35,1329,1330],{"class":45},"n,\n",[35,1332,1333,1335,1337,1339,1342,1344,1346,1349,1352,1354],{"class":37,"line":804},[35,1334,1313],{"class":52},[35,1336,56],{"class":41},[35,1338,344],{"class":52},[35,1340,1341],{"class":45},"(l, r) ",[35,1343,1324],{"class":41},[35,1345,1282],{"class":52},[35,1347,1348],{"class":45},"(l) ",[35,1350,1351],{"class":41},"+",[35,1353,1282],{"class":52},[35,1355,1356],{"class":45},"(r),\n",[35,1358,1359,1361,1363,1366,1368,1370,1372,1374,1377,1379],{"class":37,"line":809},[35,1360,1313],{"class":52},[35,1362,56],{"class":41},[35,1364,1365],{"class":52},"Mul",[35,1367,1341],{"class":45},[35,1369,1324],{"class":41},[35,1371,1282],{"class":52},[35,1373,1348],{"class":45},[35,1375,1376],{"class":41},"*",[35,1378,1282],{"class":52},[35,1380,1356],{"class":45},[35,1382,1383],{"class":37,"line":814},[35,1384,554],{"class":45},[35,1386,1387],{"class":37,"line":827},[35,1388,560],{"class":45},[141,1390,1392,1404,1414,1427],{"className":1391},[144],[146,1393,1395,1397,1398,1400,1401,1403],{"className":1394},[149],[151,1396],{"disabled":153,"type":154}," An exhaustive ",[32,1399,895],{}," over the enum's variants, where the compiler enforces that every variant is handled — new variants force every existing ",[32,1402,895],{}," to be updated or fail to compile",[146,1405,1407,1409,1410,1413],{"className":1406},[149],[151,1408],{"disabled":153,"type":154}," A separate ",[32,1411,1412],{},"Visitor"," trait with one method per variant is mandatory; enums cannot be visited without it",[146,1415,1417,1419,1420,1423,1424],{"className":1416},[149],[151,1418],{"disabled":153,"type":154}," Dynamic dispatch through ",[32,1421,1422],{},"Box\u003Cdyn Any>"," and runtime type-checking via ",[32,1425,1426],{},"downcast_ref",[146,1428,1430,1432],{"className":1429},[149],[151,1431],{"disabled":153,"type":154}," Enums cannot express the visitor pattern in Rust; only trait objects can",[191,1434,1435,1437,1445],{},[194,1436,196],{},[198,1438,1439,1441,1442,1444],{},[201,1440,203],{}," A — an exhaustive ",[32,1443,895],{},", with the compiler enforcing every variant is handled",[198,1446,1447,363,1449,1451,1452,1454,1455,1457,1458,1460,1461,1465,1466,1468,1469,1471,1472,1475,1476,1479],{},[201,1448,211],{},[201,1450,620],{}," Rust's enums plus exhaustive ",[32,1453,895],{}," give you the visitor pattern's core benefit (dispatch based on concrete node kind) without needing the classic double-dispatch machinery OOP languages use to work around lacking sum types — and critically, adding a new ",[32,1456,1232],{}," variant makes every non-wildcard ",[32,1459,895],{}," across the codebase a compile error until updated, which is a ",[1462,1463,1464],"em",{},"stronger"," guarantee than the classic visitor pattern's ",[32,1467,1412],{}," trait (where forgetting to implement a new visit method for a new node type is usually just a silent no-op or an easy-to-miss default). A separate ",[32,1470,1412],{}," trait is a valid ",[1462,1473,1474],{},"alternative"," implementation style (useful when the set of \"visitors\"\u002Foperations grows faster than the set of node types), not a requirement — enums alone are sufficient and commonly used exactly this way (e.g. rustc's own AST handling). ",[32,1477,1478],{},"dyn Any"," downcasting throws away compile-time exhaustiveness checking entirely and is not idiomatic here.",[14,1481,1482,1496,1541],{},[18,1483,1485,1486,1488,1489,1492,1493,1495],{"id":1484},"q7-why-might-a-codebase-choose-the-classic-trait-based-visitor-pattern-a-visitor-trait-with-a-visit_-method-per-node-type-over-a-plain-match-based-enum-approach-for-an-ast","Q7. Why might a codebase choose the classic trait-based visitor pattern (a ",[32,1487,1412],{}," trait with a ",[32,1490,1491],{},"visit_*"," method per node type) over a plain ",[32,1494,895],{},"-based enum approach for an AST?",[141,1497,1499,1515,1524,1532],{"className":1498},[144],[146,1500,1502,1504,1505,1508,1509,1512,1513],{"className":1501},[149],[151,1503],{"disabled":153,"type":154}," When new ",[1462,1506,1507],{},"operations"," over the AST are added frequently but the set of node ",[1462,1510,1511],{},"types"," is stable — the trait-based visitor makes adding an operation a matter of writing one new impl, rather than editing every existing ",[32,1514,895],{},[146,1516,1518,1520,1521,1523],{"className":1517},[149],[151,1519],{"disabled":153,"type":154}," The trait-based visitor is strictly faster at runtime in all cases due to avoiding ",[32,1522,895],{}," branch prediction misses",[146,1525,1527,363,1529,1531],{"className":1526},[149],[151,1528],{"disabled":153,"type":154},[32,1530,895],{},"-based enums cannot support recursive tree structures at all",[146,1533,1535,1537,1538,1540],{"className":1534},[149],[151,1536],{"disabled":153,"type":154}," There's no reason to ever prefer it — ",[32,1539,895],{},"-based enums are strictly superior in every scenario",[191,1542,1543,1545,1552],{},[194,1544,196],{},[198,1546,1547,1549,1550],{},[201,1548,203],{}," A — when operations grow faster than node types, trait-based visitors avoid editing every existing ",[32,1551,895],{},[198,1553,1554,363,1556,1558,1559,1561,1562,1565,1566,1569,1570,1573,1574,1576,1577,1579,1580,1582,1583,1585,1586,394,1588,1591,1592,1594],{},[201,1555,211],{},[201,1557,620],{}," This is the classic \"expression problem\" trade-off: enum + ",[32,1560,895],{}," makes adding a new ",[1462,1563,1564],{},"node type"," force-update every match site (good when types are the axis of change, as in Q6), while trait-based visitor makes adding a new ",[1462,1567,1568],{},"operation"," (a new ",[32,1571,1572],{},"impl Visitor",") require zero changes to existing code, at the cost of adding a new ",[1462,1575,1564],{}," now requiring updates across every existing ",[32,1578,1412],{}," implementor. Neither is \"strictly superior\" — the right choice depends on which axis (types vs. operations) changes more often in that codebase. There's no inherent, universal runtime performance advantage to virtual dispatch over a ",[32,1581,895],{}," (a ",[32,1584,895],{}," on a fieldless discriminant is typically a fast jump table, often faster than a vtable call), and enums recurse over trees perfectly well via ",[32,1587,1227],{},[32,1589,1590],{},"Rc"," indirection, as shown in Q6's ",[32,1593,1232],{}," — recursion is not a limitation of the enum approach.",[14,1596,1597,1612,1767,1813],{"language":16},[18,1598,1600,1601,1604,1605,1607,1608,1611],{"id":1599},"q8-a-config-struct-has-8-optional-fields-most-with-sensible-defaults-what-happens-if-a-builders-build-method-is-called-before-any-required-fields-say-api_key-are-set","Q8. A ",[32,1602,1603],{},"Config"," struct has 8 optional fields, most with sensible defaults. What happens if a builder's ",[32,1606,166],{}," method is called before any required fields (say, ",[32,1609,1610],{},"api_key",") are set?",[23,1613,1614],{"language":16},[26,1615,1617],{"className":28,"code":1616,"language":16,"meta":30,"style":30},"struct ConfigBuilder {\n    api_key: Option\u003CString>,\n    timeout: u64,\n}\n\nimpl ConfigBuilder {\n    fn build(self) -> Result\u003CConfig, BuildError> {\n        let api_key = self.api_key.ok_or(BuildError::MissingApiKey)?;\n        Ok(Config { api_key, timeout: self.timeout })\n    }\n}\n",[32,1618,1619,1628,1644,1656,1660,1664,1672,1701,1738,1759,1763],{"__ignoreMap":30},[35,1620,1621,1623,1626],{"class":37,"line":38},[35,1622,252],{"class":41},[35,1624,1625],{"class":52}," ConfigBuilder",[35,1627,473],{"class":45},[35,1629,1630,1633,1635,1638,1640,1642],{"class":37,"line":72},[35,1631,1632],{"class":45},"    api_key",[35,1634,295],{"class":41},[35,1636,1637],{"class":52}," Option",[35,1639,442],{"class":45},[35,1641,445],{"class":52},[35,1643,723],{"class":45},[35,1645,1646,1649,1651,1654],{"class":37,"line":88},[35,1647,1648],{"class":45},"    timeout",[35,1650,295],{"class":41},[35,1652,1653],{"class":52}," u64",[35,1655,1015],{"class":45},[35,1657,1658],{"class":37,"line":109},[35,1659,560],{"class":45},[35,1661,1662],{"class":37,"line":125},[35,1663,281],{"emptyLinePlaceholder":153},[35,1665,1666,1668,1670],{"class":37,"line":476},[35,1667,457],{"class":41},[35,1669,1625],{"class":52},[35,1671,473],{"class":45},[35,1673,1674,1676,1679,1681,1683,1685,1687,1690,1692,1694,1696,1699],{"class":37,"line":518},[35,1675,479],{"class":41},[35,1677,1678],{"class":52}," build",[35,1680,62],{"class":45},[35,1682,158],{"class":119},[35,1684,300],{"class":45},[35,1686,303],{"class":41},[35,1688,1689],{"class":52}," Result",[35,1691,442],{"class":45},[35,1693,1603],{"class":52},[35,1695,101],{"class":45},[35,1697,1698],{"class":52},"BuildError",[35,1700,697],{"class":45},[35,1702,1703,1706,1709,1711,1713,1715,1717,1719,1722,1724,1726,1728,1731,1734,1736],{"class":37,"line":551},[35,1704,1705],{"class":41},"        let",[35,1707,1708],{"class":45}," api_key ",[35,1710,49],{"class":41},[35,1712,1050],{"class":119},[35,1714,534],{"class":41},[35,1716,1610],{"class":45},[35,1718,534],{"class":41},[35,1720,1721],{"class":52},"ok_or",[35,1723,62],{"class":45},[35,1725,1698],{"class":52},[35,1727,56],{"class":41},[35,1729,1730],{"class":52},"MissingApiKey",[35,1732,1733],{"class":45},")",[35,1735,136],{"class":41},[35,1737,139],{"class":45},[35,1739,1740,1743,1745,1747,1750,1752,1754,1756],{"class":37,"line":557},[35,1741,1742],{"class":52},"        Ok",[35,1744,62],{"class":45},[35,1746,1603],{"class":52},[35,1748,1749],{"class":45}," { api_key, timeout",[35,1751,295],{"class":41},[35,1753,1050],{"class":119},[35,1755,534],{"class":41},[35,1757,1758],{"class":45},"timeout })\n",[35,1760,1761],{"class":37,"line":804},[35,1762,554],{"class":45},[35,1764,1765],{"class":37,"line":809},[35,1766,560],{"class":45},[141,1768,1770,1782,1790,1803],{"className":1769},[144],[146,1771,1773,363,1775,1777,1778,1781],{"className":1772},[149],[151,1774],{"disabled":153,"type":154},[32,1776,166],{}," returns ",[32,1779,1780],{},"Err(BuildError::MissingApiKey)",", since the required field was validated and found absent — this is the idiomatic way to surface missing-required-field errors without a panic",[146,1783,1785,363,1787,1789],{"className":1784},[149],[151,1786],{"disabled":153,"type":154},[32,1788,166],{}," panics immediately with an \"unwrap on None\" message",[146,1791,1793,363,1795,1797,1798,1800,1801],{"className":1792},[149],[151,1794],{"disabled":153,"type":154},[32,1796,166],{}," silently substitutes an empty string for ",[32,1799,1610],{}," and returns ",[32,1802,1170],{},[146,1804,1806,1808,1809,1812],{"className":1805},[149],[151,1807],{"disabled":153,"type":154}," This code fails to compile because ",[32,1810,1811],{},"Option\u003CString>"," can't be used inside a builder struct",[191,1814,1815,1817,1826],{},[194,1816,196],{},[198,1818,1819,1137,1821,1777,1823,1825],{},[201,1820,203],{},[32,1822,166],{},[32,1824,1780],{},", the idiomatic way to surface a missing required field",[198,1827,1828,1830,1831,1834,1835,1837,1838,1840,1841,1843,1844,1847,1848,1850,1851,1854,1855,1857],{},[201,1829,211],{}," Using ",[32,1832,1833],{},".ok_or(...)?"," converts the ",[32,1836,1811],{}," into a ",[32,1839,222],{},", propagating a descriptive error rather than panicking — this is exactly why ",[32,1842,166],{}," idiomatically returns ",[32,1845,1846],{},"Result\u003CConfig, BuildError>"," instead of ",[32,1849,1603],{}," directly, letting callers handle missing-configuration errors gracefully (e.g. surfacing a helpful message) instead of crashing. It does not panic (there's no ",[32,1852,1853],{},".unwrap()"," anywhere in this path), does not silently default a security-sensitive field like an API key to empty string (that would be a dangerous silent failure mode, not idiomatic error handling), and ",[32,1856,1811],{}," inside a plain struct is completely ordinary, valid Rust with no compile issue.",[14,1859,1860,1864,1944,1996],{"language":16},[18,1861,1863],{"id":1862},"q9-what-happens-when-a-typestate-encoded-value-is-used-after-a-state-transitioning-method-has-consumed-it","Q9. What happens when a typestate-encoded value is used after a state-transitioning method has consumed it?",[23,1865,1866],{"language":16},[26,1867,1869],{"className":28,"code":1868,"language":16,"meta":30,"style":30},"let door = Door::\u003CLocked> { _state: std::marker::PhantomData };\nlet unlocked = door.unlock(\"1234\");\ndoor.unlock(\"1234\");\n",[32,1870,1871,1906,1929],{"__ignoreMap":30},[35,1872,1873,1875,1878,1880,1882,1884,1886,1888,1891,1893,1895,1897,1899,1901,1903],{"class":37,"line":38},[35,1874,42],{"class":41},[35,1876,1877],{"class":45}," door ",[35,1879,49],{"class":41},[35,1881,689],{"class":52},[35,1883,56],{"class":41},[35,1885,442],{"class":45},[35,1887,742],{"class":52},[35,1889,1890],{"class":45},"> { _state",[35,1892,295],{"class":41},[35,1894,418],{"class":52},[35,1896,56],{"class":41},[35,1898,711],{"class":52},[35,1900,56],{"class":41},[35,1902,716],{"class":52},[35,1904,1905],{"class":45}," };\n",[35,1907,1908,1910,1913,1915,1918,1920,1922,1924,1927],{"class":37,"line":72},[35,1909,42],{"class":41},[35,1911,1912],{"class":45}," unlocked ",[35,1914,49],{"class":41},[35,1916,1917],{"class":45}," door",[35,1919,534],{"class":41},[35,1921,944],{"class":52},[35,1923,62],{"class":45},[35,1925,1926],{"class":65},"\"1234\"",[35,1928,263],{"class":45},[35,1930,1931,1934,1936,1938,1940,1942],{"class":37,"line":88},[35,1932,1933],{"class":45},"door",[35,1935,534],{"class":41},[35,1937,944],{"class":52},[35,1939,62],{"class":45},[35,1941,1926],{"class":65},[35,1943,263],{"class":45},[141,1945,1947,1966,1975,1981],{"className":1946},[144],[146,1948,1950,1952,1953,1955,1956,1958,1959,1961,1962,1965],{"className":1949},[149],[151,1951],{"disabled":153,"type":154}," Compile error — ",[32,1954,944],{}," takes ",[32,1957,158],{}," by value, so ",[32,1960,1933],{}," is moved into the first call; the second ",[32,1963,1964],{},"door.unlock(...)"," is a use-after-move error",[146,1967,1969,1971,1972,1974],{"className":1968},[149],[151,1970],{"disabled":153,"type":154}," Both calls succeed; ",[32,1973,1933],{}," is implicitly cloned since it's a zero-sized type",[146,1976,1978,1980],{"className":1977},[149],[151,1979],{"disabled":153,"type":154}," The second call panics at runtime with \"use of moved value\"",[146,1982,1984,363,1986,1988,1989,1991,1992,1995],{"className":1983},[149],[151,1985],{"disabled":153,"type":154},[32,1987,1933],{}," is automatically re-locked and re-usable since ",[32,1990,783],{}," implements ",[32,1993,1994],{},"Copy"," by default",[191,1997,1998,2000,2012],{},[194,1999,196],{},[198,2001,2002,2004,2005,2008,2009,2011],{},[201,2003,203],{}," A — compile error; ",[32,2006,2007],{},"unlock(self)"," moves ",[32,2010,1933],{},", so the second call is a use-after-move",[198,2013,2014,363,2016,2018,2019,2021,2022,394,2025,2027,2028,2030,2031,2034,2035,2037,2038,2040,2041,2043,2044,2046,2047,2049,2050,2053],{},[201,2015,211],{},[201,2017,366],{}," This is precisely why typestate methods take ",[32,2020,158],{}," by value rather than ",[32,2023,2024],{},"&self",[32,2026,162],{}," — consuming ",[32,2029,158],{}," guarantees the ",[1462,2032,2033],{},"old","-state value cannot be reused after transitioning, which is what makes a state transition genuinely one-way and irreversible at compile time (you can't accidentally \"unlock an already-consumed door twice\"). The borrow checker rejects the second ",[32,2036,1964],{}," at compile time with a \"use of moved value\" error — this is a compile-time diagnostic, never a runtime panic, since move-checking has no runtime component. Structs are never implicitly ",[32,2039,1994],{}," by default in Rust (it must be explicitly derived and is only valid when every field is ",[32,2042,1994],{},"), and even a zero-sized ",[32,2045,716],{},"-only struct doesn't get free ",[32,2048,1994],{}," without ",[32,2051,2052],{},"#[derive(Copy, Clone)]"," explicitly opting in.",[14,2055,2056,2066,2128,2164],{"language":16},[18,2057,2059,2060,2062,2063,2065],{"id":2058},"q10-in-a-drop-implementation-what-happens-if-drop-itself-panics-while-the-program-is-already-unwinding-from-a-prior-panic-ie-a-double-panic","Q10. In a ",[32,2061,976],{}," implementation, what happens if ",[32,2064,1085],{}," itself panics while the program is already unwinding from a prior panic (i.e. a \"double panic\")?",[23,2067,2068],{"language":16},[26,2069,2071],{"className":28,"code":2070,"language":16,"meta":30,"style":30},"struct Noisy;\nimpl Drop for Noisy {\n    fn drop(&mut self) {\n        panic!(\"dropped during unwind\");\n    }\n}\n",[32,2072,2073,2082,2094,2108,2120,2124],{"__ignoreMap":30},[35,2074,2075,2077,2080],{"class":37,"line":38},[35,2076,252],{"class":41},[35,2078,2079],{"class":52}," Noisy",[35,2081,139],{"class":45},[35,2083,2084,2086,2088,2090,2092],{"class":37,"line":72},[35,2085,457],{"class":41},[35,2087,1030],{"class":52},[35,2089,468],{"class":41},[35,2091,2079],{"class":52},[35,2093,473],{"class":45},[35,2095,2096,2098,2100,2102,2104,2106],{"class":37,"line":88},[35,2097,479],{"class":41},[35,2099,1043],{"class":52},[35,2101,62],{"class":45},[35,2103,643],{"class":41},[35,2105,1050],{"class":119},[35,2107,1053],{"class":45},[35,2109,2110,2113,2115,2118],{"class":37,"line":109},[35,2111,2112],{"class":52},"        panic!",[35,2114,62],{"class":45},[35,2116,2117],{"class":65},"\"dropped during unwind\"",[35,2119,263],{"class":45},[35,2121,2122],{"class":37,"line":125},[35,2123,554],{"class":45},[35,2125,2126],{"class":37,"line":476},[35,2127,560],{"class":45},[141,2129,2131,2137,2143,2149],{"className":2130},[144],[146,2132,2134,2136],{"className":2133},[149],[151,2135],{"disabled":153,"type":154}," The process aborts immediately — Rust cannot unwind through two simultaneous panics, so this becomes a hard abort instead of a normal panic-and-recover",[146,2138,2140,2142],{"className":2139},[149],[151,2141],{"disabled":153,"type":154}," The second panic is silently swallowed and unwinding continues normally",[146,2144,2146,2148],{"className":2145},[149],[151,2147],{"disabled":153,"type":154}," The second panic simply replaces the first, and the program continues as if only one panic occurred",[146,2150,2152,363,2154,2157,2158,2160,2161],{"className":2151},[149],[151,2153],{"disabled":153,"type":154},[32,2155,2156],{},"Drop::drop"," cannot panic; the compiler rejects any ",[32,2159,1085],{}," body containing ",[32,2162,2163],{},"panic!",[191,2165,2166,2168,2173],{},[194,2167,196],{},[198,2169,2170,2172],{},[201,2171,203],{}," A — the process aborts immediately; Rust cannot unwind through two simultaneous panics",[198,2174,2175,363,2177,2180,2181,2183,2184,2187,2188,2190,2191,2193,2194,2196,2197,2199],{},[201,2176,211],{},[201,2178,2179],{},"Safety\u002FDebug:"," If a ",[32,2182,1085],{}," runs as part of unwinding from an earlier panic and itself panics, Rust has no defined way to unwind two panics at once through the same stack, so the runtime immediately calls ",[32,2185,2186],{},"abort()"," — no further cleanup, no graceful shutdown, process terminates hard. This is a production-relevant gotcha: ",[32,2189,976],{}," implementations should avoid any code that can panic (avoid ",[32,2192,1853],{},", indexing, arithmetic that can overflow in debug mode, etc.), preferring to log-and-continue or use fallible alternatives, precisely because a panicking destructor during unwinding is one of the few ways to lose the ability to gracefully report an error at all. The compiler does not reject ",[32,2195,2163],{}," inside ",[32,2198,1085],{}," — it's syntactically and semantically legal, just dangerous in this specific double-unwind scenario; the double-panic-aborts behavior is a hard runtime rule, not something silently absorbed or overwritten.",[14,2201,2202,2210,2333,2390],{"language":16},[18,2203,2205,2206,2209],{"id":2204},"q11-a-struct-wraps-a-vecu8-as-a-newtype-to-represent-a-validated-non-empty-buffer-what-is-the-most-common-mistake-that-defeats-the-purpose-of-this-newtype","Q11. A struct wraps a ",[32,2207,2208],{},"Vec\u003Cu8>"," as a newtype to represent a validated, non-empty buffer. What is the most common mistake that defeats the purpose of this newtype?",[23,2211,2212],{"language":16},[26,2213,2215],{"className":28,"code":2214,"language":16,"meta":30,"style":30},"pub struct NonEmptyBuffer(Vec\u003Cu8>);\n\nimpl NonEmptyBuffer {\n    pub fn new(data: Vec\u003Cu8>) -> Option\u003CSelf> {\n        if data.is_empty() { None } else { Some(Self(data)) }\n    }\n}\n",[32,2216,2217,2239,2243,2251,2288,2325,2329],{"__ignoreMap":30},[35,2218,2219,2222,2225,2228,2230,2232,2234,2237],{"class":37,"line":38},[35,2220,2221],{"class":41},"pub",[35,2223,2224],{"class":41}," struct",[35,2226,2227],{"class":52}," NonEmptyBuffer",[35,2229,62],{"class":45},[35,2231,439],{"class":52},[35,2233,442],{"class":45},[35,2235,2236],{"class":52},"u8",[35,2238,448],{"class":45},[35,2240,2241],{"class":37,"line":72},[35,2242,281],{"emptyLinePlaceholder":153},[35,2244,2245,2247,2249],{"class":37,"line":88},[35,2246,457],{"class":41},[35,2248,2227],{"class":52},[35,2250,473],{"class":45},[35,2252,2253,2256,2259,2262,2265,2267,2270,2272,2274,2277,2279,2281,2283,2286],{"class":37,"line":109},[35,2254,2255],{"class":41},"    pub",[35,2257,2258],{"class":41}," fn",[35,2260,2261],{"class":52}," new",[35,2263,2264],{"class":45},"(data",[35,2266,295],{"class":41},[35,2268,2269],{"class":52}," Vec",[35,2271,442],{"class":45},[35,2273,2236],{"class":52},[35,2275,2276],{"class":45},">) ",[35,2278,303],{"class":41},[35,2280,1637],{"class":52},[35,2282,442],{"class":45},[35,2284,2285],{"class":119},"Self",[35,2287,697],{"class":45},[35,2289,2290,2293,2296,2298,2301,2304,2307,2310,2312,2315,2318,2320,2322],{"class":37,"line":125},[35,2291,2292],{"class":41},"        if",[35,2294,2295],{"class":45}," data",[35,2297,534],{"class":41},[35,2299,2300],{"class":52},"is_empty",[35,2302,2303],{"class":45},"() { ",[35,2305,2306],{"class":52},"None",[35,2308,2309],{"class":45}," } ",[35,2311,908],{"class":41},[35,2313,2314],{"class":45}," { ",[35,2316,2317],{"class":52},"Some",[35,2319,62],{"class":45},[35,2321,2285],{"class":119},[35,2323,2324],{"class":45},"(data)) }\n",[35,2326,2327],{"class":37,"line":476},[35,2328,554],{"class":45},[35,2330,2331],{"class":37,"line":518},[35,2332,560],{"class":45},[141,2334,2336,2357,2369,2379],{"className":2335},[144],[146,2337,2339,2341,2342,2344,2345,2348,2349,2352,2353,2356],{"className":2338},[149],[151,2340],{"disabled":153,"type":154}," Leaving the tuple field ",[32,2343,2208],{}," public (",[32,2346,2347],{},"pub Vec\u003Cu8>"," instead of a private field), which lets any caller construct ",[32,2350,2351],{},"NonEmptyBuffer(vec![])"," directly, bypassing the validating ",[32,2354,2355],{},"new()"," and violating the non-empty invariant",[146,2358,2360,1830,2362,1847,2365,2368],{"className":2359},[149],[151,2361],{"disabled":153,"type":154},[32,2363,2364],{},"Option\u003CSelf>",[32,2366,2367],{},"Result\u003CSelf, Error>"," in the constructor, which is always wrong",[146,2370,2372,2374,2375,2378],{"className":2371},[149],[151,2373],{"disabled":153,"type":154}," Deriving ",[32,2376,2377],{},"Clone"," on the struct, which would allow duplicating the buffer",[146,2380,2382,2384,2385,1847,2387],{"className":2381},[149],[151,2383],{"disabled":153,"type":154}," Naming the constructor ",[32,2386,2355],{},[32,2388,2389],{},"from_vec()",[191,2391,2392,2394,2399],{},[194,2393,196],{},[198,2395,2396,2398],{},[201,2397,203],{}," A — leaving the inner field public lets callers construct the newtype directly, bypassing validation",[198,2400,2401,363,2403,2405,2406,2408,2409,2411,2412,2414,2415,2417,2418,2420,2421,2423,2424,2427,2428,2431,2432,2434,2435,2437,2438,2440,2441,2444],{},[201,2402,211],{},[201,2404,366],{}," The entire value of a \"validated newtype\" (non-empty buffer, positive integer, normalized email, etc.) depends on there being no way to construct one except through the checked constructor — if the tuple field is ",[32,2407,2221],{},", anyone can write ",[32,2410,2351],{}," directly from outside the module, completely bypassing ",[32,2413,2355],{},"'s emptiness check and silently reintroducing the exact bug the type was created to prevent. Keeping the field private (as shown, no ",[32,2416,2221],{}," on ",[32,2419,2208],{},") is what makes ",[32,2422,2355],{}," the ",[1462,2425,2426],{},"only"," construction path. ",[32,2429,2430],{},"Option"," vs ",[32,2433,222],{}," in the constructor is a legitimate, context-dependent API choice (not \"always wrong\" — ",[32,2436,2430],{}," is fine when there's only one failure reason and no extra context to convey). Deriving ",[32,2439,2377],{}," is harmless here — cloning a valid ",[32,2442,2443],{},"NonEmptyBuffer"," produces another valid one, since the invariant (non-empty) is preserved by copying the same data. Constructor naming is a style preference with no soundness implication.",[14,2446,2447,2458,2523,2557],{"language":16},[18,2448,2450,2451,2453,2454,2457],{"id":2449},"q12-a-builders-build-method-is-called-twice-on-the-same-builder-instance-given-standard-consuming-builder-design-fn-buildself-t-what-happens-on-the-second-call","Q12. A builder's ",[32,2452,166],{}," method is called twice on the same builder instance. Given standard consuming-builder design (",[32,2455,2456],{},"fn build(self) -> T","), what happens on the second call?",[23,2459,2460],{"language":16},[26,2461,2463],{"className":28,"code":2462,"language":16,"meta":30,"style":30},"let builder = RequestBuilder::new(\"url\");\nlet req1 = builder.build();\nlet req2 = builder.build();\n",[32,2464,2465,2487,2506],{"__ignoreMap":30},[35,2466,2467,2469,2472,2474,2476,2478,2480,2482,2485],{"class":37,"line":38},[35,2468,42],{"class":41},[35,2470,2471],{"class":45}," builder ",[35,2473,49],{"class":41},[35,2475,53],{"class":52},[35,2477,56],{"class":41},[35,2479,59],{"class":52},[35,2481,62],{"class":45},[35,2483,2484],{"class":65},"\"url\"",[35,2486,263],{"class":45},[35,2488,2489,2491,2494,2496,2499,2501,2503],{"class":37,"line":72},[35,2490,42],{"class":41},[35,2492,2493],{"class":45}," req1 ",[35,2495,49],{"class":41},[35,2497,2498],{"class":45}," builder",[35,2500,534],{"class":41},[35,2502,130],{"class":52},[35,2504,2505],{"class":45},"();\n",[35,2507,2508,2510,2513,2515,2517,2519,2521],{"class":37,"line":88},[35,2509,42],{"class":41},[35,2511,2512],{"class":45}," req2 ",[35,2514,49],{"class":41},[35,2516,2498],{"class":45},[35,2518,534],{"class":41},[35,2520,130],{"class":52},[35,2522,2505],{"class":45},[141,2524,2526,2539,2545,2551],{"className":2525},[144],[146,2527,2529,1952,2531,2534,2535,2538],{"className":2528},[149],[151,2530],{"disabled":153,"type":154},[32,2532,2533],{},"build(self)"," consumes the builder by value on the first call, making ",[32,2536,2537],{},"builder"," unavailable for the second call (use-after-move)",[146,2540,2542,2544],{"className":2541},[149],[151,2543],{"disabled":153,"type":154}," Both calls succeed and produce two independent, identically-configured requests",[146,2546,2548,2550],{"className":2547},[149],[151,2549],{"disabled":153,"type":154}," The second call returns a default-constructed, empty request instead of erroring",[146,2552,2554,2556],{"className":2553},[149],[151,2555],{"disabled":153,"type":154}," It compiles, but the second call panics at runtime with \"builder already consumed\"",[191,2558,2559,2561,2568],{},[194,2560,196],{},[198,2562,2563,2004,2565,2567],{},[201,2564,203],{},[32,2566,2533],{}," moves the builder, so calling it twice is a use-after-move caught at compile time",[198,2569,2570,363,2572,2574,2575,2577,2578,2580,2581,2584,2585,2587,2588,2590,2591,2593,2594,2596,2597,2600],{},[201,2571,211],{},[201,2573,620],{}," Taking ",[32,2576,158],{}," by value in ",[32,2579,166],{}," is a deliberate design choice (not an accident) — it statically enforces \"a builder can only be finalized once,\" turning a whole class of \"did I already call ",[32,2582,2583],{},".build()","?\" bugs into compile errors rather than needing runtime tracking. This is why many builder APIs use ",[32,2586,158],{}," (consuming) rather than ",[32,2589,162],{}," for chained methods that lead into ",[32,2592,166],{},": it composes with move semantics to make double-finalization structurally impossible, exactly analogous to the typestate consumption in Q9. There's no runtime panic path here — the compiler rejects the second call before the program can ever run, and there's no default-empty fallback or implicit duplication; if a caller genuinely needs to build multiple times, the builder type would need to implement ",[32,2595,2377],{}," explicitly, or expose ",[32,2598,2599],{},"build(&self)"," instead (a valid alternative design with its own trade-offs, but not what's shown here).",[14,2602,2603,2612,2692,2742],{"language":16},[18,2604,2606,2607,2609,2610,136],{"id":2605},"q13-what-happens-if-a-drop-impl-is-written-for-a-type-that-also-derives-copy","Q13. What happens if a ",[32,2608,976],{}," impl is written for a type that also derives ",[32,2611,1994],{},[23,2613,2614],{"language":16},[26,2615,2617],{"className":28,"code":2616,"language":16,"meta":30,"style":30},"#[derive(Clone, Copy)]\nstruct Point { x: i32, y: i32 }\n\nimpl Drop for Point {\n    fn drop(&mut self) {}\n}\n",[32,2618,2619,2633,2657,2661,2673,2688],{"__ignoreMap":30},[35,2620,2621,2624,2626,2628,2630],{"class":37,"line":38},[35,2622,2623],{"class":45},"#[derive(",[35,2625,2377],{"class":52},[35,2627,101],{"class":45},[35,2629,1994],{"class":52},[35,2631,2632],{"class":45},")]\n",[35,2634,2635,2637,2640,2643,2645,2648,2651,2653,2655],{"class":37,"line":72},[35,2636,252],{"class":41},[35,2638,2639],{"class":52}," Point",[35,2641,2642],{"class":45}," { x",[35,2644,295],{"class":41},[35,2646,2647],{"class":52}," i32",[35,2649,2650],{"class":45},", y",[35,2652,295],{"class":41},[35,2654,2647],{"class":52},[35,2656,864],{"class":45},[35,2658,2659],{"class":37,"line":88},[35,2660,281],{"emptyLinePlaceholder":153},[35,2662,2663,2665,2667,2669,2671],{"class":37,"line":109},[35,2664,457],{"class":41},[35,2666,1030],{"class":52},[35,2668,468],{"class":41},[35,2670,2639],{"class":52},[35,2672,473],{"class":45},[35,2674,2675,2677,2679,2681,2683,2685],{"class":37,"line":125},[35,2676,479],{"class":41},[35,2678,1043],{"class":52},[35,2680,62],{"class":45},[35,2682,643],{"class":41},[35,2684,1050],{"class":119},[35,2686,2687],{"class":45},") {}\n",[35,2689,2690],{"class":37,"line":476},[35,2691,560],{"class":45},[141,2693,2695,2712,2721,2733],{"className":2694},[144],[146,2696,2698,2700,2701,345,2703,2705,2706,2708,2709,2711],{"className":2697},[149],[151,2699],{"disabled":153,"type":154}," This is a compile error — ",[32,2702,1994],{},[32,2704,976],{}," are mutually exclusive on the same type, because ",[32,2707,1994],{}," implies bitwise duplication with no notion of \"the original is now gone,\" which conflicts with ",[32,2710,976],{},"'s single-owner cleanup guarantee",[146,2713,2715,2717,2718,2720],{"className":2714},[149],[151,2716],{"disabled":153,"type":154}," This compiles fine; ",[32,2719,1085],{}," simply runs once per each bitwise copy independently",[146,2722,2724,2726,2727,2729,2730,2732],{"className":2723},[149],[151,2725],{"disabled":153,"type":154}," This compiles, but ",[32,2728,1994],{}," is silently ignored and the type behaves as ",[32,2731,2377],{},"-only",[146,2734,2736,2738,2739,2741],{"className":2735},[149],[151,2737],{"disabled":153,"type":154}," This compiles only if ",[32,2740,2156],{}," is an empty function body, as shown",[191,2743,2744,2746,2755],{},[194,2745,196],{},[198,2747,2748,2004,2750,345,2752,2754],{},[201,2749,203],{},[32,2751,1994],{},[32,2753,976],{}," are mutually exclusive by design",[198,2756,2757,363,2759,363,2761,2763,2764,2766,2767,2770,2771,2774,2775,2778,2779,2781,2782,2784,2785,394,2788,2790],{},[201,2758,211],{},[201,2760,366],{},[32,2762,1994],{}," means assignment\u002Fpassing duplicates the bits with no move semantics — both the \"original\" and the \"copy\" remain simultaneously valid and usable. ",[32,2765,976],{}," is built entirely around Rust's ownership guarantee that a value has exactly one owner responsible for cleanup at scope end. If a type were both, you'd get either a double-free (both bitwise copies' destructors trying to free\u002Frelease the same resource) or an ill-defined \"which copy actually owns the resource\" question — so the compiler flatly rejects ",[32,2768,2769],{},"#[derive(Copy)]"," (or a manual ",[32,2772,2773],{},"impl Copy",") on any type that also ",[32,2776,2777],{},"impl Drop",", regardless of whether the ",[32,2780,1085],{}," body is empty (option D is a red herring: the restriction is structural\u002Ftype-level, not based on the body's contents). This isn't silently downgraded to ",[32,2783,2377],{},"-only either — it's a hard compile error at the ",[32,2786,2787],{},"derive",[32,2789,457],{}," site.",[14,2792,2793,2805,2878,2922],{"language":16},[18,2794,2796,2797,2800,2801,2804],{"id":2795},"q14-a-typestate-api-models-a-network-connection-with-disconnected-connecting-connected-states-a-method-needs-to-handle-the-case-where-connecting-can-fail-and-should-return-to-disconnected-how-is-this-typically-expressed-in-the-return-type","Q14. A typestate API models a network connection with ",[32,2798,2799],{},"Disconnected -> Connecting -> Connected"," states. A method needs to handle the case where connecting can fail and should return to ",[32,2802,2803],{},"Disconnected",". How is this typically expressed in the return type?",[23,2806,2807],{"language":16},[26,2808,2810],{"className":28,"code":2809,"language":16,"meta":30,"style":30},"impl Connection\u003CConnecting> {\n    fn finish(self) -> Result\u003CConnection\u003CConnected>, Connection\u003CDisconnected>> {\n        \u002F\u002F ...\n    }\n}\n",[32,2811,2812,2826,2864,2870,2874],{"__ignoreMap":30},[35,2813,2814,2816,2819,2821,2824],{"class":37,"line":38},[35,2815,457],{"class":41},[35,2817,2818],{"class":52}," Connection",[35,2820,442],{"class":45},[35,2822,2823],{"class":52},"Connecting",[35,2825,697],{"class":45},[35,2827,2828,2830,2833,2835,2837,2839,2841,2843,2845,2848,2850,2853,2855,2857,2859,2861],{"class":37,"line":72},[35,2829,479],{"class":41},[35,2831,2832],{"class":52}," finish",[35,2834,62],{"class":45},[35,2836,158],{"class":119},[35,2838,300],{"class":45},[35,2840,303],{"class":41},[35,2842,1689],{"class":52},[35,2844,442],{"class":45},[35,2846,2847],{"class":52},"Connection",[35,2849,442],{"class":45},[35,2851,2852],{"class":52},"Connected",[35,2854,1235],{"class":45},[35,2856,2847],{"class":52},[35,2858,442],{"class":45},[35,2860,2803],{"class":52},[35,2862,2863],{"class":45},">> {\n",[35,2865,2866],{"class":37,"line":88},[35,2867,2869],{"class":2868},"sdCPZ","        \u002F\u002F ...\n",[35,2871,2872],{"class":37,"line":109},[35,2873,554],{"class":45},[35,2875,2876],{"class":37,"line":125},[35,2877,560],{"class":45},[141,2879,2881,2894,2900,2910],{"className":2880},[144],[146,2882,2884,2886,2887,2890,2891,2893],{"className":2883},[149],[151,2885],{"disabled":153,"type":154}," Return a ",[32,2888,2889],{},"Result\u003CConnection\u003CConnected>, Connection\u003CDisconnected>>"," (or a similar ",[32,2892,222],{},"\u002Fenum of the two possible resulting typestates), so callers must handle both outcomes and the compiler enforces that the returned value's state matches what actually happened",[146,2895,2897,2899],{"className":2896},[149],[151,2898],{"disabled":153,"type":154}," Panic on connection failure, since typestate patterns cannot express fallible transitions",[146,2901,2903,2905,2906,2909],{"className":2902},[149],[151,2904],{"disabled":153,"type":154}," Return ",[32,2907,2908],{},"Connection\u003CConnecting>"," unchanged and let the caller retry indefinitely",[146,2911,2913,2915,2916,2919,2920],{"className":2912},[149],[151,2914],{"disabled":153,"type":154}," Use ",[32,2917,2918],{},"unsafe { std::mem::transmute }"," to force the state type back to ",[32,2921,2803],{},[191,2923,2924,2926,2940],{},[194,2925,196],{},[198,2927,2928,2930,2931,2933,2934,394,2936,2939],{},[201,2929,203],{}," A — return a ",[32,2932,222],{}," (or equivalent) whose ",[32,2935,1170],{},[32,2937,2938],{},"Err"," carry the two possible resulting typestates",[198,2941,2942,363,2944,2946,2947,2950,2951,2953,2954,394,2956,2958,2959,2961,2962,2965,2966,2968],{},[201,2943,211],{},[201,2945,620],{}," Fallible transitions compose naturally with typestate by making the ",[1462,2948,2949],{},"return type itself"," encode \"one of these two states is what you'll get,\" typically via ",[32,2952,2889],{}," or a small enum — the caller is then compiler-forced (via ",[32,2955,895],{},[32,2957,136],{},") to handle both branches, and whichever branch executes hands back a correctly-typed value for that actual state, preserving the whole pattern's compile-time guarantees through the fallible step. Typestate absolutely can express fallible transitions this way — panicking would be a strictly worse design that throws away the ability to recover from an ordinary, expected failure (a network connect timing out is not exceptional). Returning ",[32,2960,2908],{}," unchanged doesn't reflect reality (the state actually changed to failed\u002Fdisconnected) and invites infinite-retry bugs. Using ",[32,2963,2964],{},"transmute"," to force a type back is exactly the kind of unsound hack the entire pattern exists to make unnecessary — legitimate typestate code should never need ",[32,2967,918],{}," to move between states.",[14,2970,2971,2978,3020,3055],{"language":16},[18,2972,2974,2975,136],{"id":2973},"q15-when-is-it-idiomatic-to-use-the-builder-pattern-versus-simply-using-a-struct-literal-with-defaultdefault","Q15. When is it idiomatic to use the builder pattern versus simply using a struct literal with ",[32,2976,2977],{},"..Default::default()",[23,2979,2980],{"language":16},[26,2981,2983],{"className":28,"code":2982,"language":16,"meta":30,"style":30},"let cfg = Config { timeout: 30, ..Default::default() };\n",[32,2984,2985],{"__ignoreMap":30},[35,2986,2987,2989,2992,2994,2997,3000,3002,3005,3007,3010,3012,3014,3017],{"class":37,"line":38},[35,2988,42],{"class":41},[35,2990,2991],{"class":45}," cfg ",[35,2993,49],{"class":41},[35,2995,2996],{"class":52}," Config",[35,2998,2999],{"class":45}," { timeout",[35,3001,295],{"class":41},[35,3003,3004],{"class":119}," 30",[35,3006,101],{"class":45},[35,3008,3009],{"class":41},"..",[35,3011,176],{"class":52},[35,3013,56],{"class":41},[35,3015,3016],{"class":52},"default",[35,3018,3019],{"class":45},"() };\n",[141,3021,3023,3032,3038,3046],{"className":3022},[144],[146,3024,3026,3028,3029,3031],{"className":3025},[149],[151,3027],{"disabled":153,"type":154}," Prefer ",[32,3030,2977],{}," struct-update syntax for simple, all-public-field configs with no cross-field validation needed; reach for a builder when construction needs validation, computed\u002Fderived defaults, required fields enforced at compile time, or a fluent multi-step API",[146,3033,3035,3037],{"className":3034},[149],[151,3036],{"disabled":153,"type":154}," The builder pattern should always be used, even for a two-field public struct, since it's considered more professional",[146,3039,3041,363,3043,3045],{"className":3040},[149],[151,3042],{"disabled":153,"type":154},[32,3044,2977],{}," cannot be combined with named field initialization in the same literal",[146,3047,3049,3051,3052,3054],{"className":3048},[149],[151,3050],{"disabled":153,"type":154}," Builders are strictly for compatibility with older Rust editions; ",[32,3053,2977],{}," fully replaces them in modern code",[191,3056,3057,3059,3067],{},[194,3058,196],{},[198,3060,3061,3063,3064,3066],{},[201,3062,203],{}," A — use ",[32,3065,2977],{}," for simple public-field configs with no validation; use a builder when validation, derived defaults, or required-field enforcement is needed",[198,3068,3069,363,3071,363,3073,3075,3076,3078,3079,3081,3082,3085,3086,101,3088,3091,3092,534],{},[201,3070,211],{},[201,3072,620],{},[32,3074,2977],{}," is lighter-weight and perfectly idiomatic when a struct's fields are all meant to be public and independently valid in any combination — it avoids the ceremony of a whole separate builder type for something trivial. A builder earns its complexity when construction has invariants to check (cross-field validation), needs a required field enforced (impossible to skip ",[32,3077,1610],{},", unlike a ",[32,3080,176],{},"-based struct literal where every field is implicitly optional-with-a-default), or benefits from a readable fluent chain for many optional settings. \"Always use a builder\" ignores this real trade-off and adds needless boilerplate for simple cases. The syntax shown (",[32,3083,3084],{},"Config { timeout: 30, ..Default::default() }",") is exactly the valid, common combination of named fields plus a base — the claim that they can't be combined is false. And builders remain a first-class, actively-used pattern in modern Rust (e.g. ",[32,3087,229],{},[32,3089,3090],{},"reqwest::ClientBuilder",") — they were never edition-specific or made obsolete by ",[32,3093,176],{},[14,3095,3096,3100,3204,3253],{"language":16},[18,3097,3099],{"id":3098},"q16-what-is-the-idiomatic-way-to-make-a-builders-chained-setter-methods-ergonomic-for-method-chaining-while-still-being-usable-in-a-non-chained-imperative-style","Q16. What is the idiomatic way to make a builder's chained setter methods ergonomic for method chaining while still being usable in a non-chained, imperative style?",[23,3101,3102],{"language":16},[26,3103,3105],{"className":28,"code":3104,"language":16,"meta":30,"style":30},"impl RequestBuilder {\n    pub fn header(mut self, key: &str, val: &str) -> Self {\n        self.headers.push((key.into(), val.into()));\n        self\n    }\n}\n",[32,3106,3107,3115,3158,3191,3196,3200],{"__ignoreMap":30},[35,3108,3109,3111,3113],{"class":37,"line":38},[35,3110,457],{"class":41},[35,3112,53],{"class":52},[35,3114,473],{"class":45},[35,3116,3117,3119,3121,3124,3126,3129,3131,3134,3136,3138,3140,3143,3145,3147,3149,3151,3153,3156],{"class":37,"line":72},[35,3118,2255],{"class":41},[35,3120,2258],{"class":41},[35,3122,3123],{"class":52}," header",[35,3125,62],{"class":45},[35,3127,3128],{"class":41},"mut",[35,3130,1050],{"class":119},[35,3132,3133],{"class":45},", key",[35,3135,295],{"class":41},[35,3137,763],{"class":41},[35,3139,766],{"class":52},[35,3141,3142],{"class":45},", val",[35,3144,295],{"class":41},[35,3146,763],{"class":41},[35,3148,766],{"class":52},[35,3150,300],{"class":45},[35,3152,303],{"class":41},[35,3154,3155],{"class":119}," Self",[35,3157,473],{"class":45},[35,3159,3160,3163,3165,3168,3170,3173,3176,3178,3181,3184,3186,3188],{"class":37,"line":88},[35,3161,3162],{"class":119},"        self",[35,3164,534],{"class":41},[35,3166,3167],{"class":45},"headers",[35,3169,534],{"class":41},[35,3171,3172],{"class":52},"push",[35,3174,3175],{"class":45},"((key",[35,3177,534],{"class":41},[35,3179,3180],{"class":52},"into",[35,3182,3183],{"class":45},"(), val",[35,3185,534],{"class":41},[35,3187,3180],{"class":52},[35,3189,3190],{"class":45},"()));\n",[35,3192,3193],{"class":37,"line":109},[35,3194,3195],{"class":119},"        self\n",[35,3197,3198],{"class":37,"line":125},[35,3199,554],{"class":45},[35,3201,3202],{"class":37,"line":476},[35,3203,560],{"class":45},[141,3205,3207,3228,3239,3247],{"className":3206},[144],[146,3208,3210,3212,3213,3216,3217,3219,3220,3223,3224,3227],{"className":3209},[149],[151,3211],{"disabled":153,"type":154}," Take ",[32,3214,3215],{},"mut self"," by value and return ",[32,3218,2285],{},", mutating the owned copy and handing it back — this supports both ",[32,3221,3222],{},"builder.header(..).header(..)"," chaining and ",[32,3225,3226],{},"let b = b.header(..);"," reassignment style",[146,3229,3231,3212,3233,3235,3236,3238],{"className":3230},[149],[151,3232],{"disabled":153,"type":154},[32,3234,162],{}," and return ",[32,3237,133],{},", which is the only way to support method chaining in Rust",[146,3240,3242,3212,3244,3246],{"className":3241},[149],[151,3243],{"disabled":153,"type":154},[32,3245,2024],{}," (immutable) and return a brand-new heap-allocated builder each call, which is the most performant option",[146,3248,3250,3252],{"className":3249},[149],[151,3251],{"disabled":153,"type":154}," It's impossible to support both chained and non-chained calling styles with the same method signature",[191,3254,3255,3257,3268],{},[194,3256,196],{},[198,3258,3259,3261,3262,3264,3265,3267],{},[201,3260,203],{}," A — take ",[32,3263,3215],{}," by value, return ",[32,3266,2285],{},"; supports both chaining and imperative reassignment",[198,3269,3270,363,3272,2574,3274,3276,3277,3279,3280,3282,3283,3286,3287,3290,3291,3294,3295,3298,3299,3302,3303,3305],{},[201,3271,211],{},[201,3273,620],{},[32,3275,158],{}," by value (not ",[32,3278,162],{},") and returning ",[32,3281,2285],{}," is the standard consuming-builder signature: it supports fluent chaining (",[32,3284,3285],{},"RequestBuilder::new(url).header(...).header(...).build()",") because each call produces a new owned value to call the next method on, ",[1462,3288,3289],{},"and"," it equally supports the imperative style ",[32,3292,3293],{},"let b = b.header(...);"," since it's just an ordinary function taking and returning a value — no special calling convention required. ",[32,3296,3297],{},"&mut self -> ()"," cannot be chained at all (there's nothing returned to call the next method on — you'd need separate statements), so it's actually the ",[1462,3300,3301],{},"opposite"," of what enables chaining, making that option's claim backwards. ",[32,3304,2024],{}," returning a freshly allocated builder is unnecessary allocation churn for no benefit over consuming-and-returning the existing owned value, and it isn't \"more performant\" — it's strictly more allocation for the same result. Supporting both styles with one signature is exactly what the consuming pattern already does, contrary to the last option.",[14,3307,3308,3320],{"language":16},[18,3309,3311,3312,3314,3315,3317,3318,136],{"id":3310},"q17-best-practice-should-a-drop-implementation-perform-fallible-io-eg-flushing-a-buffered-writer-to-disk-directly-given-that-drop-cannot-return-a-result","Q17. Best practice: should a ",[32,3313,976],{}," implementation perform fallible I\u002FO (e.g. flushing a buffered writer to disk) directly, given that ",[32,3316,1085],{}," cannot return a ",[32,3319,222],{},[23,3321,3322,3330,3338,3340,3376,3408,3409,3606],{"language":16},[198,3323,3324,3325,3329],{},"struct BufferedLog { writer: std::io::BufWriter",[3326,3327,3328],"a",{"href":3328},"std::fs::File"," }",[26,3331,3336],{"className":3332,"code":3334,"language":3335},[3333],"language-text","::\n\n- [ ] No — since `drop()` can't propagate errors, best practice is to expose an explicit fallible `close()`\u002F`flush()` method that callers invoke to handle errors properly, with `Drop` only as a best-effort fallback (often logging-and-swallowing) for callers who forgot\n- [ ] Yes — `Drop` is the only place cleanup should ever happen; explicit `close()` methods are redundant and should be avoided\n- [ ] It doesn't matter; any error inside `drop()` automatically becomes the return value of the enclosing function\n- [ ] Fallible I\u002FO should never appear in RAII types at all; buffered writers should not implement `Drop`\n\n\u003Cdetails>\n\u003Csummary>Show Answer\u003C\u002Fsummary>\n\n**Answer:** A — expose an explicit fallible `close()`\u002F`flush()` for real error handling; `Drop` is only a best-effort fallback\n\n**Explanation:** **Idiom\u002FDebug:** Because `Drop::drop(&mut self)` has a fixed `()` return type, there is no way to propagate a flush failure to the caller from inside it — if flushing fails during `drop()`, the best you can typically do is log the error (or, in truly critical cases, panic — accepting the abort-on-double-panic risk from Q10) and move on; the error is otherwise silently lost. This is exactly why types like `BufWriter` document that callers should call an explicit `.flush()` (which *does* return `io::Result\u003C()>`) before the value is dropped, rather than relying on the implicit drop to handle a failure path correctly — the implicit drop exists as a safety net for panics\u002Fearly-returns, not as the primary error-handling path. Errors inside `drop()` are never auto-propagated to any enclosing function — the calling code has no visibility into `drop()`'s internals at all. And RAII types absolutely can and do wrap fallible resources (files, sockets, locks) — that's a huge fraction of `Drop`'s real-world use; the pattern isn't disqualified by fallibility, it just requires this explicit-close convention to handle errors properly.\n\n\u003C\u002Fdetails>\n::\n\n::question-wrapper{language=\"rust\"}\n### Q18. In a visitor implemented as a trait (`trait Visitor { fn visit_num(&mut self, n: f64); fn visit_add(&mut self, l: &Expr, r: &Expr); }`), what is the best-practice way to allow visitors to skip most node types without writing every method?\n\n::code-wrapper{language=\"rust\"}\n```rust\ntrait Visitor {\n    fn visit_num(&mut self, n: f64) {}\n    fn visit_add(&mut self, l: &Expr, r: &Expr) {}\n    fn visit_mul(&mut self, l: &Expr, r: &Expr) {}\n}\n","text",[32,3337,3334],{"__ignoreMap":30},[198,3339,56],{},[141,3341,3343,3352,3361,3367],{"className":3342},[144],[146,3344,3346,3348,3349,3351],{"className":3345},[149],[151,3347],{"disabled":153,"type":154}," Give each method a default (often empty or auto-recursing) implementation in the trait definition, so implementors only override the specific ",[32,3350,1491],{}," methods they actually care about",[146,3353,3355,3357,3358,3360],{"className":3354},[149],[151,3356],{"disabled":153,"type":154}," Make the trait's methods all ",[32,3359,918],{}," so unimplemented ones default to undefined behavior instead of a compile error",[146,3362,3364,3366],{"className":3363},[149],[151,3365],{"disabled":153,"type":154}," There is no way to make methods optional; every implementor must provide every method or fail to compile",[146,3368,3370,2915,3372,3375],{"className":3369},[149],[151,3371],{"disabled":153,"type":154},[32,3373,3374],{},"#[derive(Visitor)]"," from the standard library to auto-generate no-op defaults",[191,3377,3378,3380,3385],{},[194,3379,196],{},[198,3381,3382,3384],{},[201,3383,203],{}," A — give trait methods default implementations so implementors override only what they need",[198,3386,3387,363,3389,3391,3392,3395,3396,3398,3399,3401,3402,3404,3405,3407],{},[201,3388,211],{},[201,3390,620],{}," Rust traits support default method bodies directly in the trait definition; any implementor can simply omit a method to inherit the default (commonly a no-op, or one that recurses into child nodes to keep traversal working), which is precisely how ecosystem visitor traits (e.g. ",[32,3393,3394],{},"syn::visit::Visit",") let users override only the handful of node types they care about instead of exhaustively implementing dozens of ",[32,3397,1491],{}," methods. Making methods ",[32,3400,918],{}," has nothing to do with optionality and would just require callers to wrap every call in an ",[32,3403,918],{}," block for no benefit — it doesn't create \"default to UB,\" which isn't a real Rust mechanism. There is no ",[32,3406,3374],{}," in the standard library; default method bodies in the trait itself are the actual, standard mechanism, and without them every method genuinely would be mandatory, making the \"no way\" option only true in the absence of defaults, which is exactly what this pattern adds.","\n::",[14,3410,3411,3433,3499,3552],{"language":16},[18,3412,3414,3415,101,3418,101,3421,3424,3425,3428,3429,3432],{"id":3413},"q19-a-codebase-has-many-newtypes-like-useridu64-orderidu64-productidu64-what-best-practice-most-directly-prevents-accidentally-passing-an-orderid-where-a-userid-is-expected-beyond-just-wrapping-in-a-struct","Q19. A codebase has many newtypes like ",[32,3416,3417],{},"UserId(u64)",[32,3419,3420],{},"OrderId(u64)",[32,3422,3423],{},"ProductId(u64)",". What best practice most directly prevents accidentally passing an ",[32,3426,3427],{},"OrderId"," where a ",[32,3430,3431],{},"UserId"," is expected, beyond just wrapping in a struct?",[23,3434,3435],{"language":16},[26,3436,3438],{"className":28,"code":3437,"language":16,"meta":30,"style":30},"struct UserId(u64);\nstruct OrderId(u64);\n\nfn get_user(id: UserId) -> User { \u002F* ... *\u002F }\n",[32,3439,3440,3454,3467,3471],{"__ignoreMap":30},[35,3441,3442,3444,3447,3449,3452],{"class":37,"line":38},[35,3443,252],{"class":41},[35,3445,3446],{"class":52}," UserId",[35,3448,62],{"class":45},[35,3450,3451],{"class":52},"u64",[35,3453,263],{"class":45},[35,3455,3456,3458,3461,3463,3465],{"class":37,"line":72},[35,3457,252],{"class":41},[35,3459,3460],{"class":52}," OrderId",[35,3462,62],{"class":45},[35,3464,3451],{"class":52},[35,3466,263],{"class":45},[35,3468,3469],{"class":37,"line":88},[35,3470,281],{"emptyLinePlaceholder":153},[35,3472,3473,3475,3478,3481,3483,3485,3487,3489,3492,3494,3497],{"class":37,"line":109},[35,3474,286],{"class":41},[35,3476,3477],{"class":52}," get_user",[35,3479,3480],{"class":45},"(id",[35,3482,295],{"class":41},[35,3484,3446],{"class":52},[35,3486,300],{"class":45},[35,3488,303],{"class":41},[35,3490,3491],{"class":52}," User",[35,3493,2314],{"class":45},[35,3495,3496],{"class":2868},"\u002F* ... *\u002F",[35,3498,864],{"class":45},[141,3500,3502,3520,3530,3542],{"className":3501},[144],[146,3503,3505,3507,3508,387,3511,3514,3515,345,3517,3519],{"className":3504},[149],[151,3506],{"disabled":153,"type":154}," Nothing extra is needed beyond the newtype wrapper itself and using it consistently in function signatures — ",[32,3509,3510],{},"get_user(order_id)",[32,3512,3513],{},"order_id: OrderId"," is already a compile error because ",[32,3516,3427],{},[32,3518,3431],{}," are distinct, non-interchangeable types",[146,3521,3523,3525,3526,3529],{"className":3522},[149],[151,3524],{"disabled":153,"type":154}," Add a runtime assertion inside ",[32,3527,3528],{},"get_user"," that checks a \"type tag\" field to catch mismatches",[146,3531,3533,2915,3535,3537,3538,3541],{"className":3532},[149],[151,3534],{"disabled":153,"type":154},[32,3536,3451],{}," directly everywhere and rely on descriptive parameter names like ",[32,3539,3540],{},"user_id: u64"," for safety",[146,3543,3545,3547,3548,3551],{"className":3544},[149],[151,3546],{"disabled":153,"type":154}," Implement ",[32,3549,3550],{},"From\u003COrderId> for UserId"," so the two remain freely convertible for flexibility",[191,3553,3554,3556,3561],{},[194,3555,196],{},[198,3557,3558,3560],{},[201,3559,203],{}," A — nothing extra needed; distinct newtypes are already non-interchangeable at compile time when used consistently in signatures",[198,3562,3563,363,3565,3567,3568,345,3570,3572,3573,3576,3577,3579,3580,3582,3583,3585,3586,3588,3589,3591,3592,387,3595,3598,3599,3601,3602,3605],{},[201,3564,211],{},[201,3566,366],{}," This is the newtype pattern's core payoff restated concretely: once ",[32,3569,3431],{},[32,3571,3427],{}," are separate structs, ",[32,3574,3575],{},"fn get_user(id: UserId)"," simply cannot accept an ",[32,3578,3427],{}," argument — the compiler rejects ",[32,3581,3510],{}," as a type mismatch with zero runtime cost or extra ceremony, as long as the signatures consistently use the specific ID types rather than degrading back to raw ",[32,3584,3451],{}," anywhere in the call chain. A runtime \"type tag\" check is redundant ",[1462,3587,3289],{}," strictly worse (it defers a catchable compile-time bug to a runtime check that could be skipped or forgotten) given the compiler already enforces this for free. Using bare ",[32,3590,3451],{}," everywhere and relying on naming conventions is exactly the unsafe baseline this pattern replaces — parameter names provide no compiler enforcement at all, and a caller passing ",[32,3593,3594],{},"user_id",[32,3596,3597],{},"order_id_as_u64"," was expected compiles silently. And implementing ",[32,3600,3550],{}," would be actively counterproductive — it reintroduces easy, silent interchangeability (via ",[32,3603,3604],{},".into()",") between two IDs that should never be conflated, undermining the entire point of separating them.",[14,3607,3608,3624,3715,3749],{"language":16},[18,3609,3611,3612,394,3614,3616,3617,394,3620,3623],{"id":3610},"q20-which-of-these-is-a-legitimate-best-practice-reason-to-prefer-the-typestate-pattern-over-runtime-state-validation-an-enum-field-checked-with-ifmatch-inside-each-method-for-a-resource-with-a-strict-lifecycle-eg-a-database-transaction-begun-committedrolledback","Q20. Which of these is a legitimate best-practice reason to prefer the typestate pattern over runtime state validation (an enum field checked with ",[32,3613,905],{},[32,3615,895],{}," inside each method) for a resource with a strict lifecycle (e.g. a database transaction: ",[32,3618,3619],{},"Begun -> Committed",[32,3621,3622],{},"RolledBack",")?",[23,3625,3626],{"language":16},[26,3627,3629],{"className":28,"code":3628,"language":16,"meta":30,"style":30},"fn commit(&mut self) -> Result\u003C(), TxError> {\n    if self.state != TxState::Begun {\n        return Err(TxError::InvalidState);\n    }\n    \u002F\u002F ...\n}\n",[32,3630,3631,3658,3683,3702,3706,3711],{"__ignoreMap":30},[35,3632,3633,3635,3638,3640,3642,3644,3646,3648,3650,3653,3656],{"class":37,"line":38},[35,3634,286],{"class":41},[35,3636,3637],{"class":52}," commit",[35,3639,62],{"class":45},[35,3641,643],{"class":41},[35,3643,1050],{"class":119},[35,3645,300],{"class":45},[35,3647,303],{"class":41},[35,3649,1689],{"class":52},[35,3651,3652],{"class":45},"\u003C(), ",[35,3654,3655],{"class":52},"TxError",[35,3657,697],{"class":45},[35,3659,3660,3663,3665,3667,3670,3673,3676,3678,3681],{"class":37,"line":72},[35,3661,3662],{"class":41},"    if",[35,3664,1050],{"class":119},[35,3666,534],{"class":41},[35,3668,3669],{"class":45},"state ",[35,3671,3672],{"class":41},"!=",[35,3674,3675],{"class":52}," TxState",[35,3677,56],{"class":41},[35,3679,3680],{"class":52},"Begun",[35,3682,473],{"class":45},[35,3684,3685,3688,3691,3693,3695,3697,3700],{"class":37,"line":88},[35,3686,3687],{"class":41},"        return",[35,3689,3690],{"class":52}," Err",[35,3692,62],{"class":45},[35,3694,3655],{"class":52},[35,3696,56],{"class":41},[35,3698,3699],{"class":52},"InvalidState",[35,3701,263],{"class":45},[35,3703,3704],{"class":37,"line":109},[35,3705,554],{"class":45},[35,3707,3708],{"class":37,"line":125},[35,3709,3710],{"class":2868},"    \u002F\u002F ...\n",[35,3712,3713],{"class":37,"line":476},[35,3714,560],{"class":45},[141,3716,3718,3728,3737,3743],{"className":3717},[144],[146,3719,3721,3723,3724,3727],{"className":3720},[149],[151,3722],{"disabled":153,"type":154}," Typestate turns \"call ",[32,3725,3726],{},"commit()"," on an already-committed transaction\" from a runtime error path (that must be tested and can be forgotten) into something the compiler refuses to build in the first place, eliminating an entire category of production incident",[146,3729,3731,3733,3734,3736],{"className":3730},[149],[151,3732],{"disabled":153,"type":154}," Typestate is always faster at runtime because it eliminates one ",[32,3735,905],{}," statement, which dominates performance in most programs",[146,3738,3740,3742],{"className":3739},[149],[151,3741],{"disabled":153,"type":154}," Runtime state validation is impossible to implement correctly in Rust, so typestate is the only valid option",[146,3744,3746,3748],{"className":3745},[149],[151,3747],{"disabled":153,"type":154}," Typestate and runtime validation are functionally identical; the only difference is which one the linter prefers",[191,3750,3751,3753,3758],{},[194,3752,196],{},[198,3754,3755,3757],{},[201,3756,203],{}," A — typestate eliminates the invalid-call category at compile time instead of relying on a tested-and-hopefully-not-forgotten runtime check",[198,3759,3760,363,3762,3765,3766,3768,3769,3772,3773,3776,3777,3779],{},[201,3761,211],{},[201,3763,3764],{},"Safety\u002FIdiom:"," The runtime-",[32,3767,905],{}," version shown is a perfectly valid, common Rust pattern, but it has a fundamental weakness the question highlights: its correctness depends on every method remembering to check state and on every caller correctly handling the ",[32,3770,3771],{},"Err(TxError::InvalidState)"," path — a forgotten check, or a caller that unwraps and ignores the error, becomes a real production bug (e.g. double-committing a transaction). Typestate instead makes ",[32,3774,3775],{},"Committed\u003CTx>::commit()"," not exist as a callable method at all, so the mistake can't compile, full stop — no test coverage, code review vigilance, or runtime error handling is needed to catch it, because there is no code path where it's possible. This isn't primarily a performance optimization (the eliminated ",[32,3778,905],{}," is typically negligible against actual I\u002FO costs like a database round-trip, making that option's performance framing misleading) and it isn't that runtime validation is \"impossible to implement correctly\" (the example compiles and works) — it's a strictly weaker safety guarantee, not a broken one. The two approaches are absolutely not functionally identical: one defers the invalid-state class of bug to runtime, the other removes it from the possibility space entirely.",[3781,3782,3783],"style",{},"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 .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}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 .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}",{"title":30,"searchDepth":72,"depth":72,"links":3785},[3786,3787,3789,3790,3791,3793,3794,3796,3798,3799,3801,3803,3805,3807,3809,3811,3812],{"id":20,"depth":88,"text":21},{"id":235,"depth":88,"text":3788},"Q2. What core problem does the newtype pattern (struct Meters(f64);) solve?",{"id":402,"depth":88,"text":403},{"id":652,"depth":88,"text":653},{"id":972,"depth":88,"text":3792},"Q5. What guarantee does RAII (Resource Acquisition Is Initialization) via Drop provide in Rust?",{"id":1187,"depth":88,"text":1188},{"id":1484,"depth":88,"text":3795},"Q7. Why might a codebase choose the classic trait-based visitor pattern (a Visitor trait with a visit_* method per node type) over a plain match-based enum approach for an AST?",{"id":1599,"depth":88,"text":3797},"Q8. A Config struct has 8 optional fields, most with sensible defaults. What happens if a builder's build() method is called before any required fields (say, api_key) are set?",{"id":1862,"depth":88,"text":1863},{"id":2058,"depth":88,"text":3800},"Q10. In a Drop implementation, what happens if drop() itself panics while the program is already unwinding from a prior panic (i.e. a \"double panic\")?",{"id":2204,"depth":88,"text":3802},"Q11. A struct wraps a Vec\u003Cu8> as a newtype to represent a validated, non-empty buffer. What is the most common mistake that defeats the purpose of this newtype?",{"id":2449,"depth":88,"text":3804},"Q12. A builder's build() method is called twice on the same builder instance. Given standard consuming-builder design (fn build(self) -> T), what happens on the second call?",{"id":2605,"depth":88,"text":3806},"Q13. What happens if a Drop impl is written for a type that also derives Copy?",{"id":2795,"depth":88,"text":3808},"Q14. A typestate API models a network connection with Disconnected -> Connecting -> Connected states. A method needs to handle the case where connecting can fail and should return to Disconnected. How is this typically expressed in the return type?",{"id":2973,"depth":88,"text":3810},"Q15. When is it idiomatic to use the builder pattern versus simply using a struct literal with ..Default::default()?",{"id":3098,"depth":88,"text":3099},{"id":3310,"depth":88,"text":3813},"Q17. Best practice: should a Drop implementation perform fallible I\u002FO (e.g. flushing a buffered writer to disk) directly, given that drop() cannot return a Result?","md",{},"\u002Frust\u002F30-design-patterns",{"title":5,"description":30},"rust\u002F30-design-patterns","ZmTkNTy47BApmaTU5IXB1UthYAxWweafAnUSeO0kSkY",1787335398480]