| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175 |
- // SPDX-License-Identifier: Apache-2.0 OR MIT
- use crate::attr::Attribute;
- #[cfg(all(feature = "parsing", feature = "full"))]
- use crate::error::Result;
- #[cfg(feature = "parsing")]
- use crate::ext::IdentExt as _;
- #[cfg(feature = "full")]
- use crate::generics::BoundLifetimes;
- use crate::ident::Ident;
- #[cfg(any(feature = "parsing", feature = "full"))]
- use crate::lifetime::Lifetime;
- use crate::lit::Lit;
- use crate::mac::Macro;
- use crate::op::{BinOp, UnOp};
- #[cfg(feature = "parsing")]
- use crate::parse::ParseStream;
- #[cfg(feature = "full")]
- use crate::pat::Pat;
- use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
- use crate::punctuated::Punctuated;
- #[cfg(feature = "full")]
- use crate::stmt::Block;
- use crate::token;
- #[cfg(feature = "full")]
- use crate::ty::ReturnType;
- use crate::ty::Type;
- use proc_macro2::{Span, TokenStream};
- #[cfg(feature = "printing")]
- use quote::IdentFragment;
- #[cfg(feature = "printing")]
- use std::fmt::{self, Display};
- use std::hash::{Hash, Hasher};
- #[cfg(all(feature = "parsing", feature = "full"))]
- use std::mem;
- ast_enum_of_structs! {
- /// A Rust expression.
- ///
- /// *This type is available only if Syn is built with the `"derive"` or `"full"`
- /// feature, but most of the variants are not available unless "full" is enabled.*
- ///
- /// # Syntax tree enums
- ///
- /// This type is a syntax tree enum. In Syn this and other syntax tree enums
- /// are designed to be traversed using the following rebinding idiom.
- ///
- /// ```
- /// # use syn::Expr;
- /// #
- /// # fn example(expr: Expr) {
- /// # const IGNORE: &str = stringify! {
- /// let expr: Expr = /* ... */;
- /// # };
- /// match expr {
- /// Expr::MethodCall(expr) => {
- /// /* ... */
- /// }
- /// Expr::Cast(expr) => {
- /// /* ... */
- /// }
- /// Expr::If(expr) => {
- /// /* ... */
- /// }
- ///
- /// /* ... */
- /// # _ => {}
- /// # }
- /// # }
- /// ```
- ///
- /// We begin with a variable `expr` of type `Expr` that has no fields
- /// (because it is an enum), and by matching on it and rebinding a variable
- /// with the same name `expr` we effectively imbue our variable with all of
- /// the data fields provided by the variant that it turned out to be. So for
- /// example above if we ended up in the `MethodCall` case then we get to use
- /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
- /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
- ///
- /// This approach avoids repeating the variant names twice on every line.
- ///
- /// ```
- /// # use syn::{Expr, ExprMethodCall};
- /// #
- /// # fn example(expr: Expr) {
- /// // Repetitive; recommend not doing this.
- /// match expr {
- /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
- /// # }
- /// # _ => {}
- /// # }
- /// # }
- /// ```
- ///
- /// In general, the name to which a syntax tree enum variant is bound should
- /// be a suitable name for the complete syntax tree enum type.
- ///
- /// ```
- /// # use syn::{Expr, ExprField};
- /// #
- /// # fn example(discriminant: ExprField) {
- /// // Binding is called `base` which is the name I would use if I were
- /// // assigning `*discriminant.base` without an `if let`.
- /// if let Expr::Tuple(base) = *discriminant.base {
- /// # }
- /// # }
- /// ```
- ///
- /// A sign that you may not be choosing the right variable names is if you
- /// see names getting repeated in your code, like accessing
- /// `receiver.receiver` or `pat.pat` or `cond.cond`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- #[non_exhaustive]
- pub enum Expr {
- /// A slice literal expression: `[a, b, c, d]`.
- Array(ExprArray),
- /// An assignment expression: `a = compute()`.
- Assign(ExprAssign),
- /// An async block: `async { ... }`.
- Async(ExprAsync),
- /// An await expression: `fut.await`.
- Await(ExprAwait),
- /// A binary operation: `a + b`, `a += b`.
- Binary(ExprBinary),
- /// A blocked scope: `{ ... }`.
- Block(ExprBlock),
- /// A `break`, with an optional label to break and an optional
- /// expression.
- Break(ExprBreak),
- /// A function call expression: `invoke(a, b)`.
- Call(ExprCall),
- /// A cast expression: `foo as f64`.
- Cast(ExprCast),
- /// A closure expression: `|a, b| a + b`.
- Closure(ExprClosure),
- /// A const block: `const { ... }`.
- Const(ExprConst),
- /// A `continue`, with an optional label.
- Continue(ExprContinue),
- /// Access of a named struct field (`obj.k`) or unnamed tuple struct
- /// field (`obj.0`).
- Field(ExprField),
- /// A for loop: `for pat in expr { ... }`.
- ForLoop(ExprForLoop),
- /// An expression contained within invisible delimiters.
- ///
- /// This variant is important for faithfully representing the precedence
- /// of expressions and is related to `None`-delimited spans in a
- /// `TokenStream`.
- Group(ExprGroup),
- /// An `if` expression with an optional `else` block: `if expr { ... }
- /// else { ... }`.
- ///
- /// The `else` branch expression may only be an `If` or `Block`
- /// expression, not any of the other types of expression.
- If(ExprIf),
- /// A square bracketed indexing expression: `vector[2]`.
- Index(ExprIndex),
- /// The inferred value of a const generic argument, denoted `_`.
- Infer(ExprInfer),
- /// A `let` guard: `let Some(x) = opt`.
- Let(ExprLet),
- /// A literal in place of an expression: `1`, `"foo"`.
- Lit(ExprLit),
- /// Conditionless loop: `loop { ... }`.
- Loop(ExprLoop),
- /// A macro invocation expression: `format!("{}", q)`.
- Macro(ExprMacro),
- /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
- Match(ExprMatch),
- /// A method call expression: `x.foo::<T>(a, b)`.
- MethodCall(ExprMethodCall),
- /// A parenthesized expression: `(a + b)`.
- Paren(ExprParen),
- /// A path like `std::mem::replace` possibly containing generic
- /// parameters and a qualified self-type.
- ///
- /// A plain identifier like `x` is a path of length 1.
- Path(ExprPath),
- /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
- Range(ExprRange),
- /// Address-of operation: `&raw const place` or `&raw mut place`.
- RawAddr(ExprRawAddr),
- /// A referencing operation: `&a` or `&mut a`.
- Reference(ExprReference),
- /// An array literal constructed from one repeated element: `[0u8; N]`.
- Repeat(ExprRepeat),
- /// A `return`, with an optional value to be returned.
- Return(ExprReturn),
- /// A struct literal expression: `Point { x: 1, y: 1 }`.
- ///
- /// The `rest` provides the value of the remaining fields as in `S { a:
- /// 1, b: 1, ..rest }`.
- Struct(ExprStruct),
- /// A try-expression: `expr?`.
- Try(ExprTry),
- /// A try block: `try { ... }`.
- TryBlock(ExprTryBlock),
- /// A tuple expression: `(a, b, c, d)`.
- Tuple(ExprTuple),
- /// A unary operation: `!x`, `*x`.
- Unary(ExprUnary),
- /// An unsafe block: `unsafe { ... }`.
- Unsafe(ExprUnsafe),
- /// Tokens in expression position not interpreted by Syn.
- Verbatim(TokenStream),
- /// A while loop: `while expr { ... }`.
- While(ExprWhile),
- /// A yield expression: `yield expr`.
- Yield(ExprYield),
- // For testing exhaustiveness in downstream code, use the following idiom:
- //
- // match expr {
- // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
- //
- // Expr::Array(expr) => {...}
- // Expr::Assign(expr) => {...}
- // ...
- // Expr::Yield(expr) => {...}
- //
- // _ => { /* some sane fallback */ }
- // }
- //
- // This way we fail your tests but don't break your library when adding
- // a variant. You will be notified by a test failure when a variant is
- // added, so that you can add code to handle it, but your library will
- // continue to compile and work for downstream users in the interim.
- }
- }
- ast_struct! {
- /// A slice literal expression: `[a, b, c, d]`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprArray #full {
- pub attrs: Vec<Attribute>,
- pub bracket_token: token::Bracket,
- pub elems: Punctuated<Expr, Token![,]>,
- }
- }
- ast_struct! {
- /// An assignment expression: `a = compute()`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprAssign #full {
- pub attrs: Vec<Attribute>,
- pub left: Box<Expr>,
- pub eq_token: Token![=],
- pub right: Box<Expr>,
- }
- }
- ast_struct! {
- /// An async block: `async { ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprAsync #full {
- pub attrs: Vec<Attribute>,
- pub async_token: Token![async],
- pub capture: Option<Token![move]>,
- pub block: Block,
- }
- }
- ast_struct! {
- /// An await expression: `fut.await`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprAwait #full {
- pub attrs: Vec<Attribute>,
- pub base: Box<Expr>,
- pub dot_token: Token![.],
- pub await_token: Token![await],
- }
- }
- ast_struct! {
- /// A binary operation: `a + b`, `a += b`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprBinary {
- pub attrs: Vec<Attribute>,
- pub left: Box<Expr>,
- pub op: BinOp,
- pub right: Box<Expr>,
- }
- }
- ast_struct! {
- /// A blocked scope: `{ ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprBlock #full {
- pub attrs: Vec<Attribute>,
- pub label: Option<Label>,
- pub block: Block,
- }
- }
- ast_struct! {
- /// A `break`, with an optional label to break and an optional
- /// expression.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprBreak #full {
- pub attrs: Vec<Attribute>,
- pub break_token: Token![break],
- pub label: Option<Lifetime>,
- pub expr: Option<Box<Expr>>,
- }
- }
- ast_struct! {
- /// A function call expression: `invoke(a, b)`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprCall {
- pub attrs: Vec<Attribute>,
- pub func: Box<Expr>,
- pub paren_token: token::Paren,
- pub args: Punctuated<Expr, Token![,]>,
- }
- }
- ast_struct! {
- /// A cast expression: `foo as f64`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprCast {
- pub attrs: Vec<Attribute>,
- pub expr: Box<Expr>,
- pub as_token: Token![as],
- pub ty: Box<Type>,
- }
- }
- ast_struct! {
- /// A closure expression: `|a, b| a + b`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprClosure #full {
- pub attrs: Vec<Attribute>,
- pub lifetimes: Option<BoundLifetimes>,
- pub constness: Option<Token![const]>,
- pub movability: Option<Token![static]>,
- pub asyncness: Option<Token![async]>,
- pub capture: Option<Token![move]>,
- pub or1_token: Token![|],
- pub inputs: Punctuated<Pat, Token![,]>,
- pub or2_token: Token![|],
- pub output: ReturnType,
- pub body: Box<Expr>,
- }
- }
- ast_struct! {
- /// A const block: `const { ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprConst #full {
- pub attrs: Vec<Attribute>,
- pub const_token: Token![const],
- pub block: Block,
- }
- }
- ast_struct! {
- /// A `continue`, with an optional label.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprContinue #full {
- pub attrs: Vec<Attribute>,
- pub continue_token: Token![continue],
- pub label: Option<Lifetime>,
- }
- }
- ast_struct! {
- /// Access of a named struct field (`obj.k`) or unnamed tuple struct
- /// field (`obj.0`).
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprField {
- pub attrs: Vec<Attribute>,
- pub base: Box<Expr>,
- pub dot_token: Token![.],
- pub member: Member,
- }
- }
- ast_struct! {
- /// A for loop: `for pat in expr { ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprForLoop #full {
- pub attrs: Vec<Attribute>,
- pub label: Option<Label>,
- pub for_token: Token![for],
- pub pat: Box<Pat>,
- pub in_token: Token![in],
- pub expr: Box<Expr>,
- pub body: Block,
- }
- }
- ast_struct! {
- /// An expression contained within invisible delimiters.
- ///
- /// This variant is important for faithfully representing the precedence
- /// of expressions and is related to `None`-delimited spans in a
- /// `TokenStream`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprGroup {
- pub attrs: Vec<Attribute>,
- pub group_token: token::Group,
- pub expr: Box<Expr>,
- }
- }
- ast_struct! {
- /// An `if` expression with an optional `else` block: `if expr { ... }
- /// else { ... }`.
- ///
- /// The `else` branch expression may only be an `If` or `Block`
- /// expression, not any of the other types of expression.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprIf #full {
- pub attrs: Vec<Attribute>,
- pub if_token: Token![if],
- pub cond: Box<Expr>,
- pub then_branch: Block,
- pub else_branch: Option<(Token![else], Box<Expr>)>,
- }
- }
- ast_struct! {
- /// A square bracketed indexing expression: `vector[2]`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprIndex {
- pub attrs: Vec<Attribute>,
- pub expr: Box<Expr>,
- pub bracket_token: token::Bracket,
- pub index: Box<Expr>,
- }
- }
- ast_struct! {
- /// The inferred value of a const generic argument, denoted `_`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprInfer #full {
- pub attrs: Vec<Attribute>,
- pub underscore_token: Token![_],
- }
- }
- ast_struct! {
- /// A `let` guard: `let Some(x) = opt`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprLet #full {
- pub attrs: Vec<Attribute>,
- pub let_token: Token![let],
- pub pat: Box<Pat>,
- pub eq_token: Token![=],
- pub expr: Box<Expr>,
- }
- }
- ast_struct! {
- /// A literal in place of an expression: `1`, `"foo"`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprLit {
- pub attrs: Vec<Attribute>,
- pub lit: Lit,
- }
- }
- ast_struct! {
- /// Conditionless loop: `loop { ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprLoop #full {
- pub attrs: Vec<Attribute>,
- pub label: Option<Label>,
- pub loop_token: Token![loop],
- pub body: Block,
- }
- }
- ast_struct! {
- /// A macro invocation expression: `format!("{}", q)`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprMacro {
- pub attrs: Vec<Attribute>,
- pub mac: Macro,
- }
- }
- ast_struct! {
- /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprMatch #full {
- pub attrs: Vec<Attribute>,
- pub match_token: Token![match],
- pub expr: Box<Expr>,
- pub brace_token: token::Brace,
- pub arms: Vec<Arm>,
- }
- }
- ast_struct! {
- /// A method call expression: `x.foo::<T>(a, b)`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprMethodCall {
- pub attrs: Vec<Attribute>,
- pub receiver: Box<Expr>,
- pub dot_token: Token![.],
- pub method: Ident,
- pub turbofish: Option<AngleBracketedGenericArguments>,
- pub paren_token: token::Paren,
- pub args: Punctuated<Expr, Token![,]>,
- }
- }
- ast_struct! {
- /// A parenthesized expression: `(a + b)`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprParen {
- pub attrs: Vec<Attribute>,
- pub paren_token: token::Paren,
- pub expr: Box<Expr>,
- }
- }
- ast_struct! {
- /// A path like `std::mem::replace` possibly containing generic
- /// parameters and a qualified self-type.
- ///
- /// A plain identifier like `x` is a path of length 1.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprPath {
- pub attrs: Vec<Attribute>,
- pub qself: Option<QSelf>,
- pub path: Path,
- }
- }
- ast_struct! {
- /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprRange #full {
- pub attrs: Vec<Attribute>,
- pub start: Option<Box<Expr>>,
- pub limits: RangeLimits,
- pub end: Option<Box<Expr>>,
- }
- }
- ast_struct! {
- /// Address-of operation: `&raw const place` or `&raw mut place`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprRawAddr #full {
- pub attrs: Vec<Attribute>,
- pub and_token: Token![&],
- pub raw: Token![raw],
- pub mutability: PointerMutability,
- pub expr: Box<Expr>,
- }
- }
- ast_struct! {
- /// A referencing operation: `&a` or `&mut a`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprReference {
- pub attrs: Vec<Attribute>,
- pub and_token: Token![&],
- pub mutability: Option<Token![mut]>,
- pub expr: Box<Expr>,
- }
- }
- ast_struct! {
- /// An array literal constructed from one repeated element: `[0u8; N]`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprRepeat #full {
- pub attrs: Vec<Attribute>,
- pub bracket_token: token::Bracket,
- pub expr: Box<Expr>,
- pub semi_token: Token![;],
- pub len: Box<Expr>,
- }
- }
- ast_struct! {
- /// A `return`, with an optional value to be returned.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprReturn #full {
- pub attrs: Vec<Attribute>,
- pub return_token: Token![return],
- pub expr: Option<Box<Expr>>,
- }
- }
- ast_struct! {
- /// A struct literal expression: `Point { x: 1, y: 1 }`.
- ///
- /// The `rest` provides the value of the remaining fields as in `S { a:
- /// 1, b: 1, ..rest }`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprStruct {
- pub attrs: Vec<Attribute>,
- pub qself: Option<QSelf>,
- pub path: Path,
- pub brace_token: token::Brace,
- pub fields: Punctuated<FieldValue, Token![,]>,
- pub dot2_token: Option<Token![..]>,
- pub rest: Option<Box<Expr>>,
- }
- }
- ast_struct! {
- /// A try-expression: `expr?`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprTry #full {
- pub attrs: Vec<Attribute>,
- pub expr: Box<Expr>,
- pub question_token: Token![?],
- }
- }
- ast_struct! {
- /// A try block: `try { ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprTryBlock #full {
- pub attrs: Vec<Attribute>,
- pub try_token: Token![try],
- pub block: Block,
- }
- }
- ast_struct! {
- /// A tuple expression: `(a, b, c, d)`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprTuple {
- pub attrs: Vec<Attribute>,
- pub paren_token: token::Paren,
- pub elems: Punctuated<Expr, Token![,]>,
- }
- }
- ast_struct! {
- /// A unary operation: `!x`, `*x`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ExprUnary {
- pub attrs: Vec<Attribute>,
- pub op: UnOp,
- pub expr: Box<Expr>,
- }
- }
- ast_struct! {
- /// An unsafe block: `unsafe { ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprUnsafe #full {
- pub attrs: Vec<Attribute>,
- pub unsafe_token: Token![unsafe],
- pub block: Block,
- }
- }
- ast_struct! {
- /// A while loop: `while expr { ... }`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprWhile #full {
- pub attrs: Vec<Attribute>,
- pub label: Option<Label>,
- pub while_token: Token![while],
- pub cond: Box<Expr>,
- pub body: Block,
- }
- }
- ast_struct! {
- /// A yield expression: `yield expr`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct ExprYield #full {
- pub attrs: Vec<Attribute>,
- pub yield_token: Token![yield],
- pub expr: Option<Box<Expr>>,
- }
- }
- impl Expr {
- /// An unspecified invalid expression.
- ///
- /// ```
- /// use quote::ToTokens;
- /// use std::mem;
- /// use syn::{parse_quote, Expr};
- ///
- /// fn unparenthesize(e: &mut Expr) {
- /// while let Expr::Paren(paren) = e {
- /// *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER);
- /// }
- /// }
- ///
- /// fn main() {
- /// let mut e: Expr = parse_quote! { ((1 + 1)) };
- /// unparenthesize(&mut e);
- /// assert_eq!("1 + 1", e.to_token_stream().to_string());
- /// }
- /// ```
- pub const PLACEHOLDER: Self = Expr::Path(ExprPath {
- attrs: Vec::new(),
- qself: None,
- path: Path {
- leading_colon: None,
- segments: Punctuated::new(),
- },
- });
- /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
- /// trait) for ambiguous syntactic positions in which a trailing brace
- /// should not be taken as part of the expression.
- ///
- /// [`Parse`]: crate::parse::Parse
- ///
- /// Rust grammar has an ambiguity where braces sometimes turn a path
- /// expression into a struct initialization and sometimes do not. In the
- /// following code, the expression `S {}` is one expression. Presumably
- /// there is an empty struct `struct S {}` defined somewhere which it is
- /// instantiating.
- ///
- /// ```
- /// # struct S;
- /// # impl std::ops::Deref for S {
- /// # type Target = bool;
- /// # fn deref(&self) -> &Self::Target {
- /// # &true
- /// # }
- /// # }
- /// let _ = *S {};
- ///
- /// // parsed by rustc as: `*(S {})`
- /// ```
- ///
- /// We would want to parse the above using `Expr::parse` after the `=`
- /// token.
- ///
- /// But in the following, `S {}` is *not* a struct init expression.
- ///
- /// ```
- /// # const S: &bool = &true;
- /// if *S {} {}
- ///
- /// // parsed by rustc as:
- /// //
- /// // if (*S) {
- /// // /* empty block */
- /// // }
- /// // {
- /// // /* another empty block */
- /// // }
- /// ```
- ///
- /// For that reason we would want to parse if-conditions using
- /// `Expr::parse_without_eager_brace` after the `if` token. Same for similar
- /// syntactic positions such as the condition expr after a `while` token or
- /// the expr at the top of a `match`.
- ///
- /// The Rust grammar's choices around which way this ambiguity is resolved
- /// at various syntactic positions is fairly arbitrary. Really either parse
- /// behavior could work in most positions, and language designers just
- /// decide each case based on which is more likely to be what the programmer
- /// had in mind most of the time.
- ///
- /// ```
- /// # struct S;
- /// # fn doc() -> S {
- /// if return S {} {}
- /// # unreachable!()
- /// # }
- ///
- /// // parsed by rustc as:
- /// //
- /// // if (return (S {})) {
- /// // }
- /// //
- /// // but could equally well have been this other arbitrary choice:
- /// //
- /// // if (return S) {
- /// // }
- /// // {}
- /// ```
- ///
- /// Note the grammar ambiguity on trailing braces is distinct from
- /// precedence and is not captured by assigning a precedence level to the
- /// braced struct init expr in relation to other operators. This can be
- /// illustrated by `return 0..S {}` vs `match 0..S {}`. The former parses as
- /// `return (0..(S {}))` implying tighter precedence for struct init than
- /// `..`, while the latter parses as `match (0..S) {}` implying tighter
- /// precedence for `..` than struct init, a contradiction.
- #[cfg(all(feature = "full", feature = "parsing"))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
- pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
- parsing::ambiguous_expr(input, parsing::AllowStruct(false))
- }
- /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
- /// trait) for syntactic positions in which expression boundaries are placed
- /// more eagerly than done by the typical expression grammar. This includes
- /// expressions at the head of a statement or in the right-hand side of a
- /// `match` arm.
- ///
- /// [`Parse`]: crate::parse::Parse
- ///
- /// Compare the following cases:
- ///
- /// 1.
- /// ```
- /// # let result = ();
- /// # let guard = false;
- /// # let cond = true;
- /// # let f = true;
- /// # let g = f;
- /// #
- /// let _ = match result {
- /// () if guard => if cond { f } else { g }
- /// () => false,
- /// };
- /// ```
- ///
- /// 2.
- /// ```
- /// # let cond = true;
- /// # let f = ();
- /// # let g = f;
- /// #
- /// let _ = || {
- /// if cond { f } else { g }
- /// ()
- /// };
- /// ```
- ///
- /// 3.
- /// ```
- /// # let cond = true;
- /// # let f = || ();
- /// # let g = f;
- /// #
- /// let _ = [if cond { f } else { g } ()];
- /// ```
- ///
- /// The same sequence of tokens `if cond { f } else { g } ()` appears in
- /// expression position 3 times. The first two syntactic positions use eager
- /// placement of expression boundaries, and parse as `Expr::If`, with the
- /// adjacent `()` becoming `Pat::Tuple` or `Expr::Tuple`. In contrast, the
- /// third case uses standard expression boundaries and parses as
- /// `Expr::Call`.
- ///
- /// As with [`parse_without_eager_brace`], this ambiguity in the Rust
- /// grammar is independent of precedence.
- ///
- /// [`parse_without_eager_brace`]: Self::parse_without_eager_brace
- #[cfg(all(feature = "full", feature = "parsing"))]
- #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
- pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
- parsing::parse_with_earlier_boundary_rule(input)
- }
- /// Returns whether the next token in the parse stream is one that might
- /// possibly form the beginning of an expr.
- ///
- /// This classification is a load-bearing part of the grammar of some Rust
- /// expressions, notably `return` and `break`. For example `return < …` will
- /// never parse `<` as a binary operator regardless of what comes after,
- /// because `<` is a legal starting token for an expression and so it's
- /// required to be continued as a return value, such as `return <Struct as
- /// Trait>::CONST`. Meanwhile `return > …` treats the `>` as a binary
- /// operator because it cannot be a starting token for any Rust expression.
- #[cfg(feature = "parsing")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- pub fn peek(input: ParseStream) -> bool {
- input.peek(Ident::peek_any) && !input.peek(Token![as]) // value name or keyword
- || input.peek(token::Paren) // tuple
- || input.peek(token::Bracket) // array
- || input.peek(token::Brace) // block
- || input.peek(Lit) // literal
- || input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
- || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
- || input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
- || input.peek(Token![|]) && !input.peek(Token![|=]) // closure
- || input.peek(Token![&]) && !input.peek(Token![&=]) // reference
- || input.peek(Token![..]) // range
- || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
- || input.peek(Token![::]) // absolute path
- || input.peek(Lifetime) // labeled loop
- || input.peek(Token![#]) // expression attributes
- }
- #[cfg(all(feature = "parsing", feature = "full"))]
- pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
- match self {
- Expr::Array(ExprArray { attrs, .. })
- | Expr::Assign(ExprAssign { attrs, .. })
- | Expr::Async(ExprAsync { attrs, .. })
- | Expr::Await(ExprAwait { attrs, .. })
- | Expr::Binary(ExprBinary { attrs, .. })
- | Expr::Block(ExprBlock { attrs, .. })
- | Expr::Break(ExprBreak { attrs, .. })
- | Expr::Call(ExprCall { attrs, .. })
- | Expr::Cast(ExprCast { attrs, .. })
- | Expr::Closure(ExprClosure { attrs, .. })
- | Expr::Const(ExprConst { attrs, .. })
- | Expr::Continue(ExprContinue { attrs, .. })
- | Expr::Field(ExprField { attrs, .. })
- | Expr::ForLoop(ExprForLoop { attrs, .. })
- | Expr::Group(ExprGroup { attrs, .. })
- | Expr::If(ExprIf { attrs, .. })
- | Expr::Index(ExprIndex { attrs, .. })
- | Expr::Infer(ExprInfer { attrs, .. })
- | Expr::Let(ExprLet { attrs, .. })
- | Expr::Lit(ExprLit { attrs, .. })
- | Expr::Loop(ExprLoop { attrs, .. })
- | Expr::Macro(ExprMacro { attrs, .. })
- | Expr::Match(ExprMatch { attrs, .. })
- | Expr::MethodCall(ExprMethodCall { attrs, .. })
- | Expr::Paren(ExprParen { attrs, .. })
- | Expr::Path(ExprPath { attrs, .. })
- | Expr::Range(ExprRange { attrs, .. })
- | Expr::RawAddr(ExprRawAddr { attrs, .. })
- | Expr::Reference(ExprReference { attrs, .. })
- | Expr::Repeat(ExprRepeat { attrs, .. })
- | Expr::Return(ExprReturn { attrs, .. })
- | Expr::Struct(ExprStruct { attrs, .. })
- | Expr::Try(ExprTry { attrs, .. })
- | Expr::TryBlock(ExprTryBlock { attrs, .. })
- | Expr::Tuple(ExprTuple { attrs, .. })
- | Expr::Unary(ExprUnary { attrs, .. })
- | Expr::Unsafe(ExprUnsafe { attrs, .. })
- | Expr::While(ExprWhile { attrs, .. })
- | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
- Expr::Verbatim(_) => Vec::new(),
- }
- }
- }
- ast_enum! {
- /// A struct or tuple struct field accessed in a struct literal or field
- /// expression.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub enum Member {
- /// A named field like `self.x`.
- Named(Ident),
- /// An unnamed field like `self.0`.
- Unnamed(Index),
- }
- }
- impl From<Ident> for Member {
- fn from(ident: Ident) -> Member {
- Member::Named(ident)
- }
- }
- impl From<Index> for Member {
- fn from(index: Index) -> Member {
- Member::Unnamed(index)
- }
- }
- impl From<usize> for Member {
- fn from(index: usize) -> Member {
- Member::Unnamed(Index::from(index))
- }
- }
- impl Eq for Member {}
- impl PartialEq for Member {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (Member::Named(this), Member::Named(other)) => this == other,
- (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
- _ => false,
- }
- }
- }
- impl Hash for Member {
- fn hash<H: Hasher>(&self, state: &mut H) {
- match self {
- Member::Named(m) => m.hash(state),
- Member::Unnamed(m) => m.hash(state),
- }
- }
- }
- #[cfg(feature = "printing")]
- impl IdentFragment for Member {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- match self {
- Member::Named(m) => Display::fmt(m, formatter),
- Member::Unnamed(m) => Display::fmt(&m.index, formatter),
- }
- }
- fn span(&self) -> Option<Span> {
- match self {
- Member::Named(m) => Some(m.span()),
- Member::Unnamed(m) => Some(m.span),
- }
- }
- }
- #[cfg(any(feature = "parsing", feature = "printing"))]
- impl Member {
- pub(crate) fn is_named(&self) -> bool {
- match self {
- Member::Named(_) => true,
- Member::Unnamed(_) => false,
- }
- }
- }
- ast_struct! {
- /// The index of an unnamed tuple struct field.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct Index {
- pub index: u32,
- pub span: Span,
- }
- }
- impl From<usize> for Index {
- fn from(index: usize) -> Index {
- assert!(index < u32::MAX as usize);
- Index {
- index: index as u32,
- span: Span::call_site(),
- }
- }
- }
- impl Eq for Index {}
- impl PartialEq for Index {
- fn eq(&self, other: &Self) -> bool {
- self.index == other.index
- }
- }
- impl Hash for Index {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.index.hash(state);
- }
- }
- #[cfg(feature = "printing")]
- impl IdentFragment for Index {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- Display::fmt(&self.index, formatter)
- }
- fn span(&self) -> Option<Span> {
- Some(self.span)
- }
- }
- ast_struct! {
- /// A field-value pair in a struct literal.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct FieldValue {
- pub attrs: Vec<Attribute>,
- pub member: Member,
- /// The colon in `Struct { x: x }`. If written in shorthand like
- /// `Struct { x }`, there is no colon.
- pub colon_token: Option<Token![:]>,
- pub expr: Expr,
- }
- }
- #[cfg(feature = "full")]
- ast_struct! {
- /// A lifetime labeling a `for`, `while`, or `loop`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct Label {
- pub name: Lifetime,
- pub colon_token: Token![:],
- }
- }
- #[cfg(feature = "full")]
- ast_struct! {
- /// One arm of a `match` expression: `0..=10 => { return true; }`.
- ///
- /// As in:
- ///
- /// ```
- /// # fn f() -> bool {
- /// # let n = 0;
- /// match n {
- /// 0..=10 => {
- /// return true;
- /// }
- /// // ...
- /// # _ => {}
- /// }
- /// # false
- /// # }
- /// ```
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct Arm {
- pub attrs: Vec<Attribute>,
- pub pat: Pat,
- pub guard: Option<(Token![if], Box<Expr>)>,
- pub fat_arrow_token: Token![=>],
- pub body: Box<Expr>,
- pub comma: Option<Token![,]>,
- }
- }
- #[cfg(feature = "full")]
- ast_enum! {
- /// Limit types of a range, inclusive or exclusive.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub enum RangeLimits {
- /// Inclusive at the beginning, exclusive at the end.
- HalfOpen(Token![..]),
- /// Inclusive at the beginning and end.
- Closed(Token![..=]),
- }
- }
- #[cfg(feature = "full")]
- ast_enum! {
- /// Mutability of a raw pointer (`*const T`, `*mut T`), in which non-mutable
- /// isn't the implicit default.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub enum PointerMutability {
- Const(Token![const]),
- Mut(Token![mut]),
- }
- }
- #[cfg(feature = "parsing")]
- pub(crate) mod parsing {
- #[cfg(feature = "full")]
- use crate::attr;
- use crate::attr::Attribute;
- #[cfg(feature = "full")]
- use crate::classify;
- use crate::error::{Error, Result};
- #[cfg(feature = "full")]
- use crate::expr::{
- Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
- ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
- ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
- ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
- };
- use crate::expr::{
- Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
- ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
- FieldValue, Index, Member,
- };
- #[cfg(feature = "full")]
- use crate::generics::{self, BoundLifetimes};
- use crate::ident::Ident;
- #[cfg(feature = "full")]
- use crate::lifetime::Lifetime;
- use crate::lit::{Lit, LitFloat, LitInt};
- use crate::mac::{self, Macro};
- use crate::op::BinOp;
- use crate::parse::discouraged::Speculative as _;
- #[cfg(feature = "full")]
- use crate::parse::ParseBuffer;
- use crate::parse::{Parse, ParseStream};
- #[cfg(feature = "full")]
- use crate::pat::{Pat, PatType};
- use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
- use crate::precedence::Precedence;
- use crate::punctuated::Punctuated;
- #[cfg(feature = "full")]
- use crate::stmt::Block;
- use crate::token;
- use crate::ty;
- #[cfg(feature = "full")]
- use crate::ty::{ReturnType, Type};
- use crate::verbatim;
- #[cfg(feature = "full")]
- use proc_macro2::{Span, TokenStream};
- use std::mem;
- // When we're parsing expressions which occur before blocks, like in an if
- // statement's condition, we cannot parse a struct literal.
- //
- // Struct literals are ambiguous in certain positions
- // https://github.com/rust-lang/rfcs/pull/92
- #[cfg(feature = "full")]
- pub(super) struct AllowStruct(pub bool);
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Expr {
- fn parse(input: ParseStream) -> Result<Self> {
- ambiguous_expr(
- input,
- #[cfg(feature = "full")]
- AllowStruct(true),
- )
- }
- }
- #[cfg(feature = "full")]
- pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
- let mut attrs = input.call(expr_attrs)?;
- let mut expr = if input.peek(token::Group) {
- let allow_struct = AllowStruct(true);
- let atom = expr_group(input, allow_struct)?;
- if continue_parsing_early(&atom) {
- trailer_helper(input, atom)?
- } else {
- atom
- }
- } else if input.peek(Token![if]) {
- Expr::If(input.parse()?)
- } else if input.peek(Token![while]) {
- Expr::While(input.parse()?)
- } else if input.peek(Token![for])
- && !generics::parsing::choose_generics_over_qpath_after_keyword(input)
- {
- Expr::ForLoop(input.parse()?)
- } else if input.peek(Token![loop]) {
- Expr::Loop(input.parse()?)
- } else if input.peek(Token![match]) {
- Expr::Match(input.parse()?)
- } else if input.peek(Token![try]) && input.peek2(token::Brace) {
- Expr::TryBlock(input.parse()?)
- } else if input.peek(Token![unsafe]) {
- Expr::Unsafe(input.parse()?)
- } else if input.peek(Token![const]) && input.peek2(token::Brace) {
- Expr::Const(input.parse()?)
- } else if input.peek(token::Brace) {
- Expr::Block(input.parse()?)
- } else if input.peek(Lifetime) {
- atom_labeled(input)?
- } else {
- let allow_struct = AllowStruct(true);
- unary_expr(input, allow_struct)?
- };
- if continue_parsing_early(&expr) {
- attrs.extend(expr.replace_attrs(Vec::new()));
- expr.replace_attrs(attrs);
- let allow_struct = AllowStruct(true);
- return parse_expr(input, expr, allow_struct, Precedence::MIN);
- }
- if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
- expr = trailer_helper(input, expr)?;
- attrs.extend(expr.replace_attrs(Vec::new()));
- expr.replace_attrs(attrs);
- let allow_struct = AllowStruct(true);
- return parse_expr(input, expr, allow_struct, Precedence::MIN);
- }
- attrs.extend(expr.replace_attrs(Vec::new()));
- expr.replace_attrs(attrs);
- Ok(expr)
- }
- #[cfg(feature = "full")]
- impl Copy for AllowStruct {}
- #[cfg(feature = "full")]
- impl Clone for AllowStruct {
- fn clone(&self) -> Self {
- *self
- }
- }
- #[cfg(feature = "full")]
- fn parse_expr(
- input: ParseStream,
- mut lhs: Expr,
- allow_struct: AllowStruct,
- base: Precedence,
- ) -> Result<Expr> {
- loop {
- let ahead = input.fork();
- if let Expr::Range(_) = lhs {
- // A range cannot be the left-hand side of another binary operator.
- break;
- } else if let Ok(op) = ahead.parse::<BinOp>() {
- let precedence = Precedence::of_binop(&op);
- if precedence < base {
- break;
- }
- if precedence == Precedence::Assign {
- if let Expr::Range(_) = lhs {
- break;
- }
- }
- if precedence == Precedence::Compare {
- if let Expr::Binary(lhs) = &lhs {
- if Precedence::of_binop(&lhs.op) == Precedence::Compare {
- return Err(input.error("comparison operators cannot be chained"));
- }
- }
- }
- input.advance_to(&ahead);
- let right = parse_binop_rhs(input, allow_struct, precedence)?;
- lhs = Expr::Binary(ExprBinary {
- attrs: Vec::new(),
- left: Box::new(lhs),
- op,
- right,
- });
- } else if Precedence::Assign >= base
- && input.peek(Token![=])
- && !input.peek(Token![=>])
- && match lhs {
- Expr::Range(_) => false,
- _ => true,
- }
- {
- let eq_token: Token![=] = input.parse()?;
- let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
- lhs = Expr::Assign(ExprAssign {
- attrs: Vec::new(),
- left: Box::new(lhs),
- eq_token,
- right,
- });
- } else if Precedence::Range >= base && input.peek(Token![..]) {
- let limits: RangeLimits = input.parse()?;
- let end = parse_range_end(input, &limits, allow_struct)?;
- lhs = Expr::Range(ExprRange {
- attrs: Vec::new(),
- start: Some(Box::new(lhs)),
- limits,
- end,
- });
- } else if Precedence::Cast >= base && input.peek(Token![as]) {
- let as_token: Token![as] = input.parse()?;
- let allow_plus = false;
- let allow_group_generic = false;
- let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
- check_cast(input)?;
- lhs = Expr::Cast(ExprCast {
- attrs: Vec::new(),
- expr: Box::new(lhs),
- as_token,
- ty: Box::new(ty),
- });
- } else {
- break;
- }
- }
- Ok(lhs)
- }
- #[cfg(not(feature = "full"))]
- fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
- loop {
- let ahead = input.fork();
- if let Ok(op) = ahead.parse::<BinOp>() {
- let precedence = Precedence::of_binop(&op);
- if precedence < base {
- break;
- }
- if precedence == Precedence::Compare {
- if let Expr::Binary(lhs) = &lhs {
- if Precedence::of_binop(&lhs.op) == Precedence::Compare {
- return Err(input.error("comparison operators cannot be chained"));
- }
- }
- }
- input.advance_to(&ahead);
- let right = parse_binop_rhs(input, precedence)?;
- lhs = Expr::Binary(ExprBinary {
- attrs: Vec::new(),
- left: Box::new(lhs),
- op,
- right,
- });
- } else if Precedence::Cast >= base && input.peek(Token![as]) {
- let as_token: Token![as] = input.parse()?;
- let allow_plus = false;
- let allow_group_generic = false;
- let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
- check_cast(input)?;
- lhs = Expr::Cast(ExprCast {
- attrs: Vec::new(),
- expr: Box::new(lhs),
- as_token,
- ty: Box::new(ty),
- });
- } else {
- break;
- }
- }
- Ok(lhs)
- }
- fn parse_binop_rhs(
- input: ParseStream,
- #[cfg(feature = "full")] allow_struct: AllowStruct,
- precedence: Precedence,
- ) -> Result<Box<Expr>> {
- let mut rhs = unary_expr(
- input,
- #[cfg(feature = "full")]
- allow_struct,
- )?;
- loop {
- let next = peek_precedence(input);
- if next > precedence || next == precedence && precedence == Precedence::Assign {
- let cursor = input.cursor();
- rhs = parse_expr(
- input,
- rhs,
- #[cfg(feature = "full")]
- allow_struct,
- next,
- )?;
- if cursor == input.cursor() {
- // Bespoke grammar restrictions separate from precedence can
- // cause parsing to not advance, such as `..a` being
- // disallowed in the left-hand side of binary operators,
- // even ones that have lower precedence than `..`.
- break;
- }
- } else {
- break;
- }
- }
- Ok(Box::new(rhs))
- }
- fn peek_precedence(input: ParseStream) -> Precedence {
- if let Ok(op) = input.fork().parse() {
- Precedence::of_binop(&op)
- } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
- Precedence::Assign
- } else if input.peek(Token![..]) {
- Precedence::Range
- } else if input.peek(Token![as]) {
- Precedence::Cast
- } else {
- Precedence::MIN
- }
- }
- // Parse an arbitrary expression.
- pub(super) fn ambiguous_expr(
- input: ParseStream,
- #[cfg(feature = "full")] allow_struct: AllowStruct,
- ) -> Result<Expr> {
- let lhs = unary_expr(
- input,
- #[cfg(feature = "full")]
- allow_struct,
- )?;
- parse_expr(
- input,
- lhs,
- #[cfg(feature = "full")]
- allow_struct,
- Precedence::MIN,
- )
- }
- #[cfg(feature = "full")]
- fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
- let mut attrs = Vec::new();
- while !input.peek(token::Group) && input.peek(Token![#]) {
- attrs.push(input.call(attr::parsing::single_parse_outer)?);
- }
- Ok(attrs)
- }
- // <UnOp> <trailer>
- // & <trailer>
- // &mut <trailer>
- // box <trailer>
- #[cfg(feature = "full")]
- fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
- let begin = input.fork();
- let attrs = input.call(expr_attrs)?;
- if input.peek(token::Group) {
- return trailer_expr(begin, attrs, input, allow_struct);
- }
- if input.peek(Token![&]) {
- let and_token: Token![&] = input.parse()?;
- let raw: Option<Token![raw]> = if input.peek(Token![raw])
- && (input.peek2(Token![mut]) || input.peek2(Token![const]))
- {
- Some(input.parse()?)
- } else {
- None
- };
- let mutability: Option<Token![mut]> = input.parse()?;
- let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
- Some(input.parse()?)
- } else {
- None
- };
- let expr = Box::new(unary_expr(input, allow_struct)?);
- if let Some(raw) = raw {
- Ok(Expr::RawAddr(ExprRawAddr {
- attrs,
- and_token,
- raw,
- mutability: match mutability {
- Some(mut_token) => PointerMutability::Mut(mut_token),
- None => PointerMutability::Const(const_token.unwrap()),
- },
- expr,
- }))
- } else {
- Ok(Expr::Reference(ExprReference {
- attrs,
- and_token,
- mutability,
- expr,
- }))
- }
- } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
- expr_unary(input, attrs, allow_struct).map(Expr::Unary)
- } else {
- trailer_expr(begin, attrs, input, allow_struct)
- }
- }
- #[cfg(not(feature = "full"))]
- fn unary_expr(input: ParseStream) -> Result<Expr> {
- if input.peek(Token![&]) {
- Ok(Expr::Reference(ExprReference {
- attrs: Vec::new(),
- and_token: input.parse()?,
- mutability: input.parse()?,
- expr: Box::new(unary_expr(input)?),
- }))
- } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
- Ok(Expr::Unary(ExprUnary {
- attrs: Vec::new(),
- op: input.parse()?,
- expr: Box::new(unary_expr(input)?),
- }))
- } else {
- trailer_expr(input)
- }
- }
- // <atom> (..<args>) ...
- // <atom> . <ident> (..<args>) ...
- // <atom> . <ident> ...
- // <atom> . <lit> ...
- // <atom> [ <expr> ] ...
- // <atom> ? ...
- #[cfg(feature = "full")]
- fn trailer_expr(
- begin: ParseBuffer,
- mut attrs: Vec<Attribute>,
- input: ParseStream,
- allow_struct: AllowStruct,
- ) -> Result<Expr> {
- let atom = atom_expr(input, allow_struct)?;
- let mut e = trailer_helper(input, atom)?;
- if let Expr::Verbatim(tokens) = &mut e {
- *tokens = verbatim::between(&begin, input);
- } else if !attrs.is_empty() {
- if let Expr::Range(range) = e {
- let spans: &[Span] = match &range.limits {
- RangeLimits::HalfOpen(limits) => &limits.spans,
- RangeLimits::Closed(limits) => &limits.spans,
- };
- return Err(crate::error::new2(
- spans[0],
- *spans.last().unwrap(),
- "attributes are not allowed on range expressions starting with `..`",
- ));
- }
- let inner_attrs = e.replace_attrs(Vec::new());
- attrs.extend(inner_attrs);
- e.replace_attrs(attrs);
- }
- Ok(e)
- }
- #[cfg(feature = "full")]
- fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
- loop {
- if input.peek(token::Paren) {
- let content;
- e = Expr::Call(ExprCall {
- attrs: Vec::new(),
- func: Box::new(e),
- paren_token: parenthesized!(content in input),
- args: content.parse_terminated(Expr::parse, Token![,])?,
- });
- } else if input.peek(Token![.])
- && !input.peek(Token![..])
- && match e {
- Expr::Range(_) => false,
- _ => true,
- }
- {
- let mut dot_token: Token![.] = input.parse()?;
- let float_token: Option<LitFloat> = input.parse()?;
- if let Some(float_token) = float_token {
- if multi_index(&mut e, &mut dot_token, float_token)? {
- continue;
- }
- }
- let await_token: Option<Token![await]> = input.parse()?;
- if let Some(await_token) = await_token {
- e = Expr::Await(ExprAwait {
- attrs: Vec::new(),
- base: Box::new(e),
- dot_token,
- await_token,
- });
- continue;
- }
- let member: Member = input.parse()?;
- let turbofish = if member.is_named() && input.peek(Token![::]) {
- Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
- } else {
- None
- };
- if turbofish.is_some() || input.peek(token::Paren) {
- if let Member::Named(method) = member {
- let content;
- e = Expr::MethodCall(ExprMethodCall {
- attrs: Vec::new(),
- receiver: Box::new(e),
- dot_token,
- method,
- turbofish,
- paren_token: parenthesized!(content in input),
- args: content.parse_terminated(Expr::parse, Token![,])?,
- });
- continue;
- }
- }
- e = Expr::Field(ExprField {
- attrs: Vec::new(),
- base: Box::new(e),
- dot_token,
- member,
- });
- } else if input.peek(token::Bracket) {
- let content;
- e = Expr::Index(ExprIndex {
- attrs: Vec::new(),
- expr: Box::new(e),
- bracket_token: bracketed!(content in input),
- index: content.parse()?,
- });
- } else if input.peek(Token![?])
- && match e {
- Expr::Range(_) => false,
- _ => true,
- }
- {
- e = Expr::Try(ExprTry {
- attrs: Vec::new(),
- expr: Box::new(e),
- question_token: input.parse()?,
- });
- } else {
- break;
- }
- }
- Ok(e)
- }
- #[cfg(not(feature = "full"))]
- fn trailer_expr(input: ParseStream) -> Result<Expr> {
- let mut e = atom_expr(input)?;
- loop {
- if input.peek(token::Paren) {
- let content;
- e = Expr::Call(ExprCall {
- attrs: Vec::new(),
- func: Box::new(e),
- paren_token: parenthesized!(content in input),
- args: content.parse_terminated(Expr::parse, Token![,])?,
- });
- } else if input.peek(Token![.])
- && !input.peek(Token![..])
- && !input.peek2(Token![await])
- {
- let mut dot_token: Token![.] = input.parse()?;
- let float_token: Option<LitFloat> = input.parse()?;
- if let Some(float_token) = float_token {
- if multi_index(&mut e, &mut dot_token, float_token)? {
- continue;
- }
- }
- let member: Member = input.parse()?;
- let turbofish = if member.is_named() && input.peek(Token![::]) {
- let colon2_token: Token![::] = input.parse()?;
- let turbofish =
- AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
- Some(turbofish)
- } else {
- None
- };
- if turbofish.is_some() || input.peek(token::Paren) {
- if let Member::Named(method) = member {
- let content;
- e = Expr::MethodCall(ExprMethodCall {
- attrs: Vec::new(),
- receiver: Box::new(e),
- dot_token,
- method,
- turbofish,
- paren_token: parenthesized!(content in input),
- args: content.parse_terminated(Expr::parse, Token![,])?,
- });
- continue;
- }
- }
- e = Expr::Field(ExprField {
- attrs: Vec::new(),
- base: Box::new(e),
- dot_token,
- member,
- });
- } else if input.peek(token::Bracket) {
- let content;
- e = Expr::Index(ExprIndex {
- attrs: Vec::new(),
- expr: Box::new(e),
- bracket_token: bracketed!(content in input),
- index: content.parse()?,
- });
- } else {
- break;
- }
- }
- Ok(e)
- }
- // Parse all atomic expressions which don't have to worry about precedence
- // interactions, as they are fully contained.
- #[cfg(feature = "full")]
- fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
- if input.peek(token::Group) {
- expr_group(input, allow_struct)
- } else if input.peek(Lit) {
- input.parse().map(Expr::Lit)
- } else if input.peek(Token![async])
- && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
- {
- input.parse().map(Expr::Async)
- } else if input.peek(Token![try]) && input.peek2(token::Brace) {
- input.parse().map(Expr::TryBlock)
- } else if input.peek(Token![|])
- || input.peek(Token![move])
- || input.peek(Token![for])
- && generics::parsing::choose_generics_over_qpath_after_keyword(input)
- || input.peek(Token![const]) && !input.peek2(token::Brace)
- || input.peek(Token![static])
- || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
- {
- expr_closure(input, allow_struct).map(Expr::Closure)
- } else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(Token![#])
- {
- expr_builtin(input)
- } else if input.peek(Ident)
- || input.peek(Token![::])
- || input.peek(Token![<])
- || input.peek(Token![self])
- || input.peek(Token![Self])
- || input.peek(Token![super])
- || input.peek(Token![crate])
- || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
- {
- path_or_macro_or_struct(input, allow_struct)
- } else if input.peek(token::Paren) {
- paren_or_tuple(input)
- } else if input.peek(Token![break]) {
- expr_break(input, allow_struct).map(Expr::Break)
- } else if input.peek(Token![continue]) {
- input.parse().map(Expr::Continue)
- } else if input.peek(Token![return]) {
- input.parse().map(Expr::Return)
- } else if input.peek(Token![become]) {
- expr_become(input)
- } else if input.peek(token::Bracket) {
- array_or_repeat(input)
- } else if input.peek(Token![let]) {
- expr_let(input, allow_struct).map(Expr::Let)
- } else if input.peek(Token![if]) {
- input.parse().map(Expr::If)
- } else if input.peek(Token![while]) {
- input.parse().map(Expr::While)
- } else if input.peek(Token![for]) {
- input.parse().map(Expr::ForLoop)
- } else if input.peek(Token![loop]) {
- input.parse().map(Expr::Loop)
- } else if input.peek(Token![match]) {
- input.parse().map(Expr::Match)
- } else if input.peek(Token![yield]) {
- input.parse().map(Expr::Yield)
- } else if input.peek(Token![unsafe]) {
- input.parse().map(Expr::Unsafe)
- } else if input.peek(Token![const]) {
- input.parse().map(Expr::Const)
- } else if input.peek(token::Brace) {
- input.parse().map(Expr::Block)
- } else if input.peek(Token![..]) {
- expr_range(input, allow_struct).map(Expr::Range)
- } else if input.peek(Token![_]) {
- input.parse().map(Expr::Infer)
- } else if input.peek(Lifetime) {
- atom_labeled(input)
- } else {
- Err(input.error("expected an expression"))
- }
- }
- #[cfg(feature = "full")]
- fn atom_labeled(input: ParseStream) -> Result<Expr> {
- let the_label: Label = input.parse()?;
- let mut expr = if input.peek(Token![while]) {
- Expr::While(input.parse()?)
- } else if input.peek(Token![for]) {
- Expr::ForLoop(input.parse()?)
- } else if input.peek(Token![loop]) {
- Expr::Loop(input.parse()?)
- } else if input.peek(token::Brace) {
- Expr::Block(input.parse()?)
- } else {
- return Err(input.error("expected loop or block expression"));
- };
- match &mut expr {
- Expr::While(ExprWhile { label, .. })
- | Expr::ForLoop(ExprForLoop { label, .. })
- | Expr::Loop(ExprLoop { label, .. })
- | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
- _ => unreachable!(),
- }
- Ok(expr)
- }
- #[cfg(not(feature = "full"))]
- fn atom_expr(input: ParseStream) -> Result<Expr> {
- if input.peek(token::Group) {
- expr_group(input)
- } else if input.peek(Lit) {
- input.parse().map(Expr::Lit)
- } else if input.peek(token::Paren) {
- paren_or_tuple(input)
- } else if input.peek(Ident)
- || input.peek(Token![::])
- || input.peek(Token![<])
- || input.peek(Token![self])
- || input.peek(Token![Self])
- || input.peek(Token![super])
- || input.peek(Token![crate])
- {
- path_or_macro_or_struct(input)
- } else if input.is_empty() {
- Err(input.error("expected an expression"))
- } else {
- if input.peek(token::Brace) {
- let scan = input.fork();
- let content;
- braced!(content in scan);
- if content.parse::<Expr>().is_ok() && content.is_empty() {
- let expr_block = verbatim::between(input, &scan);
- input.advance_to(&scan);
- return Ok(Expr::Verbatim(expr_block));
- }
- }
- Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
- }
- }
- #[cfg(feature = "full")]
- fn expr_builtin(input: ParseStream) -> Result<Expr> {
- let begin = input.fork();
- token::parsing::keyword(input, "builtin")?;
- input.parse::<Token![#]>()?;
- input.parse::<Ident>()?;
- let args;
- parenthesized!(args in input);
- args.parse::<TokenStream>()?;
- Ok(Expr::Verbatim(verbatim::between(&begin, input)))
- }
- fn path_or_macro_or_struct(
- input: ParseStream,
- #[cfg(feature = "full")] allow_struct: AllowStruct,
- ) -> Result<Expr> {
- let expr_style = true;
- let (qself, path) = path::parsing::qpath(input, expr_style)?;
- rest_of_path_or_macro_or_struct(
- qself,
- path,
- input,
- #[cfg(feature = "full")]
- allow_struct,
- )
- }
- fn rest_of_path_or_macro_or_struct(
- qself: Option<QSelf>,
- path: Path,
- input: ParseStream,
- #[cfg(feature = "full")] allow_struct: AllowStruct,
- ) -> Result<Expr> {
- if qself.is_none()
- && input.peek(Token![!])
- && !input.peek(Token![!=])
- && path.is_mod_style()
- {
- let bang_token: Token![!] = input.parse()?;
- let (delimiter, tokens) = mac::parse_delimiter(input)?;
- return Ok(Expr::Macro(ExprMacro {
- attrs: Vec::new(),
- mac: Macro {
- path,
- bang_token,
- delimiter,
- tokens,
- },
- }));
- }
- #[cfg(not(feature = "full"))]
- let allow_struct = (true,);
- if allow_struct.0 && input.peek(token::Brace) {
- return expr_struct_helper(input, qself, path).map(Expr::Struct);
- }
- Ok(Expr::Path(ExprPath {
- attrs: Vec::new(),
- qself,
- path,
- }))
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprMacro {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprMacro {
- attrs: Vec::new(),
- mac: input.parse()?,
- })
- }
- }
- fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
- let content;
- let paren_token = parenthesized!(content in input);
- if content.is_empty() {
- return Ok(Expr::Tuple(ExprTuple {
- attrs: Vec::new(),
- paren_token,
- elems: Punctuated::new(),
- }));
- }
- let first: Expr = content.parse()?;
- if content.is_empty() {
- return Ok(Expr::Paren(ExprParen {
- attrs: Vec::new(),
- paren_token,
- expr: Box::new(first),
- }));
- }
- let mut elems = Punctuated::new();
- elems.push_value(first);
- while !content.is_empty() {
- let punct = content.parse()?;
- elems.push_punct(punct);
- if content.is_empty() {
- break;
- }
- let value = content.parse()?;
- elems.push_value(value);
- }
- Ok(Expr::Tuple(ExprTuple {
- attrs: Vec::new(),
- paren_token,
- elems,
- }))
- }
- #[cfg(feature = "full")]
- fn array_or_repeat(input: ParseStream) -> Result<Expr> {
- let content;
- let bracket_token = bracketed!(content in input);
- if content.is_empty() {
- return Ok(Expr::Array(ExprArray {
- attrs: Vec::new(),
- bracket_token,
- elems: Punctuated::new(),
- }));
- }
- let first: Expr = content.parse()?;
- if content.is_empty() || content.peek(Token![,]) {
- let mut elems = Punctuated::new();
- elems.push_value(first);
- while !content.is_empty() {
- let punct = content.parse()?;
- elems.push_punct(punct);
- if content.is_empty() {
- break;
- }
- let value = content.parse()?;
- elems.push_value(value);
- }
- Ok(Expr::Array(ExprArray {
- attrs: Vec::new(),
- bracket_token,
- elems,
- }))
- } else if content.peek(Token![;]) {
- let semi_token: Token![;] = content.parse()?;
- let len: Expr = content.parse()?;
- Ok(Expr::Repeat(ExprRepeat {
- attrs: Vec::new(),
- bracket_token,
- expr: Box::new(first),
- semi_token,
- len: Box::new(len),
- }))
- } else {
- Err(content.error("expected `,` or `;`"))
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprArray {
- fn parse(input: ParseStream) -> Result<Self> {
- let content;
- let bracket_token = bracketed!(content in input);
- let mut elems = Punctuated::new();
- while !content.is_empty() {
- let first: Expr = content.parse()?;
- elems.push_value(first);
- if content.is_empty() {
- break;
- }
- let punct = content.parse()?;
- elems.push_punct(punct);
- }
- Ok(ExprArray {
- attrs: Vec::new(),
- bracket_token,
- elems,
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprRepeat {
- fn parse(input: ParseStream) -> Result<Self> {
- let content;
- Ok(ExprRepeat {
- bracket_token: bracketed!(content in input),
- attrs: Vec::new(),
- expr: content.parse()?,
- semi_token: content.parse()?,
- len: content.parse()?,
- })
- }
- }
- #[cfg(feature = "full")]
- fn continue_parsing_early(mut expr: &Expr) -> bool {
- while let Expr::Group(group) = expr {
- expr = &group.expr;
- }
- match expr {
- Expr::If(_)
- | Expr::While(_)
- | Expr::ForLoop(_)
- | Expr::Loop(_)
- | Expr::Match(_)
- | Expr::TryBlock(_)
- | Expr::Unsafe(_)
- | Expr::Const(_)
- | Expr::Block(_) => false,
- _ => true,
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprLit {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprLit {
- attrs: Vec::new(),
- lit: input.parse()?,
- })
- }
- }
- fn expr_group(
- input: ParseStream,
- #[cfg(feature = "full")] allow_struct: AllowStruct,
- ) -> Result<Expr> {
- let group = crate::group::parse_group(input)?;
- let mut inner: Expr = group.content.parse()?;
- match inner {
- Expr::Path(mut expr) if expr.attrs.is_empty() => {
- let grouped_len = expr.path.segments.len();
- Path::parse_rest(input, &mut expr.path, true)?;
- match rest_of_path_or_macro_or_struct(
- expr.qself,
- expr.path,
- input,
- #[cfg(feature = "full")]
- allow_struct,
- )? {
- Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
- inner = Expr::Path(expr);
- }
- extended => return Ok(extended),
- }
- }
- _ => {}
- }
- Ok(Expr::Group(ExprGroup {
- attrs: Vec::new(),
- group_token: group.token,
- expr: Box::new(inner),
- }))
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprParen {
- fn parse(input: ParseStream) -> Result<Self> {
- let content;
- Ok(ExprParen {
- attrs: Vec::new(),
- paren_token: parenthesized!(content in input),
- expr: content.parse()?,
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprLet {
- fn parse(input: ParseStream) -> Result<Self> {
- let allow_struct = AllowStruct(true);
- expr_let(input, allow_struct)
- }
- }
- #[cfg(feature = "full")]
- fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
- Ok(ExprLet {
- attrs: Vec::new(),
- let_token: input.parse()?,
- pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
- eq_token: input.parse()?,
- expr: Box::new({
- let lhs = unary_expr(input, allow_struct)?;
- parse_expr(input, lhs, allow_struct, Precedence::Compare)?
- }),
- })
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprIf {
- fn parse(input: ParseStream) -> Result<Self> {
- let attrs = input.call(Attribute::parse_outer)?;
- let mut clauses = Vec::new();
- let mut expr;
- loop {
- let if_token: Token![if] = input.parse()?;
- let cond = input.call(Expr::parse_without_eager_brace)?;
- let then_branch: Block = input.parse()?;
- expr = ExprIf {
- attrs: Vec::new(),
- if_token,
- cond: Box::new(cond),
- then_branch,
- else_branch: None,
- };
- if !input.peek(Token![else]) {
- break;
- }
- let else_token: Token![else] = input.parse()?;
- let lookahead = input.lookahead1();
- if lookahead.peek(Token![if]) {
- expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
- clauses.push(expr);
- } else if lookahead.peek(token::Brace) {
- expr.else_branch = Some((
- else_token,
- Box::new(Expr::Block(ExprBlock {
- attrs: Vec::new(),
- label: None,
- block: input.parse()?,
- })),
- ));
- break;
- } else {
- return Err(lookahead.error());
- }
- }
- while let Some(mut prev) = clauses.pop() {
- *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
- expr = prev;
- }
- expr.attrs = attrs;
- Ok(expr)
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprInfer {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprInfer {
- attrs: input.call(Attribute::parse_outer)?,
- underscore_token: input.parse()?,
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprForLoop {
- fn parse(input: ParseStream) -> Result<Self> {
- let mut attrs = input.call(Attribute::parse_outer)?;
- let label: Option<Label> = input.parse()?;
- let for_token: Token![for] = input.parse()?;
- let pat = Pat::parse_multi_with_leading_vert(input)?;
- let in_token: Token![in] = input.parse()?;
- let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
- let content;
- let brace_token = braced!(content in input);
- attr::parsing::parse_inner(&content, &mut attrs)?;
- let stmts = content.call(Block::parse_within)?;
- Ok(ExprForLoop {
- attrs,
- label,
- for_token,
- pat: Box::new(pat),
- in_token,
- expr: Box::new(expr),
- body: Block { brace_token, stmts },
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprLoop {
- fn parse(input: ParseStream) -> Result<Self> {
- let mut attrs = input.call(Attribute::parse_outer)?;
- let label: Option<Label> = input.parse()?;
- let loop_token: Token![loop] = input.parse()?;
- let content;
- let brace_token = braced!(content in input);
- attr::parsing::parse_inner(&content, &mut attrs)?;
- let stmts = content.call(Block::parse_within)?;
- Ok(ExprLoop {
- attrs,
- label,
- loop_token,
- body: Block { brace_token, stmts },
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprMatch {
- fn parse(input: ParseStream) -> Result<Self> {
- let mut attrs = input.call(Attribute::parse_outer)?;
- let match_token: Token![match] = input.parse()?;
- let expr = Expr::parse_without_eager_brace(input)?;
- let content;
- let brace_token = braced!(content in input);
- attr::parsing::parse_inner(&content, &mut attrs)?;
- let arms = Arm::parse_multiple(&content)?;
- Ok(ExprMatch {
- attrs,
- match_token,
- expr: Box::new(expr),
- brace_token,
- arms,
- })
- }
- }
- macro_rules! impl_by_parsing_expr {
- (
- $(
- $expr_type:ty, $variant:ident, $msg:expr,
- )*
- ) => {
- $(
- #[cfg(all(feature = "full", feature = "printing"))]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for $expr_type {
- fn parse(input: ParseStream) -> Result<Self> {
- let mut expr: Expr = input.parse()?;
- loop {
- match expr {
- Expr::$variant(inner) => return Ok(inner),
- Expr::Group(next) => expr = *next.expr,
- _ => return Err(Error::new_spanned(expr, $msg)),
- }
- }
- }
- }
- )*
- };
- }
- impl_by_parsing_expr! {
- ExprAssign, Assign, "expected assignment expression",
- ExprAwait, Await, "expected await expression",
- ExprBinary, Binary, "expected binary operation",
- ExprCall, Call, "expected function call expression",
- ExprCast, Cast, "expected cast expression",
- ExprField, Field, "expected struct field access",
- ExprIndex, Index, "expected indexing expression",
- ExprMethodCall, MethodCall, "expected method call expression",
- ExprRange, Range, "expected range expression",
- ExprTry, Try, "expected try expression",
- ExprTuple, Tuple, "expected tuple expression",
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprUnary {
- fn parse(input: ParseStream) -> Result<Self> {
- let attrs = Vec::new();
- let allow_struct = AllowStruct(true);
- expr_unary(input, attrs, allow_struct)
- }
- }
- #[cfg(feature = "full")]
- fn expr_unary(
- input: ParseStream,
- attrs: Vec<Attribute>,
- allow_struct: AllowStruct,
- ) -> Result<ExprUnary> {
- Ok(ExprUnary {
- attrs,
- op: input.parse()?,
- expr: Box::new(unary_expr(input, allow_struct)?),
- })
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprClosure {
- fn parse(input: ParseStream) -> Result<Self> {
- let allow_struct = AllowStruct(true);
- expr_closure(input, allow_struct)
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprRawAddr {
- fn parse(input: ParseStream) -> Result<Self> {
- let allow_struct = AllowStruct(true);
- Ok(ExprRawAddr {
- attrs: Vec::new(),
- and_token: input.parse()?,
- raw: input.parse()?,
- mutability: input.parse()?,
- expr: Box::new(unary_expr(input, allow_struct)?),
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprReference {
- fn parse(input: ParseStream) -> Result<Self> {
- let allow_struct = AllowStruct(true);
- Ok(ExprReference {
- attrs: Vec::new(),
- and_token: input.parse()?,
- mutability: input.parse()?,
- expr: Box::new(unary_expr(input, allow_struct)?),
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprBreak {
- fn parse(input: ParseStream) -> Result<Self> {
- let allow_struct = AllowStruct(true);
- expr_break(input, allow_struct)
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprReturn {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprReturn {
- attrs: Vec::new(),
- return_token: input.parse()?,
- expr: {
- if Expr::peek(input) {
- Some(input.parse()?)
- } else {
- None
- }
- },
- })
- }
- }
- #[cfg(feature = "full")]
- fn expr_become(input: ParseStream) -> Result<Expr> {
- let begin = input.fork();
- input.parse::<Token![become]>()?;
- input.parse::<Expr>()?;
- Ok(Expr::Verbatim(verbatim::between(&begin, input)))
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprTryBlock {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprTryBlock {
- attrs: Vec::new(),
- try_token: input.parse()?,
- block: input.parse()?,
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprYield {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprYield {
- attrs: Vec::new(),
- yield_token: input.parse()?,
- expr: {
- if Expr::peek(input) {
- Some(input.parse()?)
- } else {
- None
- }
- },
- })
- }
- }
- #[cfg(feature = "full")]
- fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
- let lifetimes: Option<BoundLifetimes> = input.parse()?;
- let constness: Option<Token![const]> = input.parse()?;
- let movability: Option<Token![static]> = input.parse()?;
- let asyncness: Option<Token![async]> = input.parse()?;
- let capture: Option<Token![move]> = input.parse()?;
- let or1_token: Token![|] = input.parse()?;
- let mut inputs = Punctuated::new();
- loop {
- if input.peek(Token![|]) {
- break;
- }
- let value = closure_arg(input)?;
- inputs.push_value(value);
- if input.peek(Token![|]) {
- break;
- }
- let punct: Token![,] = input.parse()?;
- inputs.push_punct(punct);
- }
- let or2_token: Token![|] = input.parse()?;
- let (output, body) = if input.peek(Token![->]) {
- let arrow_token: Token![->] = input.parse()?;
- let ty: Type = input.parse()?;
- let body: Block = input.parse()?;
- let output = ReturnType::Type(arrow_token, Box::new(ty));
- let block = Expr::Block(ExprBlock {
- attrs: Vec::new(),
- label: None,
- block: body,
- });
- (output, block)
- } else {
- let body = ambiguous_expr(input, allow_struct)?;
- (ReturnType::Default, body)
- };
- Ok(ExprClosure {
- attrs: Vec::new(),
- lifetimes,
- constness,
- movability,
- asyncness,
- capture,
- or1_token,
- inputs,
- or2_token,
- output,
- body: Box::new(body),
- })
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprAsync {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprAsync {
- attrs: Vec::new(),
- async_token: input.parse()?,
- capture: input.parse()?,
- block: input.parse()?,
- })
- }
- }
- #[cfg(feature = "full")]
- fn closure_arg(input: ParseStream) -> Result<Pat> {
- let attrs = input.call(Attribute::parse_outer)?;
- let mut pat = Pat::parse_single(input)?;
- if input.peek(Token![:]) {
- Ok(Pat::Type(PatType {
- attrs,
- pat: Box::new(pat),
- colon_token: input.parse()?,
- ty: input.parse()?,
- }))
- } else {
- match &mut pat {
- Pat::Const(pat) => pat.attrs = attrs,
- Pat::Ident(pat) => pat.attrs = attrs,
- Pat::Lit(pat) => pat.attrs = attrs,
- Pat::Macro(pat) => pat.attrs = attrs,
- Pat::Or(pat) => pat.attrs = attrs,
- Pat::Paren(pat) => pat.attrs = attrs,
- Pat::Path(pat) => pat.attrs = attrs,
- Pat::Range(pat) => pat.attrs = attrs,
- Pat::Reference(pat) => pat.attrs = attrs,
- Pat::Rest(pat) => pat.attrs = attrs,
- Pat::Slice(pat) => pat.attrs = attrs,
- Pat::Struct(pat) => pat.attrs = attrs,
- Pat::Tuple(pat) => pat.attrs = attrs,
- Pat::TupleStruct(pat) => pat.attrs = attrs,
- Pat::Type(_) => unreachable!(),
- Pat::Verbatim(_) => {}
- Pat::Wild(pat) => pat.attrs = attrs,
- }
- Ok(pat)
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprWhile {
- fn parse(input: ParseStream) -> Result<Self> {
- let mut attrs = input.call(Attribute::parse_outer)?;
- let label: Option<Label> = input.parse()?;
- let while_token: Token![while] = input.parse()?;
- let cond = Expr::parse_without_eager_brace(input)?;
- let content;
- let brace_token = braced!(content in input);
- attr::parsing::parse_inner(&content, &mut attrs)?;
- let stmts = content.call(Block::parse_within)?;
- Ok(ExprWhile {
- attrs,
- label,
- while_token,
- cond: Box::new(cond),
- body: Block { brace_token, stmts },
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprConst {
- fn parse(input: ParseStream) -> Result<Self> {
- let const_token: Token![const] = input.parse()?;
- let content;
- let brace_token = braced!(content in input);
- let inner_attrs = content.call(Attribute::parse_inner)?;
- let stmts = content.call(Block::parse_within)?;
- Ok(ExprConst {
- attrs: inner_attrs,
- const_token,
- block: Block { brace_token, stmts },
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Label {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(Label {
- name: input.parse()?,
- colon_token: input.parse()?,
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Option<Label> {
- fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Lifetime) {
- input.parse().map(Some)
- } else {
- Ok(None)
- }
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprContinue {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(ExprContinue {
- attrs: Vec::new(),
- continue_token: input.parse()?,
- label: input.parse()?,
- })
- }
- }
- #[cfg(feature = "full")]
- fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
- let break_token: Token![break] = input.parse()?;
- let ahead = input.fork();
- let label: Option<Lifetime> = ahead.parse()?;
- if label.is_some() && ahead.peek(Token![:]) {
- // Not allowed: `break 'label: loop {...}`
- // Parentheses are required. `break ('label: loop {...})`
- let _: Expr = input.parse()?;
- let start_span = label.unwrap().apostrophe;
- let end_span = input.cursor().prev_span();
- return Err(crate::error::new2(
- start_span,
- end_span,
- "parentheses required",
- ));
- }
- input.advance_to(&ahead);
- let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
- Some(input.parse()?)
- } else {
- None
- };
- Ok(ExprBreak {
- attrs: Vec::new(),
- break_token,
- label,
- expr,
- })
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for FieldValue {
- fn parse(input: ParseStream) -> Result<Self> {
- let attrs = input.call(Attribute::parse_outer)?;
- let member: Member = input.parse()?;
- let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
- let colon_token: Token![:] = input.parse()?;
- let value: Expr = input.parse()?;
- (Some(colon_token), value)
- } else if let Member::Named(ident) = &member {
- let value = Expr::Path(ExprPath {
- attrs: Vec::new(),
- qself: None,
- path: Path::from(ident.clone()),
- });
- (None, value)
- } else {
- unreachable!()
- };
- Ok(FieldValue {
- attrs,
- member,
- colon_token,
- expr: value,
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprStruct {
- fn parse(input: ParseStream) -> Result<Self> {
- let expr_style = true;
- let (qself, path) = path::parsing::qpath(input, expr_style)?;
- expr_struct_helper(input, qself, path)
- }
- }
- fn expr_struct_helper(
- input: ParseStream,
- qself: Option<QSelf>,
- path: Path,
- ) -> Result<ExprStruct> {
- let content;
- let brace_token = braced!(content in input);
- let mut fields = Punctuated::new();
- while !content.is_empty() {
- if content.peek(Token![..]) {
- return Ok(ExprStruct {
- attrs: Vec::new(),
- qself,
- path,
- brace_token,
- fields,
- dot2_token: Some(content.parse()?),
- rest: if content.is_empty() {
- None
- } else {
- Some(Box::new(content.parse()?))
- },
- });
- }
- fields.push(content.parse()?);
- if content.is_empty() {
- break;
- }
- let punct: Token![,] = content.parse()?;
- fields.push_punct(punct);
- }
- Ok(ExprStruct {
- attrs: Vec::new(),
- qself,
- path,
- brace_token,
- fields,
- dot2_token: None,
- rest: None,
- })
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprUnsafe {
- fn parse(input: ParseStream) -> Result<Self> {
- let unsafe_token: Token![unsafe] = input.parse()?;
- let content;
- let brace_token = braced!(content in input);
- let inner_attrs = content.call(Attribute::parse_inner)?;
- let stmts = content.call(Block::parse_within)?;
- Ok(ExprUnsafe {
- attrs: inner_attrs,
- unsafe_token,
- block: Block { brace_token, stmts },
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprBlock {
- fn parse(input: ParseStream) -> Result<Self> {
- let mut attrs = input.call(Attribute::parse_outer)?;
- let label: Option<Label> = input.parse()?;
- let content;
- let brace_token = braced!(content in input);
- attr::parsing::parse_inner(&content, &mut attrs)?;
- let stmts = content.call(Block::parse_within)?;
- Ok(ExprBlock {
- attrs,
- label,
- block: Block { brace_token, stmts },
- })
- }
- }
- #[cfg(feature = "full")]
- fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
- let limits: RangeLimits = input.parse()?;
- let end = parse_range_end(input, &limits, allow_struct)?;
- Ok(ExprRange {
- attrs: Vec::new(),
- start: None,
- limits,
- end,
- })
- }
- #[cfg(feature = "full")]
- fn parse_range_end(
- input: ParseStream,
- limits: &RangeLimits,
- allow_struct: AllowStruct,
- ) -> Result<Option<Box<Expr>>> {
- if matches!(limits, RangeLimits::HalfOpen(_))
- && (input.is_empty()
- || input.peek(Token![,])
- || input.peek(Token![;])
- || input.peek(Token![.]) && !input.peek(Token![..])
- || input.peek(Token![?])
- || input.peek(Token![=>])
- || !allow_struct.0 && input.peek(token::Brace)
- || input.peek(Token![=])
- || input.peek(Token![+])
- || input.peek(Token![/])
- || input.peek(Token![%])
- || input.peek(Token![^])
- || input.peek(Token![>])
- || input.peek(Token![<=])
- || input.peek(Token![!=])
- || input.peek(Token![-=])
- || input.peek(Token![*=])
- || input.peek(Token![&=])
- || input.peek(Token![|=])
- || input.peek(Token![<<=])
- || input.peek(Token![as]))
- {
- Ok(None)
- } else {
- let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
- Ok(Some(end))
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for RangeLimits {
- fn parse(input: ParseStream) -> Result<Self> {
- let lookahead = input.lookahead1();
- let dot_dot = lookahead.peek(Token![..]);
- let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
- let dot_dot_dot = dot_dot && input.peek(Token![...]);
- if dot_dot_eq {
- input.parse().map(RangeLimits::Closed)
- } else if dot_dot && !dot_dot_dot {
- input.parse().map(RangeLimits::HalfOpen)
- } else {
- Err(lookahead.error())
- }
- }
- }
- #[cfg(feature = "full")]
- impl RangeLimits {
- pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
- let lookahead = input.lookahead1();
- let dot_dot = lookahead.peek(Token![..]);
- let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
- let dot_dot_dot = dot_dot && input.peek(Token![...]);
- if dot_dot_eq {
- input.parse().map(RangeLimits::Closed)
- } else if dot_dot_dot {
- let dot3: Token![...] = input.parse()?;
- Ok(RangeLimits::Closed(Token))
- } else if dot_dot {
- input.parse().map(RangeLimits::HalfOpen)
- } else {
- Err(lookahead.error())
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ExprPath {
- fn parse(input: ParseStream) -> Result<Self> {
- #[cfg(not(feature = "full"))]
- let attrs = Vec::new();
- #[cfg(feature = "full")]
- let attrs = input.call(Attribute::parse_outer)?;
- let expr_style = true;
- let (qself, path) = path::parsing::qpath(input, expr_style)?;
- Ok(ExprPath { attrs, qself, path })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Member {
- fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Ident) {
- input.parse().map(Member::Named)
- } else if input.peek(LitInt) {
- input.parse().map(Member::Unnamed)
- } else {
- Err(input.error("expected identifier or integer"))
- }
- }
- }
- #[cfg(feature = "full")]
- impl Arm {
- pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
- let mut arms = Vec::new();
- while !input.is_empty() {
- arms.push(input.call(Arm::parse)?);
- }
- Ok(arms)
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Arm {
- fn parse(input: ParseStream) -> Result<Arm> {
- let requires_comma;
- Ok(Arm {
- attrs: input.call(Attribute::parse_outer)?,
- pat: Pat::parse_multi_with_leading_vert(input)?,
- guard: {
- if input.peek(Token![if]) {
- let if_token: Token![if] = input.parse()?;
- let guard: Expr = input.parse()?;
- Some((if_token, Box::new(guard)))
- } else {
- None
- }
- },
- fat_arrow_token: input.parse()?,
- body: {
- let body = Expr::parse_with_earlier_boundary_rule(input)?;
- requires_comma = classify::requires_comma_to_be_match_arm(&body);
- Box::new(body)
- },
- comma: {
- if requires_comma && !input.is_empty() {
- Some(input.parse()?)
- } else {
- input.parse()?
- }
- },
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Index {
- fn parse(input: ParseStream) -> Result<Self> {
- let lit: LitInt = input.parse()?;
- if lit.suffix().is_empty() {
- Ok(Index {
- index: lit
- .base10_digits()
- .parse()
- .map_err(|err| Error::new(lit.span(), err))?,
- span: lit.span(),
- })
- } else {
- Err(Error::new(lit.span(), "expected unsuffixed integer"))
- }
- }
- }
- fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
- let float_token = float.token();
- let float_span = float_token.span();
- let mut float_repr = float_token.to_string();
- let trailing_dot = float_repr.ends_with('.');
- if trailing_dot {
- float_repr.truncate(float_repr.len() - 1);
- }
- let mut offset = 0;
- for part in float_repr.split('.') {
- let mut index: Index =
- crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
- let part_end = offset + part.len();
- index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
- let base = mem::replace(e, Expr::PLACEHOLDER);
- *e = Expr::Field(ExprField {
- attrs: Vec::new(),
- base: Box::new(base),
- dot_token: Token,
- member: Member::Unnamed(index),
- });
- let dot_span = float_token
- .subspan(part_end..part_end + 1)
- .unwrap_or(float_span);
- *dot_token = Token;
- offset = part_end + 1;
- }
- Ok(!trailing_dot)
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for PointerMutability {
- fn parse(input: ParseStream) -> Result<Self> {
- let lookahead = input.lookahead1();
- if lookahead.peek(Token![const]) {
- Ok(PointerMutability::Const(input.parse()?))
- } else if lookahead.peek(Token![mut]) {
- Ok(PointerMutability::Mut(input.parse()?))
- } else {
- Err(lookahead.error())
- }
- }
- }
- fn check_cast(input: ParseStream) -> Result<()> {
- let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
- if input.peek2(Token![await]) {
- "`.await`"
- } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
- "a method call"
- } else {
- "a field access"
- }
- } else if input.peek(Token![?]) {
- "`?`"
- } else if input.peek(token::Bracket) {
- "indexing"
- } else if input.peek(token::Paren) {
- "a function call"
- } else {
- return Ok(());
- };
- let msg = format!("casts cannot be followed by {}", kind);
- Err(input.error(msg))
- }
- }
- #[cfg(feature = "printing")]
- pub(crate) mod printing {
- use crate::attr::Attribute;
- #[cfg(feature = "full")]
- use crate::attr::FilterAttrs;
- #[cfg(feature = "full")]
- use crate::classify;
- #[cfg(feature = "full")]
- use crate::expr::{
- Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
- ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
- ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
- ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
- };
- use crate::expr::{
- Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
- ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
- FieldValue, Index, Member,
- };
- use crate::fixup::FixupContext;
- use crate::op::BinOp;
- use crate::path;
- use crate::path::printing::PathStyle;
- use crate::precedence::Precedence;
- use crate::token;
- #[cfg(feature = "full")]
- use crate::ty::ReturnType;
- use proc_macro2::{Literal, Span, TokenStream};
- use quote::{ToTokens, TokenStreamExt};
- #[cfg(feature = "full")]
- pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
- tokens.append_all(attrs.outer());
- }
- #[cfg(feature = "full")]
- fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
- tokens.append_all(attrs.inner());
- }
- #[cfg(not(feature = "full"))]
- pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
- pub(crate) fn print_subexpression(
- expr: &Expr,
- needs_group: bool,
- tokens: &mut TokenStream,
- mut fixup: FixupContext,
- ) {
- if needs_group {
- // If we are surrounding the whole cond in parentheses, such as:
- //
- // if (return Struct {}) {}
- //
- // then there is no need for parenthesizing the individual struct
- // expressions within. On the other hand if the whole cond is not
- // parenthesized, then print_expr must parenthesize exterior struct
- // literals.
- //
- // if x == (Struct {}) {}
- //
- fixup = FixupContext::NONE;
- }
- let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
- if needs_group {
- token::Paren::default().surround(tokens, do_print_expr);
- } else {
- do_print_expr(tokens);
- }
- }
- pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
- #[cfg(feature = "full")]
- let needs_group = fixup.parenthesize(expr);
- #[cfg(not(feature = "full"))]
- let needs_group = false;
- if needs_group {
- fixup = FixupContext::NONE;
- }
- let do_print_expr = |tokens: &mut TokenStream| match expr {
- #[cfg(feature = "full")]
- Expr::Array(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::Async(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Await(e) => print_expr_await(e, tokens, fixup),
- Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::Block(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Break(e) => print_expr_break(e, tokens, fixup),
- Expr::Call(e) => print_expr_call(e, tokens, fixup),
- Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::Const(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Continue(e) => e.to_tokens(tokens),
- Expr::Field(e) => print_expr_field(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::ForLoop(e) => e.to_tokens(tokens),
- Expr::Group(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::If(e) => e.to_tokens(tokens),
- Expr::Index(e) => print_expr_index(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::Infer(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Let(e) => print_expr_let(e, tokens, fixup),
- Expr::Lit(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Loop(e) => e.to_tokens(tokens),
- Expr::Macro(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Match(e) => e.to_tokens(tokens),
- Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
- Expr::Paren(e) => e.to_tokens(tokens),
- Expr::Path(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Range(e) => print_expr_range(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
- Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::Repeat(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Return(e) => print_expr_return(e, tokens, fixup),
- Expr::Struct(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Try(e) => print_expr_try(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::TryBlock(e) => e.to_tokens(tokens),
- Expr::Tuple(e) => e.to_tokens(tokens),
- Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
- #[cfg(feature = "full")]
- Expr::Unsafe(e) => e.to_tokens(tokens),
- Expr::Verbatim(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::While(e) => e.to_tokens(tokens),
- #[cfg(feature = "full")]
- Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
- #[cfg(not(feature = "full"))]
- _ => unreachable!(),
- };
- if needs_group {
- token::Paren::default().surround(tokens, do_print_expr);
- } else {
- do_print_expr(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprArray {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.bracket_token.surround(tokens, |tokens| {
- self.elems.to_tokens(tokens);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprAssign {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_assign(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let needs_group = !e.attrs.is_empty();
- if needs_group {
- fixup = FixupContext::NONE;
- }
- let do_print_expr = |tokens: &mut TokenStream| {
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
- &e.left,
- false,
- false,
- Precedence::Assign,
- );
- print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
- e.eq_token.to_tokens(tokens);
- print_expr(
- &e.right,
- tokens,
- fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
- );
- };
- if needs_group {
- token::Paren::default().surround(tokens, do_print_expr);
- } else {
- do_print_expr(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprAsync {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.async_token.to_tokens(tokens);
- self.capture.to_tokens(tokens);
- self.block.to_tokens(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprAwait {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_await(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
- print_subexpression(
- &e.base,
- left_prec < Precedence::Unambiguous,
- tokens,
- left_fixup,
- );
- e.dot_token.to_tokens(tokens);
- e.await_token.to_tokens(tokens);
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprBinary {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_binary(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let needs_group = !e.attrs.is_empty();
- if needs_group {
- fixup = FixupContext::NONE;
- }
- let do_print_expr = |tokens: &mut TokenStream| {
- let binop_prec = Precedence::of_binop(&e.op);
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
- &e.left,
- #[cfg(feature = "full")]
- match &e.op {
- BinOp::Sub(_)
- | BinOp::Mul(_)
- | BinOp::And(_)
- | BinOp::Or(_)
- | BinOp::BitAnd(_)
- | BinOp::BitOr(_)
- | BinOp::Shl(_)
- | BinOp::Lt(_) => true,
- _ => false,
- },
- match &e.op {
- BinOp::Shl(_) | BinOp::Lt(_) => true,
- _ => false,
- },
- #[cfg(feature = "full")]
- binop_prec,
- );
- let left_needs_group = match binop_prec {
- Precedence::Assign => left_prec <= Precedence::Range,
- Precedence::Compare => left_prec <= binop_prec,
- _ => left_prec < binop_prec,
- };
- let right_fixup = fixup.rightmost_subexpression_fixup(
- #[cfg(feature = "full")]
- false,
- #[cfg(feature = "full")]
- false,
- #[cfg(feature = "full")]
- binop_prec,
- );
- let right_needs_group = binop_prec != Precedence::Assign
- && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
- print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
- e.op.to_tokens(tokens);
- print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
- };
- if needs_group {
- token::Paren::default().surround(tokens, do_print_expr);
- } else {
- do_print_expr(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprBlock {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.label.to_tokens(tokens);
- self.block.brace_token.surround(tokens, |tokens| {
- inner_attrs_to_tokens(&self.attrs, tokens);
- tokens.append_all(&self.block.stmts);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprBreak {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_break(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.break_token.to_tokens(tokens);
- e.label.to_tokens(tokens);
- if let Some(value) = &e.expr {
- print_subexpression(
- value,
- // Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
- // ^---------------------------------^
- e.label.is_none() && classify::expr_leading_label(value),
- tokens,
- fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
- );
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprCall {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_call(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
- &e.func,
- #[cfg(feature = "full")]
- true,
- false,
- #[cfg(feature = "full")]
- Precedence::Unambiguous,
- );
- let needs_group = if let Expr::Field(func) = &*e.func {
- func.member.is_named()
- } else {
- left_prec < Precedence::Unambiguous
- };
- print_subexpression(&e.func, needs_group, tokens, left_fixup);
- e.paren_token.surround(tokens, |tokens| {
- e.args.to_tokens(tokens);
- });
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprCast {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_cast(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let needs_group = !e.attrs.is_empty();
- if needs_group {
- fixup = FixupContext::NONE;
- }
- let do_print_expr = |tokens: &mut TokenStream| {
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
- &e.expr,
- #[cfg(feature = "full")]
- false,
- false,
- #[cfg(feature = "full")]
- Precedence::Cast,
- );
- print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
- e.as_token.to_tokens(tokens);
- e.ty.to_tokens(tokens);
- };
- if needs_group {
- token::Paren::default().surround(tokens, do_print_expr);
- } else {
- do_print_expr(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprClosure {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_closure(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.lifetimes.to_tokens(tokens);
- e.constness.to_tokens(tokens);
- e.movability.to_tokens(tokens);
- e.asyncness.to_tokens(tokens);
- e.capture.to_tokens(tokens);
- e.or1_token.to_tokens(tokens);
- e.inputs.to_tokens(tokens);
- e.or2_token.to_tokens(tokens);
- e.output.to_tokens(tokens);
- if matches!(e.output, ReturnType::Default)
- || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
- {
- print_expr(
- &e.body,
- tokens,
- fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
- );
- } else {
- token::Brace::default().surround(tokens, |tokens| {
- print_expr(&e.body, tokens, FixupContext::new_stmt());
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprConst {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.const_token.to_tokens(tokens);
- self.block.brace_token.surround(tokens, |tokens| {
- inner_attrs_to_tokens(&self.attrs, tokens);
- tokens.append_all(&self.block.stmts);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprContinue {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.continue_token.to_tokens(tokens);
- self.label.to_tokens(tokens);
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprField {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_field(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
- print_subexpression(
- &e.base,
- left_prec < Precedence::Unambiguous,
- tokens,
- left_fixup,
- );
- e.dot_token.to_tokens(tokens);
- e.member.to_tokens(tokens);
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprForLoop {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.label.to_tokens(tokens);
- self.for_token.to_tokens(tokens);
- self.pat.to_tokens(tokens);
- self.in_token.to_tokens(tokens);
- print_expr(&self.expr, tokens, FixupContext::new_condition());
- self.body.brace_token.surround(tokens, |tokens| {
- inner_attrs_to_tokens(&self.attrs, tokens);
- tokens.append_all(&self.body.stmts);
- });
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprGroup {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.group_token.surround(tokens, |tokens| {
- self.expr.to_tokens(tokens);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprIf {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- let mut expr = self;
- loop {
- expr.if_token.to_tokens(tokens);
- print_expr(&expr.cond, tokens, FixupContext::new_condition());
- expr.then_branch.to_tokens(tokens);
- let (else_token, else_) = match &expr.else_branch {
- Some(else_branch) => else_branch,
- None => break,
- };
- else_token.to_tokens(tokens);
- match &**else_ {
- Expr::If(next) => {
- expr = next;
- }
- Expr::Block(last) => {
- last.to_tokens(tokens);
- break;
- }
- // If this is not one of the valid expressions to exist in
- // an else clause, wrap it in a block.
- other => {
- token::Brace::default().surround(tokens, |tokens| {
- print_expr(other, tokens, FixupContext::new_stmt());
- });
- break;
- }
- }
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprIndex {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_index(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
- &e.expr,
- #[cfg(feature = "full")]
- true,
- false,
- #[cfg(feature = "full")]
- Precedence::Unambiguous,
- );
- print_subexpression(
- &e.expr,
- left_prec < Precedence::Unambiguous,
- tokens,
- left_fixup,
- );
- e.bracket_token.surround(tokens, |tokens| {
- e.index.to_tokens(tokens);
- });
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprInfer {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.underscore_token.to_tokens(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprLet {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_let(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.let_token.to_tokens(tokens);
- e.pat.to_tokens(tokens);
- e.eq_token.to_tokens(tokens);
- let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
- print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprLit {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.lit.to_tokens(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprLoop {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.label.to_tokens(tokens);
- self.loop_token.to_tokens(tokens);
- self.body.brace_token.surround(tokens, |tokens| {
- inner_attrs_to_tokens(&self.attrs, tokens);
- tokens.append_all(&self.body.stmts);
- });
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprMacro {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.mac.to_tokens(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprMatch {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.match_token.to_tokens(tokens);
- print_expr(&self.expr, tokens, FixupContext::new_condition());
- self.brace_token.surround(tokens, |tokens| {
- inner_attrs_to_tokens(&self.attrs, tokens);
- for (i, arm) in self.arms.iter().enumerate() {
- arm.to_tokens(tokens);
- // Ensure that we have a comma after a non-block arm, except
- // for the last one.
- let is_last = i == self.arms.len() - 1;
- if !is_last
- && classify::requires_comma_to_be_match_arm(&arm.body)
- && arm.comma.is_none()
- {
- <Token![,]>::default().to_tokens(tokens);
- }
- }
- });
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprMethodCall {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_method_call(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
- print_subexpression(
- &e.receiver,
- left_prec < Precedence::Unambiguous,
- tokens,
- left_fixup,
- );
- e.dot_token.to_tokens(tokens);
- e.method.to_tokens(tokens);
- if let Some(turbofish) = &e.turbofish {
- path::printing::print_angle_bracketed_generic_arguments(
- tokens,
- turbofish,
- PathStyle::Expr,
- );
- }
- e.paren_token.surround(tokens, |tokens| {
- e.args.to_tokens(tokens);
- });
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprParen {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.paren_token.surround(tokens, |tokens| {
- self.expr.to_tokens(tokens);
- });
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprPath {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprRange {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_range(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let needs_group = !e.attrs.is_empty();
- if needs_group {
- fixup = FixupContext::NONE;
- }
- let do_print_expr = |tokens: &mut TokenStream| {
- if let Some(start) = &e.start {
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
- start,
- true,
- false,
- Precedence::Range,
- );
- print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
- }
- e.limits.to_tokens(tokens);
- if let Some(end) = &e.end {
- let right_fixup =
- fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
- let right_prec = right_fixup.rightmost_subexpression_precedence(end);
- print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
- }
- };
- if needs_group {
- token::Paren::default().surround(tokens, do_print_expr);
- } else {
- do_print_expr(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprRawAddr {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_raw_addr(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.and_token.to_tokens(tokens);
- e.raw.to_tokens(tokens);
- e.mutability.to_tokens(tokens);
- let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
- print_subexpression(
- &e.expr,
- right_prec < Precedence::Prefix,
- tokens,
- right_fixup,
- );
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprReference {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_reference(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.and_token.to_tokens(tokens);
- e.mutability.to_tokens(tokens);
- let (right_prec, right_fixup) = fixup.rightmost_subexpression(
- &e.expr,
- #[cfg(feature = "full")]
- Precedence::Prefix,
- );
- print_subexpression(
- &e.expr,
- right_prec < Precedence::Prefix,
- tokens,
- right_fixup,
- );
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprRepeat {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.bracket_token.surround(tokens, |tokens| {
- self.expr.to_tokens(tokens);
- self.semi_token.to_tokens(tokens);
- self.len.to_tokens(tokens);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprReturn {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_return(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.return_token.to_tokens(tokens);
- if let Some(expr) = &e.expr {
- print_expr(
- expr,
- tokens,
- fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
- );
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprStruct {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
- self.brace_token.surround(tokens, |tokens| {
- self.fields.to_tokens(tokens);
- if let Some(dot2_token) = &self.dot2_token {
- dot2_token.to_tokens(tokens);
- } else if self.rest.is_some() {
- Token).to_tokens(tokens);
- }
- self.rest.to_tokens(tokens);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprTry {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_try(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
- print_subexpression(
- &e.expr,
- left_prec < Precedence::Unambiguous,
- tokens,
- left_fixup,
- );
- e.question_token.to_tokens(tokens);
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprTryBlock {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.try_token.to_tokens(tokens);
- self.block.to_tokens(tokens);
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprTuple {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.paren_token.surround(tokens, |tokens| {
- self.elems.to_tokens(tokens);
- // If we only have one argument, we need a trailing comma to
- // distinguish ExprTuple from ExprParen.
- if self.elems.len() == 1 && !self.elems.trailing_punct() {
- <Token![,]>::default().to_tokens(tokens);
- }
- });
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprUnary {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_unary(self, tokens, FixupContext::NONE);
- }
- }
- fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.op.to_tokens(tokens);
- let (right_prec, right_fixup) = fixup.rightmost_subexpression(
- &e.expr,
- #[cfg(feature = "full")]
- Precedence::Prefix,
- );
- print_subexpression(
- &e.expr,
- right_prec < Precedence::Prefix,
- tokens,
- right_fixup,
- );
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprUnsafe {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.unsafe_token.to_tokens(tokens);
- self.block.brace_token.surround(tokens, |tokens| {
- inner_attrs_to_tokens(&self.attrs, tokens);
- tokens.append_all(&self.block.stmts);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprWhile {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.label.to_tokens(tokens);
- self.while_token.to_tokens(tokens);
- print_expr(&self.cond, tokens, FixupContext::new_condition());
- self.body.brace_token.surround(tokens, |tokens| {
- inner_attrs_to_tokens(&self.attrs, tokens);
- tokens.append_all(&self.body.stmts);
- });
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ExprYield {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- print_expr_yield(self, tokens, FixupContext::NONE);
- }
- }
- #[cfg(feature = "full")]
- fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
- outer_attrs_to_tokens(&e.attrs, tokens);
- e.yield_token.to_tokens(tokens);
- if let Some(expr) = &e.expr {
- print_expr(
- expr,
- tokens,
- fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
- );
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for Arm {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append_all(&self.attrs);
- self.pat.to_tokens(tokens);
- if let Some((if_token, guard)) = &self.guard {
- if_token.to_tokens(tokens);
- guard.to_tokens(tokens);
- }
- self.fat_arrow_token.to_tokens(tokens);
- print_expr(&self.body, tokens, FixupContext::new_match_arm());
- self.comma.to_tokens(tokens);
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for FieldValue {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- outer_attrs_to_tokens(&self.attrs, tokens);
- self.member.to_tokens(tokens);
- if let Some(colon_token) = &self.colon_token {
- colon_token.to_tokens(tokens);
- self.expr.to_tokens(tokens);
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for Index {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
- lit.set_span(self.span);
- tokens.append(lit);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for Label {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.name.to_tokens(tokens);
- self.colon_token.to_tokens(tokens);
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for Member {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- match self {
- Member::Named(ident) => ident.to_tokens(tokens),
- Member::Unnamed(index) => index.to_tokens(tokens),
- }
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for RangeLimits {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- match self {
- RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
- RangeLimits::Closed(t) => t.to_tokens(tokens),
- }
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for PointerMutability {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- match self {
- PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
- PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
- }
- }
- }
- }
|