If I were changing the signature of `do_something` in Rust and wanted to avoid breaking callers when changing the function from accepting `T` to `Option<T>` , I'd do the following:
fn do_something(value: impl Into<Option<T>>) {
let value = value.into();
// remaining function body using `value` as an `Option<T>`
}
Existing calls to `do_something` will continue working because `Option<T>` implements `From<T>` (and `Into` implementations are generated in the opposite direction whenever `From` is implemented). Passing in `None` will also work because every type `T` implements `From<T>`, and therefore `Into<T>` as well.I'd even argue that in a lot of cases, this is worth doing even when creating new library functions (where there are no existing callers to worry about). In my experience, it's generally better to keep the API clean from a caller's perspective by taking on extra boilerplate internally in the implementation rather than shift the burden to the callers of the API in order to keep the library's implementation clean.