pub(crate) fn is_useful(
    cx: &MatchCheckCtx,
    matrix: &Matrix,
    v: &PatStack,
) -> MatchCheckResult<Usefulness> {
    // Handle the special case of enums with no variants. In that case, no match
    // arm is useful.
    if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) =
        cx.infer[cx.match_expr].strip_references()
    {
        if cx.db.enum_data(*enum_id).variants.is_empty() {
            return Ok(Usefulness::NotUseful);
        }
    }

    if v.is_empty() {
        let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };

        return Ok(result);
    }

    if let Pat::Or(pat_ids) = v.head().as_pat(cx) {
        let mut found_unimplemented = false;
        let any_useful = pat_ids.iter().any(|&pat_id| {
            let v = PatStack::from_pattern(pat_id);

            match is_useful(cx, matrix, &v) {
                Ok(Usefulness::Useful) => true,
                Ok(Usefulness::NotUseful) => false,
                _ => {
                    found_unimplemented = true;
                    false
                }
            }
        });

        return if any_useful {
            Ok(Usefulness::Useful)
        } else if found_unimplemented {
            Err(MatchCheckErr::NotImplemented)
        } else {
            Ok(Usefulness::NotUseful)
        };
    }

    if let Some(constructor) = pat_constructor(cx, v.head())? {
        let matrix = matrix.specialize_constructor(&cx, &constructor)?;
        let v = v
            .specialize_constructor(&cx, &constructor)?
            .expect("we know this can't fail because we get the constructor from `v.head()` above");

        is_useful(&cx, &matrix, &v)
    } else {
        // expanding wildcard
        let mut used_constructors: Vec<Constructor> = vec![];
        for pat in matrix.heads() {
            if let Some(constructor) = pat_constructor(cx, pat)? {
                used_constructors.push(constructor);
            }
        }

        // We assume here that the first constructor is the "correct" type. Since we
        // only care about the "type" of the constructor (i.e. if it is a bool we
        // don't care about the value), this assumption should be valid as long as
        // the match statement is well formed. We currently uphold this invariant by
        // filtering match arms before calling `is_useful`, only passing in match arms
        // whose type matches the type of the match expression.
        match &used_constructors.first() {
            Some(constructor) if all_constructors_covered(&cx, constructor, &used_constructors) => {
                // If all constructors are covered, then we need to consider whether
                // any values are covered by this wildcard.
                //
                // For example, with matrix '[[Some(true)], [None]]', all
                // constructors are covered (`Some`/`None`), so we need
                // to perform specialization to see that our wildcard will cover
                // the `Some(false)` case.
                //
                // Here we create a constructor for each variant and then check
                // usefulness after specializing for that constructor.
                let mut found_unimplemented = false;
                for constructor in constructor.all_constructors(cx) {
                    let matrix = matrix.specialize_constructor(&cx, &constructor)?;
                    let v = v.expand_wildcard(&cx, &constructor)?;

                    match is_useful(&cx, &matrix, &v) {
                        Ok(Usefulness::Useful) => return Ok(Usefulness::Useful),
                        Ok(Usefulness::NotUseful) => continue,
                        _ => found_unimplemented = true,
                    };
                }

                if found_unimplemented {
                    Err(MatchCheckErr::NotImplemented)
                } else {
                    Ok(Usefulness::NotUseful)
                }
            }
            _ => {
                // Either not all constructors are covered, or the only other arms
                // are wildcards. Either way, this pattern is useful if it is useful
                // when compared to those arms with wildcards.
                let matrix = matrix.specialize_wildcard(&cx);
                let v = v.to_tail();

                is_useful(&cx, &matrix, &v)
            }
        }
    }
}
/// Given a set of patterns `matrix`, and pattern to consider `v`, determines
/// whether `v` is useful. A pattern is useful if it covers cases which were
/// not previously covered.
///
/// When calling this function externally (that is, not the recursive calls) it
/// expected that you have already type checked the match arms. All patterns in
/// matrix should be the same type as v, as well as they should all be the same
/// type as the match expression.


When calling this function externally (that is, not the recursive calls) it
expected that you have already type checked the match arms. All patterns in
matrix should be the same type as v, as well as they should all be the same
type as the match expression.
When calling this function externally ( that is not the recursive calls ) it expected that you have already type checked the match arms . All patterns in matrix should be the same type as v as well as they should all be the same type as the match expression .
pub(crate) fn is_useful(
    cx: &MatchCheckCtx,
    matrix: &Matrix,
    v: &PatStack,
) -> MatchCheckResult<Usefulness> {
    // Handle the special case of enums with no variants. In that case, no match
    // arm is useful.
    if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(AdtId::EnumId(enum_id)), .. }) =
        cx.infer[cx.match_expr].strip_references()
    {
        if cx.db.enum_data(*enum_id).variants.is_empty() {
            return Ok(Usefulness::NotUseful);
        }
    }
    if v.is_empty() {
        let result = if matrix.is_empty() { Usefulness::Useful } else { Usefulness::NotUseful };
        return Ok(result);
    }
    if let Pat::Or(pat_ids) = v.head().as_pat(cx) {
        let mut found_unimplemented = false;
        let any_useful = pat_ids.iter().any(|&pat_id| {
            let v = PatStack::from_pattern(pat_id);
            match is_useful(cx, matrix, &v) {
                Ok(Usefulness::Useful) => true,
                Ok(Usefulness::NotUseful) => false,
                _ => {
                    found_unimplemented = true;
                    false
                }
            }
        });
        return if any_useful {
            Ok(Usefulness::Useful)
        } else if found_unimplemented {
            Err(MatchCheckErr::NotImplemented)
        } else {
            Ok(Usefulness::NotUseful)
        };
    }
    if let Some(constructor) = pat_constructor(cx, v.head())? {
        let matrix = matrix.specialize_constructor(&cx, &constructor)?;
        let v = v
            .specialize_constructor(&cx, &constructor)?
            .expect("we know this can't fail because we get the constructor from `v.head()` above");
        is_useful(&cx, &matrix, &v)
    } else {
        // expanding wildcard
        let mut used_constructors: Vec<Constructor> = vec![];
        for pat in matrix.heads() {
            if let Some(constructor) = pat_constructor(cx, pat)? {
                used_constructors.push(constructor);
            }
        }
        // We assume here that the first constructor is the "correct" type. Since we
        // only care about the "type" of the constructor (i.e. if it is a bool we
        // don't care about the value), this assumption should be valid as long as
        // the match statement is well formed. We currently uphold this invariant by
        // filtering match arms before calling `is_useful`, only passing in match arms
        // whose type matches the type of the match expression.
        match &used_constructors.first() {
            Some(constructor) if all_constructors_covered(&cx, constructor, &used_constructors) => {
                // If all constructors are covered, then we need to consider whether
                // any values are covered by this wildcard.
                //
                // For example, with matrix '[[Some(true)], [None]]', all
                // constructors are covered (`Some`/`None`), so we need
                // to perform specialization to see that our wildcard will cover
                // the `Some(false)` case.
                //
                // Here we create a constructor for each variant and then check
                // usefulness after specializing for that constructor.
                let mut found_unimplemented = false;
                for constructor in constructor.all_constructors(cx) {
                    let matrix = matrix.specialize_constructor(&cx, &constructor)?;
                    let v = v.expand_wildcard(&cx, &constructor)?;
                    match is_useful(&cx, &matrix, &v) {
                        Ok(Usefulness::Useful) => return Ok(Usefulness::Useful),
                        Ok(Usefulness::NotUseful) => continue,
                        _ => found_unimplemented = true,
                    };
                }
                if found_unimplemented {
                    Err(MatchCheckErr::NotImplemented)
                } else {
                    Ok(Usefulness::NotUseful)
                }
            }
            _ => {
                // Either not all constructors are covered, or the only other arms
                // are wildcards. Either way, this pattern is useful if it is useful
                // when compared to those arms with wildcards.
                let matrix = matrix.specialize_wildcard(&cx);
                let v = v.to_tail();
                is_useful(&cx, &matrix, &v)
            }
        }
    }
}
pub ( crate ) fn is_useful ( cx : & MatchCheckCtx , matrix : & Matrix , v : & PatStack , ) -> MatchCheckResult < Usefulness > { // Handle the special case of enums with no variants. In that case, no match // arm is useful. if let Ty :: Apply ( ApplicationTy { ctor : TypeCtor :: Adt ( AdtId :: EnumId ( enum_id ) ) , .. } ) = cx . infer [ cx . match_expr ] . strip_references ( ) { if cx . db . enum_data ( * enum_id ) . variants . is_empty ( ) { return Ok ( Usefulness :: NotUseful ) ; } } if v . is_empty ( ) { let result = if matrix . is_empty ( ) { Usefulness :: Useful } else { Usefulness :: NotUseful } ; return Ok ( result ) ; } if let Pat :: Or ( pat_ids ) = v . head ( ) . as_pat ( cx ) { let mut found_unimplemented = false ; let any_useful = pat_ids . iter ( ) . any ( | & pat_id | { let v = PatStack :: from_pattern ( pat_id ) ; match is_useful ( cx , matrix , & v ) { Ok ( Usefulness :: Useful ) => true , Ok ( Usefulness :: NotUseful ) => false , _ => { found_unimplemented = true ; false } } } ) ; return if any_useful { Ok ( Usefulness :: Useful ) } else if found_unimplemented { Err ( MatchCheckErr :: NotImplemented ) } else { Ok ( Usefulness :: NotUseful ) } ; } if let Some ( constructor ) = pat_constructor ( cx , v . head ( ) ) ? { let matrix = matrix . specialize_constructor ( & cx , & constructor ) ? ; let v = v . specialize_constructor ( & cx , & constructor ) ? . expect ( " " ) ; is_useful ( & cx , & matrix , & v ) } else { // expanding wildcard let mut used_constructors : Vec < Constructor > = vec ! [ ] ; for pat in matrix . heads ( ) { if let Some ( constructor ) = pat_constructor ( cx , pat ) ? { used_constructors . push ( constructor ) ; } } // We assume here that the first constructor is the "correct" type. Since we // only care about the "type" of the constructor (i.e. if it is a bool we // don't care about the value), this assumption should be valid as long as // the match statement is well formed. We currently uphold this invariant by // filtering match arms before calling `is_useful`, only passing in match arms // whose type matches the type of the match expression. match & used_constructors . first ( ) { Some ( constructor ) if all_constructors_covered ( & cx , constructor , & used_constructors ) => { // If all constructors are covered, then we need to consider whether // any values are covered by this wildcard. // // For example, with matrix '[[Some(true)], [None]]', all // constructors are covered (`Some`/`None`), so we need // to perform specialization to see that our wildcard will cover // the `Some(false)` case. // // Here we create a constructor for each variant and then check // usefulness after specializing for that constructor. let mut found_unimplemented = false ; for constructor in constructor . all_constructors ( cx ) { let matrix = matrix . specialize_constructor ( & cx , & constructor ) ? ; let v = v . expand_wildcard ( & cx , & constructor ) ? ; match is_useful ( & cx , & matrix , & v ) { Ok ( Usefulness :: Useful ) => return Ok ( Usefulness :: Useful ) , Ok ( Usefulness :: NotUseful ) => continue , _ => found_unimplemented = true , } ; } if found_unimplemented { Err ( MatchCheckErr :: NotImplemented ) } else { Ok ( Usefulness :: NotUseful ) } } _ => { // Either not all constructors are covered, or the only other arms // are wildcards. Either way, this pattern is useful if it is useful // when compared to those arms with wildcards. let matrix = matrix . specialize_wildcard ( & cx ) ; let v = v . to_tail ( ) ; is_useful ( & cx , & matrix , & v ) } } } }
Given a set of patterns `matrix`, and pattern to consider `v`, determines
whether `v` is useful.
Given a set of patterns ` matrix ` and pattern to consider ` v ` determines whether ` v ` is useful .
cx
&MatchCheckCtx
matrix
&Matrix
v
&PatStack
cx
&MatchCheckCtx
matrix
&Matrix
v
&PatStack