aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src/code_model.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-02-16 14:01:09 +0000
committerGitHub <[email protected]>2021-02-16 14:01:09 +0000
commit88e8b0a5fa17075475c75941932056f7289c5bcf (patch)
tree84889038ca64a9ee4775ecf5605ed0213b90a0b7 /crates/hir/src/code_model.rs
parent00d5a9563af9c84cdea9d029a9583be0513cc459 (diff)
parent37a8cec6386d57e76b3067af48c78867aa9922ed (diff)
Merge #7620
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 <[email protected]>
Diffstat (limited to 'crates/hir/src/code_model.rs')
-rw-r--r--crates/hir/src/code_model.rs12
1 files changed, 12 insertions, 0 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 35b532602..7d43d4097 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1802,6 +1802,18 @@ impl Type {
1802 None 1802 None
1803 } 1803 }
1804 1804
1805 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ {
1806 let ty = self.ty.value.strip_references();
1807 let substs = match ty {
1808 Ty::Apply(apply_ty) => &apply_ty.parameters,
1809 Ty::Opaque(opaque_ty) => &opaque_ty.parameters,
1810 _ => return Either::Left(iter::empty()),
1811 };
1812
1813 let iter = substs.iter().map(move |ty| self.derived(ty.clone()));
1814 Either::Right(iter)
1815 }
1816
1805 pub fn iterate_method_candidates<T>( 1817 pub fn iterate_method_candidates<T>(
1806 &self, 1818 &self,
1807 db: &dyn HirDatabase, 1819 db: &dyn HirDatabase,