I really appreciate @chriskrycho’s perspective, especially on the return value syntax. Keeping -> Result<T, E> is important to keep the complexity down, to give beginners an obvious path forward for learning more, and because this sugar (however it looks in the end) is purely local to the function and thus not the only idiomatic way to generate such a return type.
However, I also think catch blocks are important as a way to localize the effect of ? to an expression. The catch block itself doing Try::from_ok is the perfect complement to ? doing Try::from_error, and makes far more sense to me than either catch { Ok(x) } or any sort of coercion-like Ok-wrapping. In that light, the -> Result<T, E> catch { syntax is a good, conservative, straightforward way to extend the benefits of Try::from_ok to functions as a whole.
I might even go a little further and introduce a more general fn f() -> T = ... syntax to make function-level catch less of a special case. This resolves the catch E syntax question in favor of just sticking to using type annotations (-> Result<T, E> = catch {, let x: Result<T, E> = catch {), extends nicely to other situations (e.g. other function-level wrappers, private-fn type inference), and has precedent in both C# and Kotlin.
I’m less convinced of throw e and return t. throw because it’s too similar to (labeled-)break-with-value to merit an entirely new syntax, and return because it doesn’t have a counterpart for expression-level catch. Further, if we used the fn f() -> T = syntax above, return wouldn’t even make sense as the catch block would be one layer inside the function body itself. I would prefer whatever solution we come up with here both a) align well with (labeled-)break-with-value and b) apply equally to function-level and expression-level catch. Perhaps simply some kind of break catch?