Skip to content

Commit bcc720f

Browse files
bors[bot]Veykril
andauthored
Merge #10979
10979: fix: Don't show trait flyimports for impl trait and placeholders r=Veykril a=Veykril cc #8539 bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents bc8efca + c81aa68 commit bcc720f

File tree

10 files changed

+102
-45
lines changed

10 files changed

+102
-45
lines changed

crates/hir/src/lib.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,13 +2623,15 @@ impl Type {
26232623
}
26242624

26252625
pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
2626+
self.autoderef_(db).map(move |ty| self.derived(ty))
2627+
}
2628+
2629+
pub fn autoderef_<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Ty> + 'a {
26262630
// There should be no inference vars in types passed here
26272631
let canonical = hir_ty::replace_errors_with_variables(&self.ty);
26282632
let environment = self.env.env.clone();
26292633
let ty = InEnvironment { goal: canonical, environment };
2630-
autoderef(db, Some(self.krate), ty)
2631-
.map(|canonical| canonical.value)
2632-
.map(move |ty| self.derived(ty))
2634+
autoderef(db, Some(self.krate), ty).map(|canonical| canonical.value)
26332635
}
26342636

26352637
// This would be nicer if it just returned an iterator, but that runs into
@@ -2808,22 +2810,32 @@ impl Type {
28082810
db: &'a dyn HirDatabase,
28092811
) -> impl Iterator<Item = Trait> + 'a {
28102812
let _p = profile::span("applicable_inherent_traits");
2811-
self.autoderef(db)
2812-
.filter_map(|derefed_type| derefed_type.ty.dyn_trait())
2813+
self.autoderef_(db)
2814+
.filter_map(|ty| ty.dyn_trait())
28132815
.flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
28142816
.map(Trait::from)
28152817
}
28162818

2817-
pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
2819+
pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Trait> + 'a {
2820+
let _p = profile::span("env_traits");
2821+
self.autoderef_(db)
2822+
.filter(|ty| matches!(ty.kind(&Interner), TyKind::Placeholder(_)))
2823+
.flat_map(|ty| {
2824+
self.env
2825+
.traits_in_scope_from_clauses(ty)
2826+
.flat_map(|t| hir_ty::all_super_traits(db.upcast(), t))
2827+
})
2828+
.map(Trait::from)
2829+
}
2830+
2831+
pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
28182832
self.ty.impl_trait_bounds(db).map(|it| {
2819-
it.into_iter()
2820-
.filter_map(|pred| match pred.skip_binders() {
2821-
hir_ty::WhereClause::Implemented(trait_ref) => {
2822-
Some(Trait::from(trait_ref.hir_trait_id()))
2823-
}
2824-
_ => None,
2825-
})
2826-
.collect()
2833+
it.into_iter().filter_map(|pred| match pred.skip_binders() {
2834+
hir_ty::WhereClause::Implemented(trait_ref) => {
2835+
Some(Trait::from(trait_ref.hir_trait_id()))
2836+
}
2837+
_ => None,
2838+
})
28272839
})
28282840
}
28292841

crates/hir_ty/src/method_resolution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ fn iterate_trait_method_candidates(
719719
let env_traits = match self_ty.value.kind(&Interner) {
720720
TyKind::Placeholder(_) => {
721721
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
722-
env.traits_in_scope_from_clauses(&self_ty.value)
722+
env.traits_in_scope_from_clauses(self_ty.value.clone())
723723
.flat_map(|t| all_super_traits(db.upcast(), t))
724724
.collect()
725725
}

crates/hir_ty/src/traits.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,13 @@ impl TraitEnvironment {
5454
}
5555
}
5656

57-
pub(crate) fn traits_in_scope_from_clauses<'a>(
57+
pub fn traits_in_scope_from_clauses<'a>(
5858
&'a self,
59-
ty: &'a Ty,
59+
ty: Ty,
6060
) -> impl Iterator<Item = TraitId> + 'a {
61-
self.traits_from_clauses.iter().filter_map(move |(self_ty, trait_id)| {
62-
if self_ty == ty {
63-
Some(*trait_id)
64-
} else {
65-
None
66-
}
67-
})
61+
self.traits_from_clauses
62+
.iter()
63+
.filter_map(move |(self_ty, trait_id)| (*self_ty == ty).then(|| *trait_id))
6864
}
6965
}
7066

crates/ide/src/goto_type_definition.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ pub(crate) fn goto_type_definition(
7575
} else if let Some(trait_) = t.as_dyn_trait() {
7676
push(trait_.into());
7777
} else if let Some(traits) = t.as_impl_traits(db) {
78-
traits.into_iter().for_each(|it| push(it.into()));
78+
traits.for_each(|it| push(it.into()));
7979
} else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
8080
push(trait_.into());
8181
}

crates/ide/src/hover.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ fn walk_and_push_ty(
337337
} else if let Some(trait_) = t.as_dyn_trait() {
338338
push_new_def(trait_.into());
339339
} else if let Some(traits) = t.as_impl_traits(db) {
340-
traits.into_iter().for_each(|it| push_new_def(it.into()));
340+
traits.for_each(|it| push_new_def(it.into()));
341341
} else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
342342
push_new_def(trait_.into());
343343
}

crates/ide_assists/src/utils/suggest_name.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ fn name_of_type(ty: &hir::Type, db: &RootDatabase) -> Option<String> {
243243
} else if let Some(trait_) = ty.as_dyn_trait() {
244244
trait_name(&trait_, db)?
245245
} else if let Some(traits) = ty.as_impl_traits(db) {
246-
let mut iter = traits.into_iter().filter_map(|t| trait_name(&t, db));
246+
let mut iter = traits.filter_map(|t| trait_name(&t, db));
247247
let name = iter.next()?;
248248
if iter.next().is_some() {
249249
return None;

crates/ide_completion/src/completions/pattern.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Completes constants and paths in unqualified patterns.
22
3+
use hir::db::DefDatabase;
4+
35
use crate::{
46
context::{PatternContext, PatternRefutability},
57
CompletionContext, Completions,
@@ -13,11 +15,12 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
1315
}
1416
_ => return,
1517
};
18+
let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1;
1619

17-
if refutable {
18-
if let Some(hir::Adt::Enum(e)) =
19-
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
20-
{
20+
if let Some(hir::Adt::Enum(e)) =
21+
ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
22+
{
23+
if refutable || single_variant_enum(e) {
2124
super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| {
2225
acc.add_qualified_variant_pat(ctx, variant, path.clone());
2326
acc.add_qualified_enum_variant(ctx, variant, path);
@@ -28,20 +31,20 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
2831
// FIXME: ideally, we should look at the type we are matching against and
2932
// suggest variants + auto-imports
3033
ctx.process_all_names(&mut |name, res| {
31-
let add_resolution = match &res {
34+
let add_resolution = match res {
3235
hir::ScopeDef::ModuleDef(def) => match def {
3336
hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
34-
acc.add_struct_pat(ctx, *strukt, Some(name.clone()));
37+
acc.add_struct_pat(ctx, strukt, Some(name.clone()));
3538
true
3639
}
37-
hir::ModuleDef::Variant(variant) if refutable => {
38-
acc.add_variant_pat(ctx, *variant, Some(name.clone()));
40+
hir::ModuleDef::Variant(variant)
41+
if refutable || single_variant_enum(variant.parent_enum(ctx.db)) =>
42+
{
43+
acc.add_variant_pat(ctx, variant, Some(name.clone()));
3944
true
4045
}
41-
hir::ModuleDef::Adt(hir::Adt::Enum(..))
42-
| hir::ModuleDef::Variant(..)
43-
| hir::ModuleDef::Const(..)
44-
| hir::ModuleDef::Module(..) => refutable,
46+
hir::ModuleDef::Adt(hir::Adt::Enum(e)) => refutable || single_variant_enum(e),
47+
hir::ModuleDef::Const(..) | hir::ModuleDef::Module(..) => refutable,
4548
_ => false,
4649
},
4750
hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),

crates/ide_completion/src/tests/flyimport.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,44 @@ mod bar {
924924
"#,
925925
expect![[r#""#]],
926926
);
927+
check(
928+
r#"
929+
mod baz {
930+
pub trait DefDatabase {
931+
fn method1(&self);
932+
}
933+
pub trait HirDatabase: DefDatabase {
934+
fn method2(&self);
935+
}
936+
}
937+
938+
mod bar {
939+
fn test(db: &impl crate::baz::HirDatabase) {
940+
db.metho$0
941+
}
942+
}
943+
"#,
944+
expect![[r#""#]],
945+
);
946+
check(
947+
r#"
948+
mod baz {
949+
pub trait DefDatabase {
950+
fn method1(&self);
951+
}
952+
pub trait HirDatabase: DefDatabase {
953+
fn method2(&self);
954+
}
955+
}
956+
957+
mod bar {
958+
fn test<T: crate::baz::HirDatabase>(db: T) {
959+
db.metho$0
960+
}
961+
}
962+
"#,
963+
expect![[r#""#]],
964+
);
927965
}
928966

929967
#[test]

crates/ide_completion/src/tests/pattern.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,18 +130,24 @@ fn foo() {
130130
fn irrefutable() {
131131
check(
132132
r#"
133+
enum SingleVariantEnum {
134+
Variant
135+
}
136+
use SingleVariantEnum::Variant;
133137
fn foo() {
134138
let a$0
135139
}
136140
"#,
137141
expect![[r##"
138142
kw mut
139-
bn Record Record { field$1 }$0
143+
bn Record Record { field$1 }$0
140144
st Record
141-
bn Tuple Tuple($1)$0
145+
bn Tuple Tuple($1)$0
142146
st Tuple
147+
ev Variant
148+
en SingleVariantEnum
143149
st Unit
144-
ma makro!(…) #[macro_export] macro_rules! makro
150+
ma makro!(…) #[macro_export] macro_rules! makro
145151
"##]],
146152
);
147153
}

crates/ide_db/src/helpers/import_assets.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,10 @@ fn trait_applicable_items(
454454

455455
let db = sema.db;
456456

457-
let related_dyn_traits =
458-
trait_candidate.receiver_ty.applicable_inherent_traits(db).collect::<FxHashSet<_>>();
457+
let inherent_traits = trait_candidate.receiver_ty.applicable_inherent_traits(db);
458+
let env_traits = trait_candidate.receiver_ty.env_traits(db);
459+
let related_traits = inherent_traits.chain(env_traits).collect::<FxHashSet<_>>();
460+
459461
let mut required_assoc_items = FxHashSet::default();
460462
let trait_candidates = items_locator::items_with_name(
461463
sema,
@@ -467,7 +469,7 @@ fn trait_applicable_items(
467469
.filter_map(|input| item_as_assoc(db, input))
468470
.filter_map(|assoc| {
469471
let assoc_item_trait = assoc.containing_trait(db)?;
470-
if related_dyn_traits.contains(&assoc_item_trait) {
472+
if related_traits.contains(&assoc_item_trait) {
471473
None
472474
} else {
473475
required_assoc_items.insert(assoc);

0 commit comments

Comments
 (0)