aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/lib.rs12
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs8
-rw-r--r--crates/hir_ty/src/lib.rs1
-rw-r--r--crates/hir_ty/src/tests/simple.rs18
-rw-r--r--crates/hir_ty/src/utils.rs2
-rw-r--r--crates/ide_assists/src/handlers/fill_match_arms.rs22
-rw-r--r--crates/ide_completion/src/completions/flyimport.rs23
-rw-r--r--crates/ide_db/src/helpers/import_assets.rs22
-rw-r--r--crates/syntax/src/ast/make.rs18
9 files changed, 102 insertions, 24 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index eba46a056..0acfa582a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2066,6 +2066,18 @@ impl Type {
2066 self.ty.dyn_trait().map(Into::into) 2066 self.ty.dyn_trait().map(Into::into)
2067 } 2067 }
2068 2068
2069 /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
2070 /// or an empty iterator otherwise.
2071 pub fn applicable_inherent_traits<'a>(
2072 &'a self,
2073 db: &'a dyn HirDatabase,
2074 ) -> impl Iterator<Item = Trait> + 'a {
2075 self.autoderef(db)
2076 .filter_map(|derefed_type| derefed_type.ty.dyn_trait())
2077 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
2078 .map(Trait::from)
2079 }
2080
2069 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { 2081 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
2070 self.ty.impl_trait_bounds(db).map(|it| { 2082 self.ty.impl_trait_bounds(db).map(|it| {
2071 it.into_iter() 2083 it.into_iter()
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index ccc9f22eb..c984148c3 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -387,7 +387,13 @@ impl DefMap {
387 .get_legacy_macro(name) 387 .get_legacy_macro(name)
388 .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); 388 .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public));
389 let from_scope = self[module].scope.get(name); 389 let from_scope = self[module].scope.get(name);
390 let from_builtin = BUILTIN_SCOPE.get(name).copied().unwrap_or_else(PerNs::none); 390 let from_builtin = match self.block {
391 Some(_) => {
392 // Only resolve to builtins in the root `DefMap`.
393 PerNs::none()
394 }
395 None => BUILTIN_SCOPE.get(name).copied().unwrap_or_else(PerNs::none),
396 };
391 let from_scope_or_builtin = match shadow { 397 let from_scope_or_builtin = match shadow {
392 BuiltinShadowMode::Module => from_scope.or(from_builtin), 398 BuiltinShadowMode::Module => from_scope.or(from_builtin),
393 BuiltinShadowMode::Other => { 399 BuiltinShadowMode::Other => {
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 113234fa4..0505fa4ae 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -56,6 +56,7 @@ pub use mapping::{
56 to_foreign_def_id, to_placeholder_idx, 56 to_foreign_def_id, to_placeholder_idx,
57}; 57};
58pub use traits::TraitEnvironment; 58pub use traits::TraitEnvironment;
59pub use utils::all_super_traits;
59pub use walk::TypeWalk; 60pub use walk::TypeWalk;
60 61
61pub use chalk_ir::{ 62pub use chalk_ir::{
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 84c5c05fd..5948d0bc2 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -1765,6 +1765,24 @@ fn main() {
1765} 1765}
1766 1766
1767#[test] 1767#[test]
1768fn shadowing_primitive_with_inner_items() {
1769 check_types(
1770 r#"
1771struct i32;
1772struct Foo;
1773
1774impl i32 { fn foo(&self) -> Foo { Foo } }
1775
1776fn main() {
1777 fn inner() {}
1778 let x: i32 = i32;
1779 x.foo();
1780 //^ Foo
1781}"#,
1782 );
1783}
1784
1785#[test]
1768fn not_shadowing_primitive_by_module() { 1786fn not_shadowing_primitive_by_module() {
1769 check_types( 1787 check_types(
1770 r#" 1788 r#"
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 5f6cb052a..2f04ee57a 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -78,7 +78,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
78 78
79/// Returns an iterator over the whole super trait hierarchy (including the 79/// Returns an iterator over the whole super trait hierarchy (including the
80/// trait itself). 80/// trait itself).
81pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 81pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
82 // we need to take care a bit here to avoid infinite loops in case of cycles 82 // we need to take care a bit here to avoid infinite loops in case of cycles
83 // (i.e. if we have `trait A: B; trait B: A;`) 83 // (i.e. if we have `trait A: B; trait B: A;`)
84 let mut result = vec![trait_]; 84 let mut result = vec![trait_];
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs
index 878b3a3fa..80bd1b7e8 100644
--- a/crates/ide_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ide_assists/src/handlers/fill_match_arms.rs
@@ -71,12 +71,6 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
71 return None; 71 return None;
72 } 72 }
73 73
74 // We do not currently support filling match arms for a tuple
75 // containing a single enum.
76 if enum_defs.len() < 2 {
77 return None;
78 }
79
80 // When calculating the match arms for a tuple of enums, we want 74 // When calculating the match arms for a tuple of enums, we want
81 // to create a match arm for each possible combination of enum 75 // to create a match arm for each possible combination of enum
82 // values. The `multi_cartesian_product` method transforms 76 // values. The `multi_cartesian_product` method transforms
@@ -514,10 +508,7 @@ fn main() {
514 508
515 #[test] 509 #[test]
516 fn fill_match_arms_single_element_tuple_of_enum() { 510 fn fill_match_arms_single_element_tuple_of_enum() {
517 // For now we don't hande the case of a single element tuple, but 511 check_assist(
518 // we could handle this in the future if `make::tuple_pat` allowed
519 // creating a tuple with a single pattern.
520 check_assist_not_applicable(
521 fill_match_arms, 512 fill_match_arms,
522 r#" 513 r#"
523 enum A { One, Two } 514 enum A { One, Two }
@@ -528,6 +519,17 @@ fn main() {
528 } 519 }
529 } 520 }
530 "#, 521 "#,
522 r#"
523 enum A { One, Two }
524
525 fn main() {
526 let a = A::One;
527 match (a, ) {
528 $0(A::One,) => {}
529 (A::Two,) => {}
530 }
531 }
532 "#,
531 ); 533 );
532 } 534 }
533 535
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index 5e61ecb4d..8e211ae1e 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -1127,4 +1127,27 @@ impl Bar for Foo {
1127 expect![[r#""#]], 1127 expect![[r#""#]],
1128 ); 1128 );
1129 } 1129 }
1130
1131 #[test]
1132 fn no_inherent_candidates_proposed() {
1133 check(
1134 r#"
1135mod baz {
1136 pub trait DefDatabase {
1137 fn method1(&self);
1138 }
1139 pub trait HirDatabase: DefDatabase {
1140 fn method2(&self);
1141 }
1142}
1143
1144mod bar {
1145 fn test(db: &dyn crate::baz::HirDatabase) {
1146 db.metho$0
1147 }
1148}
1149 "#,
1150 expect![[r#""#]],
1151 );
1152 }
1130} 1153}
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs
index 8ce648367..91d6a4665 100644
--- a/crates/ide_db/src/helpers/import_assets.rs
+++ b/crates/ide_db/src/helpers/import_assets.rs
@@ -436,6 +436,8 @@ fn trait_applicable_items(
436 }) 436 })
437 .collect(); 437 .collect();
438 438
439 let related_dyn_traits =
440 trait_candidate.receiver_ty.applicable_inherent_traits(db).collect::<FxHashSet<_>>();
439 let mut located_imports = FxHashSet::default(); 441 let mut located_imports = FxHashSet::default();
440 442
441 if trait_assoc_item { 443 if trait_assoc_item {
@@ -451,12 +453,16 @@ fn trait_applicable_items(
451 return None; 453 return None;
452 } 454 }
453 } 455 }
456 let located_trait = assoc.containing_trait(db)?;
457 if related_dyn_traits.contains(&located_trait) {
458 return None;
459 }
454 460
455 let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); 461 let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
456 let original_item = assoc_to_item(assoc); 462 let original_item = assoc_to_item(assoc);
457 located_imports.insert(LocatedImport::new( 463 located_imports.insert(LocatedImport::new(
458 mod_path(item)?, 464 mod_path(trait_item)?,
459 item, 465 trait_item,
460 original_item, 466 original_item,
461 mod_path(original_item), 467 mod_path(original_item),
462 )); 468 ));
@@ -473,11 +479,15 @@ fn trait_applicable_items(
473 |_, function| { 479 |_, function| {
474 let assoc = function.as_assoc_item(db)?; 480 let assoc = function.as_assoc_item(db)?;
475 if required_assoc_items.contains(&assoc) { 481 if required_assoc_items.contains(&assoc) {
476 let item = ItemInNs::from(ModuleDef::from(assoc.containing_trait(db)?)); 482 let located_trait = assoc.containing_trait(db)?;
483 if related_dyn_traits.contains(&located_trait) {
484 return None;
485 }
486 let trait_item = ItemInNs::from(ModuleDef::from(located_trait));
477 let original_item = assoc_to_item(assoc); 487 let original_item = assoc_to_item(assoc);
478 located_imports.insert(LocatedImport::new( 488 located_imports.insert(LocatedImport::new(
479 mod_path(item)?, 489 mod_path(trait_item)?,
480 item, 490 trait_item,
481 original_item, 491 original_item,
482 mod_path(original_item), 492 mod_path(original_item),
483 )); 493 ));
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index c6a7b99b7..94d4f2cf0 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -29,9 +29,13 @@ pub fn ty(text: &str) -> ast::Type {
29pub fn ty_unit() -> ast::Type { 29pub fn ty_unit() -> ast::Type {
30 ty("()") 30 ty("()")
31} 31}
32// FIXME: handle types of length == 1
33pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { 32pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
34 let contents = types.into_iter().join(", "); 33 let mut count: usize = 0;
34 let mut contents = types.into_iter().inspect(|_| count += 1).join(", ");
35 if count == 1 {
36 contents.push(',');
37 }
38
35 ty(&format!("({})", contents)) 39 ty(&format!("({})", contents))
36} 40}
37// FIXME: handle path to type 41// FIXME: handle path to type
@@ -292,11 +296,13 @@ pub fn wildcard_pat() -> ast::WildcardPat {
292 296
293/// Creates a tuple of patterns from an iterator of patterns. 297/// Creates a tuple of patterns from an iterator of patterns.
294/// 298///
295/// Invariant: `pats` must be length > 1 299/// Invariant: `pats` must be length > 0
296///
297/// FIXME handle `pats` length == 1
298pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat { 300pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat {
299 let pats_str = pats.into_iter().map(|p| p.to_string()).join(", "); 301 let mut count: usize = 0;
302 let mut pats_str = pats.into_iter().inspect(|_| count += 1).join(", ");
303 if count == 1 {
304 pats_str.push(',');
305 }
300 return from_text(&format!("({})", pats_str)); 306 return from_text(&format!("({})", pats_str));
301 307
302 fn from_text(text: &str) -> ast::TuplePat { 308 fn from_text(text: &str) -> ast::TuplePat {