aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assists/add_explicit_type.rs13
-rw-r--r--crates/ra_assists/src/assists/fill_match_arms.rs7
-rw-r--r--crates/ra_assists/src/test_db.rs3
-rw-r--r--crates/ra_cli/src/analysis_bench.rs4
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_hir/Cargo.toml11
-rw-r--r--crates/ra_hir/src/code_model.rs211
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/expr.rs4
-rw-r--r--crates/ra_hir/src/from_id.rs17
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/source_binder.rs46
-rw-r--r--crates/ra_hir/src/test_db.rs4
-rw-r--r--crates/ra_hir/src/ty.rs12
-rw-r--r--crates/ra_hir/src/ty/infer.rs4
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs12
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs21
-rw-r--r--crates/ra_hir/src/ty/lower.rs36
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs105
-rw-r--r--crates/ra_hir/src/ty/primitive.rs159
-rw-r--r--crates/ra_hir/src/ty/traits.rs4
-rw-r--r--crates/ra_hir_def/src/adt.rs4
-rw-r--r--crates/ra_hir_def/src/lib.rs10
-rw-r--r--crates/ra_hir_def/src/test_db.rs4
-rw-r--r--crates/ra_hir_expand/src/test_db.rs4
-rw-r--r--crates/ra_hir_ty/Cargo.toml32
-rw-r--r--crates/ra_hir_ty/src/lib.rs4
-rw-r--r--crates/ra_hir_ty/src/primitive.rs193
-rw-r--r--crates/ra_ide_api/src/call_info.rs4
-rw-r--r--crates/ra_ide_api/src/change.rs2
-rw-r--r--crates/ra_ide_api/src/completion/complete_dot.rs36
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs16
-rw-r--r--crates/ra_ide_api/src/completion/complete_record_literal.rs7
-rw-r--r--crates/ra_ide_api/src/completion/complete_record_pattern.rs7
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs39
-rw-r--r--crates/ra_ide_api/src/db.rs3
-rw-r--r--crates/ra_ide_api/src/goto_type_definition.rs4
-rw-r--r--crates/ra_ide_api/src/impls.rs10
-rw-r--r--crates/ra_ide_api/src/inlay_hints.rs23
-rw-r--r--crates/ra_ide_api/src/references/name_definition.rs1
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs9
-rw-r--r--crates/ra_lsp_server/Cargo.toml2
42 files changed, 675 insertions, 420 deletions
diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs
index 562a09685..eeb4ff39f 100644
--- a/crates/ra_assists/src/assists/add_explicit_type.rs
+++ b/crates/ra_assists/src/assists/add_explicit_type.rs
@@ -1,4 +1,4 @@
1use hir::{db::HirDatabase, HirDisplay, Ty}; 1use hir::{db::HirDatabase, HirDisplay};
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode, LetStmt, NameOwner}, 3 ast::{self, AstNode, LetStmt, NameOwner},
4 T, 4 T,
@@ -43,7 +43,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi
43 let analyzer = ctx.source_analyzer(stmt.syntax(), None); 43 let analyzer = ctx.source_analyzer(stmt.syntax(), None);
44 let ty = analyzer.type_of(db, &expr)?; 44 let ty = analyzer.type_of(db, &expr)?;
45 // Assist not applicable if the type is unknown 45 // Assist not applicable if the type is unknown
46 if is_unknown(&ty) { 46 if ty.contains_unknown() {
47 return None; 47 return None;
48 } 48 }
49 49
@@ -53,15 +53,6 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi
53 }) 53 })
54} 54}
55 55
56/// Returns true if any type parameter is unknown
57fn is_unknown(ty: &Ty) -> bool {
58 match ty {
59 Ty::Unknown => true,
60 Ty::Apply(a_ty) => a_ty.parameters.iter().any(is_unknown),
61 _ => false,
62 }
63}
64
65#[cfg(test)] 56#[cfg(test)]
66mod tests { 57mod tests {
67 use super::*; 58 use super::*;
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index 8482897c5..b75bd44eb 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -83,10 +83,11 @@ fn resolve_enum_def(
83) -> Option<ast::EnumDef> { 83) -> Option<ast::EnumDef> {
84 let expr_ty = analyzer.type_of(db, &expr)?; 84 let expr_ty = analyzer.type_of(db, &expr)?;
85 85
86 analyzer.autoderef(db, expr_ty).find_map(|ty| match ty.as_adt() { 86 let res = expr_ty.autoderef(db).find_map(|ty| match ty.as_adt() {
87 Some((Adt::Enum(e), _)) => Some(e.source(db).value), 87 Some(Adt::Enum(e)) => Some(e.source(db).value),
88 _ => None, 88 _ => None,
89 }) 89 });
90 res
90} 91}
91 92
92fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> { 93fn build_pat(var: ast::EnumVariant) -> Option<ast::Pat> {
diff --git a/crates/ra_assists/src/test_db.rs b/crates/ra_assists/src/test_db.rs
index 5f96c974b..523259fd4 100644
--- a/crates/ra_assists/src/test_db.rs
+++ b/crates/ra_assists/src/test_db.rs
@@ -21,6 +21,9 @@ impl salsa::Database for TestDB {
21 fn salsa_runtime(&self) -> &salsa::Runtime<Self> { 21 fn salsa_runtime(&self) -> &salsa::Runtime<Self> {
22 &self.runtime 22 &self.runtime
23 } 23 }
24 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
25 &mut self.runtime
26 }
24} 27}
25 28
26impl std::panic::RefUnwindSafe for TestDB {} 29impl std::panic::RefUnwindSafe for TestDB {}
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs
index 8bbe5d9e8..34105af57 100644
--- a/crates/ra_cli/src/analysis_bench.rs
+++ b/crates/ra_cli/src/analysis_bench.rs
@@ -91,7 +91,7 @@ fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, w
91 { 91 {
92 let start = Instant::now(); 92 let start = Instant::now();
93 eprint!("trivial change: "); 93 eprint!("trivial change: ");
94 host.raw_database().salsa_runtime().synthetic_write(Durability::LOW); 94 host.raw_database_mut().salsa_runtime_mut().synthetic_write(Durability::LOW);
95 work(&host.analysis()); 95 work(&host.analysis());
96 eprintln!("{:?}", start.elapsed()); 96 eprintln!("{:?}", start.elapsed());
97 } 97 }
@@ -111,7 +111,7 @@ fn do_work<F: Fn(&Analysis) -> T, T>(host: &mut AnalysisHost, file_id: FileId, w
111 { 111 {
112 let start = Instant::now(); 112 let start = Instant::now();
113 eprint!("const change: "); 113 eprint!("const change: ");
114 host.raw_database().salsa_runtime().synthetic_write(Durability::HIGH); 114 host.raw_database_mut().salsa_runtime_mut().synthetic_write(Durability::HIGH);
115 let res = work(&host.analysis()); 115 let res = work(&host.analysis());
116 eprintln!("{:?}", start.elapsed()); 116 eprintln!("{:?}", start.elapsed());
117 res 117 res
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index 4ec09b6d9..7afa5d8fc 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -8,7 +8,7 @@ authors = ["rust-analyzer developers"]
8doctest = false 8doctest = false
9 9
10[dependencies] 10[dependencies]
11salsa = "0.13.0" 11salsa = "0.14.1"
12relative-path = "1.0.0" 12relative-path = "1.0.0"
13rustc-hash = "1.0" 13rustc-hash = "1.0"
14 14
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 42ddfecc9..caba85a4f 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
11arrayvec = "0.5.1" 11arrayvec = "0.5.1"
12log = "0.4.5" 12log = "0.4.5"
13rustc-hash = "1.0" 13rustc-hash = "1.0"
14parking_lot = "0.9.0" 14parking_lot = "0.10.0"
15ena = "0.13" 15ena = "0.13"
16once_cell = "1.0.1" 16once_cell = "1.0.1"
17 17
@@ -23,12 +23,15 @@ mbe = { path = "../ra_mbe", package = "ra_mbe" }
23tt = { path = "../ra_tt", package = "ra_tt" } 23tt = { path = "../ra_tt", package = "ra_tt" }
24hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" } 24hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" }
25hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } 25hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
26hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }
26test_utils = { path = "../test_utils" } 27test_utils = { path = "../test_utils" }
27ra_prof = { path = "../ra_prof" } 28ra_prof = { path = "../ra_prof" }
28 29
29chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" } 30# https://github.com/rust-lang/chalk/pull/294
30chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" } 31chalk-solve = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" }
31chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" } 32chalk-rust-ir = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" }
33chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" }
34
32lalrpop-intern = "0.15.1" 35lalrpop-intern = "0.15.1"
33 36
34[dev-dependencies] 37[dev-dependencies]
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index f7fc80d4e..821f919d4 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -10,10 +10,10 @@ use hir_def::{
10 docs::Documentation, 10 docs::Documentation,
11 per_ns::PerNs, 11 per_ns::PerNs,
12 resolver::{HasResolver, TypeNs}, 12 resolver::{HasResolver, TypeNs},
13 type_ref::TypeRef, 13 type_ref::{Mutability, TypeRef},
14 AstItemDef, ConstId, ContainerId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, 14 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId,
15 LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, 15 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId,
16 StaticId, StructId, TraitId, TypeAliasId, UnionId, 16 Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
17}; 17};
18use hir_expand::{ 18use hir_expand::{
19 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
@@ -26,8 +26,12 @@ use ra_syntax::{ast, AstNode, SyntaxNode};
26use crate::{ 26use crate::{
27 db::{DefDatabase, HirDatabase}, 27 db::{DefDatabase, HirDatabase},
28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
29 ty::{InferenceResult, Namespace, TraitRef}, 29 ty::display::HirFormatter,
30 Either, Name, Source, Ty, 30 ty::{
31 self, InEnvironment, InferenceResult, Namespace, TraitEnvironment, TraitRef, Ty, TypeCtor,
32 TypeWalk,
33 },
34 CallableDef, Either, HirDisplay, Name, Source,
31}; 35};
32 36
33/// hir::Crate describes a single crate. It's the main interface with which 37/// hir::Crate describes a single crate. It's the main interface with which
@@ -379,6 +383,28 @@ impl Union {
379 pub fn ty(self, db: &impl HirDatabase) -> Ty { 383 pub fn ty(self, db: &impl HirDatabase) -> Ty {
380 db.type_for_def(self.into(), Namespace::Types) 384 db.type_for_def(self.into(), Namespace::Types)
381 } 385 }
386
387 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
388 db.union_data(self.id)
389 .variant_data
390 .fields()
391 .iter()
392 .map(|(id, _)| StructField { parent: self.into(), id })
393 .collect()
394 }
395
396 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
397 db.union_data(self.id)
398 .variant_data
399 .fields()
400 .iter()
401 .find(|(_id, data)| data.name == *name)
402 .map(|(id, _)| StructField { parent: self.into(), id })
403 }
404
405 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
406 db.union_data(self.id).variant_data.clone()
407 }
382} 408}
383 409
384#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 410#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -469,6 +495,10 @@ pub enum Adt {
469impl_froms!(Adt: Struct, Union, Enum); 495impl_froms!(Adt: Struct, Union, Enum);
470 496
471impl Adt { 497impl Adt {
498 pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool {
499 let subst = db.generic_defaults(self.into());
500 subst.iter().any(|ty| ty == &Ty::Unknown)
501 }
472 pub fn ty(self, db: &impl HirDatabase) -> Ty { 502 pub fn ty(self, db: &impl HirDatabase) -> Ty {
473 match self { 503 match self {
474 Adt::Struct(it) => it.ty(db), 504 Adt::Struct(it) => it.ty(db),
@@ -493,14 +523,16 @@ impl Adt {
493#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 523#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
494pub enum VariantDef { 524pub enum VariantDef {
495 Struct(Struct), 525 Struct(Struct),
526 Union(Union),
496 EnumVariant(EnumVariant), 527 EnumVariant(EnumVariant),
497} 528}
498impl_froms!(VariantDef: Struct, EnumVariant); 529impl_froms!(VariantDef: Struct, Union, EnumVariant);
499 530
500impl VariantDef { 531impl VariantDef {
501 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 532 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
502 match self { 533 match self {
503 VariantDef::Struct(it) => it.fields(db), 534 VariantDef::Struct(it) => it.fields(db),
535 VariantDef::Union(it) => it.fields(db),
504 VariantDef::EnumVariant(it) => it.fields(db), 536 VariantDef::EnumVariant(it) => it.fields(db),
505 } 537 }
506 } 538 }
@@ -508,6 +540,7 @@ impl VariantDef {
508 pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { 540 pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
509 match self { 541 match self {
510 VariantDef::Struct(it) => it.field(db, name), 542 VariantDef::Struct(it) => it.field(db, name),
543 VariantDef::Union(it) => it.field(db, name),
511 VariantDef::EnumVariant(it) => it.field(db, name), 544 VariantDef::EnumVariant(it) => it.field(db, name),
512 } 545 }
513 } 546 }
@@ -515,6 +548,7 @@ impl VariantDef {
515 pub fn module(self, db: &impl HirDatabase) -> Module { 548 pub fn module(self, db: &impl HirDatabase) -> Module {
516 match self { 549 match self {
517 VariantDef::Struct(it) => it.module(db), 550 VariantDef::Struct(it) => it.module(db),
551 VariantDef::Union(it) => it.module(db),
518 VariantDef::EnumVariant(it) => it.module(db), 552 VariantDef::EnumVariant(it) => it.module(db),
519 } 553 }
520 } 554 }
@@ -522,6 +556,7 @@ impl VariantDef {
522 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 556 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
523 match self { 557 match self {
524 VariantDef::Struct(it) => it.variant_data(db), 558 VariantDef::Struct(it) => it.variant_data(db),
559 VariantDef::Union(it) => it.variant_data(db),
525 VariantDef::EnumVariant(it) => it.variant_data(db), 560 VariantDef::EnumVariant(it) => it.variant_data(db),
526 } 561 }
527 } 562 }
@@ -777,6 +812,11 @@ pub struct TypeAlias {
777} 812}
778 813
779impl TypeAlias { 814impl TypeAlias {
815 pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool {
816 let subst = db.generic_defaults(self.id.into());
817 subst.iter().any(|ty| ty == &Ty::Unknown)
818 }
819
780 pub fn module(self, db: &impl DefDatabase) -> Module { 820 pub fn module(self, db: &impl DefDatabase) -> Module {
781 Module { id: self.id.lookup(db).module(db) } 821 Module { id: self.id.lookup(db).module(db) }
782 } 822 }
@@ -927,9 +967,14 @@ impl Local {
927 self.parent.module(db) 967 self.parent.module(db)
928 } 968 }
929 969
930 pub fn ty(self, db: &impl HirDatabase) -> Ty { 970 pub fn ty(self, db: &impl HirDatabase) -> Type {
931 let infer = db.infer(self.parent); 971 let infer = db.infer(self.parent);
932 infer[self.pat_id].clone() 972 let ty = infer[self.pat_id].clone();
973 let def = DefWithBodyId::from(self.parent);
974 let resolver = def.resolver(db);
975 let krate = def.module(db).krate;
976 let environment = TraitEnvironment::lower(db, &resolver);
977 Type { krate, ty: InEnvironment { value: ty, environment } }
933 } 978 }
934 979
935 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { 980 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> {
@@ -952,6 +997,15 @@ pub struct ImplBlock {
952} 997}
953 998
954impl ImplBlock { 999impl ImplBlock {
1000 pub fn all_in_crate(db: &impl HirDatabase, krate: Crate) -> Vec<ImplBlock> {
1001 let impls = db.impls_in_crate(krate.crate_id);
1002 impls.all_impls().map(Self::from).collect()
1003 }
1004 pub fn for_trait(db: &impl HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplBlock> {
1005 let impls = db.impls_in_crate(krate.crate_id);
1006 impls.lookup_impl_blocks_for_trait(trait_).map(Self::from).collect()
1007 }
1008
955 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { 1009 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
956 db.impl_data(self.id).target_trait.clone() 1010 db.impl_data(self.id).target_trait.clone()
957 } 1011 }
@@ -986,6 +1040,145 @@ impl ImplBlock {
986 } 1040 }
987} 1041}
988 1042
1043#[derive(Clone, PartialEq, Eq)]
1044pub struct Type {
1045 pub(crate) krate: CrateId,
1046 pub(crate) ty: InEnvironment<Ty>,
1047}
1048
1049impl Type {
1050 pub fn is_bool(&self) -> bool {
1051 match &self.ty.value {
1052 Ty::Apply(a_ty) => match a_ty.ctor {
1053 TypeCtor::Bool => true,
1054 _ => false,
1055 },
1056 _ => false,
1057 }
1058 }
1059
1060 pub fn is_mutable_reference(&self) -> bool {
1061 match &self.ty.value {
1062 Ty::Apply(a_ty) => match a_ty.ctor {
1063 TypeCtor::Ref(Mutability::Mut) => true,
1064 _ => false,
1065 },
1066 _ => false,
1067 }
1068 }
1069
1070 pub fn is_unknown(&self) -> bool {
1071 match &self.ty.value {
1072 Ty::Unknown => true,
1073 _ => false,
1074 }
1075 }
1076
1077 // FIXME: this method is broken, as it doesn't take closures into account.
1078 pub fn as_callable(&self) -> Option<CallableDef> {
1079 Some(self.ty.value.as_callable()?.0)
1080 }
1081
1082 pub fn contains_unknown(&self) -> bool {
1083 return go(&self.ty.value);
1084
1085 fn go(ty: &Ty) -> bool {
1086 match ty {
1087 Ty::Unknown => true,
1088 Ty::Apply(a_ty) => a_ty.parameters.iter().any(go),
1089 _ => false,
1090 }
1091 }
1092 }
1093
1094 pub fn fields(&self, db: &impl HirDatabase) -> Vec<(StructField, Type)> {
1095 if let Ty::Apply(a_ty) = &self.ty.value {
1096 match a_ty.ctor {
1097 ty::TypeCtor::Adt(AdtId::StructId(s)) => {
1098 let var_def = s.into();
1099 return db
1100 .field_types(var_def)
1101 .iter()
1102 .map(|(local_id, ty)| {
1103 let def = StructField { parent: var_def.into(), id: local_id };
1104 let ty = ty.clone().subst(&a_ty.parameters);
1105 (def, self.derived(ty))
1106 })
1107 .collect();
1108 }
1109 _ => {}
1110 }
1111 };
1112 Vec::new()
1113 }
1114
1115 pub fn tuple_fields(&self, _db: &impl HirDatabase) -> Vec<Type> {
1116 let mut res = Vec::new();
1117 if let Ty::Apply(a_ty) = &self.ty.value {
1118 match a_ty.ctor {
1119 ty::TypeCtor::Tuple { .. } => {
1120 for ty in a_ty.parameters.iter() {
1121 let ty = ty.clone().subst(&a_ty.parameters);
1122 res.push(self.derived(ty));
1123 }
1124 }
1125 _ => {}
1126 }
1127 };
1128 res
1129 }
1130
1131 pub fn variant_fields(
1132 &self,
1133 db: &impl HirDatabase,
1134 def: VariantDef,
1135 ) -> Vec<(StructField, Type)> {
1136 // FIXME: check that ty and def match
1137 match &self.ty.value {
1138 Ty::Apply(a_ty) => def
1139 .fields(db)
1140 .into_iter()
1141 .map(|it| (it, self.derived(it.ty(db).subst(&a_ty.parameters))))
1142 .collect(),
1143 _ => Vec::new(),
1144 }
1145 }
1146
1147 pub fn autoderef<'a>(&'a self, db: &'a impl HirDatabase) -> impl Iterator<Item = Type> + 'a {
1148 // There should be no inference vars in types passed here
1149 // FIXME check that?
1150 let canonical = crate::ty::Canonical { value: self.ty.value.clone(), num_vars: 0 };
1151 let environment = self.ty.environment.clone();
1152 let ty = InEnvironment { value: canonical, environment: environment.clone() };
1153 ty::autoderef(db, Some(self.krate), ty)
1154 .map(|canonical| canonical.value)
1155 .map(move |ty| self.derived(ty))
1156 }
1157
1158 // FIXME: remove
1159 pub fn into_ty(self) -> Ty {
1160 self.ty.value
1161 }
1162
1163 pub fn as_adt(&self) -> Option<Adt> {
1164 let (adt, _subst) = self.ty.value.as_adt()?;
1165 Some(adt)
1166 }
1167
1168 fn derived(&self, ty: Ty) -> Type {
1169 Type {
1170 krate: self.krate,
1171 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
1172 }
1173 }
1174}
1175
1176impl HirDisplay for Type {
1177 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> std::fmt::Result {
1178 self.ty.value.hir_fmt(f)
1179 }
1180}
1181
989/// For IDE only 1182/// For IDE only
990pub enum ScopeDef { 1183pub enum ScopeDef {
991 ModuleDef(ModuleDef), 1184 ModuleDef(ModuleDef),
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index b034d4e44..32f05a4d8 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -3,7 +3,7 @@
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use ra_arena::map::ArenaMap; 5use ra_arena::map::ArenaMap;
6use ra_db::salsa; 6use ra_db::{salsa, CrateId};
7 7
8use crate::{ 8use crate::{
9 ty::{ 9 ty::{
@@ -60,7 +60,7 @@ pub trait HirDatabase: DefDatabase {
60 fn generic_defaults(&self, def: GenericDefId) -> Substs; 60 fn generic_defaults(&self, def: GenericDefId) -> Substs;
61 61
62 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 62 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
63 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 63 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplBlocks>;
64 64
65 #[salsa::invoke(crate::ty::traits::impls_for_trait_query)] 65 #[salsa::invoke(crate::ty::traits::impls_for_trait_query)]
66 fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>; 66 fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>;
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 43fedde7a..adb9805ab 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -2,7 +2,7 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{path::known, resolver::HasResolver}; 5use hir_def::{path::known, resolver::HasResolver, AdtId};
6use hir_expand::diagnostics::DiagnosticSink; 6use hir_expand::diagnostics::DiagnosticSink;
7use ra_syntax::ast; 7use ra_syntax::ast;
8use ra_syntax::AstPtr; 8use ra_syntax::AstPtr;
@@ -127,7 +127,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
127 _ => return, 127 _ => return,
128 }; 128 };
129 129
130 let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum.into())); 130 let std_result_ctor = TypeCtor::Adt(AdtId::EnumId(std_result_enum));
131 let params = match &mismatch.expected { 131 let params = match &mismatch.expected {
132 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, 132 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters,
133 _ => return, 133 _ => return,
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
index 619f6055e..38daa5e59 100644
--- a/crates/ra_hir/src/from_id.rs
+++ b/crates/ra_hir/src/from_id.rs
@@ -199,11 +199,22 @@ impl From<Adt> for GenericDefId {
199 } 199 }
200} 200}
201 201
202impl From<VariantId> for VariantDef {
203 fn from(def: VariantId) -> Self {
204 match def {
205 VariantId::StructId(it) => VariantDef::Struct(it.into()),
206 VariantId::EnumVariantId(it) => VariantDef::EnumVariant(it.into()),
207 VariantId::UnionId(it) => VariantDef::Union(it.into()),
208 }
209 }
210}
211
202impl From<VariantDef> for VariantId { 212impl From<VariantDef> for VariantId {
203 fn from(def: VariantDef) -> Self { 213 fn from(def: VariantDef) -> Self {
204 match def { 214 match def {
205 VariantDef::Struct(it) => VariantId::StructId(it.id), 215 VariantDef::Struct(it) => VariantId::StructId(it.id),
206 VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()), 216 VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()),
217 VariantDef::Union(it) => VariantId::UnionId(it.id),
207 } 218 }
208 } 219 }
209} 220}
@@ -214,6 +225,12 @@ impl From<StructField> for StructFieldId {
214 } 225 }
215} 226}
216 227
228impl From<StructFieldId> for StructField {
229 fn from(def: StructFieldId) -> Self {
230 StructField { parent: def.parent.into(), id: def.local_id }
231 }
232}
233
217impl From<AttrDef> for AttrDefId { 234impl From<AttrDef> for AttrDefId {
218 fn from(def: AttrDef) -> Self { 235 fn from(def: AttrDef) -> Self {
219 match def { 236 match def {
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 843ce6a88..b88e4c745 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -51,7 +51,7 @@ pub use crate::{
51 src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, 51 src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency,
52 DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, 52 DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam,
53 HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, 53 HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef,
54 Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, 54 Static, Struct, StructField, Trait, Type, TypeAlias, Union, VariantDef,
55 }, 55 },
56 expr::ExprScopes, 56 expr::ExprScopes,
57 from_source::FromSource, 57 from_source::FromSource,
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 144e144bb..82cb66583 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -29,10 +29,10 @@ use crate::{
29 expr::{BodySourceMap, ExprScopes, ScopeId}, 29 expr::{BodySourceMap, ExprScopes, ScopeId},
30 ty::{ 30 ty::{
31 method_resolution::{self, implements_trait}, 31 method_resolution::{self, implements_trait},
32 TraitEnvironment, 32 InEnvironment, TraitEnvironment, Ty,
33 }, 33 },
34 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, 34 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function,
35 GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, 35 GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias,
36}; 36};
37 37
38fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { 38fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> {
@@ -199,14 +199,18 @@ impl SourceAnalyzer {
199 self.body_source_map.as_ref()?.node_pat(src) 199 self.body_source_map.as_ref()?.node_pat(src)
200 } 200 }
201 201
202 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { 202 pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> {
203 let expr_id = self.expr_id(expr)?; 203 let expr_id = self.expr_id(expr)?;
204 Some(self.infer.as_ref()?[expr_id].clone()) 204 let ty = self.infer.as_ref()?[expr_id].clone();
205 let environment = TraitEnvironment::lower(db, &self.resolver);
206 Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } })
205 } 207 }
206 208
207 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { 209 pub fn type_of_pat(&self, db: &impl HirDatabase, pat: &ast::Pat) -> Option<Type> {
208 let pat_id = self.pat_id(pat)?; 210 let pat_id = self.pat_id(pat)?;
209 Some(self.infer.as_ref()?[pat_id].clone()) 211 let ty = self.infer.as_ref()?[pat_id].clone();
212 let environment = TraitEnvironment::lower(db, &self.resolver);
213 Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } })
210 } 214 }
211 215
212 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 216 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
@@ -362,14 +366,14 @@ impl SourceAnalyzer {
362 pub fn iterate_method_candidates<T>( 366 pub fn iterate_method_candidates<T>(
363 &self, 367 &self,
364 db: &impl HirDatabase, 368 db: &impl HirDatabase,
365 ty: Ty, 369 ty: &Type,
366 name: Option<&Name>, 370 name: Option<&Name>,
367 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 371 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
368 ) -> Option<T> { 372 ) -> Option<T> {
369 // There should be no inference vars in types passed here 373 // There should be no inference vars in types passed here
370 // FIXME check that? 374 // FIXME check that?
371 // FIXME replace Unknown by bound vars here 375 // FIXME replace Unknown by bound vars here
372 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 376 let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 };
373 method_resolution::iterate_method_candidates( 377 method_resolution::iterate_method_candidates(
374 &canonical, 378 &canonical,
375 db, 379 db,
@@ -404,19 +408,19 @@ impl SourceAnalyzer {
404 ) 408 )
405 } 409 }
406 410
407 pub fn autoderef<'a>( 411 // pub fn autoderef<'a>(
408 &'a self, 412 // &'a self,
409 db: &'a impl HirDatabase, 413 // db: &'a impl HirDatabase,
410 ty: Ty, 414 // ty: Ty,
411 ) -> impl Iterator<Item = Ty> + 'a { 415 // ) -> impl Iterator<Item = Ty> + 'a {
412 // There should be no inference vars in types passed here 416 // // There should be no inference vars in types passed here
413 // FIXME check that? 417 // // FIXME check that?
414 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 418 // let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
415 let krate = self.resolver.krate(); 419 // let krate = self.resolver.krate();
416 let environment = TraitEnvironment::lower(db, &self.resolver); 420 // let environment = TraitEnvironment::lower(db, &self.resolver);
417 let ty = crate::ty::InEnvironment { value: canonical, environment }; 421 // let ty = crate::ty::InEnvironment { value: canonical, environment };
418 crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) 422 // crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value)
419 } 423 // }
420 424
421 /// Checks that particular type `ty` implements `std::future::Future`. 425 /// Checks that particular type `ty` implements `std::future::Future`.
422 /// This function is used in `.await` syntax completion. 426 /// This function is used in `.await` syntax completion.
diff --git a/crates/ra_hir/src/test_db.rs b/crates/ra_hir/src/test_db.rs
index efee2f658..a2071f71c 100644
--- a/crates/ra_hir/src/test_db.rs
+++ b/crates/ra_hir/src/test_db.rs
@@ -28,6 +28,10 @@ impl salsa::Database for TestDB {
28 &self.runtime 28 &self.runtime
29 } 29 }
30 30
31 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
32 &mut self.runtime
33 }
34
31 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) { 35 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
32 let mut events = self.events.lock(); 36 let mut events = self.events.lock();
33 if let Some(events) = &mut *events { 37 if let Some(events) = &mut *events {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 388530f31..bd03055b9 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -58,7 +58,7 @@ pub enum TypeCtor {
58 Float(Uncertain<FloatTy>), 58 Float(Uncertain<FloatTy>),
59 59
60 /// Structures, enumerations and unions. 60 /// Structures, enumerations and unions.
61 Adt(Adt), 61 Adt(AdtId),
62 62
63 /// The pointee of a string slice. Written as `str`. 63 /// The pointee of a string slice. Written as `str`.
64 Str, 64 Str,
@@ -174,7 +174,7 @@ impl TypeCtor {
174 | TypeCtor::Tuple { .. } => None, 174 | TypeCtor::Tuple { .. } => None,
175 // Closure's krate is irrelevant for coherence I would think? 175 // Closure's krate is irrelevant for coherence I would think?
176 TypeCtor::Closure { .. } => None, 176 TypeCtor::Closure { .. } => None,
177 TypeCtor::Adt(adt) => adt.krate(db), 177 TypeCtor::Adt(adt) => Some(adt.module(db).krate.into()),
178 TypeCtor::FnDef(callable) => Some(callable.krate(db).into()), 178 TypeCtor::FnDef(callable) => Some(callable.krate(db).into()),
179 TypeCtor::AssociatedType(type_alias) => { 179 TypeCtor::AssociatedType(type_alias) => {
180 Some(type_alias.lookup(db).module(db).krate.into()) 180 Some(type_alias.lookup(db).module(db).krate.into())
@@ -598,7 +598,7 @@ impl Ty {
598 pub fn as_adt(&self) -> Option<(Adt, &Substs)> { 598 pub fn as_adt(&self) -> Option<(Adt, &Substs)> {
599 match self { 599 match self {
600 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => { 600 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => {
601 Some((*adt_def, parameters)) 601 Some(((*adt_def).into(), parameters))
602 } 602 }
603 _ => None, 603 _ => None,
604 } 604 }
@@ -889,9 +889,9 @@ impl HirDisplay for ApplicationTy {
889 } 889 }
890 TypeCtor::Adt(def_id) => { 890 TypeCtor::Adt(def_id) => {
891 let name = match def_id { 891 let name = match def_id {
892 Adt::Struct(s) => s.name(f.db), 892 AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
893 Adt::Union(u) => u.name(f.db), 893 AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
894 Adt::Enum(e) => e.name(f.db), 894 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
895 } 895 }
896 .unwrap_or_else(Name::missing); 896 .unwrap_or_else(Name::missing);
897 write!(f, "{}", name)?; 897 write!(f, "{}", name)?;
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 6fd00d457..fce45321d 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -598,10 +598,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
598 trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE) 598 trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE)
599 } 599 }
600 600
601 fn resolve_boxed_box(&self) -> Option<Adt> { 601 fn resolve_boxed_box(&self) -> Option<AdtId> {
602 let path = known::std_boxed_box(); 602 let path = known::std_boxed_box();
603 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 603 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
604 Some(Adt::Struct(struct_.into())) 604 Some(struct_.into())
605 } 605 }
606} 606}
607 607
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs
index bb9a2e427..5ed4470af 100644
--- a/crates/ra_hir/src/ty/infer/coerce.rs
+++ b/crates/ra_hir/src/ty/infer/coerce.rs
@@ -4,14 +4,14 @@
4//! 4//!
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; 7use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AdtId};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9use test_utils::tested_by; 9use test_utils::tested_by;
10 10
11use crate::{ 11use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, 13 ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk},
14 Adt, Mutability, 14 Mutability,
15}; 15};
16 16
17use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; 17use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
@@ -242,11 +242,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
242 // - T is not part of the type of any other fields 242 // - T is not part of the type of any other fields
243 // - Bar<T>: Unsize<Bar<U>>, if the last field of Foo has type Bar<T> 243 // - Bar<T>: Unsize<Bar<U>>, if the last field of Foo has type Bar<T>
244 ( 244 (
245 ty_app!(TypeCtor::Adt(Adt::Struct(struct1)), st1), 245 ty_app!(TypeCtor::Adt(AdtId::StructId(struct1)), st1),
246 ty_app!(TypeCtor::Adt(Adt::Struct(struct2)), st2), 246 ty_app!(TypeCtor::Adt(AdtId::StructId(struct2)), st2),
247 ) if struct1 == struct2 => { 247 ) if struct1 == struct2 => {
248 let field_tys = self.db.field_types(struct1.id.into()); 248 let field_tys = self.db.field_types((*struct1).into());
249 let struct_data = self.db.struct_data(struct1.id); 249 let struct_data = self.db.struct_data(*struct1);
250 250
251 let mut fields = struct_data.variant_data.fields().iter(); 251 let mut fields = struct_data.variant_data.fields().iter();
252 let (last_field_id, _data) = fields.next_back()?; 252 let (last_field_id, _data) = fields.next_back()?;
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs
index 316cdc880..3d0895dc6 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir/src/ty/infer/expr.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 generics::GenericParams, 8 generics::GenericParams,
9 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
10 resolver::resolver_for_expr, 10 resolver::resolver_for_expr,
11 ContainerId, Lookup, 11 AdtId, ContainerId, Lookup, StructFieldId,
12}; 12};
13use hir_expand::name; 13use hir_expand::name;
14 14
@@ -20,7 +20,7 @@ use crate::{
20 Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, 20 Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty,
21 TypeCtor, TypeWalk, Uncertain, 21 TypeCtor, TypeWalk, Uncertain,
22 }, 22 },
23 Adt, Name, 23 Name,
24}; 24};
25 25
26use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 26use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
@@ -259,14 +259,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
259 TypeCtor::Tuple { .. } => name 259 TypeCtor::Tuple { .. } => name
260 .as_tuple_index() 260 .as_tuple_index()
261 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), 261 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()),
262 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { 262 TypeCtor::Adt(AdtId::StructId(s)) => {
263 self.write_field_resolution(tgt_expr, field); 263 self.db.struct_data(s).variant_data.field(name).map(|local_id| {
264 self.db.field_types(s.id.into())[field.id] 264 let field = StructFieldId { parent: s.into(), local_id }.into();
265 .clone() 265 self.write_field_resolution(tgt_expr, field);
266 .subst(&a_ty.parameters) 266 self.db.field_types(s.into())[field.id]
267 }), 267 .clone()
268 .subst(&a_ty.parameters)
269 })
270 }
268 // FIXME: 271 // FIXME:
269 TypeCtor::Adt(Adt::Union(_)) => None, 272 TypeCtor::Adt(AdtId::UnionId(_)) => None,
270 _ => None, 273 _ => None,
271 }, 274 },
272 _ => None, 275 _ => None,
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index d7d4bb0d6..2d23890a5 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -9,7 +9,7 @@ use std::iter;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use hir_def::{ 11use hir_def::{
12 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType}, 12 builtin_type::BuiltinType,
13 generics::WherePredicate, 13 generics::WherePredicate,
14 path::{GenericArg, PathSegment}, 14 path::{GenericArg, PathSegment},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
@@ -27,7 +27,7 @@ use super::{
27use crate::{ 27use crate::{
28 db::HirDatabase, 28 db::HirDatabase,
29 ty::{ 29 ty::{
30 primitive::{FloatTy, IntTy, Uncertain}, 30 primitive::{FloatTy, IntTy},
31 Adt, 31 Adt,
32 }, 32 },
33 util::make_mut_slice, 33 util::make_mut_slice,
@@ -679,36 +679,6 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
679 }) 679 })
680} 680}
681 681
682impl From<BuiltinInt> for IntTy {
683 fn from(t: BuiltinInt) -> Self {
684 IntTy { signedness: t.signedness, bitness: t.bitness }
685 }
686}
687
688impl From<BuiltinFloat> for FloatTy {
689 fn from(t: BuiltinFloat) -> Self {
690 FloatTy { bitness: t.bitness }
691 }
692}
693
694impl From<Option<BuiltinInt>> for Uncertain<IntTy> {
695 fn from(t: Option<BuiltinInt>) -> Self {
696 match t {
697 None => Uncertain::Unknown,
698 Some(t) => Uncertain::Known(t.into()),
699 }
700 }
701}
702
703impl From<Option<BuiltinFloat>> for Uncertain<FloatTy> {
704 fn from(t: Option<BuiltinFloat>) -> Self {
705 match t {
706 None => Uncertain::Unknown,
707 Some(t) => Uncertain::Known(t.into()),
708 }
709 }
710}
711
712fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig { 682fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig {
713 let struct_data = db.struct_data(def.into()); 683 let struct_data = db.struct_data(def.into());
714 let fields = struct_data.variant_data.fields(); 684 let fields = struct_data.variant_data.fields();
@@ -762,7 +732,7 @@ fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty {
762 let adt = adt.into(); 732 let adt = adt.into();
763 let adt_id: AdtId = adt.into(); 733 let adt_id: AdtId = adt.into();
764 let generics = db.generic_params(adt_id.into()); 734 let generics = db.generic_params(adt_id.into());
765 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) 735 Ty::apply(TypeCtor::Adt(adt_id), Substs::identity(&generics))
766} 736}
767 737
768fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 738fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty {
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index c5ab690eb..489fcd64b 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -5,14 +5,19 @@
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{lang_item::LangItemTarget, resolver::Resolver, AstItemDef}; 8use hir_def::{
9 lang_item::LangItemTarget, resolver::HasResolver, resolver::Resolver, AssocItemId, AstItemDef,
10 HasModule, ImplId, TraitId,
11};
12use ra_db::CrateId;
13use ra_prof::profile;
9use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
10 15
11use crate::{ 16use crate::{
12 db::HirDatabase, 17 db::HirDatabase,
13 ty::primitive::{FloatBitness, Uncertain}, 18 ty::primitive::{FloatBitness, Uncertain},
14 ty::{Ty, TypeCtor}, 19 ty::{Ty, TypeCtor},
15 AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, 20 AssocItem, Crate, Function, Mutability, Name, Trait,
16}; 21};
17 22
18use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 23use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
@@ -37,54 +42,58 @@ impl TyFingerprint {
37 42
38#[derive(Debug, PartialEq, Eq)] 43#[derive(Debug, PartialEq, Eq)]
39pub struct CrateImplBlocks { 44pub struct CrateImplBlocks {
40 impls: FxHashMap<TyFingerprint, Vec<ImplBlock>>, 45 impls: FxHashMap<TyFingerprint, Vec<ImplId>>,
41 impls_by_trait: FxHashMap<Trait, Vec<ImplBlock>>, 46 impls_by_trait: FxHashMap<TraitId, Vec<ImplId>>,
42} 47}
43 48
44impl CrateImplBlocks { 49impl CrateImplBlocks {
45 pub(crate) fn impls_in_crate_query( 50 pub(crate) fn impls_in_crate_query(
46 db: &impl HirDatabase, 51 db: &impl HirDatabase,
47 krate: Crate, 52 krate: CrateId,
48 ) -> Arc<CrateImplBlocks> { 53 ) -> Arc<CrateImplBlocks> {
49 let mut crate_impl_blocks = 54 let _p = profile("impls_in_crate_query");
55 let mut res =
50 CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() }; 56 CrateImplBlocks { impls: FxHashMap::default(), impls_by_trait: FxHashMap::default() };
51 if let Some(module) = krate.root_module(db) { 57
52 crate_impl_blocks.collect_recursive(db, module); 58 let crate_def_map = db.crate_def_map(krate);
59 for (_module_id, module_data) in crate_def_map.modules.iter() {
60 for &impl_id in module_data.impls.iter() {
61 let impl_data = db.impl_data(impl_id);
62 let resolver = impl_id.resolver(db);
63
64 let target_ty = { Ty::from_hir(db, &resolver, &impl_data.target_type) };
65
66 match &impl_data.target_trait {
67 Some(trait_ref) => {
68 if let Some(tr) =
69 TraitRef::from_hir(db, &resolver, &trait_ref, Some(target_ty))
70 {
71 res.impls_by_trait.entry(tr.trait_.id).or_default().push(impl_id);
72 }
73 }
74 None => {
75 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
76 res.impls.entry(target_ty_fp).or_default().push(impl_id);
77 }
78 }
79 }
80 }
53 } 81 }
54 Arc::new(crate_impl_blocks) 82
83 Arc::new(res)
55 } 84 }
56 pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + '_ { 85 pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
57 let fingerprint = TyFingerprint::for_impl(ty); 86 let fingerprint = TyFingerprint::for_impl(ty);
58 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() 87 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
59 } 88 }
60 89
61 pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ { 90 pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplId> + '_ {
62 self.impls_by_trait.get(&tr).into_iter().flatten().copied() 91 self.impls_by_trait.get(&tr.id).into_iter().flatten().copied()
63 } 92 }
64 93
65 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { 94 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
66 self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() 95 self.impls.values().chain(self.impls_by_trait.values()).flatten().copied()
67 } 96 }
68
69 fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) {
70 for impl_block in module.impl_blocks(db) {
71 let target_ty = impl_block.target_ty(db);
72
73 if impl_block.target_trait(db).is_some() {
74 if let Some(tr) = impl_block.target_trait_ref(db) {
75 self.impls_by_trait.entry(tr.trait_).or_default().push(impl_block);
76 }
77 } else {
78 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
79 self.impls.entry(target_ty_fp).or_default().push(impl_block);
80 }
81 }
82 }
83
84 for child in module.children(db) {
85 self.collect_recursive(db, child);
86 }
87 }
88} 97}
89 98
90fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { 99fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> {
@@ -102,7 +111,9 @@ fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayV
102 111
103 let lang_item_targets = match ty { 112 let lang_item_targets = match ty {
104 Ty::Apply(a_ty) => match a_ty.ctor { 113 Ty::Apply(a_ty) => match a_ty.ctor {
105 TypeCtor::Adt(def_id) => return Some(std::iter::once(def_id.krate(db)?).collect()), 114 TypeCtor::Adt(def_id) => {
115 return Some(std::iter::once(def_id.module(db).krate.into()).collect())
116 }
106 TypeCtor::Bool => lang_item_crate!("bool"), 117 TypeCtor::Bool => lang_item_crate!("bool"),
107 TypeCtor::Char => lang_item_crate!("char"), 118 TypeCtor::Char => lang_item_crate!("char"),
108 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { 119 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness {
@@ -277,14 +288,14 @@ fn iterate_inherent_methods<T>(
277 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 288 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
278) -> Option<T> { 289) -> Option<T> {
279 for krate in def_crates(db, krate, &ty.value)? { 290 for krate in def_crates(db, krate, &ty.value)? {
280 let impls = db.impls_in_crate(krate); 291 let impls = db.impls_in_crate(krate.crate_id);
281 292
282 for impl_block in impls.lookup_impl_blocks(&ty.value) { 293 for impl_block in impls.lookup_impl_blocks(&ty.value) {
283 for item in impl_block.items(db) { 294 for &item in db.impl_data(impl_block).items.iter() {
284 if !is_valid_candidate(db, name, mode, item) { 295 if !is_valid_candidate(db, name, mode, item) {
285 continue; 296 continue;
286 } 297 }
287 if let Some(result) = callback(&ty.value, item) { 298 if let Some(result) = callback(&ty.value, item.into()) {
288 return Some(result); 299 return Some(result);
289 } 300 }
290 } 301 }
@@ -297,17 +308,17 @@ fn is_valid_candidate(
297 db: &impl HirDatabase, 308 db: &impl HirDatabase,
298 name: Option<&Name>, 309 name: Option<&Name>,
299 mode: LookupMode, 310 mode: LookupMode,
300 item: AssocItem, 311 item: AssocItemId,
301) -> bool { 312) -> bool {
302 match item { 313 match item {
303 AssocItem::Function(m) => { 314 AssocItemId::FunctionId(m) => {
304 let data = db.function_data(m.id); 315 let data = db.function_data(m);
305 name.map_or(true, |name| data.name == *name) 316 name.map_or(true, |name| &data.name == name)
306 && (data.has_self_param || mode == LookupMode::Path) 317 && (data.has_self_param || mode == LookupMode::Path)
307 } 318 }
308 AssocItem::Const(c) => { 319 AssocItemId::ConstId(c) => {
309 name.map_or(true, |name| Some(name) == c.name(db).as_ref()) 320 let data = db.const_data(c);
310 && (mode == LookupMode::Path) 321 name.map_or(true, |name| data.name.as_ref() == Some(name)) && (mode == LookupMode::Path)
311 } 322 }
312 _ => false, 323 _ => false,
313 } 324 }
@@ -342,11 +353,11 @@ impl Ty {
342 mut callback: impl FnMut(AssocItem) -> Option<T>, 353 mut callback: impl FnMut(AssocItem) -> Option<T>,
343 ) -> Option<T> { 354 ) -> Option<T> {
344 for krate in def_crates(db, krate, &self)? { 355 for krate in def_crates(db, krate, &self)? {
345 let impls = db.impls_in_crate(krate); 356 let impls = db.impls_in_crate(krate.crate_id);
346 357
347 for impl_block in impls.lookup_impl_blocks(&self) { 358 for impl_block in impls.lookup_impl_blocks(&self) {
348 for item in impl_block.items(db) { 359 for &item in db.impl_data(impl_block).items.iter() {
349 if let Some(result) = callback(item) { 360 if let Some(result) = callback(item.into()) {
350 return Some(result); 361 return Some(result);
351 } 362 }
352 } 363 }
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs
index 47789db87..12dc96572 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir/src/ty/primitive.rs
@@ -1,160 +1,3 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::fmt; 3pub use hir_ty::primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain};
4
5pub use hir_def::builtin_type::{FloatBitness, IntBitness, Signedness};
6
7#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
8pub enum Uncertain<T> {
9 Unknown,
10 Known(T),
11}
12
13impl From<IntTy> for Uncertain<IntTy> {
14 fn from(ty: IntTy) -> Self {
15 Uncertain::Known(ty)
16 }
17}
18
19impl fmt::Display for Uncertain<IntTy> {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 match *self {
22 Uncertain::Unknown => write!(f, "{{integer}}"),
23 Uncertain::Known(ty) => write!(f, "{}", ty),
24 }
25 }
26}
27
28impl From<FloatTy> for Uncertain<FloatTy> {
29 fn from(ty: FloatTy) -> Self {
30 Uncertain::Known(ty)
31 }
32}
33
34impl fmt::Display for Uncertain<FloatTy> {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 match *self {
37 Uncertain::Unknown => write!(f, "{{float}}"),
38 Uncertain::Known(ty) => write!(f, "{}", ty),
39 }
40 }
41}
42
43#[derive(Copy, Clone, Eq, PartialEq, Hash)]
44pub struct IntTy {
45 pub signedness: Signedness,
46 pub bitness: IntBitness,
47}
48
49impl fmt::Debug for IntTy {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 fmt::Display::fmt(self, f)
52 }
53}
54
55impl fmt::Display for IntTy {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 write!(f, "{}", self.ty_to_string())
58 }
59}
60
61impl IntTy {
62 pub fn isize() -> IntTy {
63 IntTy { signedness: Signedness::Signed, bitness: IntBitness::Xsize }
64 }
65
66 pub fn i8() -> IntTy {
67 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X8 }
68 }
69
70 pub fn i16() -> IntTy {
71 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X16 }
72 }
73
74 pub fn i32() -> IntTy {
75 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X32 }
76 }
77
78 pub fn i64() -> IntTy {
79 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X64 }
80 }
81
82 pub fn i128() -> IntTy {
83 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X128 }
84 }
85
86 pub fn usize() -> IntTy {
87 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }
88 }
89
90 pub fn u8() -> IntTy {
91 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }
92 }
93
94 pub fn u16() -> IntTy {
95 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }
96 }
97
98 pub fn u32() -> IntTy {
99 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }
100 }
101
102 pub fn u64() -> IntTy {
103 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }
104 }
105
106 pub fn u128() -> IntTy {
107 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }
108 }
109
110 pub(crate) fn ty_to_string(self) -> &'static str {
111 match (self.signedness, self.bitness) {
112 (Signedness::Signed, IntBitness::Xsize) => "isize",
113 (Signedness::Signed, IntBitness::X8) => "i8",
114 (Signedness::Signed, IntBitness::X16) => "i16",
115 (Signedness::Signed, IntBitness::X32) => "i32",
116 (Signedness::Signed, IntBitness::X64) => "i64",
117 (Signedness::Signed, IntBitness::X128) => "i128",
118 (Signedness::Unsigned, IntBitness::Xsize) => "usize",
119 (Signedness::Unsigned, IntBitness::X8) => "u8",
120 (Signedness::Unsigned, IntBitness::X16) => "u16",
121 (Signedness::Unsigned, IntBitness::X32) => "u32",
122 (Signedness::Unsigned, IntBitness::X64) => "u64",
123 (Signedness::Unsigned, IntBitness::X128) => "u128",
124 }
125 }
126}
127
128#[derive(Copy, Clone, PartialEq, Eq, Hash)]
129pub struct FloatTy {
130 pub bitness: FloatBitness,
131}
132
133impl fmt::Debug for FloatTy {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 fmt::Display::fmt(self, f)
136 }
137}
138
139impl fmt::Display for FloatTy {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 write!(f, "{}", self.ty_to_string())
142 }
143}
144
145impl FloatTy {
146 pub fn f32() -> FloatTy {
147 FloatTy { bitness: FloatBitness::X32 }
148 }
149
150 pub fn f64() -> FloatTy {
151 FloatTy { bitness: FloatBitness::X64 }
152 }
153
154 pub(crate) fn ty_to_string(self) -> &'static str {
155 match self.bitness {
156 FloatBitness::X32 => "f32",
157 FloatBitness::X64 => "f64",
158 }
159 }
160}
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index b9a5d651f..2eeb03099 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -88,8 +88,8 @@ pub(crate) fn impls_for_trait_query(
88 for dep in krate.dependencies(db) { 88 for dep in krate.dependencies(db) {
89 impls.extend(db.impls_for_trait(dep.krate, trait_).iter()); 89 impls.extend(db.impls_for_trait(dep.krate, trait_).iter());
90 } 90 }
91 let crate_impl_blocks = db.impls_in_crate(krate); 91 let crate_impl_blocks = db.impls_in_crate(krate.crate_id);
92 impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_)); 92 impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_).map(ImplBlock::from));
93 impls.into_iter().collect() 93 impls.into_iter().collect()
94} 94}
95 95
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 0091bfbc3..0cf418d30 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -129,6 +129,10 @@ impl VariantData {
129 } 129 }
130 } 130 }
131 131
132 pub fn field(&self, name: &Name) -> Option<LocalStructFieldId> {
133 self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None })
134 }
135
132 pub fn is_unit(&self) -> bool { 136 pub fn is_unit(&self) -> bool {
133 match self { 137 match self {
134 VariantData::Unit => true, 138 VariantData::Unit => true,
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index a88a78b38..274dd1467 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -489,6 +489,16 @@ impl HasModule for AdtId {
489 } 489 }
490} 490}
491 491
492impl HasModule for DefWithBodyId {
493 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
494 match self {
495 DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
496 DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
497 DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
498 }
499 }
500}
501
492impl HasModule for StaticLoc { 502impl HasModule for StaticLoc {
493 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { 503 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
494 self.container 504 self.container
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs
index 439e8a412..54e3a84bd 100644
--- a/crates/ra_hir_def/src/test_db.rs
+++ b/crates/ra_hir_def/src/test_db.rs
@@ -24,7 +24,9 @@ impl salsa::Database for TestDB {
24 fn salsa_runtime(&self) -> &salsa::Runtime<Self> { 24 fn salsa_runtime(&self) -> &salsa::Runtime<Self> {
25 &self.runtime 25 &self.runtime
26 } 26 }
27 27 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
28 &mut self.runtime
29 }
28 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) { 30 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
29 let mut events = self.events.lock().unwrap(); 31 let mut events = self.events.lock().unwrap();
30 if let Some(events) = &mut *events { 32 if let Some(events) = &mut *events {
diff --git a/crates/ra_hir_expand/src/test_db.rs b/crates/ra_hir_expand/src/test_db.rs
index d23e75d9e..918736e2a 100644
--- a/crates/ra_hir_expand/src/test_db.rs
+++ b/crates/ra_hir_expand/src/test_db.rs
@@ -23,6 +23,10 @@ impl salsa::Database for TestDB {
23 &self.runtime 23 &self.runtime
24 } 24 }
25 25
26 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
27 &mut self.runtime
28 }
29
26 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) { 30 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
27 let mut events = self.events.lock().unwrap(); 31 let mut events = self.events.lock().unwrap();
28 if let Some(events) = &mut *events { 32 if let Some(events) = &mut *events {
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
new file mode 100644
index 000000000..70216ab24
--- /dev/null
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -0,0 +1,32 @@
1[package]
2edition = "2018"
3name = "ra_hir_ty"
4version = "0.1.0"
5authors = ["rust-analyzer developers"]
6
7[lib]
8doctest = false
9
10[dependencies]
11log = "0.4.5"
12rustc-hash = "1.0"
13parking_lot = "0.9.0"
14ena = "0.13"
15
16ra_syntax = { path = "../ra_syntax" }
17ra_arena = { path = "../ra_arena" }
18ra_db = { path = "../ra_db" }
19hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" }
20hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
21test_utils = { path = "../test_utils" }
22ra_prof = { path = "../ra_prof" }
23
24# https://github.com/rust-lang/chalk/pull/294
25chalk-solve = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" }
26chalk-rust-ir = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" }
27chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" }
28
29lalrpop-intern = "0.15.1"
30
31[dev-dependencies]
32insta = "0.12.0"
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
new file mode 100644
index 000000000..28859ba63
--- /dev/null
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -0,0 +1,4 @@
1//! Work in Progress: everything related to types, type inference and trait
2//! solving.
3
4pub mod primitive;
diff --git a/crates/ra_hir_ty/src/primitive.rs b/crates/ra_hir_ty/src/primitive.rs
new file mode 100644
index 000000000..02a8179d9
--- /dev/null
+++ b/crates/ra_hir_ty/src/primitive.rs
@@ -0,0 +1,193 @@
1//! Defines primitive types, which have a couple of peculiarities:
2//!
3//! * during type inference, they can be uncertain (ie, `let x = 92;`)
4//! * they don't belong to any particular crate.
5
6use std::fmt;
7
8pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness};
9
10#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
11pub enum Uncertain<T> {
12 Unknown,
13 Known(T),
14}
15
16impl From<IntTy> for Uncertain<IntTy> {
17 fn from(ty: IntTy) -> Self {
18 Uncertain::Known(ty)
19 }
20}
21
22impl fmt::Display for Uncertain<IntTy> {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 match *self {
25 Uncertain::Unknown => write!(f, "{{integer}}"),
26 Uncertain::Known(ty) => write!(f, "{}", ty),
27 }
28 }
29}
30
31impl From<FloatTy> for Uncertain<FloatTy> {
32 fn from(ty: FloatTy) -> Self {
33 Uncertain::Known(ty)
34 }
35}
36
37impl fmt::Display for Uncertain<FloatTy> {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 match *self {
40 Uncertain::Unknown => write!(f, "{{float}}"),
41 Uncertain::Known(ty) => write!(f, "{}", ty),
42 }
43 }
44}
45
46#[derive(Copy, Clone, Eq, PartialEq, Hash)]
47pub struct IntTy {
48 pub signedness: Signedness,
49 pub bitness: IntBitness,
50}
51
52impl fmt::Debug for IntTy {
53 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54 fmt::Display::fmt(self, f)
55 }
56}
57
58impl fmt::Display for IntTy {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 write!(f, "{}", self.ty_to_string())
61 }
62}
63
64impl IntTy {
65 pub fn isize() -> IntTy {
66 IntTy { signedness: Signedness::Signed, bitness: IntBitness::Xsize }
67 }
68
69 pub fn i8() -> IntTy {
70 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X8 }
71 }
72
73 pub fn i16() -> IntTy {
74 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X16 }
75 }
76
77 pub fn i32() -> IntTy {
78 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X32 }
79 }
80
81 pub fn i64() -> IntTy {
82 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X64 }
83 }
84
85 pub fn i128() -> IntTy {
86 IntTy { signedness: Signedness::Signed, bitness: IntBitness::X128 }
87 }
88
89 pub fn usize() -> IntTy {
90 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize }
91 }
92
93 pub fn u8() -> IntTy {
94 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X8 }
95 }
96
97 pub fn u16() -> IntTy {
98 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X16 }
99 }
100
101 pub fn u32() -> IntTy {
102 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X32 }
103 }
104
105 pub fn u64() -> IntTy {
106 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X64 }
107 }
108
109 pub fn u128() -> IntTy {
110 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }
111 }
112
113 pub fn ty_to_string(self) -> &'static str {
114 match (self.signedness, self.bitness) {
115 (Signedness::Signed, IntBitness::Xsize) => "isize",
116 (Signedness::Signed, IntBitness::X8) => "i8",
117 (Signedness::Signed, IntBitness::X16) => "i16",
118 (Signedness::Signed, IntBitness::X32) => "i32",
119 (Signedness::Signed, IntBitness::X64) => "i64",
120 (Signedness::Signed, IntBitness::X128) => "i128",
121 (Signedness::Unsigned, IntBitness::Xsize) => "usize",
122 (Signedness::Unsigned, IntBitness::X8) => "u8",
123 (Signedness::Unsigned, IntBitness::X16) => "u16",
124 (Signedness::Unsigned, IntBitness::X32) => "u32",
125 (Signedness::Unsigned, IntBitness::X64) => "u64",
126 (Signedness::Unsigned, IntBitness::X128) => "u128",
127 }
128 }
129}
130
131#[derive(Copy, Clone, PartialEq, Eq, Hash)]
132pub struct FloatTy {
133 pub bitness: FloatBitness,
134}
135
136impl fmt::Debug for FloatTy {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 fmt::Display::fmt(self, f)
139 }
140}
141
142impl fmt::Display for FloatTy {
143 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
144 write!(f, "{}", self.ty_to_string())
145 }
146}
147
148impl FloatTy {
149 pub fn f32() -> FloatTy {
150 FloatTy { bitness: FloatBitness::X32 }
151 }
152
153 pub fn f64() -> FloatTy {
154 FloatTy { bitness: FloatBitness::X64 }
155 }
156
157 pub fn ty_to_string(self) -> &'static str {
158 match self.bitness {
159 FloatBitness::X32 => "f32",
160 FloatBitness::X64 => "f64",
161 }
162 }
163}
164
165impl From<BuiltinInt> for IntTy {
166 fn from(t: BuiltinInt) -> Self {
167 IntTy { signedness: t.signedness, bitness: t.bitness }
168 }
169}
170
171impl From<BuiltinFloat> for FloatTy {
172 fn from(t: BuiltinFloat) -> Self {
173 FloatTy { bitness: t.bitness }
174 }
175}
176
177impl From<Option<BuiltinInt>> for Uncertain<IntTy> {
178 fn from(t: Option<BuiltinInt>) -> Self {
179 match t {
180 None => Uncertain::Unknown,
181 Some(t) => Uncertain::Known(t.into()),
182 }
183 }
184}
185
186impl From<Option<BuiltinFloat>> for Uncertain<FloatTy> {
187 fn from(t: Option<BuiltinFloat>) -> Self {
188 match t {
189 None => Uncertain::Unknown,
190 Some(t) => Uncertain::Known(t.into()),
191 }
192 }
193}
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index 7ebdfc585..d559dc4d0 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -23,8 +23,8 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
23 let analyzer = hir::SourceAnalyzer::new(db, name_ref, None); 23 let analyzer = hir::SourceAnalyzer::new(db, name_ref, None);
24 let (mut call_info, has_self) = match &calling_node { 24 let (mut call_info, has_self) = match &calling_node {
25 FnCallNode::CallExpr(expr) => { 25 FnCallNode::CallExpr(expr) => {
26 //FIXME: don't poke into Ty 26 //FIXME: Type::as_callable is broken
27 let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; 27 let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
28 match callable_def { 28 match callable_def {
29 hir::CallableDef::FunctionId(it) => { 29 hir::CallableDef::FunctionId(it) => {
30 let fn_def = it.into(); 30 let fn_def = it.into();
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 0f692460d..84340aff8 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -171,7 +171,7 @@ impl RootDatabase {
171 log::info!("apply_change {:?}", change); 171 log::info!("apply_change {:?}", change);
172 { 172 {
173 let _p = profile("RootDatabase::apply_change/cancellation"); 173 let _p = profile("RootDatabase::apply_change/cancellation");
174 self.salsa_runtime().synthetic_write(Durability::LOW); 174 self.salsa_runtime_mut().synthetic_write(Durability::LOW);
175 } 175 }
176 if !change.new_roots.is_empty() { 176 if !change.new_roots.is_empty() {
177 let mut local_roots = Vec::clone(&self.local_roots()); 177 let mut local_roots = Vec::clone(&self.local_roots());
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 5a3f9b5f6..b6fe48627 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Adt, Ty, TypeCtor}; 3use hir::Type;
4 4
5use crate::completion::completion_item::CompletionKind; 5use crate::completion::completion_item::CompletionKind;
6use crate::{ 6use crate::{
@@ -22,12 +22,12 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
22 }; 22 };
23 23
24 if !ctx.is_call { 24 if !ctx.is_call {
25 complete_fields(acc, ctx, receiver_ty.clone()); 25 complete_fields(acc, ctx, &receiver_ty);
26 } 26 }
27 complete_methods(acc, ctx, receiver_ty.clone()); 27 complete_methods(acc, ctx, &receiver_ty);
28 28
29 // Suggest .await syntax for types that implement Future trait 29 // Suggest .await syntax for types that implement Future trait
30 if ctx.analyzer.impls_future(ctx.db, receiver_ty) { 30 if ctx.analyzer.impls_future(ctx.db, receiver_ty.into_ty()) {
31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") 31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
32 .detail("expr.await") 32 .detail("expr.await")
33 .insert_text("await") 33 .insert_text("await")
@@ -35,28 +35,18 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
35 } 35 }
36} 36}
37 37
38fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 38fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
39 for receiver in ctx.analyzer.autoderef(ctx.db, receiver) { 39 for receiver in receiver.autoderef(ctx.db) {
40 if let Ty::Apply(a_ty) = receiver { 40 for (field, ty) in receiver.fields(ctx.db) {
41 match a_ty.ctor { 41 acc.add_field(ctx, field, &ty);
42 TypeCtor::Adt(Adt::Struct(s)) => { 42 }
43 for field in s.fields(ctx.db) { 43 for (i, ty) in receiver.tuple_fields(ctx.db).into_iter().enumerate() {
44 acc.add_field(ctx, field, &a_ty.parameters); 44 acc.add_tuple_field(ctx, i, &ty);
45 } 45 }
46 }
47 // FIXME unions
48 TypeCtor::Tuple { .. } => {
49 for (i, ty) in a_ty.parameters.iter().enumerate() {
50 acc.add_tuple_field(ctx, i, ty);
51 }
52 }
53 _ => {}
54 }
55 };
56 } 46 }
57} 47}
58 48
59fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { 49fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
60 let mut seen_methods = FxHashSet::default(); 50 let mut seen_methods = FxHashSet::default();
61 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { 51 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| {
62 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { 52 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index 17b75cf7e..646a30c76 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -1,6 +1,5 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{Ty, TypeCtor};
4use ra_syntax::{ast::AstNode, TextRange, TextUnit}; 3use ra_syntax::{ast::AstNode, TextRange, TextUnit};
5use ra_text_edit::TextEdit; 4use ra_text_edit::TextEdit;
6 5
@@ -30,9 +29,12 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
30 dot_receiver.syntax().text().to_string() 29 dot_receiver.syntax().text().to_string()
31 }; 30 };
32 31
33 let receiver_ty = ctx.analyzer.type_of(ctx.db, &dot_receiver); 32 let receiver_ty = match ctx.analyzer.type_of(ctx.db, &dot_receiver) {
33 Some(it) => it,
34 None => return,
35 };
34 36
35 if is_bool_or_unknown(receiver_ty) { 37 if receiver_ty.is_bool() || receiver_ty.is_unknown() {
36 postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text)) 38 postfix_snippet(ctx, "if", "if expr {}", &format!("if {} {{$0}}", receiver_text))
37 .add_to(acc); 39 .add_to(acc);
38 postfix_snippet( 40 postfix_snippet(
@@ -75,14 +77,6 @@ fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet:
75 .snippet_edit(edit) 77 .snippet_edit(edit)
76} 78}
77 79
78fn is_bool_or_unknown(ty: Option<Ty>) -> bool {
79 match &ty {
80 Some(Ty::Apply(app)) if app.ctor == TypeCtor::Bool => true,
81 Some(Ty::Unknown) | None => true,
82 Some(_) => false,
83 }
84}
85
86#[cfg(test)] 80#[cfg(test)]
87mod tests { 81mod tests {
88 use insta::assert_debug_snapshot; 82 use insta::assert_debug_snapshot;
diff --git a/crates/ra_ide_api/src/completion/complete_record_literal.rs b/crates/ra_ide_api/src/completion/complete_record_literal.rs
index 45a4a9738..577c394d2 100644
--- a/crates/ra_ide_api/src/completion/complete_record_literal.rs
+++ b/crates/ra_ide_api/src/completion/complete_record_literal.rs
@@ -1,7 +1,5 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::Substs;
4
5use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
6 4
7/// Complete fields in fields literals. 5/// Complete fields in fields literals.
@@ -15,10 +13,9 @@ pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionCon
15 Some(it) => it, 13 Some(it) => it,
16 _ => return, 14 _ => return,
17 }; 15 };
18 let substs = &ty.substs().unwrap_or_else(Substs::empty);
19 16
20 for field in variant.fields(ctx.db) { 17 for (field, field_ty) in ty.variant_fields(ctx.db, variant) {
21 acc.add_field(ctx, field, substs); 18 acc.add_field(ctx, field, &field_ty);
22 } 19 }
23} 20}
24 21
diff --git a/crates/ra_ide_api/src/completion/complete_record_pattern.rs b/crates/ra_ide_api/src/completion/complete_record_pattern.rs
index aa0fd6d24..a56c7e3a1 100644
--- a/crates/ra_ide_api/src/completion/complete_record_pattern.rs
+++ b/crates/ra_ide_api/src/completion/complete_record_pattern.rs
@@ -1,7 +1,5 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::Substs;
4
5use crate::completion::{CompletionContext, Completions}; 3use crate::completion::{CompletionContext, Completions};
6 4
7pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) { 5pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionContext) {
@@ -14,10 +12,9 @@ pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionCon
14 Some(it) => it, 12 Some(it) => it,
15 _ => return, 13 _ => return,
16 }; 14 };
17 let substs = &ty.substs().unwrap_or_else(Substs::empty);
18 15
19 for field in variant.fields(ctx.db) { 16 for (field, field_ty) in ty.variant_fields(ctx.db, variant) {
20 acc.add_field(ctx, field, substs); 17 acc.add_field(ctx, field, &field_ty);
21 } 18 }
22} 19}
23 20
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 85b053a6e..5f056730a 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -1,12 +1,12 @@
1//! This modules takes care of rendering various definitions as completion items. 1//! This modules takes care of rendering various definitions as completion items.
2 2
3use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; 3use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Type};
4use join_to_string::join; 4use join_to_string::join;
5use ra_syntax::ast::NameOwner; 5use ra_syntax::ast::NameOwner;
6use test_utils::tested_by; 6use test_utils::tested_by;
7 7
8use crate::completion::{ 8use crate::completion::{
9 db, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, 9 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
10}; 10};
11 11
12use crate::display::{const_label, function_label, macro_label, type_label}; 12use crate::display::{const_label, function_label, macro_label, type_label};
@@ -16,7 +16,7 @@ impl Completions {
16 &mut self, 16 &mut self,
17 ctx: &CompletionContext, 17 ctx: &CompletionContext,
18 field: hir::StructField, 18 field: hir::StructField,
19 substs: &hir::Substs, 19 ty: &Type,
20 ) { 20 ) {
21 let is_deprecated = is_deprecated(field, ctx.db); 21 let is_deprecated = is_deprecated(field, ctx.db);
22 CompletionItem::new( 22 CompletionItem::new(
@@ -25,13 +25,13 @@ impl Completions {
25 field.name(ctx.db).to_string(), 25 field.name(ctx.db).to_string(),
26 ) 26 )
27 .kind(CompletionItemKind::Field) 27 .kind(CompletionItemKind::Field)
28 .detail(field.ty(ctx.db).subst(substs).display(ctx.db).to_string()) 28 .detail(ty.display(ctx.db).to_string())
29 .set_documentation(field.docs(ctx.db)) 29 .set_documentation(field.docs(ctx.db))
30 .set_deprecated(is_deprecated) 30 .set_deprecated(is_deprecated)
31 .add_to(self); 31 .add_to(self);
32 } 32 }
33 33
34 pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &hir::Ty) { 34 pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &Type) {
35 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string()) 35 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), field.to_string())
36 .kind(CompletionItemKind::Field) 36 .kind(CompletionItemKind::Field)
37 .detail(ty.display(ctx.db).to_string()) 37 .detail(ty.display(ctx.db).to_string())
@@ -98,7 +98,7 @@ impl Completions {
98 CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone()); 98 CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone());
99 if let ScopeDef::Local(local) = resolution { 99 if let ScopeDef::Local(local) = resolution {
100 let ty = local.ty(ctx.db); 100 let ty = local.ty(ctx.db);
101 if ty != Ty::Unknown { 101 if !ty.is_unknown() {
102 completion_item = completion_item.detail(ty.display(ctx.db).to_string()); 102 completion_item = completion_item.detail(ty.display(ctx.db).to_string());
103 } 103 }
104 }; 104 };
@@ -108,19 +108,17 @@ impl Completions {
108 && !ctx.has_type_args 108 && !ctx.has_type_args
109 && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") 109 && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
110 { 110 {
111 let generic_def: Option<hir::GenericDef> = match resolution { 111 let has_non_default_type_params = match resolution {
112 ScopeDef::ModuleDef(Adt(it)) => Some((*it).into()), 112 ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db),
113 ScopeDef::ModuleDef(TypeAlias(it)) => Some((*it).into()), 113 ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db),
114 _ => None, 114 _ => false,
115 }; 115 };
116 if let Some(def) = generic_def { 116 if has_non_default_type_params {
117 if has_non_default_type_params(def, ctx.db) { 117 tested_by!(inserts_angle_brackets_for_generics);
118 tested_by!(inserts_angle_brackets_for_generics); 118 completion_item = completion_item
119 completion_item = completion_item 119 .lookup_by(local_name.clone())
120 .lookup_by(local_name.clone()) 120 .label(format!("{}<…>", local_name))
121 .label(format!("{}<…>", local_name)) 121 .insert_snippet(format!("{}<$0>", local_name));
122 .insert_snippet(format!("{}<$0>", local_name));
123 }
124 } 122 }
125 } 123 }
126 124
@@ -291,11 +289,6 @@ fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool {
291 node.attrs(db).by_key("deprecated").exists() 289 node.attrs(db).by_key("deprecated").exists()
292} 290}
293 291
294fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {
295 let subst = db.generic_defaults(def.into());
296 subst.iter().any(|ty| ty == &Ty::Unknown)
297}
298
299#[cfg(test)] 292#[cfg(test)]
300mod tests { 293mod tests {
301 use insta::assert_debug_snapshot; 294 use insta::assert_debug_snapshot;
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index c2a9dcdd1..f739ebecd 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -65,6 +65,9 @@ impl salsa::Database for RootDatabase {
65 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { 65 fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> {
66 &self.runtime 66 &self.runtime
67 } 67 }
68 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
69 &mut self.runtime
70 }
68 fn on_propagated_panic(&self) -> ! { 71 fn on_propagated_panic(&self) -> ! {
69 Canceled::throw() 72 Canceled::throw()
70 } 73 }
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs
index 28a83a3e2..992a08809 100644
--- a/crates/ra_ide_api/src/goto_type_definition.rs
+++ b/crates/ra_ide_api/src/goto_type_definition.rs
@@ -24,7 +24,7 @@ pub(crate) fn goto_type_definition(
24 24
25 let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None); 25 let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None);
26 26
27 let ty: hir::Ty = if let Some(ty) = 27 let ty: hir::Type = if let Some(ty) =
28 ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) 28 ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e))
29 { 29 {
30 ty 30 ty
@@ -35,7 +35,7 @@ pub(crate) fn goto_type_definition(
35 return None; 35 return None;
36 }; 36 };
37 37
38 let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?; 38 let adt_def = ty.autoderef(db).find_map(|ty| ty.as_adt())?;
39 39
40 let nav = adt_def.to_nav(db); 40 let nav = adt_def.to_nav(db);
41 Some(RangeInfo::new(node.text_range(), vec![nav])) 41 Some(RangeInfo::new(node.text_range(), vec![nav]))
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index 2b3100fc3..b3ebd9145 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor}; 3use hir::{ApplicationTy, FromSource, ImplBlock, Ty, TypeCtor};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 5use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
6 6
@@ -56,11 +56,11 @@ fn impls_for_def(
56 }; 56 };
57 57
58 let krate = module.krate(); 58 let krate = module.krate();
59 let impls = db.impls_in_crate(krate); 59 let impls = ImplBlock::all_in_crate(db, krate);
60 60
61 Some( 61 Some(
62 impls 62 impls
63 .all_impls() 63 .into_iter()
64 .filter(|impl_block| is_equal_for_find_impls(&ty, &impl_block.target_ty(db))) 64 .filter(|impl_block| is_equal_for_find_impls(&ty, &impl_block.target_ty(db)))
65 .map(|imp| imp.to_nav(db)) 65 .map(|imp| imp.to_nav(db))
66 .collect(), 66 .collect(),
@@ -77,9 +77,9 @@ fn impls_for_trait(
77 let tr = hir::Trait::from_source(db, src)?; 77 let tr = hir::Trait::from_source(db, src)?;
78 78
79 let krate = module.krate(); 79 let krate = module.krate();
80 let impls = db.impls_in_crate(krate); 80 let impls = ImplBlock::for_trait(db, krate, tr);
81 81
82 Some(impls.lookup_impl_blocks_for_trait(tr).map(|imp| imp.to_nav(db)).collect()) 82 Some(impls.into_iter().map(|imp| imp.to_nav(db)).collect())
83} 83}
84 84
85fn is_equal_for_find_impls(original_ty: &Ty, impl_ty: &Ty) -> bool { 85fn is_equal_for_find_impls(original_ty: &Ty, impl_ty: &Ty) -> bool {
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs
index 24a7ca5e7..45149bf0c 100644
--- a/crates/ra_ide_api/src/inlay_hints.rs
+++ b/crates/ra_ide_api/src/inlay_hints.rs
@@ -1,7 +1,7 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use crate::{db::RootDatabase, FileId}; 3use crate::{db::RootDatabase, FileId};
4use hir::{HirDisplay, SourceAnalyzer, Ty}; 4use hir::{HirDisplay, SourceAnalyzer};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, TypeAscriptionOwner}, 6 ast::{self, AstNode, TypeAscriptionOwner},
7 match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, 7 match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange,
@@ -100,8 +100,11 @@ fn get_pat_type_hints(
100 .into_iter() 100 .into_iter()
101 .filter(|pat| !skip_root_pat_hint || pat != original_pat) 101 .filter(|pat| !skip_root_pat_hint || pat != original_pat)
102 .filter_map(|pat| { 102 .filter_map(|pat| {
103 get_node_displayable_type(db, &analyzer, &pat) 103 let ty = analyzer.type_of_pat(db, &pat)?;
104 .map(|pat_type| (pat.syntax().text_range(), pat_type)) 104 if ty.is_unknown() {
105 return None;
106 }
107 Some((pat.syntax().text_range(), ty))
105 }) 108 })
106 .map(|(range, pat_type)| InlayHint { 109 .map(|(range, pat_type)| InlayHint {
107 range, 110 range,
@@ -158,20 +161,6 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec<ast::Pat> {
158 leaf_pats 161 leaf_pats
159} 162}
160 163
161fn get_node_displayable_type(
162 db: &RootDatabase,
163 analyzer: &SourceAnalyzer,
164 node_pat: &ast::Pat,
165) -> Option<Ty> {
166 analyzer.type_of_pat(db, node_pat).and_then(|resolved_type| {
167 if let Ty::Apply(_) = resolved_type {
168 Some(resolved_type)
169 } else {
170 None
171 }
172 })
173}
174
175#[cfg(test)] 164#[cfg(test)]
176mod tests { 165mod tests {
177 use crate::mock_analysis::single_file; 166 use crate::mock_analysis::single_file;
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs
index aca23f79e..cf12db066 100644
--- a/crates/ra_ide_api/src/references/name_definition.rs
+++ b/crates/ra_ide_api/src/references/name_definition.rs
@@ -46,6 +46,7 @@ pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDe
46 let container = parent.module(db); 46 let container = parent.module(db);
47 let visibility = match parent { 47 let visibility = match parent {
48 VariantDef::Struct(s) => s.source(db).value.visibility(), 48 VariantDef::Struct(s) => s.source(db).value.visibility(),
49 VariantDef::Union(e) => e.source(db).value.visibility(),
49 VariantDef::EnumVariant(e) => e.source(db).value.parent_enum().visibility(), 50 VariantDef::EnumVariant(e) => e.source(db).value.parent_enum().visibility(),
50 }; 51 };
51 NameDefinition { kind, container, visibility } 52 NameDefinition { kind, container, visibility }
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index 2b653fe8f..10165a9bb 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -2,7 +2,7 @@
2 2
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
4 4
5use hir::{Mutability, Name, Source}; 5use hir::{Name, Source};
6use ra_db::SourceDatabase; 6use ra_db::SourceDatabase;
7use ra_prof::profile; 7use ra_prof::profile;
8use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; 8use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T};
@@ -230,11 +230,10 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str {
230 Local(local) => { 230 Local(local) => {
231 if local.is_mut(db) { 231 if local.is_mut(db) {
232 "variable.mut" 232 "variable.mut"
233 } else if local.ty(db).is_mutable_reference() {
234 "variable.mut"
233 } else { 235 } else {
234 match local.ty(db).as_reference() { 236 "variable"
235 Some((_, Mutability::Mut)) => "variable.mut",
236 _ => "variable",
237 }
238 } 237 }
239 } 238 }
240 } 239 }
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 72dbe06dc..58b9cfaa0 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -17,7 +17,7 @@ flexi_logger = "0.14.0"
17log = "0.4.3" 17log = "0.4.3"
18lsp-types = { version = "0.61.0", features = ["proposed"] } 18lsp-types = { version = "0.61.0", features = ["proposed"] }
19rustc-hash = "1.0" 19rustc-hash = "1.0"
20parking_lot = "0.9.0" 20parking_lot = "0.10.0"
21jod-thread = "0.1.0" 21jod-thread = "0.1.0"
22ra_vfs = "0.5.0" 22ra_vfs = "0.5.0"
23ra_syntax = { path = "../ra_syntax" } 23ra_syntax = { path = "../ra_syntax" }