88e8b0a5fa
7620: Support control flow in `extract_function` assist r=matklad a=cpud36 Support `return`ing from outer function, `break`ing and `continue`ing outer loops when extracting function. # Example Transforms ```rust fn foo() -> i32 { let items = [1,2,3]; let mut sum = 0; for &item in items { <|>if item == 42 { break; }<|> sum += item; } sum } ``` Into ```rust fn foo() -> i32 { let items = [1,2,3]; let mut sum = 0; for &item in items { if fun_name(item) { break; } sum += item; } sum } fn fun_name(item: i32) -> bool { if item == 42 { return true; } false } ``` ![add_explicit_type_infer_type](https://user-images.githubusercontent.com/4218373/107544222-0fadf280-6bdb-11eb-9625-ed6194ba92c0.gif) # Features Supported variants - break and function does not return => uses `bool` and plain if - break and function does return => uses `Option<T>` and matches on it - break with value and function does not return => uses `Option<T>` and if let - break with value and function does return => uses `Result<T, U>` and matches on t - same for `return` and `continue`(but we can't continue with value) Assist does handle nested loops and nested items(like functions, modules, impls) Try `expr?` operator is allowed together with `return Err(_)` and `return None`. `return expr` is not allowed. # Not supported ## Mixing `return` with `break` or `continue` If we have e.g. a `return` and a `break` in the selected code, it is unclear what the produced code should look like. We can try `Result<T, Option<U>>` or something like that, but it isn't idiomatic, nor it is established. Otherwise, implementation is relatively simple. ## `break` with label Not sure how to handle different labels for multiple `break`s. [edit] implemented try `expr?` Co-authored-by: Vladyslav Katasonov <cpud47@gmail.com> |
||
---|---|---|
.. | ||
add_explicit_type.rs | ||
add_lifetime_to_type.rs | ||
add_missing_impl_members.rs | ||
add_turbo_fish.rs | ||
apply_demorgan.rs | ||
auto_import.rs | ||
change_visibility.rs | ||
convert_integer_literal.rs | ||
early_return.rs | ||
expand_glob_import.rs | ||
extract_function.rs | ||
extract_struct_from_enum_variant.rs | ||
extract_variable.rs | ||
fill_match_arms.rs | ||
fix_visibility.rs | ||
flip_binexpr.rs | ||
flip_comma.rs | ||
flip_trait_bound.rs | ||
generate_default_from_enum_variant.rs | ||
generate_derive.rs | ||
generate_enum_match_method.rs | ||
generate_from_impl_for_enum.rs | ||
generate_function.rs | ||
generate_getter_mut.rs | ||
generate_getter.rs | ||
generate_impl.rs | ||
generate_new.rs | ||
generate_setter.rs | ||
infer_function_return_type.rs | ||
inline_function.rs | ||
inline_local_variable.rs | ||
introduce_named_lifetime.rs | ||
invert_if.rs | ||
merge_imports.rs | ||
merge_match_arms.rs | ||
move_bounds.rs | ||
move_guard.rs | ||
move_module_to_file.rs | ||
pull_assignment_up.rs | ||
qualify_path.rs | ||
raw_string.rs | ||
remove_dbg.rs | ||
remove_mut.rs | ||
remove_unused_param.rs | ||
reorder_fields.rs | ||
reorder_impl.rs | ||
replace_derive_with_manual_impl.rs | ||
replace_if_let_with_match.rs | ||
replace_impl_trait_with_generic.rs | ||
replace_let_with_if_let.rs | ||
replace_qualified_name_with_use.rs | ||
replace_string_with_char.rs | ||
replace_unwrap_with_match.rs | ||
split_import.rs | ||
toggle_ignore.rs | ||
unmerge_use.rs | ||
unwrap_block.rs | ||
wrap_return_type_in_result.rs |