二つのxxx::Result<T>が同時に出てくることはないから混乱しないんだよ

例えば以下の単純な文字数を数える関数を作ったとする
fn foo(path: impl AsRef<Path>) -> Result<usize> {
Ok(fs::read_to_string(path)?.chars().count())
}

もしanyhowを使う場合
use anyhow::Result;だけでいい
途中にio::Resultが返されるけど自動的に変換されて出て来ない
std::error::Errorトレイトを実装するエラーならどれも自動変換される

もしthiserrorを使う場合
自分でMyErrorとResultを定義する
type Result<T, E = MyError> = std::result::Result<T, E>;
#[derive(thiserror::Error)]
enum MyError {
#[error("I/O Error")]
Io(#[from] std::io::Error),
}
io::Errorが返された場合の自動変換ルールはこのように自分で定義する
したがって関数から返されるio::Resultは出て来ない

もう一つ重要な点はこのResultの再定義の方法
type Result<T, E = MyError> = std::result::Result<T, E>;
デフォルト値をMyErrorとしているだけなので
本来のResult<T, E>としてもそのまま使える
同じ再定義をしているanyhow::Result<T, E>も大丈夫