Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  pat.rs   Sprache: unbekannt

 
use crate::attr::Attribute;
use crate::expr::Member;
use crate::ident::Ident;
use crate::path::{Path, QSelf};
use crate::punctuated::Punctuated;
use crate::token;
use crate::ty::Type;
use proc_macro2::TokenStream;

pub use crate::expr::{
    ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath,
    ExprRange as PatRange,
};

ast_enum_of_structs! {
    /// A pattern in a local binding, function signature, match expression, or
    /// various other places.
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    #[non_exhaustive]
    pub enum Pat {
        /// A const block: `const { ... }`.
        Const(PatConst),

        /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
        Ident(PatIdent),

        /// A literal pattern: `0`.
        Lit(PatLit),

        /// A macro in pattern position.
        Macro(PatMacro),

        /// A pattern that matches any one of a set of cases.
        Or(PatOr),

        /// A parenthesized pattern: `(A | B)`.
        Paren(PatParen),

        /// A path pattern like `Color::Red`, optionally qualified with a
        /// self-type.
        ///
        /// Unqualified path patterns can legally refer to variants, structs,
        /// constants or associated constants. Qualified path patterns like
        /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
        /// associated constants.
        Path(PatPath),

        /// A range pattern: `1..=2`.
        Range(PatRange),

        /// A reference pattern: `&mut var`.
        Reference(PatReference),

        /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
        Rest(PatRest),

        /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
        Slice(PatSlice),

        /// A struct or struct variant pattern: `Variant { x, y, .. }`.
        Struct(PatStruct),

        /// A tuple pattern: `(a, b)`.
        Tuple(PatTuple),

        /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
        TupleStruct(PatTupleStruct),

        /// A type ascription pattern: `foo: f64`.
        Type(PatType),

        /// Tokens in pattern position not interpreted by Syn.
        Verbatim(TokenStream),

        /// A pattern that matches any value: `_`.
        Wild(PatWild),

        // For testing exhaustiveness in downstream code, use the following idiom:
        //
        //     match pat {
        //         #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
        //
        //         Pat::Box(pat) => {...}
        //         Pat::Ident(pat) => {...}
        //         ...
        //         Pat::Wild(pat) => {...}
        //
        //         _ => { /* some sane fallback */ }
        //     }
        //
        // This way we fail your tests but don't break your library when adding
        // a variant. You will be notified by a test failure when a variant is
        // added, so that you can add code to handle it, but your library will
        // continue to compile and work for downstream users in the interim.
    }
}

ast_struct! {
    /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
    ///
    /// It may also be a unit struct or struct variant (e.g. `None`), or a
    /// constant; these cannot be distinguished syntactically.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatIdent {
        pub attrs: Vec<Attribute>,
        pub by_ref: Option<Token![ref]>,
        pub mutability: Option<Token![mut]>,
        pub ident: Ident,
        pub subpat: Option<(Token![@], Box<Pat>)>,
    }
}

ast_struct! {
    /// A pattern that matches any one of a set of cases.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatOr {
        pub attrs: Vec<Attribute>,
        pub leading_vert: Option<Token![|]>,
        pub cases: Punctuated<Pat, Token![|]>,
    }
}

ast_struct! {
    /// A parenthesized pattern: `(A | B)`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatParen {
        pub attrs: Vec<Attribute>,
        pub paren_token: token::Paren,
        pub pat: Box<Pat>,
    }
}

ast_struct! {
    /// A reference pattern: `&mut var`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatReference {
        pub attrs: Vec<Attribute>,
        pub and_token: Token![&],
        pub mutability: Option<Token![mut]>,
        pub pat: Box<Pat>,
    }
}

ast_struct! {
    /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatRest {
        pub attrs: Vec<Attribute>,
        pub dot2_token: Token![..],
    }
}

ast_struct! {
    /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatSlice {
        pub attrs: Vec<Attribute>,
        pub bracket_token: token::Bracket,
        pub elems: Punctuated<Pat, Token![,]>,
    }
}

ast_struct! {
    /// A struct or struct variant pattern: `Variant { x, y, .. }`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatStruct {
        pub attrs: Vec<Attribute>,
        pub qself: Option<QSelf>,
        pub path: Path,
        pub brace_token: token::Brace,
        pub fields: Punctuated<FieldPat, Token![,]>,
        pub rest: Option<PatRest>,
    }
}

ast_struct! {
    /// A tuple pattern: `(a, b)`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatTuple {
        pub attrs: Vec<Attribute>,
        pub paren_token: token::Paren,
        pub elems: Punctuated<Pat, Token![,]>,
    }
}

ast_struct! {
    /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatTupleStruct {
        pub attrs: Vec<Attribute>,
        pub qself: Option<QSelf>,
        pub path: Path,
        pub paren_token: token::Paren,
        pub elems: Punctuated<Pat, Token![,]>,
    }
}

ast_struct! {
    /// A type ascription pattern: `foo: f64`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatType {
        pub attrs: Vec<Attribute>,
        pub pat: Box<Pat>,
        pub colon_token: Token![:],
        pub ty: Box<Type>,
    }
}

ast_struct! {
    /// A pattern that matches any value: `_`.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct PatWild {
        pub attrs: Vec<Attribute>,
        pub underscore_token: Token![_],
    }
}

ast_struct! {
    /// A single field in a struct pattern.
    ///
    /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
    /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
    pub struct FieldPat {
        pub attrs: Vec<Attribute>,
        pub member: Member,
        pub colon_token: Option<Token![:]>,
        pub pat: Box<Pat>,
    }
}

#[cfg(feature = "parsing")]
pub(crate) mod parsing {
    use crate::attr::Attribute;
    use crate::error::{self, Result};
    use crate::expr::{
        Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits,
    };
    use crate::ext::IdentExt as _;
    use crate::ident::Ident;
    use crate::lit::Lit;
    use crate::mac::{self, Macro};
    use crate::parse::{Parse, ParseBuffer, ParseStream};
    use crate::pat::{
        FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
        PatTuple, PatTupleStruct, PatType, PatWild,
    };
    use crate::path::{self, Path, QSelf};
    use crate::punctuated::Punctuated;
    use crate::stmt::Block;
    use crate::token;
    use crate::verbatim;
    use proc_macro2::TokenStream;

    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
    impl Pat {
        /// Parse a pattern that does _not_ involve `|` at the top level.
        ///
        /// This parser matches the behavior of the `$:pat_param` macro_rules
        /// matcher, and on editions prior to Rust 2021, the behavior of
        /// `$:pat`.
        ///
        /// In Rust syntax, some examples of where this syntax would occur are
        /// in the argument pattern of functions and closures. Patterns using
        /// `|` are not allowed to occur in these positions.
        ///
        /// ```compile_fail
        /// fn f(Some(_) | None: Option<T>) {
        ///     let _ = |Some(_) | None: Option<T>| {};
        ///     //       ^^^^^^^^^^^^^^^^^^^^^^^^^??? :(
        /// }
        /// ```
        ///
        /// ```console
        /// error: top-level or-patterns are not allowed in function parameters
        ///  --> src/main.rs:1:6
        ///   |
        /// 1 | fn f(Some(_) | None: Option<T>) {
        ///   |      ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)`
        /// ```
        pub fn parse_single(input: ParseStream) -> Result<Self> {
            let begin = input.fork();
            let lookahead = input.lookahead1();
            if lookahead.peek(Ident)
                && (input.peek2(Token![::])
                    || input.peek2(Token![!])
                    || input.peek2(token::Brace)
                    || input.peek2(token::Paren)
                    || input.peek2(Token![..]))
                || input.peek(Token![self]) && input.peek2(Token![::])
                || lookahead.peek(Token![::])
                || lookahead.peek(Token![<])
                || input.peek(Token![Self])
                || input.peek(Token![super])
                || input.peek(Token![crate])
            {
                pat_path_or_macro_or_struct_or_range(input)
            } else if lookahead.peek(Token![_]) {
                input.call(pat_wild).map(Pat::Wild)
            } else if input.peek(Token![box]) {
                pat_box(begin, input)
            } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const])
            {
                pat_lit_or_range(input)
            } else if lookahead.peek(Token![ref])
                || lookahead.peek(Token![mut])
                || input.peek(Token![self])
                || input.peek(Ident)
            {
                input.call(pat_ident).map(Pat::Ident)
            } else if lookahead.peek(Token![&]) {
                input.call(pat_reference).map(Pat::Reference)
            } else if lookahead.peek(token::Paren) {
                input.call(pat_paren_or_tuple)
            } else if lookahead.peek(token::Bracket) {
                input.call(pat_slice).map(Pat::Slice)
            } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
                pat_range_half_open(input)
            } else if lookahead.peek(Token![const]) {
                input.call(pat_const).map(Pat::Verbatim)
            } else {
                Err(lookahead.error())
            }
        }

        /// Parse a pattern, possibly involving `|`, but not a leading `|`.
        pub fn parse_multi(input: ParseStream) -> Result<Self> {
            multi_pat_impl(input, None)
        }

        /// Parse a pattern, possibly involving `|`, possibly including a
        /// leading `|`.
        ///
        /// This parser matches the behavior of the Rust 2021 edition's `$:pat`
        /// macro_rules matcher.
        ///
        /// In Rust syntax, an example of where this syntax would occur is in
        /// the pattern of a `match` arm, where the language permits an optional
        /// leading `|`, although it is not idiomatic to write one there in
        /// handwritten code.
        ///
        /// ```
        /// # let wat = None;
        /// match wat {
        ///     | None | Some(false) => {}
        ///     | Some(true) => {}
        /// }
        /// ```
        ///
        /// The compiler accepts it only to facilitate some situations in
        /// macro-generated code where a macro author might need to write:
        ///
        /// ```
        /// # macro_rules! doc {
        /// #     ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => {
        /// match $value {
        ///     $(| $conditions1)* $(| $conditions2)* => $then
        /// }
        /// #     };
        /// # }
        /// #
        /// # doc!(true, (true), (false), {});
        /// # doc!(true, (), (true, false), {});
        /// # doc!(true, (true, false), (), {});
        /// ```
        ///
        /// Expressing the same thing correctly in the case that either one (but
        /// not both) of `$conditions1` and `$conditions2` might be empty,
        /// without leading `|`, is complex.
        ///
        /// Use [`Pat::parse_multi`] instead if you are not intending to support
        /// macro-generated macro input.
        pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
            let leading_vert: Option<Token![|]> = input.parse()?;
            multi_pat_impl(input, leading_vert)
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
    impl Parse for PatType {
        fn parse(input: ParseStream) -> Result<Self> {
            Ok(PatType {
                attrs: Vec::new(),
                pat: Box::new(Pat::parse_single(input)?),
                colon_token: input.parse()?,
                ty: input.parse()?,
            })
        }
    }

    fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> {
        let mut pat = Pat::parse_single(input)?;
        if leading_vert.is_some()
            || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
        {
            let mut cases = Punctuated::new();
            cases.push_value(pat);
            while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
                let punct = input.parse()?;
                cases.push_punct(punct);
                let pat = Pat::parse_single(input)?;
                cases.push_value(pat);
            }
            pat = Pat::Or(PatOr {
                attrs: Vec::new(),
                leading_vert,
                cases,
            });
        }
        Ok(pat)
    }

    fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
        let expr_style = true;
        let (qself, path) = path::parsing::qpath(input, expr_style)?;

        if qself.is_none()
            && input.peek(Token![!])
            && !input.peek(Token![!=])
            && path.is_mod_style()
        {
            let bang_token: Token![!] = input.parse()?;
            let (delimiter, tokens) = mac::parse_delimiter(input)?;
            return Ok(Pat::Macro(ExprMacro {
                attrs: Vec::new(),
                mac: Macro {
                    path,
                    bang_token,
                    delimiter,
                    tokens,
                },
            }));
        }

        if input.peek(token::Brace) {
            pat_struct(input, qself, path).map(Pat::Struct)
        } else if input.peek(token::Paren) {
            pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
        } else if input.peek(Token![..]) {
            pat_range(input, qself, path)
        } else {
            Ok(Pat::Path(ExprPath {
                attrs: Vec::new(),
                qself,
                path,
            }))
        }
    }

    fn pat_wild(input: ParseStream) -> Result<PatWild> {
        Ok(PatWild {
            attrs: Vec::new(),
            underscore_token: input.parse()?,
        })
    }

    fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> {
        input.parse::<Token![box]>()?;
        Pat::parse_single(input)?;
        Ok(Pat::Verbatim(verbatim::between(&begin, input)))
    }

    fn pat_ident(input: ParseStream) -> Result<PatIdent> {
        Ok(PatIdent {
            attrs: Vec::new(),
            by_ref: input.parse()?,
            mutability: input.parse()?,
            ident: {
                if input.peek(Token![self]) {
                    input.call(Ident::parse_any)?
                } else {
                    input.parse()?
                }
            },
            subpat: {
                if input.peek(Token![@]) {
                    let at_token: Token![@] = input.parse()?;
                    let subpat = Pat::parse_single(input)?;
                    Some((at_token, Box::new(subpat)))
                } else {
                    None
                }
            },
        })
    }

    fn pat_tuple_struct(
        input: ParseStream,
        qself: Option<QSelf>,
        path: Path,
    ) -> Result<PatTupleStruct> {
        let content;
        let paren_token = parenthesized!(content in input);

        let mut elems = Punctuated::new();
        while !content.is_empty() {
            let value = Pat::parse_multi_with_leading_vert(&content)?;
            elems.push_value(value);
            if content.is_empty() {
                break;
            }
            let punct = content.parse()?;
            elems.push_punct(punct);
        }

        Ok(PatTupleStruct {
            attrs: Vec::new(),
            qself,
            path,
            paren_token,
            elems,
        })
    }

    fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
        let content;
        let brace_token = braced!(content in input);

        let mut fields = Punctuated::new();
        let mut rest = None;
        while !content.is_empty() {
            let attrs = content.call(Attribute::parse_outer)?;
            if content.peek(Token![..]) {
                rest = Some(PatRest {
                    attrs,
                    dot2_token: content.parse()?,
                });
                break;
            }
            let mut value = content.call(field_pat)?;
            value.attrs = attrs;
            fields.push_value(value);
            if content.is_empty() {
                break;
            }
            let punct: Token![,] = content.parse()?;
            fields.push_punct(punct);
        }

        Ok(PatStruct {
            attrs: Vec::new(),
            qself,
            path,
            brace_token,
            fields,
            rest,
        })
    }

    fn field_pat(input: ParseStream) -> Result<FieldPat> {
        let begin = input.fork();
        let boxed: Option<Token![box]> = input.parse()?;
        let by_ref: Option<Token![ref]> = input.parse()?;
        let mutability: Option<Token![mut]> = input.parse()?;

        let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
            input.parse().map(Member::Named)
        } else {
            input.parse()
        }?;

        if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
            || !member.is_named()
        {
            return Ok(FieldPat {
                attrs: Vec::new(),
                member,
                colon_token: Some(input.parse()?),
                pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
            });
        }

        let ident = match member {
            Member::Named(ident) => ident,
            Member::Unnamed(_) => unreachable!(),
        };

        let pat = if boxed.is_some() {
            Pat::Verbatim(verbatim::between(&begin, input))
        } else {
            Pat::Ident(PatIdent {
                attrs: Vec::new(),
                by_ref,
                mutability,
                ident: ident.clone(),
                subpat: None,
            })
        };

        Ok(FieldPat {
            attrs: Vec::new(),
            member: Member::Named(ident),
            colon_token: None,
            pat: Box::new(pat),
        })
    }

    fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
        let limits = RangeLimits::parse_obsolete(input)?;
        let end = input.call(pat_range_bound)?;
        if let (RangeLimits::Closed(_), None) = (&limits, &end) {
            return Err(input.error("expected range upper bound"));
        }
        Ok(Pat::Range(ExprRange {
            attrs: Vec::new(),
            start: Some(Box::new(Expr::Path(ExprPath {
                attrs: Vec::new(),
                qself,
                path,
            }))),
            limits,
            end: end.map(PatRangeBound::into_expr),
        }))
    }

    fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
        let limits: RangeLimits = input.parse()?;
        let end = input.call(pat_range_bound)?;
        if end.is_some() {
            Ok(Pat::Range(ExprRange {
                attrs: Vec::new(),
                start: None,
                limits,
                end: end.map(PatRangeBound::into_expr),
            }))
        } else {
            match limits {
                RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
                    attrs: Vec::new(),
                    dot2_token,
                })),
                RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
            }
        }
    }

    fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
        let content;
        let paren_token = parenthesized!(content in input);

        let mut elems = Punctuated::new();
        while !content.is_empty() {
            let value = Pat::parse_multi_with_leading_vert(&content)?;
            if content.is_empty() {
                if elems.is_empty() && !matches!(value, Pat::Rest(_)) {
                    return Ok(Pat::Paren(PatParen {
                        attrs: Vec::new(),
                        paren_token,
                        pat: Box::new(value),
                    }));
                }
                elems.push_value(value);
                break;
            }
            elems.push_value(value);
            let punct = content.parse()?;
            elems.push_punct(punct);
        }

        Ok(Pat::Tuple(PatTuple {
            attrs: Vec::new(),
            paren_token,
            elems,
        }))
    }

    fn pat_reference(input: ParseStream) -> Result<PatReference> {
        Ok(PatReference {
            attrs: Vec::new(),
            and_token: input.parse()?,
            mutability: input.parse()?,
            pat: Box::new(Pat::parse_single(input)?),
        })
    }

    fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
        let start = input.call(pat_range_bound)?.unwrap();
        if input.peek(Token![..]) {
            let limits = RangeLimits::parse_obsolete(input)?;
            let end = input.call(pat_range_bound)?;
            if let (RangeLimits::Closed(_), None) = (&limits, &end) {
                return Err(input.error("expected range upper bound"));
            }
            Ok(Pat::Range(ExprRange {
                attrs: Vec::new(),
                start: Some(start.into_expr()),
                limits,
                end: end.map(PatRangeBound::into_expr),
            }))
        } else {
            Ok(start.into_pat())
        }
    }

    // Patterns that can appear on either side of a range pattern.
    enum PatRangeBound {
        Const(ExprConst),
        Lit(ExprLit),
        Path(ExprPath),
    }

    impl PatRangeBound {
        fn into_expr(self) -> Box<Expr> {
            Box::new(match self {
                PatRangeBound::Const(pat) => Expr::Const(pat),
                PatRangeBound::Lit(pat) => Expr::Lit(pat),
                PatRangeBound::Path(pat) => Expr::Path(pat),
            })
        }

        fn into_pat(self) -> Pat {
            match self {
                PatRangeBound::Const(pat) => Pat::Const(pat),
                PatRangeBound::Lit(pat) => Pat::Lit(pat),
                PatRangeBound::Path(pat) => Pat::Path(pat),
            }
        }
    }

    fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
        if input.is_empty()
            || input.peek(Token![|])
            || input.peek(Token![=])
            || input.peek(Token![:]) && !input.peek(Token![::])
            || input.peek(Token![,])
            || input.peek(Token![;])
            || input.peek(Token![if])
        {
            return Ok(None);
        }

        let lookahead = input.lookahead1();
        let expr = if lookahead.peek(Lit) {
            PatRangeBound::Lit(input.parse()?)
        } else if lookahead.peek(Ident)
            || lookahead.peek(Token![::])
            || lookahead.peek(Token![<])
            || lookahead.peek(Token![self])
            || lookahead.peek(Token![Self])
            || lookahead.peek(Token![super])
            || lookahead.peek(Token![crate])
        {
            PatRangeBound::Path(input.parse()?)
        } else if lookahead.peek(Token![const]) {
            PatRangeBound::Const(input.parse()?)
        } else {
            return Err(lookahead.error());
        };

        Ok(Some(expr))
    }

    fn pat_slice(input: ParseStream) -> Result<PatSlice> {
        let content;
        let bracket_token = bracketed!(content in input);

        let mut elems = Punctuated::new();
        while !content.is_empty() {
            let value = Pat::parse_multi_with_leading_vert(&content)?;
            match value {
                Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
                    let (start, end) = match pat.limits {
                        RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
                        RangeLimits::Closed(dot_dot_eq) => {
                            (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
                        }
                    };
                    let msg = "range pattern is not allowed unparenthesized inside slice pattern";
                    return Err(error::new2(start, end, msg));
                }
                _ => {}
            }
            elems.push_value(value);
            if content.is_empty() {
                break;
            }
            let punct = content.parse()?;
            elems.push_punct(punct);
        }

        Ok(PatSlice {
            attrs: Vec::new(),
            bracket_token,
            elems,
        })
    }

    fn pat_const(input: ParseStream) -> Result<TokenStream> {
        let begin = input.fork();
        input.parse::<Token![const]>()?;

        let content;
        braced!(content in input);
        content.call(Attribute::parse_inner)?;
        content.call(Block::parse_within)?;

        Ok(verbatim::between(&begin, input))
    }
}

#[cfg(feature = "printing")]
mod printing {
    use crate::attr::FilterAttrs;
    use crate::pat::{
        FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
        PatTuple, PatTupleStruct, PatType, PatWild,
    };
    use crate::path;
    use crate::path::printing::PathStyle;
    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatIdent {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.by_ref.to_tokens(tokens);
            self.mutability.to_tokens(tokens);
            self.ident.to_tokens(tokens);
            if let Some((at_token, subpat)) = &self.subpat {
                at_token.to_tokens(tokens);
                subpat.to_tokens(tokens);
            }
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatOr {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.leading_vert.to_tokens(tokens);
            self.cases.to_tokens(tokens);
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatParen {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.paren_token.surround(tokens, |tokens| {
                self.pat.to_tokens(tokens);
            });
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatReference {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.and_token.to_tokens(tokens);
            self.mutability.to_tokens(tokens);
            self.pat.to_tokens(tokens);
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatRest {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.dot2_token.to_tokens(tokens);
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatSlice {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.bracket_token.surround(tokens, |tokens| {
                self.elems.to_tokens(tokens);
            });
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatStruct {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
            self.brace_token.surround(tokens, |tokens| {
                self.fields.to_tokens(tokens);
                // NOTE: We need a comma before the dot2 token if it is present.
                if !self.fields.empty_or_trailing() && self.rest.is_some() {
                    <Token![,]>::default().to_tokens(tokens);
                }
                self.rest.to_tokens(tokens);
            });
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatTuple {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.paren_token.surround(tokens, |tokens| {
                self.elems.to_tokens(tokens);
                // If there is only one element, a trailing comma is needed to
                // distinguish PatTuple from PatParen, unless this is `(..)`
                // which is a tuple pattern even without comma.
                if self.elems.len() == 1
                    && !self.elems.trailing_punct()
                    && !matches!(self.elems[0], Pat::Rest { .. })
                {
                    <Token![,]>::default().to_tokens(tokens);
                }
            });
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatTupleStruct {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
            self.paren_token.surround(tokens, |tokens| {
                self.elems.to_tokens(tokens);
            });
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatType {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.pat.to_tokens(tokens);
            self.colon_token.to_tokens(tokens);
            self.ty.to_tokens(tokens);
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for PatWild {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            self.underscore_token.to_tokens(tokens);
        }
    }

    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
    impl ToTokens for FieldPat {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(self.attrs.outer());
            if let Some(colon_token) = &self.colon_token {
                self.member.to_tokens(tokens);
                colon_token.to_tokens(tokens);
            }
            self.pat.to_tokens(tokens);
        }
    }
}

[ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge