diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index 6e899249b69..c75627e0f7a 100644 --- a/crates/hir-ty/src/infer/coerce.rs +++ b/crates/hir-ty/src/infer/coerce.rs @@ -151,7 +151,7 @@ pub(super) fn coerce( if let Some(id) = expr { ctx.result.type_mismatches.insert( id.into(), - TypeMismatch { expected: self.merged_ty().clone(), actual: expr_ty.clone() }, + TypeMismatch { expected: self.merged_ty(), actual: expr_ty.clone() }, ); } cov_mark::hit!(coerce_merge_fail_fallback); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index d52188bb284..b524837abbb 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -331,7 +331,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); let prev_ret_coercion = - mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty.clone()))); + mem::replace(&mut self.return_coercion, Some(CoerceMany::new(ret_ty))); let prev_resume_yield_tys = mem::replace(&mut self.resume_yield_tys, resume_yield_tys); @@ -402,7 +402,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { .push(callee_ty.clone()) .push(TyBuilder::tuple_with(params.iter().cloned())) .build(); - self.write_method_resolution(tgt_expr, func, subst.clone()); + self.write_method_resolution(tgt_expr, func, subst) } } self.write_expr_adj(*callee, adjustments); @@ -803,7 +803,7 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { .push(self_ty.clone()) .push(index_ty.clone()) .build(); - self.write_method_resolution(tgt_expr, func, substs.clone()); + self.write_method_resolution(tgt_expr, func, substs); } self.resolve_associated_type_with_params( self_ty, @@ -912,7 +912,7 @@ fn infer_expr_array( (elem_ty, consteval::usize_const(self.db, Some(0), krate)) } Array::ElementList { elements, .. } => { - let mut coerce = CoerceMany::new(elem_ty.clone()); + let mut coerce = CoerceMany::new(elem_ty); for &expr in elements.iter() { let cur_elem_ty = self.infer_expr_inner(expr, &expected); coerce.coerce(self, Some(expr), &cur_elem_ty); @@ -1214,7 +1214,7 @@ fn infer_block( let g = self.resolver.update_to_inner_scope(self.db.upcast(), self.owner, expr); let (break_ty, ty) = - self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty.clone()), label, |this| { + self.with_breakable_ctx(BreakableKind::Block, Some(coerce_ty), label, |this| { for stmt in statements { match stmt { Statement::Let { pat, type_ref, initializer, else_branch } => { diff --git a/crates/hir-ty/src/interner.rs b/crates/hir-ty/src/interner.rs index aea7e9762fd..874f808cda1 100644 --- a/crates/hir-ty/src/interner.rs +++ b/crates/hir-ty/src/interner.rs @@ -51,8 +51,8 @@ impl chalk_ir::interner::Interner for Interner { type InternedGoal = Arc>; type InternedGoals = Vec>; type InternedSubstitution = Interned>>; - type InternedProgramClause = chalk_ir::ProgramClauseData; type InternedProgramClauses = Interned>>>; + type InternedProgramClause = chalk_ir::ProgramClauseData; type InternedQuantifiedWhereClauses = Interned>>>; type InternedVariableKinds = Interned>>>; @@ -86,6 +86,27 @@ fn debug_assoc_type_id( tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) } + fn debug_opaque_ty_id( + opaque_ty_id: chalk_ir::OpaqueTyId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + Some(write!(fmt, "OpaqueTy#{}", opaque_ty_id.0)) + } + + fn debug_fn_def_id( + fn_def_id: chalk_ir::FnDefId, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt))) + } + + fn debug_closure_id( + _fn_def_id: chalk_ir::ClosureId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + fn debug_alias( alias: &chalk_ir::AliasTy, fmt: &mut fmt::Formatter<'_>, @@ -113,13 +134,6 @@ fn debug_opaque_ty( Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id)) } - fn debug_opaque_ty_id( - opaque_ty_id: chalk_ir::OpaqueTyId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "OpaqueTy#{}", opaque_ty_id.0)) - } - fn debug_ty(ty: &chalk_ir::Ty, fmt: &mut fmt::Formatter<'_>) -> Option { Some(write!(fmt, "{:?}", ty.data(Interner))) } @@ -131,6 +145,13 @@ fn debug_lifetime( Some(write!(fmt, "{:?}", lifetime.data(Interner))) } + fn debug_const( + constant: &chalk_ir::Const, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + Some(write!(fmt, "{:?}", constant.data(Interner))) + } + fn debug_generic_arg( parameter: &GenericArg, fmt: &mut fmt::Formatter<'_>, @@ -138,69 +159,42 @@ fn debug_generic_arg( Some(write!(fmt, "{:?}", parameter.data(Interner).inner_debug())) } - fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { - let goal_data = goal.data(Interner); - Some(write!(fmt, "{goal_data:?}")) - } - - fn debug_goals( - goals: &chalk_ir::Goals, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", goals.debug(Interner))) - } - - fn debug_program_clause_implication( - pci: &chalk_ir::ProgramClauseImplication, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", pci.debug(Interner))) - } - - fn debug_substitution( - substitution: &chalk_ir::Substitution, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", substitution.debug(Interner))) - } - - fn debug_separator_trait_ref( - separator_trait_ref: &chalk_ir::SeparatorTraitRef<'_, Interner>, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", separator_trait_ref.debug(Interner))) - } - - fn debug_fn_def_id( - fn_def_id: chalk_ir::FnDefId, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt))) - } - fn debug_const( - constant: &chalk_ir::Const, - fmt: &mut fmt::Formatter<'_>, - ) -> Option { - Some(write!(fmt, "{:?}", constant.data(Interner))) - } fn debug_variable_kinds( variable_kinds: &chalk_ir::VariableKinds, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", variable_kinds.as_slice(Interner))) } + fn debug_variable_kinds_with_angles( variable_kinds: &chalk_ir::VariableKinds, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", variable_kinds.inner_debug(Interner))) } + fn debug_canonical_var_kinds( canonical_var_kinds: &chalk_ir::CanonicalVarKinds, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", canonical_var_kinds.as_slice(Interner))) } + fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option { + let goal_data = goal.data(Interner); + Some(write!(fmt, "{goal_data:?}")) + } + fn debug_goals( + goals: &chalk_ir::Goals, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + Some(write!(fmt, "{:?}", goals.debug(Interner))) + } + fn debug_program_clause_implication( + pci: &chalk_ir::ProgramClauseImplication, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + Some(write!(fmt, "{:?}", pci.debug(Interner))) + } fn debug_program_clause( clause: &chalk_ir::ProgramClause, fmt: &mut fmt::Formatter<'_>, @@ -213,6 +207,19 @@ fn debug_program_clauses( ) -> Option { Some(write!(fmt, "{:?}", clauses.as_slice(Interner))) } + fn debug_substitution( + substitution: &chalk_ir::Substitution, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + Some(write!(fmt, "{:?}", substitution.debug(Interner))) + } + fn debug_separator_trait_ref( + separator_trait_ref: &chalk_ir::SeparatorTraitRef<'_, Interner>, + fmt: &mut fmt::Formatter<'_>, + ) -> Option { + Some(write!(fmt, "{:?}", separator_trait_ref.debug(Interner))) + } + fn debug_quantified_where_clauses( clauses: &chalk_ir::QuantifiedWhereClauses, fmt: &mut fmt::Formatter<'_>, @@ -220,6 +227,13 @@ fn debug_quantified_where_clauses( Some(write!(fmt, "{:?}", clauses.as_slice(Interner))) } + fn debug_constraints( + _clauses: &chalk_ir::Constraints, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + fn intern_ty(self, kind: chalk_ir::TyKind) -> Self::InternedType { let flags = kind.compute_flags(self); Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags })) @@ -272,6 +286,10 @@ fn intern_goal(self, goal: GoalData) -> Self::InternedGoal { Arc::new(goal) } + fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData { + goal + } + fn intern_goals( self, data: impl IntoIterator, E>>, @@ -279,10 +297,6 @@ fn intern_goals( data.into_iter().collect() } - fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData { - goal - } - fn goals_data(self, goals: &Self::InternedGoals) -> &[Goal] { goals } @@ -367,32 +381,18 @@ fn canonical_var_kinds_data( ) -> &[chalk_ir::CanonicalVarKind] { canonical_var_kinds } - fn intern_constraints( self, data: impl IntoIterator>, E>>, ) -> Result { data.into_iter().collect() } - fn constraints_data( self, constraints: &Self::InternedConstraints, ) -> &[chalk_ir::InEnvironment>] { constraints } - fn debug_closure_id( - _fn_def_id: chalk_ir::ClosureId, - _fmt: &mut fmt::Formatter<'_>, - ) -> Option { - None - } - fn debug_constraints( - _clauses: &chalk_ir::Constraints, - _fmt: &mut fmt::Formatter<'_>, - ) -> Option { - None - } fn intern_variances( self, diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 782a8ab4aa2..ea494a0dbde 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -588,7 +588,7 @@ pub fn callable_sig_from_fnonce( let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?; let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; - let mut table = InferenceTable::new(db, env.clone()); + let mut table = InferenceTable::new(db, env); let b = TyBuilder::trait_ref(db, fn_once_trait); if b.remaining() != 2 { return None; diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 7b83645faef..84b59b5eeb9 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1414,7 +1414,7 @@ fn exec_fn_def( } CallableDefId::StructId(id) => { let (size, variant_layout, tag) = - self.layout_of_variant(id.into(), generic_args.clone(), &locals)?; + self.layout_of_variant(id.into(), generic_args, &locals)?; let result = self.make_by_layout( size, &variant_layout, @@ -1425,7 +1425,7 @@ fn exec_fn_def( } CallableDefId::EnumVariantId(id) => { let (size, variant_layout, tag) = - self.layout_of_variant(id.into(), generic_args.clone(), &locals)?; + self.layout_of_variant(id.into(), generic_args, &locals)?; let result = self.make_by_layout( size, &variant_layout, @@ -1507,7 +1507,7 @@ fn exec_fn_with_args( ); } let (imp, generic_args) = - lookup_impl_method(self.db, self.trait_env.clone(), def, generic_args.clone()); + lookup_impl_method(self.db, self.trait_env.clone(), def, generic_args); let generic_args = self.subst_filler(&generic_args, &locals); let def = imp.into(); let mir_body = diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs index a6967414aa8..9d97ab84a56 100644 --- a/crates/hir-ty/src/utils.rs +++ b/crates/hir-ty/src/utils.rs @@ -69,9 +69,7 @@ pub(super) fn all_super_trait_refs( cb: impl FnMut(TraitRef) -> Option, ) -> Option { let seen = iter::once(trait_ref.trait_id).collect(); - let mut stack = Vec::new(); - stack.push(trait_ref); - SuperTraits { db, seen, stack }.find_map(cb) + SuperTraits { db, seen, stack: vec![trait_ref] }.find_map(cb) } struct SuperTraits<'a> { diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 5d81e8cfeac..7384390f28b 100644 --- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -148,7 +148,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) return None; } - let variants_of_enums = vec![variants.clone(); len]; + let variants_of_enums = vec![variants; len]; let missing_pats = variants_of_enums .into_iter() diff --git a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs index c82a3b53032..5f7056b9c1c 100644 --- a/crates/ide-assists/src/handlers/convert_let_else_to_match.rs +++ b/crates/ide-assists/src/handlers/convert_let_else_to_match.rs @@ -5,6 +5,88 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; +// Assist: convert_let_else_to_match +// +// Converts let-else statement to let statement and match expression. +// +// ``` +// fn main() { +// let Ok(mut x) = f() else$0 { return }; +// } +// ``` +// -> +// ``` +// fn main() { +// let mut x = match f() { +// Ok(x) => x, +// _ => return, +// }; +// } +// ``` +pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + // should focus on else token to trigger + let let_stmt = ctx + .find_token_syntax_at_offset(T![else]) + .and_then(|it| it.parent()?.parent()) + .or_else(|| ctx.find_token_syntax_at_offset(T![let])?.parent())?; + let let_stmt = LetStmt::cast(let_stmt)?; + let let_else_block = let_stmt.let_else()?.block_expr()?; + let let_init = let_stmt.initializer()?; + if let_stmt.ty().is_some() { + // don't support let with type annotation + return None; + } + let pat = let_stmt.pat()?; + let mut binders = Vec::new(); + binders_in_pat(&mut binders, &pat, &ctx.sema)?; + + let target = let_stmt.syntax().text_range(); + acc.add( + AssistId("convert_let_else_to_match", AssistKind::RefactorRewrite), + "Convert let-else to let and match", + target, + |edit| { + let indent_level = let_stmt.indent_level().0 as usize; + let indent = " ".repeat(indent_level); + let indent1 = " ".repeat(indent_level + 1); + + let binders_str = binders_to_str(&binders, false); + let binders_str_mut = binders_to_str(&binders, true); + + let init_expr = let_init.syntax().text(); + let mut pat_no_mut = pat.syntax().text().to_string(); + // remove the mut from the pattern + for (b, ismut) in binders.iter() { + if *ismut { + pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string()); + } + } + + let only_expr = let_else_block.statements().next().is_none(); + let branch2 = match &let_else_block.tail_expr() { + Some(tail) if only_expr => format!("{tail},"), + _ => let_else_block.syntax().text().to_string(), + }; + let replace = if binders.is_empty() { + format!( + "match {init_expr} {{ +{indent1}{pat_no_mut} => {binders_str} +{indent1}_ => {branch2} +{indent}}}" + ) + } else { + format!( + "let {binders_str_mut} = match {init_expr} {{ +{indent1}{pat_no_mut} => {binders_str}, +{indent1}_ => {branch2} +{indent}}};" + ) + }; + edit.replace(target, replace); + }, + ) +} + /// Gets a list of binders in a pattern, and whether they are mut. fn binders_in_pat( acc: &mut Vec<(Name, bool)>, @@ -97,85 +179,6 @@ fn binders_to_str(binders: &[(Name, bool)], addmut: bool) -> String { } } -// Assist: convert_let_else_to_match -// -// Converts let-else statement to let statement and match expression. -// -// ``` -// fn main() { -// let Ok(mut x) = f() else$0 { return }; -// } -// ``` -// -> -// ``` -// fn main() { -// let mut x = match f() { -// Ok(x) => x, -// _ => return, -// }; -// } -// ``` -pub(crate) fn convert_let_else_to_match(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - // should focus on else token to trigger - let else_token = ctx.find_token_syntax_at_offset(T![else])?; - let let_stmt = LetStmt::cast(else_token.parent()?.parent()?)?; - let let_else_block = let_stmt.let_else()?.block_expr()?; - let let_init = let_stmt.initializer()?; - if let_stmt.ty().is_some() { - // don't support let with type annotation - return None; - } - let pat = let_stmt.pat()?; - let mut binders = Vec::new(); - binders_in_pat(&mut binders, &pat, &ctx.sema)?; - - let target = let_stmt.syntax().text_range(); - acc.add( - AssistId("convert_let_else_to_match", AssistKind::RefactorRewrite), - "Convert let-else to let and match", - target, - |edit| { - let indent_level = let_stmt.indent_level().0 as usize; - let indent = " ".repeat(indent_level); - let indent1 = " ".repeat(indent_level + 1); - - let binders_str = binders_to_str(&binders, false); - let binders_str_mut = binders_to_str(&binders, true); - - let init_expr = let_init.syntax().text(); - let mut pat_no_mut = pat.syntax().text().to_string(); - // remove the mut from the pattern - for (b, ismut) in binders.iter() { - if *ismut { - pat_no_mut = pat_no_mut.replace(&format!("mut {b}"), &b.to_string()); - } - } - - let only_expr = let_else_block.statements().next().is_none(); - let branch2 = match &let_else_block.tail_expr() { - Some(tail) if only_expr => format!("{tail},"), - _ => let_else_block.syntax().text().to_string(), - }; - let replace = if binders.is_empty() { - format!( - "match {init_expr} {{ -{indent1}{pat_no_mut} => {binders_str} -{indent1}_ => {branch2} -{indent}}}" - ) - } else { - format!( - "let {binders_str_mut} = match {init_expr} {{ -{indent1}{pat_no_mut} => {binders_str}, -{indent1}_ => {branch2} -{indent}}};" - ) - }; - edit.replace(target, replace); - }, - ) -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/ide-assists/src/handlers/convert_match_to_let_else.rs b/crates/ide-assists/src/handlers/convert_match_to_let_else.rs index 7f2c01772ba..fc6236a1755 100644 --- a/crates/ide-assists/src/handlers/convert_match_to_let_else.rs +++ b/crates/ide-assists/src/handlers/convert_match_to_let_else.rs @@ -16,7 +16,7 @@ // ``` // # //- minicore: option // fn foo(opt: Option<()>) { -// let val = $0match opt { +// let val$0 = match opt { // Some(it) => it, // None => return, // }; @@ -30,7 +30,10 @@ // ``` pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let let_stmt: ast::LetStmt = ctx.find_node_at_offset()?; - let binding = let_stmt.pat()?; + let pat = let_stmt.pat()?; + if ctx.offset() > pat.syntax().text_range().end() { + return None; + } let Some(ast::Expr::MatchExpr(initializer)) = let_stmt.initializer() else { return None }; let initializer_expr = initializer.expr()?; @@ -56,7 +59,7 @@ pub(crate) fn convert_match_to_let_else(acc: &mut Assists, ctx: &AssistContext<' let_stmt.syntax().text_range(), |builder| { let extracting_arm_pat = - rename_variable(&extracting_arm_pat, &extracted_variable_positions, binding); + rename_variable(&extracting_arm_pat, &extracted_variable_positions, pat); builder.replace( let_stmt.syntax().text_range(), format!("let {extracting_arm_pat} = {initializer_expr} else {diverging_arm_expr};"), @@ -161,7 +164,7 @@ fn should_not_be_applicable_for_non_diverging_match() { r#" //- minicore: option fn foo(opt: Option<()>) { - let val = $0match opt { + let val$0 = match opt { Some(it) => it, None => (), }; @@ -211,7 +214,7 @@ fn should_not_be_applicable_if_extracting_arm_is_not_an_identity_expr() { r#" //- minicore: option fn foo(opt: Option) { - let val = $0match opt { + let val$0 = match opt { Some(it) => it + 1, None => return, }; @@ -224,7 +227,7 @@ fn foo(opt: Option) { r#" //- minicore: option fn foo(opt: Option<()>) { - let val = $0match opt { + let val$0 = match opt { Some(it) => { let _ = 1 + 1; it @@ -244,7 +247,7 @@ fn should_not_be_applicable_if_extracting_arm_has_guard() { r#" //- minicore: option fn foo(opt: Option<()>) { - let val = $0match opt { + let val$0 = match opt { Some(it) if 2 > 1 => it, None => return, }; @@ -260,7 +263,7 @@ fn basic_pattern() { r#" //- minicore: option fn foo(opt: Option<()>) { - let val = $0match opt { + let val$0 = match opt { Some(it) => it, None => return, }; @@ -281,7 +284,7 @@ fn keeps_modifiers() { r#" //- minicore: option fn foo(opt: Option<()>) { - let ref mut val = $0match opt { + let ref mut val$0 = match opt { Some(it) => it, None => return, }; @@ -302,7 +305,7 @@ fn nested_pattern() { r#" //- minicore: option, result fn foo(opt: Option>) { - let val = $0match opt { + let val$0 = match opt { Some(Ok(it)) => it, _ => return, }; @@ -324,7 +327,7 @@ fn works_with_any_diverging_block() { //- minicore: option fn foo(opt: Option<()>) { loop { - let val = $0match opt { + let val$0 = match opt { Some(it) => it, None => break, }; @@ -346,7 +349,7 @@ fn foo(opt: Option<()>) { //- minicore: option fn foo(opt: Option<()>) { loop { - let val = $0match opt { + let val$0 = match opt { Some(it) => it, None => continue, }; @@ -370,7 +373,7 @@ fn panic() -> ! {} fn foo(opt: Option<()>) { loop { - let val = $0match opt { + let val$0 = match opt { Some(it) => it, None => panic(), }; @@ -401,7 +404,7 @@ struct Point { } fn foo(opt: Option) { - let val = $0match opt { + let val$0 = match opt { Some(Point { x: 0, y }) => y, _ => return, }; @@ -427,7 +430,7 @@ fn renames_whole_binding() { r#" //- minicore: option fn foo(opt: Option) -> Option { - let val = $0match opt { + let val$0 = match opt { it @ Some(42) => it, _ => return None, }; @@ -450,7 +453,7 @@ fn complex_pattern() { r#" //- minicore: option fn f() { - let (x, y) = $0match Some((0, 1)) { + let (x, y)$0 = match Some((0, 1)) { Some(it) => it, None => return, }; @@ -471,7 +474,7 @@ fn diverging_block() { r#" //- minicore: option fn f() { - let x = $0match Some(()) { + let x$0 = match Some(()) { Some(it) => it, None => {//comment println!("nope"); diff --git a/crates/ide-assists/src/handlers/generate_constant.rs b/crates/ide-assists/src/handlers/generate_constant.rs index ccdfcb0d9e4..57bb679729f 100644 --- a/crates/ide-assists/src/handlers/generate_constant.rs +++ b/crates/ide-assists/src/handlers/generate_constant.rs @@ -106,10 +106,10 @@ fn get_text_for_generate_constant( let mut text = format!("{vis}const {constant_token}: {type_name} = $0;"); while let Some(name_ref) = not_exist_name_ref.pop() { let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " }; - text = text.replace("\n", "\n "); + text = text.replace('\n', "\n "); text = format!("{vis}mod {name_ref} {{{text}\n}}"); } - Some(text.replace("\n", &format!("\n{indent}"))) + Some(text.replace('\n', &format!("\n{indent}"))) } fn target_data_for_generate_constant( @@ -131,7 +131,7 @@ fn target_data_for_generate_constant( let siblings_has_newline = l_curly_token .siblings_with_tokens(Direction::Next) - .find(|it| it.kind() == SyntaxKind::WHITESPACE && it.to_string().contains("\n")) + .find(|it| it.kind() == SyntaxKind::WHITESPACE && it.to_string().contains('\n')) .is_some(); let post_string = if siblings_has_newline { format!("{indent}") } else { format!("\n{indent}") }; diff --git a/crates/ide-assists/src/handlers/reorder_fields.rs b/crates/ide-assists/src/handlers/reorder_fields.rs index 58dcaf9a221..cd977a68a67 100644 --- a/crates/ide-assists/src/handlers/reorder_fields.rs +++ b/crates/ide-assists/src/handlers/reorder_fields.rs @@ -20,9 +20,10 @@ // const test: Foo = Foo {foo: 1, bar: 0} // ``` pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let record = ctx.find_node_at_offset::>()?; + let path = ctx.find_node_at_offset::()?; + let record = + path.syntax().parent().and_then(>::cast)?; - let path = record.as_ref().either(|it| it.path(), |it| it.path())?; let ranks = compute_fields_ranks(&path, ctx)?; let get_rank_of_field = |of: Option<_>| *ranks.get(&of.unwrap_or_default()).unwrap_or(&usize::MAX); diff --git a/crates/ide-assists/src/handlers/unwrap_block.rs b/crates/ide-assists/src/handlers/unwrap_block.rs index 33b19a354b9..939055f148c 100644 --- a/crates/ide-assists/src/handlers/unwrap_block.rs +++ b/crates/ide-assists/src/handlers/unwrap_block.rs @@ -51,15 +51,11 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option let replaced = match list.syntax().last_child() { Some(last) => { let stmts: Vec = list.statements().collect(); - let initializer = ast::Expr::cast(last.clone())?; + let initializer = ast::Expr::cast(last)?; let let_stmt = make::let_stmt(pattern, ty, Some(initializer)); if stmts.len() > 0 { let block = make::block_expr(stmts, None); - format!( - "{}\n {}", - update_expr_string(block.to_string()), - let_stmt.to_string() - ) + format!("{}\n {}", update_expr_string(block.to_string()), let_stmt) } else { let_stmt.to_string() } diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs index aff11367de9..dd8705d797c 100644 --- a/crates/ide-assists/src/tests/generated.rs +++ b/crates/ide-assists/src/tests/generated.rs @@ -439,7 +439,7 @@ fn doctest_convert_match_to_let_else() { r#####" //- minicore: option fn foo(opt: Option<()>) { - let val = $0match opt { + let val$0 = match opt { Some(it) => it, None => return, }; diff --git a/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/crates/ide-diagnostics/src/handlers/unlinked_file.rs index 3d45a75913a..145e18c5c48 100644 --- a/crates/ide-diagnostics/src/handlers/unlinked_file.rs +++ b/crates/ide-diagnostics/src/handlers/unlinked_file.rs @@ -92,7 +92,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option> { // if we aren't adding to a crate root, walk backwards such that we support `#[path = ...]` overrides if possible // build all parent paths of the form `../module_name/mod.rs` and `../module_name.rs` - let paths = iter::successors(Some(parent.clone()), |prev| prev.parent()).filter_map(|path| { + let paths = iter::successors(Some(parent), |prev| prev.parent()).filter_map(|path| { let parent = path.parent()?; let (name, _) = path.name_and_extension()?; Some(([parent.join(&format!("{name}.rs"))?, path.join("mod.rs")?], name.to_owned())) diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index 3e5e40750e9..1c848090b6a 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -66,7 +66,6 @@ pub fn run(self) -> Result<()> { .as_os_str() .to_str() .ok_or(anyhow::anyhow!("Unable to normalize project_root path"))? - .to_string() ), text_document_encoding: scip_types::TextEncoding::UTF8.into(), special_fields: Default::default(), @@ -212,7 +211,7 @@ fn new_descriptor_str( fn new_descriptor(name: Name, suffix: scip_types::descriptor::Suffix) -> scip_types::Descriptor { let mut name = name.to_string(); - if name.contains("'") { + if name.contains('\'') { name = format!("`{name}`"); } diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 7d97b69f8ea..2b9dfecceff 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -279,7 +279,7 @@ fn completion_item( let mut lsp_item = lsp_types::CompletionItem { label: item.label.to_string(), - detail: item.detail.map(|it| it.to_string()), + detail: item.detail, filter_text: Some(lookup), kind: Some(completion_item_kind(item.kind)), text_edit: Some(text_edit),