mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-01 12:37:37 +00:00
![]() Several compiler functions have `Option<!>` for their return type. That's odd. The only valid return value is `None`, so why is this type used? Because it lets you write certain patterns slightly more concisely. E.g. if you have these common patterns: ``` let Some(a) = f() else { return }; let Ok(b) = g() else { return }; ``` you can shorten them to these: ``` let a = f()?; let b = g().ok()?; ``` Huh. An `Option` return type typically designates success/failure. How should I interpret the type signature of a function that always returns (i.e. doesn't panic), does useful work (modifying `&mut` arguments), and yet only ever fails? This idiom subverts the type system for a cute syntactic trick. Furthermore, returning `Option<!>` from a function F makes things syntactically more convenient within F, but makes things worse at F's callsites. The callsites can themselves use `?` with F but should not, because they will get an unconditional early return, which is almost certainly not desirable. Instead the return value should be ignored. (Note that some of callsites of `process_operand`, `process_immedate`, `process_assign` actually do use `?`, though the early return doesn't matter in these cases because nothing of significance comes after those calls. Ugh.) When I first saw this pattern I had no idea how to interpret it, and it took me several minutes of close reading to understand everything I've written above. I even started a Zulip thread about it to make sure I understood it properly. "Save a few characters by introducing types so weird that compiler devs have to discuss it on Zulip" feels like a bad trade-off to me. This commit replaces all the `Option<!>` return values and uses `else`/`return` (or something similar) to replace the relevant `?` uses. The result is slightly more verbose but much easier to understand. |
||
---|---|---|
.. | ||
coroutine | ||
coverage | ||
inline | ||
shim | ||
abort_unwinding_calls.rs | ||
add_call_guards.rs | ||
add_moves_for_packed_drops.rs | ||
add_retag.rs | ||
add_subtyping_projections.rs | ||
check_alignment.rs | ||
check_const_item_mutation.rs | ||
check_packed_ref.rs | ||
cleanup_post_borrowck.rs | ||
copy_prop.rs | ||
coroutine.rs | ||
cost_checker.rs | ||
cross_crate_inline.rs | ||
ctfe_limit.rs | ||
dataflow_const_prop.rs | ||
dead_store_elimination.rs | ||
deduce_param_attrs.rs | ||
deduplicate_blocks.rs | ||
deref_separator.rs | ||
dest_prop.rs | ||
dump_mir.rs | ||
early_otherwise_branch.rs | ||
elaborate_box_derefs.rs | ||
elaborate_drops.rs | ||
errors.rs | ||
ffi_unwind_calls.rs | ||
function_item_references.rs | ||
gvn.rs | ||
inline.rs | ||
instsimplify.rs | ||
jump_threading.rs | ||
known_panics_lint.rs | ||
large_enums.rs | ||
lib.rs | ||
lint.rs | ||
lower_intrinsics.rs | ||
lower_slice_len.rs | ||
match_branches.rs | ||
mentioned_items.rs | ||
multiple_return_terminators.rs | ||
nrvo.rs | ||
pass_manager.rs | ||
prettify.rs | ||
promote_consts.rs | ||
ref_prop.rs | ||
remove_noop_landing_pads.rs | ||
remove_place_mention.rs | ||
remove_storage_markers.rs | ||
remove_uninit_drops.rs | ||
remove_unneeded_drops.rs | ||
remove_zsts.rs | ||
required_consts.rs | ||
reveal_all.rs | ||
shim.rs | ||
simplify_branches.rs | ||
simplify_comparison_integral.rs | ||
simplify.rs | ||
single_use_consts.rs | ||
sroa.rs | ||
ssa.rs | ||
unreachable_enum_branching.rs | ||
unreachable_prop.rs | ||
validate.rs |