Skip to content

Commit 7e6ade1

Browse files
ChayimFriedman2Veykril
authored andcommitted
Allow excluding specific traits from completion
To be accurate, only their methods are excluded, the trait themselves are still available. I also excluded a bunch of std traits by default. Some less opinionated, like `AsRef`, which should never be used directly except in generic scenarios (and won't be excluded there), some more opinionated, like the ops traits, which I know some users sometimes want to use directly. Either way it's configurable. It should be pretty easy to extend support to excluding only specific methods, but I didn't do that currently. Traits configured to be excluded are resolved in each completion request from scratch. If this proves too expensive, it is easy enough to cache them in the DB.
1 parent c86dd17 commit 7e6ade1

File tree

18 files changed

+1011
-82
lines changed

18 files changed

+1011
-82
lines changed

crates/hir-def/src/item_scope.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,13 @@ impl ItemScope {
354354
.chain(self.unnamed_trait_imports.keys().copied())
355355
}
356356

357+
pub fn trait_by_name(&self, name: &Name) -> Option<TraitId> {
358+
self.types.get(name).and_then(|def| match def.def {
359+
ModuleDefId::TraitId(it) => Some(it),
360+
_ => None,
361+
})
362+
}
363+
357364
pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
358365
self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
359366
self.unnamed_trait_imports.iter().map(|(tr, trait_)| {

crates/hir-ty/src/method_resolution.rs

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ pub fn iterate_path_candidates(
913913
traits_in_scope: &FxHashSet<TraitId>,
914914
visible_from_module: VisibleFromModule,
915915
name: Option<&Name>,
916-
callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
916+
callback: &mut dyn MethodCandidateCallback,
917917
) -> ControlFlow<()> {
918918
iterate_method_candidates_dyn(
919919
ty,
@@ -924,7 +924,7 @@ pub fn iterate_path_candidates(
924924
name,
925925
LookupMode::Path,
926926
// the adjustments are not relevant for path lookup
927-
&mut |_, id, _| callback(id),
927+
callback,
928928
)
929929
}
930930

@@ -936,7 +936,7 @@ pub fn iterate_method_candidates_dyn(
936936
visible_from_module: VisibleFromModule,
937937
name: Option<&Name>,
938938
mode: LookupMode,
939-
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
939+
callback: &mut dyn MethodCandidateCallback,
940940
) -> ControlFlow<()> {
941941
let _p = tracing::info_span!(
942942
"iterate_method_candidates_dyn",
@@ -1006,7 +1006,7 @@ fn iterate_method_candidates_with_autoref(
10061006
traits_in_scope: &FxHashSet<TraitId>,
10071007
visible_from_module: VisibleFromModule,
10081008
name: Option<&Name>,
1009-
mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1009+
callback: &mut dyn MethodCandidateCallback,
10101010
) -> ControlFlow<()> {
10111011
if receiver_ty.value.is_general_var(Interner, &receiver_ty.binders) {
10121012
// don't try to resolve methods on unknown types
@@ -1021,7 +1021,7 @@ fn iterate_method_candidates_with_autoref(
10211021
traits_in_scope,
10221022
visible_from_module,
10231023
name,
1024-
&mut callback,
1024+
callback,
10251025
)
10261026
};
10271027

@@ -1051,6 +1051,45 @@ fn iterate_method_candidates_with_autoref(
10511051
iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
10521052
}
10531053

1054+
pub trait MethodCandidateCallback {
1055+
fn on_inherent_method(
1056+
&mut self,
1057+
adjustments: ReceiverAdjustments,
1058+
item: AssocItemId,
1059+
is_visible: bool,
1060+
) -> ControlFlow<()>;
1061+
1062+
fn on_trait_method(
1063+
&mut self,
1064+
adjustments: ReceiverAdjustments,
1065+
item: AssocItemId,
1066+
is_visible: bool,
1067+
) -> ControlFlow<()>;
1068+
}
1069+
1070+
impl<F> MethodCandidateCallback for F
1071+
where
1072+
F: FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1073+
{
1074+
fn on_inherent_method(
1075+
&mut self,
1076+
adjustments: ReceiverAdjustments,
1077+
item: AssocItemId,
1078+
is_visible: bool,
1079+
) -> ControlFlow<()> {
1080+
self(adjustments, item, is_visible)
1081+
}
1082+
1083+
fn on_trait_method(
1084+
&mut self,
1085+
adjustments: ReceiverAdjustments,
1086+
item: AssocItemId,
1087+
is_visible: bool,
1088+
) -> ControlFlow<()> {
1089+
self(adjustments, item, is_visible)
1090+
}
1091+
}
1092+
10541093
#[tracing::instrument(skip_all, fields(name = ?name))]
10551094
fn iterate_method_candidates_by_receiver(
10561095
table: &mut InferenceTable<'_>,
@@ -1059,7 +1098,7 @@ fn iterate_method_candidates_by_receiver(
10591098
traits_in_scope: &FxHashSet<TraitId>,
10601099
visible_from_module: VisibleFromModule,
10611100
name: Option<&Name>,
1062-
mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1101+
callback: &mut dyn MethodCandidateCallback,
10631102
) -> ControlFlow<()> {
10641103
let receiver_ty = table.instantiate_canonical(receiver_ty);
10651104
// We're looking for methods with *receiver* type receiver_ty. These could
@@ -1075,7 +1114,9 @@ fn iterate_method_candidates_by_receiver(
10751114
Some(&receiver_ty),
10761115
Some(receiver_adjustments.clone()),
10771116
visible_from_module,
1078-
&mut callback,
1117+
&mut |adjustments, item, is_visible| {
1118+
callback.on_inherent_method(adjustments, item, is_visible)
1119+
},
10791120
)?
10801121
}
10811122
ControlFlow::Continue(())
@@ -1095,7 +1136,9 @@ fn iterate_method_candidates_by_receiver(
10951136
name,
10961137
Some(&receiver_ty),
10971138
Some(receiver_adjustments.clone()),
1098-
&mut callback,
1139+
&mut |adjustments, item, is_visible| {
1140+
callback.on_trait_method(adjustments, item, is_visible)
1141+
},
10991142
)?
11001143
}
11011144
ControlFlow::Continue(())
@@ -1110,7 +1153,7 @@ fn iterate_method_candidates_for_self_ty(
11101153
traits_in_scope: &FxHashSet<TraitId>,
11111154
visible_from_module: VisibleFromModule,
11121155
name: Option<&Name>,
1113-
mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1156+
callback: &mut dyn MethodCandidateCallback,
11141157
) -> ControlFlow<()> {
11151158
let mut table = InferenceTable::new(db, env);
11161159
let self_ty = table.instantiate_canonical(self_ty.clone());
@@ -1121,7 +1164,9 @@ fn iterate_method_candidates_for_self_ty(
11211164
None,
11221165
None,
11231166
visible_from_module,
1124-
&mut callback,
1167+
&mut |adjustments, item, is_visible| {
1168+
callback.on_inherent_method(adjustments, item, is_visible)
1169+
},
11251170
)?;
11261171
iterate_trait_method_candidates(
11271172
&self_ty,
@@ -1130,7 +1175,9 @@ fn iterate_method_candidates_for_self_ty(
11301175
name,
11311176
None,
11321177
None,
1133-
callback,
1178+
&mut |adjustments, item, is_visible| {
1179+
callback.on_trait_method(adjustments, item, is_visible)
1180+
},
11341181
)
11351182
}
11361183

crates/hir/src/attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ fn resolve_impl_trait_item(
258258
&traits_in_scope,
259259
method_resolution::VisibleFromModule::None,
260260
Some(name),
261-
&mut |assoc_item_id| {
261+
&mut |_, assoc_item_id: AssocItemId, _| {
262262
// If two traits in scope define the same item, Rustdoc links to no specific trait (for
263263
// instance, given two methods `a`, Rustdoc simply links to `method.a` with no
264264
// disambiguation) so we just pick the first one we find as well.

0 commit comments

Comments
 (0)