Something went wrong. Try again.
forked from verus-lang/verus
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650use crate::algorithm::{BreakToken, Printer};use crate::attr;use crate::classify;use crate::fixup::FixupContext;use crate::iter::IterDelimited;use crate::path::PathKind;use crate::precedence::Precedence;use crate::stmt;use crate::INDENT;use proc_macro2::TokenStream;use verus_syn::punctuated::Punctuated;use verus_syn::{ token, Arm, Attribute, BinOp, Block, Expr, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBinary, ExprBlock, ExprBreak, ExprCall, ExprCast, ExprClosure, ExprConst, ExprContinue, ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLet, ExprLit, ExprLoop, ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprRawAddr, ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnary, ExprUnsafe, ExprWhile, ExprYield, FieldValue, Index, Label, Lit, Member, PointerMutability, RangeLimits, ReturnType, Stmt, Token, UnOp,};
impl Printer { pub fn expr(&mut self, expr: &Expr, mut fixup: FixupContext) { let needs_paren = fixup.parenthesize(expr); if needs_paren { self.word("("); fixup = FixupContext::NONE; }
let beginning_of_line = false;
match expr { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Expr::Array(expr) => self.expr_array(expr), Expr::Assign(expr) => self.expr_assign(expr, fixup), Expr::Async(expr) => self.expr_async(expr), Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup), Expr::Binary(expr) => self.expr_binary(expr, fixup), Expr::Block(expr) => self.expr_block(expr), Expr::Break(expr) => self.expr_break(expr, fixup), Expr::Call(expr) => self.expr_call(expr, beginning_of_line, fixup), Expr::Cast(expr) => self.expr_cast(expr, fixup), Expr::Closure(expr) => self.expr_closure(expr, fixup), Expr::Const(expr) => self.expr_const(expr), Expr::Continue(expr) => self.expr_continue(expr), Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup), Expr::ForLoop(expr) => self.expr_for_loop(expr), Expr::Group(expr) => self.expr_group(expr, fixup), Expr::If(expr) => self.expr_if(expr), Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup), Expr::Infer(expr) => self.expr_infer(expr), Expr::Let(expr) => self.expr_let(expr, fixup), Expr::Lit(expr) => self.expr_lit(expr), Expr::Loop(expr) => self.expr_loop(expr), Expr::Macro(expr) => self.expr_macro(expr), Expr::Match(expr) => self.expr_match(expr), Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup), Expr::Paren(expr) => self.expr_paren(expr), Expr::Path(expr) => self.expr_path(expr), Expr::Range(expr) => self.expr_range(expr, fixup), Expr::RawAddr(expr) => self.expr_raw_addr(expr, fixup), Expr::Reference(expr) => self.expr_reference(expr, fixup), Expr::Repeat(expr) => self.expr_repeat(expr), Expr::Return(expr) => self.expr_return(expr, fixup), Expr::Struct(expr) => self.expr_struct(expr), Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup), Expr::TryBlock(expr) => self.expr_try_block(expr), Expr::Tuple(expr) => self.expr_tuple(expr), Expr::Unary(expr) => self.expr_unary(expr, fixup), Expr::Unsafe(expr) => self.expr_unsafe(expr), Expr::Verbatim(expr) => self.expr_verbatim(expr, fixup), Expr::While(expr) => self.expr_while(expr), Expr::Yield(expr) => self.expr_yield(expr, fixup),
// verus // (note: for now, not supporting assert, assume, etc., since we're // only using this for spec expressions at the moment) Expr::View(v) => self.expr_view(v), Expr::BigAnd(expr) => { self.expr_big_op(&expr.exprs.iter().map(|e| &e.expr).collect(), false) } Expr::BigOr(expr) => { self.expr_big_op(&expr.exprs.iter().map(|e| &e.expr).collect(), true) } Expr::Is(expr) => self.expr_is(expr), Expr::IsNot(expr) => self.expr_isnot(expr), Expr::Has(expr) => self.expr_has(expr), Expr::HasNot(expr) => self.expr_hasnot(expr), Expr::GetField(expr) => self.expr_get_field(expr), Expr::Matches(m) => self.expr_matches(m), Expr::Final(e) => self.expr_final(e),
Expr::Assume(_) | Expr::Assert(_) | Expr::AssertForall(_) | Expr::RevealHide(_) => {} }
if needs_paren { self.word(")"); } }
pub fn expr_view(&mut self, expr: &verus_syn::View) { // Similar to expr_tyr self.outer_attrs(&expr.attrs); self.expr(&expr.expr, FixupContext::NONE); self.word("@"); }
pub fn expr_big_op(&mut self, exprs: &Vec<&Box<Expr>>, is_or: bool) { for expr in exprs { self.ibox(0); self.word(if is_or { "||| " } else { "&&& " }); self.expr(expr, FixupContext::NONE); self.end(); self.hardbreak(); } }
pub fn expr_is(&mut self, expr: &verus_syn::ExprIs) { self.outer_attrs(&expr.attrs); self.expr(&expr.base, FixupContext::NONE); self.word(" is "); self.ident(&expr.variant_ident); }
pub fn expr_isnot(&mut self, expr: &verus_syn::ExprIsNot) { self.outer_attrs(&expr.attrs); self.expr(&expr.base, FixupContext::NONE); self.word(" !is "); self.ident(&expr.variant_ident); }
pub fn expr_has(&mut self, expr: &verus_syn::ExprHas) { self.outer_attrs(&expr.attrs); self.expr(&expr.lhs, FixupContext::NONE); self.word(" has "); self.expr(&expr.rhs, FixupContext::NONE); }
pub fn expr_hasnot(&mut self, expr: &verus_syn::ExprHasNot) { self.outer_attrs(&expr.attrs); self.expr(&expr.lhs, FixupContext::NONE); self.word(" !has "); self.expr(&expr.rhs, FixupContext::NONE); }
pub fn expr_matches(&mut self, expr: &verus_syn::ExprMatches) { self.outer_attrs(&expr.attrs); self.expr(&expr.lhs, FixupContext::NONE); self.word(" matches "); self.pat(&expr.pat); match &expr.op_expr { None => {} Some(verus_syn::MatchesOpExpr { op_token, rhs }) => { match op_token { verus_syn::MatchesOpToken::Implies(..) => { self.word(" ==> "); } verus_syn::MatchesOpToken::AndAnd(..) => { self.word(" && "); } verus_syn::MatchesOpToken::BigAnd => { self.word(" &&& "); } } self.expr(rhs, FixupContext::NONE); } } }
pub fn expr_get_field(&mut self, expr: &verus_syn::ExprGetField) { self.outer_attrs(&expr.attrs); self.expr(&expr.base, FixupContext::NONE); self.word("->"); self.member(&expr.member); }
pub fn expr_final(&mut self, expr: &verus_syn::ExprFinal) { self.outer_attrs(&expr.attrs); self.word("final("); self.expr(&expr.arg, FixupContext::NONE); self.word(")"); }
pub fn expr_beginning_of_line( &mut self, expr: &Expr, mut needs_paren: bool, beginning_of_line: bool, mut fixup: FixupContext, ) { needs_paren |= fixup.parenthesize(expr); if needs_paren { self.word("("); fixup = FixupContext::NONE; }
match expr { Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup), Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup), Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup), Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup), Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup), _ => self.expr(expr, fixup), }
if needs_paren { self.word(")"); } }
fn prefix_subexpr( &mut self, expr: &Expr, mut needs_paren: bool, beginning_of_line: bool, mut fixup: FixupContext, ) { needs_paren |= fixup.parenthesize(expr); if needs_paren { self.word("("); fixup = FixupContext::NONE; }
match expr { Expr::Await(expr) => self.prefix_subexpr_await(expr, beginning_of_line, fixup), Expr::Call(expr) => self.prefix_subexpr_call(expr, fixup), Expr::Field(expr) => self.prefix_subexpr_field(expr, beginning_of_line, fixup), Expr::Index(expr) => self.prefix_subexpr_index(expr, beginning_of_line, fixup), Expr::MethodCall(expr) => { let unindent_call_args = false; self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup); } Expr::Try(expr) => self.prefix_subexpr_try(expr, beginning_of_line, fixup), _ => { self.cbox(-INDENT); self.expr(expr, fixup); self.end(); } }
if needs_paren { self.word(")"); } }
fn expr_condition(&mut self, expr: &Expr) { self.cbox(0); self.expr(expr, FixupContext::new_condition()); if needs_newline_if_wrap(expr) { self.space(); } else { self.nbsp(); } self.end(); }
pub fn subexpr(&mut self, expr: &Expr, needs_paren: bool, mut fixup: FixupContext) { if needs_paren { self.word("("); fixup = FixupContext::NONE; }
self.expr(expr, fixup);
if needs_paren { self.word(")"); } }
fn expr_array(&mut self, expr: &ExprArray) { self.outer_attrs(&expr.attrs); if expr.elems.is_empty() { self.word("[]"); } else if simple_array(&expr.elems) { self.cbox(INDENT); self.word("["); self.zerobreak(); self.ibox(0); for elem in expr.elems.iter().delimited() { self.expr(&elem, FixupContext::NONE); if !elem.is_last { self.word(","); self.space(); } } self.end(); self.trailing_comma(true); self.offset(-INDENT); self.word("]"); self.end(); } else { self.word("["); self.cbox(INDENT); self.zerobreak(); for elem in expr.elems.iter().delimited() { self.expr(&elem, FixupContext::NONE); self.trailing_comma(elem.is_last); } self.offset(-INDENT); self.end(); self.word("]"); } }
fn expr_assign(&mut self, expr: &ExprAssign, fixup: FixupContext) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( &expr.left, false, false, Precedence::Assign, ); let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign);
self.outer_attrs(&expr.attrs); self.ibox(0); if !expr.attrs.is_empty() { self.word("("); } self.subexpr(&expr.left, left_prec <= Precedence::Range, left_fixup); self.word(" = "); self.neverbreak(); self.expr(&expr.right, right_fixup); if !expr.attrs.is_empty() { self.word(")"); } self.end(); }
fn expr_async(&mut self, expr: &ExprAsync) { self.outer_attrs(&expr.attrs); self.word("async "); if expr.capture.is_some() { self.word("move "); } self.cbox(INDENT); self.small_block(&expr.block, &expr.attrs); self.end(); }
fn expr_await(&mut self, expr: &ExprAwait, beginning_of_line: bool, fixup: FixupContext) { self.outer_attrs(&expr.attrs); self.cbox(INDENT); self.prefix_subexpr_await(expr, beginning_of_line, fixup); self.end(); }
fn prefix_subexpr_await( &mut self, expr: &ExprAwait, beginning_of_line: bool, fixup: FixupContext, ) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
self.prefix_subexpr( &expr.base, left_prec < Precedence::Unambiguous, beginning_of_line, left_fixup, ); if !(beginning_of_line && is_short_ident(&expr.base)) { self.scan_break(BreakToken { no_break: self.ends_with('.').then_some(' '), ..BreakToken::default() }); } self.word(".await"); }
fn expr_binary(&mut self, expr: &ExprBinary, fixup: FixupContext) { let binop_prec = Precedence::of_binop(&expr.op); let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( &expr.left, match &expr.op { BinOp::Sub(_) | BinOp::Mul(_) | BinOp::And(_) | BinOp::Or(_) | BinOp::BitAnd(_) | BinOp::BitOr(_) | BinOp::Shl(_) | BinOp::Lt(_) => true, _ => false, }, match &expr.op { BinOp::Shl(_) | BinOp::Lt(_) => true, _ => false, }, binop_prec, ); let left_needs_group = match binop_prec { Precedence::Assign => left_prec <= Precedence::Range, // verus supports chained comparisons: // Precedence::Compare => left_prec <= binop_prec, _ => left_prec < binop_prec, }; let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec); let right_needs_group = binop_prec != Precedence::Assign && right_fixup.rightmost_subexpression_precedence(&expr.right) <= binop_prec;
self.outer_attrs(&expr.attrs); self.ibox(INDENT); self.ibox(-INDENT); if !expr.attrs.is_empty() { self.word("("); } self.subexpr(&expr.left, left_needs_group, left_fixup); self.end(); self.space(); self.binary_operator(&expr.op); self.nbsp(); self.subexpr(&expr.right, right_needs_group, right_fixup); if !expr.attrs.is_empty() { self.word(")"); } self.end(); }
pub fn expr_block(&mut self, expr: &ExprBlock) { self.outer_attrs(&expr.attrs); if let Some(label) = &expr.label { self.label(label); } self.cbox(INDENT); self.small_block(&expr.block, &expr.attrs); self.end(); }
fn expr_break(&mut self, expr: &ExprBreak, fixup: FixupContext) { self.outer_attrs(&expr.attrs); self.word("break"); if let Some(lifetime) = &expr.label { self.nbsp(); self.lifetime(lifetime); } if let Some(value) = &expr.expr { self.nbsp(); self.subexpr( value, expr.label.is_none() && classify::expr_leading_label(value), fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump), ); } }
fn expr_call(&mut self, expr: &ExprCall, beginning_of_line: bool, fixup: FixupContext) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( &expr.func, true, false, Precedence::Unambiguous, ); let needs_paren = if let Expr::Field(func) = &*expr.func { matches!(func.member, Member::Named(_)) } else { left_prec < Precedence::Unambiguous };
self.outer_attrs(&expr.attrs); self.expr_beginning_of_line(&expr.func, needs_paren, beginning_of_line, left_fixup); self.word("("); self.call_args(&expr.args); self.word(")"); }
fn prefix_subexpr_call(&mut self, expr: &ExprCall, fixup: FixupContext) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( &expr.func, true, false, Precedence::Unambiguous, ); let needs_paren = if let Expr::Field(func) = &*expr.func { matches!(func.member, Member::Named(_)) } else { left_prec < Precedence::Unambiguous };
let beginning_of_line = false; self.prefix_subexpr(&expr.func, needs_paren, beginning_of_line, left_fixup); self.word("("); self.call_args(&expr.args); self.word(")"); }
fn expr_cast(&mut self, expr: &ExprCast, fixup: FixupContext) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(&expr.expr, false, false, Precedence::Cast);
self.outer_attrs(&expr.attrs); self.ibox(INDENT); self.ibox(-INDENT); if !expr.attrs.is_empty() { self.word("("); } self.subexpr(&expr.expr, left_prec < Precedence::Cast, left_fixup); self.end(); self.space(); self.word("as "); self.ty(&expr.ty); if !expr.attrs.is_empty() { self.word(")"); } self.end(); }
fn expr_closure(&mut self, expr: &ExprClosure, fixup: FixupContext) { self.outer_attrs(&expr.attrs); self.ibox(0); if let Some(bound_lifetimes) = &expr.lifetimes { self.bound_lifetimes(bound_lifetimes); } if expr.constness.is_some() { self.word("const "); } if expr.movability.is_some() { self.word("static "); } if expr.asyncness.is_some() { self.word("async "); } if expr.capture.is_some() { self.word("move "); } self.cbox(INDENT); self.word("|"); for pat in expr.inputs.iter().delimited() { if pat.is_first { self.zerobreak(); } self.pat(&pat.pat); if !pat.is_last { self.word(","); self.space(); } } match &expr.output { ReturnType::Default => { self.word("|"); self.space(); self.offset(-INDENT); self.end(); self.neverbreak(); let wrap_in_brace = match &*expr.body { Expr::Match(ExprMatch { attrs, .. }) | Expr::Call(ExprCall { attrs, .. }) => { attr::has_outer(attrs) } body => !is_blocklike(body), }; if wrap_in_brace { self.cbox(INDENT); let okay_to_brace = parseable_as_stmt(&expr.body); self.scan_break(BreakToken { pre_break: Some(if okay_to_brace { '{' } else { '(' }), ..BreakToken::default() }); self.expr( &expr.body, fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump), ); self.scan_break(BreakToken { offset: -INDENT, pre_break: (okay_to_brace && stmt::add_semi(&expr.body)).then_some(';'), post_break: if okay_to_brace { "}" } else { ")" }, ..BreakToken::default() }); self.end(); } else { self.expr( &expr.body, fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump), ); } } ReturnType::Type(_arrow, _, _, ty) => { if !expr.inputs.is_empty() { self.trailing_comma(true); self.offset(-INDENT); } self.word("|"); self.end(); self.word(" -> "); self.ty(ty); self.nbsp(); self.neverbreak(); if matches!(&*expr.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none()) { self.expr( &expr.body, fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump), ); } else { self.cbox(INDENT); self.expr_as_small_block(&expr.body, 0); self.end(); } } } self.end(); }
pub fn expr_const(&mut self, expr: &ExprConst) { self.outer_attrs(&expr.attrs); self.word("const "); self.cbox(INDENT); self.small_block(&expr.block, &expr.attrs); self.end(); }
fn expr_continue(&mut self, expr: &ExprContinue) { self.outer_attrs(&expr.attrs); self.word("continue"); if let Some(lifetime) = &expr.label { self.nbsp(); self.lifetime(lifetime); } }
fn expr_field(&mut self, expr: &ExprField, beginning_of_line: bool, fixup: FixupContext) { self.outer_attrs(&expr.attrs); self.cbox(INDENT); self.prefix_subexpr_field(expr, beginning_of_line, fixup); self.end(); }
fn prefix_subexpr_field( &mut self, expr: &ExprField, beginning_of_line: bool, fixup: FixupContext, ) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
self.prefix_subexpr( &expr.base, left_prec < Precedence::Unambiguous, beginning_of_line, left_fixup, ); if !(beginning_of_line && is_short_ident(&expr.base)) { self.scan_break(BreakToken { no_break: self.ends_with('.').then_some(' '), ..BreakToken::default() }); } self.word("."); self.member(&expr.member); }
fn expr_for_loop(&mut self, expr: &ExprForLoop) { self.outer_attrs(&expr.attrs); self.ibox(0); if let Some(label) = &expr.label { self.label(label); } self.word("for "); self.pat(&expr.pat); self.word(" in "); self.neverbreak(); self.expr_condition(&expr.expr); self.word("{"); self.neverbreak(); self.cbox(INDENT); self.hardbreak_if_nonempty(); self.inner_attrs(&expr.attrs); for stmt in expr.body.stmts.iter().delimited() { self.stmt(&stmt, stmt.is_last); } self.offset(-INDENT); self.end(); self.word("}"); self.end(); }
fn expr_group(&mut self, expr: &ExprGroup, fixup: FixupContext) { self.outer_attrs(&expr.attrs); self.expr(&expr.expr, fixup); }
fn expr_if(&mut self, expr: &ExprIf) { self.outer_attrs(&expr.attrs); self.cbox(INDENT); self.word("if "); self.cbox(-INDENT); self.expr_condition(&expr.cond); self.end(); if let Some((_else_token, else_branch)) = &expr.else_branch { let mut else_branch = &**else_branch; self.small_block(&expr.then_branch, &[]); loop { self.word(" else "); match else_branch { Expr::If(expr) => { self.word("if "); self.cbox(-INDENT); self.expr_condition(&expr.cond); self.end(); self.small_block(&expr.then_branch, &[]); if let Some((_else_token, next)) = &expr.else_branch { else_branch = next; continue; } } Expr::Block(expr) => { self.small_block(&expr.block, &[]); } // If not one of the valid expressions to exist in an else // clause, wrap in a block. other => self.expr_as_small_block(other, INDENT), } break; } } else if expr.then_branch.stmts.is_empty() { self.word("{}"); } else { self.word("{"); self.hardbreak(); for stmt in expr.then_branch.stmts.iter().delimited() { self.stmt(&stmt, stmt.is_last); } self.offset(-INDENT); self.word("}"); } self.end(); }
fn expr_index(&mut self, expr: &ExprIndex, beginning_of_line: bool, fixup: FixupContext) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( &expr.expr, true, false, Precedence::Unambiguous, );
self.outer_attrs(&expr.attrs); self.expr_beginning_of_line( &expr.expr, left_prec < Precedence::Unambiguous, beginning_of_line, left_fixup, ); self.word("["); self.expr(&expr.index, FixupContext::NONE); self.word("]"); }
fn prefix_subexpr_index( &mut self, expr: &ExprIndex, beginning_of_line: bool, fixup: FixupContext, ) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( &expr.expr, true, false, Precedence::Unambiguous, );
self.prefix_subexpr( &expr.expr, left_prec < Precedence::Unambiguous, beginning_of_line, left_fixup, ); self.word("["); self.expr(&expr.index, FixupContext::NONE); self.word("]"); }
fn expr_infer(&mut self, expr: &ExprInfer) { self.outer_attrs(&expr.attrs); self.word("_"); }
fn expr_let(&mut self, expr: &ExprLet, fixup: FixupContext) { let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Let);
self.outer_attrs(&expr.attrs); self.ibox(0); self.word("let "); self.ibox(0); self.pat(&expr.pat); self.end(); self.word(" = "); self.neverbreak(); self.ibox(0); self.subexpr(&expr.expr, right_prec < Precedence::Let, right_fixup); self.end(); self.end(); }
pub fn expr_lit(&mut self, expr: &ExprLit) { self.outer_attrs(&expr.attrs); self.lit(&expr.lit); }
fn expr_loop(&mut self, expr: &ExprLoop) { self.outer_attrs(&expr.attrs); if let Some(label) = &expr.label { self.label(label); } self.word("loop {"); self.cbox(INDENT); self.hardbreak_if_nonempty(); self.inner_attrs(&expr.attrs); for stmt in expr.body.stmts.iter().delimited() { self.stmt(&stmt, stmt.is_last); } self.offset(-INDENT); self.end(); self.word("}"); }
pub fn expr_macro(&mut self, expr: &ExprMacro) { self.outer_attrs(&expr.attrs); let semicolon = false; self.mac(&expr.mac, None, semicolon); }
fn expr_match(&mut self, expr: &ExprMatch) { self.outer_attrs(&expr.attrs); self.ibox(0); self.word("match "); self.expr_condition(&expr.expr); self.word("{"); self.neverbreak(); self.cbox(INDENT); self.hardbreak_if_nonempty(); self.inner_attrs(&expr.attrs); for arm in &expr.arms { self.arm(arm); self.hardbreak(); } self.offset(-INDENT); self.end(); self.word("}"); self.end(); }
fn expr_method_call( &mut self, expr: &ExprMethodCall, beginning_of_line: bool, fixup: FixupContext, ) { self.outer_attrs(&expr.attrs); self.cbox(INDENT); let unindent_call_args = beginning_of_line && is_short_ident(&expr.receiver); self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup); self.end(); }
fn prefix_subexpr_method_call( &mut self, expr: &ExprMethodCall, beginning_of_line: bool, unindent_call_args: bool, fixup: FixupContext, ) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.receiver);
self.prefix_subexpr( &expr.receiver, left_prec < Precedence::Unambiguous, beginning_of_line, left_fixup, ); if !(beginning_of_line && is_short_ident(&expr.receiver)) { self.scan_break(BreakToken { no_break: self.ends_with('.').then_some(' '), ..BreakToken::default() }); } self.word("."); self.ident(&expr.method); if let Some(turbofish) = &expr.turbofish { self.angle_bracketed_generic_arguments(turbofish, PathKind::Expr); } self.cbox(if unindent_call_args { -INDENT } else { 0 }); self.word("("); self.call_args(&expr.args); self.word(")"); self.end(); }
fn expr_paren(&mut self, expr: &ExprParen) { self.outer_attrs(&expr.attrs); self.word("("); self.expr(&expr.expr, FixupContext::NONE); self.word(")"); }
pub fn expr_path(&mut self, expr: &ExprPath) { self.outer_attrs(&expr.attrs); self.qpath(&expr.qself, &expr.path, PathKind::Expr); }
pub fn expr_range(&mut self, expr: &ExprRange, fixup: FixupContext) { self.outer_attrs(&expr.attrs); if !expr.attrs.is_empty() { self.word("("); } if let Some(start) = &expr.start { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range); self.subexpr(start, left_prec <= Precedence::Range, left_fixup); } else if self.ends_with('.') { self.nbsp(); } self.word(match expr.limits { RangeLimits::HalfOpen(_) => "..", RangeLimits::Closed(_) => "..=", }); if let Some(end) = &expr.end { let right_fixup = fixup.rightmost_subexpression_fixup(false, true, Precedence::Range); let right_prec = right_fixup.rightmost_subexpression_precedence(end); self.subexpr(end, right_prec <= Precedence::Range, right_fixup); } if !expr.attrs.is_empty() { self.word(")"); } }
fn expr_raw_addr(&mut self, expr: &ExprRawAddr, fixup: FixupContext) { let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
self.outer_attrs(&expr.attrs); self.word("&raw "); self.pointer_mutability(&expr.mutability); self.nbsp(); self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup); }
fn expr_reference(&mut self, expr: &ExprReference, fixup: FixupContext) { let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
self.outer_attrs(&expr.attrs); self.word("&"); if expr.mutability.is_some() { self.word("mut "); } self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup); }
fn expr_repeat(&mut self, expr: &ExprRepeat) { self.outer_attrs(&expr.attrs); self.word("["); self.expr(&expr.expr, FixupContext::NONE); self.word("; "); self.expr(&expr.len, FixupContext::NONE); self.word("]"); }
fn expr_return(&mut self, expr: &ExprReturn, fixup: FixupContext) { self.outer_attrs(&expr.attrs); self.word("return"); if let Some(value) = &expr.expr { self.nbsp(); self.expr( value, fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump), ); } }
fn expr_struct(&mut self, expr: &ExprStruct) { self.outer_attrs(&expr.attrs); self.cbox(INDENT); self.ibox(-INDENT); self.qpath(&expr.qself, &expr.path, PathKind::Expr); self.end(); self.word(" {"); self.space_if_nonempty(); for field_value in expr.fields.iter().delimited() { self.field_value(&field_value); self.trailing_comma_or_space(field_value.is_last && expr.rest.is_none()); } if let Some(rest) = &expr.rest { self.word(".."); self.expr(rest, FixupContext::NONE); self.space(); } self.offset(-INDENT); self.end_with_max_width(34); self.word("}"); }
fn expr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
self.outer_attrs(&expr.attrs); self.expr_beginning_of_line( &expr.expr, left_prec < Precedence::Unambiguous, beginning_of_line, left_fixup, ); self.word("?"); }
fn prefix_subexpr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) { let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
self.prefix_subexpr( &expr.expr, left_prec < Precedence::Unambiguous, beginning_of_line, left_fixup, ); self.word("?"); }
fn expr_try_block(&mut self, expr: &ExprTryBlock) { self.outer_attrs(&expr.attrs); self.word("try "); self.cbox(INDENT); self.small_block(&expr.block, &expr.attrs); self.end(); }
fn expr_tuple(&mut self, expr: &ExprTuple) { self.outer_attrs(&expr.attrs); self.word("("); self.cbox(INDENT); self.zerobreak(); for elem in expr.elems.iter().delimited() { self.expr(&elem, FixupContext::NONE); if expr.elems.len() == 1 { self.word(","); self.zerobreak(); } else { self.trailing_comma(elem.is_last); } } self.offset(-INDENT); self.end(); self.word(")"); }
fn expr_unary(&mut self, expr: &ExprUnary, fixup: FixupContext) { let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
self.outer_attrs(&expr.attrs); self.unary_operator(&expr.op); self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup); }
fn expr_unsafe(&mut self, expr: &ExprUnsafe) { self.outer_attrs(&expr.attrs); self.word("unsafe "); self.cbox(INDENT); self.small_block(&expr.block, &expr.attrs); self.end(); }
#[cfg(not(feature = "verbatim"))] fn expr_verbatim(&mut self, expr: &TokenStream, _fixup: FixupContext) { if !expr.is_empty() { unimplemented!("Expr::Verbatim `{}`", expr); } }
#[cfg(feature = "verbatim")] fn expr_verbatim(&mut self, tokens: &TokenStream, fixup: FixupContext) { use syn::parse::discouraged::Speculative; use syn::parse::{Parse, ParseStream, Result}; use syn::{parenthesized, Ident};
enum ExprVerbatim { Empty, Ellipsis, Become(Become), Builtin(Builtin), }
struct Become { attrs: Vec<Attribute>, tail_call: Expr, }
struct Builtin { attrs: Vec<Attribute>, name: Ident, args: TokenStream, }
mod kw { syn::custom_keyword!(builtin); syn::custom_keyword!(raw); }
impl Parse for ExprVerbatim { fn parse(input: ParseStream) -> Result<Self> { let ahead = input.fork(); let attrs = ahead.call(Attribute::parse_outer)?; let lookahead = ahead.lookahead1(); if input.is_empty() { Ok(ExprVerbatim::Empty) } else if lookahead.peek(Token![become]) { input.advance_to(&ahead); input.parse::<Token![become]>()?; let tail_call: Expr = input.parse()?; Ok(ExprVerbatim::Become(Become { attrs, tail_call })) } else if lookahead.peek(kw::builtin) { input.advance_to(&ahead); input.parse::<kw::builtin>()?; input.parse::<Token![#]>()?; let name: Ident = input.parse()?; let args; parenthesized!(args in input); let args: TokenStream = args.parse()?; Ok(ExprVerbatim::Builtin(Builtin { attrs, name, args })) } else if lookahead.peek(Token![...]) { input.parse::<Token![...]>()?; Ok(ExprVerbatim::Ellipsis) } else { Err(lookahead.error()) } } }
let expr: ExprVerbatim = match syn::parse2(tokens.clone()) { Ok(expr) => expr, Err(_) => unimplemented!("Expr::Verbatim `{}`", tokens), };
match expr { ExprVerbatim::Empty => {} ExprVerbatim::Ellipsis => { self.word("..."); } ExprVerbatim::Become(expr) => { self.outer_attrs(&expr.attrs); self.word("become"); self.nbsp(); self.expr( &expr.tail_call, fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump), ); } ExprVerbatim::Builtin(expr) => { self.outer_attrs(&expr.attrs); self.word("builtin # "); self.ident(&expr.name); self.word("("); if !expr.args.is_empty() { self.cbox(INDENT); self.zerobreak(); self.ibox(0); self.macro_rules_tokens(expr.args, false); self.end(); self.zerobreak(); self.offset(-INDENT); self.end(); } self.word(")"); } } }
fn expr_while(&mut self, expr: &ExprWhile) { self.outer_attrs(&expr.attrs); if let Some(label) = &expr.label { self.label(label); } self.word("while "); self.expr_condition(&expr.cond); self.word("{"); self.neverbreak(); self.cbox(INDENT); self.hardbreak_if_nonempty(); self.inner_attrs(&expr.attrs); for stmt in expr.body.stmts.iter().delimited() { self.stmt(&stmt, stmt.is_last); } self.offset(-INDENT); self.end(); self.word("}"); }
fn expr_yield(&mut self, expr: &ExprYield, fixup: FixupContext) { self.outer_attrs(&expr.attrs); self.word("yield"); if let Some(value) = &expr.expr { self.nbsp(); self.expr( value, fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump), ); } }
fn label(&mut self, label: &Label) { self.lifetime(&label.name); self.word(": "); }
fn field_value(&mut self, field_value: &FieldValue) { self.outer_attrs(&field_value.attrs); self.member(&field_value.member); if field_value.colon_token.is_some() { self.word(": "); self.ibox(0); self.expr(&field_value.expr, FixupContext::NONE); self.end(); } }
fn arm(&mut self, arm: &Arm) { self.outer_attrs(&arm.attrs); self.ibox(0); self.pat(&arm.pat); if let Some((_if_token, guard)) = &arm.guard { self.word(" if "); self.expr(guard, FixupContext::NONE); } self.word(" => "); let empty_block; let mut body = &*arm.body; while let Expr::Block(expr) = body { if expr.attrs.is_empty() && expr.label.is_none() { let mut stmts = expr.block.stmts.iter(); if let (Some(Stmt::Expr(inner, None)), None) = (stmts.next(), stmts.next()) { body = inner; continue; } } break; } if let Expr::Tuple(expr) = body { if expr.elems.is_empty() && expr.attrs.is_empty() { empty_block = Expr::Block(ExprBlock { attrs: Vec::new(), label: None, block: Block { brace_token: token::Brace::default(), stmts: Vec::new(), }, }); body = &empty_block; } } if let Expr::Block(body) = body { if let Some(label) = &body.label { self.label(label); } self.word("{"); self.neverbreak(); self.cbox(INDENT); self.hardbreak_if_nonempty(); self.inner_attrs(&body.attrs); for stmt in body.block.stmts.iter().delimited() { self.stmt(&stmt, stmt.is_last); } self.offset(-INDENT); self.end(); self.word("}"); } else { self.neverbreak(); self.cbox(INDENT); let okay_to_brace = parseable_as_stmt(body); self.scan_break(BreakToken { pre_break: Some(if okay_to_brace { '{' } else { '(' }), ..BreakToken::default() }); self.expr_beginning_of_line(body, false, true, FixupContext::new_match_arm()); self.scan_break(BreakToken { offset: -INDENT, pre_break: (okay_to_brace && stmt::add_semi(body)).then_some(';'), post_break: if okay_to_brace { "}" } else { ")," }, no_break: classify::requires_comma_to_be_match_arm(body).then_some(','), ..BreakToken::default() }); self.end(); } self.end(); }
fn call_args(&mut self, args: &Punctuated<Expr, Token![,]>) { let mut iter = args.iter(); match (iter.next(), iter.next()) { (Some(expr), None) if is_blocklike(expr) => { self.expr(expr, FixupContext::NONE); } _ => { self.cbox(INDENT); self.zerobreak(); for arg in args.iter().delimited() { self.expr(&arg, FixupContext::NONE); self.trailing_comma(arg.is_last); } self.offset(-INDENT); self.end(); } } }
pub fn small_block(&mut self, block: &Block, attrs: &[Attribute]) { self.word("{"); if attr::has_inner(attrs) || !block.stmts.is_empty() { self.space(); self.inner_attrs(attrs); match block.stmts.as_slice() { [Stmt::Expr(expr, None)] if stmt::break_after(expr) => { self.ibox(0); self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt()); self.end(); self.space(); } _ => { for stmt in block.stmts.iter().delimited() { self.stmt(&stmt, stmt.is_last); } } } self.offset(-INDENT); } self.word("}"); }
pub fn expr_as_small_block(&mut self, expr: &Expr, indent: isize) { self.word("{"); self.space(); self.ibox(indent); self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt()); self.end(); self.space(); self.offset(-INDENT); self.word("}"); }
pub fn member(&mut self, member: &Member) { match member { Member::Named(ident) => self.ident(ident), Member::Unnamed(index) => self.index(index), } }
fn index(&mut self, member: &Index) { self.word(member.index.to_string()); }
fn binary_operator(&mut self, op: &BinOp) { self.word(match op { BinOp::Add(_) => "+", BinOp::Sub(_) => "-", BinOp::Mul(_) => "*", BinOp::Div(_) => "/", BinOp::Rem(_) => "%", BinOp::And(_) => "&&", BinOp::Or(_) => "||", BinOp::BitXor(_) => "^", BinOp::BitAnd(_) => "&", BinOp::BitOr(_) => "|", BinOp::Shl(_) => "<<", BinOp::Shr(_) => ">>", BinOp::Eq(_) => "==", BinOp::Lt(_) => "<", BinOp::Le(_) => "<=", BinOp::Ne(_) => "!=", BinOp::Ge(_) => ">=", BinOp::Gt(_) => ">", BinOp::AddAssign(_) => "+=", BinOp::SubAssign(_) => "-=", BinOp::MulAssign(_) => "*=", BinOp::DivAssign(_) => "/=", BinOp::RemAssign(_) => "%=", BinOp::BitXorAssign(_) => "^=", BinOp::BitAndAssign(_) => "&=", BinOp::BitOrAssign(_) => "|=", BinOp::ShlAssign(_) => "<<=", BinOp::ShrAssign(_) => ">>=",
// verus BinOp::Equiv(_) => "<==>", BinOp::Imply(_) => "==>", BinOp::Exply(_) => "<==", BinOp::BigEq(_) => "===", BinOp::BigNe(_) => "!==", BinOp::ExtEq(_) => "=~=", BinOp::ExtNe(_) => "!~=", BinOp::ExtDeepEq(_) => "=~~=", BinOp::ExtDeepNe(_) => "!~~=",
_ => unimplemented!("unknown BinOp"), }); }
fn unary_operator(&mut self, op: &UnOp) { self.word(match op { UnOp::Deref(_) => "*", UnOp::Not(_) => "!", UnOp::Neg(_) => "-",
// verus UnOp::Proof(_) => "proof ", UnOp::Forall(_) => "forall ", UnOp::Exists(_) => "exists ", UnOp::Choose(_) => "choose ",
_ => unimplemented!("unknown UnOp"), }); }
fn pointer_mutability(&mut self, mutability: &PointerMutability) { match mutability { PointerMutability::Const(_) => self.word("const"), PointerMutability::Mut(_) => self.word("mut"), } }}
fn needs_newline_if_wrap(expr: &Expr) -> bool { match expr { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Expr::Array(_) | Expr::Async(_) | Expr::Block(_) | Expr::Break(ExprBreak { expr: None, .. }) | Expr::Closure(_) | Expr::Const(_) | Expr::Continue(_) | Expr::ForLoop(_) | Expr::If(_) | Expr::Infer(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::Path(_) | Expr::Range(ExprRange { end: None, .. }) | Expr::Repeat(_) | Expr::Return(ExprReturn { expr: None, .. }) | Expr::Struct(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::While(_) | Expr::Yield(ExprYield { expr: None, .. }) => false,
Expr::Assign(_) | Expr::Await(_) | Expr::Binary(_) | Expr::Cast(_) | Expr::Field(_) | Expr::Index(_) | Expr::MethodCall(_) => true,
Expr::Break(ExprBreak { expr: Some(e), .. }) | Expr::Call(ExprCall { func: e, .. }) | Expr::Group(ExprGroup { expr: e, .. }) | Expr::Let(ExprLet { expr: e, .. }) | Expr::Paren(ExprParen { expr: e, .. }) | Expr::Range(ExprRange { end: Some(e), .. }) | Expr::RawAddr(ExprRawAddr { expr: e, .. }) | Expr::Reference(ExprReference { expr: e, .. }) | Expr::Return(ExprReturn { expr: Some(e), .. }) | Expr::Try(ExprTry { expr: e, .. }) | Expr::Unary(ExprUnary { expr: e, .. }) | Expr::Yield(ExprYield { expr: Some(e), .. }) => needs_newline_if_wrap(e),
_ => false, }}
fn is_short_ident(expr: &Expr) -> bool { if let Expr::Path(expr) = expr { return expr.attrs.is_empty() && expr.qself.is_none() && expr .path .get_ident() .is_some_and(|ident| ident.to_string().len() as isize <= INDENT); } false}
fn is_blocklike(expr: &Expr) -> bool { match expr { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Expr::Array(ExprArray { attrs, .. }) | Expr::Async(ExprAsync { attrs, .. }) | Expr::Block(ExprBlock { attrs, .. }) | Expr::Closure(ExprClosure { attrs, .. }) | Expr::Const(ExprConst { attrs, .. }) | Expr::Struct(ExprStruct { attrs, .. }) | Expr::TryBlock(ExprTryBlock { attrs, .. }) | Expr::Tuple(ExprTuple { attrs, .. }) | Expr::Unsafe(ExprUnsafe { attrs, .. }) => !attr::has_outer(attrs),
Expr::Assign(_) | Expr::Await(_) | Expr::Binary(_) | Expr::Break(_) | Expr::Call(_) | Expr::Cast(_) | Expr::Continue(_) | Expr::Field(_) | Expr::ForLoop(_) | Expr::If(_) | Expr::Index(_) | Expr::Infer(_) | Expr::Let(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::MethodCall(_) | Expr::Paren(_) | Expr::Path(_) | Expr::Range(_) | Expr::RawAddr(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) | Expr::Try(_) | Expr::Unary(_) | Expr::Verbatim(_) | Expr::While(_) | Expr::Yield(_) => false,
Expr::Group(e) => is_blocklike(&e.expr),
_ => false, }}
pub fn simple_block(expr: &Expr) -> Option<&ExprBlock> { if let Expr::Block(expr) = expr { if expr.attrs.is_empty() && expr.label.is_none() { return Some(expr); } } None}
pub fn simple_array(elements: &Punctuated<Expr, Token![,]>) -> bool { for expr in elements { if let Expr::Lit(expr) = expr { match expr.lit { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Lit::Byte(_) | Lit::Char(_) | Lit::Int(_) | Lit::Bool(_) => {}
Lit::Str(_) | Lit::ByteStr(_) | Lit::CStr(_) | Lit::Float(_) | Lit::Verbatim(_) => { return false; }
_ => return false, } } else { return false; } } true}
// Expressions for which `$expr` and `{ $expr }` mean the same thing.//// This is not the case for all expressions. For example `{} | x | x` has some// bitwise OR operators while `{ {} |x| x }` has a block followed by a closure.fn parseable_as_stmt(mut expr: &Expr) -> bool { loop { match expr { #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] Expr::Array(_) | Expr::Async(_) | Expr::Block(_) | Expr::Break(_) | Expr::Closure(_) | Expr::Const(_) | Expr::Continue(_) | Expr::ForLoop(_) | Expr::If(_) | Expr::Infer(_) | Expr::Lit(_) | Expr::Loop(_) | Expr::Macro(_) | Expr::Match(_) | Expr::Paren(_) | Expr::Path(_) | Expr::RawAddr(_) | Expr::Reference(_) | Expr::Repeat(_) | Expr::Return(_) | Expr::Struct(_) | Expr::TryBlock(_) | Expr::Tuple(_) | Expr::Unary(_) | Expr::Unsafe(_) | Expr::Verbatim(_) | Expr::While(_) | Expr::Yield(_) => return true,
Expr::Let(_) => return false,
Expr::Assign(e) => { if !classify::requires_semi_to_be_stmt(&e.left) { return false; } expr = &e.left; } Expr::Await(e) => expr = &e.base, Expr::Binary(e) => { if !classify::requires_semi_to_be_stmt(&e.left) { return false; } expr = &e.left; } Expr::Call(e) => { if !classify::requires_semi_to_be_stmt(&e.func) { return false; } expr = &e.func; } Expr::Cast(e) => { if !classify::requires_semi_to_be_stmt(&e.expr) { return false; } expr = &e.expr; } Expr::Field(e) => expr = &e.base, Expr::Group(e) => expr = &e.expr, Expr::Index(e) => { if !classify::requires_semi_to_be_stmt(&e.expr) { return false; } expr = &e.expr; } Expr::MethodCall(e) => expr = &e.receiver, Expr::Range(e) => match &e.start { None => return true, Some(start) => { if !classify::requires_semi_to_be_stmt(start) { return false; } expr = start; } }, Expr::Try(e) => expr = &e.expr,
_ => return false, } }}