From 529c369c9bc15a73e7a03260eca84ccef99ac281 Mon Sep 17 00:00:00 2001 From: oxalica Date: Sat, 12 Sep 2020 01:03:28 +0800 Subject: Fix type walking about type of async block --- crates/hir/src/code_model.rs | 5 ++++ crates/hir_ty/src/lib.rs | 23 +++++++--------- crates/ide/src/hover.rs | 64 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 14 deletions(-) (limited to 'crates') 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 { cb(type_.derived(ty.clone())); } } + TypeCtor::OpaqueType(..) => { + if let Some(bounds) = ty.impl_trait_bounds(db) { + walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); + } + } _ => (), } 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::{ AdtId, AssocContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, TypeParamId, }; -use hir_expand::name::name; use itertools::Itertools; use crate::{ @@ -848,26 +847,22 @@ impl Ty { pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option> { match self { - Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), parameters }) => { + Ty::Apply(ApplicationTy { ctor: TypeCtor::OpaqueType(opaque_ty_id), .. }) => { match opaque_ty_id { OpaqueTyId::AsyncBlockTypeImplTrait(def, _expr) => { let krate = def.module(db.upcast()).krate; - if let Some(future_output) = db + if let Some(future_trait) = db .lang_item(krate, "future_trait".into()) .and_then(|item| item.as_trait()) - .and_then(|trait_| { - db.trait_data(trait_).associated_type_by_name(&name![Output]) - }) { - let proj = GenericPredicate::Projection(ProjectionPredicate { - projection_ty: ProjectionTy { - associated_ty: future_output, - // Self type. - parameters: Substs::single(self.clone()), - }, - ty: parameters[0].clone(), + // This is only used by type walking. + // Parameters will be walked outside, and projection predicate is not used. + // So just provide the Future trait. + let impl_bound = GenericPredicate::Implemented(TraitRef { + trait_: future_trait, + substs: Substs::empty(), }); - Some(vec![proj]) + Some(vec![impl_bound]) } else { None } 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 @@ -2646,6 +2646,70 @@ fn foo(ar<|>g: &impl Foo + Bar) {} ); } + #[test] + fn test_hover_async_block_impl_trait_has_goto_type_action() { + check_actions( + r#" +struct S; +fn foo() { + let fo<|>o = async { S }; +} + +#[prelude_import] use future::*; +mod future { + #[lang = "future_trait"] + pub trait Future { type Output; } +} +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "test::future::Future", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 101..163, + focus_range: Some( + 140..146, + ), + name: "Future", + kind: TRAIT, + container_name: None, + description: Some( + "pub trait Future", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "test::S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..9, + focus_range: Some( + 7..8, + ), + name: "S", + kind: STRUCT, + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], + ); + } + #[test] fn test_hover_arg_generic_impl_trait_has_goto_type_action() { check_actions( -- cgit v1.2.3