aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/code_model.rs78
-rw-r--r--crates/ra_hir/src/db.rs11
-rw-r--r--crates/ra_hir/src/ty.rs26
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs10
-rw-r--r--crates/ra_hir/src/ty/infer.rs65
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs10
-rw-r--r--crates/ra_hir/src/ty/infer/path.rs46
-rw-r--r--crates/ra_hir/src/ty/lower.rs230
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs25
-rw-r--r--crates/ra_hir/src/ty/traits.rs5
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs75
-rw-r--r--crates/ra_hir/src/ty/utils.rs63
12 files changed, 310 insertions, 334 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 821f919d4..c5cf39ee1 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -9,7 +9,7 @@ use hir_def::{
9 builtin_type::BuiltinType, 9 builtin_type::BuiltinType,
10 docs::Documentation, 10 docs::Documentation,
11 per_ns::PerNs, 11 per_ns::PerNs,
12 resolver::{HasResolver, TypeNs}, 12 resolver::HasResolver,
13 type_ref::{Mutability, TypeRef}, 13 type_ref::{Mutability, TypeRef},
14 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, 14 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId,
15 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, 15 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId,
@@ -28,8 +28,7 @@ use crate::{
28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
29 ty::display::HirFormatter, 29 ty::display::HirFormatter,
30 ty::{ 30 ty::{
31 self, InEnvironment, InferenceResult, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor, 31 self, InEnvironment, InferenceResult, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
32 TypeWalk,
33 }, 32 },
34 CallableDef, Either, HirDisplay, Name, Source, 33 CallableDef, Either, HirDisplay, Name, Source,
35}; 34};
@@ -354,11 +353,11 @@ impl Struct {
354 } 353 }
355 354
356 pub fn ty(self, db: &impl HirDatabase) -> Ty { 355 pub fn ty(self, db: &impl HirDatabase) -> Ty {
357 db.type_for_def(self.into(), Namespace::Types) 356 db.ty(self.id.into())
358 } 357 }
359 358
360 pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty { 359 pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty {
361 db.type_for_def(self.into(), Namespace::Values) 360 db.value_ty(self.id.into())
362 } 361 }
363 362
364 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 363 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
@@ -381,7 +380,7 @@ impl Union {
381 } 380 }
382 381
383 pub fn ty(self, db: &impl HirDatabase) -> Ty { 382 pub fn ty(self, db: &impl HirDatabase) -> Ty {
384 db.type_for_def(self.into(), Namespace::Types) 383 db.ty(self.id.into())
385 } 384 }
386 385
387 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 386 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
@@ -442,7 +441,7 @@ impl Enum {
442 } 441 }
443 442
444 pub fn ty(self, db: &impl HirDatabase) -> Ty { 443 pub fn ty(self, db: &impl HirDatabase) -> Ty {
445 db.type_for_def(self.into(), Namespace::Types) 444 db.ty(self.id.into())
446 } 445 }
447} 446}
448 447
@@ -617,7 +616,7 @@ impl Function {
617 } 616 }
618 617
619 pub fn ty(self, db: &impl HirDatabase) -> Ty { 618 pub fn ty(self, db: &impl HirDatabase) -> Ty {
620 db.type_for_def(self.into(), Namespace::Values) 619 db.value_ty(self.id.into())
621 } 620 }
622 621
623 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 622 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
@@ -737,68 +736,11 @@ impl Trait {
737 } 736 }
738 737
739 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { 738 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> {
740 db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect() 739 db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
741 }
742
743 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
744 let resolver = self.id.resolver(db);
745 // returning the iterator directly doesn't easily work because of
746 // lifetime problems, but since there usually shouldn't be more than a
747 // few direct traits this should be fine (we could even use some kind of
748 // SmallVec if performance is a concern)
749 db.generic_params(self.id.into())
750 .where_predicates
751 .iter()
752 .filter_map(|pred| match &pred.type_ref {
753 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
754 _ => None,
755 })
756 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
757 Some(TypeNs::TraitId(t)) => Some(t),
758 _ => None,
759 })
760 .map(Trait::from)
761 .collect()
762 }
763
764 /// Returns an iterator over the whole super trait hierarchy (including the
765 /// trait itself).
766 pub fn all_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
767 // we need to take care a bit here to avoid infinite loops in case of cycles
768 // (i.e. if we have `trait A: B; trait B: A;`)
769 let mut result = vec![self];
770 let mut i = 0;
771 while i < result.len() {
772 let t = result[i];
773 // yeah this is quadratic, but trait hierarchies should be flat
774 // enough that this doesn't matter
775 for tt in t.direct_super_traits(db) {
776 if !result.contains(&tt) {
777 result.push(tt);
778 }
779 }
780 i += 1;
781 }
782 result
783 }
784
785 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
786 let trait_data = db.trait_data(self.id);
787 let res =
788 trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?;
789 Some(res)
790 }
791
792 pub fn associated_type_by_name_including_super_traits(
793 self,
794 db: &impl HirDatabase,
795 name: &Name,
796 ) -> Option<TypeAlias> {
797 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
798 } 740 }
799 741
800 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { 742 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
801 TraitRef::for_trait(db, self) 743 TraitRef::for_trait(db, self.id)
802 } 744 }
803 745
804 pub fn is_auto(self, db: &impl DefDatabase) -> bool { 746 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
@@ -854,7 +796,7 @@ impl TypeAlias {
854 } 796 }
855 797
856 pub fn ty(self, db: &impl HirDatabase) -> Ty { 798 pub fn ty(self, db: &impl HirDatabase) -> Ty {
857 db.type_for_def(self.into(), Namespace::Types) 799 db.ty(self.id.into())
858 } 800 }
859 801
860 pub fn name(self, db: &impl DefDatabase) -> Name { 802 pub fn name(self, db: &impl DefDatabase) -> Name {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 32f05a4d8..3b5aa7516 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -9,8 +9,8 @@ use crate::{
9 ty::{ 9 ty::{
10 method_resolution::CrateImplBlocks, 10 method_resolution::CrateImplBlocks,
11 traits::{AssocTyValue, Impl}, 11 traits::{AssocTyValue, Impl},
12 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, 12 CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
13 TypeCtor, 13 ValueTyDefId,
14 }, 14 },
15 Crate, DefWithBody, ImplBlock, Trait, 15 Crate, DefWithBody, ImplBlock, Trait,
16}; 16};
@@ -37,8 +37,11 @@ pub trait HirDatabase: DefDatabase {
37 #[salsa::invoke(crate::ty::infer_query)] 37 #[salsa::invoke(crate::ty::infer_query)]
38 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>; 38 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
39 39
40 #[salsa::invoke(crate::ty::type_for_def)] 40 #[salsa::invoke(crate::ty::ty_query)]
41 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty; 41 fn ty(&self, def: TyDefId) -> Ty;
42
43 #[salsa::invoke(crate::ty::value_ty_query)]
44 fn value_ty(&self, def: ValueTyDefId) -> Ty;
42 45
43 #[salsa::invoke(crate::ty::field_types_query)] 46 #[salsa::invoke(crate::ty::field_types_query)]
44 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>; 47 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index bd03055b9..680ddc2f9 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -9,6 +9,7 @@ mod op;
9mod lower; 9mod lower;
10mod infer; 10mod infer;
11pub(crate) mod display; 11pub(crate) mod display;
12pub(crate) mod utils;
12 13
13#[cfg(test)] 14#[cfg(test)]
14mod tests; 15mod tests;
@@ -18,14 +19,16 @@ use std::sync::Arc;
18use std::{fmt, iter, mem}; 19use std::{fmt, iter, mem};
19 20
20use hir_def::{ 21use hir_def::{
21 generics::GenericParams, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, 22 expr::ExprId, generics::GenericParams, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId,
22 TraitId, TypeAliasId, 23 GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
23}; 24};
24use ra_db::{impl_intern_key, salsa}; 25use ra_db::{impl_intern_key, salsa};
25 26
26use crate::{ 27use crate::{
27 db::HirDatabase, expr::ExprId, util::make_mut_slice, Adt, Crate, FloatTy, IntTy, Mutability, 28 db::HirDatabase,
28 Name, Trait, Uncertain, 29 ty::primitive::{FloatTy, IntTy, Uncertain},
30 util::make_mut_slice,
31 Adt, Crate, Name,
29}; 32};
30use display::{HirDisplay, HirFormatter}; 33use display::{HirDisplay, HirFormatter};
31 34
@@ -34,8 +37,8 @@ pub(crate) use infer::{infer_query, InferTy, InferenceResult};
34pub use lower::CallableDef; 37pub use lower::CallableDef;
35pub(crate) use lower::{ 38pub(crate) use lower::{
36 callable_item_sig, field_types_query, generic_defaults_query, 39 callable_item_sig, field_types_query, generic_defaults_query,
37 generic_predicates_for_param_query, generic_predicates_query, type_for_def, Namespace, 40 generic_predicates_for_param_query, generic_predicates_query, ty_query, value_ty_query,
38 TypableDef, 41 TyDefId, TypableDef, ValueTyDefId,
39}; 42};
40pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 43pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
41 44
@@ -444,7 +447,7 @@ impl Deref for Substs {
444#[derive(Clone, PartialEq, Eq, Debug, Hash)] 447#[derive(Clone, PartialEq, Eq, Debug, Hash)]
445pub struct TraitRef { 448pub struct TraitRef {
446 /// FIXME name? 449 /// FIXME name?
447 pub trait_: Trait, 450 pub trait_: TraitId,
448 pub substs: Substs, 451 pub substs: Substs,
449} 452}
450 453
@@ -675,7 +678,7 @@ impl Ty {
675 } 678 }
676 679
677 /// If this is an `impl Trait` or `dyn Trait`, returns that trait. 680 /// If this is an `impl Trait` or `dyn Trait`, returns that trait.
678 pub fn inherent_trait(&self) -> Option<Trait> { 681 pub fn inherent_trait(&self) -> Option<TraitId> {
679 match self { 682 match self {
680 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 683 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
681 predicates.iter().find_map(|pred| match pred { 684 predicates.iter().find_map(|pred| match pred {
@@ -987,7 +990,10 @@ impl HirDisplay for Ty {
987 write!( 990 write!(
988 f, 991 f,
989 "{}", 992 "{}",
990 trait_ref.trait_.name(f.db).unwrap_or_else(Name::missing) 993 f.db.trait_data(trait_ref.trait_)
994 .name
995 .clone()
996 .unwrap_or_else(Name::missing)
991 )?; 997 )?;
992 if trait_ref.substs.len() > 1 { 998 if trait_ref.substs.len() > 1 {
993 write!(f, "<")?; 999 write!(f, "<")?;
@@ -1048,7 +1054,7 @@ impl TraitRef {
1048 } else { 1054 } else {
1049 write!(f, ": ")?; 1055 write!(f, ": ")?;
1050 } 1056 }
1051 write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?; 1057 write!(f, "{}", f.db.trait_data(self.trait_).name.clone().unwrap_or_else(Name::missing))?;
1052 if self.substs.len() > 1 { 1058 if self.substs.len() > 1 {
1053 write!(f, "<")?; 1059 write!(f, "<")?;
1054 f.write_joined(&self.substs[1..], ", ")?; 1060 f.write_joined(&self.substs[1..], ", ")?;
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 9e7593b8b..ae68234ac 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -10,7 +10,7 @@ use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId; 11use ra_db::CrateId;
12 12
13use crate::{db::HirDatabase, Trait}; 13use crate::db::HirDatabase;
14 14
15use super::{ 15use super::{
16 traits::{InEnvironment, Solution}, 16 traits::{InEnvironment, Solution},
@@ -49,12 +49,12 @@ fn deref_by_trait(
49 ty: InEnvironment<&Canonical<Ty>>, 49 ty: InEnvironment<&Canonical<Ty>>,
50) -> Option<Canonical<Ty>> { 50) -> Option<Canonical<Ty>> {
51 let deref_trait = match db.lang_item(krate.into(), "deref".into())? { 51 let deref_trait = match db.lang_item(krate.into(), "deref".into())? {
52 LangItemTarget::TraitId(t) => Trait::from(t), 52 LangItemTarget::TraitId(it) => it,
53 _ => return None, 53 _ => return None,
54 }; 54 };
55 let target = deref_trait.associated_type_by_name(db, &name::TARGET_TYPE)?; 55 let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?;
56 56
57 let generic_params = db.generic_params(target.id.into()); 57 let generic_params = db.generic_params(target.into());
58 if generic_params.count_params_including_parent() != 1 { 58 if generic_params.count_params_including_parent() != 1 {
59 // the Target type + Deref trait should only have one generic parameter, 59 // the Target type + Deref trait should only have one generic parameter,
60 // namely Deref's Self type 60 // namely Deref's Self type
@@ -69,7 +69,7 @@ fn deref_by_trait(
69 69
70 let projection = super::traits::ProjectionPredicate { 70 let projection = super::traits::ProjectionPredicate {
71 ty: Ty::Bound(0), 71 ty: Ty::Bound(0),
72 projection_ty: super::ProjectionTy { associated_ty: target.id, parameters }, 72 projection_ty: super::ProjectionTy { associated_ty: target, parameters },
73 }; 73 };
74 74
75 let obligation = super::Obligation::Projection(projection); 75 let obligation = super::Obligation::Projection(projection);
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index fce45321d..beb2efb7a 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -35,15 +35,15 @@ use test_utils::tested_by;
35 35
36use super::{ 36use super::{
37 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 37 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
38 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, 38 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
39 TypeCtor, TypeWalk, Uncertain, 39 TypeWalk, Uncertain,
40}; 40};
41use crate::{ 41use crate::{
42 code_model::TypeAlias, 42 code_model::TypeAlias,
43 db::HirDatabase, 43 db::HirDatabase,
44 expr::{BindingAnnotation, Body, ExprId, PatId}, 44 expr::{BindingAnnotation, Body, ExprId, PatId},
45 ty::infer::diagnostics::InferenceDiagnostic, 45 ty::infer::diagnostics::InferenceDiagnostic,
46 Adt, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, Trait, VariantDef, 46 AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, VariantDef,
47}; 47};
48 48
49macro_rules! ty_app { 49macro_rules! ty_app {
@@ -520,45 +520,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
520 None => return (Ty::Unknown, None), 520 None => return (Ty::Unknown, None),
521 }; 521 };
522 let resolver = &self.resolver; 522 let resolver = &self.resolver;
523 let def: TypableDef = 523 // FIXME: this should resolve assoc items as well, see this example:
524 // FIXME: this should resolve assoc items as well, see this example: 524 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
525 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 525 match resolver.resolve_path_in_type_ns_fully(self.db, &path) {
526 match resolver.resolve_path_in_type_ns_fully(self.db, &path) { 526 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
527 Some(TypeNs::AdtId(AdtId::StructId(it))) => it.into(), 527 let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into());
528 Some(TypeNs::AdtId(AdtId::UnionId(it))) => it.into(), 528 let ty = self.db.ty(strukt.into());
529 Some(TypeNs::AdtSelfType(adt)) => adt.into(),
530 Some(TypeNs::EnumVariantId(it)) => it.into(),
531 Some(TypeNs::TypeAliasId(it)) => it.into(),
532
533 Some(TypeNs::SelfType(_)) |
534 Some(TypeNs::GenericParam(_)) |
535 Some(TypeNs::BuiltinType(_)) |
536 Some(TypeNs::TraitId(_)) |
537 Some(TypeNs::AdtId(AdtId::EnumId(_))) |
538 None => {
539 return (Ty::Unknown, None)
540 }
541 };
542 // FIXME remove the duplication between here and `Ty::from_path`?
543 let substs = Ty::substs_from_path(self.db, resolver, path, def);
544 match def {
545 TypableDef::Adt(Adt::Struct(s)) => {
546 let ty = s.ty(self.db);
547 let ty = self.insert_type_vars(ty.apply_substs(substs)); 529 let ty = self.insert_type_vars(ty.apply_substs(substs));
548 (ty, Some(s.into())) 530 (ty, Some(VariantDef::Struct(strukt.into())))
549 } 531 }
550 TypableDef::EnumVariant(var) => { 532 Some(TypeNs::EnumVariantId(var)) => {
551 let ty = var.parent_enum(self.db).ty(self.db); 533 let substs = Ty::substs_from_path(self.db, resolver, path, var.into());
534 let ty = self.db.ty(var.parent.into());
552 let ty = self.insert_type_vars(ty.apply_substs(substs)); 535 let ty = self.insert_type_vars(ty.apply_substs(substs));
553 (ty, Some(var.into())) 536 (ty, Some(VariantDef::EnumVariant(var.into())))
554 } 537 }
555 TypableDef::Adt(Adt::Enum(_)) 538 Some(_) | None => (Ty::Unknown, None),
556 | TypableDef::Adt(Adt::Union(_))
557 | TypableDef::TypeAlias(_)
558 | TypableDef::Function(_)
559 | TypableDef::Const(_)
560 | TypableDef::Static(_)
561 | TypableDef::BuiltinType(_) => (Ty::Unknown, None),
562 } 539 }
563 } 540 }
564 541
@@ -582,20 +559,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
582 559
583 fn resolve_into_iter_item(&self) -> Option<TypeAlias> { 560 fn resolve_into_iter_item(&self) -> Option<TypeAlias> {
584 let path = known::std_iter_into_iterator(); 561 let path = known::std_iter_into_iterator();
585 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 562 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
586 trait_.associated_type_by_name(self.db, &name::ITEM_TYPE) 563 self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE).map(TypeAlias::from)
587 } 564 }
588 565
589 fn resolve_ops_try_ok(&self) -> Option<TypeAlias> { 566 fn resolve_ops_try_ok(&self) -> Option<TypeAlias> {
590 let path = known::std_ops_try(); 567 let path = known::std_ops_try();
591 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 568 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
592 trait_.associated_type_by_name(self.db, &name::OK_TYPE) 569 self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE).map(TypeAlias::from)
593 } 570 }
594 571
595 fn resolve_future_future_output(&self) -> Option<TypeAlias> { 572 fn resolve_future_future_output(&self) -> Option<TypeAlias> {
596 let path = known::std_future_future(); 573 let path = known::std_future_future();
597 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 574 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
598 trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE) 575 self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE).map(TypeAlias::from)
599 } 576 }
600 577
601 fn resolve_boxed_box(&self) -> Option<AdtId> { 578 fn resolve_boxed_box(&self) -> Option<AdtId> {
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index 3d0895dc6..eb221d6bc 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -17,8 +17,8 @@ use crate::{
17 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 17 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
18 ty::{ 18 ty::{
19 autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, 19 autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy,
20 Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, 20 Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
21 TypeCtor, TypeWalk, Uncertain, 21 TypeWalk, Uncertain,
22 }, 22 },
23 Name, 23 Name,
24}; 24};
@@ -558,11 +558,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
558 Some((ty, func)) => { 558 Some((ty, func)) => {
559 let ty = canonicalized_receiver.decanonicalize_ty(ty); 559 let ty = canonicalized_receiver.decanonicalize_ty(ty);
560 self.write_method_resolution(tgt_expr, func); 560 self.write_method_resolution(tgt_expr, func);
561 ( 561 (ty, self.db.value_ty(func.id.into()), Some(self.db.generic_params(func.id.into())))
562 ty,
563 self.db.type_for_def(func.into(), Namespace::Values),
564 Some(self.db.generic_params(func.id.into())),
565 )
566 } 562 }
567 None => (receiver_ty, Ty::Unknown, None), 563 None => (receiver_ty, Ty::Unknown, None),
568 }; 564 };
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs
index 6165eba4f..be2067dd4 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir/src/ty/infer/path.rs
@@ -7,7 +7,7 @@ use hir_def::{
7 7
8use crate::{ 8use crate::{
9 db::HirDatabase, 9 db::HirDatabase,
10 ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, 10 ty::{method_resolution, Substs, Ty, TypeWalk, ValueTyDefId},
11 AssocItem, Container, Function, Name, Path, 11 AssocItem, Container, Function, Name, Path,
12}; 12};
13 13
@@ -56,7 +56,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
56 } 56 }
57 }; 57 };
58 58
59 let typable: TypableDef = match value { 59 let typable: ValueTyDefId = match value {
60 ValueNs::LocalBinding(pat) => { 60 ValueNs::LocalBinding(pat) => {
61 let ty = self.result.type_of_pat.get(pat)?.clone(); 61 let ty = self.result.type_of_pat.get(pat)?.clone();
62 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 62 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
@@ -69,11 +69,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
69 ValueNs::EnumVariantId(it) => it.into(), 69 ValueNs::EnumVariantId(it) => it.into(),
70 }; 70 };
71 71
72 let mut ty = self.db.type_for_def(typable, Namespace::Values); 72 let mut ty = self.db.value_ty(typable);
73 if let Some(self_subst) = self_subst { 73 if let Some(self_subst) = self_subst {
74 ty = ty.subst(&self_subst); 74 ty = ty.subst(&self_subst);
75 } 75 }
76
77 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 76 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
78 let ty = ty.subst(&substs); 77 let ty = ty.subst(&substs);
79 Some(ty) 78 Some(ty)
@@ -143,24 +142,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
143 id: ExprOrPatId, 142 id: ExprOrPatId,
144 ) -> Option<(ValueNs, Option<Substs>)> { 143 ) -> Option<(ValueNs, Option<Substs>)> {
145 let trait_ = trait_ref.trait_; 144 let trait_ = trait_ref.trait_;
146 let item = trait_.items(self.db).iter().copied().find_map(|item| match item { 145 let item =
147 AssocItem::Function(func) => { 146 self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id).into()).find_map(
148 if segment.name == func.name(self.db) { 147 |item| match item {
149 Some(AssocItem::Function(func)) 148 AssocItem::Function(func) => {
150 } else { 149 if segment.name == func.name(self.db) {
151 None 150 Some(AssocItem::Function(func))
152 } 151 } else {
153 } 152 None
153 }
154 }
154 155
155 AssocItem::Const(konst) => { 156 AssocItem::Const(konst) => {
156 if konst.name(self.db).map_or(false, |n| n == segment.name) { 157 if konst.name(self.db).map_or(false, |n| n == segment.name) {
157 Some(AssocItem::Const(konst)) 158 Some(AssocItem::Const(konst))
158 } else { 159 } else {
159 None 160 None
160 } 161 }
161 } 162 }
162 AssocItem::TypeAlias(_) => None, 163 AssocItem::TypeAlias(_) => None,
163 })?; 164 },
165 )?;
164 let def = match item { 166 let def = match item {
165 AssocItem::Function(f) => ValueNs::FunctionId(f.id), 167 AssocItem::Function(f) => ValueNs::FunctionId(f.id),
166 AssocItem::Const(c) => ValueNs::ConstId(c.id), 168 AssocItem::Const(c) => ValueNs::ConstId(c.id),
@@ -212,7 +214,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
212 .fill_with_params() 214 .fill_with_params()
213 .build(); 215 .build();
214 self.obligations.push(super::Obligation::Trait(TraitRef { 216 self.obligations.push(super::Obligation::Trait(TraitRef {
215 trait_: t, 217 trait_: t.id,
216 substs: trait_substs, 218 substs: trait_substs,
217 })); 219 }));
218 Some(substs) 220 Some(substs)
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 2d23890a5..709492d21 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -14,8 +14,8 @@ use hir_def::{
14 path::{GenericArg, PathSegment}, 14 path::{GenericArg, PathSegment},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, AstItemDef, EnumVariantId, FunctionId, GenericDefId, HasModule, LocalStructFieldId, 17 AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule,
18 Lookup, StructId, VariantId, 18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
19}; 19};
20use ra_arena::map::ArenaMap; 20use ra_arena::map::ArenaMap;
21use ra_db::CrateId; 21use ra_db::CrateId;
@@ -28,24 +28,13 @@ use crate::{
28 db::HirDatabase, 28 db::HirDatabase,
29 ty::{ 29 ty::{
30 primitive::{FloatTy, IntTy}, 30 primitive::{FloatTy, IntTy},
31 Adt, 31 utils::{all_super_traits, associated_type_by_name_including_super_traits},
32 }, 32 },
33 util::make_mut_slice, 33 util::make_mut_slice,
34 Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait, 34 Adt, Const, Enum, EnumVariant, Function, ImplBlock, ModuleDef, Path, Static, Struct, Trait,
35 TypeAlias, Union, 35 TypeAlias, Union,
36}; 36};
37 37
38// FIXME: this is only really used in `type_for_def`, which contains a bunch of
39// impossible cases. Perhaps we should recombine `TypeableDef` and `Namespace`
40// into a `AsTypeDef`, `AsValueDef` enums?
41#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub enum Namespace {
43 Types,
44 Values,
45 // Note that only type inference uses this enum, and it doesn't care about macros.
46 // Macro,
47}
48
49impl Ty { 38impl Ty {
50 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { 39 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
51 match type_ref { 40 match type_ref {
@@ -169,14 +158,16 @@ impl Ty {
169 ); 158 );
170 return if remaining_segments.len() == 1 { 159 return if remaining_segments.len() == 1 {
171 let segment = &remaining_segments[0]; 160 let segment = &remaining_segments[0];
172 match trait_ref 161 let associated_ty = associated_type_by_name_including_super_traits(
173 .trait_ 162 db,
174 .associated_type_by_name_including_super_traits(db, &segment.name) 163 trait_ref.trait_,
175 { 164 &segment.name,
165 );
166 match associated_ty {
176 Some(associated_ty) => { 167 Some(associated_ty) => {
177 // FIXME handle type parameters on the segment 168 // FIXME handle type parameters on the segment
178 Ty::Projection(ProjectionTy { 169 Ty::Projection(ProjectionTy {
179 associated_ty: associated_ty.id, 170 associated_ty,
180 parameters: trait_ref.substs, 171 parameters: trait_ref.substs,
181 }) 172 })
182 } 173 }
@@ -260,18 +251,16 @@ impl Ty {
260 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), 251 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_),
261 _ => None, 252 _ => None,
262 }); 253 });
263 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); 254 let traits = traits_from_env.flat_map(|t| all_super_traits(db, t)).map(Trait::from);
264 for t in traits { 255 for t in traits {
265 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { 256 if let Some(associated_ty) = db.trait_data(t.id).associated_type_by_name(&segment.name)
257 {
266 let substs = Substs::build_for_def(db, t.id) 258 let substs = Substs::build_for_def(db, t.id)
267 .push(self_ty.clone()) 259 .push(self_ty.clone())
268 .fill_with_unknown() 260 .fill_with_unknown()
269 .build(); 261 .build();
270 // FIXME handle type parameters on the segment 262 // FIXME handle type parameters on the segment
271 return Ty::Projection(ProjectionTy { 263 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
272 associated_ty: associated_ty.id,
273 parameters: substs,
274 });
275 } 264 }
276 } 265 }
277 Ty::Unknown 266 Ty::Unknown
@@ -281,27 +270,15 @@ impl Ty {
281 db: &impl HirDatabase, 270 db: &impl HirDatabase,
282 resolver: &Resolver, 271 resolver: &Resolver,
283 segment: &PathSegment, 272 segment: &PathSegment,
284 typable: TypableDef, 273 typable: TyDefId,
285 ) -> Ty { 274 ) -> Ty {
286 let ty = db.type_for_def(typable, Namespace::Types); 275 let generic_def = match typable {
287 let substs = Ty::substs_from_path_segment(db, resolver, segment, typable); 276 TyDefId::BuiltinType(_) => None,
288 ty.subst(&substs) 277 TyDefId::AdtId(it) => Some(it.into()),
289 } 278 TyDefId::TypeAliasId(it) => Some(it.into()),
290
291 pub(super) fn substs_from_path_segment(
292 db: &impl HirDatabase,
293 resolver: &Resolver,
294 segment: &PathSegment,
295 resolved: TypableDef,
296 ) -> Substs {
297 let def_generic: Option<GenericDefId> = match resolved {
298 TypableDef::Function(func) => Some(func.id.into()),
299 TypableDef::Adt(adt) => Some(adt.into()),
300 TypableDef::EnumVariant(var) => Some(var.parent_enum(db).id.into()),
301 TypableDef::TypeAlias(t) => Some(t.id.into()),
302 TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None,
303 }; 279 };
304 substs_from_path_segment(db, resolver, segment, def_generic, false) 280 let substs = substs_from_path_segment(db, resolver, segment, generic_def, false);
281 db.ty(typable).subst(&substs)
305 } 282 }
306 283
307 /// Collect generic arguments from a path into a `Substs`. See also 284 /// Collect generic arguments from a path into a `Substs`. See also
@@ -310,17 +287,18 @@ impl Ty {
310 db: &impl HirDatabase, 287 db: &impl HirDatabase,
311 resolver: &Resolver, 288 resolver: &Resolver,
312 path: &Path, 289 path: &Path,
313 resolved: TypableDef, 290 // Note that we don't call `db.value_type(resolved)` here,
291 // `ValueTyDefId` is just a convenient way to pass generics and
292 // special-case enum variants
293 resolved: ValueTyDefId,
314 ) -> Substs { 294 ) -> Substs {
315 let last = path.segments.last().expect("path should have at least one segment"); 295 let last = path.segments.last().expect("path should have at least one segment");
316 let segment = match resolved { 296 let (segment, generic_def) = match resolved {
317 TypableDef::Function(_) 297 ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
318 | TypableDef::Adt(_) 298 ValueTyDefId::StructId(it) => (last, Some(it.into())),
319 | TypableDef::Const(_) 299 ValueTyDefId::ConstId(it) => (last, Some(it.into())),
320 | TypableDef::Static(_) 300 ValueTyDefId::StaticId(_) => (last, None),
321 | TypableDef::TypeAlias(_) 301 ValueTyDefId::EnumVariantId(var) => {
322 | TypableDef::BuiltinType(_) => last,
323 TypableDef::EnumVariant(_) => {
324 // the generic args for an enum variant may be either specified 302 // the generic args for an enum variant may be either specified
325 // on the segment referring to the enum, or on the segment 303 // on the segment referring to the enum, or on the segment
326 // referring to the variant. So `Option::<T>::None` and 304 // referring to the variant. So `Option::<T>::None` and
@@ -334,10 +312,10 @@ impl Ty {
334 // Option::None::<T> 312 // Option::None::<T>
335 last 313 last
336 }; 314 };
337 segment 315 (segment, Some(var.parent.into()))
338 } 316 }
339 }; 317 };
340 Ty::substs_from_path_segment(db, resolver, segment, resolved) 318 substs_from_path_segment(db, resolver, segment, generic_def, false)
341 } 319 }
342} 320}
343 321
@@ -422,7 +400,7 @@ impl TraitRef {
422 if let Some(self_ty) = explicit_self_ty { 400 if let Some(self_ty) = explicit_self_ty {
423 make_mut_slice(&mut substs.0)[0] = self_ty; 401 make_mut_slice(&mut substs.0)[0] = self_ty;
424 } 402 }
425 TraitRef { trait_: resolved, substs } 403 TraitRef { trait_: resolved.id, substs }
426 } 404 }
427 405
428 pub(crate) fn from_hir( 406 pub(crate) fn from_hir(
@@ -449,8 +427,8 @@ impl TraitRef {
449 substs_from_path_segment(db, resolver, segment, Some(resolved.id.into()), !has_self_param) 427 substs_from_path_segment(db, resolver, segment, Some(resolved.id.into()), !has_self_param)
450 } 428 }
451 429
452 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { 430 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: TraitId) -> TraitRef {
453 let substs = Substs::identity(&db.generic_params(trait_.id.into())); 431 let substs = Substs::identity(&db.generic_params(trait_.into()));
454 TraitRef { trait_, substs } 432 TraitRef { trait_, substs }
455 } 433 }
456 434
@@ -509,10 +487,11 @@ fn assoc_type_bindings_from_type_bound<'a>(
509 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 487 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
510 .map(move |(name, type_ref)| { 488 .map(move |(name, type_ref)| {
511 let associated_ty = 489 let associated_ty =
512 match trait_ref.trait_.associated_type_by_name_including_super_traits(db, &name) { 490 associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name);
513 None => return GenericPredicate::Error, 491 let associated_ty = match associated_ty {
514 Some(t) => t.id, 492 None => return GenericPredicate::Error,
515 }; 493 Some(t) => t,
494 };
516 let projection_ty = 495 let projection_ty =
517 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; 496 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
518 let ty = Ty::from_hir(db, resolver, type_ref); 497 let ty = Ty::from_hir(db, resolver, type_ref);
@@ -521,33 +500,6 @@ fn assoc_type_bindings_from_type_bound<'a>(
521 }) 500 })
522} 501}
523 502
524/// Build the declared type of an item. This depends on the namespace; e.g. for
525/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
526/// the constructor function `(usize) -> Foo` which lives in the values
527/// namespace.
528pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
529 match (def, ns) {
530 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
531 (TypableDef::Adt(Adt::Struct(s)), Namespace::Values) => type_for_struct_constructor(db, s),
532 (TypableDef::Adt(adt), Namespace::Types) => type_for_adt(db, adt),
533 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
534 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
535 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c),
536 (TypableDef::Static(c), Namespace::Values) => type_for_static(db, c),
537 (TypableDef::BuiltinType(t), Namespace::Types) => type_for_builtin(t),
538
539 // 'error' cases:
540 (TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
541 (TypableDef::Adt(Adt::Union(_)), Namespace::Values) => Ty::Unknown,
542 (TypableDef::Adt(Adt::Enum(_)), Namespace::Values) => Ty::Unknown,
543 (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
544 (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown,
545 (TypableDef::Const(_), Namespace::Types) => Ty::Unknown,
546 (TypableDef::Static(_), Namespace::Types) => Ty::Unknown,
547 (TypableDef::BuiltinType(_), Namespace::Values) => Ty::Unknown,
548 }
549}
550
551/// Build the signature of a callable item (function, struct or enum variant). 503/// Build the signature of a callable item (function, struct or enum variant).
552pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { 504pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig {
553 match def { 505 match def {
@@ -646,24 +598,24 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
646 598
647/// Build the declared type of a function. This should not need to look at the 599/// Build the declared type of a function. This should not need to look at the
648/// function body. 600/// function body.
649fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 601fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
650 let generics = db.generic_params(def.id.into()); 602 let generics = db.generic_params(def.into());
651 let substs = Substs::identity(&generics); 603 let substs = Substs::identity(&generics);
652 Ty::apply(TypeCtor::FnDef(def.id.into()), substs) 604 Ty::apply(TypeCtor::FnDef(def.into()), substs)
653} 605}
654 606
655/// Build the declared type of a const. 607/// Build the declared type of a const.
656fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { 608fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty {
657 let data = db.const_data(def.id); 609 let data = db.const_data(def);
658 let resolver = def.id.resolver(db); 610 let resolver = def.resolver(db);
659 611
660 Ty::from_hir(db, &resolver, &data.type_ref) 612 Ty::from_hir(db, &resolver, &data.type_ref)
661} 613}
662 614
663/// Build the declared type of a static. 615/// Build the declared type of a static.
664fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { 616fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty {
665 let data = db.static_data(def.id); 617 let data = db.static_data(def);
666 let resolver = def.id.resolver(db); 618 let resolver = def.resolver(db);
667 619
668 Ty::from_hir(db, &resolver, &data.type_ref) 620 Ty::from_hir(db, &resolver, &data.type_ref)
669} 621}
@@ -687,19 +639,19 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig
687 .iter() 639 .iter()
688 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 640 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
689 .collect::<Vec<_>>(); 641 .collect::<Vec<_>>();
690 let ret = type_for_adt(db, Struct::from(def)); 642 let ret = type_for_adt(db, def.into());
691 FnSig::from_params_and_return(params, ret) 643 FnSig::from_params_and_return(params, ret)
692} 644}
693 645
694/// Build the type of a tuple struct constructor. 646/// Build the type of a tuple struct constructor.
695fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 647fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
696 let struct_data = db.struct_data(def.id.into()); 648 let struct_data = db.struct_data(def.into());
697 if struct_data.variant_data.is_unit() { 649 if struct_data.variant_data.is_unit() {
698 return type_for_adt(db, def); // Unit struct 650 return type_for_adt(db, def.into()); // Unit struct
699 } 651 }
700 let generics = db.generic_params(def.id.into()); 652 let generics = db.generic_params(def.into());
701 let substs = Substs::identity(&generics); 653 let substs = Substs::identity(&generics);
702 Ty::apply(TypeCtor::FnDef(def.id.into()), substs) 654 Ty::apply(TypeCtor::FnDef(def.into()), substs)
703} 655}
704 656
705fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig { 657fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig {
@@ -713,34 +665,33 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId
713 .collect::<Vec<_>>(); 665 .collect::<Vec<_>>();
714 let generics = db.generic_params(def.parent.into()); 666 let generics = db.generic_params(def.parent.into());
715 let substs = Substs::identity(&generics); 667 let substs = Substs::identity(&generics);
716 let ret = type_for_adt(db, Enum::from(def.parent)).subst(&substs); 668 let ret = type_for_adt(db, def.parent.into()).subst(&substs);
717 FnSig::from_params_and_return(params, ret) 669 FnSig::from_params_and_return(params, ret)
718} 670}
719 671
720/// Build the type of a tuple enum variant constructor. 672/// Build the type of a tuple enum variant constructor.
721fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { 673fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty {
722 let var_data = def.variant_data(db); 674 let enum_data = db.enum_data(def.parent);
675 let var_data = &enum_data.variants[def.local_id].variant_data;
723 if var_data.is_unit() { 676 if var_data.is_unit() {
724 return type_for_adt(db, def.parent_enum(db)); // Unit variant 677 return type_for_adt(db, def.parent.into()); // Unit variant
725 } 678 }
726 let generics = db.generic_params(def.parent_enum(db).id.into()); 679 let generics = db.generic_params(def.parent.into());
727 let substs = Substs::identity(&generics); 680 let substs = Substs::identity(&generics);
728 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) 681 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
729} 682}
730 683
731fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty { 684fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
732 let adt = adt.into(); 685 let generics = db.generic_params(adt.into());
733 let adt_id: AdtId = adt.into(); 686 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
734 let generics = db.generic_params(adt_id.into());
735 Ty::apply(TypeCtor::Adt(adt_id), Substs::identity(&generics))
736} 687}
737 688
738fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 689fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
739 let generics = db.generic_params(t.id.into()); 690 let generics = db.generic_params(t.into());
740 let resolver = t.id.resolver(db); 691 let resolver = t.resolver(db);
741 let type_ref = t.type_ref(db); 692 let type_ref = &db.type_alias_data(t).type_ref;
742 let substs = Substs::identity(&generics); 693 let substs = Substs::identity(&generics);
743 let inner = Ty::from_hir(db, &resolver, &type_ref.unwrap_or(TypeRef::Error)); 694 let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error));
744 inner.subst(&substs) 695 inner.subst(&substs)
745} 696}
746 697
@@ -807,3 +758,42 @@ impl From<CallableDef> for GenericDefId {
807 } 758 }
808 } 759 }
809} 760}
761
762#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
763pub enum TyDefId {
764 BuiltinType(BuiltinType),
765 AdtId(AdtId),
766 TypeAliasId(TypeAliasId),
767}
768impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId);
769
770#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
771pub enum ValueTyDefId {
772 FunctionId(FunctionId),
773 StructId(StructId),
774 EnumVariantId(EnumVariantId),
775 ConstId(ConstId),
776 StaticId(StaticId),
777}
778impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId);
779
780/// Build the declared type of an item. This depends on the namespace; e.g. for
781/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
782/// the constructor function `(usize) -> Foo` which lives in the values
783/// namespace.
784pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty {
785 match def {
786 TyDefId::BuiltinType(it) => type_for_builtin(it),
787 TyDefId::AdtId(it) => type_for_adt(db, it),
788 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
789 }
790}
791pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
792 match def {
793 ValueTyDefId::FunctionId(it) => type_for_fn(db, it),
794 ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
795 ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
796 ValueTyDefId::ConstId(it) => type_for_const(db, it),
797 ValueTyDefId::StaticId(it) => type_for_static(db, it),
798 }
799}
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 489fcd64b..f1bc638ee 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -16,7 +16,7 @@ use rustc_hash::FxHashMap;
16use crate::{ 16use crate::{
17 db::HirDatabase, 17 db::HirDatabase,
18 ty::primitive::{FloatBitness, Uncertain}, 18 ty::primitive::{FloatBitness, Uncertain},
19 ty::{Ty, TypeCtor}, 19 ty::{utils::all_super_traits, Ty, TypeCtor},
20 AssocItem, Crate, Function, Mutability, Name, Trait, 20 AssocItem, Crate, Function, Mutability, Name, Trait,
21}; 21};
22 22
@@ -68,7 +68,7 @@ impl CrateImplBlocks {
68 if let Some(tr) = 68 if let Some(tr) =
69 TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty)) 69 TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty))
70 { 70 {
71 res.impls_by_trait.entry(tr.trait_.id).or_default().push(impl_id); 71 res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
72 } 72 }
73 } 73 }
74 None => { 74 None => {
@@ -249,19 +249,18 @@ fn iterate_trait_method_candidates<T>(
249 let traits_from_env = env 249 let traits_from_env = env
250 .trait_predicates_for_self_ty(&ty.value) 250 .trait_predicates_for_self_ty(&ty.value)
251 .map(|tr| tr.trait_) 251 .map(|tr| tr.trait_)
252 .flat_map(|t| t.all_super_traits(db)); 252 .flat_map(|t| all_super_traits(db, t));
253 let traits = inherent_trait 253 let traits =
254 .chain(traits_from_env) 254 inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter());
255 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from));
256 'traits: for t in traits { 255 'traits: for t in traits {
257 let data = db.trait_data(t.id); 256 let data = db.trait_data(t);
258 257
259 // we'll be lazy about checking whether the type implements the 258 // we'll be lazy about checking whether the type implements the
260 // trait, but if we find out it doesn't, we'll skip the rest of the 259 // trait, but if we find out it doesn't, we'll skip the rest of the
261 // iteration 260 // iteration
262 let mut known_implemented = false; 261 let mut known_implemented = false;
263 for &item in data.items.iter() { 262 for (_name, item) in data.items.iter() {
264 if !is_valid_candidate(db, name, mode, item.into()) { 263 if !is_valid_candidate(db, name, mode, (*item).into()) {
265 continue; 264 continue;
266 } 265 }
267 if !known_implemented { 266 if !known_implemented {
@@ -271,7 +270,7 @@ fn iterate_trait_method_candidates<T>(
271 } 270 }
272 } 271 }
273 known_implemented = true; 272 known_implemented = true;
274 if let Some(result) = callback(&ty.value, item.into()) { 273 if let Some(result) = callback(&ty.value, (*item).into()) {
275 return Some(result); 274 return Some(result);
276 } 275 }
277 } 276 }
@@ -329,7 +328,7 @@ pub(crate) fn implements_trait(
329 db: &impl HirDatabase, 328 db: &impl HirDatabase,
330 resolver: &Resolver, 329 resolver: &Resolver,
331 krate: Crate, 330 krate: Crate,
332 trait_: Trait, 331 trait_: TraitId,
333) -> bool { 332) -> bool {
334 if ty.value.inherent_trait() == Some(trait_) { 333 if ty.value.inherent_trait() == Some(trait_) {
335 // FIXME this is a bit of a hack, since Chalk should say the same thing 334 // FIXME this is a bit of a hack, since Chalk should say the same thing
@@ -372,11 +371,11 @@ impl Ty {
372fn generic_implements_goal( 371fn generic_implements_goal(
373 db: &impl HirDatabase, 372 db: &impl HirDatabase,
374 env: Arc<TraitEnvironment>, 373 env: Arc<TraitEnvironment>,
375 trait_: Trait, 374 trait_: TraitId,
376 self_ty: Canonical<Ty>, 375 self_ty: Canonical<Ty>,
377) -> Canonical<InEnvironment<super::Obligation>> { 376) -> Canonical<InEnvironment<super::Obligation>> {
378 let num_vars = self_ty.num_vars; 377 let num_vars = self_ty.num_vars;
379 let substs = super::Substs::build_for_def(db, trait_.id) 378 let substs = super::Substs::build_for_def(db, trait_)
380 .push(self_ty.value) 379 .push(self_ty.value)
381 .fill_with_bound_vars(num_vars as u32) 380 .fill_with_bound_vars(num_vars as u32)
382 .build(); 381 .build();
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 2eeb03099..a91c2476b 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -2,14 +2,15 @@
2use std::sync::{Arc, Mutex}; 2use std::sync::{Arc, Mutex};
3 3
4use chalk_ir::{cast::Cast, family::ChalkIr}; 4use chalk_ir::{cast::Cast, family::ChalkIr};
5use hir_def::DefWithBodyId; 5use hir_def::{expr::ExprId, DefWithBodyId};
6use log::debug; 6use log::debug;
7use ra_db::{impl_intern_key, salsa}; 7use ra_db::{impl_intern_key, salsa};
8use ra_prof::profile; 8use ra_prof::profile;
9use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
10 10
11use crate::{db::HirDatabase, Crate, ImplBlock, Trait, TypeAlias};
12
11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
12use crate::{db::HirDatabase, expr::ExprId, Crate, ImplBlock, Trait, TypeAlias};
13 14
14use self::chalk::{from_chalk, ToChalk}; 15use self::chalk::{from_chalk, ToChalk};
15 16
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 06388a3ce..4b0f4f56c 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -9,7 +9,9 @@ use chalk_ir::{
9}; 9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11 11
12use hir_def::{lang_item::LangItemTarget, ContainerId, GenericDefId, Lookup, TypeAliasId}; 12use hir_def::{
13 lang_item::LangItemTarget, AstItemDef, ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId,
14};
13use hir_expand::name; 15use hir_expand::name;
14 16
15use ra_db::salsa::{InternId, InternKey}; 17use ra_db::salsa::{InternId, InternKey};
@@ -19,7 +21,7 @@ use crate::{
19 db::HirDatabase, 21 db::HirDatabase,
20 ty::display::HirDisplay, 22 ty::display::HirDisplay,
21 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, 23 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
22 Crate, ImplBlock, Trait, TypeAlias, 24 Crate, ImplBlock, TypeAlias,
23}; 25};
24 26
25/// This represents a trait whose name we could not resolve. 27/// This represents a trait whose name we could not resolve.
@@ -167,15 +169,15 @@ impl ToChalk for TraitRef {
167 } 169 }
168} 170}
169 171
170impl ToChalk for Trait { 172impl ToChalk for TraitId {
171 type Chalk = chalk_ir::TraitId; 173 type Chalk = chalk_ir::TraitId;
172 174
173 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { 175 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId {
174 chalk_ir::TraitId(id_to_chalk(self.id)) 176 chalk_ir::TraitId(id_to_chalk(self))
175 } 177 }
176 178
177 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> Trait { 179 fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> TraitId {
178 Trait { id: id_from_chalk(trait_id.0) } 180 id_from_chalk(trait_id.0)
179 } 181 }
180} 182}
181 183
@@ -443,10 +445,10 @@ where
443 if trait_id == UNKNOWN_TRAIT { 445 if trait_id == UNKNOWN_TRAIT {
444 return Vec::new(); 446 return Vec::new();
445 } 447 }
446 let trait_: Trait = from_chalk(self.db, trait_id); 448 let trait_: TraitId = from_chalk(self.db, trait_id);
447 let mut result: Vec<_> = self 449 let mut result: Vec<_> = self
448 .db 450 .db
449 .impls_for_trait(self.krate, trait_) 451 .impls_for_trait(self.krate, trait_.into())
450 .iter() 452 .iter()
451 .copied() 453 .copied()
452 .map(Impl::ImplBlock) 454 .map(Impl::ImplBlock)
@@ -516,7 +518,7 @@ pub(crate) fn associated_ty_data_query(
516 where_clauses: vec![], 518 where_clauses: vec![],
517 }; 519 };
518 let datum = AssociatedTyDatum { 520 let datum = AssociatedTyDatum {
519 trait_id: Trait::from(trait_).to_chalk(db), 521 trait_id: trait_.to_chalk(db),
520 id, 522 id,
521 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), 523 name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()),
522 binders: make_binders(bound_data, generic_params.count_params_including_parent()), 524 binders: make_binders(bound_data, generic_params.count_params_including_parent()),
@@ -548,29 +550,23 @@ pub(crate) fn trait_datum_query(
548 associated_ty_ids: vec![], 550 associated_ty_ids: vec![],
549 }); 551 });
550 } 552 }
551 let trait_: Trait = from_chalk(db, trait_id); 553 let trait_: TraitId = from_chalk(db, trait_id);
552 debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); 554 let trait_data = db.trait_data(trait_);
553 let generic_params = db.generic_params(trait_.id.into()); 555 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
556 let generic_params = db.generic_params(trait_.into());
554 let bound_vars = Substs::bound_vars(&generic_params); 557 let bound_vars = Substs::bound_vars(&generic_params);
555 let flags = chalk_rust_ir::TraitFlags { 558 let flags = chalk_rust_ir::TraitFlags {
556 auto: trait_.is_auto(db), 559 auto: trait_data.auto,
557 upstream: trait_.module(db).krate() != krate, 560 upstream: trait_.module(db).krate != krate.crate_id,
558 non_enumerable: true, 561 non_enumerable: true,
559 coinductive: false, // only relevant for Chalk testing 562 coinductive: false, // only relevant for Chalk testing
560 // FIXME set these flags correctly 563 // FIXME set these flags correctly
561 marker: false, 564 marker: false,
562 fundamental: false, 565 fundamental: false,
563 }; 566 };
564 let where_clauses = convert_where_clauses(db, trait_.id.into(), &bound_vars); 567 let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
565 let associated_ty_ids = trait_ 568 let associated_ty_ids =
566 .items(db) 569 trait_data.associated_types().map(|type_alias| type_alias.to_chalk(db)).collect();
567 .into_iter()
568 .filter_map(|trait_item| match trait_item {
569 crate::AssocItem::TypeAlias(type_alias) => Some(type_alias.id),
570 _ => None,
571 })
572 .map(|type_alias| type_alias.to_chalk(db))
573 .collect();
574 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; 570 let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses };
575 let trait_datum = TraitDatum { 571 let trait_datum = TraitDatum {
576 id: trait_id, 572 id: trait_id,
@@ -661,6 +657,7 @@ fn impl_block_datum(
661 }; 657 };
662 658
663 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; 659 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses };
660 let trait_data = db.trait_data(trait_);
664 let associated_ty_value_ids = impl_block 661 let associated_ty_value_ids = impl_block
665 .items(db) 662 .items(db)
666 .into_iter() 663 .into_iter()
@@ -670,7 +667,7 @@ fn impl_block_datum(
670 }) 667 })
671 .filter(|type_alias| { 668 .filter(|type_alias| {
672 // don't include associated types that don't exist in the trait 669 // don't include associated types that don't exist in the trait
673 trait_.associated_type_by_name(db, &type_alias.name(db)).is_some() 670 trait_data.associated_type_by_name(&type_alias.name(db)).is_some()
674 }) 671 })
675 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) 672 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db))
676 .collect(); 673 .collect();
@@ -713,7 +710,7 @@ fn closure_fn_trait_impl_datum(
713 // and don't want to return a valid value only to find out later that FnOnce 710 // and don't want to return a valid value only to find out later that FnOnce
714 // is broken 711 // is broken
715 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; 712 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
716 fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; 713 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?;
717 714
718 let num_args: u16 = match &db.body(data.def.into())[data.expr] { 715 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
719 crate::expr::Expr::Lambda { args, .. } => args.len() as u16, 716 crate::expr::Expr::Lambda { args, .. } => args.len() as u16,
@@ -735,8 +732,8 @@ fn closure_fn_trait_impl_datum(
735 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 732 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
736 733
737 let trait_ref = TraitRef { 734 let trait_ref = TraitRef {
738 trait_, 735 trait_: trait_.into(),
739 substs: Substs::build_for_def(db, trait_.id).push(self_ty).push(arg_ty).build(), 736 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
740 }; 737 };
741 738
742 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); 739 let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db);
@@ -783,13 +780,13 @@ fn type_alias_associated_ty_value(
783 .target_trait_ref(db) 780 .target_trait_ref(db)
784 .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved 781 .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved
785 .trait_; 782 .trait_;
786 let assoc_ty = trait_ 783 let assoc_ty = db
787 .associated_type_by_name(db, &type_alias.name(db)) 784 .trait_data(trait_)
788 .expect("assoc ty value should not exist") // validated when building the impl data as well 785 .associated_type_by_name(&type_alias.name(db))
789 .id; 786 .expect("assoc ty value should not exist"); // validated when building the impl data as well
790 let generic_params = db.generic_params(impl_block.id.into()); 787 let generic_params = db.generic_params(impl_block.id.into());
791 let bound_vars = Substs::bound_vars(&generic_params); 788 let bound_vars = Substs::bound_vars(&generic_params);
792 let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); 789 let ty = db.ty(type_alias.id.into()).subst(&bound_vars);
793 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 790 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
794 let value = chalk_rust_ir::AssociatedTyValue { 791 let value = chalk_rust_ir::AssociatedTyValue {
795 impl_id, 792 impl_id,
@@ -819,10 +816,10 @@ fn closure_fn_trait_output_assoc_ty_value(
819 let fn_once_trait = 816 let fn_once_trait =
820 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); 817 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
821 818
822 let output_ty_id = fn_once_trait 819 let output_ty_id = db
823 .associated_type_by_name(db, &name::OUTPUT_TYPE) 820 .trait_data(fn_once_trait)
824 .expect("assoc ty value should not exist") 821 .associated_type_by_name(&name::OUTPUT_TYPE)
825 .id; 822 .expect("assoc ty value should not exist");
826 823
827 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; 824 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) };
828 825
@@ -834,10 +831,10 @@ fn closure_fn_trait_output_assoc_ty_value(
834 Arc::new(value) 831 Arc::new(value)
835} 832}
836 833
837fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { 834fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<TraitId> {
838 let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?; 835 let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?;
839 match target { 836 match target {
840 LangItemTarget::TraitId(t) => Some(t.into()), 837 LangItemTarget::TraitId(t) => Some(t),
841 _ => None, 838 _ => None,
842 } 839 }
843} 840}
diff --git a/crates/ra_hir/src/ty/utils.rs b/crates/ra_hir/src/ty/utils.rs
new file mode 100644
index 000000000..80ffceb4b
--- /dev/null
+++ b/crates/ra_hir/src/ty/utils.rs
@@ -0,0 +1,63 @@
1//! Helper functions for working with def, which don't need to be a separate
2//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
3
4use hir_def::{
5 db::DefDatabase,
6 resolver::{HasResolver, TypeNs},
7 type_ref::TypeRef,
8 TraitId, TypeAliasId,
9};
10use hir_expand::name::{self, Name};
11
12// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
13// We should return a `TraitREf` here.
14fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
15 let resolver = trait_.resolver(db);
16 // returning the iterator directly doesn't easily work because of
17 // lifetime problems, but since there usually shouldn't be more than a
18 // few direct traits this should be fine (we could even use some kind of
19 // SmallVec if performance is a concern)
20 db.generic_params(trait_.into())
21 .where_predicates
22 .iter()
23 .filter_map(|pred| match &pred.type_ref {
24 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
25 _ => None,
26 })
27 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
28 Some(TypeNs::TraitId(t)) => Some(t),
29 _ => None,
30 })
31 .collect()
32}
33
34/// Returns an iterator over the whole super trait hierarchy (including the
35/// trait itself).
36pub(super) fn all_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
37 // we need to take care a bit here to avoid infinite loops in case of cycles
38 // (i.e. if we have `trait A: B; trait B: A;`)
39 let mut result = vec![trait_];
40 let mut i = 0;
41 while i < result.len() {
42 let t = result[i];
43 // yeah this is quadratic, but trait hierarchies should be flat
44 // enough that this doesn't matter
45 for tt in direct_super_traits(db, t) {
46 if !result.contains(&tt) {
47 result.push(tt);
48 }
49 }
50 i += 1;
51 }
52 result
53}
54
55pub(super) fn associated_type_by_name_including_super_traits(
56 db: &impl DefDatabase,
57 trait_: TraitId,
58 name: &Name,
59) -> Option<TypeAliasId> {
60 all_super_traits(db, trait_)
61 .into_iter()
62 .find_map(|t| db.trait_data(t).associated_type_by_name(name))
63}