[{"data":1,"prerenderedAt":3075},["ShallowReactive",2],{"page-\u002Frust\u002F29-advanced-type-system":3},{"id":4,"title":5,"body":6,"description":30,"extension":3069,"meta":3070,"navigation":117,"path":3071,"seo":3072,"stem":3073,"__hash__":3074},"content\u002Frust\u002F29-advanced-type-system.md","29 — Advanced Type System",{"type":7,"value":8,"toc":3030},"minimark",[9,13,270,342,534,624,774,860,977,1171,1354,1451,1625,1807,2057,2237,2331,2458,2559,2709,2834,3026],[10,11,5],"h1",{"id":12},"_29-advanced-type-system",[14,15,17,22,179,212],"question-wrapper",{"language":16},"rust",[18,19,21],"h3",{"id":20},"q1-what-is-the-key-difference-between-an-associated-type-and-a-generic-type-parameter-on-a-trait","Q1. What is the key difference between an associated type and a generic type parameter on a trait?",[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","trait IteratorLike {\n    type Item;\n    fn next(&mut self) -> Option\u003CSelf::Item>;\n}\n\ntrait Container\u003CT> {\n    fn get(&self, i: usize) -> Option\u003C&T>;\n}\n","",[32,33,34,51,63,106,112,119,135,174],"code",{"__ignoreMap":30},[35,36,39,43,47],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"svdQ7","trait",[35,44,46],{"class":45},"sIsaT"," IteratorLike",[35,48,50],{"class":49},"ssxIu"," {\n",[35,52,54,57,60],{"class":37,"line":53},2,[35,55,56],{"class":41},"    type",[35,58,59],{"class":45}," Item",[35,61,62],{"class":49},";\n",[35,64,66,69,72,75,78,82,85,88,91,94,97,100,103],{"class":37,"line":65},3,[35,67,68],{"class":41},"    fn",[35,70,71],{"class":45}," next",[35,73,74],{"class":49},"(",[35,76,77],{"class":41},"&mut",[35,79,81],{"class":80},"snvgF"," self",[35,83,84],{"class":49},") ",[35,86,87],{"class":41},"->",[35,89,90],{"class":45}," Option",[35,92,93],{"class":49},"\u003C",[35,95,96],{"class":80},"Self",[35,98,99],{"class":41},"::",[35,101,102],{"class":45},"Item",[35,104,105],{"class":49},">;\n",[35,107,109],{"class":37,"line":108},4,[35,110,111],{"class":49},"}\n",[35,113,115],{"class":37,"line":114},5,[35,116,118],{"emptyLinePlaceholder":117},true,"\n",[35,120,122,124,127,129,132],{"class":37,"line":121},6,[35,123,42],{"class":41},[35,125,126],{"class":45}," Container",[35,128,93],{"class":49},[35,130,131],{"class":45},"T",[35,133,134],{"class":49},"> {\n",[35,136,138,140,143,145,148,151,154,157,160,162,164,166,168,170,172],{"class":37,"line":137},7,[35,139,68],{"class":41},[35,141,142],{"class":45}," get",[35,144,74],{"class":49},[35,146,147],{"class":41},"&",[35,149,150],{"class":80},"self",[35,152,153],{"class":49},", i",[35,155,156],{"class":41},":",[35,158,159],{"class":45}," usize",[35,161,84],{"class":49},[35,163,87],{"class":41},[35,165,90],{"class":45},[35,167,93],{"class":49},[35,169,147],{"class":41},[35,171,131],{"class":45},[35,173,105],{"class":49},[35,175,177],{"class":37,"line":176},8,[35,178,111],{"class":49},[180,181,184,194,200,206],"ul",{"className":182},[183],"contains-task-list",[185,186,189,193],"li",{"className":187},[188],"task-list-item",[190,191],"input",{"disabled":117,"type":192},"checkbox"," A type implementing a trait with an associated type may only provide ONE concrete type for it, while a generic trait parameter allows multiple impls for different types on the same type",[185,195,197,199],{"className":196},[188],[190,198],{"disabled":117,"type":192}," Associated types are resolved at runtime; generic parameters are resolved at compile time",[185,201,203,205],{"className":202},[188],[190,204],{"disabled":117,"type":192}," Associated types can only be primitive types; generics can be any type",[185,207,209,211],{"className":208},[188],[190,210],{"disabled":117,"type":192}," There is no functional difference — they are two syntaxes for the same feature",[213,214,215,219,227],"details",{},[216,217,218],"summary",{},"Show Answer",[220,221,222,226],"p",{},[223,224,225],"strong",{},"Answer:"," A — a type may implement a trait with an associated type only once, but can implement a generic-parameter trait many times for different type arguments",[220,228,229,232,233,236,237,239,240,243,244,247,248,250,251,254,255,258,259,262,263,265,266,269],{},[223,230,231],{},"Explanation:"," ",[32,234,235],{},"impl\u003CT> Container\u003CT> for MyType"," can be written once per distinct ",[32,238,131],{}," (e.g. ",[32,241,242],{},"Container\u003Ci32> for MyType"," and ",[32,245,246],{},"Container\u003CString> for MyType"," can coexist), because ",[32,249,131],{}," is part of the trait signature being implemented. But ",[32,252,253],{},"impl IteratorLike for MyType"," can only exist once total, with ",[32,256,257],{},"Self::Item"," fixed to a single concrete type — the associated type is an output determined by the impl, not an input you can vary across multiple impls. Both are fully resolved at compile time (Rust has no runtime generics), and associated types can be any type, not just primitives — this is why real-world ",[32,260,261],{},"Iterator"," uses an associated ",[32,264,102],{}," (one element type per iterator) while traits like ",[32,267,268],{},"From\u003CT>"," use a generic parameter (many conversions per type).",[14,271,272,276,306],{},[18,273,275],{"id":274},"q2-what-does-gat-stand-for-and-what-capability-does-it-add-over-a-plain-associated-type","Q2. What does GAT stand for, and what capability does it add over a plain associated type?",[180,277,279,288,294,300],{"className":278},[183],[185,280,282,284,285],{"className":281},[188],[190,283],{"disabled":117,"type":192}," Generic Associated Type — an associated type that can itself be generic over a lifetime or type parameter, e.g. ",[32,286,287],{},"type Item\u003C'a>",[185,289,291,293],{"className":290},[188],[190,292],{"disabled":117,"type":192}," Global Application Trait — a trait implemented automatically for every type in the crate",[185,295,297,299],{"className":296},[188],[190,298],{"disabled":117,"type":192}," Guaranteed Allocation Type — a marker trait indicating heap-allocated storage",[185,301,303,305],{"className":302},[188],[190,304],{"disabled":117,"type":192}," Generic Abstract Trait — a trait with no default method implementations",[213,307,308,310,315],{},[216,309,218],{},[220,311,312,314],{},[223,313,225],{}," A — Generic Associated Type: an associated type parameterized by a lifetime or type",[220,316,317,319,320,323,324,327,328,331,332,335,336,338,339,341],{},[223,318,231],{}," A plain associated type (",[32,321,322],{},"type Item;",") is a single fixed type per impl. A GAT (",[32,325,326],{},"type Item\u003C'a>;"," or ",[32,329,330],{},"type Container\u003CT>;",") lets that associated type itself depend on a lifetime or type parameter supplied at the point of use, which is what makes \"lending iterators\" (an iterator whose ",[32,333,334],{},"next()"," borrows from ",[32,337,150],{}," for the duration of the call) expressible — something impossible with the older associated-type system because ",[32,340,102],{}," couldn't vary per call. The other three options describe nothing that exists in Rust's type system.",[14,343,344,352,431,473],{"language":16},[18,345,347,348,351],{"id":346},"q3-what-is-phantomdatat-primarily-used-for","Q3. What is ",[32,349,350],{},"PhantomData\u003CT>"," primarily used for?",[23,353,354],{"language":16},[26,355,357],{"className":28,"code":356,"language":16,"meta":30,"style":30},"use std::marker::PhantomData;\n\nstruct TypedId\u003CT> {\n    id: u64,\n    _marker: PhantomData\u003CT>,\n}\n",[32,358,359,379,383,397,410,427],{"__ignoreMap":30},[35,360,361,364,367,369,372,374,377],{"class":37,"line":38},[35,362,363],{"class":41},"use",[35,365,366],{"class":45}," std",[35,368,99],{"class":41},[35,370,371],{"class":45},"marker",[35,373,99],{"class":41},[35,375,376],{"class":45},"PhantomData",[35,378,62],{"class":49},[35,380,381],{"class":37,"line":53},[35,382,118],{"emptyLinePlaceholder":117},[35,384,385,388,391,393,395],{"class":37,"line":65},[35,386,387],{"class":41},"struct",[35,389,390],{"class":45}," TypedId",[35,392,93],{"class":49},[35,394,131],{"class":45},[35,396,134],{"class":49},[35,398,399,402,404,407],{"class":37,"line":108},[35,400,401],{"class":49},"    id",[35,403,156],{"class":41},[35,405,406],{"class":45}," u64",[35,408,409],{"class":49},",\n",[35,411,412,415,417,420,422,424],{"class":37,"line":114},[35,413,414],{"class":49},"    _marker",[35,416,156],{"class":41},[35,418,419],{"class":45}," PhantomData",[35,421,93],{"class":49},[35,423,131],{"class":45},[35,425,426],{"class":49},">,\n",[35,428,429],{"class":37,"line":121},[35,430,111],{"class":49},[180,432,434,445,454,460],{"className":433},[183],[185,435,437,439,440,442,443],{"className":436},[188],[190,438],{"disabled":117,"type":192}," Telling the compiler a struct \"acts as if\" it owns\u002Fuses a ",[32,441,131],{}," for variance, drop-check, and auto-trait purposes, even though no field actually stores a ",[32,444,131],{},[185,446,448,450,451,453],{"className":447},[188],[190,449],{"disabled":117,"type":192}," Allocating a placeholder value of type ",[32,452,131],{}," lazily on first access",[185,455,457,459],{"className":456},[188],[190,458],{"disabled":117,"type":192}," Making a struct's fields optional at compile time",[185,461,463,465,466,468,469,472],{"className":462},[188],[190,464],{"disabled":117,"type":192}," Forcing ",[32,467,131],{}," to implement ",[32,470,471],{},"Default"," so a zero value can be materialized",[213,474,475,477,485],{},[216,476,218],{},[220,478,479,481,482,484],{},[223,480,225],{}," A — signals the compiler to treat the struct as if it owns\u002Fuses a ",[32,483,131],{},", for variance, drop-check, and auto-trait purposes",[220,486,487,232,489,491,492,495,496,499,500,503,504,506,507,509,510,513,514,517,518,520,521,524,525,527,528,530,531,533],{},[223,488,231],{},[32,490,350],{}," occupies zero space at runtime but participates in the type system: it affects variance (does ",[32,493,494],{},"TypedId\u003C&'a str>"," behave covariantly in ",[32,497,498],{},"'a","?), the drop-checker (does dropping ",[32,501,502],{},"TypedId\u003CT>"," count as potentially dropping a ",[32,505,131],{},", affecting borrow-checking around ",[32,508,131],{},"'s lifetime?), and auto-trait inference (",[32,511,512],{},"Send","\u002F",[32,515,516],{},"Sync",") exactly as if a real ",[32,519,131],{}," field were present. It's commonly used for phantom-typed IDs, unit-of-measure wrappers, or marking unsafe code's intended ownership. It doesn't allocate anything, doesn't affect field optionality, and doesn't require ",[32,522,523],{},"T: Default"," — ",[32,526,350],{}," is constructible via ",[32,529,376],{}," regardless of what traits ",[32,532,131],{}," implements.",[14,535,536,544,577],{},[18,537,539,540,543],{"id":538},"q4-which-of-the-following-best-describes-object-safety-for-a-trait-ie-what-determines-whether-dyn-trait-is-a-valid-type","Q4. Which of the following best describes \"object safety\" for a trait — i.e. what determines whether ",[32,541,542],{},"dyn Trait"," is a valid type?",[180,545,547,556,565,571],{"className":546},[183],[185,548,550,552,553,555],{"className":549},[188],[190,551],{"disabled":117,"type":192}," A trait is object-safe roughly when none of its methods return ",[32,554,96],{}," by value or take generic type parameters, and it has no associated consts (with some further refinements)",[185,557,559,561,562,564],{"className":558},[188],[190,560],{"disabled":117,"type":192}," Every trait in Rust is automatically object-safe; ",[32,563,542],{}," always compiles for any trait",[185,566,568,570],{"className":567},[188],[190,569],{"disabled":117,"type":192}," A trait is object-safe only if it has exactly one method",[185,572,574,576],{"className":573},[188],[190,575],{"disabled":117,"type":192}," Object safety is a runtime property checked when the trait object is constructed, not a compile-time one",[213,578,579,581,589],{},[216,580,218],{},[220,582,583,585,586,588],{},[223,584,225],{}," A — roughly: no methods returning ",[32,587,96],{}," by value, no generic methods, no associated consts (plus a few more refinements)",[220,590,591,232,593,595,596,598,599,601,602,604,605,608,609,612,613,616,617,620,621,623],{},[223,592,231],{},[32,594,542],{}," erases the concrete type behind a vtable, so any method whose signature depends on knowing the concrete ",[32,597,96],{}," size or identity at compile time (returning ",[32,600,96],{}," by value, taking ",[32,603,96],{}," by value as a non-receiver parameter, or having generic type parameters that would require monomorphizing per call site) can't be represented in a single vtable entry, making the trait not object-safe as-is (methods can individually opt out via ",[32,606,607],{},"where Self: Sized","). This is checked entirely at compile time — attempting ",[32,610,611],{},"Box\u003Cdyn Trait>"," for a non-object-safe trait is a compile error, never a runtime failure. Not every trait qualifies (e.g. ",[32,614,615],{},"Clone"," is famously not object-safe because ",[32,618,619],{},"fn clone(&self) -> Self"," returns ",[32,622,96],{}," by value), and method count is irrelevant to object safety.",[14,625,626,637,679,724],{"language":16},[18,627,629,630,632,633,636],{"id":628},"q5-why-is-clone-not-object-safe-ie-why-cant-you-write-boxdyn-clone","Q5. Why is ",[32,631,615],{}," not object-safe, i.e. why can't you write ",[32,634,635],{},"Box\u003Cdyn Clone>","?",[23,638,639],{"language":16},[26,640,642],{"className":28,"code":641,"language":16,"meta":30,"style":30},"trait Clone {\n    fn clone(&self) -> Self;\n}\n",[32,643,644,653,675],{"__ignoreMap":30},[35,645,646,648,651],{"class":37,"line":38},[35,647,42],{"class":41},[35,649,650],{"class":45}," Clone",[35,652,50],{"class":49},[35,654,655,657,660,662,664,666,668,670,673],{"class":37,"line":53},[35,656,68],{"class":41},[35,658,659],{"class":45}," clone",[35,661,74],{"class":49},[35,663,147],{"class":41},[35,665,150],{"class":80},[35,667,84],{"class":49},[35,669,87],{"class":41},[35,671,672],{"class":80}," Self",[35,674,62],{"class":49},[35,676,677],{"class":37,"line":65},[35,678,111],{"class":49},[180,680,682,693,705,713],{"className":681},[183],[185,683,685,232,687,620,690,692],{"className":684},[188],[190,686],{"disabled":117,"type":192},[32,688,689],{},"clone(&self) -> Self",[32,691,96],{}," by value, and the vtable has no way to know the size of the concrete type to return, since that information is erased",[185,694,696,232,698,700,701,704],{"className":695},[188],[190,697],{"disabled":117,"type":192},[32,699,615],{}," requires ",[32,702,703],{},"unsafe"," internally, which trait objects forbid",[185,706,708,232,710,712],{"className":707},[188],[190,709],{"disabled":117,"type":192},[32,711,615],{}," has too many blanket implementations for the compiler to resolve a vtable",[185,714,716,232,718,720,721],{"className":715},[188],[190,717],{"disabled":117,"type":192},[32,719,635],{}," actually does compile; the restriction only applies to ",[32,722,723],{},"&dyn Clone",[213,725,726,728,739],{},[216,727,218],{},[220,729,730,732,733,735,736],{},[223,731,225],{}," A — returning ",[32,734,96],{}," by value requires knowing the concrete type's size, which is erased by ",[32,737,738],{},"dyn",[220,740,741,743,744,747,748,751,752,755,756,758,759,761,762,764,765,767,768,770,771,773],{},[223,742,231],{}," A ",[32,745,746],{},"dyn Clone"," trait object has erased its concrete type down to a ",[32,749,750],{},"(data pointer, vtable pointer)"," pair; the caller of ",[32,753,754],{},"clone()"," on it has no compile-time knowledge of how large the returned ",[32,757,96],{}," is or how to place it on the stack, since different underlying types implementing ",[32,760,615],{}," have different sizes. This makes ",[32,763,619],{}," impossible to call through a vtable in a type-erased way, so the trait fails object safety. Neither ",[32,766,703],{}," nor blanket impls have anything to do with it, and ",[32,769,635],{}," fails to compile identically to ",[32,772,723],{}," — boxing doesn't change the object-safety requirement, since the vtable problem exists regardless of the pointer wrapper.",[14,775,776,791,826],{},[18,777,779,780,783,784,783,787,790],{"id":778},"q6-given-fn-foot-traitx-t-versus-fn-foox-impl-trait-versus-fn-foox-boxdyn-trait-which-statement-is-correct","Q6. Given ",[32,781,782],{},"fn foo\u003CT: Trait>(x: T)"," versus ",[32,785,786],{},"fn foo(x: impl Trait)",[32,788,789],{},"fn foo(x: Box\u003Cdyn Trait>)",", which statement is correct?",[180,792,794,800,806,818],{"className":793},[183],[185,795,797,799],{"className":796},[188],[190,798],{"disabled":117,"type":192}," The first two are static dispatch (monomorphized per concrete type at compile time); the third is dynamic dispatch through a vtable at runtime",[185,801,803,805],{"className":802},[188],[190,804],{"disabled":117,"type":192}," All three compile to identical machine code; the syntax differences are purely stylistic",[185,807,809,232,811,814,815],{"className":808},[188],[190,810],{"disabled":117,"type":192},[32,812,813],{},"impl Trait"," in argument position uses dynamic dispatch, unlike ",[32,816,817],{},"\u003CT: Trait>",[185,819,821,232,823,825],{"className":820},[188],[190,822],{"disabled":117,"type":192},[32,824,611],{}," is resolved at compile time via monomorphization just like generics",[213,827,828,830,835],{},[216,829,218],{},[220,831,832,834],{},[223,833,225],{}," A — the first two are static dispatch via monomorphization; the third is dynamic dispatch via a vtable",[220,836,837,232,839,232,842,243,844,846,847,850,851,853,854,856,857,859],{},[223,838,231],{},[223,840,841],{},"Performance:",[32,843,782],{},[32,845,786],{}," are exactly equivalent sugar for each other — both cause the compiler to generate a separate specialized copy of ",[32,848,849],{},"foo"," for every concrete type used at call sites (monomorphization), enabling inlining and eliminating indirect calls, at the cost of larger binary size (\"code bloat\") if used with many types. ",[32,852,611],{}," instead compiles ",[32,855,849],{}," once, taking a fat pointer, and dispatches each method call through the vtable at runtime — smaller binary, one indirect call per invocation, no inlining across the call boundary. They are not machine-code-identical, and ",[32,858,813],{}," in argument position is definitively static, not dynamic, dispatch.",[14,861,862,870,924],{},[18,863,865,866,869],{"id":864},"q7-what-does-it-mean-for-a-generic-type-to-be-covariant-in-a-lifetime-parameter-using-a-t-as-the-canonical-example","Q7. What does it mean for a generic type to be \"covariant\" in a lifetime parameter, using ",[32,867,868],{},"&'a T"," as the canonical example?",[180,871,873,899,912,918],{"className":872},[183],[185,874,876,878,879,882,883,886,887,890,891,894,895,898],{"className":875},[188],[190,877],{"disabled":117,"type":192}," If ",[32,880,881],{},"'long: 'short"," (i.e. ",[32,884,885],{},"'long"," outlives ",[32,888,889],{},"'short","), then ",[32,892,893],{},"&'long T"," can be used wherever ",[32,896,897],{},"&'short T"," is expected — the subtyping relationship on the lifetime carries over to the reference type",[185,900,902,904,905,907,908,911],{"className":901},[188],[190,903],{"disabled":117,"type":192}," Covariance means the compiler automatically converts ",[32,906,868],{}," into ",[32,909,910],{},"&'a mut T"," when needed",[185,913,915,917],{"className":914},[188],[190,916],{"disabled":117,"type":192}," Covariance means the type can be mutated through an immutable reference",[185,919,921,923],{"className":920},[188],[190,922],{"disabled":117,"type":192}," Covariance only applies to trait objects, never to plain reference types",[213,925,926,928,933],{},[216,927,218],{},[220,929,930,932],{},[223,931,225],{}," A — a longer-lived reference can be used where a shorter-lived one is expected, mirroring the lifetime subtyping relationship",[220,934,935,232,937,939,940,942,943,945,946,948,949,952,953,956,957,959,960,963,964,513,967,970,971,939,974,976],{},[223,936,231],{},[32,938,868],{}," is covariant in ",[32,941,498],{},": because a longer lifetime is considered a \"subtype\" of a shorter one (anything valid for longer is trivially valid for a shorter window), ",[32,944,893],{}," can be passed anywhere ",[32,947,897],{}," is needed automatically — this is what lets you pass a ",[32,950,951],{},"&'static str"," to a function expecting ",[32,954,955],{},"&'a str"," for any ",[32,958,498],{},". It has nothing to do with converting immutable to mutable references (that's an entirely separate, forbidden operation) or mutating through ",[32,961,962],{},"&T"," (that's interior mutability via ",[32,965,966],{},"Cell",[32,968,969],{},"RefCell",", unrelated to variance). Variance applies broadly to any generic type over lifetimes or type parameters, not only trait objects — ",[32,972,973],{},"Vec\u003CT>",[32,975,131],{},", for instance.",[14,978,979,1007,1047,1091],{"language":16},[18,980,982,983,243,986,989,990,992,993,243,995,997,998,1000,1001,1003,1004,1006],{"id":981},"q8-cellt-and-refcellt-are-invariant-in-t-while-t-and-vect-are-covariant-in-t-why-does-refcellt-need-to-be-invariant-even-though-t-is-covariant","Q8. ",[32,984,985],{},"Cell\u003CT>",[32,987,988],{},"RefCell\u003CT>"," are invariant in ",[32,991,131],{},", while ",[32,994,962],{},[32,996,973],{}," are covariant in ",[32,999,131],{},". Why does ",[32,1002,988],{}," need to be invariant even though ",[32,1005,962],{}," is covariant?",[23,1008,1009],{"language":16},[26,1010,1012],{"className":28,"code":1011,"language":16,"meta":30,"style":30},"struct RefCell\u003CT> {\n    value: UnsafeCell\u003CT>,\n}\n",[32,1013,1014,1027,1043],{"__ignoreMap":30},[35,1015,1016,1018,1021,1023,1025],{"class":37,"line":38},[35,1017,387],{"class":41},[35,1019,1020],{"class":45}," RefCell",[35,1022,93],{"class":49},[35,1024,131],{"class":45},[35,1026,134],{"class":49},[35,1028,1029,1032,1034,1037,1039,1041],{"class":37,"line":53},[35,1030,1031],{"class":49},"    value",[35,1033,156],{"class":41},[35,1035,1036],{"class":45}," UnsafeCell",[35,1038,93],{"class":49},[35,1040,131],{"class":45},[35,1042,426],{"class":49},[35,1044,1045],{"class":37,"line":65},[35,1046,111],{"class":49},[180,1048,1050,1059,1065,1076],{"className":1049},[183],[185,1051,1053,1055,1056,1058],{"className":1052},[188],[190,1054],{"disabled":117,"type":192}," Because ",[32,1057,969],{}," allows mutation through a shared reference (interior mutability); if it were covariant, you could smuggle a shorter-lived value in through a longer-lived alias and later read it back out as the longer lifetime, unsoundly extending it",[185,1060,1062,1064],{"className":1061},[188],[190,1063],{"disabled":117,"type":192}," Invariance is just a conservative default the compiler applies to any struct with more than one field",[185,1066,1068,232,1070,1072,1073,1075],{"className":1067},[188],[190,1069],{"disabled":117,"type":192},[32,1071,988],{}," is actually covariant; only ",[32,1074,985],{}," is invariant",[185,1077,1079,1081,1082,1084,1085,1087,1088,1090],{"className":1078},[188],[190,1080],{"disabled":117,"type":192}," Invariance only matters for ",[32,1083,703],{}," code; ",[32,1086,969],{}," doesn't use ",[32,1089,703],{}," internally so this is moot",[213,1092,1093,1095,1100],{},[216,1094,218],{},[220,1096,1097,1099],{},[223,1098,225],{}," A — covariance plus interior mutability would let a shorter-lived value be written in and later smuggled out under a longer lifetime, unsoundly extending it",[220,1101,1102,232,1104,878,1107,1110,1111,1114,1115,1117,1118,1121,1122,1124,1125,1128,1129,1131,1132,1134,1135,1138,1139,1142,1143,1145,1146,1148,1149,1152,1153,513,1155,1158,1159,1161,1162,1164,1165,1167,1168,1170],{},[223,1103,231],{},[223,1105,1106],{},"Safety:",[32,1108,1109],{},"RefCell\u003C&'short U>"," could coerce to ",[32,1112,1113],{},"RefCell\u003C&'long U>"," (covariance), code holding the ",[32,1116,1113],{}," handle could ",[32,1119,1120],{},".replace()"," in a value borrowed for only ",[32,1123,889],{},", then later ",[32,1126,1127],{},".borrow()"," it back out believing it's valid for ",[32,1130,885],{}," — a lifetime-extension unsoundness bug. Because ",[32,1133,969],{}," exposes mutation through ",[32,1136,1137],{},"&self"," via ",[32,1140,1141],{},"UnsafeCell",", the type system must be conservative and treat ",[32,1144,131],{}," as invariant (",[32,1147,988],{}," is neither a subtype nor supertype of ",[32,1150,1151],{},"RefCell\u003CU>"," even if ",[32,1154,131],{},[32,1156,1157],{},"U"," are related), closing that hole. This isn't a generic \"more than one field\" rule — variance is derived structurally from how ",[32,1160,131],{}," is actually used inside the type, and ",[32,1163,969],{}," genuinely does rely on ",[32,1166,703],{}," (",[32,1169,1141],{},") internally precisely because interior mutability requires it; that's exactly why its variance can't be left permissive.",[14,1172,1173,1181,1276,1314],{"language":16},[18,1174,1176,1177,1180],{"id":1175},"q9-what-happens-if-you-attempt-to-define-a-gat-style-associated-type-where-the-type-parameter-needs-a-where-self-a-bound-but-you-omit-it","Q9. What happens if you attempt to define a GAT-style associated type where the type parameter needs a ",[32,1178,1179],{},"where Self: 'a"," bound but you omit it?",[23,1182,1183],{"language":16},[26,1184,1186],{"className":28,"code":1185,"language":16,"meta":30,"style":30},"trait LendingIterator {\n    type Item\u003C'a> where Self: 'a;\n    fn next\u003C'a>(&'a mut self) -> Option\u003CSelf::Item\u003C'a>>;\n}\n",[32,1187,1188,1197,1226,1272],{"__ignoreMap":30},[35,1189,1190,1192,1195],{"class":37,"line":38},[35,1191,42],{"class":41},[35,1193,1194],{"class":45}," LendingIterator",[35,1196,50],{"class":49},[35,1198,1199,1201,1203,1206,1209,1212,1215,1217,1219,1222,1224],{"class":37,"line":53},[35,1200,56],{"class":41},[35,1202,59],{"class":45},[35,1204,1205],{"class":49},"\u003C'",[35,1207,1208],{"class":45},"a",[35,1210,1211],{"class":49},"> ",[35,1213,1214],{"class":41},"where",[35,1216,672],{"class":80},[35,1218,156],{"class":41},[35,1220,1221],{"class":49}," '",[35,1223,1208],{"class":45},[35,1225,62],{"class":49},[35,1227,1228,1230,1232,1234,1236,1239,1241,1244,1246,1249,1251,1253,1255,1257,1259,1261,1263,1265,1267,1269],{"class":37,"line":65},[35,1229,68],{"class":41},[35,1231,71],{"class":45},[35,1233,1205],{"class":49},[35,1235,1208],{"class":45},[35,1237,1238],{"class":49},">(",[35,1240,147],{"class":41},[35,1242,1243],{"class":49},"'",[35,1245,1208],{"class":45},[35,1247,1248],{"class":41}," mut",[35,1250,81],{"class":80},[35,1252,84],{"class":49},[35,1254,87],{"class":41},[35,1256,90],{"class":45},[35,1258,93],{"class":49},[35,1260,96],{"class":80},[35,1262,99],{"class":41},[35,1264,102],{"class":45},[35,1266,1205],{"class":49},[35,1268,1208],{"class":45},[35,1270,1271],{"class":49},">>;\n",[35,1273,1274],{"class":37,"line":108},[35,1275,111],{"class":49},[180,1277,1279,1290,1299,1305],{"className":1278},[183],[185,1280,1282,1284,1285,1287,1288],{"className":1281},[188],[190,1283],{"disabled":117,"type":192}," Omitting a required ",[32,1286,1179],{}," clause on a GAT typically produces a compile error demanding the bound, because without it the compiler cannot prove the associated type's lifetime is compatible with borrows of ",[32,1289,96],{},[185,1291,1293,1295,1296],{"className":1292},[188],[190,1294],{"disabled":117,"type":192}," The bound is optional stylistic sugar; omitting it silently defaults to ",[32,1297,1298],{},"'static",[185,1300,1302,1304],{"className":1301},[188],[190,1303],{"disabled":117,"type":192}," Omitting it causes a runtime panic the first time the associated type is instantiated",[185,1306,1308,1310,1311,1313],{"className":1307},[188],[190,1309],{"disabled":117,"type":192}," It compiles identically either way; ",[32,1312,1179],{}," has no semantic effect on GATs",[213,1315,1316,1318,1326],{},[216,1317,218],{},[220,1319,1320,1322,1323,1325],{},[223,1321,225],{}," A — omitting a required ",[32,1324,1179],{}," clause is a compile error demanding the bound",[220,1327,1328,1330,1331,1333,1334,1337,1338,1340,1341,1343,1344,1346,1347,1350,1351,1353],{},[223,1329,231],{}," GATs that borrow from ",[32,1332,96],{}," (like a lending iterator's ",[32,1335,1336],{},"Item\u003C'a>",") generally need a ",[32,1339,1179],{}," clause so the compiler can verify, for every concrete lifetime ",[32,1342,498],{}," the associated type gets instantiated with, that ",[32,1345,96],{}," itself lives at least that long — without it, downstream code manipulating ",[32,1348,1349],{},"Self::Item\u003C'a>"," couldn't safely assume this relationship and the compiler rejects the trait definition (or usages of it) with a lifetime-bound error. It's not sugar and not optional when the implementation actually needs it, there's no ",[32,1352,1298],{}," default, and this is caught entirely at compile time — GATs, like all Rust generics, have no runtime instantiation step to panic during.",[14,1355,1356,1364,1415],{},[18,1357,1359,1360,1363],{"id":1358},"q10-a-trait-method-has-this-signature-fn-processt-sendself-val-t-can-this-trait-still-be-object-safe-overall-assuming-this-is-its-only-method","Q10. A trait method has this signature: ",[32,1361,1362],{},"fn process\u003CT: Send>(&self, val: T);",". Can this trait still be object-safe overall (assuming this is its only method)?",[180,1365,1367,1379,1388,1402],{"className":1366},[183],[185,1368,1370,1372,1373,1375,1376,1378],{"className":1369},[188],[190,1371],{"disabled":117,"type":192}," No — a generic method (one with its own type parameters beyond ",[32,1374,96],{},") makes the trait not object-safe, because the vtable would need a separate entry per possible ",[32,1377,131],{},", which is unbounded",[185,1380,1382,1384,1385,1387],{"className":1381},[188],[190,1383],{"disabled":117,"type":192}," Yes — ",[32,1386,512],{}," bounds have no effect on object safety, only lifetime bounds do",[185,1389,1391,1393,1394,1397,1398,1401],{"className":1390},[188],[190,1392],{"disabled":117,"type":192}," Yes — as long as ",[32,1395,1396],{},"T: Send"," and not ",[32,1399,1400],{},"T: 'static",", generic methods are exempted from the object-safety rule",[185,1403,1405,1407,1408,1410,1411,1414],{"className":1404},[188],[190,1406],{"disabled":117,"type":192}," No — but only because ",[32,1409,1137],{}," should be ",[32,1412,1413],{},"&mut self"," for the method to be considered",[213,1416,1417,1419,1424],{},[216,1418,218],{},[220,1420,1421,1423],{},[223,1422,225],{}," A — a generic method makes the trait not object-safe, since the vtable can't have unboundedly many entries",[220,1425,1426,1428,1429,1432,1433,1435,1436,1438,1439,1441,1442,1444,1445,1447,1448,1450],{},[223,1427,231],{}," A vtable is a fixed, finite table of function pointers built once per concrete implementing type; a generic method like ",[32,1430,1431],{},"process\u003CT>"," would need a distinct function pointer per possible ",[32,1434,131],{}," used at any call site anywhere in the program, which is open-ended and unknowable at the point the vtable is built. This makes any trait with a generic method (regardless of what bound, ",[32,1437,512],{}," or otherwise, is on that generic parameter) non-object-safe for that method — though the trait can still be used as ",[32,1440,813],{}," or with static dispatch, or the method can be excluded from the vtable via ",[32,1443,607],{}," on just that method. The receiver being ",[32,1446,1137],{}," vs ",[32,1449,1413],{}," is unrelated to this particular restriction.",[14,1452,1453,1466,1546,1590],{"language":16},[18,1454,1456,1457,1459,1460,243,1462,1465],{"id":1455},"q11-what-is-the-compile-time-behavior-of-this-code-given-that-iterator-has-one-associated-type-item-and-dyn-iterator-no-type-argument-is-written-without-specifying-it","Q11. What is the compile-time behavior of this code, given that ",[32,1458,261],{}," has one associated type ",[32,1461,102],{},[32,1463,1464],{},"dyn Iterator"," (no type argument) is written without specifying it?",[23,1467,1468],{"language":16},[26,1469,1471],{"className":28,"code":1470,"language":16,"meta":30,"style":30},"fn make_iter() -> Box\u003Cdyn Iterator> {\n    Box::new(vec![1, 2, 3].into_iter())\n}\n",[32,1472,1473,1498,1542],{"__ignoreMap":30},[35,1474,1475,1478,1481,1484,1486,1489,1491,1493,1496],{"class":37,"line":38},[35,1476,1477],{"class":41},"fn",[35,1479,1480],{"class":45}," make_iter",[35,1482,1483],{"class":49},"() ",[35,1485,87],{"class":41},[35,1487,1488],{"class":45}," Box",[35,1490,93],{"class":49},[35,1492,738],{"class":41},[35,1494,1495],{"class":45}," Iterator",[35,1497,134],{"class":49},[35,1499,1500,1503,1505,1508,1510,1513,1516,1519,1522,1525,1527,1530,1533,1536,1539],{"class":37,"line":53},[35,1501,1502],{"class":45},"    Box",[35,1504,99],{"class":41},[35,1506,1507],{"class":45},"new",[35,1509,74],{"class":49},[35,1511,1512],{"class":45},"vec!",[35,1514,1515],{"class":49},"[",[35,1517,1518],{"class":80},"1",[35,1520,1521],{"class":49},", ",[35,1523,1524],{"class":80},"2",[35,1526,1521],{"class":49},[35,1528,1529],{"class":80},"3",[35,1531,1532],{"class":49},"]",[35,1534,1535],{"class":41},".",[35,1537,1538],{"class":45},"into_iter",[35,1540,1541],{"class":49},"())\n",[35,1543,1544],{"class":37,"line":65},[35,1545,111],{"class":49},[180,1547,1549,1558,1571,1584],{"className":1548},[183],[185,1550,1552,1554,1555],{"className":1551},[188],[190,1553],{"disabled":117,"type":192}," Compile error — a trait object over a trait with an associated type must specify that associated type, e.g. ",[32,1556,1557],{},"dyn Iterator\u003CItem = i32>",[185,1559,1561,1563,1564,1566,1567,1570],{"className":1560},[188],[190,1562],{"disabled":117,"type":192}," Compiles fine; the compiler infers ",[32,1565,102],{}," from the ",[32,1568,1569],{},"Box::new"," argument automatically",[185,1572,1574,1576,1577,1579,1580,1583],{"className":1573},[188],[190,1575],{"disabled":117,"type":192}," Compiles fine; ",[32,1578,102],{}," defaults to ",[32,1581,1582],{},"()"," when omitted from a trait object",[185,1585,1587,1589],{"className":1586},[188],[190,1588],{"disabled":117,"type":192}," Compiles fine; associated types are erased entirely for trait objects and don't need specifying",[213,1591,1592,1594,1601],{},[216,1593,218],{},[220,1595,1596,1598,1599],{},[223,1597,225],{}," A — compile error; trait objects must specify associated types explicitly, e.g. ",[32,1600,1557],{},[220,1602,1603,232,1605,1608,1609,1611,1612,1614,1615,1617,1618,1620,1621,1624],{},[223,1604,231],{},[223,1606,1607],{},"Debug:"," Unlike a generic type parameter, an associated type is part of the trait's contract that must be pinned down to form a concrete, well-defined vtable — ",[32,1610,1464],{}," alone is ambiguous about what ",[32,1613,334],{}," returns, so Rust requires ",[32,1616,1557],{}," (or whatever concrete item type) to be written explicitly. This differs from ordinary type inference elsewhere in the language; there's no defaulting to ",[32,1619,1582],{},", no erasure of associated types (the vtable's ",[32,1622,1623],{},"next"," method needs a known return layout), and no automatic inference from the constructor argument in the return-type position — the function signature itself must be unambiguous independent of the body.",[14,1626,1627,1638,1718,1751],{"language":16},[18,1628,1630,1631,1634,1635,1637],{"id":1629},"q12-what-is-the-effect-of-non_exhaustive-combined-with-a-private-field-pattern-versus-using-phantomdata-purely-for-sealing-a-trait-so-external-crates-cannot-implement-it-which-correctly-implements-the-sealed-trait-pattern","Q12. What is the effect of ",[32,1632,1633],{},"#[non_exhaustive]"," combined with a private field pattern versus using ",[32,1636,376],{}," purely for sealing a trait so external crates cannot implement it — which correctly implements the \"sealed trait\" pattern?",[23,1639,1640],{"language":16},[26,1641,1643],{"className":28,"code":1642,"language":16,"meta":30,"style":30},"mod sealed {\n    pub trait Sealed {}\n}\n\npub trait MyTrait: sealed::Sealed {\n    fn method(&self);\n}\n",[32,1644,1645,1655,1669,1673,1677,1698,1714],{"__ignoreMap":30},[35,1646,1647,1650,1653],{"class":37,"line":38},[35,1648,1649],{"class":41},"mod",[35,1651,1652],{"class":45}," sealed",[35,1654,50],{"class":49},[35,1656,1657,1660,1663,1666],{"class":37,"line":53},[35,1658,1659],{"class":41},"    pub",[35,1661,1662],{"class":41}," trait",[35,1664,1665],{"class":45}," Sealed",[35,1667,1668],{"class":49}," {}\n",[35,1670,1671],{"class":37,"line":65},[35,1672,111],{"class":49},[35,1674,1675],{"class":37,"line":108},[35,1676,118],{"emptyLinePlaceholder":117},[35,1678,1679,1682,1684,1687,1689,1691,1693,1696],{"class":37,"line":114},[35,1680,1681],{"class":41},"pub",[35,1683,1662],{"class":41},[35,1685,1686],{"class":45}," MyTrait",[35,1688,156],{"class":41},[35,1690,1652],{"class":45},[35,1692,99],{"class":41},[35,1694,1695],{"class":45},"Sealed",[35,1697,50],{"class":49},[35,1699,1700,1702,1705,1707,1709,1711],{"class":37,"line":121},[35,1701,68],{"class":41},[35,1703,1704],{"class":45}," method",[35,1706,74],{"class":49},[35,1708,147],{"class":41},[35,1710,150],{"class":80},[35,1712,1713],{"class":49},");\n",[35,1715,1716],{"class":37,"line":137},[35,1717,111],{"class":49},[180,1719,1721,1727,1736,1745],{"className":1720},[183],[185,1722,1724,1726],{"className":1723},[188],[190,1725],{"disabled":117,"type":192}," Making the public trait require a supertrait defined in a private module that external crates cannot name or implement, so they cannot satisfy the supertrait bound and thus cannot implement the public trait",[185,1728,1730,1732,1733,1735],{"className":1729},[188],[190,1731],{"disabled":117,"type":192}," Adding ",[32,1734,1633],{}," to the trait definition itself prevents external implementations",[185,1737,1739,1741,1742,1744],{"className":1738},[188],[190,1740],{"disabled":117,"type":192}," Using ",[32,1743,376],{}," as an associated type prevents external crates from implementing the trait",[185,1746,1748,1750],{"className":1747},[188],[190,1749],{"disabled":117,"type":192}," There is no way to prevent external crates from implementing a public trait; visibility only affects structs and enums",[213,1752,1753,1755,1760],{},[216,1754,218],{},[220,1756,1757,1759],{},[223,1758,225],{}," A — require a supertrait from a private module that outside crates can't name or implement",[220,1761,1762,232,1764,1767,1768,1771,1772,1775,1776,1779,1780,1784,1785,1787,1788,1790,1791,1793,1794,1796,1797,1799,1800,1802,1803,1806],{},[223,1763,231],{},[223,1765,1766],{},"Idiom:"," The \"sealed trait\" pattern exploits the fact that implementing ",[32,1769,1770],{},"MyTrait"," requires also implementing ",[32,1773,1774],{},"sealed::Sealed",", but ",[32,1777,1778],{},"sealed"," is a private module — external crates can ",[1781,1782,1783],"em",{},"see"," and use ",[32,1786,1770],{}," (it's ",[32,1789,1681],{},") but cannot name ",[32,1792,1774],{}," to provide an impl of it, so they're structurally barred from ever implementing ",[32,1795,1770],{},", while code within the defining crate can implement both freely. ",[32,1798,1633],{}," only affects exhaustive matching\u002Fconstruction of structs, enums, and variants — it has no effect on trait implementability. ",[32,1801,376],{}," is a marker for variance\u002Fdrop-check, unrelated to sealing. This pattern is exactly why sealing traits ",[1781,1804,1805],{},"is"," possible, contrary to the last option.",[14,1808,1809,1824,1956,2001],{"language":16},[18,1810,1812,1813,1816,1817,1820,1821,636],{"id":1811},"q13-whats-wrong-with-this-attempt-to-implement-a-trait-generically-for-a-type-parameter-assuming-wrappert-is-a-local-struct-and-display-is-from-stdfmt","Q13. What's wrong with this attempt to implement a trait generically for a type parameter, assuming ",[32,1814,1815],{},"Wrapper\u003CT>"," is a local struct and ",[32,1818,1819],{},"Display"," is from ",[32,1822,1823],{},"std::fmt",[23,1825,1826],{"language":16},[26,1827,1829],{"className":28,"code":1828,"language":16,"meta":30,"style":30},"struct Wrapper\u003CT>(T);\n\nimpl\u003CT> std::fmt::Display for T {\n    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {\n        write!(f, \"generic\")\n    }\n}\n",[32,1830,1831,1848,1852,1883,1932,1947,1952],{"__ignoreMap":30},[35,1832,1833,1835,1838,1840,1842,1844,1846],{"class":37,"line":38},[35,1834,387],{"class":41},[35,1836,1837],{"class":45}," Wrapper",[35,1839,93],{"class":49},[35,1841,131],{"class":45},[35,1843,1238],{"class":49},[35,1845,131],{"class":45},[35,1847,1713],{"class":49},[35,1849,1850],{"class":37,"line":53},[35,1851,118],{"emptyLinePlaceholder":117},[35,1853,1854,1857,1859,1861,1863,1866,1868,1871,1873,1875,1878,1881],{"class":37,"line":65},[35,1855,1856],{"class":41},"impl",[35,1858,93],{"class":49},[35,1860,131],{"class":45},[35,1862,1211],{"class":49},[35,1864,1865],{"class":45},"std",[35,1867,99],{"class":41},[35,1869,1870],{"class":45},"fmt",[35,1872,99],{"class":41},[35,1874,1819],{"class":45},[35,1876,1877],{"class":41}," for",[35,1879,1880],{"class":45}," T",[35,1882,50],{"class":49},[35,1884,1885,1887,1890,1892,1894,1896,1899,1901,1904,1906,1908,1910,1912,1915,1917,1919,1921,1923,1925,1927,1930],{"class":37,"line":108},[35,1886,68],{"class":41},[35,1888,1889],{"class":45}," fmt",[35,1891,74],{"class":49},[35,1893,147],{"class":41},[35,1895,150],{"class":80},[35,1897,1898],{"class":49},", f",[35,1900,156],{"class":41},[35,1902,1903],{"class":41}," &mut",[35,1905,366],{"class":45},[35,1907,99],{"class":41},[35,1909,1870],{"class":45},[35,1911,99],{"class":41},[35,1913,1914],{"class":45},"Formatter",[35,1916,84],{"class":49},[35,1918,87],{"class":41},[35,1920,366],{"class":45},[35,1922,99],{"class":41},[35,1924,1870],{"class":45},[35,1926,99],{"class":41},[35,1928,1929],{"class":45},"Result",[35,1931,50],{"class":49},[35,1933,1934,1937,1940,1944],{"class":37,"line":114},[35,1935,1936],{"class":45},"        write!",[35,1938,1939],{"class":49},"(f, ",[35,1941,1943],{"class":1942},"sJ6F3","\"generic\"",[35,1945,1946],{"class":49},")\n",[35,1948,1949],{"class":37,"line":121},[35,1950,1951],{"class":49},"    }\n",[35,1953,1954],{"class":37,"line":137},[35,1955,111],{"class":49},[180,1957,1959,1974,1980,1992],{"className":1958},[183],[185,1960,1962,1964,1965,1967,1968,1970,1971,1973],{"className":1961},[188],[190,1963],{"disabled":117,"type":192}," This violates the orphan rule: you cannot implement a foreign trait (",[32,1966,1819],{},", from ",[32,1969,1865],{},") for a fully generic, unconstrained type ",[32,1972,131],{}," that isn't local to this crate — it must be a local type or the trait must be local",[185,1975,1977,1979],{"className":1976},[188],[190,1978],{"disabled":117,"type":192}," This is valid but only compiles in edition 2021 and later",[185,1981,1983,1985,1986,1988,1989,1991],{"className":1982},[188],[190,1984],{"disabled":117,"type":192}," The error is that ",[32,1987,1815],{}," should have been used instead of ",[32,1990,131],{},", but otherwise the pattern is fine",[185,1993,1995,1997,1998,2000],{"className":1994},[188],[190,1996],{"disabled":117,"type":192}," This is legal Rust; the orphan rule only restricts ",[32,1999,1856],{}," blocks for concrete foreign types, not generic ones",[213,2002,2003,2005,2013],{},[216,2004,218],{},[220,2006,2007,2009,2010,2012],{},[223,2008,225],{}," A — this violates the orphan rule; both the trait and the blanket-implemented type must have some local connection, and a bare unconstrained ",[32,2011,131],{}," has none",[220,2014,2015,232,2017,2019,2020,2023,2024,327,2027,2030,2031,2033,2034,2036,2037,2039,2040,2042,2043,2046,2047,2050,2051,2053,2054,2056],{},[223,2016,231],{},[223,2018,1106],{}," The orphan rule requires that for ",[32,2021,2022],{},"impl Trait for Type",", either ",[32,2025,2026],{},"Trait",[32,2028,2029],{},"Type"," be local to the current crate (with generic parameters needing to appear \"covered\" by a local type when the trait is foreign). Here ",[32,2032,1819],{}," is foreign (from ",[32,2035,1865],{},") and ",[32,2038,131],{}," is a fully generic, uncovered type parameter — not ",[32,2041,1815],{},", which ",[1781,2044,2045],{},"would"," be local and legal (",[32,2048,2049],{},"impl\u003CT: Display> Display for Wrapper\u003CT>"," compiles fine). Allowing a blanket foreign-trait-for-any-",[32,2052,131],{}," impl would let any crate globally claim ",[32,2055,1819],{}," for every type in the ecosystem, causing unresolvable conflicts if two crates both tried it — exactly the coherence violation the orphan rule exists to prevent. This is not edition-gated; the rule is a fundamental, long-standing part of trait coherence.",[14,2058,2059,2067,2145,2178],{"language":16},[18,2060,2062,2063,2066],{"id":2061},"q14-what-does-self-sized-mean-when-added-as-a-bound-to-an-individual-trait-method-and-why-would-you-add-it","Q14. What does ",[32,2064,2065],{},"Self: Sized"," mean when added as a bound to an individual trait method, and why would you add it?",[23,2068,2069],{"language":16},[26,2070,2072],{"className":28,"code":2071,"language":16,"meta":30,"style":30},"trait Shape {\n    fn area(&self) -> f64;\n    fn scaled(self, factor: f64) -> Self where Self: Sized;\n}\n",[32,2073,2074,2083,2105,2141],{"__ignoreMap":30},[35,2075,2076,2078,2081],{"class":37,"line":38},[35,2077,42],{"class":41},[35,2079,2080],{"class":45}," Shape",[35,2082,50],{"class":49},[35,2084,2085,2087,2090,2092,2094,2096,2098,2100,2103],{"class":37,"line":53},[35,2086,68],{"class":41},[35,2088,2089],{"class":45}," area",[35,2091,74],{"class":49},[35,2093,147],{"class":41},[35,2095,150],{"class":80},[35,2097,84],{"class":49},[35,2099,87],{"class":41},[35,2101,2102],{"class":45}," f64",[35,2104,62],{"class":49},[35,2106,2107,2109,2112,2114,2116,2119,2121,2123,2125,2127,2129,2132,2134,2136,2139],{"class":37,"line":65},[35,2108,68],{"class":41},[35,2110,2111],{"class":45}," scaled",[35,2113,74],{"class":49},[35,2115,150],{"class":80},[35,2117,2118],{"class":49},", factor",[35,2120,156],{"class":41},[35,2122,2102],{"class":45},[35,2124,84],{"class":49},[35,2126,87],{"class":41},[35,2128,672],{"class":80},[35,2130,2131],{"class":41}," where",[35,2133,672],{"class":80},[35,2135,156],{"class":41},[35,2137,2138],{"class":45}," Sized",[35,2140,62],{"class":49},[35,2142,2143],{"class":37,"line":108},[35,2144,111],{"class":49},[180,2146,2148,2160,2166,2172],{"className":2147},[183],[185,2149,2151,2153,2154,2156,2157],{"className":2150},[188],[190,2152],{"disabled":117,"type":192}," It opts that specific method out of being included in the trait's vtable, allowing the rest of the trait to remain object-safe even though this one method (which takes\u002Freturns ",[32,2155,96],{}," by value) could not itself be called through ",[32,2158,2159],{},"dyn Shape",[185,2161,2163,2165],{"className":2162},[188],[190,2164],{"disabled":117,"type":192}," It forces every implementor of the trait to be a fixed, statically known size at compile time, which all Rust types already are by default anyway so the bound is meaningless",[185,2167,2169,2171],{"className":2168},[188],[190,2170],{"disabled":117,"type":192}," It's required on every trait method as boilerplate and has no functional effect",[185,2173,2175,2177],{"className":2174},[188],[190,2176],{"disabled":117,"type":192}," It disables monomorphization for that method, forcing dynamic dispatch even when called via a generic",[213,2179,2180,2182,2189],{},[216,2181,218],{},[220,2183,2184,2186,2187],{},[223,2185,225],{}," A — it excludes that method from the vtable, letting the rest of the trait stay object-safe despite this method being incompatible with ",[32,2188,738],{},[220,2190,2191,232,2193,2195,2196,2198,2199,2202,2203,2205,2206,2209,2210,2212,2213,2215,2216,2218,2219,2222,2223,2225,2226,2229,2230,2232,2233,2236],{},[223,2192,231],{},[223,2194,1766],{}," Methods that take or return ",[32,2197,96],{}," by value (like ",[32,2200,2201],{},"scaled",", which consumes and returns ",[32,2204,96],{},") are individually incompatible with dynamic dispatch for the same reason ",[32,2207,2208],{},"Clone::clone"," is — the vtable can't represent an unsized-context by-value ",[32,2211,96],{},". Adding ",[32,2214,607],{}," to just that method tells the compiler \"this method is unavailable when called through ",[32,2217,2159],{},",\" which excludes it from the vtable while leaving the rest of the trait (like ",[32,2220,2221],{},"area(&self)",") usable through ",[32,2224,2159],{}," — a common technique to make otherwise-inconvenient traits partially object-safe. It's not boilerplate (most methods don't need it), it doesn't relate to monomorphization\u002Fdispatch selection for other calls, and while most types genuinely are ",[32,2227,2228],{},"Sized"," by default, trait objects (",[32,2231,542],{},") and slices (",[32,2234,2235],{},"[T]",") are the important unsized exceptions this bound is specifically excluding.",[14,2238,2239,2243,2277],{},[18,2240,2242],{"id":2241},"q15-when-designing-a-trait-when-should-you-prefer-an-associated-type-over-a-generic-type-parameter-as-a-matter-of-api-design-idiom","Q15. When designing a trait, when should you prefer an associated type over a generic type parameter as a matter of API design idiom?",[180,2244,2246,2259,2265,2271],{"className":2245},[183],[185,2247,2249,2251,2252,2254,2255,2258],{"className":2248},[188],[190,2250],{"disabled":117,"type":192}," When there is logically only one sensible output type per implementation (e.g. one ",[32,2253,102],{}," type per iterator, one ",[32,2256,2257],{},"Error"," type per parser) — use an associated type; when a type can meaningfully implement the trait multiple times for different type arguments, use a generic parameter",[185,2260,2262,2264],{"className":2261},[188],[190,2263],{"disabled":117,"type":192}," Always prefer generic type parameters; associated types are a legacy feature kept only for backward compatibility",[185,2266,2268,2270],{"className":2267},[188],[190,2269],{"disabled":117,"type":192}," Associated types should be used whenever performance matters, since they avoid monomorphization",[185,2272,2274,2276],{"className":2273},[188],[190,2275],{"disabled":117,"type":192}," It's purely a stylistic choice with no design implications either way",[213,2278,2279,2281,2286],{},[216,2280,218],{},[220,2282,2283,2285],{},[223,2284,225],{}," A — use an associated type when there's one canonical output per impl; use a generic when a type can implement the trait multiple ways",[220,2287,2288,232,2290,2292,2293,1521,2296,2299,2300,2303,2304,2307,2308,2311,2312,2314,2315,513,2317,2320,2321,1521,2324,2327,2328,2330],{},[223,2289,231],{},[223,2291,1766],{}," This is the standard Rust API-design heuristic: ",[32,2294,2295],{},"Iterator::Item",[32,2297,2298],{},"Add::Output",", and ",[32,2301,2302],{},"Deref::Target"," are associated types because a given type has exactly one sensible answer (a ",[32,2305,2306],{},"Vec\u003Ci32>","'s iterator only ever yields ",[32,2309,2310],{},"i32","), which also gives callers cleaner type inference (no need to annotate ",[32,2313,102],{}," at every call site). ",[32,2316,268],{},[32,2318,2319],{},"Into\u003CT>"," are generic-parameterized because a single type genuinely can convert from many different source types (",[32,2322,2323],{},"String: From\u003C&str>",[32,2325,2326],{},"String: From\u003Cchar>",", etc.), which associated types couldn't express since each impl would collide. Neither choice affects monomorphization or dispatch strategy by itself — that's a function of ",[32,2329,738],{}," vs static generics, orthogonal to associated-type-vs-generic-parameter. This is a real, consequential API design decision, not a stylistic wash.",[14,2332,2333,2345,2398],{},[18,2334,2336,2337,2340,2341,2344],{"id":2335},"q16-a-crate-defines-trait-repositoryt-fn-saveself-item-t-and-separately-has-three-concrete-repository-structs-a-reviewer-suggests-switching-to-trait-repository-type-item-fn-saveself-item-selfitem-instead-when-is-this-refactor-the-better-idiomatic-choice","Q16. A crate defines ",[32,2338,2339],{},"trait Repository\u003CT> { fn save(&self, item: T); }"," and separately has three concrete repository structs. A reviewer suggests switching to ",[32,2342,2343],{},"trait Repository { type Item; fn save(&self, item: Self::Item); }"," instead. When is this refactor the better idiomatic choice?",[180,2346,2348,2368,2374,2388],{"className":2347},[183],[185,2349,2351,2353,2354,243,2357,2360,2361,2364,2365,2367],{"className":2350},[188],[190,2352],{"disabled":117,"type":192}," When each concrete repository type is only ever meant to store one specific item type — the associated-type version prevents accidentally implementing ",[32,2355,2356],{},"Repository\u003CFoo>",[32,2358,2359],{},"Repository\u003CBar>"," on the same struct and simplifies generic code that's writing against ",[32,2362,2363],{},"impl Repository"," without specifying ",[32,2366,131],{}," everywhere",[185,2369,2371,2373],{"className":2370},[188],[190,2372],{"disabled":117,"type":192}," Never — generic parameters are strictly more powerful and associated types should be avoided whenever a generic would also work",[185,2375,2377,2379,2380,2382,2383,327,2385],{"className":2376},[188],[190,2378],{"disabled":117,"type":192}," Only when ",[32,2381,131],{}," is a primitive type like ",[32,2384,2310],{},[32,2386,2387],{},"bool",[185,2389,2391,2393,2394,2397],{"className":2390},[188],[190,2392],{"disabled":117,"type":192}," Only if ",[32,2395,2396],{},"Repository"," needs to be object-safe, since generic-parameter traits are always automatically object-safe",[213,2399,2400,2402,2407],{},[216,2401,218],{},[220,2403,2404,2406],{},[223,2405,225],{}," A — when each repository is meant to store exactly one item type, associated types prevent accidental multi-impl and simplify generic call sites",[220,2408,2409,232,2411,878,2413,2416,2417,2420,2421,2424,2425,2428,2429,2432,2433,2436,2437,2439,2440,2443,2444,2447,2448,2450,2451,2454,2455,2457],{},[223,2410,231],{},[223,2412,1766],{},[32,2414,2415],{},"UserRepository"," should only ever save ",[32,2418,2419],{},"User","s, the generic version ",[32,2422,2423],{},"Repository\u003CT>"," technically permits also implementing ",[32,2426,2427],{},"Repository\u003COtherType>"," on the same struct by accident (nothing stops it), while ",[32,2430,2431],{},"Repository { type Item; }"," makes \"one item type per repository\" a structural guarantee. It also means code generic over ",[32,2434,2435],{},"fn process\u003CR: Repository>(repo: R)"," doesn't need an extra ",[32,2438,131],{}," parameter threaded through — ",[32,2441,2442],{},"R::Item"," is derivable. This is a real trade-off, not a strict-dominance situation — generics remain correct when multiple simultaneous implementations genuinely make sense (as in Q1's ",[32,2445,2446],{},"Container\u003CT>","). Object safety is unrelated: a generic-parameter trait like ",[32,2449,2423],{}," is not automatically object-safe either — ",[32,2452,2453],{},"dyn Repository\u003CT>"," still needs a concrete ",[32,2456,131],{}," picked, same as an associated type needing to be pinned down; generic methods within an impl are what break object safety, not the presence of a type parameter on the trait itself.",[14,2459,2460,2470,2511],{},[18,2461,2463,2464,2466,2467,636],{"id":2462},"q17-in-idiomatic-rust-when-should-a-public-api-function-accept-impl-trait-in-argument-position-versus-dyn-trait","Q17. In idiomatic Rust, when should a public API function accept ",[32,2465,813],{}," in argument position versus ",[32,2468,2469],{},"&dyn Trait",[180,2471,2473,2485,2497,2503],{"className":2472},[183],[185,2474,2476,2478,2479,2481,2482,2484],{"className":2475},[188],[190,2477],{"disabled":117,"type":192}," Prefer ",[32,2480,813],{}," (or a generic bound) by default for performance-sensitive or small-surface-area APIs since it enables inlining and avoids vtable indirection; reach for ",[32,2483,2469],{}," when you need to store heterogeneous trait objects in a collection, reduce compile times\u002Fbinary size from excessive monomorphization, or avoid generic code bloat across many call sites",[185,2486,2488,2490,2491,2493,2494,2496],{"className":2487},[188],[190,2489],{"disabled":117,"type":192}," Always use ",[32,2492,2469],{},"; ",[32,2495,813],{}," in argument position is deprecated",[185,2498,2500,2502],{"className":2499},[188],[190,2501],{"disabled":117,"type":192}," They are interchangeable in every context including trait method signatures used as trait objects",[185,2504,2506,2478,2508,2510],{"className":2505},[188],[190,2507],{"disabled":117,"type":192},[32,2509,813],{}," only for return types, never for arguments — using it for arguments is a syntax error",[213,2512,2513,2515,2526],{},[216,2514,218],{},[220,2516,2517,2519,2520,2522,2523,2525],{},[223,2518,225],{}," A — default to ",[32,2521,813],{},"\u002Fgenerics for performance; use ",[32,2524,2469],{}," for heterogeneous collections or to curb monomorphization bloat",[220,2527,2528,232,2530,2533,2534,2536,2537,2540,2541,2543,2544,2546,2547,2549,2550,2552,2553,2555,2556,2558],{},[223,2529,231],{},[223,2531,2532],{},"Performance\u002FIdiom:"," This mirrors the static-vs-dynamic dispatch trade-off from Q6: ",[32,2535,813],{}," arguments get monomorphized per call site, which is usually the right default for hot paths since it allows inlining, but if a function is called with many different concrete types across a large codebase, or if you need a ",[32,2538,2539],{},"Vec\u003CBox\u003Cdyn Trait>>"," of mixed concrete types, ",[32,2542,542],{}," avoids both the code-size explosion and enables true runtime heterogeneity that generics fundamentally cannot express (a ",[32,2545,973],{}," can only hold one ",[32,2548,131],{},"). ",[32,2551,813],{}," in argument position is valid, current, non-deprecated syntax and works in both positions (though the two behave differently in the two positions regarding caller vs. callee choosing the type) — this option is fabricated. And ",[32,2554,813],{}," cannot be used directly in a trait method signature that also needs to be object-safe\u002Fused as ",[32,2557,738],{},", since that would itself introduce a hidden generic parameter, colliding with object-safety rules from Q10.",[14,2560,2561,2568,2648,2675],{"language":16},[18,2562,2564,2565,2567],{"id":2563},"q18-what-is-the-idiomatic-reason-to-reach-for-a-gat-instead-of-just-returning-owned-data-cloning-from-a-trait-method-that-would-otherwise-need-to-borrow-from-mut-self-per-call","Q18. What is the idiomatic reason to reach for a GAT instead of just returning owned data (cloning) from a trait method that would otherwise need to borrow from ",[32,2566,1413],{}," per call?",[23,2569,2570],{"language":16},[26,2571,2573],{"className":28,"code":2572,"language":16,"meta":30,"style":30},"trait WindowIterator {\n    type Window\u003C'a> where Self: 'a;\n    fn next_window(&mut self) -> Option\u003CSelf::Window\u003C'_>>;\n}\n",[32,2574,2575,2584,2609,2644],{"__ignoreMap":30},[35,2576,2577,2579,2582],{"class":37,"line":38},[35,2578,42],{"class":41},[35,2580,2581],{"class":45}," WindowIterator",[35,2583,50],{"class":49},[35,2585,2586,2588,2591,2593,2595,2597,2599,2601,2603,2605,2607],{"class":37,"line":53},[35,2587,56],{"class":41},[35,2589,2590],{"class":45}," Window",[35,2592,1205],{"class":49},[35,2594,1208],{"class":45},[35,2596,1211],{"class":49},[35,2598,1214],{"class":41},[35,2600,672],{"class":80},[35,2602,156],{"class":41},[35,2604,1221],{"class":49},[35,2606,1208],{"class":45},[35,2608,62],{"class":49},[35,2610,2611,2613,2616,2618,2620,2622,2624,2626,2628,2630,2632,2634,2637,2639,2642],{"class":37,"line":65},[35,2612,68],{"class":41},[35,2614,2615],{"class":45}," next_window",[35,2617,74],{"class":49},[35,2619,77],{"class":41},[35,2621,81],{"class":80},[35,2623,84],{"class":49},[35,2625,87],{"class":41},[35,2627,90],{"class":45},[35,2629,93],{"class":49},[35,2631,96],{"class":80},[35,2633,99],{"class":41},[35,2635,2636],{"class":45},"Window",[35,2638,1205],{"class":49},[35,2640,2641],{"class":45},"_",[35,2643,1271],{"class":49},[35,2645,2646],{"class":37,"line":108},[35,2647,111],{"class":49},[180,2649,2651,2657,2663,2669],{"className":2650},[183],[185,2652,2654,2656],{"className":2653},[188],[190,2655],{"disabled":117,"type":192}," To avoid the allocation\u002Fclone cost of materializing owned data on every call when the underlying data can instead be borrowed directly, which matters in hot loops over large buffers",[185,2658,2660,2662],{"className":2659},[188],[190,2661],{"disabled":117,"type":192}," GATs are purely a compile-time convenience with no runtime performance implication either way",[185,2664,2666,2668],{"className":2665},[188],[190,2667],{"disabled":117,"type":192}," Cloning is always faster than borrowing in Rust, so GATs are used for API ergonomics only, never performance",[185,2670,2672,2674],{"className":2671},[188],[190,2673],{"disabled":117,"type":192}," GATs eliminate the need for lifetimes entirely in the method signature",[213,2676,2677,2679,2684],{},[216,2678,218],{},[220,2680,2681,2683],{},[223,2682,225],{}," A — to avoid allocation\u002Fclone overhead by borrowing directly instead of materializing owned copies each call",[220,2685,2686,232,2688,2690,2691,2693,2694,2697,2698,2700,2701,2704,2705,2708],{},[223,2687,231],{},[223,2689,841],{}," Before GATs, a trait method wanting to return \"a view into ",[32,2692,150],{},"\" per call had no way to express a per-call lifetime in an associated type, so implementors were forced to either return owned\u002Fcloned data (extra allocation and copying on every iteration) or use awkward external-iteration workarounds. GATs let ",[32,2695,2696],{},"Window\u003C'a>"," borrow from ",[32,2699,150],{}," for exactly the call's lifetime, which is why \"lending iterators\" over large in-memory buffers (audio samples, matrix rows, parser tokens) benefit — no per-item allocation. It's very much a runtime-performance-relevant feature, not merely compile-time sugar, cloning is not \"always faster\" (it's essentially always slower or equal, since it does strictly more work than a borrow), and lifetimes remain very much present in GAT signatures (",[32,2702,2703],{},"Self::Window\u003C'_>",") — GATs add lifetime ",[1781,2706,2707],{},"parameters"," to associated types, they don't remove lifetimes from the picture.",[14,2710,2711,2722,2764],{},[18,2712,2714,2715,2718,2719,2721],{"id":2713},"q19-why-does-the-standard-library-not-define-iteratornextmut-self-optionselfitem_-ie-why-is-the-standard-iteratoritem-not-a-gat-even-though-a-lending-iterator-would-seem-more-general","Q19. Why does the standard library NOT define ",[32,2716,2717],{},"Iterator::next(&mut self) -> Option\u003CSelf::Item\u003C'_>>"," (i.e. why is the standard ",[32,2720,2295],{}," not a GAT), even though a \"lending iterator\" would seem more general?",[180,2723,2725,2741,2747,2756],{"className":2724},[183],[185,2726,2728,2730,2731,2733,2734,2737,2738,2740],{"className":2727},[188],[190,2729],{"disabled":117,"type":192}," Making ",[32,2732,102],{}," a GAT would break an enormous amount of existing code that relies on being able to hold multiple yielded items simultaneously (e.g. collecting into a ",[32,2735,2736],{},"Vec","), since a lending iterator's items are tied to the borrow of ",[32,2739,150],{}," and can't outlive the next call",[185,2742,2744,2746],{"className":2743},[188],[190,2745],{"disabled":117,"type":192}," The standard library simply hasn't gotten around to it yet and it's a planned future breaking change",[185,2748,2750,2752,2753,2755],{"className":2749},[188],[190,2751],{"disabled":117,"type":192}," GATs didn't exist when ",[32,2754,261],{}," was designed, and Rust never changes existing trait definitions for any reason",[185,2757,2759,232,2761,2763],{"className":2758},[188],[190,2760],{"disabled":117,"type":192},[32,2762,2295],{}," actually is a GAT already; this question's premise is false",[213,2765,2766,2768,2783],{},[216,2767,218],{},[220,2769,2770,2772,2773,2775,2776,2778,2779,2782],{},[223,2771,225],{}," A — a GAT-based ",[32,2774,102],{}," would tie each yielded item to the borrow of ",[32,2777,150],{},", breaking the enormous amount of code that holds multiple items at once (e.g. ",[32,2780,2781],{},"collect()",")",[220,2784,2785,232,2787,232,2790,2792,2793,2795,2796,2799,2800,2802,2803,2806,2807,2809,2810,2813,2814,2816,2817,2820,2821,2823,2824,2826,2827,2830,2831,2833],{},[223,2786,231],{},[223,2788,2789],{},"Safety\u002FIdiom:",[32,2791,261],{},"'s ",[32,2794,102],{}," is deliberately a plain (non-GAT) associated type precisely so that ",[32,2797,2798],{},"iter.next()"," returns something with no borrow-tie to ",[32,2801,150],{},", letting you do ",[32,2804,2805],{},"v.iter().cloned().collect::\u003CVec\u003C_>>()"," or hold many yielded items alive at once — a lending-iterator ",[32,2808,1336],{}," tied to ",[32,2811,2812],{},"&'a mut self"," would forbid exactly this pattern, since each item would have to be dropped or copied before calling ",[32,2815,334],{}," again. This is a genuine, permanent API-design decision (there's ongoing separate work on a distinct ",[32,2818,2819],{},"LendingIterator","-style trait, but it is not, and won't be, a change to ",[32,2822,261],{}," itself) — not a stopgap due to GATs being unavailable at design time (GATs postdate ",[32,2825,261],{}," by years, correct, but that's not why the design stands: it stands because it's the ",[1781,2828,2829],{},"right"," design for the vast majority of iteration use cases). ",[32,2832,2295],{}," in std remains a plain associated type today.",[14,2835,2836,2848,2916,2971],{"language":16},[18,2837,2839,2840,2843,2844,2847],{"id":2838},"q20-a-team-is-designing-a-plugin-trait-meant-to-be-stored-as-vecboxdyn-plugin-and-called-uniformly-one-team-member-proposes-adding-fn-configurec-configmut-self-cfg-c-to-the-trait-whats-the-best-practice-critique","Q20. A team is designing a plugin trait meant to be stored as ",[32,2841,2842],{},"Vec\u003CBox\u003Cdyn Plugin>>"," and called uniformly. One team member proposes adding ",[32,2845,2846],{},"fn configure\u003CC: Config>(&mut self, cfg: C)"," to the trait. What's the best-practice critique?",[23,2849,2850],{"language":16},[26,2851,2853],{"className":28,"code":2852,"language":16,"meta":30,"style":30},"trait Plugin {\n    fn run(&mut self);\n    fn configure\u003CC: Config>(&mut self, cfg: C);\n}\n",[32,2854,2855,2864,2879,2912],{"__ignoreMap":30},[35,2856,2857,2859,2862],{"class":37,"line":38},[35,2858,42],{"class":41},[35,2860,2861],{"class":45}," Plugin",[35,2863,50],{"class":49},[35,2865,2866,2868,2871,2873,2875,2877],{"class":37,"line":53},[35,2867,68],{"class":41},[35,2869,2870],{"class":45}," run",[35,2872,74],{"class":49},[35,2874,77],{"class":41},[35,2876,81],{"class":80},[35,2878,1713],{"class":49},[35,2880,2881,2883,2886,2888,2891,2893,2896,2898,2900,2902,2905,2907,2910],{"class":37,"line":65},[35,2882,68],{"class":41},[35,2884,2885],{"class":45}," configure",[35,2887,93],{"class":49},[35,2889,2890],{"class":45},"C",[35,2892,156],{"class":41},[35,2894,2895],{"class":45}," Config",[35,2897,1238],{"class":49},[35,2899,77],{"class":41},[35,2901,81],{"class":80},[35,2903,2904],{"class":49},", cfg",[35,2906,156],{"class":41},[35,2908,2909],{"class":45}," C",[35,2911,1713],{"class":49},[35,2913,2914],{"class":37,"line":108},[35,2915,111],{"class":49},[180,2917,2919,2933,2943,2959],{"className":2918},[183],[185,2920,2922,2924,2925,2928,2929,2932],{"className":2921},[188],[190,2923],{"disabled":117,"type":192}," The generic method makes ",[32,2926,2927],{},"Plugin"," not object-safe, which directly conflicts with the stated goal of storing plugins as ",[32,2930,2931],{},"Box\u003Cdyn Plugin>","; it should instead take a concrete or enum-based config type, or be moved to a separate non-object-safe extension trait",[185,2934,2936,2938,2939,2942],{"className":2935},[188],[190,2937],{"disabled":117,"type":192}," There's no issue; generic methods work fine on trait objects as long as ",[32,2940,2941],{},"C: Config"," is a marker trait with no methods",[185,2944,2946,2948,2949,2951,2952,2955,2956],{"className":2945},[188],[190,2947],{"disabled":117,"type":192}," The fix is to add ",[32,2950,607],{}," to ",[32,2953,2954],{},"run"," instead of touching ",[32,2957,2958],{},"configure",[185,2960,2962,232,2964,2966,2967,2970],{"className":2961},[188],[190,2963],{"disabled":117,"type":192},[32,2965,2931],{}," would still compile, but calling ",[32,2968,2969],{},".configure()"," through it would panic at runtime instead of failing to compile",[213,2972,2973,2975,2983],{},[216,2974,218],{},[220,2976,2977,2979,2980,2982],{},[223,2978,225],{}," A — a generic method breaks object safety, conflicting with the ",[32,2981,2931],{}," requirement; use a concrete\u002Fenum config type or split it into a separate trait",[220,2984,2985,232,2987,2990,2991,2993,2994,2997,2998,3000,3001,3004,3005,3008,3009,3011,3012,3014,3015,2951,3017,3019,3020,3022,3023,3025],{},[223,2986,231],{},[223,2988,2989],{},"Idiom\u002FDebug:"," As established in Q10, any generic method (regardless of what the bound ",[32,2992,2941],{}," requires) makes a trait non-object-safe because the vtable can't have unbounded entries — this isn't about whether ",[32,2995,2996],{},"Config"," has methods, it's structural. Given the explicit design goal of ",[32,2999,2842],{},", the fix must remove the genericity from the object-safe surface: accept a concrete type (",[32,3002,3003],{},"&dyn Config"," or a specific ",[32,3006,3007],{},"PluginConfig"," struct\u002Fenum) instead of ",[32,3010,2941],{},", or split ",[32,3013,2958],{}," off into a separate, non-object-safe trait that's used only where static dispatch is acceptable. Adding ",[32,3016,607],{},[32,3018,2954],{}," (an unrelated, already-object-safe method) does nothing to fix ",[32,3021,2958],{},". And critically, this is a compile-time rejection — ",[32,3024,2931],{}," with a generic method present simply fails to compile at the trait-object-construction or vtable-formation point; there is no runtime panic path here, since Rust never allows constructing a value of a type it can't statically verify.",[3027,3028,3029],"style",{},"html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}",{"title":30,"searchDepth":53,"depth":53,"links":3031},[3032,3033,3034,3036,3038,3040,3042,3044,3046,3048,3050,3052,3054,3056,3058,3059,3061,3063,3065,3067],{"id":20,"depth":65,"text":21},{"id":274,"depth":65,"text":275},{"id":346,"depth":65,"text":3035},"Q3. What is PhantomData\u003CT> primarily used for?",{"id":538,"depth":65,"text":3037},"Q4. Which of the following best describes \"object safety\" for a trait — i.e. what determines whether dyn Trait is a valid type?",{"id":628,"depth":65,"text":3039},"Q5. Why is Clone not object-safe, i.e. why can't you write Box\u003Cdyn Clone>?",{"id":778,"depth":65,"text":3041},"Q6. Given fn foo\u003CT: Trait>(x: T) versus fn foo(x: impl Trait) versus fn foo(x: Box\u003Cdyn Trait>), which statement is correct?",{"id":864,"depth":65,"text":3043},"Q7. What does it mean for a generic type to be \"covariant\" in a lifetime parameter, using &'a T as the canonical example?",{"id":981,"depth":65,"text":3045},"Q8. Cell\u003CT> and RefCell\u003CT> are invariant in T, while &T and Vec\u003CT> are covariant in T. Why does RefCell\u003CT> need to be invariant even though &T is covariant?",{"id":1175,"depth":65,"text":3047},"Q9. What happens if you attempt to define a GAT-style associated type where the type parameter needs a where Self: 'a bound but you omit it?",{"id":1358,"depth":65,"text":3049},"Q10. A trait method has this signature: fn process\u003CT: Send>(&self, val: T);. Can this trait still be object-safe overall (assuming this is its only method)?",{"id":1455,"depth":65,"text":3051},"Q11. What is the compile-time behavior of this code, given that Iterator has one associated type Item and dyn Iterator (no type argument) is written without specifying it?",{"id":1629,"depth":65,"text":3053},"Q12. What is the effect of #[non_exhaustive] combined with a private field pattern versus using PhantomData purely for sealing a trait so external crates cannot implement it — which correctly implements the \"sealed trait\" pattern?",{"id":1811,"depth":65,"text":3055},"Q13. What's wrong with this attempt to implement a trait generically for a type parameter, assuming Wrapper\u003CT> is a local struct and Display is from std::fmt?",{"id":2061,"depth":65,"text":3057},"Q14. What does Self: Sized mean when added as a bound to an individual trait method, and why would you add it?",{"id":2241,"depth":65,"text":2242},{"id":2335,"depth":65,"text":3060},"Q16. A crate defines trait Repository\u003CT> { fn save(&self, item: T); } and separately has three concrete repository structs. A reviewer suggests switching to trait Repository { type Item; fn save(&self, item: Self::Item); } instead. When is this refactor the better idiomatic choice?",{"id":2462,"depth":65,"text":3062},"Q17. In idiomatic Rust, when should a public API function accept impl Trait in argument position versus &dyn Trait?",{"id":2563,"depth":65,"text":3064},"Q18. What is the idiomatic reason to reach for a GAT instead of just returning owned data (cloning) from a trait method that would otherwise need to borrow from &mut self per call?",{"id":2713,"depth":65,"text":3066},"Q19. Why does the standard library NOT define Iterator::next(&mut self) -> Option\u003CSelf::Item\u003C'_>> (i.e. why is the standard Iterator::Item not a GAT), even though a \"lending iterator\" would seem more general?",{"id":2838,"depth":65,"text":3068},"Q20. A team is designing a plugin trait meant to be stored as Vec\u003CBox\u003Cdyn Plugin>> and called uniformly. One team member proposes adding fn configure\u003CC: Config>(&mut self, cfg: C) to the trait. What's the best-practice critique?","md",{},"\u002Frust\u002F29-advanced-type-system",{"title":5,"description":30},"rust\u002F29-advanced-type-system","uxrEWVGSVL1eibsy7f8a1pa_iC3bfIMXf8m0zT_ZFfY",1787335398468]