diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs index ef4b977fe524..44d020a1b46c 100644 --- a/crates/ide-assists/src/handlers/extract_function.rs +++ b/crates/ide-assists/src/handlers/extract_function.rs @@ -2060,7 +2060,7 @@ fn fix_param_usages( .filter_map(|reference| path_element_of_reference(syntax, reference)) .map(|expr| tm.make_mut(&expr)); - usages_for_param.push((param, usages.collect())); + usages_for_param.push((param, usages.unique().collect())); } let res = tm.make_syntax_mut(syntax); @@ -6233,4 +6233,64 @@ fn $0fun_name(a: i32, b: i32) { cov_mark::check!(extract_function_in_braces_is_not_applicable); check_assist_not_applicable(extract_function, r"fn foo(arr: &mut $0[$0i32]) {}"); } + + #[test] + fn issue_20965_panic() { + check_assist( + extract_function, + r#" +//- minicore: fmt +#[derive(Debug)] +struct Foo(&'static str); + +impl Foo { + fn text(&self) -> &str { self.0 } +} + +fn main() { + let s = Foo(""); + $0print!("{}{}", s, s);$0 + let _ = s.text() == ""; +}"#, + r#" +#[derive(Debug)] +struct Foo(&'static str); + +impl Foo { + fn text(&self) -> &str { self.0 } +} + +fn main() { + let s = Foo(""); + fun_name(&s); + let _ = s.text() == ""; +} + +fn $0fun_name(s: &Foo) { + *print!("{}{}", s, s); +}"#, + ); + } + + #[test] + fn parameter_is_added_used_in_eq_expression_in_macro() { + check_assist( + extract_function, + r#" +//- minicore: fmt +fn foo() { + let v = 123; + $0print!("{v:?}{}", v == 123);$0 +}"#, + r#" +fn foo() { + let v = 123; + fun_name(v); +} + +fn $0fun_name(v: i32) { + print!("{v:?}{}", v == 123); +}"#, + ); + } } diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs index cde62e03238a..ab1830930854 100644 --- a/crates/parser/src/grammar/expressions/atom.rs +++ b/crates/parser/src/grammar/expressions/atom.rs @@ -283,7 +283,7 @@ fn builtin_expr(p: &mut Parser<'_>) -> Option { if p.eat(T![,]) { while !p.at(EOF) && !p.at(T![')']) { let m = p.start(); - if p.at(IDENT) && p.nth_at(1, T![=]) { + if p.at(IDENT) && p.nth_at(1, T![=]) && !p.nth_at(2, T![=]) { name(p); p.bump(T![=]); }