How to mark a 'not part of example' branch?

Hi,

I have a function returning some enum with a documentaion and an example:

/// Some function
///
/// # Example
/// ```
/// // some code ...
///
/// let SomeEnum::SomeVariant(...) = some_function() else { unreachable!() };
///
/// // more code...
/// ```
fn some_function() -> SomeEnum {
    todo!()
}

My question is: What to put inside the else branch (or analogous places in other branching constructs that require exhaustiveness) to indicate that it is not a part of the example?

If SomeEnum was a Result, I would just use an unwrap() or ? (and not bother with let ... else), but for my types these are not available by default and it does not make sense to add them (e.g. unwrap()-like method) just to be used in examples.

Currently I am using unreachable!() (as shown), but I do not want to make an impression that this usage is intended for my function(s).

Is there something better? Or is this ok?

If unwrap would be okay, why isn't this? If anything I feel it's more informative, as it conveys "this cannot happen" more directly than unwrap.

What would you be writing in place of unreachable!() in code that is "real" and not an example? Whatever that thing is, I would suggest including a sketch of it. Hidden lines are useful for setting up the code so it will compile, but doesn't have distracting elements.

In aprticular, If the point of the example is to discuss the SomeVariant case only, but other variants are returned by the function too, then I would use a match instead of an unrealistic let else, and hide the arm that handles making the match exhaustive.

/// # Example
/// ```
/// match some_function() {
///     SomeEnum::SomeVariant(...) => {
///         <insert example code here>
///     }
/// #   _ => todo!(),
///     // handle other cases
/// }
/// ```

This way, if the user copy-and-pastes the example as displayed, they get a non-exhaustive match error. If they copy the code with hidden lines, they see a todo!() to do.

If the let else is how real code would handle it, then I would go ahead with what you already have, but with todo!(), not unreachable!(). unreachable!() means “This control flow cannot happen (or it's a bug)”; todo!() means “This code is incomplete”, which is exactly the case here.

1 Like

In most of the "real" code I would not actually match on the output of some_function. I would just use it as a value (e.g. as argument to another function) or even not call that function directly, rather just provide an input for someone else to call it on.

The point of the example is to show that some_function (with some particular input, which I didn't include in OP) returns SomeVariant. In simple cases assert_eq!() would do the job, but not always.

In other words, something like this would be other way to formulate my example:

assert_matches!(some_function(), SomeEnum::SomeVariant(some_var));  // but bring bindings into scope
// use `some_var` further, e.g.
assert!(some_var > 7);

But assert_matches! is not stable and it would not bring bindings from the pattern into scope.

If that's the case, unreachable!("<explanation>") where the explanation clearly states why an input X always returns an enum variant Y is a perfectly sensible way to go. I'd start by handling the most common list of cases first and leave that example for last, though.

1 Like

Ok, so I conclude that my current approach is fine (or at least not completely wrong). I will not add explanations however as I think they would be redundant -- the function should be described well enough and the example should be simple enough that it is clear why that variant is returned.

(For example here you also do not have somethimg like:

assert_eq!(12 + 1, 13, "by basic arithmetic rules 13 is one more than 12");

... and my let else unreachable is just glorified version of that.)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.