diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-12-29 16:58:29 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2019-12-29 16:58:29 +0000 |
commit | b30de4ed49be362ed8fd71ac367c90554441b079 (patch) | |
tree | 57a73fd5f720d5890b82999fafa897eac70f0749 | |
parent | 232785251bc80bc32c2ab52b624ecffbf5e35185 (diff) | |
parent | 8280795a85a9a6d5ec43fea00a023e0b7dc9aaa8 (diff) |
Merge #2679
2679: Resolve traits for infer using lang item infrastructure r=matklad a=kiljacken
As we already have the infrastructure for collecting lang items, use it to find the right traits when doing type-inference.
Co-authored-by: Emil Lauridsen <[email protected]>
-rw-r--r-- | crates/ra_hir_def/src/lang_item.rs | 44 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 5 |
5 files changed, 63 insertions, 14 deletions
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index cef061837..37c861a87 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs | |||
@@ -22,6 +22,50 @@ pub enum LangItemTarget { | |||
22 | TraitId(TraitId), | 22 | TraitId(TraitId), |
23 | } | 23 | } |
24 | 24 | ||
25 | impl LangItemTarget { | ||
26 | pub fn as_enum(self) -> Option<EnumId> { | ||
27 | match self { | ||
28 | LangItemTarget::EnumId(id) => Some(id), | ||
29 | _ => None, | ||
30 | } | ||
31 | } | ||
32 | |||
33 | pub fn as_function(self) -> Option<FunctionId> { | ||
34 | match self { | ||
35 | LangItemTarget::FunctionId(id) => Some(id), | ||
36 | _ => None, | ||
37 | } | ||
38 | } | ||
39 | |||
40 | pub fn as_impl_block(self) -> Option<ImplId> { | ||
41 | match self { | ||
42 | LangItemTarget::ImplBlockId(id) => Some(id), | ||
43 | _ => None, | ||
44 | } | ||
45 | } | ||
46 | |||
47 | pub fn as_static(self) -> Option<StaticId> { | ||
48 | match self { | ||
49 | LangItemTarget::StaticId(id) => Some(id), | ||
50 | _ => None, | ||
51 | } | ||
52 | } | ||
53 | |||
54 | pub fn as_struct(self) -> Option<StructId> { | ||
55 | match self { | ||
56 | LangItemTarget::StructId(id) => Some(id), | ||
57 | _ => None, | ||
58 | } | ||
59 | } | ||
60 | |||
61 | pub fn as_trait(self) -> Option<TraitId> { | ||
62 | match self { | ||
63 | LangItemTarget::TraitId(id) => Some(id), | ||
64 | _ => None, | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | |||
25 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 69 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
26 | pub struct LangItems { | 70 | pub struct LangItems { |
27 | items: FxHashMap<SmolStr, LangItemTarget>, | 71 | items: FxHashMap<SmolStr, LangItemTarget>, |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 107d2d799..82cfa67a9 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -260,12 +260,8 @@ macro_rules! __known_path { | |||
260 | (std::ops::RangeTo) => {}; | 260 | (std::ops::RangeTo) => {}; |
261 | (std::ops::RangeToInclusive) => {}; | 261 | (std::ops::RangeToInclusive) => {}; |
262 | (std::ops::RangeInclusive) => {}; | 262 | (std::ops::RangeInclusive) => {}; |
263 | (std::boxed::Box) => {}; | ||
264 | (std::future::Future) => {}; | 263 | (std::future::Future) => {}; |
265 | (std::ops::Try) => {}; | 264 | (std::ops::Try) => {}; |
266 | (std::ops::Neg) => {}; | ||
267 | (std::ops::Not) => {}; | ||
268 | (std::ops::Index) => {}; | ||
269 | ($path:path) => { | 265 | ($path:path) => { |
270 | compile_error!("Please register your known path in the path module") | 266 | compile_error!("Please register your known path in the path module") |
271 | }; | 267 | }; |
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::{ | |||
32 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; | 33 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
33 | use ra_arena::map::ArenaMap; | 34 | use ra_arena::map::ArenaMap; |
34 | use ra_prof::profile; | 35 | use ra_prof::profile; |
36 | use ra_syntax::SmolStr; | ||
35 | use test_utils::tested_by; | 37 | use test_utils::tested_by; |
36 | 38 | ||
37 | use super::{ | 39 | use 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/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 00134c99b..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() { | |||
20 | mod prelude {} | 20 | mod prelude {} |
21 | 21 | ||
22 | mod boxed { | 22 | mod 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 | } |
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::*; |
29 | mod future { | 29 | mod 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::*; |
58 | mod future { | 59 | mod 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::*; |
200 | mod ops { | 202 | mod 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::*; |
232 | mod ops { | 235 | mod 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::*; |
508 | mod ops { | 512 | mod ops { |
513 | #[lang = "index"] | ||
509 | pub trait Index<Idx> { | 514 | pub trait Index<Idx> { |
510 | type Output; | 515 | type Output; |
511 | } | 516 | } |