Critical: Use of 'unsafe' keyword bypasses Rust's safety guarantees. Requires careful auditing, clear justification (FFI, specific optimizations), and minimal scope.
unsafe fn deallocate(&self, ptr: NonNull<u8>);
1use hir::HasSource;2use syntax::{3 Edition,4 ast::{self, AstNode, syntax_factory::SyntaxFactory},5 syntax_editor::{Position, SyntaxEditor},6};78use crate::{9 AssistId,10 assist_context::{AssistContext, Assists},11 utils::{12 DefaultMethods, IgnoreAssocItems, add_trait_assoc_items_to_impl, filter_assoc_items,13 gen_trait_fn_body,14 },15};1617// Assist: add_impl_missing_members18//19// Adds scaffold for required impl members.20//21// ```22// trait Trait<T> {23// type X;24// fn foo(&self) -> T;25// fn bar(&self) {}26// }27//28// impl Trait<u32> for () {$029//30// }31// ```32// ->33// ```34// trait Trait<T> {35// type X;36// fn foo(&self) -> T;37// fn bar(&self) {}38// }39//40// impl Trait<u32> for () {41// $0type X;42//43// fn foo(&self) -> u32 {44// todo!()45// }46// }47// ```48pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {49 add_missing_impl_members_inner(50 acc,51 ctx,52 DefaultMethods::No,53 IgnoreAssocItems::DocHiddenAttrPresent,54 "add_impl_missing_members",55 "Implement missing members",56 )57}5859// Assist: add_impl_default_members60//61// Adds scaffold for overriding default impl members.62//63// ```64// trait Trait {65// type X;66// fn foo(&self);67// fn bar(&self) {}68// }69//70// impl Trait for () {71// type X = ();72// fn foo(&self) {}$073// }74// ```75// ->76// ```77// trait Trait {78// type X;79// fn foo(&self);80// fn bar(&self) {}81// }82//83// impl Trait for () {84// type X = ();85// fn foo(&self) {}86//87// $0fn bar(&self) {}88// }89// ```90pub(crate) fn add_missing_default_members(91 acc: &mut Assists,92 ctx: &AssistContext<'_>,93) -> Option<()> {94 add_missing_impl_members_inner(95 acc,96 ctx,97 DefaultMethods::Only,98 IgnoreAssocItems::DocHiddenAttrPresent,99 "add_impl_default_members",100 "Implement default members",101 )102}103104fn add_missing_impl_members_inner(105 acc: &mut Assists,106 ctx: &AssistContext<'_>,107 mode: DefaultMethods,108 ignore_items: IgnoreAssocItems,109 assist_id: &'static str,110 label: &'static str,111) -> Option<()> {112 let _p = tracing::info_span!("add_missing_impl_members_inner").entered();113 let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;114 let impl_ = ctx.sema.to_def(&impl_def)?;115116 if ctx.token_at_offset().all(|t| {117 t.parent_ancestors()118 .take_while(|node| node != impl_def.syntax())119 .any(|s| ast::BlockExpr::can_cast(s.kind()) || ast::ParamList::can_cast(s.kind()))120 }) {121 return None;122 }123124 let target_scope = ctx.sema.scope(impl_def.syntax())?;125 let trait_ref = impl_.trait_ref(ctx.db())?;126 let trait_ = trait_ref.trait_();127128 let mut ign_item = ignore_items;129130 if let IgnoreAssocItems::DocHiddenAttrPresent = ignore_items {131 // Relax condition for local crates.132 let db = ctx.db();133 if trait_.module(db).krate(db).origin(db).is_local() {134 ign_item = IgnoreAssocItems::No;135 }136 }137138 let missing_items = filter_assoc_items(139 &ctx.sema,140 &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def),141 mode,142 ign_item,143 );144145 if missing_items.is_empty() {146 return None;147 }148149 let target = impl_def.syntax().text_range();150 acc.add(AssistId::quick_fix(assist_id), label, target, |edit| {151 let editor = edit.make_editor(impl_def.syntax());152 let make = editor.make();153 let new_item = add_trait_assoc_items_to_impl(154 make,155 &ctx.sema,156 ctx.config,157 &missing_items,158 trait_,159 &impl_def,160 &target_scope,161 );162163 let Some((first_new_item, other_items)) = new_item.split_first() else {164 return;165 };166167 let mut first_new_item = if let DefaultMethods::No = mode168 && let ast::AssocItem::Fn(func) = &first_new_item169 && let Some(body) = try_gen_trait_body(170 make,171 ctx,172 func,173 trait_ref,174 &impl_def,175 target_scope.krate().edition(ctx.sema.db),176 )177 && let Some(func_body) = func.body()178 {179 let (func_editor, _) = SyntaxEditor::new(first_new_item.syntax().clone());180 func_editor.replace(func_body.syntax(), body.syntax());181 ast::AssocItem::cast(func_editor.finish().new_root().clone())182 } else {183 Some(first_new_item.clone())184 };185186 let new_assoc_items = first_new_item187 .clone()188 .into_iter()189 .chain(other_items.iter().cloned())190 .collect::<Vec<_>>();191192 if let Some(assoc_item_list) = impl_def.assoc_item_list() {193 assoc_item_list.add_items(&editor, new_assoc_items);194 } else {195 let assoc_item_list = make.assoc_item_list(new_assoc_items);196 editor.insert_all(197 Position::after(impl_def.syntax()),198 vec![make.whitespace(" ").into(), assoc_item_list.syntax().clone().into()],199 );200 first_new_item = assoc_item_list.assoc_items().next();201 }202203 if let Some(cap) = ctx.config.snippet_cap {204 let mut placeholder = None;205 if let DefaultMethods::No = mode206 && let Some(ast::AssocItem::Fn(func)) = &first_new_item207 && let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)208 && m.syntax().text() == "todo!()"209 {210 placeholder = Some(m);211 }212213 if let Some(macro_call) = placeholder {214 let placeholder = edit.make_placeholder_snippet(cap);215 editor.add_annotation(macro_call.syntax(), placeholder);216 } else if let Some(first_new_item) = first_new_item {217 let tabstop = edit.make_tabstop_before(cap);218 editor.add_annotation(first_new_item.syntax(), tabstop);219 };220 };221 edit.add_file_edits(ctx.vfs_file_id(), editor);222 })223}224225fn try_gen_trait_body(226 make: &SyntaxFactory,227 ctx: &AssistContext<'_>,228 func: &ast::Fn,229 trait_ref: hir::TraitRef<'_>,230 impl_def: &ast::Impl,231 edition: Edition,232) -> Option<ast::BlockExpr> {233 let trait_path =234 make.ident_path(&trait_ref.trait_().name(ctx.db()).display(ctx.db(), edition).to_string());235 let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?;236 let adt = hir_ty.as_adt()?.source(ctx.db())?;237 gen_trait_fn_body(make, func, &trait_path, &adt.value, Some(trait_ref))238}239240#[cfg(test)]241mod tests {242 use crate::tests::{check_assist, check_assist_not_applicable};243244 use super::*;245246 #[test]247 fn test_add_missing_impl_members() {248 check_assist(249 add_missing_impl_members,250 r#"251trait Foo {252 type Output;253254 const CONST: usize = 42;255 const CONST_2: i32;256257 fn foo(&self);258 fn bar(&self);259 fn baz(&self);260}261262struct S;263264impl Foo for S {265 fn bar(&self) {}266$0267}"#,268 r#"269trait Foo {270 type Output;271272 const CONST: usize = 42;273 const CONST_2: i32;274275 fn foo(&self);276 fn bar(&self);277 fn baz(&self);278}279280struct S;281282impl Foo for S {283 fn bar(&self) {}284285 $0type Output;286287 const CONST_2: i32;288289 fn foo(&self) {290 todo!()291 }292293 fn baz(&self) {294 todo!()295 }296297}"#,298 );299 }300301 #[test]302 fn test_copied_overridden_members() {303 check_assist(304 add_missing_impl_members,305 r#"306trait Foo {307 fn foo(&self);308 fn bar(&self) -> bool { true }309 fn baz(&self) -> u32 { 42 }310}311312struct S;313314impl Foo for S {315 fn bar(&self) {}316$0317}"#,318 r#"319trait Foo {320 fn foo(&self);321 fn bar(&self) -> bool { true }322 fn baz(&self) -> u32 { 42 }323}324325struct S;326327impl Foo for S {328 fn bar(&self) {}329330 fn foo(&self) {331 ${0:todo!()}332 }333334}"#,335 );336 }337338 #[test]339 fn test_empty_impl_def() {340 check_assist(341 add_missing_impl_members,342 r#"343trait Foo { fn foo(&self); }344struct S;345impl Foo for S { $0 }"#,346 r#"347trait Foo { fn foo(&self); }348struct S;349impl Foo for S {350 fn foo(&self) {351 ${0:todo!()}352 }353}"#,354 );355 }356357 #[test]358 fn test_impl_def_without_braces_macro() {359 check_assist(360 add_missing_impl_members,361 r#"362trait Foo { fn foo(&self); }363struct S;364impl Foo for S$0"#,365 r#"366trait Foo { fn foo(&self); }367struct S;368impl Foo for S {369 fn foo(&self) {370 ${0:todo!()}371 }372}"#,373 );374 }375376 #[test]377 fn test_impl_def_without_braces_tabstop_first_item() {378 check_assist(379 add_missing_impl_members,380 r#"381trait Foo {382 type Output;383 fn foo(&self);384}385struct S;386impl Foo for S { $0 }"#,387 r#"388trait Foo {389 type Output;390 fn foo(&self);391}392struct S;393impl Foo for S {394 $0type Output;395396 fn foo(&self) {397 todo!()398 }399}"#,400 );401 }402403 #[test]404 fn fill_in_type_params_1() {405 check_assist(406 add_missing_impl_members,407 r#"408trait Foo<T> { fn foo(&self, t: T) -> &T; }409struct S;410impl Foo<u32> for S { $0 }"#,411 r#"412trait Foo<T> { fn foo(&self, t: T) -> &T; }413struct S;414impl Foo<u32> for S {415 fn foo(&self, t: u32) -> &u32 {416 ${0:todo!()}417 }418}"#,419 );420 }421422 #[test]423 fn fill_in_type_params_2() {424 check_assist(425 add_missing_impl_members,426 r#"427trait Foo<T> { fn foo(&self, t: T) -> &T; }428struct S;429impl<U> Foo<U> for S { $0 }"#,430 r#"431trait Foo<T> { fn foo(&self, t: T) -> &T; }432struct S;433impl<U> Foo<U> for S {434 fn foo(&self, t: U) -> &U {435 ${0:todo!()}436 }437}"#,438 );439 }440441 #[test]442 fn test_lifetime_substitution() {443 check_assist(444 add_missing_impl_members,445 r#"446pub trait Trait<'a, 'b, A, B, C> {447 fn foo(&self, one: &'a A, another: &'b B) -> &'a C;448}449450impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () {$0}"#,451 r#"452pub trait Trait<'a, 'b, A, B, C> {453 fn foo(&self, one: &'a A, another: &'b B) -> &'a C;454}455456impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () {457 fn foo(&self, one: &'x T, another: &'y V) -> &'x U {458 ${0:todo!()}459 }460}"#,461 );462 }463464 #[test]465 fn test_lifetime_substitution_with_body() {466 check_assist(467 add_missing_default_members,468 r#"469pub trait Trait<'a, 'b, A, B, C: Default> {470 fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) {471 let value: &'a i32 = &0;472 (C::default(), value)473 }474}475476impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () {$0}"#,477 r#"478pub trait Trait<'a, 'b, A, B, C: Default> {479 fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) {480 let value: &'a i32 = &0;481 (C::default(), value)482 }483}484485impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () {486 $0fn foo(&self, _one: &'x T, _another: &'y V) -> (U, &'x i32) {487 let value: &'x i32 = &0;488 (<U>::default(), value)489 }490}"#,491 );492 }493494 #[test]495 fn test_const_substitution() {496 check_assist(497 add_missing_default_members,498 r#"499struct Bar<const N: usize> {500 bar: [i32, N]501}502503trait Foo<const N: usize, T> {504 fn get_n_sq(&self, arg: &T) -> usize { N * N }505 fn get_array(&self, arg: Bar<N>) -> [i32; N] { [1; N] }506}507508struct S<T> {509 wrapped: T510}511512impl<const X: usize, Y, Z> Foo<X, Z> for S<Y> {513 $0514}"#,515 r#"516struct Bar<const N: usize> {517 bar: [i32, N]518}519520trait Foo<const N: usize, T> {521 fn get_n_sq(&self, arg: &T) -> usize { N * N }522 fn get_array(&self, arg: Bar<N>) -> [i32; N] { [1; N] }523}524525struct S<T> {526 wrapped: T527}528529impl<const X: usize, Y, Z> Foo<X, Z> for S<Y> {530 $0fn get_n_sq(&self, arg: &Z) -> usize { X * X }531532 fn get_array(&self, arg: Bar<X>) -> [i32; X] { [1; X] }533}"#,534 )535 }536537 #[test]538 fn test_const_substitution_2() {539 check_assist(540 add_missing_default_members,541 r#"542trait Foo<const N: usize, const M: usize, T> {543 fn get_sum(&self, arg: &T) -> usize { N + M }544}545546impl<X> Foo<42, {20 + 22}, X> for () {547 $0548}"#,549 r#"550trait Foo<const N: usize, const M: usize, T> {551 fn get_sum(&self, arg: &T) -> usize { N + M }552}553554impl<X> Foo<42, {20 + 22}, X> for () {555 $0fn get_sum(&self, arg: &X) -> usize { 42 + {20 + 22} }556}"#,557 )558 }559560 #[test]561 fn test_const_substitution_with_defaults() {562 check_assist(563 add_missing_default_members,564 r#"565trait Foo<T, const N: usize = 42, const M: bool = false, const P: char = 'a'> {566 fn get_n(&self) -> usize { N }567 fn get_m(&self) -> bool { M }568 fn get_p(&self) -> char { P }569 fn get_array(&self, arg: &T) -> [bool; N] { [M; N] }570}571572impl<X> Foo<X> for () {573 $0574}"#,575 r#"576trait Foo<T, const N: usize = 42, const M: bool = false, const P: char = 'a'> {577 fn get_n(&self) -> usize { N }578 fn get_m(&self) -> bool { M }579 fn get_p(&self) -> char { P }580 fn get_array(&self, arg: &T) -> [bool; N] { [M; N] }581}582583impl<X> Foo<X> for () {584 $0fn get_n(&self) -> usize { 42 }585586 fn get_m(&self) -> bool { false }587588 fn get_p(&self) -> char { 'a' }589590 fn get_array(&self, arg: &X) -> [bool; 42] { [false; 42] }591}"#,592 );593 }594595 #[test]596 fn test_const_substitution_with_defaults_2() {597 check_assist(598 add_missing_impl_members,599 r#"600mod m {601 pub const LEN: usize = 42;602 pub trait Foo<const M: usize = LEN, const N: usize = M, T = [bool; N]> {603 fn get_t(&self) -> T;604 }605}606607impl m::Foo for () {608 $0609}"#,610 r#"611mod m {612 pub const LEN: usize = 42;613 pub trait Foo<const M: usize = LEN, const N: usize = M, T = [bool; N]> {614 fn get_t(&self) -> T;615 }616}617618impl m::Foo for () {619 fn get_t(&self) -> [bool; m::LEN] {620 ${0:todo!()}621 }622}"#,623 )624 }625626 #[test]627 fn test_const_substitution_with_defaults_3() {628 check_assist(629 add_missing_default_members,630 r#"631mod m {632 pub const VAL: usize = 0;633634 pub trait Foo<const N: usize = {40 + 2}, const M: usize = {VAL + 1}> {635 fn get_n(&self) -> usize { N }636 fn get_m(&self) -> usize { M }637 }638}639640impl m::Foo for () {641 $0642}"#,643 r#"644mod m {645 pub const VAL: usize = 0;646647 pub trait Foo<const N: usize = {40 + 2}, const M: usize = {VAL + 1}> {648 fn get_n(&self) -> usize { N }649 fn get_m(&self) -> usize { M }650 }651}652653impl m::Foo for () {654 $0fn get_n(&self) -> usize { N }655656 fn get_m(&self) -> usize { M }657}"#,658 )659 }660661 #[test]662 fn test_cursor_after_empty_impl_def() {663 check_assist(664 add_missing_impl_members,665 r#"666trait Foo { fn foo(&self); }667struct S;668impl Foo for S {}$0"#,669 r#"670trait Foo { fn foo(&self); }671struct S;672impl Foo for S {673 fn foo(&self) {674 ${0:todo!()}675 }676}"#,677 )678 }679680 #[test]681 fn test_qualify_path_1() {682 check_assist(683 add_missing_impl_members,684 r#"685mod foo {686 pub struct Bar;687 pub trait Foo { fn foo(&self, bar: Bar); }688}689struct S;690impl foo::Foo for S { $0 }"#,691 r#"692mod foo {693 pub struct Bar;694 pub trait Foo { fn foo(&self, bar: Bar); }695}696struct S;697impl foo::Foo for S {698 fn foo(&self, bar: foo::Bar) {699 ${0:todo!()}700 }701}"#,702 );703 }704705 #[test]706 fn test_qualify_path_2() {707 check_assist(708 add_missing_impl_members,709 r#"710mod foo {711 pub mod bar {712 pub struct Bar;713 pub trait Foo { fn foo(&self, bar: Bar); }714 }715}716717use foo::bar;718719struct S;720impl bar::Foo for S { $0 }"#,721 r#"722mod foo {723 pub mod bar {724 pub struct Bar;725 pub trait Foo { fn foo(&self, bar: Bar); }726 }727}728729use foo::bar;730731struct S;732impl bar::Foo for S {733 fn foo(&self, bar: bar::Bar) {734 ${0:todo!()}735 }736}"#,737 );738 }739740 #[test]741 fn test_qualify_path_generic() {742 check_assist(743 add_missing_impl_members,744 r#"745mod foo {746 pub struct Bar<T>;747 pub trait Foo { fn foo(&self, bar: Bar<u32>); }748}749struct S;750impl foo::Foo for S { $0 }"#,751 r#"752mod foo {753 pub struct Bar<T>;754 pub trait Foo { fn foo(&self, bar: Bar<u32>); }755}756struct S;757impl foo::Foo for S {758 fn foo(&self, bar: foo::Bar<u32>) {759 ${0:todo!()}760 }761}"#,762 );763 }764765 #[test]766 fn test_qualify_path_and_substitute_param() {767 check_assist(768 add_missing_impl_members,769 r#"770mod foo {771 pub struct Bar<T>;772 pub trait Foo<T> { fn foo(&self, bar: Bar<T>); }773}774struct S;775impl foo::Foo<u32> for S { $0 }"#,776 r#"777mod foo {778 pub struct Bar<T>;779 pub trait Foo<T> { fn foo(&self, bar: Bar<T>); }780}781struct S;782impl foo::Foo<u32> for S {783 fn foo(&self, bar: foo::Bar<u32>) {784 ${0:todo!()}785 }786}"#,787 );788 }789790 #[test]791 fn test_substitute_param_no_qualify() {792 // when substituting params, the substituted param should not be qualified!793 check_assist(794 add_missing_impl_members,795 r#"796mod foo {797 pub trait Foo<T> { fn foo(&self, bar: T); }798 pub struct Param;799}800struct Param;801struct S;802impl foo::Foo<Param> for S { $0 }"#,803 r#"804mod foo {805 pub trait Foo<T> { fn foo(&self, bar: T); }806 pub struct Param;807}808struct Param;809struct S;810impl foo::Foo<Param> for S {811 fn foo(&self, bar: Param) {812 ${0:todo!()}813 }814}"#,815 );816 }817818 #[test]819 fn test_qualify_path_associated_item() {820 check_assist(821 add_missing_impl_members,822 r#"823mod foo {824 pub struct Bar<T>;825 impl Bar<T> { type Assoc = u32; }826 pub trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }827}828struct S;829impl foo::Foo for S { $0 }"#,830 r#"831mod foo {832 pub struct Bar<T>;833 impl Bar<T> { type Assoc = u32; }834 pub trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }835}836struct S;837impl foo::Foo for S {838 fn foo(&self, bar: foo::Bar<u32>::Assoc) {839 ${0:todo!()}840 }841}"#,842 );843 }844845 #[test]846 fn test_qualify_path_nested() {847 check_assist(848 add_missing_impl_members,849 r#"850mod foo {851 pub struct Bar<T>;852 pub struct Baz;853 pub trait Foo { fn foo(&self, bar: Bar<Baz>); }854}855struct S;856impl foo::Foo for S { $0 }"#,857 r#"858mod foo {859 pub struct Bar<T>;860 pub struct Baz;861 pub trait Foo { fn foo(&self, bar: Bar<Baz>); }862}863struct S;864impl foo::Foo for S {865 fn foo(&self, bar: foo::Bar<foo::Baz>) {866 ${0:todo!()}867 }868}"#,869 );870 }871872 #[test]873 fn test_qualify_path_fn_trait_notation() {874 check_assist(875 add_missing_impl_members,876 r#"877mod foo {878 pub trait Fn<Args> { type Output; }879 pub trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }880}881struct S;882impl foo::Foo for S { $0 }"#,883 r#"884mod foo {885 pub trait Fn<Args> { type Output; }886 pub trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }887}888struct S;889impl foo::Foo for S {890 fn foo(&self, bar: dyn Fn(u32) -> i32) {891 ${0:todo!()}892 }893}"#,894 );895 }896897 #[test]898 fn test_empty_trait() {899 check_assist_not_applicable(900 add_missing_impl_members,901 r#"902trait Foo;903struct S;904impl Foo for S { $0 }"#,905 )906 }907908 #[test]909 fn test_ignore_unnamed_trait_members_and_default_methods() {910 check_assist_not_applicable(911 add_missing_impl_members,912 r#"913trait Foo {914 fn (arg: u32);915 fn valid(some: u32) -> bool { false }916}917struct S;918impl Foo for S { $0 }"#,919 )920 }921922 #[test]923 fn test_with_docstring_and_attrs() {924 check_assist(925 add_missing_impl_members,926 r#"927#[doc(alias = "test alias")]928trait Foo {929 /// doc string930 type Output;931932 #[must_use]933 fn foo(&self);934}935struct S;936impl Foo for S {}$0"#,937 r#"938#[doc(alias = "test alias")]939trait Foo {940 /// doc string941 type Output;942943 #[must_use]944 fn foo(&self);945}946struct S;947impl Foo for S {948 $0type Output;949950 fn foo(&self) {951 todo!()952 }953}"#,954 )955 }956957 #[test]958 fn test_default_methods() {959 check_assist(960 add_missing_default_members,961 r#"962trait Foo {963 type Output;964965 const CONST: usize = 42;966 const CONST_2: i32;967968 fn valid(some: u32) -> bool { false }969 fn foo(some: u32) -> bool;970}971struct S;972impl Foo for S { $0 }"#,973 r#"974trait Foo {975 type Output;976977 const CONST: usize = 42;978 const CONST_2: i32;979980 fn valid(some: u32) -> bool { false }981 fn foo(some: u32) -> bool;982}983struct S;984impl Foo for S {985 $0const CONST: usize = 42;986987 fn valid(some: u32) -> bool { false }988}"#,989 )990 }991992 #[test]993 fn test_generic_single_default_parameter() {994 check_assist(995 add_missing_impl_members,996 r#"997trait Foo<T = Self> {998 fn bar(&self, other: &T);999}10001001struct S;1002impl Foo for S { $0 }"#,1003 r#"1004trait Foo<T = Self> {1005 fn bar(&self, other: &T);1006}10071008struct S;1009impl Foo for S {1010 fn bar(&self, other: &Self) {1011 ${0:todo!()}1012 }1013}"#,1014 )1015 }10161017 #[test]1018 fn test_generic_default_parameter_is_second() {1019 check_assist(1020 add_missing_impl_members,1021 r#"1022trait Foo<T1, T2 = Self> {1023 fn bar(&self, this: &T1, that: &T2);1024}10251026struct S<T>;1027impl Foo<T> for S<T> { $0 }"#,1028 r#"1029trait Foo<T1, T2 = Self> {1030 fn bar(&self, this: &T1, that: &T2);1031}10321033struct S<T>;1034impl Foo<T> for S<T> {1035 fn bar(&self, this: &T, that: &Self) {1036 ${0:todo!()}1037 }1038}"#,1039 )1040 }10411042 #[test]1043 fn test_qualify_generic_default_parameter() {1044 check_assist(1045 add_missing_impl_members,1046 r#"1047mod m {1048 pub struct S;1049 pub trait Foo<T = S> {1050 fn bar(&self, other: &T);1051 }1052}10531054struct S;1055impl m::Foo for S { $0 }"#,1056 r#"1057mod m {1058 pub struct S;1059 pub trait Foo<T = S> {1060 fn bar(&self, other: &T);1061 }1062}10631064struct S;1065impl m::Foo for S {1066 fn bar(&self, other: &m::S) {1067 ${0:todo!()}1068 }1069}"#,1070 )1071 }10721073 #[test]1074 fn test_qualify_generic_default_parameter_2() {1075 check_assist(1076 add_missing_impl_members,1077 r#"1078mod m {1079 pub struct Wrapper<T, V> {1080 one: T,1081 another: V1082 };1083 pub struct S;1084 pub trait Foo<T = Wrapper<S, bool>> {1085 fn bar(&self, other: &T);1086 }1087}10881089struct S;1090impl m::Foo for S { $0 }"#,1091 r#"1092mod m {1093 pub struct Wrapper<T, V> {1094 one: T,1095 another: V1096 };1097 pub struct S;1098 pub trait Foo<T = Wrapper<S, bool>> {1099 fn bar(&self, other: &T);1100 }1101}11021103struct S;1104impl m::Foo for S {1105 fn bar(&self, other: &m::Wrapper<m::S, bool>) {1106 ${0:todo!()}1107 }1108}"#,1109 );1110 }11111112 #[test]1113 fn test_qualify_generic_default_parameter_3() {1114 check_assist(1115 add_missing_impl_members,1116 r#"1117mod m {1118 pub struct Wrapper<T, V> {1119 one: T,1120 another: V1121 };1122 pub struct S;1123 pub trait Foo<T = S, V = Wrapper<T, S>> {1124 fn bar(&self, other: &V);1125 }1126}11271128struct S;1129impl m::Foo for S { $0 }"#,1130 r#"1131mod m {1132 pub struct Wrapper<T, V> {1133 one: T,1134 another: V1135 };1136 pub struct S;1137 pub trait Foo<T = S, V = Wrapper<T, S>> {1138 fn bar(&self, other: &V);1139 }1140}11411142struct S;1143impl m::Foo for S {1144 fn bar(&self, other: &m::Wrapper<m::S, m::S>) {1145 ${0:todo!()}1146 }1147}"#,1148 );1149 }11501151 #[test]1152 fn test_assoc_type_bounds_are_removed() {1153 check_assist(1154 add_missing_impl_members,1155 r#"1156trait Tr {1157 type Ty: Copy + 'static;1158}11591160impl Tr for ()$0 {1161}"#,1162 r#"1163trait Tr {1164 type Ty: Copy + 'static;1165}11661167impl Tr for () {1168 $0type Ty;1169}"#,1170 )1171 }11721173 #[test]1174 fn test_whitespace_fixup_preserves_bad_tokens() {1175 check_assist(1176 add_missing_impl_members,1177 r#"1178trait Tr {1179 fn foo();1180}11811182impl Tr for ()$0 {1183 +++1184}"#,1185 r#"1186trait Tr {1187 fn foo();1188}11891190impl Tr for () {1191 fn foo() {1192 ${0:todo!()}1193 }1194 +++1195}"#,1196 )1197 }11981199 #[test]1200 fn test_whitespace_fixup_preserves_comments() {1201 check_assist(1202 add_missing_impl_members,1203 r#"1204trait Tr {1205 fn foo();1206}12071208impl Tr for ()$0 {1209 // very important1210}"#,1211 r#"1212trait Tr {1213 fn foo();1214}12151216impl Tr for () {1217 fn foo() {1218 ${0:todo!()}1219 }1220 // very important1221}"#,1222 )1223 }12241225 #[test]1226 fn weird_path() {1227 check_assist(1228 add_missing_impl_members,1229 r#"1230trait Test {1231 fn foo(&self, x: crate)1232}1233impl Test for () {1234 $01235}1236"#,1237 r#"1238trait Test {1239 fn foo(&self, x: crate)1240}1241impl Test for () {1242 fn foo(&self, x: crate) {1243 ${0:todo!()}1244 }1245}1246"#,1247 )1248 }12491250 #[test]1251 fn missing_generic_type() {1252 check_assist(1253 add_missing_impl_members,1254 r#"1255trait Foo<BAR> {1256 fn foo(&self, bar: BAR);1257}1258impl Foo for () {1259 $01260}1261"#,1262 r#"1263trait Foo<BAR> {1264 fn foo(&self, bar: BAR);1265}1266impl Foo for () {1267 fn foo(&self, bar: BAR) {1268 ${0:todo!()}1269 }1270}1271"#,1272 )1273 }12741275 #[test]1276 fn does_not_requalify_self_as_crate() {1277 check_assist(1278 add_missing_default_members,1279 r"1280struct Wrapper<T>(T);12811282trait T {1283 fn f(self) -> Wrapper<Self> {1284 Wrapper(self)1285 }1286}12871288impl T for () {1289 $01290}1291",1292 r"1293struct Wrapper<T>(T);12941295trait T {1296 fn f(self) -> Wrapper<Self> {1297 Wrapper(self)1298 }1299}13001301impl T for () {1302 $0fn f(self) -> Wrapper<Self> {1303 Wrapper(self)1304 }1305}1306",1307 );1308 }13091310 #[test]1311 fn test_default_body_generation() {1312 check_assist(1313 add_missing_impl_members,1314 r#"1315//- minicore: default1316struct Foo(usize);13171318impl Default for Foo {1319 $01320}1321"#,1322 r#"1323struct Foo(usize);13241325impl Default for Foo {1326 $0fn default() -> Self {1327 Self(Default::default())1328 }1329}1330"#,1331 )1332 }13331334 #[test]1335 fn test_from_macro() {1336 check_assist(1337 add_missing_default_members,1338 r#"1339macro_rules! foo {1340 () => {1341 trait FooB {1342 fn foo<'lt>(&'lt self) {}1343 }1344 }1345}1346foo!();1347struct Foo(usize);13481349impl FooB for Foo {1350 $01351}1352"#,1353 r#"1354macro_rules! foo {1355 () => {1356 trait FooB {1357 fn foo<'lt>(&'lt self) {}1358 }1359 }1360}1361foo!();1362struct Foo(usize);13631364impl FooB for Foo {1365 $0fn foo<'lt>(&'lt self){}1366}1367"#,1368 )1369 }13701371 #[test]1372 fn test_assoc_type_when_trait_with_same_name_in_scope() {1373 check_assist(1374 add_missing_impl_members,1375 r#"1376pub trait Foo {}13771378pub trait Types {1379 type Foo;1380}13811382pub trait Behavior<T: Types> {1383 fn reproduce(&self, foo: T::Foo);1384}13851386pub struct Impl;13871388impl<T: Types> Behavior<T> for Impl { $0 }"#,1389 r#"1390pub trait Foo {}13911392pub trait Types {1393 type Foo;1394}13951396pub trait Behavior<T: Types> {1397 fn reproduce(&self, foo: T::Foo);1398}13991400pub struct Impl;14011402impl<T: Types> Behavior<T> for Impl {1403 fn reproduce(&self, foo: <T as Types>::Foo) {1404 ${0:todo!()}1405 }1406}"#,1407 );1408 }14091410 #[test]1411 fn test_assoc_type_on_concrete_type() {1412 check_assist(1413 add_missing_impl_members,1414 r#"1415pub trait Types {1416 type Foo;1417}14181419impl Types for u32 {1420 type Foo = bool;1421}14221423pub trait Behavior<T: Types> {1424 fn reproduce(&self, foo: T::Foo);1425}14261427pub struct Impl;14281429impl Behavior<u32> for Impl { $0 }"#,1430 r#"1431pub trait Types {1432 type Foo;1433}14341435impl Types for u32 {1436 type Foo = bool;1437}14381439pub trait Behavior<T: Types> {1440 fn reproduce(&self, foo: T::Foo);1441}14421443pub struct Impl;14441445impl Behavior<u32> for Impl {1446 fn reproduce(&self, foo: <u32 as Types>::Foo) {1447 ${0:todo!()}1448 }1449}"#,1450 );1451 }14521453 #[test]1454 fn test_assoc_type_on_concrete_type_qualified() {1455 check_assist(1456 add_missing_impl_members,1457 r#"1458pub trait Types {1459 type Foo;1460}14611462impl Types for std::string::String {1463 type Foo = bool;1464}14651466pub trait Behavior<T: Types> {1467 fn reproduce(&self, foo: T::Foo);1468}14691470pub struct Impl;14711472impl Behavior<std::string::String> for Impl { $0 }"#,1473 r#"1474pub trait Types {1475 type Foo;1476}14771478impl Types for std::string::String {1479 type Foo = bool;1480}14811482pub trait Behavior<T: Types> {1483 fn reproduce(&self, foo: T::Foo);1484}14851486pub struct Impl;14871488impl Behavior<std::string::String> for Impl {1489 fn reproduce(&self, foo: <std::string::String as Types>::Foo) {1490 ${0:todo!()}1491 }1492}"#,1493 );1494 }14951496 #[test]1497 fn test_assoc_type_on_concrete_type_multi_option_ambiguous() {1498 check_assist(1499 add_missing_impl_members,1500 r#"1501pub trait Types {1502 type Foo;1503}15041505pub trait Types2 {1506 type Foo;1507}15081509impl Types for u32 {1510 type Foo = bool;1511}15121513impl Types2 for u32 {1514 type Foo = String;1515}15161517pub trait Behavior<T: Types + Types2> {1518 fn reproduce(&self, foo: <T as Types2>::Foo);1519}15201521pub struct Impl;15221523impl Behavior<u32> for Impl { $0 }"#,1524 r#"1525pub trait Types {1526 type Foo;1527}15281529pub trait Types2 {1530 type Foo;1531}15321533impl Types for u32 {1534 type Foo = bool;1535}15361537impl Types2 for u32 {1538 type Foo = String;1539}15401541pub trait Behavior<T: Types + Types2> {1542 fn reproduce(&self, foo: <T as Types2>::Foo);1543}15441545pub struct Impl;15461547impl Behavior<u32> for Impl {1548 fn reproduce(&self, foo: <u32 as Types2>::Foo) {1549 ${0:todo!()}1550 }1551}"#,1552 );1553 }15541555 #[test]1556 fn test_assoc_type_on_concrete_type_multi_option() {1557 check_assist(1558 add_missing_impl_members,1559 r#"1560pub trait Types {1561 type Foo;1562}15631564pub trait Types2 {1565 type Bar;1566}15671568impl Types for u32 {1569 type Foo = bool;1570}15711572impl Types2 for u32 {1573 type Bar = String;1574}15751576pub trait Behavior<T: Types + Types2> {1577 fn reproduce(&self, foo: T::Bar);1578}15791580pub struct Impl;15811582impl Behavior<u32> for Impl { $0 }"#,1583 r#"1584pub trait Types {1585 type Foo;1586}15871588pub trait Types2 {1589 type Bar;1590}15911592impl Types for u32 {1593 type Foo = bool;1594}15951596impl Types2 for u32 {1597 type Bar = String;1598}15991600pub trait Behavior<T: Types + Types2> {1601 fn reproduce(&self, foo: T::Bar);1602}16031604pub struct Impl;16051606impl Behavior<u32> for Impl {1607 fn reproduce(&self, foo: <u32 as Types2>::Bar) {1608 ${0:todo!()}1609 }1610}"#,1611 );1612 }16131614 #[test]1615 fn test_assoc_type_on_concrete_type_multi_option_foreign() {1616 check_assist(1617 add_missing_impl_members,1618 r#"1619mod bar {1620 pub trait Types2 {1621 type Bar;1622 }1623}16241625pub trait Types {1626 type Foo;1627}16281629impl Types for u32 {1630 type Foo = bool;1631}16321633impl bar::Types2 for u32 {1634 type Bar = String;1635}16361637pub trait Behavior<T: Types + bar::Types2> {1638 fn reproduce(&self, foo: T::Bar);1639}16401641pub struct Impl;16421643impl Behavior<u32> for Impl { $0 }"#,1644 r#"1645mod bar {1646 pub trait Types2 {1647 type Bar;1648 }1649}16501651pub trait Types {1652 type Foo;1653}16541655impl Types for u32 {1656 type Foo = bool;1657}16581659impl bar::Types2 for u32 {1660 type Bar = String;1661}16621663pub trait Behavior<T: Types + bar::Types2> {1664 fn reproduce(&self, foo: T::Bar);1665}16661667pub struct Impl;16681669impl Behavior<u32> for Impl {1670 fn reproduce(&self, foo: <u32 as bar::Types2>::Bar) {1671 ${0:todo!()}1672 }1673}"#,1674 );1675 }16761677 #[test]1678 fn test_transform_path_in_path_expr() {1679 check_assist(1680 add_missing_default_members,1681 r#"1682pub trait Const {1683 const FOO: u32;1684}16851686pub trait Trait<T: Const> {1687 fn foo() -> bool {1688 match T::FOO {1689 0 => true,1690 _ => false,1691 }1692 }1693}16941695impl Const for u32 {1696 const FOO: u32 = 1;1697}16981699struct Impl;17001701impl Trait<u32> for Impl { $0 }"#,1702 r#"1703pub trait Const {1704 const FOO: u32;1705}17061707pub trait Trait<T: Const> {1708 fn foo() -> bool {1709 match T::FOO {1710 0 => true,1711 _ => false,1712 }1713 }1714}17151716impl Const for u32 {1717 const FOO: u32 = 1;1718}17191720struct Impl;17211722impl Trait<u32> for Impl {1723 $0fn foo() -> bool {1724 match <u32 as Const>::FOO {1725 0 => true,1726 _ => false,1727 }1728 }1729}"#,1730 );1731 }17321733 #[test]1734 fn test_default_partial_eq() {1735 check_assist(1736 add_missing_default_members,1737 r#"1738//- minicore: eq1739struct SomeStruct {1740 data: usize,1741 field: (usize, usize),1742}1743impl PartialEq for SomeStruct {$0}1744"#,1745 r#"1746struct SomeStruct {1747 data: usize,1748 field: (usize, usize),1749}1750impl PartialEq for SomeStruct {1751 $0fn ne(&self, other: &Self) -> bool {1752 !self.eq(other)1753 }1754}1755"#,1756 );1757 }17581759 #[test]1760 fn test_partial_eq_body_when_types_semantically_match() {1761 check_assist(1762 add_missing_impl_members,1763 r#"1764//- minicore: eq1765struct S<T, U>(T, U);1766type Alias<T> = S<T, T>;1767impl<T> PartialEq<Alias<T>> for S<T, T> {$0}1768"#,1769 r#"1770struct S<T, U>(T, U);1771type Alias<T> = S<T, T>;1772impl<T> PartialEq<Alias<T>> for S<T, T> {1773 $0fn eq(&self, other: &Alias<T>) -> bool {1774 self.0 == other.0 && self.1 == other.11775 }1776}1777"#,1778 );1779 }17801781 #[test]1782 fn test_partial_eq_body_when_types_dont_match() {1783 check_assist(1784 add_missing_impl_members,1785 r#"1786//- minicore: eq1787struct S<T, U>(T, U);1788type Alias<T> = S<T, T>;1789impl<T> PartialEq<Alias<T>> for S<T, i32> {$0}1790"#,1791 r#"1792struct S<T, U>(T, U);1793type Alias<T> = S<T, T>;1794impl<T> PartialEq<Alias<T>> for S<T, i32> {1795 fn eq(&self, other: &Alias<T>) -> bool {1796 ${0:todo!()}1797 }1798}1799"#,1800 );1801 }18021803 #[test]1804 fn test_ignore_function_body() {1805 check_assist_not_applicable(1806 add_missing_default_members,1807 r#"1808trait Trait {1809 type X;1810 fn foo(&self);1811 fn bar(&self) {}1812}18131814impl Trait for () {1815 type X = u8;1816 fn foo(&self) {$01817 let x = 5;1818 }1819}"#,1820 )1821 }18221823 #[test]1824 fn test_ignore_param_list() {1825 check_assist_not_applicable(1826 add_missing_impl_members,1827 r#"1828trait Trait {1829 type X;1830 fn foo(&self);1831 fn bar(&self);1832}18331834impl Trait for () {1835 type X = u8;1836 fn foo(&self$0) {1837 let x = 5;1838 }1839}"#,1840 )1841 }18421843 #[test]1844 fn test_ignore_scope_inside_function() {1845 check_assist_not_applicable(1846 add_missing_impl_members,1847 r#"1848trait Trait {1849 type X;1850 fn foo(&self);1851 fn bar(&self);1852}18531854impl Trait for () {1855 type X = u8;1856 fn foo(&self) {1857 let x = async {$0 5 };1858 }1859}"#,1860 )1861 }18621863 #[test]1864 fn test_apply_outside_function() {1865 check_assist(1866 add_missing_default_members,1867 r#"1868trait Trait {1869 type X;1870 fn foo(&self);1871 fn bar(&self) {}1872}18731874impl Trait for () {1875 type X = u8;1876 fn foo(&self)$0 {}1877}"#,1878 r#"1879trait Trait {1880 type X;1881 fn foo(&self);1882 fn bar(&self) {}1883}18841885impl Trait for () {1886 type X = u8;1887 fn foo(&self) {}18881889 $0fn bar(&self) {}1890}"#,1891 )1892 }18931894 #[test]1895 fn test_works_inside_function() {1896 check_assist(1897 add_missing_impl_members,1898 r#"1899trait Tr {1900 fn method();1901}1902fn main() {1903 struct S;1904 impl Tr for S {1905 $01906 }1907}1908"#,1909 r#"1910trait Tr {1911 fn method();1912}1913fn main() {1914 struct S;1915 impl Tr for S {1916 fn method() {1917 ${0:todo!()}1918 }1919 }1920}1921"#,1922 );1923 }19241925 #[test]1926 fn test_add_missing_preserves_indentation() {1927 // in different modules1928 check_assist(1929 add_missing_impl_members,1930 r#"1931mod m {1932 pub trait Foo {1933 const CONST_MULTILINE: (1934 i32,1935 i321936 );19371938 fn foo(&self);1939 }1940}1941struct S;1942impl m::Foo for S { $0 }"#,1943 r#"1944mod m {1945 pub trait Foo {1946 const CONST_MULTILINE: (1947 i32,1948 i321949 );19501951 fn foo(&self);1952 }1953}1954struct S;1955impl m::Foo for S {1956 $0const CONST_MULTILINE: (1957 i32,1958 i321959 );19601961 fn foo(&self) {1962 todo!()1963 }1964}"#,1965 );1966 // in the same module1967 check_assist(1968 add_missing_impl_members,1969 r#"1970mod m {1971 trait Foo {1972 type Output;19731974 const CONST: usize = 42;1975 const CONST_2: i32;1976 const CONST_MULTILINE: (1977 i32,1978 i321979 );19801981 fn foo(&self);1982 fn bar(&self);1983 fn baz(&self);1984 }19851986 struct S;19871988 impl Foo for S {1989 fn bar(&self) {}1990$01991 }1992}"#,1993 r#"1994mod m {1995 trait Foo {1996 type Output;19971998 const CONST: usize = 42;1999 const CONST_2: i32;2000 const CONST_MULTILINE: (
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.