aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/display.rs12
-rw-r--r--crates/ra_hir_ty/src/infer.rs23
-rw-r--r--crates/ra_hir_ty/src/lib.rs31
-rw-r--r--crates/ra_hir_ty/src/tests.rs80
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs36
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs3
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs57
7 files changed, 199 insertions, 43 deletions
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index dcca1bace..37def7c03 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -10,7 +10,7 @@ pub struct HirFormatter<'a, 'b, DB> {
10 buf: String, 10 buf: String,
11 curr_size: usize, 11 curr_size: usize,
12 max_size: Option<usize>, 12 max_size: Option<usize>,
13 should_display_default_types: bool, 13 omit_verbose_types: bool,
14} 14}
15 15
16pub trait HirDisplay { 16pub trait HirDisplay {
@@ -20,7 +20,7 @@ pub trait HirDisplay {
20 where 20 where
21 Self: Sized, 21 Self: Sized,
22 { 22 {
23 HirDisplayWrapper(db, self, None, true) 23 HirDisplayWrapper(db, self, None, false)
24 } 24 }
25 25
26 fn display_truncated<'a, DB>( 26 fn display_truncated<'a, DB>(
@@ -31,7 +31,7 @@ pub trait HirDisplay {
31 where 31 where
32 Self: Sized, 32 Self: Sized,
33 { 33 {
34 HirDisplayWrapper(db, self, max_size, false) 34 HirDisplayWrapper(db, self, max_size, true)
35 } 35 }
36} 36}
37 37
@@ -74,8 +74,8 @@ where
74 } 74 }
75 } 75 }
76 76
77 pub fn should_display_default_types(&self) -> bool { 77 pub fn omit_verbose_types(&self) -> bool {
78 self.should_display_default_types 78 self.omit_verbose_types
79 } 79 }
80} 80}
81 81
@@ -93,7 +93,7 @@ where
93 buf: String::with_capacity(20), 93 buf: String::with_capacity(20),
94 curr_size: 0, 94 curr_size: 0,
95 max_size: self.2, 95 max_size: self.2,
96 should_display_default_types: self.3, 96 omit_verbose_types: self.3,
97 }) 97 })
98 } 98 }
99} 99}
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index e97b81473..32c0d07a5 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -37,8 +37,8 @@ use test_utils::tested_by;
37use super::{ 37use super::{
38 primitive::{FloatTy, IntTy}, 38 primitive::{FloatTy, IntTy},
39 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 39 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
40 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, 40 ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment,
41 TypeWalk, Uncertain, 41 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain,
42}; 42};
43use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; 43use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
44 44
@@ -379,6 +379,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
379 ) -> Ty { 379 ) -> Ty {
380 match assoc_ty { 380 match assoc_ty {
381 Some(res_assoc_ty) => { 381 Some(res_assoc_ty) => {
382 // FIXME:
383 // Check if inner_ty is is `impl Trait` and contained input TypeAlias id
384 // this is a workaround while Chalk assoc type projection doesn't always work yet,
385 // but once that is fixed I don't think we should keep this
386 // (we'll probably change how associated types are resolved anyway)
387 if let Ty::Opaque(ref predicates) = inner_ty {
388 for p in predicates.iter() {
389 if let GenericPredicate::Projection(projection) = p {
390 if projection.projection_ty.associated_ty == res_assoc_ty {
391 if let ty_app!(_, params) = &projection.ty {
392 if params.len() == 0 {
393 return projection.ty.clone();
394 }
395 }
396 }
397 }
398 }
399 }
400
382 let ty = self.table.new_type_var(); 401 let ty = self.table.new_type_var();
383 let builder = Substs::build_for_def(self.db, res_assoc_ty) 402 let builder = Substs::build_for_def(self.db, res_assoc_ty)
384 .push(inner_ty) 403 .push(inner_ty)
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 48abf97c9..55b6dd836 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -821,6 +821,8 @@ impl TypeWalk for Ty {
821 } 821 }
822} 822}
823 823
824const TYPE_HINT_TRUNCATION: &str = "…";
825
824impl HirDisplay for &Ty { 826impl HirDisplay for &Ty {
825 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 827 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
826 HirDisplay::hir_fmt(*self, f) 828 HirDisplay::hir_fmt(*self, f)
@@ -830,7 +832,7 @@ impl HirDisplay for &Ty {
830impl HirDisplay for ApplicationTy { 832impl HirDisplay for ApplicationTy {
831 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 833 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
832 if f.should_truncate() { 834 if f.should_truncate() {
833 return write!(f, ""); 835 return write!(f, "{}", TYPE_HINT_TRUNCATION);
834 } 836 }
835 837
836 match self.ctor { 838 match self.ctor {
@@ -908,9 +910,7 @@ impl HirDisplay for ApplicationTy {
908 write!(f, "<")?; 910 write!(f, "<")?;
909 911
910 let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); 912 let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
911 let parameters_to_write = if f.should_display_default_types() { 913 let parameters_to_write = if f.omit_verbose_types() {
912 self.parameters.0.as_ref()
913 } else {
914 match self 914 match self
915 .ctor 915 .ctor
916 .as_generic_def() 916 .as_generic_def()
@@ -935,6 +935,8 @@ impl HirDisplay for ApplicationTy {
935 &non_default_parameters 935 &non_default_parameters
936 } 936 }
937 } 937 }
938 } else {
939 self.parameters.0.as_ref()
938 }; 940 };
939 941
940 f.write_joined(parameters_to_write, ", ")?; 942 f.write_joined(parameters_to_write, ", ")?;
@@ -959,9 +961,16 @@ impl HirDisplay for ApplicationTy {
959 let sig = self.parameters[0] 961 let sig = self.parameters[0]
960 .callable_sig(f.db) 962 .callable_sig(f.db)
961 .expect("first closure parameter should contain signature"); 963 .expect("first closure parameter should contain signature");
962 write!(f, "|")?; 964 let return_type_hint = sig.ret().display(f.db);
963 f.write_joined(sig.params(), ", ")?; 965 if sig.params().is_empty() {
964 write!(f, "| -> {}", sig.ret().display(f.db))?; 966 write!(f, "|| -> {}", return_type_hint)?;
967 } else if f.omit_verbose_types() {
968 write!(f, "|{}| -> {}", TYPE_HINT_TRUNCATION, return_type_hint)?;
969 } else {
970 write!(f, "|")?;
971 f.write_joined(sig.params(), ", ")?;
972 write!(f, "| -> {}", return_type_hint)?;
973 };
965 } 974 }
966 } 975 }
967 Ok(()) 976 Ok(())
@@ -971,7 +980,7 @@ impl HirDisplay for ApplicationTy {
971impl HirDisplay for ProjectionTy { 980impl HirDisplay for ProjectionTy {
972 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 981 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
973 if f.should_truncate() { 982 if f.should_truncate() {
974 return write!(f, ""); 983 return write!(f, "{}", TYPE_HINT_TRUNCATION);
975 } 984 }
976 985
977 let trait_name = f.db.trait_data(self.trait_(f.db)).name.clone(); 986 let trait_name = f.db.trait_data(self.trait_(f.db)).name.clone();
@@ -989,7 +998,7 @@ impl HirDisplay for ProjectionTy {
989impl HirDisplay for Ty { 998impl HirDisplay for Ty {
990 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 999 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
991 if f.should_truncate() { 1000 if f.should_truncate() {
992 return write!(f, ""); 1001 return write!(f, "{}", TYPE_HINT_TRUNCATION);
993 } 1002 }
994 1003
995 match self { 1004 match self {
@@ -1074,7 +1083,7 @@ impl HirDisplay for Ty {
1074impl TraitRef { 1083impl TraitRef {
1075 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { 1084 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
1076 if f.should_truncate() { 1085 if f.should_truncate() {
1077 return write!(f, ""); 1086 return write!(f, "{}", TYPE_HINT_TRUNCATION);
1078 } 1087 }
1079 1088
1080 self.substs[0].hir_fmt(f)?; 1089 self.substs[0].hir_fmt(f)?;
@@ -1108,7 +1117,7 @@ impl HirDisplay for &GenericPredicate {
1108impl HirDisplay for GenericPredicate { 1117impl HirDisplay for GenericPredicate {
1109 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 1118 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1110 if f.should_truncate() { 1119 if f.should_truncate() {
1111 return write!(f, ""); 1120 return write!(f, "{}", TYPE_HINT_TRUNCATION);
1112 } 1121 }
1113 1122
1114 match self { 1123 match self {
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index d447b4571..d1f10e675 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -11,8 +11,8 @@ use std::fmt::Write;
11use std::sync::Arc; 11use std::sync::Arc;
12 12
13use hir_def::{ 13use hir_def::{
14 body::BodySourceMap, child_by_source::ChildBySource, db::DefDatabase, keys, 14 body::BodySourceMap, child_by_source::ChildBySource, db::DefDatabase, item_scope::ItemScope,
15 nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, 15 keys, nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
16}; 16};
17use hir_expand::InFile; 17use hir_expand::InFile;
18use insta::assert_snapshot; 18use insta::assert_snapshot;
@@ -163,35 +163,69 @@ fn visit_module(
163 module_id: LocalModuleId, 163 module_id: LocalModuleId,
164 cb: &mut dyn FnMut(DefWithBodyId), 164 cb: &mut dyn FnMut(DefWithBodyId),
165) { 165) {
166 for decl in crate_def_map[module_id].scope.declarations() { 166 visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb);
167 match decl {
168 ModuleDefId::FunctionId(it) => cb(it.into()),
169 ModuleDefId::ConstId(it) => cb(it.into()),
170 ModuleDefId::StaticId(it) => cb(it.into()),
171 ModuleDefId::TraitId(it) => {
172 let trait_data = db.trait_data(it);
173 for &(_, item) in trait_data.items.iter() {
174 match item {
175 AssocItemId::FunctionId(it) => cb(it.into()),
176 AssocItemId::ConstId(it) => cb(it.into()),
177 AssocItemId::TypeAliasId(_) => (),
178 }
179 }
180 }
181 ModuleDefId::ModuleId(it) => visit_module(db, crate_def_map, it.local_id, cb),
182 _ => (),
183 }
184 }
185 for impl_id in crate_def_map[module_id].scope.impls() { 167 for impl_id in crate_def_map[module_id].scope.impls() {
186 let impl_data = db.impl_data(impl_id); 168 let impl_data = db.impl_data(impl_id);
187 for &item in impl_data.items.iter() { 169 for &item in impl_data.items.iter() {
188 match item { 170 match item {
189 AssocItemId::FunctionId(it) => cb(it.into()), 171 AssocItemId::FunctionId(it) => {
190 AssocItemId::ConstId(it) => cb(it.into()), 172 let def = it.into();
173 cb(def);
174 let body = db.body(def);
175 visit_scope(db, crate_def_map, &body.item_scope, cb);
176 }
177 AssocItemId::ConstId(it) => {
178 let def = it.into();
179 cb(def);
180 let body = db.body(def);
181 visit_scope(db, crate_def_map, &body.item_scope, cb);
182 }
191 AssocItemId::TypeAliasId(_) => (), 183 AssocItemId::TypeAliasId(_) => (),
192 } 184 }
193 } 185 }
194 } 186 }
187
188 fn visit_scope(
189 db: &TestDB,
190 crate_def_map: &CrateDefMap,
191 scope: &ItemScope,
192 cb: &mut dyn FnMut(DefWithBodyId),
193 ) {
194 for decl in scope.declarations() {
195 match decl {
196 ModuleDefId::FunctionId(it) => {
197 let def = it.into();
198 cb(def);
199 let body = db.body(def);
200 visit_scope(db, crate_def_map, &body.item_scope, cb);
201 }
202 ModuleDefId::ConstId(it) => {
203 let def = it.into();
204 cb(def);
205 let body = db.body(def);
206 visit_scope(db, crate_def_map, &body.item_scope, cb);
207 }
208 ModuleDefId::StaticId(it) => {
209 let def = it.into();
210 cb(def);
211 let body = db.body(def);
212 visit_scope(db, crate_def_map, &body.item_scope, cb);
213 }
214 ModuleDefId::TraitId(it) => {
215 let trait_data = db.trait_data(it);
216 for &(_, item) in trait_data.items.iter() {
217 match item {
218 AssocItemId::FunctionId(it) => cb(it.into()),
219 AssocItemId::ConstId(it) => cb(it.into()),
220 AssocItemId::TypeAliasId(_) => (),
221 }
222 }
223 }
224 ModuleDefId::ModuleId(it) => visit_module(db, crate_def_map, it.local_id, cb),
225 _ => (),
226 }
227 }
228 }
195} 229}
196 230
197fn ellipsize(mut text: String, max_len: usize) -> String { 231fn ellipsize(mut text: String, max_len: usize) -> String {
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 09d684ac2..8b3aa8564 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -1,7 +1,8 @@
1use super::infer;
2use insta::assert_snapshot; 1use insta::assert_snapshot;
3use test_utils::covers; 2use test_utils::covers;
4 3
4use super::infer;
5
5#[test] 6#[test]
6fn bug_484() { 7fn bug_484() {
7 assert_snapshot!( 8 assert_snapshot!(
@@ -331,3 +332,36 @@ pub fn main_loop() {
331 "### 332 "###
332 ); 333 );
333} 334}
335
336#[test]
337fn issue_2669() {
338 assert_snapshot!(
339 infer(
340 r#"trait A {}
341 trait Write {}
342 struct Response<T> {}
343
344 trait D {
345 fn foo();
346 }
347
348 impl<T:A> D for Response<T> {
349 fn foo() {
350 end();
351 fn end<W: Write>() {
352 let _x: T = loop {};
353 }
354 }
355 }"#
356 ),
357 @r###"
358 [147; 262) '{ ... }': ()
359 [161; 164) 'end': fn end<{unknown}>() -> ()
360 [161; 166) 'end()': ()
361 [199; 252) '{ ... }': ()
362 [221; 223) '_x': !
363 [230; 237) 'loop {}': !
364 [235; 237) '{}': ()
365 "###
366 )
367}
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index 3e5e163e3..00134c99b 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -1518,6 +1518,7 @@ fn test() {
1518 [167; 179) 'GLOBAL_CONST': u32 1518 [167; 179) 'GLOBAL_CONST': u32
1519 [189; 191) 'id': u32 1519 [189; 191) 'id': u32
1520 [194; 210) 'Foo::A..._CONST': u32 1520 [194; 210) 'Foo::A..._CONST': u32
1521 [126; 128) '99': u32
1521 "### 1522 "###
1522 ); 1523 );
1523} 1524}
@@ -1549,6 +1550,8 @@ fn test() {
1549 [233; 246) 'GLOBAL_STATIC': u32 1550 [233; 246) 'GLOBAL_STATIC': u32
1550 [256; 257) 'w': u32 1551 [256; 257) 'w': u32
1551 [260; 277) 'GLOBAL...IC_MUT': u32 1552 [260; 277) 'GLOBAL...IC_MUT': u32
1553 [118; 120) '99': u32
1554 [161; 163) '99': u32
1552 "### 1555 "###
1553 ); 1556 );
1554} 1557}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index ae316922b..0bc72644a 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -38,6 +38,63 @@ mod future {
38} 38}
39 39
40#[test] 40#[test]
41fn infer_async() {
42 let (db, pos) = TestDB::with_position(
43 r#"
44//- /main.rs crate:main deps:std
45
46async fn foo() -> u64 {
47 128
48}
49
50fn test() {
51 let r = foo();
52 let v = r.await;
53 v<|>;
54}
55
56//- /std.rs crate:std
57#[prelude_import] use future::*;
58mod future {
59 trait Future {
60 type Output;
61 }
62}
63
64"#,
65 );
66 assert_eq!("u64", type_at_pos(&db, pos));
67}
68
69#[test]
70fn infer_desugar_async() {
71 let (db, pos) = TestDB::with_position(
72 r#"
73//- /main.rs crate:main deps:std
74
75async fn foo() -> u64 {
76 128
77}
78
79fn test() {
80 let r = foo();
81 r<|>;
82}
83
84//- /std.rs crate:std
85#[prelude_import] use future::*;
86mod future {
87 trait Future {
88 type Output;
89 }
90}
91
92"#,
93 );
94 assert_eq!("impl Future<Output = u64>", type_at_pos(&db, pos));
95}
96
97#[test]
41fn infer_try() { 98fn infer_try() {
42 let (db, pos) = TestDB::with_position( 99 let (db, pos) = TestDB::with_position(
43 r#" 100 r#"