diff options
-rw-r--r-- | crates/hir/src/code_model.rs | 5 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 23 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 64 |
3 files changed, 78 insertions, 14 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 613b35afd..7a9747fc7 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -1602,6 +1602,11 @@ impl Type { | |||
1602 | cb(type_.derived(ty.clone())); | 1602 | cb(type_.derived(ty.clone())); |
1603 | } | 1603 | } |
1604 | } | 1604 | } |
1605 | TypeCtor::OpaqueType(..) => { | ||
1606 | if let Some(bounds) = ty.impl_trait_bounds(db) { | ||
1607 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | ||
1608 | } | ||
1609 | } | ||
1605 | _ => (), | 1610 | _ => (), |
1606 | } | 1611 | } |
1607 | 1612 | ||
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 4a7d3a0d9..f16d1fc97 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -33,7 +33,6 @@ use hir_def::{ | |||
33 | AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, | 33 | AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, |
34 | TypeParamId, | 34 | TypeParamId, |
35 | }; | 35 | }; |
36 | use hir_expand::name::name; | ||
37 | use itertools::Itertools; | 36 | use itertools::Itertools; |
38 | 37 | ||
39 | use crate::{ | 38 | use crate::{ |
@@ -848,26 +847,22 @@ impl Ty { | |||
848 | 847 | ||
849 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { | 848 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { |
850 | match self { | 849 | match self { |
851 | Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), parameters }) => { | 850 | Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), .. }) => { |
852 | match opaque_ty_id { | 851 | match opaque_ty_id { |
853 | OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { | 852 | OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { |
854 | let krate = def.module(db.upcast()).krate; | 853 | let krate = def.module(db.upcast()).krate; |
855 | if let Some(future_output) = db | 854 | if let Some(future_trait) = db |
856 | .lang_item(krate, "future_trait".into()) | 855 | .lang_item(krate, "future_trait".into()) |
857 | .and_then(|item| item.as_trait()) | 856 | .and_then(|item| item.as_trait()) |
858 | .and_then(|trait_| { | ||
859 | db.trait_data(trait_).associated_type_by_name(&name![Output]) | ||
860 | }) | ||
861 | { | 857 | { |
862 | let proj = GenericPredicate::Projection(ProjectionPredicate { | 858 | // This is only used by type walking. |
863 | projection_ty: ProjectionTy { | 859 | // Parameters will be walked outside, and projection predicate is not used. |
864 | associated_ty: future_output, | 860 | // So just provide the Future trait. |
865 | // Self type. | 861 | let impl_bound = GenericPredicate::Implemented(TraitRef { |
866 | parameters: Substs::single(self.clone()), | 862 | trait_: future_trait, |
867 | }, | 863 | substs: Substs::empty(), |
868 | ty: parameters[0].clone(), | ||
869 | }); | 864 | }); |
870 | Some(vec![proj]) | 865 | Some(vec![impl_bound]) |
871 | } else { | 866 | } else { |
872 | None | 867 | None |
873 | } | 868 | } |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index efec0184e..37171cbef 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -2647,6 +2647,70 @@ fn foo(ar<|>g: &impl Foo + Bar<S>) {} | |||
2647 | } | 2647 | } |
2648 | 2648 | ||
2649 | #[test] | 2649 | #[test] |
2650 | fn test_hover_async_block_impl_trait_has_goto_type_action() { | ||
2651 | check_actions( | ||
2652 | r#" | ||
2653 | struct S; | ||
2654 | fn foo() { | ||
2655 | let fo<|>o = async { S }; | ||
2656 | } | ||
2657 | |||
2658 | #[prelude_import] use future::*; | ||
2659 | mod future { | ||
2660 | #[lang = "future_trait"] | ||
2661 | pub trait Future { type Output; } | ||
2662 | } | ||
2663 | "#, | ||
2664 | expect![[r#" | ||
2665 | [ | ||
2666 | GoToType( | ||
2667 | [ | ||
2668 | HoverGotoTypeData { | ||
2669 | mod_path: "test::future::Future", | ||
2670 | nav: NavigationTarget { | ||
2671 | file_id: FileId( | ||
2672 | 1, | ||
2673 | ), | ||
2674 | full_range: 101..163, | ||
2675 | focus_range: Some( | ||
2676 | 140..146, | ||
2677 | ), | ||
2678 | name: "Future", | ||
2679 | kind: TRAIT, | ||
2680 | container_name: None, | ||
2681 | description: Some( | ||
2682 | "pub trait Future", | ||
2683 | ), | ||
2684 | docs: None, | ||
2685 | }, | ||
2686 | }, | ||
2687 | HoverGotoTypeData { | ||
2688 | mod_path: "test::S", | ||
2689 | nav: NavigationTarget { | ||
2690 | file_id: FileId( | ||
2691 | 1, | ||
2692 | ), | ||
2693 | full_range: 0..9, | ||
2694 | focus_range: Some( | ||
2695 | 7..8, | ||
2696 | ), | ||
2697 | name: "S", | ||
2698 | kind: STRUCT, | ||
2699 | container_name: None, | ||
2700 | description: Some( | ||
2701 | "struct S", | ||
2702 | ), | ||
2703 | docs: None, | ||
2704 | }, | ||
2705 | }, | ||
2706 | ], | ||
2707 | ), | ||
2708 | ] | ||
2709 | "#]], | ||
2710 | ); | ||
2711 | } | ||
2712 | |||
2713 | #[test] | ||
2650 | fn test_hover_arg_generic_impl_trait_has_goto_type_action() { | 2714 | fn test_hover_arg_generic_impl_trait_has_goto_type_action() { |
2651 | check_actions( | 2715 | check_actions( |
2652 | r#" | 2716 | r#" |