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/infer.rs23
-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.rs4
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs5
5 files changed, 114 insertions, 34 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 32c0d07a5..37e69599d 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -24,6 +24,7 @@ use hir_def::{
24 body::Body, 24 body::Body,
25 data::{ConstData, FunctionData}, 25 data::{ConstData, FunctionData},
26 expr::{BindingAnnotation, ExprId, PatId}, 26 expr::{BindingAnnotation, ExprId, PatId},
27 lang_item::LangItemTarget,
27 path::{path, Path}, 28 path::{path, Path},
28 resolver::{HasResolver, Resolver, TypeNs}, 29 resolver::{HasResolver, Resolver, TypeNs},
29 type_ref::{Mutability, TypeRef}, 30 type_ref::{Mutability, TypeRef},
@@ -32,6 +33,7 @@ use hir_def::{
32use hir_expand::{diagnostics::DiagnosticSink, name::name}; 33use hir_expand::{diagnostics::DiagnosticSink, name::name};
33use ra_arena::map::ArenaMap; 34use ra_arena::map::ArenaMap;
34use ra_prof::profile; 35use ra_prof::profile;
36use ra_syntax::SmolStr;
35use test_utils::tested_by; 37use test_utils::tested_by;
36 38
37use super::{ 39use super::{
@@ -482,6 +484,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
482 self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone())); 484 self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
483 } 485 }
484 486
487 fn resolve_lang_item(&self, name: &str) -> Option<LangItemTarget> {
488 let krate = self.resolver.krate()?;
489 let name = SmolStr::new_inline_from_ascii(name.len(), name.as_bytes());
490 self.db.lang_item(krate, name)
491 }
492
485 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> { 493 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
486 let path = path![std::iter::IntoIterator]; 494 let path = path![std::iter::IntoIterator];
487 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; 495 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
@@ -495,26 +503,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
495 } 503 }
496 504
497 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> { 505 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
498 let path = path![std::ops::Neg]; 506 let trait_ = self.resolve_lang_item("neg")?.as_trait()?;
499 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
500 self.db.trait_data(trait_).associated_type_by_name(&name![Output]) 507 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
501 } 508 }
502 509
503 fn resolve_ops_not_output(&self) -> Option<TypeAliasId> { 510 fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
504 let path = path![std::ops::Not]; 511 let trait_ = self.resolve_lang_item("not")?.as_trait()?;
505 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
506 self.db.trait_data(trait_).associated_type_by_name(&name![Output]) 512 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
507 } 513 }
508 514
509 fn resolve_future_future_output(&self) -> Option<TypeAliasId> { 515 fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
510 let path = path![std::future::Future]; 516 let trait_ = self.resolve_lang_item("future_trait")?.as_trait()?;
511 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
512 self.db.trait_data(trait_).associated_type_by_name(&name![Output]) 517 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
513 } 518 }
514 519
515 fn resolve_boxed_box(&self) -> Option<AdtId> { 520 fn resolve_boxed_box(&self) -> Option<AdtId> {
516 let path = path![std::boxed::Box]; 521 let struct_ = self.resolve_lang_item("owned_box")?.as_struct()?;
517 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
518 Some(struct_.into()) 522 Some(struct_.into())
519 } 523 }
520 524
@@ -555,8 +559,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
555 } 559 }
556 560
557 fn resolve_ops_index_output(&self) -> Option<TypeAliasId> { 561 fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
558 let path = path![std::ops::Index]; 562 let trait_ = self.resolve_lang_item("index")?.as_trait()?;
559 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
560 self.db.trait_data(trait_).associated_type_by_name(&name![Output]) 563 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
561 } 564 }
562} 565}
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..f7e042c12 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -20,6 +20,7 @@ fn test() {
20mod prelude {} 20mod prelude {}
21 21
22mod boxed { 22mod boxed {
23 #[lang = "owned_box"]
23 pub struct Box<T: ?Sized> { 24 pub struct Box<T: ?Sized> {
24 inner: *mut T, 25 inner: *mut T,
25 } 26 }
@@ -1518,6 +1519,7 @@ fn test() {
1518 [167; 179) 'GLOBAL_CONST': u32 1519 [167; 179) 'GLOBAL_CONST': u32
1519 [189; 191) 'id': u32 1520 [189; 191) 'id': u32
1520 [194; 210) 'Foo::A..._CONST': u32 1521 [194; 210) 'Foo::A..._CONST': u32
1522 [126; 128) '99': u32
1521 "### 1523 "###
1522 ); 1524 );
1523} 1525}
@@ -1549,6 +1551,8 @@ fn test() {
1549 [233; 246) 'GLOBAL_STATIC': u32 1551 [233; 246) 'GLOBAL_STATIC': u32
1550 [256; 257) 'w': u32 1552 [256; 257) 'w': u32
1551 [260; 277) 'GLOBAL...IC_MUT': u32 1553 [260; 277) 'GLOBAL...IC_MUT': u32
1554 [118; 120) '99': u32
1555 [161; 163) '99': u32
1552 "### 1556 "###
1553 ); 1557 );
1554} 1558}
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 0bc72644a..4b268510c 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -27,6 +27,7 @@ fn test() {
27//- /std.rs crate:std 27//- /std.rs crate:std
28#[prelude_import] use future::*; 28#[prelude_import] use future::*;
29mod future { 29mod future {
30 #[lang = "future_trait"]
30 trait Future { 31 trait Future {
31 type Output; 32 type Output;
32 } 33 }
@@ -56,6 +57,7 @@ fn test() {
56//- /std.rs crate:std 57//- /std.rs crate:std
57#[prelude_import] use future::*; 58#[prelude_import] use future::*;
58mod future { 59mod future {
60 #[lang = "future_trait"]
59 trait Future { 61 trait Future {
60 type Output; 62 type Output;
61 } 63 }
@@ -198,6 +200,7 @@ fn test() {
198 200
199#[prelude_import] use ops::*; 201#[prelude_import] use ops::*;
200mod ops { 202mod ops {
203 #[lang = "neg"]
201 pub trait Neg { 204 pub trait Neg {
202 type Output; 205 type Output;
203 } 206 }
@@ -230,6 +233,7 @@ fn test() {
230 233
231#[prelude_import] use ops::*; 234#[prelude_import] use ops::*;
232mod ops { 235mod ops {
236 #[lang = "not"]
233 pub trait Not { 237 pub trait Not {
234 type Output; 238 type Output;
235 } 239 }
@@ -506,6 +510,7 @@ fn test() {
506 510
507#[prelude_import] use ops::*; 511#[prelude_import] use ops::*;
508mod ops { 512mod ops {
513 #[lang = "index"]
509 pub trait Index<Idx> { 514 pub trait Index<Idx> {
510 type Output; 515 type Output;
511 } 516 }