fn resolve_pattern_inner(
        &mut self,
        pat: &Pat,
        pat_src: PatternSource,
        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
    ) {
        // Visit all direct subpatterns of this pattern.
        pat.walk(&mut |pat| {
            debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind);
            match pat.kind {
                PatKind::Ident(bmode, ident, ref sub) => {
                    // First try to resolve the identifier as some existing entity,
                    // then fall back to a fresh binding.
                    let has_sub = sub.is_some();
                    let res = self
                        .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
                        .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
                    self.r.record_partial_res(pat.id, PartialRes::new(res));
                }
                PatKind::TupleStruct(ref path, ..) => {
                    self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
                }
                PatKind::Path(ref qself, ref path) => {
                    self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
                }
                PatKind::Struct(ref path, ..) => {
                    self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
                }
                PatKind::Or(ref ps) => {
                    // Add a new set of bindings to the stack. `Or` here records that when a
                    // binding already exists in this set, it should not result in an error because
                    // `V1(a) | V2(a)` must be allowed and are checked for consistency later.
                    bindings.push((PatBoundCtx::Or, Default::default()));
                    for p in ps {
                        // Now we need to switch back to a product context so that each
                        // part of the or-pattern internally rejects already bound names.
                        // For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
                        bindings.push((PatBoundCtx::Product, Default::default()));
                        self.resolve_pattern_inner(p, pat_src, bindings);
                        // Move up the non-overlapping bindings to the or-pattern.
                        // Existing bindings just get "merged".
                        let collected = bindings.pop().unwrap().1;
                        bindings.last_mut().unwrap().1.extend(collected);
                    }
                    // This or-pattern itself can itself be part of a product,
                    // e.g. `(V1(a) | V2(a), a)` or `(a, V1(a) | V2(a))`.
                    // Both cases bind `a` again in a product pattern and must be rejected.
                    let collected = bindings.pop().unwrap().1;
                    bindings.last_mut().unwrap().1.extend(collected);

                    // Prevent visiting `ps` as we've already done so above.
                    return false;
                }
                _ => {}
            }
            true
        });
    }
/// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
///
/// ### `bindings`
///
/// A stack of sets of bindings accumulated.
///
/// In each set, `PatBoundCtx::Product` denotes that a found binding in it should
/// be interpreted as re-binding an already bound binding. This results in an error.
/// Meanwhile, `PatBound::Or` denotes that a found binding in the set should result
/// in reusing this binding rather than creating a fresh one.
///
/// When called at the top level, the stack must have a single element
/// with `PatBound::Product`. Otherwise, pushing to the stack happens as
/// or-patterns (`p_0 | ... | p_n`) are encountered and the context needs
/// to be switched to `PatBoundCtx::Or` and then `PatBoundCtx::Product` for each `p_i`.
/// When each `p_i` has been dealt with, the top set is merged with its parent.
/// When a whole or-pattern has been dealt with, the thing happens.
///
/// See the implementation and `fresh_binding` for more details.
Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
Resolve bindings in a pattern . This is a helper to ` resolve_pattern ` .
fn resolve_pattern_inner(
        &mut self,
        pat: &Pat,
        pat_src: PatternSource,
        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
    ) {
        // Visit all direct subpatterns of this pattern.
        pat.walk(&mut |pat| {
            debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind);
            match pat.kind {
                PatKind::Ident(bmode, ident, ref sub) => {
                    // First try to resolve the identifier as some existing entity,
                    // then fall back to a fresh binding.
                    let has_sub = sub.is_some();
                    let res = self
                        .try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
                        .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
                    self.r.record_partial_res(pat.id, PartialRes::new(res));
                }
                PatKind::TupleStruct(ref path, ..) => {
                    self.smart_resolve_path(pat.id, None, path, PathSource::TupleStruct);
                }
                PatKind::Path(ref qself, ref path) => {
                    self.smart_resolve_path(pat.id, qself.as_ref(), path, PathSource::Pat);
                }
                PatKind::Struct(ref path, ..) => {
                    self.smart_resolve_path(pat.id, None, path, PathSource::Struct);
                }
                PatKind::Or(ref ps) => {
                    // Add a new set of bindings to the stack. `Or` here records that when a
                    // binding already exists in this set, it should not result in an error because
                    // `V1(a) | V2(a)` must be allowed and are checked for consistency later.
                    bindings.push((PatBoundCtx::Or, Default::default()));
                    for p in ps {
                        // Now we need to switch back to a product context so that each
                        // part of the or-pattern internally rejects already bound names.
                        // For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
                        bindings.push((PatBoundCtx::Product, Default::default()));
                        self.resolve_pattern_inner(p, pat_src, bindings);
                        // Move up the non-overlapping bindings to the or-pattern.
                        // Existing bindings just get "merged".
                        let collected = bindings.pop().unwrap().1;
                        bindings.last_mut().unwrap().1.extend(collected);
                    }
                    // This or-pattern itself can itself be part of a product,
                    // e.g. `(V1(a) | V2(a), a)` or `(a, V1(a) | V2(a))`.
                    // Both cases bind `a` again in a product pattern and must be rejected.
                    let collected = bindings.pop().unwrap().1;
                    bindings.last_mut().unwrap().1.extend(collected);
                    // Prevent visiting `ps` as we've already done so above.
                    return false;
                }
                _ => {}
            }
            true
        });
    }
fn resolve_pattern_inner ( & mut self , pat : & Pat , pat_src : PatternSource , bindings : & mut SmallVec < [ ( PatBoundCtx , FxHashSet < Ident > ) ; 1 ] > , ) { // Visit all direct subpatterns of this pattern. pat . walk ( & mut | pat | { debug ! ( " " pat pat kind ) ; match pat . kind { PatKind :: Ident ( bmode , ident , ref sub ) => { // First try to resolve the identifier as some existing entity, // then fall back to a fresh binding. let has_sub = sub . is_some ( ) ; let res = self . try_resolve_as_non_binding ( pat_src , pat , bmode , ident , has_sub ) . unwrap_or_else ( | | self . fresh_binding ( ident , pat . id , pat_src , bindings ) ) ; self . r . record_partial_res ( pat . id , PartialRes :: new ( res ) ) ; } PatKind :: TupleStruct ( ref path , .. ) => { self . smart_resolve_path ( pat . id , None , path , PathSource :: TupleStruct ) ; } PatKind :: Path ( ref qself , ref path ) => { self . smart_resolve_path ( pat . id , qself . as_ref ( ) , path , PathSource :: Pat ) ; } PatKind :: Struct ( ref path , .. ) => { self . smart_resolve_path ( pat . id , None , path , PathSource :: Struct ) ; } PatKind :: Or ( ref ps ) => { // Add a new set of bindings to the stack. `Or` here records that when a // binding already exists in this set, it should not result in an error because // `V1(a) | V2(a)` must be allowed and are checked for consistency later. bindings . push ( ( PatBoundCtx :: Or , Default :: default ( ) ) ) ; for p in ps { // Now we need to switch back to a product context so that each // part of the or-pattern internally rejects already bound names. // For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad. bindings . push ( ( PatBoundCtx :: Product , Default :: default ( ) ) ) ; self . resolve_pattern_inner ( p , pat_src , bindings ) ; // Move up the non-overlapping bindings to the or-pattern. // Existing bindings just get "merged". let collected = bindings . pop ( ) . unwrap ( ) . 1 ; bindings . last_mut ( ) . unwrap ( ) . 1 . extend ( collected ) ; } // This or-pattern itself can itself be part of a product, // e.g. `(V1(a) | V2(a), a)` or `(a, V1(a) | V2(a))`. // Both cases bind `a` again in a product pattern and must be rejected. let collected = bindings . pop ( ) . unwrap ( ) . 1 ; bindings . last_mut ( ) . unwrap ( ) . 1 . extend ( collected ) ; // Prevent visiting `ps` as we've already done so above. return false ; } _ => { } } true } ) ; }
Resolve bindings in a pattern.
Resolve bindings in a pattern .
&mut self
pat
&Pat
pat_src
PatternSource
bindings
&mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>
&mut self
pat
&Pat
pat_src
PatternSource
bindings
&mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>
`bindings`
A stack of sets of bindings accumulated.

In each set, `PatBoundCtx::Product` denotes that a found binding in it should
be interpreted as re-binding an already bound binding. This results in an error.
Meanwhile, `PatBound::Or` denotes that a found binding in the set should result
in reusing this binding rather than creating a fresh one.

When called at the top level, the stack must have a single element
with `PatBound::Product`. Otherwise, pushing to the stack happens as
or-patterns (`p_0 | ... | p_n`) are encountered and the context needs
to be switched to `PatBoundCtx::Or` and then `PatBoundCtx::Product` for each `p_i`.
When each `p_i` has been dealt with, the top set is merged with its parent.
When a whole or-pattern has been dealt with, the thing happens.

See the implementation and `fresh_binding` for more details.
A stack of sets of bindings accumulated . In each set ` PatBoundCtx :: Product ` denotes that a found binding in it should be interpreted as re - binding an already bound binding . This results in an error . Meanwhile ` PatBound :: Or ` denotes that a found binding in the set should result in reusing this binding rather than creating a fresh one . When called at the top level the stack must have a single element with ` PatBound :: Product ` . Otherwise pushing to the stack happens as or - patterns ( ` p_0 | ... | p_n ` ) are encountered and the context needs to be switched to ` PatBoundCtx :: Or ` and then ` PatBoundCtx :: Product ` for each ` p_i ` . When each ` p_i ` has been dealt with the top set is merged with its parent . When a whole or - pattern has been dealt with the thing happens . See the implementation and ` fresh_binding ` for more details .