c2rust_ast_builder/
builder.rs

1//! Helpers for building AST nodes.  Normally used by calling `mk().some_node(args...)`.
2
3use std::str;
4
5use proc_macro2::{Span, TokenStream, TokenTree};
6use std::default::Default;
7use std::iter::FromIterator;
8use syn::{__private::ToTokens, punctuated::Punctuated, *};
9
10/// a MetaItem that has already been turned into tokens in preparation for being added as an attribute
11pub struct PreparedMetaItem {
12    pub path: Path,
13    pub tokens: TokenStream,
14}
15
16pub mod properties {
17    use syn::Token;
18
19    pub trait ToToken {
20        type Token;
21        fn to_token(&self) -> Option<Self::Token>;
22    }
23
24    #[derive(Debug, Copy, Clone)]
25    pub enum Mutability {
26        Mutable,
27        Immutable,
28    }
29    impl ToToken for Mutability {
30        type Token = Token![mut];
31        fn to_token(&self) -> Option<Self::Token> {
32            match self {
33                Mutability::Mutable => Some(Default::default()),
34                Mutability::Immutable => None,
35            }
36        }
37    }
38
39    #[derive(Debug, Clone)]
40    pub enum Unsafety {
41        Normal,
42        Unsafe,
43    }
44    impl ToToken for Unsafety {
45        type Token = Token![unsafe];
46        fn to_token(&self) -> Option<Self::Token> {
47            match self {
48                Unsafety::Normal => None,
49                Unsafety::Unsafe => Some(Default::default()),
50            }
51        }
52    }
53
54    #[derive(Debug, Clone)]
55    pub enum Constness {
56        Const,
57        NotConst,
58    }
59    impl ToToken for Constness {
60        type Token = Token![const];
61        fn to_token(&self) -> Option<Self::Token> {
62            match self {
63                Constness::NotConst => None,
64                Constness::Const => Some(Default::default()),
65            }
66        }
67    }
68
69    #[derive(Debug, Clone)]
70    pub enum Movability {
71        Movable,
72        Immovable,
73    }
74    impl ToToken for Movability {
75        type Token = Token![static];
76        fn to_token(&self) -> Option<Self::Token> {
77            match self {
78                Movability::Immovable => Some(Default::default()),
79                Movability::Movable => None,
80            }
81        }
82    }
83
84    #[derive(Debug, Clone)]
85    pub enum IsAsync {
86        Async,
87        NotAsync,
88    }
89    impl ToToken for IsAsync {
90        type Token = Token![async];
91        fn to_token(&self) -> Option<Self::Token> {
92            match self {
93                IsAsync::NotAsync => None,
94                IsAsync::Async => Some(Default::default()),
95            }
96        }
97    }
98
99    #[derive(Debug, Clone)]
100    pub enum Defaultness {
101        Final,
102        Default,
103    }
104    impl ToToken for Defaultness {
105        type Token = Token![default];
106        fn to_token(&self) -> Option<Self::Token> {
107            match self {
108                Defaultness::Final => None,
109                Defaultness::Default => Some(Default::default()),
110            }
111        }
112    }
113}
114
115use self::properties::*;
116
117pub type FnDecl = (Ident, Vec<FnArg>, Option<Variadic>, ReturnType);
118pub type BareFnTyParts = (Vec<BareFnArg>, Option<Variadic>, ReturnType);
119
120pub enum CaptureBy {
121    Value,
122    Ref,
123}
124
125#[derive(Debug, Clone)]
126pub enum Extern {
127    None,
128    Implicit,
129    Explicit(String),
130}
131
132//const Async : IsAsync = Some(Default::default());
133
134pub enum SelfKind {
135    Value(Mutability),
136    Region(Lifetime, Mutability),
137}
138
139fn use_tree_with_prefix(prefix: Path, leaf: UseTree) -> UseTree {
140    let mut out = leaf;
141    for seg in prefix.segments.into_iter().rev() {
142        out = UseTree::Path(UsePath {
143            ident: seg.ident,
144            colon2_token: Default::default(),
145            tree: Box::new(out),
146        });
147    }
148    out
149}
150
151fn punct<T, P: Default>(x: Vec<T>) -> Punctuated<T, P> {
152    Punctuated::from_iter(x.into_iter())
153}
154
155fn punct_box<T, P: Default>(x: Vec<Box<T>>) -> Punctuated<T, P> {
156    Punctuated::from_iter(x.into_iter().map(|x| *x))
157}
158
159pub trait Make<T> {
160    fn make(self, mk: &Builder) -> T;
161}
162
163impl<T> Make<T> for T {
164    fn make(self, _mk: &Builder) -> T {
165        self
166    }
167}
168
169impl Make<Ident> for &str {
170    fn make(self, mk: &Builder) -> Ident {
171        Ident::new(self, mk.span)
172    }
173}
174
175impl Make<Ident> for String {
176    fn make(self, mk: &Builder) -> Ident {
177        Ident::new(&self, mk.span)
178    }
179}
180
181impl Make<Ident> for &String {
182    fn make(self, mk: &Builder) -> Ident {
183        Ident::new(self, mk.span)
184    }
185}
186
187impl<L: Make<Ident>> Make<Label> for L {
188    fn make(self, mk: &Builder) -> Label {
189        Label {
190            name: Lifetime {
191                apostrophe: mk.span,
192                ident: self.make(mk),
193            },
194            colon_token: Token![:](mk.span),
195        }
196    }
197}
198
199impl<'a> Make<Path> for &'a str {
200    fn make(self, mk: &Builder) -> Path {
201        let v = vec![self];
202        Make::<Path>::make(v, mk)
203    }
204}
205
206impl<'a> Make<Visibility> for &'a str {
207    fn make(self, mk_: &Builder) -> Visibility {
208        match self {
209            "pub" => Visibility::Public(VisPublic {
210                pub_token: Token![pub](mk_.span),
211            }),
212            "priv" | "" | "inherit" => Visibility::Inherited,
213            "crate" => Visibility::Crate(VisCrate {
214                crate_token: Token![crate](mk_.span),
215            }),
216            "pub(crate)" => Visibility::Restricted(VisRestricted {
217                pub_token: Token![pub](mk_.span),
218                paren_token: token::Paren(mk_.span),
219                in_token: None,
220                path: Box::new(mk().path("crate")),
221            }),
222            "pub(super)" => Visibility::Restricted(VisRestricted {
223                pub_token: Token![pub](mk_.span),
224                paren_token: token::Paren(mk_.span),
225                in_token: None,
226                path: Box::new(mk().path("super")),
227            }),
228            _ => panic!("unrecognized string for Visibility: {:?}", self),
229        }
230    }
231}
232
233impl<'a> Make<Abi> for &'a str {
234    fn make(self, mk: &Builder) -> Abi {
235        Abi {
236            extern_token: Token![extern](mk.span),
237            name: Some(LitStr::new(self, mk.span)),
238        }
239        // TODO: validate string: format!("unrecognized string for Abi: {:?}", self))
240    }
241}
242
243impl<'a> Make<Extern> for &'a str {
244    fn make(self, _mk: &Builder) -> Extern {
245        Extern::Explicit(self.to_owned())
246    }
247}
248
249impl Make<Extern> for Abi {
250    fn make(self, _mk: &Builder) -> Extern {
251        Extern::Explicit(self.name.to_token_stream().to_string())
252    }
253}
254
255impl<'a> Make<Mutability> for &'a str {
256    fn make(self, _mk: &Builder) -> Mutability {
257        match self {
258            "" | "imm" | "immut" | "immutable" => Mutability::Immutable,
259            "mut" | "mutable" => Mutability::Mutable,
260            _ => panic!("unrecognized string for Mutability: {:?}", self),
261        }
262    }
263}
264
265impl<'a> Make<Unsafety> for &'a str {
266    fn make(self, _mk: &Builder) -> Unsafety {
267        match self {
268            "" | "safe" | "normal" => Unsafety::Normal,
269            "unsafe" => Unsafety::Unsafe,
270            _ => panic!("unrecognized string for Unsafety: {:?}", self),
271        }
272    }
273}
274
275impl<'a> Make<Constness> for &'a str {
276    fn make(self, _mk: &Builder) -> Constness {
277        match self {
278            "" | "normal" | "not-const" => Constness::NotConst,
279            "const" => Constness::Const,
280            _ => panic!("unrecognized string for Constness: {:?}", self),
281        }
282    }
283}
284
285impl<'a> Make<UnOp> for &'a str {
286    fn make(self, _mk: &Builder) -> UnOp {
287        match self {
288            "deref" | "*" => UnOp::Deref(Default::default()),
289            "not" | "!" => UnOp::Not(Default::default()),
290            "neg" | "-" => UnOp::Neg(Default::default()),
291            _ => panic!("unrecognized string for UnOp: {:?}", self),
292        }
293    }
294}
295
296impl<I: Make<Ident>> Make<Lifetime> for I {
297    fn make(self, mk: &Builder) -> Lifetime {
298        Lifetime {
299            apostrophe: mk.span,
300            ident: self.make(mk),
301        }
302    }
303}
304
305impl<I: Make<Ident>> Make<PathSegment> for I {
306    fn make(self, mk: &Builder) -> PathSegment {
307        PathSegment {
308            ident: self.make(mk),
309            arguments: PathArguments::None,
310        }
311    }
312}
313
314impl<S: Make<PathSegment>> Make<Path> for Vec<S> {
315    fn make(self, mk: &Builder) -> Path {
316        let mut segments = Punctuated::new();
317        for s in self {
318            let segment = s.make(mk);
319            let has_params = !segment.arguments.is_empty();
320            segments.push(segment);
321            // separate params from their segment with ::
322            if has_params {
323                segments.push_punct(Default::default());
324            }
325        }
326        Path {
327            leading_colon: None,
328            segments,
329        }
330    }
331}
332
333impl Make<TokenStream> for Vec<TokenTree> {
334    fn make(self, _mk: &Builder) -> TokenStream {
335        self.into_iter().collect::<TokenStream>()
336    }
337}
338
339impl Make<PathArguments> for AngleBracketedGenericArguments {
340    fn make(self, _mk: &Builder) -> PathArguments {
341        PathArguments::AngleBracketed(self)
342    }
343}
344
345impl Make<PathArguments> for ParenthesizedGenericArguments {
346    fn make(self, _mk: &Builder) -> PathArguments {
347        PathArguments::Parenthesized(self)
348    }
349}
350
351impl Make<GenericArgument> for Box<Type> {
352    fn make(self, _mk: &Builder) -> GenericArgument {
353        GenericArgument::Type(*self)
354    }
355}
356
357impl Make<GenericArgument> for Lifetime {
358    fn make(self, _mk: &Builder) -> GenericArgument {
359        GenericArgument::Lifetime(self)
360    }
361}
362
363impl Make<NestedMeta> for Meta {
364    fn make(self, _mk: &Builder) -> NestedMeta {
365        NestedMeta::Meta(self)
366    }
367}
368
369impl Make<NestedMeta> for Lit {
370    fn make(self, _mk: &Builder) -> NestedMeta {
371        NestedMeta::Lit(self)
372    }
373}
374
375impl Make<Lit> for String {
376    fn make(self, mk: &Builder) -> Lit {
377        Lit::Str(LitStr::new(&self, mk.span))
378    }
379}
380
381impl Make<Lit> for &String {
382    fn make(self, mk: &Builder) -> Lit {
383        Lit::Str(LitStr::new(self, mk.span))
384    }
385}
386
387impl Make<Lit> for &str {
388    fn make(self, mk: &Builder) -> Lit {
389        Lit::Str(LitStr::new(self, mk.span))
390    }
391}
392
393impl Make<Lit> for Vec<u8> {
394    fn make(self, mk: &Builder) -> Lit {
395        Lit::ByteStr(LitByteStr::new(&self, mk.span))
396    }
397}
398
399impl Make<Lit> for u8 {
400    fn make(self, mk: &Builder) -> Lit {
401        Lit::Byte(LitByte::new(self, mk.span))
402    }
403}
404
405impl Make<Lit> for char {
406    fn make(self, mk: &Builder) -> Lit {
407        Lit::Char(LitChar::new(self, mk.span))
408    }
409}
410
411impl Make<Lit> for u128 {
412    fn make(self, mk: &Builder) -> Lit {
413        Lit::Int(LitInt::new(&self.to_string(), mk.span))
414    }
415}
416
417impl Make<Signature> for Box<FnDecl> {
418    fn make(self, mk: &Builder) -> Signature {
419        let (name, inputs, variadic, output) = *self;
420        Signature {
421            unsafety: mk.unsafety.to_token(),
422            asyncness: IsAsync::NotAsync.to_token(),
423            constness: mk.constness.to_token(),
424            fn_token: Token![fn](mk.span),
425            paren_token: Default::default(),
426            generics: mk.generics.clone(),
427            abi: mk.get_abi_opt(),
428            ident: name,
429            inputs: punct(inputs),
430            variadic,
431            output,
432        }
433    }
434}
435
436#[derive(Clone, Debug)]
437pub struct Builder {
438    // The builder holds a set of "modifiers", such as visibility and mutability.  Functions for
439    // building AST nodes don't take arguments of these types, but instead use any applicable
440    // modifiers from the builder to set the node's visibility, mutability, etc.
441    vis: Visibility,
442    mutbl: Mutability,
443    generics: Generics,
444    unsafety: Unsafety,
445    constness: Constness,
446    ext: Extern,
447    attrs: Vec<Attribute>,
448    span: Span,
449}
450
451impl Default for Builder {
452    fn default() -> Self {
453        Builder {
454            vis: Visibility::Inherited,
455            mutbl: Mutability::Immutable,
456            generics: Generics::default(),
457            unsafety: Unsafety::Normal,
458            constness: Constness::NotConst,
459            ext: Extern::None,
460            attrs: Vec::new(),
461            span: Span::call_site(),
462        }
463    }
464}
465
466impl Builder {
467    pub fn new() -> Builder {
468        Builder::default()
469    }
470
471    // Modifier updates.
472
473    pub fn vis<V: Make<Visibility>>(self, vis: V) -> Self {
474        let vis = vis.make(&self);
475        Builder { vis, ..self }
476    }
477
478    pub fn pub_(self) -> Self {
479        let pub_token = Token![pub](self.span);
480        self.vis(Visibility::Public(VisPublic { pub_token }))
481    }
482
483    pub fn set_mutbl<M: Make<Mutability>>(self, mutbl: M) -> Self {
484        let mutbl = mutbl.make(&self);
485        Builder { mutbl, ..self }
486    }
487
488    pub fn mutbl(self) -> Self {
489        self.set_mutbl(Mutability::Mutable)
490    }
491
492    pub fn unsafety<U: Make<Unsafety>>(self, unsafety: U) -> Self {
493        let unsafety = unsafety.make(&self);
494        Builder { unsafety, ..self }
495    }
496
497    pub fn unsafe_(self) -> Self {
498        self.unsafety(Unsafety::Unsafe)
499    }
500
501    pub fn constness<C: Make<Constness>>(self, constness: C) -> Self {
502        let constness = constness.make(&self);
503        Builder { constness, ..self }
504    }
505
506    pub fn const_(self) -> Self {
507        self.constness(Constness::Const)
508    }
509
510    pub fn extern_<A: Make<Extern>>(self, ext: A) -> Self {
511        let ext = ext.make(&self);
512        Builder { ext, ..self }
513    }
514
515    pub fn span<S: Make<Span>>(self, span: S) -> Self {
516        let span = span.make(&self);
517        Builder { span, ..self }
518    }
519
520    pub fn generic_over(mut self, param: GenericParam) -> Self {
521        self.generics.params.push(param);
522        self
523    }
524
525    pub fn prepare_meta_namevalue(&self, mnv: MetaNameValue) -> PreparedMetaItem {
526        let mut tokens = TokenStream::new();
527        mnv.eq_token.to_tokens(&mut tokens);
528        mnv.lit.to_tokens(&mut tokens);
529
530        PreparedMetaItem {
531            path: mnv.path,
532            tokens,
533        }
534    }
535
536    pub fn prepare_meta_list(&self, list: MetaList) -> PreparedMetaItem {
537        let mut tokens = TokenStream::new();
538        let comma_token = Token![,](self.span);
539        let mut it = list.nested.into_iter();
540        if let Some(value) = it.next() {
541            value.to_tokens(&mut tokens);
542        }
543        for value in it {
544            comma_token.to_tokens(&mut tokens);
545            value.to_tokens(&mut tokens);
546        }
547        let tokens = proc_macro2::TokenTree::Group(proc_macro2::Group::new(
548            proc_macro2::Delimiter::Parenthesis,
549            tokens,
550        ))
551        .into();
552
553        PreparedMetaItem {
554            path: list.path,
555            tokens,
556        }
557    }
558
559    pub fn prepare_meta_path<I>(&self, path: I) -> PreparedMetaItem
560    where
561        I: Make<Path>,
562    {
563        let path = path.make(self);
564        PreparedMetaItem {
565            path,
566            tokens: TokenStream::new(),
567        }
568    }
569
570    pub fn prepare_meta(&self, kind: Meta) -> PreparedMetaItem {
571        match kind {
572            Meta::List(ml) => self.prepare_meta_list(ml),
573            Meta::NameValue(mnv) => self.prepare_meta_namevalue(mnv),
574            Meta::Path(path) => self.prepare_meta_path(path),
575        }
576    }
577
578    pub fn prepare_nested_meta_item<I>(&self, path: I, kind: Meta) -> PreparedMetaItem
579    where
580        I: Make<Path>,
581    {
582        let path = path.make(self);
583        PreparedMetaItem {
584            path,
585            tokens: kind.to_token_stream(),
586        }
587    }
588
589    pub fn prepared_attr(self, prepared: PreparedMetaItem) -> Self {
590        let attr = self
591            .clone()
592            .attribute(AttrStyle::Outer, prepared.path, prepared.tokens);
593        let mut attrs = self.attrs;
594        attrs.push(attr);
595        Builder { attrs, ..self }
596    }
597
598    pub fn str_attr<K, V>(self, key: K, value: V) -> Self
599    where
600        K: Make<Path>,
601        V: Make<Lit>,
602    {
603        let key = key.make(&self);
604        let value = value.make(&self);
605
606        let mnv = MetaNameValue {
607            path: key,
608            eq_token: Token![=](self.span),
609            lit: value,
610        };
611        let prepared = self.prepare_meta_namevalue(mnv);
612        self.prepared_attr(prepared)
613    }
614
615    pub fn single_attr<K>(self, key: K) -> Self
616    where
617        K: Make<PathSegment>,
618    {
619        let prepared = self.prepare_meta_path(vec![key]);
620        self.prepared_attr(prepared)
621    }
622
623    pub fn call_attr<K, V>(self, func: K, arguments: Vec<V>) -> Self
624    where
625        K: Make<PathSegment>,
626        V: Make<Ident>,
627    {
628        let func: Path = vec![func].make(&self);
629        let arguments = arguments
630            .into_iter()
631            .map(|x| NestedMeta::Meta(Meta::Path(vec![x.make(&self)].make(&self))))
632            .collect();
633
634        let metalist = MetaList {
635            path: func,
636            paren_token: token::Paren(self.span),
637            nested: arguments,
638        };
639        let prepared = self.prepare_meta_list(metalist);
640        self.prepared_attr(prepared)
641    }
642
643    // Path segments with parameters
644
645    pub fn path_segment_with_args<I, P>(self, identifier: I, args: P) -> PathSegment
646    where
647        I: Make<Ident>,
648        P: Make<PathArguments>,
649    {
650        let identifier = identifier.make(&self);
651        let args = args.make(&self);
652        PathSegment {
653            ident: identifier,
654            arguments: args,
655        }
656    }
657
658    pub fn parenthesized_args(self, tys: Vec<Box<Type>>) -> ParenthesizedGenericArguments {
659        ParenthesizedGenericArguments {
660            paren_token: token::Paren(self.span),
661            inputs: punct_box(tys),
662            output: ReturnType::Default,
663        }
664    }
665
666    pub fn angle_bracketed_args<A>(self, args: Vec<A>) -> AngleBracketedGenericArguments
667    where
668        A: Make<GenericArgument>,
669    {
670        let args = args.into_iter().map(|arg| arg.make(&self)).collect();
671        AngleBracketedGenericArguments {
672            colon2_token: Some(Token![::](self.span)), // Always include a colon2 for turbofish
673            lt_token: Token![<](self.span),
674            args,
675            gt_token: Token![>](self.span),
676        }
677    }
678
679    pub fn generic_arg<A>(self, arg: A) -> GenericArgument
680    where
681        A: Make<GenericArgument>,
682    {
683        arg.make(&self)
684    }
685
686    // Simple nodes
687
688    pub fn ident<I>(self, name: I) -> Ident
689    where
690        I: Make<Ident>,
691    {
692        name.make(&self)
693    }
694
695    pub fn path_segment<S>(self, seg: S) -> PathSegment
696    where
697        S: Make<PathSegment>,
698    {
699        seg.make(&self)
700    }
701
702    pub fn path<Pa>(self, path: Pa) -> Path
703    where
704        Pa: Make<Path>,
705    {
706        path.make(&self)
707    }
708
709    pub fn use_tree<Pa>(self, prefix: Pa, mut tree: UseTree) -> UseTree
710    where
711        Pa: Make<Path>,
712    {
713        let path: Path = prefix.make(&self);
714        for seg in path.segments {
715            tree = UseTree::Path(UsePath {
716                ident: seg.ident,
717                colon2_token: Token![::](self.span),
718                tree: Box::new(tree),
719            });
720        }
721        tree
722    }
723
724    pub fn abs_path<Pa>(self, path: Pa) -> Path
725    where
726        Pa: Make<Path>,
727    {
728        let mut path = path.make(&self);
729        path.leading_colon = Some(Token![::](self.span));
730        path
731    }
732
733    // Exprs
734    // These are sorted in the same order as the corresponding ExprKind variants, with additional
735    // variant-specific details following each variant.
736
737    pub fn array_expr(self, args: Vec<Box<Expr>>) -> Box<Expr> {
738        let args = args.into_iter().map(|a| *a).collect();
739        Box::new(Expr::Array(ExprArray {
740            attrs: self.attrs,
741            bracket_token: token::Bracket(self.span),
742            elems: args,
743        }))
744    }
745
746    pub fn call_expr(self, func: Box<Expr>, args: Vec<Box<Expr>>) -> Box<Expr> {
747        let args = args.into_iter().map(|a| *a).collect();
748        Box::new(parenthesize_if_necessary(Expr::Call(ExprCall {
749            attrs: self.attrs,
750            paren_token: token::Paren(self.span),
751            func,
752            args,
753        })))
754    }
755
756    pub fn method_call_expr<S>(self, expr: Box<Expr>, seg: S, args: Vec<Box<Expr>>) -> Box<Expr>
757    where
758        S: Make<PathSegment>,
759    {
760        let seg = seg.make(&self);
761        let args = args
762            .into_iter()
763            .map(|arg| *arg)
764            .map(|arg| arg.make(&self))
765            .collect();
766
767        // Convert ::<> if present in seg
768        fn generic_arg_to_method_generic_arg(a: GenericArgument) -> GenericMethodArgument {
769            match a {
770                GenericArgument::Type(t) => GenericMethodArgument::Type(t),
771                GenericArgument::Const(c) => GenericMethodArgument::Const(c),
772                _ => panic!(
773                    "non-type-or-const generic argument found in method arguments: {:?}",
774                    a
775                ),
776            }
777        }
778        let turbofish = match seg.arguments {
779            PathArguments::None => None,
780            PathArguments::AngleBracketed(ab) => Some(MethodTurbofish {
781                colon2_token: ab.colon2_token.unwrap_or_default(),
782                lt_token: ab.lt_token,
783                args: ab
784                    .args
785                    .into_iter()
786                    .map(generic_arg_to_method_generic_arg)
787                    .collect(),
788                gt_token: ab.gt_token,
789            }),
790            PathArguments::Parenthesized(_) => {
791                panic!("Found parenthesized arguments on path segment for method call")
792            }
793        };
794
795        Box::new(parenthesize_if_necessary(Expr::MethodCall(
796            ExprMethodCall {
797                attrs: self.attrs,
798                dot_token: Token![.](self.span),
799                paren_token: token::Paren(self.span),
800                turbofish,
801                receiver: expr,
802                method: seg.ident,
803                args,
804            },
805        )))
806    }
807
808    pub fn tuple_expr(self, exprs: Vec<Box<Expr>>) -> Box<Expr> {
809        Box::new(Expr::Tuple(ExprTuple {
810            attrs: self.attrs,
811            paren_token: token::Paren(self.span),
812            elems: punct_box(exprs),
813        }))
814    }
815
816    pub fn binary_expr(self, op: BinOp, mut lhs: Box<Expr>, rhs: Box<Expr>) -> Box<Expr> {
817        match op {
818            BinOp::Lt(_) | BinOp::Shl(_) if has_rightmost_cast(&lhs) => lhs = mk().paren_expr(lhs),
819            _ => {}
820        }
821
822        Box::new(parenthesize_if_necessary(Expr::Binary(ExprBinary {
823            attrs: self.attrs,
824            left: lhs,
825            op,
826            right: rhs,
827        })))
828    }
829
830    pub fn unary_expr<O>(self, op: O, a: Box<Expr>) -> Box<Expr>
831    where
832        O: Make<UnOp>,
833    {
834        let op = op.make(&self);
835        // FIXME: set span for op
836        Box::new(parenthesize_if_necessary(Expr::Unary(ExprUnary {
837            attrs: self.attrs,
838            op,
839            expr: a,
840        })))
841    }
842
843    pub fn lit_expr<L>(self, lit: L) -> Box<Expr>
844    where
845        L: Make<Lit>,
846    {
847        let mut lit = lit.make(&self);
848        lit.set_span(self.span);
849        Box::new(Expr::Lit(ExprLit {
850            attrs: self.attrs,
851            lit,
852        }))
853    }
854
855    pub fn cast_expr(self, e: Box<Expr>, t: Box<Type>) -> Box<Expr> {
856        Box::new(parenthesize_if_necessary(Expr::Cast(ExprCast {
857            attrs: self.attrs,
858            as_token: Token![as](self.span),
859            expr: e,
860            ty: t,
861        })))
862    }
863
864    pub fn type_expr(self, e: Box<Expr>, t: Box<Type>) -> Box<Expr> {
865        Box::new(Expr::Type(ExprType {
866            attrs: self.attrs,
867            colon_token: Token![:](self.span),
868            expr: e,
869            ty: t,
870        }))
871    }
872
873    pub fn unsafe_block_expr(self, unsafe_blk: ExprUnsafe) -> Box<Expr> {
874        Box::new(Expr::Unsafe(unsafe_blk))
875    }
876
877    pub fn block_expr(self, block: Block) -> Box<Expr> {
878        Box::new(Expr::Block(ExprBlock {
879            attrs: self.attrs,
880            block,
881            label: None,
882        }))
883    }
884
885    pub fn labelled_block_expr<L>(self, block: Block, lbl: L) -> Box<Expr>
886    where
887        L: Make<Label>,
888    {
889        let lbl = lbl.make(&self);
890        Box::new(Expr::Block(ExprBlock {
891            attrs: self.attrs,
892            block,
893            label: Some(lbl),
894        }))
895    }
896
897    pub fn assign_expr(self, lhs: Box<Expr>, rhs: Box<Expr>) -> Box<Expr> {
898        Box::new(Expr::Assign(ExprAssign {
899            attrs: self.attrs,
900            eq_token: Token![=](self.span),
901            left: lhs,
902            right: rhs,
903        }))
904    }
905
906    pub fn assign_op_expr(self, op: BinOp, lhs: Box<Expr>, rhs: Box<Expr>) -> Box<Expr> {
907        Box::new(Expr::AssignOp(ExprAssignOp {
908            attrs: self.attrs,
909            op,
910            left: lhs,
911            right: rhs,
912        }))
913    }
914
915    pub fn index_expr(self, lhs: Box<Expr>, rhs: Box<Expr>) -> Box<Expr> {
916        Box::new(parenthesize_if_necessary(Expr::Index(ExprIndex {
917            attrs: self.attrs,
918            bracket_token: token::Bracket(self.span),
919            expr: lhs,
920            index: rhs,
921        })))
922    }
923
924    pub fn abs_path_expr<Pa>(self, path: Pa) -> Box<Expr>
925    where
926        Pa: Make<Path>,
927    {
928        let path = mk().abs_path(path);
929        self.path_expr(path)
930    }
931
932    pub fn path_expr<Pa>(self, path: Pa) -> Box<Expr>
933    where
934        Pa: Make<Path>,
935    {
936        self.qpath_expr(None, path)
937    }
938
939    pub fn qpath_expr<Pa>(self, qself: Option<QSelf>, path: Pa) -> Box<Expr>
940    where
941        Pa: Make<Path>,
942    {
943        let path = path.make(&self);
944        Box::new(Expr::Path(ExprPath {
945            attrs: self.attrs,
946            qself,
947            path,
948        }))
949    }
950
951    /// An array literal constructed from one repeated element.
952    /// `[expr; n]`
953    pub fn repeat_expr(self, expr: Box<Expr>, n: Box<Expr>) -> Box<Expr> {
954        Box::new(Expr::Repeat(ExprRepeat {
955            attrs: self.attrs,
956            bracket_token: token::Bracket(self.span),
957            semi_token: Token![;](self.span),
958            expr,
959            len: n,
960        }))
961    }
962
963    pub fn paren_expr(self, e: Box<Expr>) -> Box<Expr> {
964        Box::new(Expr::Paren(ExprParen {
965            attrs: self.attrs,
966            paren_token: token::Paren(self.span),
967            expr: e,
968        }))
969    }
970
971    // Special case of path_expr
972    pub fn ident_expr<I>(self, name: I) -> Box<Expr>
973    where
974        I: Make<Ident>,
975    {
976        self.path_expr(vec![name])
977    }
978
979    pub fn addr_of_expr(self, e: Box<Expr>) -> Box<Expr> {
980        Box::new(parenthesize_if_necessary(Expr::Reference(ExprReference {
981            attrs: self.attrs,
982            and_token: Token![&](self.span),
983            raw: Default::default(),
984            mutability: self.mutbl.to_token(),
985            expr: e,
986        })))
987    }
988
989    pub fn mac_expr(self, mac: Macro) -> Box<Expr> {
990        Box::new(Expr::Macro(ExprMacro {
991            attrs: self.attrs,
992            mac,
993        }))
994    }
995
996    pub fn struct_expr<Pa>(self, path: Pa, fields: Vec<FieldValue>) -> Box<Expr>
997    where
998        Pa: Make<Path>,
999    {
1000        let path = path.make(&self);
1001        Box::new(Expr::Struct(ExprStruct {
1002            attrs: self.attrs,
1003            brace_token: token::Brace(self.span),
1004            dot2_token: None,
1005            path,
1006            fields: punct(fields),
1007            rest: None,
1008        }))
1009    }
1010
1011    // struct_expr, but with optional base expression
1012    pub fn struct_expr_base<Pa>(
1013        self,
1014        path: Pa,
1015        fields: Vec<FieldValue>,
1016        base: Option<Box<Expr>>,
1017    ) -> Box<Expr>
1018    where
1019        Pa: Make<Path>,
1020    {
1021        let path = path.make(&self);
1022        Box::new(Expr::Struct(ExprStruct {
1023            attrs: self.attrs,
1024            brace_token: token::Brace(self.span),
1025            dot2_token: Some(Token![..](self.span)),
1026            path,
1027            fields: punct(fields),
1028            rest: base,
1029        }))
1030    }
1031
1032    pub fn field_expr<F>(self, val: Box<Expr>, field: F) -> Box<Expr>
1033    where
1034        F: Make<Ident>,
1035    {
1036        let field = field.make(&self);
1037        Box::new(parenthesize_if_necessary(Expr::Field(ExprField {
1038            attrs: self.attrs,
1039            dot_token: Token![.](self.span),
1040            base: val,
1041            member: Member::Named(field),
1042        })))
1043    }
1044
1045    pub fn anon_field_expr(self, val: Box<Expr>, field: u32) -> Box<Expr> {
1046        Box::new(parenthesize_if_necessary(Expr::Field(ExprField {
1047            attrs: self.attrs,
1048            dot_token: Token![.](self.span),
1049            base: val,
1050            member: Member::Unnamed(Index {
1051                index: field,
1052                span: self.span,
1053            }),
1054        })))
1055    }
1056
1057    pub fn field<I>(self, ident: I, expr: Box<Expr>) -> FieldValue
1058    where
1059        I: Make<Ident>,
1060    {
1061        let ident = ident.make(&self);
1062        FieldValue {
1063            member: Member::Named(ident),
1064            expr: *expr,
1065            colon_token: Some(Token![:](self.span)),
1066            attrs: self.attrs,
1067        }
1068    }
1069
1070    pub fn match_expr(self, cond: Box<Expr>, arms: Vec<Arm>) -> Box<Expr> {
1071        let arms = arms.into_iter().collect();
1072        Box::new(Expr::Match(ExprMatch {
1073            attrs: self.attrs,
1074            match_token: Token![match](self.span),
1075            brace_token: token::Brace(self.span),
1076            expr: cond,
1077            arms,
1078        }))
1079    }
1080
1081    pub fn arm(self, pat: Pat, guard: Option<Box<Expr>>, body: Box<Expr>) -> Arm {
1082        let guard = guard.map(|g| (Token![if](self.span), g));
1083        Arm {
1084            attrs: self.attrs,
1085            pat,
1086            guard,
1087            body,
1088            fat_arrow_token: Token![=>](self.span),
1089            comma: Some(Token![,](self.span)),
1090        }
1091    }
1092
1093    // Literals
1094
1095    pub fn int_lit(self, i: u128, ty: &str) -> Lit {
1096        Lit::Int(LitInt::new(&format!("{}{}", i, ty), self.span))
1097    }
1098
1099    pub fn int_unsuffixed_lit(self, i: u128) -> Lit {
1100        Lit::Int(LitInt::new(&format!("{}", i), self.span))
1101    }
1102
1103    pub fn float_lit(self, s: &str, ty: &str) -> Lit {
1104        Lit::Float(LitFloat::new(&format!("{}{}", s, ty), self.span))
1105    }
1106
1107    pub fn float_unsuffixed_lit(self, s: &str) -> Lit {
1108        Lit::Float(LitFloat::new(s, self.span))
1109    }
1110
1111    pub fn bool_lit(self, b: bool) -> Lit {
1112        Lit::Bool(LitBool {
1113            value: b,
1114            span: self.span,
1115        })
1116    }
1117
1118    pub fn ifte_expr(
1119        self,
1120        cond: Box<Expr>,
1121        then_branch: Block,
1122        else_branch: Option<Box<Expr>>,
1123    ) -> Box<Expr> {
1124        let else_branch = else_branch.map(|e| {
1125            // The else branch in libsyntax must be one of these three cases,
1126            // otherwise we have to manually add the block around the else expression
1127            (
1128                Token![else](self.span),
1129                match &*e {
1130                    Expr::If(..)
1131                    | Expr::Block(ExprBlock {
1132                        attrs: _,
1133                        label: None,
1134                        block: _,
1135                    }) => e,
1136                    _ => mk().block_expr(mk().block(vec![mk().expr_stmt(e)])),
1137                },
1138            )
1139        });
1140
1141        Box::new(Expr::If(ExprIf {
1142            attrs: self.attrs,
1143            if_token: Token![if](self.span),
1144            cond,
1145            then_branch,
1146            else_branch,
1147        }))
1148    }
1149
1150    pub fn while_expr<I>(self, cond: Box<Expr>, body: Block, label: Option<I>) -> Box<Expr>
1151    where
1152        I: Make<Ident>,
1153    {
1154        let label = label.map(|l| Label {
1155            name: Lifetime {
1156                ident: l.make(&self),
1157                apostrophe: self.span,
1158            },
1159            colon_token: Token![:](self.span),
1160        });
1161
1162        Box::new(Expr::While(ExprWhile {
1163            attrs: self.attrs,
1164            while_token: Token![while](self.span),
1165            cond,
1166            body,
1167            label,
1168        }))
1169    }
1170
1171    pub fn loop_expr<I>(self, body: Block, label: Option<I>) -> Box<Expr>
1172    where
1173        I: Make<Ident>,
1174    {
1175        let label = label.map(|l| Label {
1176            name: Lifetime {
1177                ident: l.make(&self),
1178                apostrophe: self.span,
1179            },
1180            colon_token: Token![:](self.span),
1181        });
1182
1183        Box::new(Expr::Loop(ExprLoop {
1184            attrs: self.attrs,
1185            loop_token: Token![loop](self.span),
1186            body,
1187            label,
1188        }))
1189    }
1190
1191    pub fn for_expr<I>(self, pat: Pat, expr: Box<Expr>, body: Block, label: Option<I>) -> Box<Expr>
1192    where
1193        I: Make<Ident>,
1194    {
1195        let label = label.map(|l| Label {
1196            name: Lifetime {
1197                ident: l.make(&self),
1198                apostrophe: self.span,
1199            },
1200            colon_token: Token![:](self.span),
1201        });
1202
1203        Box::new(Expr::ForLoop(ExprForLoop {
1204            attrs: self.attrs,
1205            for_token: Token![for](self.span),
1206            in_token: Token![in](self.span),
1207            pat,
1208            expr,
1209            body,
1210            label,
1211        }))
1212    }
1213
1214    // Patterns
1215
1216    pub fn ident_pat<I>(self, name: I) -> Pat
1217    where
1218        I: Make<Ident>,
1219    {
1220        let name = name.make(&self);
1221        Pat::Ident(PatIdent {
1222            attrs: self.attrs,
1223            mutability: self.mutbl.to_token(),
1224            by_ref: None,
1225            ident: name,
1226            subpat: None,
1227        })
1228    }
1229
1230    pub fn tuple_pat(self, pats: Vec<Pat>) -> Pat {
1231        Pat::Tuple(PatTuple {
1232            attrs: self.attrs,
1233            paren_token: token::Paren(self.span),
1234            elems: punct(pats),
1235        })
1236    }
1237
1238    pub fn qpath_pat<Pa>(self, qself: Option<QSelf>, path: Pa) -> Box<Pat>
1239    where
1240        Pa: Make<Path>,
1241    {
1242        let path = path.make(&self);
1243        Box::new(Pat::Path(PatPath {
1244            attrs: self.attrs,
1245            qself,
1246            path,
1247        }))
1248    }
1249
1250    pub fn wild_pat(self) -> Pat {
1251        Pat::Wild(PatWild {
1252            attrs: self.attrs,
1253            underscore_token: Token![_](self.span),
1254        })
1255    }
1256
1257    pub fn lit_pat(self, lit: Box<Expr>) -> Pat {
1258        Pat::Lit(PatLit {
1259            attrs: self.attrs,
1260            expr: lit,
1261        })
1262    }
1263
1264    pub fn mac_pat(self, mac: Macro) -> Pat {
1265        Pat::Macro(PatMacro {
1266            attrs: self.attrs,
1267            mac,
1268        })
1269    }
1270
1271    pub fn ident_ref_pat<I>(self, name: I) -> Pat
1272    where
1273        I: Make<Ident>,
1274    {
1275        let name = name.make(&self);
1276        Pat::Ident(PatIdent {
1277            attrs: self.attrs,
1278            by_ref: Some(Token![ref](self.span)),
1279            mutability: self.mutbl.to_token(),
1280            ident: name,
1281            subpat: None,
1282        })
1283    }
1284
1285    pub fn or_pat(self, pats: Vec<Pat>) -> Pat {
1286        Pat::Or(PatOr {
1287            attrs: self.attrs,
1288            leading_vert: None, // Untested
1289            cases: punct(pats),
1290        })
1291    }
1292
1293    // Types
1294
1295    pub fn barefn_ty(self, decl: BareFnTyParts) -> Box<Type> {
1296        let (inputs, variadic, output) = decl;
1297        let abi = self.get_abi_opt();
1298
1299        let barefn = TypeBareFn {
1300            fn_token: Token![fn](self.span),
1301            paren_token: token::Paren(self.span),
1302            unsafety: self.unsafety.to_token(),
1303            abi,
1304            inputs: punct(inputs),
1305            output,
1306            variadic,
1307            lifetimes: None,
1308        };
1309
1310        Box::new(Type::BareFn(barefn))
1311    }
1312
1313    pub fn array_ty(self, ty: Box<Type>, len: Box<Expr>) -> Box<Type> {
1314        Box::new(Type::Array(TypeArray {
1315            bracket_token: token::Bracket(self.span),
1316            semi_token: Token![;](self.span),
1317            elem: ty,
1318            len: *len,
1319        }))
1320    }
1321
1322    pub fn slice_ty(self, ty: Box<Type>) -> Box<Type> {
1323        Box::new(Type::Slice(TypeSlice {
1324            elem: ty,
1325            bracket_token: token::Bracket(self.span),
1326        }))
1327    }
1328
1329    pub fn ptr_ty(self, ty: Box<Type>) -> Box<Type> {
1330        let const_token = if self.mutbl.to_token().is_none() {
1331            Some(Token![const](self.span))
1332        } else {
1333            None
1334        };
1335        Box::new(Type::Ptr(TypePtr {
1336            elem: ty,
1337            mutability: self.mutbl.to_token(),
1338            const_token,
1339            star_token: Token![*](self.span),
1340        }))
1341    }
1342
1343    pub fn ref_ty(self, ty: Box<Type>) -> Box<Type> {
1344        Box::new(Type::Reference(TypeReference {
1345            lifetime: None,
1346            elem: ty,
1347            mutability: self.mutbl.to_token(),
1348            and_token: Token![&](self.span),
1349        }))
1350    }
1351
1352    pub fn ref_lt_ty<L>(self, lt: L, ty: Box<Type>) -> Box<Type>
1353    where
1354        L: Make<Lifetime>,
1355    {
1356        let lt = lt.make(&self);
1357        Box::new(Type::Reference(TypeReference {
1358            and_token: Token![&](self.span),
1359            lifetime: Some(lt),
1360            mutability: self.mutbl.to_token(),
1361            elem: ty,
1362        }))
1363    }
1364
1365    pub fn never_ty(self) -> Box<Type> {
1366        Box::new(Type::Never(TypeNever {
1367            bang_token: Token![!](self.span),
1368        }))
1369    }
1370
1371    pub fn tuple_ty(self, elem_tys: Vec<Box<Type>>) -> Box<Type> {
1372        let elem_tys = elem_tys.into_iter().map(|ty| *ty).collect();
1373        Box::new(Type::Tuple(TypeTuple {
1374            paren_token: token::Paren(self.span),
1375            elems: elem_tys,
1376        }))
1377    }
1378
1379    pub fn path_ty<Pa>(self, path: Pa) -> Box<Type>
1380    where
1381        Pa: Make<Path>,
1382    {
1383        self.qpath_ty(None, path)
1384    }
1385
1386    pub fn qpath_ty<Pa>(self, qself: Option<QSelf>, path: Pa) -> Box<Type>
1387    where
1388        Pa: Make<Path>,
1389    {
1390        let path = path.make(&self);
1391        Box::new(Type::Path(TypePath { qself, path }))
1392    }
1393
1394    pub fn ident_ty<I>(self, name: I) -> Box<Type>
1395    where
1396        I: Make<Ident>,
1397    {
1398        self.path_ty(vec![name])
1399    }
1400
1401    pub fn infer_ty(self) -> Box<Type> {
1402        Box::new(Type::Infer(TypeInfer {
1403            underscore_token: Token![_](self.span),
1404        }))
1405    }
1406
1407    pub fn mac_ty(self, mac: Macro) -> Box<Type> {
1408        Box::new(Type::Macro(TypeMacro { mac }))
1409    }
1410
1411    pub fn cvar_args_ty(self) -> Box<Type> {
1412        let dot = TokenTree::Punct(proc_macro2::Punct::new('.', proc_macro2::Spacing::Joint));
1413        let dots = vec![dot.clone(), dot.clone(), dot];
1414        Box::new(Type::Verbatim(TokenStream::from_iter(dots.into_iter())))
1415    }
1416
1417    // Stmts
1418
1419    pub fn local_stmt(self, local: Box<Local>) -> Stmt {
1420        Stmt::Local(*local)
1421    }
1422
1423    pub fn expr_stmt(self, expr: Box<Expr>) -> Stmt {
1424        Stmt::Expr(*expr)
1425    }
1426
1427    pub fn semi_stmt(self, expr: Box<Expr>) -> Stmt {
1428        Stmt::Semi(*expr, Token![;](self.span))
1429    }
1430
1431    pub fn item_stmt(self, item: Box<Item>) -> Stmt {
1432        Stmt::Item(*item)
1433    }
1434
1435    pub fn mac_stmt(self, mac: Macro) -> Stmt {
1436        self.semi_stmt(mk().mac_expr(mac))
1437    }
1438
1439    // Items
1440
1441    pub fn static_item<I>(self, name: I, ty: Box<Type>, init: Box<Expr>) -> Box<Item>
1442    where
1443        I: Make<Ident>,
1444    {
1445        let name = name.make(&self);
1446        Box::new(Item::Static(ItemStatic {
1447            attrs: self.attrs,
1448            vis: self.vis,
1449            mutability: self.mutbl.to_token(),
1450            ident: name,
1451            static_token: Token![static](self.span),
1452            colon_token: Token![:](self.span),
1453            eq_token: Token![=](self.span),
1454            semi_token: Token![;](self.span),
1455            expr: init,
1456            ty,
1457        }))
1458    }
1459
1460    pub fn const_item<I>(self, name: I, ty: Box<Type>, init: Box<Expr>) -> Box<Item>
1461    where
1462        I: Make<Ident>,
1463    {
1464        let name = name.make(&self);
1465        Box::new(Item::Const(ItemConst {
1466            attrs: self.attrs,
1467            vis: self.vis,
1468            const_token: Token![const](self.span),
1469            colon_token: Token![:](self.span),
1470            eq_token: Token![=](self.span),
1471            semi_token: Token![;](self.span),
1472            ident: name,
1473            ty,
1474            expr: init,
1475        }))
1476    }
1477
1478    pub fn fn_item<S>(self, sig: S, block: Block) -> Box<Item>
1479    where
1480        S: Make<Signature>,
1481    {
1482        let sig = sig.make(&self);
1483        Box::new(Item::Fn(ItemFn {
1484            attrs: self.attrs,
1485            vis: self.vis,
1486            sig,
1487            block: Box::new(block),
1488        }))
1489    }
1490
1491    pub fn variadic_arg(self, variadic_attrs: Vec<Attribute>) -> Variadic {
1492        Variadic {
1493            dots: Token![...](self.span),
1494            attrs: variadic_attrs,
1495        }
1496    }
1497
1498    pub fn fn_decl<I>(
1499        self,
1500        name: I,
1501        inputs: Vec<FnArg>,
1502        variadic: Option<Variadic>,
1503        output: ReturnType,
1504    ) -> Box<FnDecl>
1505    where
1506        I: Make<Ident>,
1507    {
1508        let name = name.make(&self);
1509        Box::new((name, inputs, variadic, output))
1510    }
1511
1512    pub fn struct_item<I>(self, name: I, fields: Vec<Field>, is_tuple: bool) -> Box<Item>
1513    where
1514        I: Make<Ident>,
1515    {
1516        let name = name.make(&self);
1517        let fields = if is_tuple {
1518            Fields::Unnamed(FieldsUnnamed {
1519                paren_token: token::Paren(self.span),
1520                unnamed: fields.into_iter().collect(),
1521            })
1522        } else {
1523            Fields::Named(FieldsNamed {
1524                brace_token: token::Brace(self.span),
1525                named: fields.into_iter().collect(),
1526            })
1527        };
1528        Box::new(Item::Struct(ItemStruct {
1529            attrs: self.attrs,
1530            vis: self.vis,
1531            struct_token: Token![struct](self.span),
1532            semi_token: None,
1533            ident: name,
1534            generics: self.generics,
1535            fields,
1536        }))
1537    }
1538
1539    pub fn union_item<I>(self, name: I, fields: Vec<Field>) -> Box<Item>
1540    where
1541        I: Make<Ident>,
1542    {
1543        let name = name.make(&self);
1544        let fields = FieldsNamed {
1545            brace_token: token::Brace(self.span),
1546            named: punct(fields),
1547        };
1548        Box::new(Item::Union(ItemUnion {
1549            attrs: self.attrs,
1550            vis: self.vis,
1551            ident: name,
1552            fields,
1553            union_token: Token![union](self.span),
1554            generics: self.generics,
1555        }))
1556    }
1557
1558    pub fn enum_item<I>(self, name: I, fields: Vec<Variant>) -> Box<Item>
1559    where
1560        I: Make<Ident>,
1561    {
1562        let name = name.make(&self);
1563        Box::new(Item::Enum(ItemEnum {
1564            attrs: self.attrs,
1565            vis: self.vis,
1566            ident: name,
1567            enum_token: Token![enum](self.span),
1568            brace_token: token::Brace(self.span),
1569            variants: punct(fields),
1570            generics: self.generics,
1571        }))
1572    }
1573
1574    pub fn type_item<I>(self, name: I, ty: Box<Type>) -> Box<Item>
1575    where
1576        I: Make<Ident>,
1577    {
1578        let name = name.make(&self);
1579        Box::new(Item::Type(ItemType {
1580            attrs: self.attrs,
1581            vis: self.vis,
1582            ident: name,
1583            generics: self.generics,
1584            type_token: Token![type](self.span),
1585            eq_token: Token![=](self.span),
1586            semi_token: Token![;](self.span),
1587            ty,
1588        }))
1589    }
1590
1591    pub fn mod_item<I>(self, name: I, items: Option<Vec<Item>>) -> Box<Item>
1592    where
1593        I: Make<Ident>,
1594    {
1595        let items = items.map(|i| (token::Brace(self.span), i));
1596        let name = name.make(&self);
1597        Box::new(Item::Mod(ItemMod {
1598            attrs: self.attrs,
1599            vis: self.vis,
1600            ident: name,
1601            mod_token: Token![mod](self.span),
1602            semi: None,
1603            content: items,
1604        }))
1605    }
1606
1607    pub fn mod_(self, items: Vec<Box<Item>>) -> Vec<Item> {
1608        items.into_iter().map(|i| *i).collect()
1609    }
1610
1611    pub fn mac_item(self, mac: Macro) -> Box<Item> {
1612        Box::new(Item::Macro(ItemMacro {
1613            attrs: self.attrs,
1614            semi_token: Some(Token![;](self.span)), // Untested
1615            ident: None,
1616            mac,
1617        }))
1618    }
1619
1620    pub fn variant<I>(self, name: I, fields: Fields) -> Variant
1621    where
1622        I: Make<Ident>,
1623    {
1624        let name = name.make(&self);
1625        Variant {
1626            ident: name,
1627            attrs: self.attrs,
1628            fields,
1629            discriminant: None,
1630        }
1631    }
1632
1633    pub fn unit_variant<I>(self, name: I, disc: Option<Box<Expr>>) -> Variant
1634    where
1635        I: Make<Ident>,
1636    {
1637        let name = name.make(&self);
1638        Variant {
1639            ident: name,
1640            fields: Fields::Unit,
1641            discriminant: disc.map(|e| (Token![=](self.span), *e)),
1642            attrs: self.attrs,
1643        }
1644    }
1645
1646    pub fn impl_item(self, ty: Box<Type>, items: Vec<ImplItem>) -> Box<Item> {
1647        Box::new(Item::Impl(ItemImpl {
1648            attrs: self.attrs,
1649            unsafety: self.unsafety.to_token(),
1650            defaultness: Defaultness::Final.to_token(),
1651            generics: self.generics,
1652            trait_: None, // not a trait implementation, no ! on said trait name
1653            self_ty: ty,
1654            impl_token: Token![impl](self.span),
1655            brace_token: token::Brace(self.span),
1656            items,
1657        }))
1658    }
1659
1660    pub fn extern_crate_item<I>(self, name: I, rename: Option<I>) -> Box<Item>
1661    where
1662        I: Make<Ident>,
1663    {
1664        let name = name.make(&self);
1665        let rename = rename.map(|n| (Token![as](self.span), n.make(&self)));
1666        Box::new(Item::ExternCrate(ItemExternCrate {
1667            attrs: self.attrs,
1668            vis: self.vis,
1669            crate_token: Token![crate](self.span),
1670            extern_token: Token![extern](self.span),
1671            semi_token: Token![;](self.span),
1672            ident: name,
1673            rename,
1674        }))
1675    }
1676
1677    pub fn use_item(self, tree: UseTree) -> Box<Item> {
1678        Box::new(Item::Use(ItemUse {
1679            attrs: self.attrs,
1680            vis: self.vis,
1681            use_token: Token![use](self.span),
1682            leading_colon: None,
1683            semi_token: Token![;](self.span),
1684            tree,
1685        }))
1686    }
1687
1688    // `use <path>;` item
1689    pub fn use_simple_item<Pa, I>(self, path: Pa, rename: Option<I>) -> Box<Item>
1690    where
1691        Pa: Make<Path>,
1692        I: Make<Ident>,
1693    {
1694        let path = path.make(&self);
1695        let rename = rename.map(|n| n.make(&self));
1696
1697        fn split_path(mut p: Path) -> (Path, Option<Ident>) {
1698            if let Some(punct) = p.segments.pop() {
1699                (p, Some(punct.into_value().ident))
1700            } else {
1701                (p, None)
1702            }
1703        }
1704        let leading_colon = path.leading_colon;
1705        let (prefix, ident) = split_path(path);
1706        let ident = ident.expect("use_simple_item called with path `::`");
1707        let tree = if let Some(rename) = rename {
1708            use_tree_with_prefix(
1709                prefix,
1710                UseTree::Rename(UseRename {
1711                    ident,
1712                    as_token: Token![as](self.span),
1713                    rename,
1714                }),
1715            )
1716        } else {
1717            use_tree_with_prefix(prefix, UseTree::Name(UseName { ident }))
1718        };
1719        Box::new(Item::Use(ItemUse {
1720            attrs: self.attrs,
1721            vis: self.vis,
1722            use_token: Token![use](self.span),
1723            leading_colon,
1724            semi_token: Token![;](self.span),
1725            tree,
1726        }))
1727    }
1728
1729    pub fn use_multiple_item<Pa, I, It>(self, path: Pa, inner: It) -> Box<Item>
1730    where
1731        Pa: Make<Path>,
1732        I: Make<Ident>,
1733        It: Iterator<Item = I>,
1734    {
1735        let path = path.make(&self);
1736        let inner_trees = inner
1737            .map(|i| {
1738                UseTree::Name(UseName {
1739                    ident: i.make(&self),
1740                })
1741            })
1742            .collect();
1743        let leading_colon = path.leading_colon;
1744        let tree = use_tree_with_prefix(
1745            path,
1746            UseTree::Group(UseGroup {
1747                brace_token: token::Brace(self.span),
1748                items: inner_trees,
1749            }),
1750        );
1751        Box::new(Item::Use(ItemUse {
1752            attrs: self.attrs,
1753            vis: self.vis,
1754            use_token: Token![use](self.span),
1755            leading_colon,
1756            semi_token: Token![;](self.span),
1757            tree,
1758        }))
1759    }
1760
1761    pub fn use_glob_item<Pa>(self, path: Pa) -> Box<Item>
1762    where
1763        Pa: Make<Path>,
1764    {
1765        let path = path.make(&self);
1766        let leading_colon = path.leading_colon;
1767        let tree = use_tree_with_prefix(
1768            path,
1769            UseTree::Glob(UseGlob {
1770                star_token: Token![*](self.span),
1771            }),
1772        );
1773        Box::new(Item::Use(ItemUse {
1774            attrs: self.attrs,
1775            vis: self.vis,
1776            use_token: Token![use](self.span),
1777            leading_colon,
1778            semi_token: Token![;](self.span),
1779            tree,
1780        }))
1781    }
1782
1783    pub fn foreign_items(self, items: Vec<ForeignItem>) -> Box<Item> {
1784        let abi = self.get_abi();
1785
1786        Box::new(Item::ForeignMod(ItemForeignMod {
1787            attrs: self.attrs,
1788            brace_token: token::Brace(self.span),
1789            items,
1790            abi,
1791        }))
1792    }
1793
1794    pub fn get_abi(&self) -> Abi {
1795        Abi {
1796            extern_token: Token![extern](self.span),
1797            name: match self.ext {
1798                Extern::None | Extern::Implicit => None,
1799                Extern::Explicit(ref s) => Some(LitStr::new(s, self.span)),
1800            },
1801        }
1802    }
1803
1804    pub fn get_abi_opt(&self) -> Option<Abi> {
1805        let name: Option<LitStr> = match self.ext {
1806            Extern::None => return None,
1807            Extern::Implicit => None,
1808            Extern::Explicit(ref s) => Some(LitStr::new(s, self.span)),
1809        };
1810        Some(Abi {
1811            extern_token: Token![extern](self.span),
1812            name,
1813        })
1814    }
1815
1816    // Impl Items
1817
1818    pub fn mac_impl_item(self, mac: Macro) -> ImplItem {
1819        ImplItem::Macro(ImplItemMacro {
1820            attrs: self.attrs,
1821            semi_token: None,
1822            mac,
1823        })
1824    }
1825
1826    // Trait Items
1827
1828    pub fn mac_trait_item(self, mac: Macro) -> TraitItem {
1829        TraitItem::Macro(TraitItemMacro {
1830            attrs: self.attrs,
1831            semi_token: None,
1832            mac,
1833        })
1834    }
1835
1836    // Foreign Items
1837
1838    /// [`ForeignItem`] is large (472 bytes), so [`Box`] it.
1839    pub fn fn_foreign_item(self, decl: Box<FnDecl>) -> Box<ForeignItem> {
1840        let sig = Signature {
1841            constness: None,
1842            asyncness: None,
1843            generics: self.generics.clone(),
1844            ..decl.make(&self)
1845        };
1846        Box::new(ForeignItem::Fn(ForeignItemFn {
1847            attrs: self.attrs,
1848            vis: self.vis,
1849            sig,
1850            semi_token: Token![;](self.span),
1851        }))
1852    }
1853
1854    /// [`ForeignItem`] is large (472 bytes), so [`Box`] it.
1855    pub fn static_foreign_item<I>(self, name: I, ty: Box<Type>) -> Box<ForeignItem>
1856    where
1857        I: Make<Ident>,
1858    {
1859        let name = name.make(&self);
1860        Box::new(ForeignItem::Static(ForeignItemStatic {
1861            attrs: self.attrs,
1862            vis: self.vis,
1863            mutability: self.mutbl.to_token(),
1864            ident: name,
1865            ty,
1866            static_token: Token![static](self.span),
1867            colon_token: Token![:](self.span),
1868            semi_token: Token![;](self.span),
1869        }))
1870    }
1871
1872    /// [`ForeignItem`] is large (472 bytes), so [`Box`] it.
1873    pub fn ty_foreign_item<I>(self, name: I) -> Box<ForeignItem>
1874    where
1875        I: Make<Ident>,
1876    {
1877        let name = name.make(&self);
1878        Box::new(ForeignItem::Type(ForeignItemType {
1879            attrs: self.attrs,
1880            vis: self.vis,
1881            ident: name,
1882            type_token: Token![type](self.span),
1883            semi_token: Token![;](self.span),
1884        }))
1885    }
1886
1887    pub fn mac_foreign_item(self, mac: Macro) -> ForeignItem {
1888        ForeignItem::Macro(ForeignItemMacro {
1889            attrs: self.attrs,
1890            mac,
1891            semi_token: None,
1892        })
1893    }
1894
1895    // struct fields
1896
1897    pub fn struct_field<I>(self, ident: I, ty: Box<Type>) -> Field
1898    where
1899        I: Make<Ident>,
1900    {
1901        let ident = ident.make(&self);
1902        Field {
1903            ident: Some(ident),
1904            vis: self.vis,
1905            attrs: self.attrs,
1906            ty: *ty,
1907            colon_token: Some(Token![:](self.span)),
1908        }
1909    }
1910
1911    pub fn enum_field(self, ty: Box<Type>) -> Field {
1912        Field {
1913            ident: None,
1914            vis: self.vis,
1915            ty: *ty,
1916            attrs: self.attrs,
1917            colon_token: None,
1918        }
1919    }
1920
1921    // Misc nodes
1922
1923    pub fn unsafe_block(self, stmts: Vec<Stmt>) -> ExprUnsafe {
1924        let blk = Block {
1925            stmts,
1926            brace_token: token::Brace(self.span),
1927        };
1928        ExprUnsafe {
1929            attrs: self.attrs,
1930            unsafe_token: Token![unsafe](self.span),
1931            block: blk,
1932        }
1933    }
1934
1935    pub fn block(self, stmts: Vec<Stmt>) -> Block {
1936        Block {
1937            stmts,
1938            brace_token: token::Brace(self.span),
1939        }
1940    }
1941
1942    pub fn label<L>(self, lbl: L) -> Label
1943    where
1944        L: Make<Label>,
1945    {
1946        lbl.make(&self)
1947    }
1948
1949    pub fn break_expr_value<L>(self, label: Option<L>, value: Option<Box<Expr>>) -> Box<Expr>
1950    where
1951        L: Make<Label>,
1952    {
1953        let label = label.map(|l| l.make(&self).name);
1954        Box::new(Expr::Break(ExprBreak {
1955            attrs: self.attrs,
1956            break_token: Token![break](self.span),
1957            label,
1958            expr: value,
1959        }))
1960    }
1961
1962    pub fn bare_arg<I>(self, ty: Box<Type>, name: Option<I>) -> BareFnArg
1963    where
1964        I: Make<Box<Ident>>,
1965    {
1966        let name = name.map(|n| (*n.make(&self), Token![:](self.span)));
1967        BareFnArg {
1968            attrs: Vec::new(),
1969            name,
1970            ty: *ty,
1971        }
1972    }
1973
1974    pub fn arg(self, ty: Box<Type>, pat: Pat) -> FnArg {
1975        FnArg::Typed(PatType {
1976            attrs: Vec::new(),
1977            ty,
1978            pat: Box::new(pat),
1979            colon_token: Token![:](self.span),
1980        })
1981    }
1982
1983    pub fn self_arg(self, kind: SelfKind) -> FnArg {
1984        let (reference, mutability) = match kind {
1985            SelfKind::Value(mutability) => (None, mutability),
1986            SelfKind::Region(lt, mutability) => {
1987                (Some((Token![&](self.span), Some(lt))), mutability)
1988            }
1989        };
1990        let attrs = Vec::new();
1991        FnArg::Receiver(Receiver {
1992            attrs,
1993            reference,
1994            mutability: mutability.to_token(),
1995            self_token: Token![self](self.span),
1996        })
1997    }
1998
1999    pub fn ty_param<I>(self, ident: I) -> GenericParam
2000    where
2001        I: Make<Ident>,
2002    {
2003        let ident = ident.make(&self);
2004        GenericParam::Type(TypeParam {
2005            attrs: self.attrs,
2006            ident,
2007            bounds: punct(vec![]),
2008            colon_token: None,
2009            eq_token: None,
2010            default: None,
2011        })
2012    }
2013
2014    pub fn ty<T>(self, kind: Type) -> Type {
2015        kind
2016    }
2017
2018    pub fn lt_param<L>(self, lifetime: L) -> GenericParam
2019    where
2020        L: Make<Lifetime>,
2021    {
2022        let lifetime = lifetime.make(&self);
2023        GenericParam::Lifetime(LifetimeDef {
2024            attrs: self.attrs,
2025            lifetime,
2026            colon_token: None,
2027            bounds: punct(vec![]),
2028        })
2029    }
2030
2031    pub fn lifetime<L: Make<Lifetime>>(self, lt: L) -> Lifetime {
2032        lt.make(&self)
2033    }
2034
2035    pub fn attribute<Pa, Ma>(self, style: AttrStyle, path: Pa, args: Ma) -> Attribute
2036    where
2037        Pa: Make<Path>,
2038        Ma: Make<TokenStream>,
2039    {
2040        let path = path.make(&self);
2041        let args = args.make(&self);
2042        Attribute {
2043            style,
2044            path,
2045            tokens: args,
2046            pound_token: Token![#](self.span),
2047            bracket_token: token::Bracket(self.span),
2048        }
2049    }
2050
2051    pub fn meta_item_attr(mut self, style: AttrStyle, meta_item: Meta) -> Self {
2052        let prepared = self.prepare_meta(meta_item);
2053        let attr = self
2054            .clone()
2055            .attribute(style, prepared.path, prepared.tokens);
2056        self.attrs.push(attr);
2057        self
2058    }
2059
2060    pub fn meta_path<Pa>(self, path: Pa) -> Meta
2061    where
2062        Pa: Make<Path>,
2063    {
2064        let path = path.make(&self);
2065        Meta::Path(path)
2066    }
2067
2068    pub fn meta_list<I, N>(self, path: I, args: N) -> Meta
2069    where
2070        I: Make<Path>,
2071        N: Make<Vec<NestedMeta>>,
2072    {
2073        let path = path.make(&self);
2074        let args = args.make(&self);
2075        Meta::List(MetaList {
2076            path,
2077            paren_token: token::Paren(self.span),
2078            nested: punct(args),
2079        })
2080    }
2081
2082    pub fn meta_namevalue<K, V>(self, key: K, value: V) -> Meta
2083    where
2084        K: Make<Path>,
2085        V: Make<Lit>,
2086    {
2087        let key = key.make(&self);
2088        let value = value.make(&self);
2089
2090        Meta::NameValue(MetaNameValue {
2091            path: key,
2092            eq_token: Token![=](self.span),
2093            lit: value,
2094        })
2095    }
2096
2097    pub fn nested_meta_item<K>(self, kind: K) -> NestedMeta
2098    where
2099        K: Make<NestedMeta>,
2100    {
2101        kind.make(&self)
2102    }
2103
2104    // Convert the current internal list of outer attributes
2105    // into a vector of inner attributes, e.g.:
2106    // `#[foo]` => `#![foo]`
2107    pub fn as_inner_attrs(self) -> Vec<Attribute> {
2108        self.attrs
2109            .into_iter()
2110            .map(|outer_attr| Attribute {
2111                style: AttrStyle::Inner(Default::default()),
2112                ..outer_attr
2113            })
2114            .collect::<Vec<Attribute>>()
2115    }
2116
2117    pub fn into_attrs(self) -> Vec<Attribute> {
2118        self.attrs
2119    }
2120
2121    pub fn empty_mac<Pa>(self, path: Pa, delim: MacroDelimiter) -> Macro
2122    where
2123        Pa: Make<Path>,
2124    {
2125        let path = path.make(&self);
2126        Macro {
2127            path,
2128            tokens: TokenStream::new(),
2129            bang_token: Token![!](self.span),
2130            delimiter: delim,
2131        }
2132    }
2133
2134    pub fn mac<Ts>(self, func: Path, arguments: Ts, delim: MacroDelimiter) -> Macro
2135    where
2136        Ts: Make<TokenStream>,
2137    {
2138        let tokens = arguments.make(&self);
2139        Macro {
2140            path: func,
2141            tokens,
2142            bang_token: Token![!](self.span),
2143            delimiter: delim,
2144        }
2145    }
2146
2147    /// Create a local variable
2148    pub fn local(self, pat: Pat, ty: Option<Box<Type>>, init: Option<Box<Expr>>) -> Local {
2149        let init = init.map(|x| (Default::default(), x));
2150        let pat = if let Some(ty) = ty {
2151            Pat::Type(PatType {
2152                attrs: vec![],
2153                pat: Box::new(pat),
2154                colon_token: Token![:](self.span),
2155                ty,
2156            })
2157        } else {
2158            pat
2159        };
2160        Local {
2161            attrs: self.attrs,
2162            let_token: Token![let](self.span),
2163            semi_token: Token![;](self.span),
2164            pat,
2165            init,
2166        }
2167    }
2168
2169    pub fn return_expr(self, val: Option<Box<Expr>>) -> Box<Expr> {
2170        Box::new(Expr::Return(ExprReturn {
2171            attrs: self.attrs,
2172            return_token: Token![return](self.span),
2173            expr: val,
2174        }))
2175    }
2176
2177    pub fn continue_expr<I>(self, label: Option<I>) -> Box<Expr>
2178    where
2179        I: Make<Ident>,
2180    {
2181        let label = label.map(|l| Lifetime {
2182            ident: l.make(&self),
2183            apostrophe: self.span,
2184        });
2185
2186        Box::new(Expr::Continue(ExprContinue {
2187            attrs: self.attrs,
2188            continue_token: Token![continue](self.span),
2189            label,
2190        }))
2191    }
2192
2193    pub fn break_expr<I>(self, label: Option<I>) -> Box<Expr>
2194    where
2195        I: Make<Ident>,
2196    {
2197        let label = label.map(|l| Lifetime {
2198            ident: l.make(&self),
2199            apostrophe: self.span,
2200        });
2201
2202        Box::new(Expr::Break(ExprBreak {
2203            attrs: self.attrs,
2204            break_token: Token![break](self.span),
2205            label,
2206            expr: None,
2207        }))
2208    }
2209
2210    pub fn closure_expr(
2211        self,
2212        capture: CaptureBy,
2213        mov: Movability,
2214        decl: FnDecl,
2215        body: Box<Expr>,
2216    ) -> Box<Expr> {
2217        let (_name, inputs, _variadic, output) = decl;
2218        let inputs = inputs
2219            .into_iter()
2220            .map(|e| match e {
2221                FnArg::Receiver(_s) => panic!("found 'self' in closure arguments"),
2222                FnArg::Typed(PatType { pat, .. }) => *pat,
2223            })
2224            .collect();
2225        let capture = match capture {
2226            CaptureBy::Ref => None,
2227            CaptureBy::Value => Some(Default::default()),
2228        };
2229        Box::new(Expr::Closure(ExprClosure {
2230            attrs: self.attrs,
2231            or1_token: Token![|](self.span),
2232            or2_token: Token![|](self.span),
2233            capture,
2234            asyncness: IsAsync::NotAsync.to_token(),
2235            movability: mov.to_token(),
2236            body,
2237            inputs,
2238            output,
2239        }))
2240    }
2241}
2242
2243pub fn mk() -> Builder {
2244    Builder::new()
2245}
2246
2247/// Detect a cast that would create a syntax error when it was the left
2248/// argument to a less-than operator. This is a work-around for an upstream
2249/// libsyntax bug.
2250fn has_rightmost_cast(expr: &Expr) -> bool {
2251    match expr {
2252        Expr::Cast(..) => true,
2253        Expr::Unary(ExprUnary {
2254            attrs: _,
2255            op: _,
2256            ref expr,
2257        }) => has_rightmost_cast(expr),
2258        Expr::Binary(ExprBinary {
2259            attrs: _,
2260            left: _,
2261            op: _,
2262            ref right,
2263        }) => has_rightmost_cast(right),
2264        _ => false,
2265    }
2266}
2267
2268fn expr_precedence(e: &Expr) -> u8 {
2269    match e {
2270        Expr::Path(_ep) => 18,
2271        Expr::MethodCall(_emc) => 17,
2272        Expr::Field(_ef) => 16,
2273        Expr::Call(_) | Expr::Index(_) => 15,
2274        Expr::Try(_et) => 14,
2275        Expr::Unary(_) | Expr::Reference(_) => 13,
2276        Expr::Cast(_ec) => 12,
2277        Expr::Binary(eb) => 2 + binop_precedence(&eb.op),
2278        Expr::Assign(_) | Expr::AssignOp(_) => 1,
2279        Expr::Return(_) | Expr::Closure(_) => 0,
2280        _ => 255,
2281    }
2282}
2283
2284/// See <https://doc.rust-lang.org/reference/expressions.html>
2285fn binop_precedence(b: &BinOp) -> u8 {
2286    match b {
2287        BinOp::Add(_) => 8,
2288        BinOp::Sub(_) => 8,
2289        BinOp::Mul(_) => 9,
2290        BinOp::Div(_) => 9,
2291        BinOp::Rem(_) => 9,
2292        BinOp::And(_) => 2,
2293        BinOp::Or(_) => 1,
2294        BinOp::BitXor(_) => 5,
2295        BinOp::BitAnd(_) => 6,
2296        BinOp::BitOr(_) => 4,
2297        BinOp::Shl(_) => 7,
2298        BinOp::Shr(_) => 7,
2299        BinOp::Eq(_) => 3,
2300        BinOp::Lt(_) => 3,
2301        BinOp::Le(_) => 3,
2302        BinOp::Ne(_) => 3,
2303        BinOp::Ge(_) => 3,
2304        BinOp::Gt(_) => 3,
2305        BinOp::AddEq(_) => 0,
2306        BinOp::SubEq(_) => 0,
2307        BinOp::MulEq(_) => 0,
2308        BinOp::DivEq(_) => 0,
2309        BinOp::RemEq(_) => 0,
2310        BinOp::BitXorEq(_) => 0,
2311        BinOp::BitAndEq(_) => 0,
2312        BinOp::BitOrEq(_) => 0,
2313        BinOp::ShlEq(_) => 0,
2314        BinOp::ShrEq(_) => 0,
2315    }
2316}
2317
2318/// Wrap an expression in parentheses
2319fn parenthesize_mut(e: &mut Box<Expr>) {
2320    let mut temp = mk().tuple_expr(Vec::new());
2321    std::mem::swap(e, &mut temp);
2322    *e = Box::new(Expr::Paren(ExprParen {
2323        attrs: vec![],
2324        paren_token: Default::default(),
2325        expr: temp,
2326    }))
2327}
2328
2329/// Wrap an expression's subexpressions in an explicit ExprParen if the
2330/// pretty-printed form of the expression would otherwise reparse differently
2331fn parenthesize_if_necessary(mut outer: Expr) -> Expr {
2332    // If outer operation has higher precedence, parenthesize inner operation
2333    let outer_precedence = expr_precedence(&outer);
2334    let parenthesize_if_gte = |inner: &mut Box<Expr>| {
2335        if expr_precedence(&*inner) <= outer_precedence {
2336            parenthesize_mut(inner);
2337        }
2338    };
2339    let parenthesize_if_gt = |inner: &mut Box<Expr>| {
2340        if expr_precedence(&*inner) < outer_precedence {
2341            parenthesize_mut(inner);
2342        }
2343    };
2344    match outer {
2345        Expr::Field(ref mut ef) => {
2346            if let Expr::Index(_) = *ef.base {
2347                /* we do not need to parenthesize the indexing in a[b].c */
2348            } else {
2349                /*if let Expr::Unary(_) = *ef.base {
2350                    parenthesize_mut(&mut ef.base);
2351                } else { */
2352                parenthesize_if_gt(&mut ef.base);
2353            }
2354        }
2355        Expr::MethodCall(ref mut emc) => {
2356            parenthesize_if_gt(&mut emc.receiver);
2357        }
2358        Expr::Call(ref mut ec) => {
2359            parenthesize_if_gt(&mut ec.func);
2360        }
2361        Expr::Cast(ref mut ec) => {
2362            if let Expr::If(_) = *ec.expr {
2363                parenthesize_mut(&mut ec.expr);
2364            } else {
2365                parenthesize_if_gt(&mut ec.expr);
2366            }
2367        }
2368        Expr::Unary(ref mut eu) => {
2369            parenthesize_if_gt(&mut eu.expr);
2370        }
2371        Expr::Reference(ref mut er) => {
2372            parenthesize_if_gt(&mut er.expr);
2373        }
2374        Expr::Binary(ref mut eb) => {
2375            parenthesize_if_gt(&mut eb.left);
2376            // Because binops associate right, parenthesize same-precedence RHS
2377            // (e.g. `5 - (6 - 7)`).
2378            parenthesize_if_gte(&mut eb.right);
2379        }
2380        Expr::Index(ref mut ei) => {
2381            parenthesize_if_gt(&mut ei.expr);
2382        }
2383        _ => (),
2384    };
2385    outer
2386}