Skip to content

Commit 97ecfe4

Browse files
committed
Remove unnecessary .as_ref() in generate getter assist
1 parent 0113bc9 commit 97ecfe4

File tree

3 files changed

+91
-22
lines changed

3 files changed

+91
-22
lines changed

crates/ide-assists/src/handlers/generate_getter_or_setter.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,21 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
7575
// Generate a getter method.
7676
//
7777
// ```
78-
// # //- minicore: as_ref
78+
// # //- minicore: as_ref, deref
7979
// # pub struct String;
8080
// # impl AsRef<str> for String {
8181
// # fn as_ref(&self) -> &str {
8282
// # ""
8383
// # }
8484
// # }
8585
// #
86+
// # impl core::ops::Deref for String {
87+
// # type Target = str;
88+
// # fn deref(&self) -> &Self::Target {
89+
// # ""
90+
// # }
91+
// # }
92+
// #
8693
// struct Person {
8794
// nam$0e: String,
8895
// }
@@ -96,13 +103,20 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
96103
// # }
97104
// # }
98105
// #
106+
// # impl core::ops::Deref for String {
107+
// # type Target = str;
108+
// # fn deref(&self) -> &Self::Target {
109+
// # ""
110+
// # }
111+
// # }
112+
// #
99113
// struct Person {
100114
// name: String,
101115
// }
102116
//
103117
// impl Person {
104118
// fn $0name(&self) -> &str {
105-
// self.name.as_ref()
119+
// &self.name
106120
// }
107121
// }
108122
// ```

crates/ide-assists/src/tests/generated.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,14 +1429,21 @@ fn doctest_generate_getter() {
14291429
check_doc_test(
14301430
"generate_getter",
14311431
r#####"
1432-
//- minicore: as_ref
1432+
//- minicore: as_ref, deref
14331433
pub struct String;
14341434
impl AsRef<str> for String {
14351435
fn as_ref(&self) -> &str {
14361436
""
14371437
}
14381438
}
14391439
1440+
impl core::ops::Deref for String {
1441+
type Target = str;
1442+
fn deref(&self) -> &Self::Target {
1443+
""
1444+
}
1445+
}
1446+
14401447
struct Person {
14411448
nam$0e: String,
14421449
}
@@ -1449,13 +1456,20 @@ impl AsRef<str> for String {
14491456
}
14501457
}
14511458
1459+
impl core::ops::Deref for String {
1460+
type Target = str;
1461+
fn deref(&self) -> &Self::Target {
1462+
""
1463+
}
1464+
}
1465+
14521466
struct Person {
14531467
name: String,
14541468
}
14551469
14561470
impl Person {
14571471
fn $0name(&self) -> &str {
1458-
self.name.as_ref()
1472+
&self.name
14591473
}
14601474
}
14611475
"#####,

crates/ide-assists/src/utils.rs

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::ops;
44

55
pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
6-
use hir::{db::HirDatabase, HasAttrs as HirHasAttrs, HirDisplay, InFile, Semantics};
6+
use hir::{db::HirDatabase, known, HasAttrs as HirHasAttrs, HirDisplay, InFile, Semantics};
77
use ide_db::{
88
famous_defs::FamousDefs, path_transform::PathTransform,
99
syntax_helpers::insert_whitespace_into_node::insert_ws_into, RootDatabase, SnippetCap,
@@ -600,6 +600,7 @@ pub(crate) fn add_method_to_adt(
600600
pub(crate) struct ReferenceConversion {
601601
conversion: ReferenceConversionType,
602602
ty: hir::Type,
603+
impls_deref: bool,
603604
}
604605

605606
#[derive(Debug)]
@@ -656,7 +657,13 @@ impl ReferenceConversion {
656657
| ReferenceConversionType::AsRefSlice
657658
| ReferenceConversionType::Dereferenced
658659
| ReferenceConversionType::Option
659-
| ReferenceConversionType::Result => format!("self.{field_name}.as_ref()"),
660+
| ReferenceConversionType::Result => {
661+
if self.impls_deref {
662+
format!("&self.{field_name}")
663+
} else {
664+
format!("self.{field_name}.as_ref()")
665+
}
666+
}
660667
}
661668
}
662669
}
@@ -675,54 +682,88 @@ pub(crate) fn convert_reference_type(
675682
.or_else(|| handle_dereferenced(&ty, db, famous_defs))
676683
.or_else(|| handle_option_as_ref(&ty, db, famous_defs))
677684
.or_else(|| handle_result_as_ref(&ty, db, famous_defs))
678-
.map(|conversion| ReferenceConversion { ty, conversion })
685+
.map(|(conversion, impls_deref)| ReferenceConversion { ty, conversion, impls_deref })
686+
}
687+
688+
fn impls_deref_for_target(
689+
ty: &hir::Type,
690+
target: hir::Type,
691+
db: &dyn HirDatabase,
692+
famous_defs: &FamousDefs<'_, '_>,
693+
) -> bool {
694+
if let Some(deref_trait) = famous_defs.core_ops_Deref() {
695+
if ty.impls_trait(db, deref_trait, &[]) {
696+
let assoc_type_item = deref_trait.items(db).into_iter().find_map(|item| match item {
697+
hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Target => Some(alias),
698+
_ => None,
699+
});
700+
if let Some(assoc_type_item) = assoc_type_item {
701+
matches!(
702+
ty.normalize_trait_assoc_type(db, &[], assoc_type_item),
703+
Some(ty) if ty.could_coerce_to(db, &target),
704+
)
705+
} else {
706+
false
707+
}
708+
} else {
709+
false
710+
}
711+
} else {
712+
false
713+
}
679714
}
680715

681-
fn handle_copy(ty: &hir::Type, db: &dyn HirDatabase) -> Option<ReferenceConversionType> {
682-
ty.is_copy(db).then_some(ReferenceConversionType::Copy)
716+
fn handle_copy(ty: &hir::Type, db: &dyn HirDatabase) -> Option<(ReferenceConversionType, bool)> {
717+
ty.is_copy(db).then_some((ReferenceConversionType::Copy, true))
683718
}
684719

685720
fn handle_as_ref_str(
686721
ty: &hir::Type,
687722
db: &dyn HirDatabase,
688723
famous_defs: &FamousDefs<'_, '_>,
689-
) -> Option<ReferenceConversionType> {
724+
) -> Option<(ReferenceConversionType, bool)> {
690725
let str_type = hir::BuiltinType::str().ty(db);
691726

692-
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[str_type])
693-
.then_some(ReferenceConversionType::AsRefStr)
727+
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[str_type.clone()]).then_some((
728+
ReferenceConversionType::AsRefStr,
729+
impls_deref_for_target(ty, str_type, db, famous_defs),
730+
))
694731
}
695732

696733
fn handle_as_ref_slice(
697734
ty: &hir::Type,
698735
db: &dyn HirDatabase,
699736
famous_defs: &FamousDefs<'_, '_>,
700-
) -> Option<ReferenceConversionType> {
737+
) -> Option<(ReferenceConversionType, bool)> {
701738
let type_argument = ty.type_arguments().next()?;
702739
let slice_type = hir::Type::new_slice(type_argument);
703740

704-
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[slice_type])
705-
.then_some(ReferenceConversionType::AsRefSlice)
741+
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[slice_type.clone()]).then_some((
742+
ReferenceConversionType::AsRefSlice,
743+
impls_deref_for_target(ty, slice_type, db, famous_defs),
744+
))
706745
}
707746

708747
fn handle_dereferenced(
709748
ty: &hir::Type,
710749
db: &dyn HirDatabase,
711750
famous_defs: &FamousDefs<'_, '_>,
712-
) -> Option<ReferenceConversionType> {
751+
) -> Option<(ReferenceConversionType, bool)> {
713752
let type_argument = ty.type_arguments().next()?;
714753

715-
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[type_argument])
716-
.then_some(ReferenceConversionType::Dereferenced)
754+
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[type_argument.clone()]).then_some((
755+
ReferenceConversionType::Dereferenced,
756+
impls_deref_for_target(ty, type_argument, db, famous_defs),
757+
))
717758
}
718759

719760
fn handle_option_as_ref(
720761
ty: &hir::Type,
721762
db: &dyn HirDatabase,
722763
famous_defs: &FamousDefs<'_, '_>,
723-
) -> Option<ReferenceConversionType> {
764+
) -> Option<(ReferenceConversionType, bool)> {
724765
if ty.as_adt() == famous_defs.core_option_Option()?.ty(db).as_adt() {
725-
Some(ReferenceConversionType::Option)
766+
Some((ReferenceConversionType::Option, false))
726767
} else {
727768
None
728769
}
@@ -732,9 +773,9 @@ fn handle_result_as_ref(
732773
ty: &hir::Type,
733774
db: &dyn HirDatabase,
734775
famous_defs: &FamousDefs<'_, '_>,
735-
) -> Option<ReferenceConversionType> {
776+
) -> Option<(ReferenceConversionType, bool)> {
736777
if ty.as_adt() == famous_defs.core_result_Result()?.ty(db).as_adt() {
737-
Some(ReferenceConversionType::Result)
778+
Some((ReferenceConversionType::Result, false))
738779
} else {
739780
None
740781
}

0 commit comments

Comments
 (0)