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/add_new.rs4
-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_batch/Cargo.toml2
-rw-r--r--crates/ra_batch/src/lib.rs2
-rw-r--r--crates/ra_cli/Cargo.toml3
-rw-r--r--crates/ra_cli/src/analysis_bench.rs6
-rw-r--r--crates/ra_cli/src/analysis_stats.rs14
-rw-r--r--crates/ra_cli/src/main.rs3
-rw-r--r--crates/ra_cli/src/progress_report.rs120
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_db/src/lib.rs2
-rw-r--r--crates/ra_hir/Cargo.toml19
-rw-r--r--crates/ra_hir/src/code_model.rs449
-rw-r--r--crates/ra_hir/src/code_model/src.rs12
-rw-r--r--crates/ra_hir/src/db.rs132
-rw-r--r--crates/ra_hir/src/diagnostics.rs86
-rw-r--r--crates/ra_hir/src/from_id.rs104
-rw-r--r--crates/ra_hir/src/from_source.rs26
-rw-r--r--crates/ra_hir/src/lib.rs11
-rw-r--r--crates/ra_hir/src/source_binder.rs113
-rw-r--r--crates/ra_hir/src/ty.rs1092
-rw-r--r--crates/ra_hir/src/util.rs12
-rw-r--r--crates/ra_hir_def/src/adt.rs43
-rw-r--r--crates/ra_hir_def/src/attr.rs6
-rw-r--r--crates/ra_hir_def/src/body.rs7
-rw-r--r--crates/ra_hir_def/src/data.rs60
-rw-r--r--crates/ra_hir_def/src/db.rs12
-rw-r--r--crates/ra_hir_def/src/docs.rs6
-rw-r--r--crates/ra_hir_def/src/generics.rs6
-rw-r--r--crates/ra_hir_def/src/lang_item.rs4
-rw-r--r--crates/ra_hir_def/src/lib.rs57
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs36
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs16
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs13
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs7
-rw-r--r--crates/ra_hir_def/src/path.rs2
-rw-r--r--crates/ra_hir_def/src/resolver.rs12
-rw-r--r--crates/ra_hir_def/src/test_db.rs4
-rw-r--r--crates/ra_hir_expand/src/lib.rs14
-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/autoderef.rs (renamed from crates/ra_hir/src/ty/autoderef.rs)55
-rw-r--r--crates/ra_hir_ty/src/db.rs119
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs91
-rw-r--r--crates/ra_hir_ty/src/display.rs (renamed from crates/ra_hir/src/ty/display.rs)0
-rw-r--r--crates/ra_hir_ty/src/expr.rs (renamed from crates/ra_hir/src/expr.rs)43
-rw-r--r--crates/ra_hir_ty/src/infer.rs (renamed from crates/ra_hir/src/ty/infer.rs)161
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs (renamed from crates/ra_hir/src/ty/infer/coerce.rs)37
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs (renamed from crates/ra_hir/src/ty/infer/expr.rs)117
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs (renamed from crates/ra_hir/src/ty/infer/pat.rs)31
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs (renamed from crates/ra_hir/src/ty/infer/path.rs)98
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs (renamed from crates/ra_hir/src/ty/infer/unify.rs)8
-rw-r--r--crates/ra_hir_ty/src/lib.rs1138
-rw-r--r--crates/ra_hir_ty/src/lower.rs (renamed from crates/ra_hir/src/ty/lower.rs)444
-rw-r--r--crates/ra_hir_ty/src/marks.rs (renamed from crates/ra_hir/src/marks.rs)0
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs (renamed from crates/ra_hir/src/ty/method_resolution.rs)246
-rw-r--r--crates/ra_hir_ty/src/op.rs (renamed from crates/ra_hir/src/ty/op.rs)6
-rw-r--r--crates/ra_hir_ty/src/primitive.rs (renamed from crates/ra_hir/src/ty/primitive.rs)41
-rw-r--r--crates/ra_hir_ty/src/test_db.rs (renamed from crates/ra_hir/src/test_db.rs)85
-rw-r--r--crates/ra_hir_ty/src/tests.rs (renamed from crates/ra_hir/src/ty/tests.rs)113
-rw-r--r--crates/ra_hir_ty/src/tests/coercion.rs (renamed from crates/ra_hir/src/ty/tests/coercion.rs)0
-rw-r--r--crates/ra_hir_ty/src/tests/never_type.rs (renamed from crates/ra_hir/src/ty/tests/never_type.rs)0
-rw-r--r--crates/ra_hir_ty/src/traits.rs (renamed from crates/ra_hir/src/ty/traits.rs)30
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs (renamed from crates/ra_hir/src/ty/traits/chalk.rs)202
-rw-r--r--crates/ra_hir_ty/src/utils.rs84
-rw-r--r--crates/ra_ide/Cargo.toml (renamed from crates/ra_ide_api/Cargo.toml)4
-rw-r--r--crates/ra_ide/src/assists.rs (renamed from crates/ra_ide_api/src/assists.rs)0
-rw-r--r--crates/ra_ide/src/call_info.rs (renamed from crates/ra_ide_api/src/call_info.rs)24
-rw-r--r--crates/ra_ide/src/change.rs (renamed from crates/ra_ide_api/src/change.rs)5
-rw-r--r--crates/ra_ide/src/completion.rs (renamed from crates/ra_ide_api/src/completion.rs)0
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs (renamed from crates/ra_ide_api/src/completion/complete_dot.rs)36
-rw-r--r--crates/ra_ide/src/completion/complete_fn_param.rs (renamed from crates/ra_ide_api/src/completion/complete_fn_param.rs)0
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs (renamed from crates/ra_ide_api/src/completion/complete_keyword.rs)0
-rw-r--r--crates/ra_ide/src/completion/complete_macro_in_item_position.rs (renamed from crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs)0
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs (renamed from crates/ra_ide_api/src/completion/complete_path.rs)2
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs (renamed from crates/ra_ide_api/src/completion/complete_pattern.rs)0
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs (renamed from crates/ra_ide_api/src/completion/complete_postfix.rs)16
-rw-r--r--crates/ra_ide/src/completion/complete_record_literal.rs (renamed from crates/ra_ide_api/src/completion/complete_record_literal.rs)7
-rw-r--r--crates/ra_ide/src/completion/complete_record_pattern.rs (renamed from crates/ra_ide_api/src/completion/complete_record_pattern.rs)7
-rw-r--r--crates/ra_ide/src/completion/complete_scope.rs (renamed from crates/ra_ide_api/src/completion/complete_scope.rs)0
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs (renamed from crates/ra_ide_api/src/completion/complete_snippet.rs)0
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs (renamed from crates/ra_ide_api/src/completion/completion_context.rs)0
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs (renamed from crates/ra_ide_api/src/completion/completion_item.rs)0
-rw-r--r--crates/ra_ide/src/completion/presentation.rs (renamed from crates/ra_ide_api/src/completion/presentation.rs)44
-rw-r--r--crates/ra_ide/src/db.rs (renamed from crates/ra_ide_api/src/db.rs)3
-rw-r--r--crates/ra_ide/src/diagnostics.rs (renamed from crates/ra_ide_api/src/diagnostics.rs)0
-rw-r--r--crates/ra_ide/src/display.rs (renamed from crates/ra_ide_api/src/display.rs)0
-rw-r--r--crates/ra_ide/src/display/function_signature.rs (renamed from crates/ra_ide_api/src/display/function_signature.rs)7
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs (renamed from crates/ra_ide_api/src/display/navigation_target.rs)0
-rw-r--r--crates/ra_ide/src/display/short_label.rs (renamed from crates/ra_ide_api/src/display/short_label.rs)6
-rw-r--r--crates/ra_ide/src/display/structure.rs (renamed from crates/ra_ide_api/src/display/structure.rs)0
-rw-r--r--crates/ra_ide/src/expand.rs (renamed from crates/ra_ide_api/src/expand.rs)0
-rw-r--r--crates/ra_ide/src/expand_macro.rs (renamed from crates/ra_ide_api/src/expand_macro.rs)23
-rw-r--r--crates/ra_ide/src/extend_selection.rs (renamed from crates/ra_ide_api/src/extend_selection.rs)0
-rw-r--r--crates/ra_ide/src/feature_flags.rs (renamed from crates/ra_ide_api/src/feature_flags.rs)0
-rw-r--r--crates/ra_ide/src/folding_ranges.rs (renamed from crates/ra_ide_api/src/folding_ranges.rs)0
-rw-r--r--crates/ra_ide/src/goto_definition.rs (renamed from crates/ra_ide_api/src/goto_definition.rs)23
-rw-r--r--crates/ra_ide/src/goto_type_definition.rs (renamed from crates/ra_ide_api/src/goto_type_definition.rs)4
-rw-r--r--crates/ra_ide/src/hover.rs (renamed from crates/ra_ide_api/src/hover.rs)95
-rw-r--r--crates/ra_ide/src/impls.rs (renamed from crates/ra_ide_api/src/impls.rs)29
-rw-r--r--crates/ra_ide/src/inlay_hints.rs (renamed from crates/ra_ide_api/src/inlay_hints.rs)23
-rw-r--r--crates/ra_ide/src/join_lines.rs (renamed from crates/ra_ide_api/src/join_lines.rs)0
-rw-r--r--crates/ra_ide/src/lib.rs (renamed from crates/ra_ide_api/src/lib.rs)2
-rw-r--r--crates/ra_ide/src/line_index.rs (renamed from crates/ra_ide_api/src/line_index.rs)0
-rw-r--r--crates/ra_ide/src/line_index_utils.rs (renamed from crates/ra_ide_api/src/line_index_utils.rs)0
-rw-r--r--crates/ra_ide/src/marks.rs (renamed from crates/ra_ide_api/src/marks.rs)0
-rw-r--r--crates/ra_ide/src/matching_brace.rs (renamed from crates/ra_ide_api/src/matching_brace.rs)0
-rw-r--r--crates/ra_ide/src/mock_analysis.rs (renamed from crates/ra_ide_api/src/mock_analysis.rs)0
-rw-r--r--crates/ra_ide/src/parent_module.rs (renamed from crates/ra_ide_api/src/parent_module.rs)0
-rw-r--r--crates/ra_ide/src/references.rs (renamed from crates/ra_ide_api/src/references.rs)5
-rw-r--r--crates/ra_ide/src/references/classify.rs (renamed from crates/ra_ide_api/src/references/classify.rs)5
-rw-r--r--crates/ra_ide/src/references/name_definition.rs (renamed from crates/ra_ide_api/src/references/name_definition.rs)7
-rw-r--r--crates/ra_ide/src/references/rename.rs (renamed from crates/ra_ide_api/src/references/rename.rs)0
-rw-r--r--crates/ra_ide/src/references/search_scope.rs (renamed from crates/ra_ide_api/src/references/search_scope.rs)0
-rw-r--r--crates/ra_ide/src/runnables.rs (renamed from crates/ra_ide_api/src/runnables.rs)0
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html (renamed from crates/ra_ide_api/src/snapshots/highlighting.html)0
-rw-r--r--crates/ra_ide/src/snapshots/rainbow_highlighting.html (renamed from crates/ra_ide_api/src/snapshots/rainbow_highlighting.html)0
-rw-r--r--crates/ra_ide/src/source_change.rs (renamed from crates/ra_ide_api/src/source_change.rs)0
-rw-r--r--crates/ra_ide/src/status.rs (renamed from crates/ra_ide_api/src/status.rs)0
-rw-r--r--crates/ra_ide/src/symbol_index.rs (renamed from crates/ra_ide_api/src/symbol_index.rs)0
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs (renamed from crates/ra_ide_api/src/syntax_highlighting.rs)14
-rw-r--r--crates/ra_ide/src/syntax_tree.rs (renamed from crates/ra_ide_api/src/syntax_tree.rs)0
-rw-r--r--crates/ra_ide/src/test_utils.rs (renamed from crates/ra_ide_api/src/test_utils.rs)0
-rw-r--r--crates/ra_ide/src/typing.rs (renamed from crates/ra_ide_api/src/typing.rs)0
-rw-r--r--crates/ra_ide/src/wasm_shims.rs (renamed from crates/ra_ide_api/src/wasm_shims.rs)0
-rw-r--r--crates/ra_lsp_server/Cargo.toml4
-rw-r--r--crates/ra_lsp_server/src/cargo_target_spec.rs2
-rw-r--r--crates/ra_lsp_server/src/conv.rs6
-rw-r--r--crates/ra_lsp_server/src/lib.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs2
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs6
-rw-r--r--crates/ra_lsp_server/src/main_loop/subscriptions.rs2
-rw-r--r--crates/ra_lsp_server/src/world.rs2
-rw-r--r--crates/ra_parser/src/grammar/items.rs10
-rw-r--r--crates/ra_parser/src/grammar/items/adt.rs (renamed from crates/ra_parser/src/grammar/items/nominal.rs)23
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs1
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs11
-rw-r--r--crates/ra_syntax/src/ast/generated.rs54
-rw-r--r--crates/ra_syntax/src/grammar.ron17
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt4
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt2
143 files changed, 3393 insertions, 2873 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/add_new.rs b/crates/ra_assists/src/assists/add_new.rs
index ee8bff346..8f68bd5fb 100644
--- a/crates/ra_assists/src/assists/add_new.rs
+++ b/crates/ra_assists/src/assists/add_new.rs
@@ -35,8 +35,8 @@ pub(crate) fn add_new(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
35 let strukt = ctx.find_node_at_offset::<ast::StructDef>()?; 35 let strukt = ctx.find_node_at_offset::<ast::StructDef>()?;
36 36
37 // We want to only apply this to non-union structs with named fields 37 // We want to only apply this to non-union structs with named fields
38 let field_list = match (strukt.kind(), strukt.is_union()) { 38 let field_list = match strukt.kind() {
39 (StructKind::Record(named), false) => named, 39 StructKind::Record(named) => named,
40 _ => return None, 40 _ => return None,
41 }; 41 };
42 42
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_batch/Cargo.toml b/crates/ra_batch/Cargo.toml
index 35626d77d..3bf351fe3 100644
--- a/crates/ra_batch/Cargo.toml
+++ b/crates/ra_batch/Cargo.toml
@@ -15,6 +15,6 @@ crossbeam-channel = "0.4.0"
15ra_vfs = "0.5.0" 15ra_vfs = "0.5.0"
16ra_vfs_glob = { path = "../ra_vfs_glob" } 16ra_vfs_glob = { path = "../ra_vfs_glob" }
17ra_db = { path = "../ra_db" } 17ra_db = { path = "../ra_db" }
18ra_ide_api = { path = "../ra_ide_api" } 18ra_ide = { path = "../ra_ide" }
19ra_hir = { path = "../ra_hir" } 19ra_hir = { path = "../ra_hir" }
20ra_project_model = { path = "../ra_project_model" } 20ra_project_model = { path = "../ra_project_model" }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index cb389eb26..2c9645c00 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -6,7 +6,7 @@ use rustc_hash::FxHashMap;
6 6
7use crossbeam_channel::{unbounded, Receiver}; 7use crossbeam_channel::{unbounded, Receiver};
8use ra_db::{CrateGraph, FileId, SourceRootId}; 8use ra_db::{CrateGraph, FileId, SourceRootId};
9use ra_ide_api::{AnalysisChange, AnalysisHost, FeatureFlags}; 9use ra_ide::{AnalysisChange, AnalysisHost, FeatureFlags};
10use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace}; 10use ra_project_model::{get_rustc_cfg_options, PackageRoot, ProjectWorkspace};
11use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; 11use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
12use ra_vfs_glob::RustPackageFilterBuilder; 12use ra_vfs_glob::RustPackageFilterBuilder;
diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml
index c9d3bdb77..c7e0d0f0f 100644
--- a/crates/ra_cli/Cargo.toml
+++ b/crates/ra_cli/Cargo.toml
@@ -8,10 +8,9 @@ publish = false
8[dependencies] 8[dependencies]
9pico-args = "0.3.0" 9pico-args = "0.3.0"
10flexi_logger = "0.14.0" 10flexi_logger = "0.14.0"
11indicatif = "0.13.0"
12 11
13ra_syntax = { path = "../ra_syntax" } 12ra_syntax = { path = "../ra_syntax" }
14ra_ide_api = { path = "../ra_ide_api" } 13ra_ide = { path = "../ra_ide" }
15ra_batch = { path = "../ra_batch" } 14ra_batch = { path = "../ra_batch" }
16ra_hir = { path = "../ra_hir" } 15ra_hir = { path = "../ra_hir" }
17ra_db = { path = "../ra_db" } 16ra_db = { path = "../ra_db" }
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs
index 8bbe5d9e8..5485a38ff 100644
--- a/crates/ra_cli/src/analysis_bench.rs
+++ b/crates/ra_cli/src/analysis_bench.rs
@@ -10,7 +10,7 @@ use ra_db::{
10 salsa::{Database, Durability}, 10 salsa::{Database, Durability},
11 FileId, SourceDatabaseExt, 11 FileId, SourceDatabaseExt,
12}; 12};
13use ra_ide_api::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol}; 13use ra_ide::{Analysis, AnalysisChange, AnalysisHost, FilePosition, LineCol};
14 14
15use crate::Result; 15use crate::Result;
16 16
@@ -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_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index c4eb28245..9b1802a5f 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -6,7 +6,7 @@ use ra_db::SourceDatabaseExt;
6use ra_hir::{AssocItem, Crate, HasSource, HirDisplay, ModuleDef, Ty, TypeWalk}; 6use ra_hir::{AssocItem, Crate, HasSource, HirDisplay, ModuleDef, Ty, TypeWalk};
7use ra_syntax::AstNode; 7use ra_syntax::AstNode;
8 8
9use crate::{Result, Verbosity}; 9use crate::{progress_report::ProgressReport, Result, Verbosity};
10 10
11pub fn run( 11pub fn run(
12 verbosity: Verbosity, 12 verbosity: Verbosity,
@@ -75,17 +75,11 @@ pub fn run(
75 println!("Item Collection: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); 75 println!("Item Collection: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
76 76
77 let inference_time = Instant::now(); 77 let inference_time = Instant::now();
78 let bar = match verbosity { 78 let mut bar = match verbosity {
79 Verbosity::Verbose | Verbosity::Normal => indicatif::ProgressBar::with_draw_target( 79 Verbosity::Verbose | Verbosity::Normal => ProgressReport::new(funcs.len() as u64),
80 funcs.len() as u64, 80 Verbosity::Quiet => ProgressReport::hidden(),
81 indicatif::ProgressDrawTarget::stderr_nohz(),
82 ),
83 Verbosity::Quiet => indicatif::ProgressBar::hidden(),
84 }; 81 };
85 82
86 bar.set_style(
87 indicatif::ProgressStyle::default_bar().template("{wide_bar} {pos}/{len}\n{msg}"),
88 );
89 bar.tick(); 83 bar.tick();
90 let mut num_exprs = 0; 84 let mut num_exprs = 0;
91 let mut num_exprs_unknown = 0; 85 let mut num_exprs_unknown = 0;
diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs
index a31fd5d6a..fe847e611 100644
--- a/crates/ra_cli/src/main.rs
+++ b/crates/ra_cli/src/main.rs
@@ -3,12 +3,13 @@
3mod analysis_stats; 3mod analysis_stats;
4mod analysis_bench; 4mod analysis_bench;
5mod help; 5mod help;
6mod progress_report;
6 7
7use std::{error::Error, fmt::Write, io::Read}; 8use std::{error::Error, fmt::Write, io::Read};
8 9
9use flexi_logger::Logger; 10use flexi_logger::Logger;
10use pico_args::Arguments; 11use pico_args::Arguments;
11use ra_ide_api::{file_structure, Analysis}; 12use ra_ide::{file_structure, Analysis};
12use ra_prof::profile; 13use ra_prof::profile;
13use ra_syntax::{AstNode, SourceFile}; 14use ra_syntax::{AstNode, SourceFile};
14 15
diff --git a/crates/ra_cli/src/progress_report.rs b/crates/ra_cli/src/progress_report.rs
new file mode 100644
index 000000000..31867a1e9
--- /dev/null
+++ b/crates/ra_cli/src/progress_report.rs
@@ -0,0 +1,120 @@
1//! A simple progress bar
2//!
3//! A single thread non-optimized progress bar
4use std::io::Write;
5
6/// A Simple ASCII Progress Bar
7pub struct ProgressReport {
8 curr: f32,
9 text: String,
10 hidden: bool,
11
12 len: u64,
13 pos: u64,
14 msg: String,
15}
16
17impl ProgressReport {
18 pub fn new(len: u64) -> ProgressReport {
19 ProgressReport {
20 curr: 0.0,
21 text: String::new(),
22 hidden: false,
23 len,
24 pos: 0,
25 msg: String::new(),
26 }
27 }
28
29 pub fn hidden() -> ProgressReport {
30 ProgressReport {
31 curr: 0.0,
32 text: String::new(),
33 hidden: true,
34 len: 0,
35 pos: 0,
36 msg: String::new(),
37 }
38 }
39
40 pub fn set_message(&mut self, msg: &str) {
41 self.msg = msg.to_string();
42 self.tick();
43 }
44
45 pub fn println<I: Into<String>>(&mut self, msg: I) {
46 self.clear();
47 println!("{}", msg.into());
48 self.tick();
49 }
50
51 pub fn inc(&mut self, delta: u64) {
52 self.pos += delta;
53 if self.len == 0 {
54 self.set_value(0.0)
55 } else {
56 self.set_value((self.pos as f32) / (self.len as f32))
57 }
58 self.tick();
59 }
60
61 pub fn finish_and_clear(&mut self) {
62 self.clear();
63 }
64
65 pub fn tick(&mut self) {
66 if self.hidden {
67 return;
68 }
69 let percent = (self.curr * 100.0) as u32;
70 let text = format!("{}/{} {:3>}% {}", self.pos, self.len, percent, self.msg);
71 self.update_text(&text);
72 }
73
74 fn update_text(&mut self, text: &str) {
75 // Get length of common portion
76 let mut common_prefix_length = 0;
77 let common_length = usize::min(self.text.len(), text.len());
78
79 while common_prefix_length < common_length
80 && text.chars().nth(common_prefix_length).unwrap()
81 == self.text.chars().nth(common_prefix_length).unwrap()
82 {
83 common_prefix_length += 1;
84 }
85
86 // Backtrack to the first differing character
87 let mut output = String::new();
88 output += &'\x08'.to_string().repeat(self.text.len() - common_prefix_length);
89 // Output new suffix
90 output += &text[common_prefix_length..text.len()];
91
92 // If the new text is shorter than the old one: delete overlapping characters
93 if let Some(overlap_count) = self.text.len().checked_sub(text.len()) {
94 if overlap_count > 0 {
95 output += &" ".repeat(overlap_count);
96 output += &"\x08".repeat(overlap_count);
97 }
98 }
99
100 let _ = std::io::stdout().write(output.as_bytes());
101 let _ = std::io::stdout().flush();
102 self.text = text.to_string();
103 }
104
105 fn set_value(&mut self, value: f32) {
106 self.curr = f32::max(0.0, f32::min(1.0, value));
107 }
108
109 fn clear(&mut self) {
110 if self.hidden {
111 return;
112 }
113
114 // Fill all last text to space and return the cursor
115 let spaces = " ".repeat(self.text.len());
116 let backspaces = "\x08".repeat(self.text.len());
117 print!("{}{}{}", backspaces, spaces, backspaces);
118 self.text = String::new();
119 }
120}
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_db/src/lib.rs b/crates/ra_db/src/lib.rs
index e8852531b..21341b769 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -1,4 +1,4 @@
1//! ra_db defines basic database traits. The concrete DB is defined by ra_ide_api. 1//! ra_db defines basic database traits. The concrete DB is defined by ra_ide.
2mod cancellation; 2mod cancellation;
3mod input; 3mod input;
4pub mod fixture; 4pub mod fixture;
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 42ddfecc9..e79361e7c 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -8,28 +8,11 @@ authors = ["rust-analyzer developers"]
8doctest = false 8doctest = false
9 9
10[dependencies] 10[dependencies]
11arrayvec = "0.5.1"
12log = "0.4.5" 11log = "0.4.5"
13rustc-hash = "1.0" 12rustc-hash = "1.0"
14parking_lot = "0.9.0"
15ena = "0.13"
16once_cell = "1.0.1"
17 13
18ra_syntax = { path = "../ra_syntax" } 14ra_syntax = { path = "../ra_syntax" }
19ra_arena = { path = "../ra_arena" }
20ra_cfg = { path = "../ra_cfg" }
21ra_db = { path = "../ra_db" } 15ra_db = { path = "../ra_db" }
22mbe = { path = "../ra_mbe", package = "ra_mbe" }
23tt = { path = "../ra_tt", package = "ra_tt" }
24hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" } 16hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" }
25hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } 17hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
26test_utils = { path = "../test_utils" } 18hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }
27ra_prof = { path = "../ra_prof" }
28
29chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" }
30chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" }
31chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "a88cad7f0a69e05ba8f40b74c58a1c229c1b2478" }
32lalrpop-intern = "0.15.1"
33
34[dev-dependencies]
35insta = "0.12.0"
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 3f44a50c4..38d66c2a7 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -6,28 +6,31 @@ use std::sync::Arc;
6 6
7use hir_def::{ 7use hir_def::{
8 adt::VariantData, 8 adt::VariantData,
9 body::{Body, BodySourceMap},
9 builtin_type::BuiltinType, 10 builtin_type::BuiltinType,
10 docs::Documentation, 11 docs::Documentation,
12 expr::{BindingAnnotation, Pat, PatId},
11 per_ns::PerNs, 13 per_ns::PerNs,
12 resolver::{HasResolver, TypeNs}, 14 resolver::HasResolver,
13 type_ref::TypeRef, 15 type_ref::{Mutability, TypeRef},
14 AstItemDef, ConstId, ContainerId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId, 16 AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId,
15 LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, 17 HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId,
16 TraitId, TypeAliasId, UnionId, 18 Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId,
17}; 19};
18use hir_expand::{ 20use hir_expand::{
19 diagnostics::DiagnosticSink, 21 diagnostics::DiagnosticSink,
20 name::{self, AsName}, 22 name::{self, AsName},
21 AstId, MacroDefId, 23 AstId, MacroDefId,
22}; 24};
25use hir_ty::expr::ExprValidator;
23use ra_db::{CrateId, Edition, FileId, FilePosition}; 26use ra_db::{CrateId, Edition, FileId, FilePosition};
24use ra_syntax::{ast, AstNode, SyntaxNode}; 27use ra_syntax::{ast, AstNode, SyntaxNode};
25 28
26use crate::{ 29use crate::{
27 db::{DefDatabase, HirDatabase}, 30 db::{DefDatabase, HirDatabase},
28 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 31 ty::display::HirFormatter,
29 ty::{InferenceResult, Namespace, TraitRef}, 32 ty::{self, InEnvironment, InferenceResult, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk},
30 Either, Name, Source, Ty, 33 CallableDef, Either, HirDisplay, Name, Source,
31}; 34};
32 35
33/// hir::Crate describes a single crate. It's the main interface with which 36/// hir::Crate describes a single crate. It's the main interface with which
@@ -168,15 +171,15 @@ pub use hir_def::attr::Attrs;
168 171
169impl Module { 172impl Module {
170 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { 173 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
171 Module { id: ModuleId { krate: krate.crate_id, module_id: crate_module_id } } 174 Module { id: ModuleId { krate: krate.crate_id, local_id: crate_module_id } }
172 } 175 }
173 176
174 /// Name of this module. 177 /// Name of this module.
175 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 178 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
176 let def_map = db.crate_def_map(self.id.krate); 179 let def_map = db.crate_def_map(self.id.krate);
177 let parent = def_map[self.id.module_id].parent?; 180 let parent = def_map[self.id.local_id].parent?;
178 def_map[parent].children.iter().find_map(|(name, module_id)| { 181 def_map[parent].children.iter().find_map(|(name, module_id)| {
179 if *module_id == self.id.module_id { 182 if *module_id == self.id.local_id {
180 Some(name.clone()) 183 Some(name.clone())
181 } else { 184 } else {
182 None 185 None
@@ -200,14 +203,14 @@ impl Module {
200 /// Finds a child module with the specified name. 203 /// Finds a child module with the specified name.
201 pub fn child(self, db: &impl DefDatabase, name: &Name) -> Option<Module> { 204 pub fn child(self, db: &impl DefDatabase, name: &Name) -> Option<Module> {
202 let def_map = db.crate_def_map(self.id.krate); 205 let def_map = db.crate_def_map(self.id.krate);
203 let child_id = def_map[self.id.module_id].children.get(name)?; 206 let child_id = def_map[self.id.local_id].children.get(name)?;
204 Some(self.with_module_id(*child_id)) 207 Some(self.with_module_id(*child_id))
205 } 208 }
206 209
207 /// Iterates over all child modules. 210 /// Iterates over all child modules.
208 pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> { 211 pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> {
209 let def_map = db.crate_def_map(self.id.krate); 212 let def_map = db.crate_def_map(self.id.krate);
210 let children = def_map[self.id.module_id] 213 let children = def_map[self.id.local_id]
211 .children 214 .children
212 .iter() 215 .iter()
213 .map(|(_, module_id)| self.with_module_id(*module_id)) 216 .map(|(_, module_id)| self.with_module_id(*module_id))
@@ -218,7 +221,7 @@ impl Module {
218 /// Finds a parent module. 221 /// Finds a parent module.
219 pub fn parent(self, db: &impl DefDatabase) -> Option<Module> { 222 pub fn parent(self, db: &impl DefDatabase) -> Option<Module> {
220 let def_map = db.crate_def_map(self.id.krate); 223 let def_map = db.crate_def_map(self.id.krate);
221 let parent_id = def_map[self.id.module_id].parent?; 224 let parent_id = def_map[self.id.local_id].parent?;
222 Some(self.with_module_id(parent_id)) 225 Some(self.with_module_id(parent_id))
223 } 226 }
224 227
@@ -234,7 +237,7 @@ impl Module {
234 237
235 /// Returns a `ModuleScope`: a set of items, visible in this module. 238 /// Returns a `ModuleScope`: a set of items, visible in this module.
236 pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<Import>)> { 239 pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option<Import>)> {
237 db.crate_def_map(self.id.krate)[self.id.module_id] 240 db.crate_def_map(self.id.krate)[self.id.local_id]
238 .scope 241 .scope
239 .entries() 242 .entries()
240 .map(|(name, res)| { 243 .map(|(name, res)| {
@@ -244,7 +247,7 @@ impl Module {
244 } 247 }
245 248
246 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { 249 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
247 db.crate_def_map(self.id.krate).add_diagnostics(db, self.id.module_id, sink); 250 db.crate_def_map(self.id.krate).add_diagnostics(db, self.id.local_id, sink);
248 for decl in self.declarations(db) { 251 for decl in self.declarations(db) {
249 match decl { 252 match decl {
250 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 253 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
@@ -269,12 +272,12 @@ impl Module {
269 272
270 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> { 273 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
271 let def_map = db.crate_def_map(self.id.krate); 274 let def_map = db.crate_def_map(self.id.krate);
272 def_map[self.id.module_id].scope.declarations().map(ModuleDef::from).collect() 275 def_map[self.id.local_id].scope.declarations().map(ModuleDef::from).collect()
273 } 276 }
274 277
275 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> { 278 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
276 let def_map = db.crate_def_map(self.id.krate); 279 let def_map = db.crate_def_map(self.id.krate);
277 def_map[self.id.module_id].impls.iter().copied().map(ImplBlock::from).collect() 280 def_map[self.id.local_id].impls.iter().copied().map(ImplBlock::from).collect()
278 } 281 }
279 282
280 fn with_module_id(self, module_id: LocalModuleId) -> Module { 283 fn with_module_id(self, module_id: LocalModuleId) -> Module {
@@ -320,14 +323,14 @@ pub struct Struct {
320 323
321impl Struct { 324impl Struct {
322 pub fn module(self, db: &impl DefDatabase) -> Module { 325 pub fn module(self, db: &impl DefDatabase) -> Module {
323 Module { id: self.id.0.module(db) } 326 Module { id: self.id.module(db) }
324 } 327 }
325 328
326 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 329 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
327 Some(self.module(db).krate()) 330 Some(self.module(db).krate())
328 } 331 }
329 332
330 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 333 pub fn name(self, db: &impl DefDatabase) -> Name {
331 db.struct_data(self.id.into()).name.clone() 334 db.struct_data(self.id.into()).name.clone()
332 } 335 }
333 336
@@ -349,12 +352,12 @@ impl Struct {
349 .map(|(id, _)| StructField { parent: self.into(), id }) 352 .map(|(id, _)| StructField { parent: self.into(), id })
350 } 353 }
351 354
352 pub fn ty(self, db: &impl HirDatabase) -> Ty { 355 pub fn ty(self, db: &impl HirDatabase) -> Type {
353 db.type_for_def(self.into(), Namespace::Types) 356 Type::from_def(db, self.id.module(db).krate, self.id)
354 } 357 }
355 358
356 pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty { 359 pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty {
357 db.type_for_def(self.into(), Namespace::Values) 360 db.value_ty(self.id.into())
358 } 361 }
359 362
360 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 363 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
@@ -368,16 +371,38 @@ pub struct Union {
368} 371}
369 372
370impl Union { 373impl Union {
371 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 374 pub fn name(self, db: &impl DefDatabase) -> Name {
372 db.struct_data(self.id.into()).name.clone() 375 db.union_data(self.id).name.clone()
373 } 376 }
374 377
375 pub fn module(self, db: &impl DefDatabase) -> Module { 378 pub fn module(self, db: &impl DefDatabase) -> Module {
376 Module { id: self.id.0.module(db) } 379 Module { id: self.id.module(db) }
377 } 380 }
378 381
379 pub fn ty(self, db: &impl HirDatabase) -> Ty { 382 pub fn ty(self, db: &impl HirDatabase) -> Type {
380 db.type_for_def(self.into(), Namespace::Types) 383 Type::from_def(db, self.id.module(db).krate, self.id)
384 }
385
386 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
387 db.union_data(self.id)
388 .variant_data
389 .fields()
390 .iter()
391 .map(|(id, _)| StructField { parent: self.into(), id })
392 .collect()
393 }
394
395 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
396 db.union_data(self.id)
397 .variant_data
398 .fields()
399 .iter()
400 .find(|(_id, data)| data.name == *name)
401 .map(|(id, _)| StructField { parent: self.into(), id })
402 }
403
404 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
405 db.union_data(self.id).variant_data.clone()
381 } 406 }
382} 407}
383 408
@@ -395,7 +420,7 @@ impl Enum {
395 Some(self.module(db).krate()) 420 Some(self.module(db).krate())
396 } 421 }
397 422
398 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 423 pub fn name(self, db: &impl DefDatabase) -> Name {
399 db.enum_data(self.id).name.clone() 424 db.enum_data(self.id).name.clone()
400 } 425 }
401 426
@@ -408,15 +433,12 @@ impl Enum {
408 } 433 }
409 434
410 pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> { 435 pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> {
411 db.enum_data(self.id) 436 let id = db.enum_data(self.id).variant(name)?;
412 .variants 437 Some(EnumVariant { parent: self, id })
413 .iter()
414 .find(|(_id, data)| data.name.as_ref() == Some(name))
415 .map(|(id, _)| EnumVariant { parent: self, id })
416 } 438 }
417 439
418 pub fn ty(self, db: &impl HirDatabase) -> Ty { 440 pub fn ty(self, db: &impl HirDatabase) -> Type {
419 db.type_for_def(self.into(), Namespace::Types) 441 Type::from_def(db, self.id.module(db).krate, self.id)
420 } 442 }
421} 443}
422 444
@@ -434,7 +456,7 @@ impl EnumVariant {
434 self.parent 456 self.parent
435 } 457 }
436 458
437 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 459 pub fn name(self, db: &impl DefDatabase) -> Name {
438 db.enum_data(self.parent.id).variants[self.id].name.clone() 460 db.enum_data(self.parent.id).variants[self.id].name.clone()
439 } 461 }
440 462
@@ -469,12 +491,13 @@ pub enum Adt {
469impl_froms!(Adt: Struct, Union, Enum); 491impl_froms!(Adt: Struct, Union, Enum);
470 492
471impl Adt { 493impl Adt {
472 pub fn ty(self, db: &impl HirDatabase) -> Ty { 494 pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool {
473 match self { 495 let subst = db.generic_defaults(self.into());
474 Adt::Struct(it) => it.ty(db), 496 subst.iter().any(|ty| ty == &Ty::Unknown)
475 Adt::Union(it) => it.ty(db), 497 }
476 Adt::Enum(it) => it.ty(db), 498 pub fn ty(self, db: &impl HirDatabase) -> Type {
477 } 499 let id = AdtId::from(self);
500 Type::from_def(db, id.module(db).krate, id)
478 } 501 }
479 502
480 pub fn module(self, db: &impl DefDatabase) -> Module { 503 pub fn module(self, db: &impl DefDatabase) -> Module {
@@ -493,28 +516,24 @@ impl Adt {
493#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 516#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
494pub enum VariantDef { 517pub enum VariantDef {
495 Struct(Struct), 518 Struct(Struct),
519 Union(Union),
496 EnumVariant(EnumVariant), 520 EnumVariant(EnumVariant),
497} 521}
498impl_froms!(VariantDef: Struct, EnumVariant); 522impl_froms!(VariantDef: Struct, Union, EnumVariant);
499 523
500impl VariantDef { 524impl VariantDef {
501 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { 525 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
502 match self { 526 match self {
503 VariantDef::Struct(it) => it.fields(db), 527 VariantDef::Struct(it) => it.fields(db),
528 VariantDef::Union(it) => it.fields(db),
504 VariantDef::EnumVariant(it) => it.fields(db), 529 VariantDef::EnumVariant(it) => it.fields(db),
505 } 530 }
506 } 531 }
507 532
508 pub(crate) fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
509 match self {
510 VariantDef::Struct(it) => it.field(db, name),
511 VariantDef::EnumVariant(it) => it.field(db, name),
512 }
513 }
514
515 pub fn module(self, db: &impl HirDatabase) -> Module { 533 pub fn module(self, db: &impl HirDatabase) -> Module {
516 match self { 534 match self {
517 VariantDef::Struct(it) => it.module(db), 535 VariantDef::Struct(it) => it.module(db),
536 VariantDef::Union(it) => it.module(db),
518 VariantDef::EnumVariant(it) => it.module(db), 537 VariantDef::EnumVariant(it) => it.module(db),
519 } 538 }
520 } 539 }
@@ -522,6 +541,7 @@ impl VariantDef {
522 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { 541 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
523 match self { 542 match self {
524 VariantDef::Struct(it) => it.variant_data(db), 543 VariantDef::Struct(it) => it.variant_data(db),
544 VariantDef::Union(it) => it.variant_data(db),
525 VariantDef::EnumVariant(it) => it.variant_data(db), 545 VariantDef::EnumVariant(it) => it.variant_data(db),
526 } 546 }
527 } 547 }
@@ -538,14 +558,6 @@ pub enum DefWithBody {
538impl_froms!(DefWithBody: Function, Const, Static); 558impl_froms!(DefWithBody: Function, Const, Static);
539 559
540impl DefWithBody { 560impl DefWithBody {
541 pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
542 match self {
543 DefWithBody::Const(c) => c.krate(db),
544 DefWithBody::Function(f) => f.krate(db),
545 DefWithBody::Static(s) => s.krate(db),
546 }
547 }
548
549 pub fn module(self, db: &impl HirDatabase) -> Module { 561 pub fn module(self, db: &impl HirDatabase) -> Module {
550 match self { 562 match self {
551 DefWithBody::Const(c) => c.module(db), 563 DefWithBody::Const(c) => c.module(db),
@@ -590,11 +602,11 @@ impl Function {
590 } 602 }
591 603
592 pub fn ty(self, db: &impl HirDatabase) -> Ty { 604 pub fn ty(self, db: &impl HirDatabase) -> Ty {
593 db.type_for_def(self.into(), Namespace::Values) 605 db.value_ty(self.id.into())
594 } 606 }
595 607
596 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 608 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
597 db.infer(self.into()) 609 db.infer(self.id.into())
598 } 610 }
599 611
600 /// The containing impl block, if this is a method. 612 /// The containing impl block, if this is a method.
@@ -623,8 +635,8 @@ impl Function {
623 635
624 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { 636 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
625 let infer = self.infer(db); 637 let infer = self.infer(db);
626 infer.add_diagnostics(db, self, sink); 638 infer.add_diagnostics(db, self.id, sink);
627 let mut validator = ExprValidator::new(self, infer, sink); 639 let mut validator = ExprValidator::new(self.id, infer, sink);
628 validator.validate_body(db); 640 validator.validate_body(db);
629 } 641 }
630} 642}
@@ -648,7 +660,7 @@ impl Const {
648 } 660 }
649 661
650 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 662 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
651 db.infer(self.into()) 663 db.infer(self.id.into())
652 } 664 }
653 665
654 /// The containing impl block, if this is a type alias. 666 /// The containing impl block, if this is a type alias.
@@ -691,7 +703,7 @@ impl Static {
691 } 703 }
692 704
693 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 705 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
694 db.infer(self.into()) 706 db.infer(self.id.into())
695 } 707 }
696} 708}
697 709
@@ -705,73 +717,12 @@ impl Trait {
705 Module { id: self.id.module(db) } 717 Module { id: self.id.module(db) }
706 } 718 }
707 719
708 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 720 pub fn name(self, db: &impl DefDatabase) -> Name {
709 db.trait_data(self.id).name.clone() 721 db.trait_data(self.id).name.clone()
710 } 722 }
711 723
712 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { 724 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> {
713 db.trait_data(self.id).items.iter().map(|it| (*it).into()).collect() 725 db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
714 }
715
716 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
717 let resolver = self.id.resolver(db);
718 // returning the iterator directly doesn't easily work because of
719 // lifetime problems, but since there usually shouldn't be more than a
720 // few direct traits this should be fine (we could even use some kind of
721 // SmallVec if performance is a concern)
722 db.generic_params(self.id.into())
723 .where_predicates
724 .iter()
725 .filter_map(|pred| match &pred.type_ref {
726 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
727 _ => None,
728 })
729 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
730 Some(TypeNs::TraitId(t)) => Some(t),
731 _ => None,
732 })
733 .map(Trait::from)
734 .collect()
735 }
736
737 /// Returns an iterator over the whole super trait hierarchy (including the
738 /// trait itself).
739 pub fn all_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
740 // we need to take care a bit here to avoid infinite loops in case of cycles
741 // (i.e. if we have `trait A: B; trait B: A;`)
742 let mut result = vec![self];
743 let mut i = 0;
744 while i < result.len() {
745 let t = result[i];
746 // yeah this is quadratic, but trait hierarchies should be flat
747 // enough that this doesn't matter
748 for tt in t.direct_super_traits(db) {
749 if !result.contains(&tt) {
750 result.push(tt);
751 }
752 }
753 i += 1;
754 }
755 result
756 }
757
758 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
759 let trait_data = db.trait_data(self.id);
760 let res =
761 trait_data.associated_types().map(TypeAlias::from).find(|t| &t.name(db) == name)?;
762 Some(res)
763 }
764
765 pub fn associated_type_by_name_including_super_traits(
766 self,
767 db: &impl HirDatabase,
768 name: &Name,
769 ) -> Option<TypeAlias> {
770 self.all_super_traits(db).into_iter().find_map(|t| t.associated_type_by_name(db, name))
771 }
772
773 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
774 TraitRef::for_trait(db, self)
775 } 726 }
776 727
777 pub fn is_auto(self, db: &impl DefDatabase) -> bool { 728 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
@@ -785,6 +736,11 @@ pub struct TypeAlias {
785} 736}
786 737
787impl TypeAlias { 738impl TypeAlias {
739 pub fn has_non_default_type_params(self, db: &impl HirDatabase) -> bool {
740 let subst = db.generic_defaults(self.id.into());
741 subst.iter().any(|ty| ty == &Ty::Unknown)
742 }
743
788 pub fn module(self, db: &impl DefDatabase) -> Module { 744 pub fn module(self, db: &impl DefDatabase) -> Module {
789 Module { id: self.id.lookup(db).module(db) } 745 Module { id: self.id.lookup(db).module(db) }
790 } 746 }
@@ -821,8 +777,8 @@ impl TypeAlias {
821 db.type_alias_data(self.id).type_ref.clone() 777 db.type_alias_data(self.id).type_ref.clone()
822 } 778 }
823 779
824 pub fn ty(self, db: &impl HirDatabase) -> Ty { 780 pub fn ty(self, db: &impl HirDatabase) -> Type {
825 db.type_for_def(self.into(), Namespace::Types) 781 Type::from_def(db, self.id.lookup(db).module(db).krate, self.id)
826 } 782 }
827 783
828 pub fn name(self, db: &impl DefDatabase) -> Name { 784 pub fn name(self, db: &impl DefDatabase) -> Name {
@@ -897,16 +853,6 @@ impl_froms!(
897 Const 853 Const
898); 854);
899 855
900impl From<AssocItem> for GenericDef {
901 fn from(item: AssocItem) -> Self {
902 match item {
903 AssocItem::Function(f) => f.into(),
904 AssocItem::Const(c) => c.into(),
905 AssocItem::TypeAlias(t) => t.into(),
906 }
907 }
908}
909
910#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 856#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
911pub struct Local { 857pub struct Local {
912 pub(crate) parent: DefWithBody, 858 pub(crate) parent: DefWithBody,
@@ -945,9 +891,14 @@ impl Local {
945 self.parent.module(db) 891 self.parent.module(db)
946 } 892 }
947 893
948 pub fn ty(self, db: &impl HirDatabase) -> Ty { 894 pub fn ty(self, db: &impl HirDatabase) -> Type {
949 let infer = db.infer(self.parent); 895 let def = DefWithBodyId::from(self.parent);
950 infer[self.pat_id].clone() 896 let infer = db.infer(def);
897 let ty = infer[self.pat_id].clone();
898 let resolver = def.resolver(db);
899 let krate = def.module(db).krate;
900 let environment = TraitEnvironment::lower(db, &resolver);
901 Type { krate, ty: InEnvironment { value: ty, environment } }
951 } 902 }
952 903
953 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> { 904 pub fn source(self, db: &impl HirDatabase) -> Source<Either<ast::BindPat, ast::SelfParam>> {
@@ -960,7 +911,7 @@ impl Local {
960 911
961#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 912#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
962pub struct GenericParam { 913pub struct GenericParam {
963 pub(crate) parent: GenericDef, 914 pub(crate) parent: GenericDefId,
964 pub(crate) idx: u32, 915 pub(crate) idx: u32,
965} 916}
966 917
@@ -970,6 +921,15 @@ pub struct ImplBlock {
970} 921}
971 922
972impl ImplBlock { 923impl ImplBlock {
924 pub fn all_in_crate(db: &impl HirDatabase, krate: Crate) -> Vec<ImplBlock> {
925 let impls = db.impls_in_crate(krate.crate_id);
926 impls.all_impls().map(Self::from).collect()
927 }
928 pub fn for_trait(db: &impl HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplBlock> {
929 let impls = db.impls_in_crate(krate.crate_id);
930 impls.lookup_impl_blocks_for_trait(trait_.id).map(Self::from).collect()
931 }
932
973 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { 933 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
974 db.impl_data(self.id).target_trait.clone() 934 db.impl_data(self.id).target_trait.clone()
975 } 935 }
@@ -978,13 +938,12 @@ impl ImplBlock {
978 db.impl_data(self.id).target_type.clone() 938 db.impl_data(self.id).target_type.clone()
979 } 939 }
980 940
981 pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { 941 pub fn target_ty(&self, db: &impl HirDatabase) -> Type {
982 Ty::from_hir(db, &self.id.resolver(db), &self.target_type(db)) 942 let impl_data = db.impl_data(self.id);
983 } 943 let resolver = self.id.resolver(db);
984 944 let environment = TraitEnvironment::lower(db, &resolver);
985 pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> { 945 let ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
986 let target_ty = self.target_ty(db); 946 Type { krate: self.id.module(db).krate, ty: InEnvironment { value: ty, environment } }
987 TraitRef::from_hir(db, &self.id.resolver(db), &self.target_trait(db)?, Some(target_ty))
988 } 947 }
989 948
990 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> { 949 pub fn items(&self, db: &impl DefDatabase) -> Vec<AssocItem> {
@@ -1004,6 +963,194 @@ impl ImplBlock {
1004 } 963 }
1005} 964}
1006 965
966#[derive(Clone, PartialEq, Eq, Debug)]
967pub struct Type {
968 pub(crate) krate: CrateId,
969 pub(crate) ty: InEnvironment<Ty>,
970}
971
972impl Type {
973 fn from_def(
974 db: &impl HirDatabase,
975 krate: CrateId,
976 def: impl HasResolver + Into<TyDefId>,
977 ) -> Type {
978 let resolver = def.resolver(db);
979 let environment = TraitEnvironment::lower(db, &resolver);
980 let ty = db.ty(def.into());
981 Type { krate, ty: InEnvironment { value: ty, environment } }
982 }
983
984 pub fn is_bool(&self) -> bool {
985 match &self.ty.value {
986 Ty::Apply(a_ty) => match a_ty.ctor {
987 TypeCtor::Bool => true,
988 _ => false,
989 },
990 _ => false,
991 }
992 }
993
994 pub fn is_mutable_reference(&self) -> bool {
995 match &self.ty.value {
996 Ty::Apply(a_ty) => match a_ty.ctor {
997 TypeCtor::Ref(Mutability::Mut) => true,
998 _ => false,
999 },
1000 _ => false,
1001 }
1002 }
1003
1004 pub fn is_unknown(&self) -> bool {
1005 match &self.ty.value {
1006 Ty::Unknown => true,
1007 _ => false,
1008 }
1009 }
1010
1011 // FIXME: this method is broken, as it doesn't take closures into account.
1012 pub fn as_callable(&self) -> Option<CallableDef> {
1013 Some(self.ty.value.as_callable()?.0)
1014 }
1015
1016 pub fn contains_unknown(&self) -> bool {
1017 return go(&self.ty.value);
1018
1019 fn go(ty: &Ty) -> bool {
1020 match ty {
1021 Ty::Unknown => true,
1022 Ty::Apply(a_ty) => a_ty.parameters.iter().any(go),
1023 _ => false,
1024 }
1025 }
1026 }
1027
1028 pub fn fields(&self, db: &impl HirDatabase) -> Vec<(StructField, Type)> {
1029 if let Ty::Apply(a_ty) = &self.ty.value {
1030 match a_ty.ctor {
1031 ty::TypeCtor::Adt(AdtId::StructId(s)) => {
1032 let var_def = s.into();
1033 return db
1034 .field_types(var_def)
1035 .iter()
1036 .map(|(local_id, ty)| {
1037 let def = StructField { parent: var_def.into(), id: local_id };
1038 let ty = ty.clone().subst(&a_ty.parameters);
1039 (def, self.derived(ty))
1040 })
1041 .collect();
1042 }
1043 _ => {}
1044 }
1045 };
1046 Vec::new()
1047 }
1048
1049 pub fn tuple_fields(&self, _db: &impl HirDatabase) -> Vec<Type> {
1050 let mut res = Vec::new();
1051 if let Ty::Apply(a_ty) = &self.ty.value {
1052 match a_ty.ctor {
1053 ty::TypeCtor::Tuple { .. } => {
1054 for ty in a_ty.parameters.iter() {
1055 let ty = ty.clone().subst(&a_ty.parameters);
1056 res.push(self.derived(ty));
1057 }
1058 }
1059 _ => {}
1060 }
1061 };
1062 res
1063 }
1064
1065 pub fn variant_fields(
1066 &self,
1067 db: &impl HirDatabase,
1068 def: VariantDef,
1069 ) -> Vec<(StructField, Type)> {
1070 // FIXME: check that ty and def match
1071 match &self.ty.value {
1072 Ty::Apply(a_ty) => def
1073 .fields(db)
1074 .into_iter()
1075 .map(|it| (it, self.derived(it.ty(db).subst(&a_ty.parameters))))
1076 .collect(),
1077 _ => Vec::new(),
1078 }
1079 }
1080
1081 pub fn autoderef<'a>(&'a self, db: &'a impl HirDatabase) -> impl Iterator<Item = Type> + 'a {
1082 // There should be no inference vars in types passed here
1083 // FIXME check that?
1084 let canonical = crate::ty::Canonical { value: self.ty.value.clone(), num_vars: 0 };
1085 let environment = self.ty.environment.clone();
1086 let ty = InEnvironment { value: canonical, environment: environment.clone() };
1087 ty::autoderef(db, Some(self.krate), ty)
1088 .map(|canonical| canonical.value)
1089 .map(move |ty| self.derived(ty))
1090 }
1091
1092 // This would be nicer if it just returned an iterator, but that runs into
1093 // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
1094 pub fn iterate_impl_items<T>(
1095 self,
1096 db: &impl HirDatabase,
1097 krate: Crate,
1098 mut callback: impl FnMut(AssocItem) -> Option<T>,
1099 ) -> Option<T> {
1100 for krate in self.ty.value.def_crates(db, krate.crate_id)? {
1101 let impls = db.impls_in_crate(krate);
1102
1103 for impl_block in impls.lookup_impl_blocks(&self.ty.value) {
1104 for &item in db.impl_data(impl_block).items.iter() {
1105 if let Some(result) = callback(item.into()) {
1106 return Some(result);
1107 }
1108 }
1109 }
1110 }
1111 None
1112 }
1113
1114 // FIXME: remove
1115 pub fn into_ty(self) -> Ty {
1116 self.ty.value
1117 }
1118
1119 pub fn as_adt(&self) -> Option<Adt> {
1120 let (adt, _subst) = self.ty.value.as_adt()?;
1121 Some(adt.into())
1122 }
1123
1124 // FIXME: provide required accessors such that it becomes implementable from outside.
1125 pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
1126 match (&self.ty.value, &other.ty.value) {
1127 (Ty::Apply(a_original_ty), Ty::Apply(ty::ApplicationTy { ctor, parameters })) => {
1128 match ctor {
1129 TypeCtor::Ref(..) => match parameters.as_single() {
1130 Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor,
1131 _ => false,
1132 },
1133 _ => a_original_ty.ctor == *ctor,
1134 }
1135 }
1136 _ => false,
1137 }
1138 }
1139
1140 fn derived(&self, ty: Ty) -> Type {
1141 Type {
1142 krate: self.krate,
1143 ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
1144 }
1145 }
1146}
1147
1148impl HirDisplay for Type {
1149 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> std::fmt::Result {
1150 self.ty.value.hir_fmt(f)
1151 }
1152}
1153
1007/// For IDE only 1154/// For IDE only
1008pub enum ScopeDef { 1155pub enum ScopeDef {
1009 ModuleDef(ModuleDef), 1156 ModuleDef(ModuleDef),
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index a4e317c20..bf3ee0834 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -22,7 +22,7 @@ impl Module {
22 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. 22 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
23 pub fn definition_source(self, db: &impl DefDatabase) -> Source<ModuleSource> { 23 pub fn definition_source(self, db: &impl DefDatabase) -> Source<ModuleSource> {
24 let def_map = db.crate_def_map(self.id.krate); 24 let def_map = db.crate_def_map(self.id.krate);
25 let src = def_map[self.id.module_id].definition_source(db); 25 let src = def_map[self.id.local_id].definition_source(db);
26 src.map(|it| match it { 26 src.map(|it| match it {
27 Either::A(it) => ModuleSource::SourceFile(it), 27 Either::A(it) => ModuleSource::SourceFile(it),
28 Either::B(it) => ModuleSource::Module(it), 28 Either::B(it) => ModuleSource::Module(it),
@@ -33,7 +33,7 @@ impl Module {
33 /// `None` for the crate root. 33 /// `None` for the crate root.
34 pub fn declaration_source(self, db: &impl DefDatabase) -> Option<Source<ast::Module>> { 34 pub fn declaration_source(self, db: &impl DefDatabase) -> Option<Source<ast::Module>> {
35 let def_map = db.crate_def_map(self.id.krate); 35 let def_map = db.crate_def_map(self.id.krate);
36 def_map[self.id.module_id].declaration_source(db) 36 def_map[self.id.local_id].declaration_source(db)
37 } 37 }
38} 38}
39 39
@@ -51,13 +51,13 @@ impl HasSource for StructField {
51impl HasSource for Struct { 51impl HasSource for Struct {
52 type Ast = ast::StructDef; 52 type Ast = ast::StructDef;
53 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> { 53 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> {
54 self.id.0.source(db) 54 self.id.source(db)
55 } 55 }
56} 56}
57impl HasSource for Union { 57impl HasSource for Union {
58 type Ast = ast::StructDef; 58 type Ast = ast::UnionDef;
59 fn source(self, db: &impl DefDatabase) -> Source<ast::StructDef> { 59 fn source(self, db: &impl DefDatabase) -> Source<ast::UnionDef> {
60 self.id.0.source(db) 60 self.id.source(db)
61 } 61 }
62} 62}
63impl HasSource for Enum { 63impl HasSource for Enum {
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 5084bbacf..bfae3660b 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,130 +1,22 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::sync::Arc; 3pub use hir_def::db::{
4 4 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery,
5use ra_arena::map::ArenaMap; 5 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery,
6use ra_db::salsa; 6 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage,
7 7 LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery,
8use crate::{ 8 StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery,
9 ty::{
10 method_resolution::CrateImplBlocks,
11 traits::{AssocTyValue, Impl},
12 CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef,
13 TypeCtor,
14 },
15 Crate, DefWithBody, GenericDef, ImplBlock, Trait,
16};
17
18pub use hir_def::{
19 db::{
20 BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery,
21 DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery,
22 FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase,
23 InternDatabaseStorage, LangItemQuery, ModuleLangItemsQuery, RawItemsQuery,
24 RawItemsWithSourceMapQuery, StaticDataQuery, StructDataQuery, TraitDataQuery,
25 TypeAliasDataQuery,
26 },
27 LocalStructFieldId, VariantId,
28}; 9};
29pub use hir_expand::db::{ 10pub use hir_expand::db::{
30 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 11 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
31 ParseMacroQuery, 12 ParseMacroQuery,
32}; 13};
33 14pub use hir_ty::db::{
34#[salsa::query_group(HirDatabaseStorage)] 15 AssociatedTyDataQuery, CallableItemSignatureQuery, FieldTypesQuery, GenericDefaultsQuery,
35#[salsa::requires(salsa::Database)] 16 GenericPredicatesQuery, HirDatabase, HirDatabaseStorage, ImplDatumQuery, ImplsForTraitQuery,
36pub trait HirDatabase: DefDatabase { 17 ImplsInCrateQuery, InferQuery, StructDatumQuery, TraitDatumQuery, TraitSolveQuery, TyQuery,
37 #[salsa::invoke(crate::ty::infer_query)] 18 ValueTyQuery,
38 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>; 19};
39
40 #[salsa::invoke(crate::ty::type_for_def)]
41 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> Ty;
42
43 #[salsa::invoke(crate::ty::field_types_query)]
44 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
45
46 #[salsa::invoke(crate::ty::callable_item_sig)]
47 fn callable_item_signature(&self, def: CallableDef) -> FnSig;
48
49 #[salsa::invoke(crate::ty::generic_predicates_for_param_query)]
50 fn generic_predicates_for_param(
51 &self,
52 def: GenericDef,
53 param_idx: u32,
54 ) -> Arc<[GenericPredicate]>;
55
56 #[salsa::invoke(crate::ty::generic_predicates_query)]
57 fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>;
58
59 #[salsa::invoke(crate::ty::generic_defaults_query)]
60 fn generic_defaults(&self, def: GenericDef) -> Substs;
61
62 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
63 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
64
65 #[salsa::invoke(crate::ty::traits::impls_for_trait_query)]
66 fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>;
67
68 /// This provides the Chalk trait solver instance. Because Chalk always
69 /// works from a specific crate, this query is keyed on the crate; and
70 /// because Chalk does its own internal caching, the solver is wrapped in a
71 /// Mutex and the query does an untracked read internally, to make sure the
72 /// cached state is thrown away when input facts change.
73 #[salsa::invoke(crate::ty::traits::trait_solver_query)]
74 fn trait_solver(&self, krate: Crate) -> crate::ty::traits::TraitSolver;
75
76 // Interned IDs for Chalk integration
77 #[salsa::interned]
78 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::ty::TypeCtorId;
79 #[salsa::interned]
80 fn intern_chalk_impl(&self, impl_: Impl) -> crate::ty::traits::GlobalImplId;
81 #[salsa::interned]
82 fn intern_assoc_ty_value(
83 &self,
84 assoc_ty_value: AssocTyValue,
85 ) -> crate::ty::traits::AssocTyValueId;
86
87 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)]
88 fn associated_ty_data(
89 &self,
90 id: chalk_ir::TypeId,
91 ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>;
92
93 #[salsa::invoke(crate::ty::traits::chalk::trait_datum_query)]
94 fn trait_datum(
95 &self,
96 krate: Crate,
97 trait_id: chalk_ir::TraitId,
98 ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>;
99
100 #[salsa::invoke(crate::ty::traits::chalk::struct_datum_query)]
101 fn struct_datum(
102 &self,
103 krate: Crate,
104 struct_id: chalk_ir::StructId,
105 ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>;
106
107 #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)]
108 fn impl_datum(
109 &self,
110 krate: Crate,
111 impl_id: chalk_ir::ImplId,
112 ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>;
113
114 #[salsa::invoke(crate::ty::traits::chalk::associated_ty_value_query)]
115 fn associated_ty_value(
116 &self,
117 krate: Crate,
118 id: chalk_rust_ir::AssociatedTyValueId,
119 ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>;
120
121 #[salsa::invoke(crate::ty::traits::trait_solve_query)]
122 fn trait_solve(
123 &self,
124 krate: Crate,
125 goal: crate::ty::Canonical<crate::ty::InEnvironment<crate::ty::Obligation>>,
126 ) -> Option<crate::ty::traits::Solution>;
127}
128 20
129#[test] 21#[test]
130fn hir_database_is_object_safe() { 22fn hir_database_is_object_safe() {
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index dafacba70..a9040ea3d 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,88 +1,4 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2
3use std::any::Any;
4
5use hir_expand::HirFileId;
6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
7
8use crate::{db::AstDatabase, Name, Source};
9
10pub use hir_def::diagnostics::UnresolvedModule; 2pub use hir_def::diagnostics::UnresolvedModule;
11pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; 3pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
12 4pub use hir_ty::diagnostics::{MissingFields, MissingOkInTailExpr, NoSuchField};
13#[derive(Debug)]
14pub struct NoSuchField {
15 pub file: HirFileId,
16 pub field: AstPtr<ast::RecordField>,
17}
18
19impl Diagnostic for NoSuchField {
20 fn message(&self) -> String {
21 "no such field".to_string()
22 }
23
24 fn source(&self) -> Source<SyntaxNodePtr> {
25 Source { file_id: self.file, value: self.field.into() }
26 }
27
28 fn as_any(&self) -> &(dyn Any + Send + 'static) {
29 self
30 }
31}
32
33#[derive(Debug)]
34pub struct MissingFields {
35 pub file: HirFileId,
36 pub field_list: AstPtr<ast::RecordFieldList>,
37 pub missed_fields: Vec<Name>,
38}
39
40impl Diagnostic for MissingFields {
41 fn message(&self) -> String {
42 "fill structure fields".to_string()
43 }
44 fn source(&self) -> Source<SyntaxNodePtr> {
45 Source { file_id: self.file, value: self.field_list.into() }
46 }
47 fn as_any(&self) -> &(dyn Any + Send + 'static) {
48 self
49 }
50}
51
52impl AstDiagnostic for MissingFields {
53 type AST = ast::RecordFieldList;
54
55 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
56 let root = db.parse_or_expand(self.source().file_id).unwrap();
57 let node = self.source().value.to_node(&root);
58 ast::RecordFieldList::cast(node).unwrap()
59 }
60}
61
62#[derive(Debug)]
63pub struct MissingOkInTailExpr {
64 pub file: HirFileId,
65 pub expr: AstPtr<ast::Expr>,
66}
67
68impl Diagnostic for MissingOkInTailExpr {
69 fn message(&self) -> String {
70 "wrap return expression in Ok".to_string()
71 }
72 fn source(&self) -> Source<SyntaxNodePtr> {
73 Source { file_id: self.file, value: self.expr.into() }
74 }
75 fn as_any(&self) -> &(dyn Any + Send + 'static) {
76 self
77 }
78}
79
80impl AstDiagnostic for MissingOkInTailExpr {
81 type AST = ast::Expr;
82
83 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
84 let root = db.parse_or_expand(self.file).unwrap();
85 let node = self.source().value.to_node(&root);
86 ast::Expr::cast(node).unwrap()
87 }
88}
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
index 529ac8251..e96a18d12 100644
--- a/crates/ra_hir/src/from_id.rs
+++ b/crates/ra_hir/src/from_id.rs
@@ -4,14 +4,13 @@
4//! are splitting the hir. 4//! are splitting the hir.
5 5
6use hir_def::{ 6use hir_def::{
7 AdtId, AssocItemId, AttrDefId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, 7 AdtId, AssocItemId, AttrDefId, DefWithBodyId, EnumVariantId, GenericDefId, ModuleDefId,
8 GenericDefId, ModuleDefId, StaticId, StructFieldId, StructId, TypeAliasId, UnionId, VariantId, 8 StructFieldId, VariantId,
9}; 9};
10 10
11use crate::{ 11use crate::{
12 ty::{CallableDef, TypableDef}, 12 Adt, AssocItem, AttrDef, Crate, DefWithBody, EnumVariant, GenericDef, ModuleDef, StructField,
13 Adt, AssocItem, AttrDef, Const, Crate, DefWithBody, EnumVariant, Function, GenericDef, 13 VariantDef,
14 ModuleDef, Static, StructField, TypeAlias, VariantDef,
15}; 14};
16 15
17impl From<ra_db::CrateId> for Crate { 16impl From<ra_db::CrateId> for Crate {
@@ -138,72 +137,6 @@ impl From<GenericDef> for GenericDefId {
138 } 137 }
139} 138}
140 139
141impl From<GenericDefId> for GenericDef {
142 fn from(def: GenericDefId) -> Self {
143 match def {
144 GenericDefId::FunctionId(it) => GenericDef::Function(it.into()),
145 GenericDefId::AdtId(it) => GenericDef::Adt(it.into()),
146 GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
147 GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
148 GenericDefId::ImplId(it) => GenericDef::ImplBlock(it.into()),
149 GenericDefId::EnumVariantId(it) => GenericDef::EnumVariant(it.into()),
150 GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
151 }
152 }
153}
154
155impl From<AdtId> for TypableDef {
156 fn from(id: AdtId) -> Self {
157 Adt::from(id).into()
158 }
159}
160
161impl From<StructId> for TypableDef {
162 fn from(id: StructId) -> Self {
163 AdtId::StructId(id).into()
164 }
165}
166
167impl From<UnionId> for TypableDef {
168 fn from(id: UnionId) -> Self {
169 AdtId::UnionId(id).into()
170 }
171}
172
173impl From<EnumId> for TypableDef {
174 fn from(id: EnumId) -> Self {
175 AdtId::EnumId(id).into()
176 }
177}
178
179impl From<EnumVariantId> for TypableDef {
180 fn from(id: EnumVariantId) -> Self {
181 EnumVariant::from(id).into()
182 }
183}
184
185impl From<TypeAliasId> for TypableDef {
186 fn from(id: TypeAliasId) -> Self {
187 TypeAlias::from(id).into()
188 }
189}
190
191impl From<FunctionId> for TypableDef {
192 fn from(id: FunctionId) -> Self {
193 Function::from(id).into()
194 }
195}
196impl From<ConstId> for TypableDef {
197 fn from(id: ConstId) -> Self {
198 Const::from(id).into()
199 }
200}
201impl From<StaticId> for TypableDef {
202 fn from(id: StaticId) -> Self {
203 Static::from(id).into()
204 }
205}
206
207impl From<Adt> for GenericDefId { 140impl From<Adt> for GenericDefId {
208 fn from(id: Adt) -> Self { 141 fn from(id: Adt) -> Self {
209 match id { 142 match id {
@@ -214,14 +147,12 @@ impl From<Adt> for GenericDefId {
214 } 147 }
215} 148}
216 149
217impl From<CallableDef> for GenericDefId { 150impl From<VariantId> for VariantDef {
218 fn from(def: CallableDef) -> Self { 151 fn from(def: VariantId) -> Self {
219 match def { 152 match def {
220 CallableDef::Function(it) => it.id.into(), 153 VariantId::StructId(it) => VariantDef::Struct(it.into()),
221 CallableDef::Struct(it) => it.id.into(), 154 VariantId::EnumVariantId(it) => VariantDef::EnumVariant(it.into()),
222 CallableDef::EnumVariant(it) => { 155 VariantId::UnionId(it) => VariantDef::Union(it.into()),
223 EnumVariantId { parent: it.parent.id, local_id: it.id }.into()
224 }
225 } 156 }
226 } 157 }
227} 158}
@@ -231,6 +162,7 @@ impl From<VariantDef> for VariantId {
231 match def { 162 match def {
232 VariantDef::Struct(it) => VariantId::StructId(it.id), 163 VariantDef::Struct(it) => VariantId::StructId(it.id),
233 VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()), 164 VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()),
165 VariantDef::Union(it) => VariantId::UnionId(it.id),
234 } 166 }
235 } 167 }
236} 168}
@@ -241,6 +173,12 @@ impl From<StructField> for StructFieldId {
241 } 173 }
242} 174}
243 175
176impl From<StructFieldId> for StructField {
177 fn from(def: StructFieldId) -> Self {
178 StructField { parent: def.parent.into(), id: def.local_id }
179 }
180}
181
244impl From<AttrDef> for AttrDefId { 182impl From<AttrDef> for AttrDefId {
245 fn from(def: AttrDef) -> Self { 183 fn from(def: AttrDef) -> Self {
246 match def { 184 match def {
@@ -257,3 +195,13 @@ impl From<AttrDef> for AttrDefId {
257 } 195 }
258 } 196 }
259} 197}
198
199impl From<AssocItem> for GenericDefId {
200 fn from(item: AssocItem) -> Self {
201 match item {
202 AssocItem::Function(f) => f.id.into(),
203 AssocItem::Const(c) => c.id.into(),
204 AssocItem::TypeAlias(t) => t.id.into(),
205 }
206 }
207}
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 1e7c22774..9f7c22b21 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{AstItemDef, LocationCtx, ModuleId, StructId, StructOrUnionId, UnionId}; 3use hir_def::{AstItemDef, LocationCtx, ModuleId};
4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, NameOwner}, 6 ast::{self, AstNode, NameOwner},
@@ -19,19 +19,18 @@ pub trait FromSource: Sized {
19 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>; 19 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>;
20} 20}
21 21
22// FIXIME: these two impls are wrong, `ast::StructDef` might produce either a struct or a union
23impl FromSource for Struct { 22impl FromSource for Struct {
24 type Ast = ast::StructDef; 23 type Ast = ast::StructDef;
25 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 24 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
26 let id: StructOrUnionId = from_source(db, src)?; 25 let id = from_source(db, src)?;
27 Some(Struct { id: StructId(id) }) 26 Some(Struct { id })
28 } 27 }
29} 28}
30impl FromSource for Union { 29impl FromSource for Union {
31 type Ast = ast::StructDef; 30 type Ast = ast::UnionDef;
32 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 31 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
33 let id: StructOrUnionId = from_source(db, src)?; 32 let id = from_source(db, src)?;
34 Some(Union { id: UnionId(id) }) 33 Some(Union { id })
35 } 34 }
36} 35}
37impl FromSource for Enum { 36impl FromSource for Enum {
@@ -263,13 +262,12 @@ impl Module {
263 262
264 let original_file = src.file_id.original_file(db); 263 let original_file = src.file_id.original_file(db);
265 264
266 let (krate, module_id) = 265 let (krate, local_id) = db.relevant_crates(original_file).iter().find_map(|&crate_id| {
267 db.relevant_crates(original_file).iter().find_map(|&crate_id| { 266 let crate_def_map = db.crate_def_map(crate_id);
268 let crate_def_map = db.crate_def_map(crate_id); 267 let local_id = crate_def_map.modules_for_file(original_file).next()?;
269 let local_module_id = crate_def_map.modules_for_file(original_file).next()?; 268 Some((crate_id, local_id))
270 Some((crate_id, local_module_id)) 269 })?;
271 })?; 270 Some(Module { id: ModuleId { krate, local_id } })
272 Some(Module { id: ModuleId { krate, module_id } })
273 } 271 }
274} 272}
275 273
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 843ce6a88..3c12c61f0 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -32,28 +32,20 @@ pub mod db;
32pub mod source_binder; 32pub mod source_binder;
33 33
34mod ty; 34mod ty;
35mod expr;
36pub mod diagnostics; 35pub mod diagnostics;
37mod util;
38 36
39mod from_id; 37mod from_id;
40mod code_model; 38mod code_model;
41 39
42pub mod from_source; 40pub mod from_source;
43 41
44#[cfg(test)]
45mod test_db;
46#[cfg(test)]
47mod marks;
48
49pub use crate::{ 42pub use crate::{
50 code_model::{ 43 code_model::{
51 src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, 44 src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency,
52 DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, 45 DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam,
53 HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, 46 HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef,
54 Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, 47 Static, Struct, StructField, Trait, Type, TypeAlias, Union, VariantDef,
55 }, 48 },
56 expr::ExprScopes,
57 from_source::FromSource, 49 from_source::FromSource,
58 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 50 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
59 ty::{ 51 ty::{
@@ -64,6 +56,7 @@ pub use crate::{
64}; 56};
65 57
66pub use hir_def::{ 58pub use hir_def::{
59 body::scope::ExprScopes,
67 builtin_type::BuiltinType, 60 builtin_type::BuiltinType,
68 docs::Documentation, 61 docs::Documentation,
69 path::{Path, PathKind}, 62 path::{Path, PathKind},
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 31390bb7f..76c493f1a 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -8,13 +8,17 @@
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use hir_def::{ 10use hir_def::{
11 body::{
12 scope::{ExprScopes, ScopeId},
13 BodySourceMap,
14 },
11 expr::{ExprId, PatId}, 15 expr::{ExprId, PatId},
12 path::known, 16 path::known,
13 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 17 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
14 DefWithBodyId, 18 AssocItemId, DefWithBodyId,
15}; 19};
16use hir_expand::{ 20use hir_expand::{
17 name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source, 21 hygiene::Hygiene, name::AsName, AstId, HirFileId, MacroCallId, MacroFileKind, Source,
18}; 22};
19use ra_syntax::{ 23use ra_syntax::{
20 ast::{self, AstNode}, 24 ast::{self, AstNode},
@@ -25,10 +29,12 @@ use ra_syntax::{
25 29
26use crate::{ 30use crate::{
27 db::HirDatabase, 31 db::HirDatabase,
28 expr::{BodySourceMap, ExprScopes, ScopeId}, 32 ty::{
29 ty::method_resolution::{self, implements_trait}, 33 method_resolution::{self, implements_trait},
34 InEnvironment, TraitEnvironment, Ty,
35 },
30 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, 36 Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function,
31 GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, 37 GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias,
32}; 38};
33 39
34fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { 40fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> {
@@ -88,7 +94,7 @@ pub struct SourceAnalyzer {
88 body_owner: Option<DefWithBody>, 94 body_owner: Option<DefWithBody>,
89 body_source_map: Option<Arc<BodySourceMap>>, 95 body_source_map: Option<Arc<BodySourceMap>>,
90 infer: Option<Arc<crate::ty::InferenceResult>>, 96 infer: Option<Arc<crate::ty::InferenceResult>>,
91 scopes: Option<Arc<crate::expr::ExprScopes>>, 97 scopes: Option<Arc<ExprScopes>>,
92} 98}
93 99
94#[derive(Debug, Clone, PartialEq, Eq)] 100#[derive(Debug, Clone, PartialEq, Eq)]
@@ -165,7 +171,7 @@ impl SourceAnalyzer {
165 resolver, 171 resolver,
166 body_owner: Some(def), 172 body_owner: Some(def),
167 body_source_map: Some(source_map), 173 body_source_map: Some(source_map),
168 infer: Some(db.infer(def)), 174 infer: Some(db.infer(def.into())),
169 scopes: Some(scopes), 175 scopes: Some(scopes),
170 file_id: node.file_id, 176 file_id: node.file_id,
171 } 177 }
@@ -195,48 +201,52 @@ impl SourceAnalyzer {
195 self.body_source_map.as_ref()?.node_pat(src) 201 self.body_source_map.as_ref()?.node_pat(src)
196 } 202 }
197 203
198 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { 204 pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> {
199 let expr_id = self.expr_id(expr)?; 205 let expr_id = self.expr_id(expr)?;
200 Some(self.infer.as_ref()?[expr_id].clone()) 206 let ty = self.infer.as_ref()?[expr_id].clone();
207 let environment = TraitEnvironment::lower(db, &self.resolver);
208 Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } })
201 } 209 }
202 210
203 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { 211 pub fn type_of_pat(&self, db: &impl HirDatabase, pat: &ast::Pat) -> Option<Type> {
204 let pat_id = self.pat_id(pat)?; 212 let pat_id = self.pat_id(pat)?;
205 Some(self.infer.as_ref()?[pat_id].clone()) 213 let ty = self.infer.as_ref()?[pat_id].clone();
214 let environment = TraitEnvironment::lower(db, &self.resolver);
215 Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } })
206 } 216 }
207 217
208 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 218 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
209 let expr_id = self.expr_id(&call.clone().into())?; 219 let expr_id = self.expr_id(&call.clone().into())?;
210 self.infer.as_ref()?.method_resolution(expr_id) 220 self.infer.as_ref()?.method_resolution(expr_id).map(Function::from)
211 } 221 }
212 222
213 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { 223 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
214 let expr_id = self.expr_id(&field.clone().into())?; 224 let expr_id = self.expr_id(&field.clone().into())?;
215 self.infer.as_ref()?.field_resolution(expr_id) 225 self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into())
216 } 226 }
217 227
218 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> { 228 pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> {
219 let expr_id = self.expr_id(&field.expr()?)?; 229 let expr_id = self.expr_id(&field.expr()?)?;
220 self.infer.as_ref()?.record_field_resolution(expr_id) 230 self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into())
221 } 231 }
222 232
223 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { 233 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> {
224 let expr_id = self.expr_id(&record_lit.clone().into())?; 234 let expr_id = self.expr_id(&record_lit.clone().into())?;
225 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 235 self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into())
226 } 236 }
227 237
228 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { 238 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> {
229 let pat_id = self.pat_id(&record_pat.clone().into())?; 239 let pat_id = self.pat_id(&record_pat.clone().into())?;
230 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 240 self.infer.as_ref()?.variant_resolution_for_pat(pat_id).map(|it| it.into())
231 } 241 }
232 242
233 pub fn resolve_macro_call( 243 pub fn resolve_macro_call(
234 &self, 244 &self,
235 db: &impl HirDatabase, 245 db: &impl HirDatabase,
236 macro_call: &ast::MacroCall, 246 macro_call: Source<&ast::MacroCall>,
237 ) -> Option<MacroDef> { 247 ) -> Option<MacroDef> {
238 // This must be a normal source file rather than macro file. 248 let hygiene = Hygiene::new(db, macro_call.file_id);
239 let path = macro_call.path().and_then(Path::from_ast)?; 249 let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?;
240 self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) 250 self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into())
241 } 251 }
242 252
@@ -248,7 +258,7 @@ impl SourceAnalyzer {
248 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { 258 let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty {
249 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), 259 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
250 TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { 260 TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam {
251 parent: self.resolver.generic_def().unwrap().into(), 261 parent: self.resolver.generic_def().unwrap(),
252 idx, 262 idx,
253 }), 263 }),
254 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { 264 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
@@ -290,13 +300,13 @@ impl SourceAnalyzer {
290 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { 300 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
291 let expr_id = self.expr_id(&path_expr.into())?; 301 let expr_id = self.expr_id(&path_expr.into())?;
292 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { 302 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
293 return Some(PathResolution::AssocItem(assoc)); 303 return Some(PathResolution::AssocItem(assoc.into()));
294 } 304 }
295 } 305 }
296 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { 306 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
297 let pat_id = self.pat_id(&path_pat.into())?; 307 let pat_id = self.pat_id(&path_pat.into())?;
298 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { 308 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
299 return Some(PathResolution::AssocItem(assoc)); 309 return Some(PathResolution::AssocItem(assoc.into()));
300 } 310 }
301 } 311 }
302 // This must be a normal source file rather than macro file. 312 // This must be a normal source file rather than macro file.
@@ -323,7 +333,7 @@ impl SourceAnalyzer {
323 resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), 333 resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
324 resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), 334 resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
325 resolver::ScopeDef::GenericParam(idx) => { 335 resolver::ScopeDef::GenericParam(idx) => {
326 let parent = self.resolver.generic_def().unwrap().into(); 336 let parent = self.resolver.generic_def().unwrap();
327 ScopeDef::GenericParam(GenericParam { parent, idx }) 337 ScopeDef::GenericParam(GenericParam { parent, idx })
328 } 338 }
329 resolver::ScopeDef::Local(pat_id) => { 339 resolver::ScopeDef::Local(pat_id) => {
@@ -358,14 +368,14 @@ impl SourceAnalyzer {
358 pub fn iterate_method_candidates<T>( 368 pub fn iterate_method_candidates<T>(
359 &self, 369 &self,
360 db: &impl HirDatabase, 370 db: &impl HirDatabase,
361 ty: Ty, 371 ty: &Type,
362 name: Option<&Name>, 372 name: Option<&Name>,
363 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 373 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
364 ) -> Option<T> { 374 ) -> Option<T> {
365 // There should be no inference vars in types passed here 375 // There should be no inference vars in types passed here
366 // FIXME check that? 376 // FIXME check that?
367 // FIXME replace Unknown by bound vars here 377 // FIXME replace Unknown by bound vars here
368 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 378 let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 };
369 method_resolution::iterate_method_candidates( 379 method_resolution::iterate_method_candidates(
370 &canonical, 380 &canonical,
371 db, 381 db,
@@ -373,7 +383,7 @@ impl SourceAnalyzer {
373 name, 383 name,
374 method_resolution::LookupMode::MethodCall, 384 method_resolution::LookupMode::MethodCall,
375 |ty, it| match it { 385 |ty, it| match it {
376 AssocItem::Function(f) => callback(ty, f), 386 AssocItemId::FunctionId(f) => callback(ty, f.into()),
377 _ => None, 387 _ => None,
378 }, 388 },
379 ) 389 )
@@ -382,34 +392,37 @@ impl SourceAnalyzer {
382 pub fn iterate_path_candidates<T>( 392 pub fn iterate_path_candidates<T>(
383 &self, 393 &self,
384 db: &impl HirDatabase, 394 db: &impl HirDatabase,
385 ty: Ty, 395 ty: &Type,
386 name: Option<&Name>, 396 name: Option<&Name>,
387 callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 397 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
388 ) -> Option<T> { 398 ) -> Option<T> {
389 // There should be no inference vars in types passed here 399 // There should be no inference vars in types passed here
390 // FIXME check that? 400 // FIXME check that?
391 // FIXME replace Unknown by bound vars here 401 // FIXME replace Unknown by bound vars here
392 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 402 let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 };
393 method_resolution::iterate_method_candidates( 403 method_resolution::iterate_method_candidates(
394 &canonical, 404 &canonical,
395 db, 405 db,
396 &self.resolver, 406 &self.resolver,
397 name, 407 name,
398 method_resolution::LookupMode::Path, 408 method_resolution::LookupMode::Path,
399 callback, 409 |ty, it| callback(ty, it.into()),
400 ) 410 )
401 } 411 }
402 412
403 pub fn autoderef<'a>( 413 // pub fn autoderef<'a>(
404 &'a self, 414 // &'a self,
405 db: &'a impl HirDatabase, 415 // db: &'a impl HirDatabase,
406 ty: Ty, 416 // ty: Ty,
407 ) -> impl Iterator<Item = Ty> + 'a { 417 // ) -> impl Iterator<Item = Ty> + 'a {
408 // There should be no inference vars in types passed here 418 // // There should be no inference vars in types passed here
409 // FIXME check that? 419 // // FIXME check that?
410 let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; 420 // let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
411 crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) 421 // let krate = self.resolver.krate();
412 } 422 // let environment = TraitEnvironment::lower(db, &self.resolver);
423 // let ty = crate::ty::InEnvironment { value: canonical, environment };
424 // crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value)
425 // }
413 426
414 /// Checks that particular type `ty` implements `std::future::Future`. 427 /// Checks that particular type `ty` implements `std::future::Future`.
415 /// This function is used in `.await` syntax completion. 428 /// This function is used in `.await` syntax completion.
@@ -435,32 +448,16 @@ impl SourceAnalyzer {
435 db: &impl HirDatabase, 448 db: &impl HirDatabase,
436 macro_call: Source<&ast::MacroCall>, 449 macro_call: Source<&ast::MacroCall>,
437 ) -> Option<Expansion> { 450 ) -> Option<Expansion> {
438 let def = self.resolve_macro_call(db, macro_call.value)?.id; 451 let def = self.resolve_macro_call(db, macro_call)?.id;
439 let ast_id = AstId::new( 452 let ast_id = AstId::new(
440 macro_call.file_id, 453 macro_call.file_id,
441 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), 454 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
442 ); 455 );
443 let macro_call_loc = MacroCallLoc { def, ast_id };
444 Some(Expansion { 456 Some(Expansion {
445 macro_call_id: db.intern_macro(macro_call_loc), 457 macro_call_id: def.as_call_id(db, ast_id),
446 macro_file_kind: to_macro_file_kind(macro_call.value), 458 macro_file_kind: to_macro_file_kind(macro_call.value),
447 }) 459 })
448 } 460 }
449
450 #[cfg(test)]
451 pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> {
452 self.body_source_map.clone().unwrap()
453 }
454
455 #[cfg(test)]
456 pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> {
457 self.infer.clone().unwrap()
458 }
459
460 #[cfg(test)]
461 pub(crate) fn analyzed_declaration(&self) -> Option<DefWithBody> {
462 self.body_owner
463 }
464} 461}
465 462
466fn scope_for( 463fn scope_for(
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index f62316c1f..4ed69c00d 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -1,1094 +1,4 @@
1//! The type system. We currently use this to infer types for completion, hover 1//! The type system. We currently use this to infer types for completion, hover
2//! information and various assists. 2//! information and various assists.
3 3
4mod autoderef; 4pub use hir_ty::*;
5pub(crate) mod primitive;
6pub(crate) mod traits;
7pub(crate) mod method_resolution;
8mod op;
9mod lower;
10mod infer;
11pub(crate) mod display;
12
13#[cfg(test)]
14mod tests;
15
16use std::ops::Deref;
17use std::sync::Arc;
18use std::{fmt, iter, mem};
19
20use hir_def::{generics::GenericParams, AdtId};
21use ra_db::{impl_intern_key, salsa};
22
23use crate::{
24 db::HirDatabase, expr::ExprId, util::make_mut_slice, Adt, Crate, DefWithBody, FloatTy,
25 GenericDef, IntTy, Mutability, Name, Trait, TypeAlias, Uncertain,
26};
27use display::{HirDisplay, HirFormatter};
28
29pub(crate) use autoderef::autoderef;
30pub(crate) use infer::{infer_query, InferTy, InferenceResult};
31pub use lower::CallableDef;
32pub(crate) use lower::{
33 callable_item_sig, field_types_query, generic_defaults_query,
34 generic_predicates_for_param_query, generic_predicates_query, type_for_def, Namespace,
35 TypableDef,
36};
37pub(crate) use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
38
39/// A type constructor or type name: this might be something like the primitive
40/// type `bool`, a struct like `Vec`, or things like function pointers or
41/// tuples.
42#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
43pub enum TypeCtor {
44 /// The primitive boolean type. Written as `bool`.
45 Bool,
46
47 /// The primitive character type; holds a Unicode scalar value
48 /// (a non-surrogate code point). Written as `char`.
49 Char,
50
51 /// A primitive integer type. For example, `i32`.
52 Int(Uncertain<IntTy>),
53
54 /// A primitive floating-point type. For example, `f64`.
55 Float(Uncertain<FloatTy>),
56
57 /// Structures, enumerations and unions.
58 Adt(Adt),
59
60 /// The pointee of a string slice. Written as `str`.
61 Str,
62
63 /// The pointee of an array slice. Written as `[T]`.
64 Slice,
65
66 /// An array with the given length. Written as `[T; n]`.
67 Array,
68
69 /// A raw pointer. Written as `*mut T` or `*const T`
70 RawPtr(Mutability),
71
72 /// A reference; a pointer with an associated lifetime. Written as
73 /// `&'a mut T` or `&'a T`.
74 Ref(Mutability),
75
76 /// The anonymous type of a function declaration/definition. Each
77 /// function has a unique type, which is output (for a function
78 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
79 ///
80 /// This includes tuple struct / enum variant constructors as well.
81 ///
82 /// For example the type of `bar` here:
83 ///
84 /// ```
85 /// fn foo() -> i32 { 1 }
86 /// let bar = foo; // bar: fn() -> i32 {foo}
87 /// ```
88 FnDef(CallableDef),
89
90 /// A pointer to a function. Written as `fn() -> i32`.
91 ///
92 /// For example the type of `bar` here:
93 ///
94 /// ```
95 /// fn foo() -> i32 { 1 }
96 /// let bar: fn() -> i32 = foo;
97 /// ```
98 FnPtr { num_args: u16 },
99
100 /// The never type `!`.
101 Never,
102
103 /// A tuple type. For example, `(i32, bool)`.
104 Tuple { cardinality: u16 },
105
106 /// Represents an associated item like `Iterator::Item`. This is used
107 /// when we have tried to normalize a projection like `T::Item` but
108 /// couldn't find a better representation. In that case, we generate
109 /// an **application type** like `(Iterator::Item)<T>`.
110 AssociatedType(TypeAlias),
111
112 /// The type of a specific closure.
113 ///
114 /// The closure signature is stored in a `FnPtr` type in the first type
115 /// parameter.
116 Closure { def: DefWithBody, expr: ExprId },
117}
118
119/// This exists just for Chalk, because Chalk just has a single `StructId` where
120/// we have different kinds of ADTs, primitive types and special type
121/// constructors like tuples and function pointers.
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
123pub struct TypeCtorId(salsa::InternId);
124impl_intern_key!(TypeCtorId);
125
126impl TypeCtor {
127 pub fn num_ty_params(self, db: &impl HirDatabase) -> usize {
128 match self {
129 TypeCtor::Bool
130 | TypeCtor::Char
131 | TypeCtor::Int(_)
132 | TypeCtor::Float(_)
133 | TypeCtor::Str
134 | TypeCtor::Never => 0,
135 TypeCtor::Slice
136 | TypeCtor::Array
137 | TypeCtor::RawPtr(_)
138 | TypeCtor::Ref(_)
139 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure
140 => 1,
141 TypeCtor::Adt(adt) => {
142 let generic_params = db.generic_params(AdtId::from(adt).into());
143 generic_params.count_params_including_parent()
144 }
145 TypeCtor::FnDef(callable) => {
146 let generic_params = db.generic_params(callable.into());
147 generic_params.count_params_including_parent()
148 }
149 TypeCtor::AssociatedType(type_alias) => {
150 let generic_params = db.generic_params(type_alias.id.into());
151 generic_params.count_params_including_parent()
152 }
153 TypeCtor::FnPtr { num_args } => num_args as usize + 1,
154 TypeCtor::Tuple { cardinality } => cardinality as usize,
155 }
156 }
157
158 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
159 match self {
160 TypeCtor::Bool
161 | TypeCtor::Char
162 | TypeCtor::Int(_)
163 | TypeCtor::Float(_)
164 | TypeCtor::Str
165 | TypeCtor::Never
166 | TypeCtor::Slice
167 | TypeCtor::Array
168 | TypeCtor::RawPtr(_)
169 | TypeCtor::Ref(_)
170 | TypeCtor::FnPtr { .. }
171 | TypeCtor::Tuple { .. } => None,
172 TypeCtor::Closure { def, .. } => def.krate(db),
173 TypeCtor::Adt(adt) => adt.krate(db),
174 TypeCtor::FnDef(callable) => callable.krate(db),
175 TypeCtor::AssociatedType(type_alias) => type_alias.krate(db),
176 }
177 }
178
179 pub fn as_generic_def(self) -> Option<crate::GenericDef> {
180 match self {
181 TypeCtor::Bool
182 | TypeCtor::Char
183 | TypeCtor::Int(_)
184 | TypeCtor::Float(_)
185 | TypeCtor::Str
186 | TypeCtor::Never
187 | TypeCtor::Slice
188 | TypeCtor::Array
189 | TypeCtor::RawPtr(_)
190 | TypeCtor::Ref(_)
191 | TypeCtor::FnPtr { .. }
192 | TypeCtor::Tuple { .. }
193 | TypeCtor::Closure { .. } => None,
194 TypeCtor::Adt(adt) => Some(adt.into()),
195 TypeCtor::FnDef(callable) => Some(callable.into()),
196 TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()),
197 }
198 }
199}
200
201/// A nominal type with (maybe 0) type parameters. This might be a primitive
202/// type like `bool`, a struct, tuple, function pointer, reference or
203/// several other things.
204#[derive(Clone, PartialEq, Eq, Debug, Hash)]
205pub struct ApplicationTy {
206 pub ctor: TypeCtor,
207 pub parameters: Substs,
208}
209
210/// A "projection" type corresponds to an (unnormalized)
211/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
212/// trait and all its parameters are fully known.
213#[derive(Clone, PartialEq, Eq, Debug, Hash)]
214pub struct ProjectionTy {
215 pub associated_ty: TypeAlias,
216 pub parameters: Substs,
217}
218
219impl ProjectionTy {
220 pub fn trait_ref(&self, db: &impl HirDatabase) -> TraitRef {
221 TraitRef {
222 trait_: self
223 .associated_ty
224 .parent_trait(db)
225 .expect("projection ty without parent trait"),
226 substs: self.parameters.clone(),
227 }
228 }
229}
230
231impl TypeWalk for ProjectionTy {
232 fn walk(&self, f: &mut impl FnMut(&Ty)) {
233 self.parameters.walk(f);
234 }
235
236 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
237 self.parameters.walk_mut_binders(f, binders);
238 }
239}
240
241/// A type.
242///
243/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
244/// the same thing (but in a different way).
245///
246/// This should be cheap to clone.
247#[derive(Clone, PartialEq, Eq, Debug, Hash)]
248pub enum Ty {
249 /// A nominal type with (maybe 0) type parameters. This might be a primitive
250 /// type like `bool`, a struct, tuple, function pointer, reference or
251 /// several other things.
252 Apply(ApplicationTy),
253
254 /// A "projection" type corresponds to an (unnormalized)
255 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
256 /// trait and all its parameters are fully known.
257 Projection(ProjectionTy),
258
259 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
260 Param {
261 /// The index of the parameter (starting with parameters from the
262 /// surrounding impl, then the current function).
263 idx: u32,
264 /// The name of the parameter, for displaying.
265 // FIXME get rid of this
266 name: Name,
267 },
268
269 /// A bound type variable. Used during trait resolution to represent Chalk
270 /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
271 Bound(u32),
272
273 /// A type variable used during type checking. Not to be confused with a
274 /// type parameter.
275 Infer(InferTy),
276
277 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
278 ///
279 /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
280 /// represents the `Self` type inside the bounds. This is currently
281 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
282 /// didn't seem worth the overhead yet.
283 Dyn(Arc<[GenericPredicate]>),
284
285 /// An opaque type (`impl Trait`).
286 ///
287 /// The predicates are quantified over the `Self` type; see `Ty::Dyn` for
288 /// more.
289 Opaque(Arc<[GenericPredicate]>),
290
291 /// A placeholder for a type which could not be computed; this is propagated
292 /// to avoid useless error messages. Doubles as a placeholder where type
293 /// variables are inserted before type checking, since we want to try to
294 /// infer a better type here anyway -- for the IDE use case, we want to try
295 /// to infer as much as possible even in the presence of type errors.
296 Unknown,
297}
298
299/// A list of substitutions for generic parameters.
300#[derive(Clone, PartialEq, Eq, Debug, Hash)]
301pub struct Substs(Arc<[Ty]>);
302
303impl TypeWalk for Substs {
304 fn walk(&self, f: &mut impl FnMut(&Ty)) {
305 for t in self.0.iter() {
306 t.walk(f);
307 }
308 }
309
310 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
311 for t in make_mut_slice(&mut self.0) {
312 t.walk_mut_binders(f, binders);
313 }
314 }
315}
316
317impl Substs {
318 pub fn empty() -> Substs {
319 Substs(Arc::new([]))
320 }
321
322 pub fn single(ty: Ty) -> Substs {
323 Substs(Arc::new([ty]))
324 }
325
326 pub fn prefix(&self, n: usize) -> Substs {
327 Substs(self.0[..std::cmp::min(self.0.len(), n)].into())
328 }
329
330 pub fn as_single(&self) -> &Ty {
331 if self.0.len() != 1 {
332 panic!("expected substs of len 1, got {:?}", self);
333 }
334 &self.0[0]
335 }
336
337 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
338 pub fn identity(generic_params: &GenericParams) -> Substs {
339 Substs(
340 generic_params
341 .params_including_parent()
342 .into_iter()
343 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
344 .collect(),
345 )
346 }
347
348 /// Return Substs that replace each parameter by a bound variable.
349 pub fn bound_vars(generic_params: &GenericParams) -> Substs {
350 Substs(
351 generic_params
352 .params_including_parent()
353 .into_iter()
354 .map(|p| Ty::Bound(p.idx))
355 .collect(),
356 )
357 }
358
359 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDef>) -> SubstsBuilder {
360 let def = def.into();
361 let params = db.generic_params(def.into());
362 let param_count = params.count_params_including_parent();
363 Substs::builder(param_count)
364 }
365
366 pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder {
367 Substs::builder(generic_params.count_params_including_parent())
368 }
369
370 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
371 Substs::builder(type_ctor.num_ty_params(db))
372 }
373
374 fn builder(param_count: usize) -> SubstsBuilder {
375 SubstsBuilder { vec: Vec::with_capacity(param_count), param_count }
376 }
377}
378
379#[derive(Debug, Clone)]
380pub struct SubstsBuilder {
381 vec: Vec<Ty>,
382 param_count: usize,
383}
384
385impl SubstsBuilder {
386 pub fn build(self) -> Substs {
387 assert_eq!(self.vec.len(), self.param_count);
388 Substs(self.vec.into())
389 }
390
391 pub fn push(mut self, ty: Ty) -> Self {
392 self.vec.push(ty);
393 self
394 }
395
396 fn remaining(&self) -> usize {
397 self.param_count - self.vec.len()
398 }
399
400 pub fn fill_with_bound_vars(self, starting_from: u32) -> Self {
401 self.fill((starting_from..).map(Ty::Bound))
402 }
403
404 pub fn fill_with_params(self) -> Self {
405 let start = self.vec.len() as u32;
406 self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
407 }
408
409 pub fn fill_with_unknown(self) -> Self {
410 self.fill(iter::repeat(Ty::Unknown))
411 }
412
413 pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
414 self.vec.extend(filler.take(self.remaining()));
415 assert_eq!(self.remaining(), 0);
416 self
417 }
418
419 pub fn use_parent_substs(mut self, parent_substs: &Substs) -> Self {
420 assert!(self.vec.is_empty());
421 assert!(parent_substs.len() <= self.param_count);
422 self.vec.extend(parent_substs.iter().cloned());
423 self
424 }
425}
426
427impl Deref for Substs {
428 type Target = [Ty];
429
430 fn deref(&self) -> &[Ty] {
431 &self.0
432 }
433}
434
435/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
436/// Name to be bikeshedded: TraitBound? TraitImplements?
437#[derive(Clone, PartialEq, Eq, Debug, Hash)]
438pub struct TraitRef {
439 /// FIXME name?
440 pub trait_: Trait,
441 pub substs: Substs,
442}
443
444impl TraitRef {
445 pub fn self_ty(&self) -> &Ty {
446 &self.substs[0]
447 }
448}
449
450impl TypeWalk for TraitRef {
451 fn walk(&self, f: &mut impl FnMut(&Ty)) {
452 self.substs.walk(f);
453 }
454
455 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
456 self.substs.walk_mut_binders(f, binders);
457 }
458}
459
460/// Like `generics::WherePredicate`, but with resolved types: A condition on the
461/// parameters of a generic item.
462#[derive(Debug, Clone, PartialEq, Eq, Hash)]
463pub enum GenericPredicate {
464 /// The given trait needs to be implemented for its type parameters.
465 Implemented(TraitRef),
466 /// An associated type bindings like in `Iterator<Item = T>`.
467 Projection(ProjectionPredicate),
468 /// We couldn't resolve the trait reference. (If some type parameters can't
469 /// be resolved, they will just be Unknown).
470 Error,
471}
472
473impl GenericPredicate {
474 pub fn is_error(&self) -> bool {
475 match self {
476 GenericPredicate::Error => true,
477 _ => false,
478 }
479 }
480
481 pub fn is_implemented(&self) -> bool {
482 match self {
483 GenericPredicate::Implemented(_) => true,
484 _ => false,
485 }
486 }
487
488 pub fn trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
489 match self {
490 GenericPredicate::Implemented(tr) => Some(tr.clone()),
491 GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)),
492 GenericPredicate::Error => None,
493 }
494 }
495}
496
497impl TypeWalk for GenericPredicate {
498 fn walk(&self, f: &mut impl FnMut(&Ty)) {
499 match self {
500 GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
501 GenericPredicate::Projection(projection_pred) => projection_pred.walk(f),
502 GenericPredicate::Error => {}
503 }
504 }
505
506 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
507 match self {
508 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
509 GenericPredicate::Projection(projection_pred) => {
510 projection_pred.walk_mut_binders(f, binders)
511 }
512 GenericPredicate::Error => {}
513 }
514 }
515}
516
517/// Basically a claim (currently not validated / checked) that the contained
518/// type / trait ref contains no inference variables; any inference variables it
519/// contained have been replaced by bound variables, and `num_vars` tells us how
520/// many there are. This is used to erase irrelevant differences between types
521/// before using them in queries.
522#[derive(Debug, Clone, PartialEq, Eq, Hash)]
523pub struct Canonical<T> {
524 pub value: T,
525 pub num_vars: usize,
526}
527
528/// A function signature as seen by type inference: Several parameter types and
529/// one return type.
530#[derive(Clone, PartialEq, Eq, Debug)]
531pub struct FnSig {
532 params_and_return: Arc<[Ty]>,
533}
534
535impl FnSig {
536 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig {
537 params.push(ret);
538 FnSig { params_and_return: params.into() }
539 }
540
541 pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig {
542 FnSig { params_and_return: Arc::clone(&substs.0) }
543 }
544
545 pub fn params(&self) -> &[Ty] {
546 &self.params_and_return[0..self.params_and_return.len() - 1]
547 }
548
549 pub fn ret(&self) -> &Ty {
550 &self.params_and_return[self.params_and_return.len() - 1]
551 }
552}
553
554impl TypeWalk for FnSig {
555 fn walk(&self, f: &mut impl FnMut(&Ty)) {
556 for t in self.params_and_return.iter() {
557 t.walk(f);
558 }
559 }
560
561 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
562 for t in make_mut_slice(&mut self.params_and_return) {
563 t.walk_mut_binders(f, binders);
564 }
565 }
566}
567
568impl Ty {
569 pub fn simple(ctor: TypeCtor) -> Ty {
570 Ty::Apply(ApplicationTy { ctor, parameters: Substs::empty() })
571 }
572 pub fn apply_one(ctor: TypeCtor, param: Ty) -> Ty {
573 Ty::Apply(ApplicationTy { ctor, parameters: Substs::single(param) })
574 }
575 pub fn apply(ctor: TypeCtor, parameters: Substs) -> Ty {
576 Ty::Apply(ApplicationTy { ctor, parameters })
577 }
578 pub fn unit() -> Self {
579 Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty())
580 }
581
582 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
583 match self {
584 Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => {
585 Some((parameters.as_single(), *mutability))
586 }
587 _ => None,
588 }
589 }
590
591 pub fn as_adt(&self) -> Option<(Adt, &Substs)> {
592 match self {
593 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => {
594 Some((*adt_def, parameters))
595 }
596 _ => None,
597 }
598 }
599
600 pub fn as_tuple(&self) -> Option<&Substs> {
601 match self {
602 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => {
603 Some(parameters)
604 }
605 _ => None,
606 }
607 }
608
609 pub fn as_callable(&self) -> Option<(CallableDef, &Substs)> {
610 match self {
611 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => {
612 Some((*callable_def, parameters))
613 }
614 _ => None,
615 }
616 }
617
618 fn builtin_deref(&self) -> Option<Ty> {
619 match self {
620 Ty::Apply(a_ty) => match a_ty.ctor {
621 TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())),
622 TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())),
623 _ => None,
624 },
625 _ => None,
626 }
627 }
628
629 fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
630 match self {
631 Ty::Apply(a_ty) => match a_ty.ctor {
632 TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)),
633 TypeCtor::FnDef(def) => {
634 let sig = db.callable_item_signature(def);
635 Some(sig.subst(&a_ty.parameters))
636 }
637 TypeCtor::Closure { .. } => {
638 let sig_param = &a_ty.parameters[0];
639 sig_param.callable_sig(db)
640 }
641 _ => None,
642 },
643 _ => None,
644 }
645 }
646
647 /// If this is a type with type parameters (an ADT or function), replaces
648 /// the `Substs` for these type parameters with the given ones. (So e.g. if
649 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
650 /// `Option<u32>` afterwards.)
651 pub fn apply_substs(self, substs: Substs) -> Ty {
652 match self {
653 Ty::Apply(ApplicationTy { ctor, parameters: previous_substs }) => {
654 assert_eq!(previous_substs.len(), substs.len());
655 Ty::Apply(ApplicationTy { ctor, parameters: substs })
656 }
657 _ => self,
658 }
659 }
660
661 /// Returns the type parameters of this type if it has some (i.e. is an ADT
662 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
663 pub fn substs(&self) -> Option<Substs> {
664 match self {
665 Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()),
666 _ => None,
667 }
668 }
669
670 /// If this is an `impl Trait` or `dyn Trait`, returns that trait.
671 pub fn inherent_trait(&self) -> Option<Trait> {
672 match self {
673 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
674 predicates.iter().find_map(|pred| match pred {
675 GenericPredicate::Implemented(tr) => Some(tr.trait_),
676 _ => None,
677 })
678 }
679 _ => None,
680 }
681 }
682}
683
684/// This allows walking structures that contain types to do something with those
685/// types, similar to Chalk's `Fold` trait.
686pub trait TypeWalk {
687 fn walk(&self, f: &mut impl FnMut(&Ty));
688 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
689 self.walk_mut_binders(&mut |ty, _binders| f(ty), 0);
690 }
691 /// Walk the type, counting entered binders.
692 ///
693 /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers
694 /// to the innermost binder, 1 to the next, etc.. So when we want to
695 /// substitute a certain bound variable, we can't just walk the whole type
696 /// and blindly replace each instance of a certain index; when we 'enter'
697 /// things that introduce new bound variables, we have to keep track of
698 /// that. Currently, the only thing that introduces bound variables on our
699 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
700 /// variable for the self type.
701 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize);
702
703 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
704 where
705 Self: Sized,
706 {
707 self.walk_mut(&mut |ty_mut| {
708 let ty = mem::replace(ty_mut, Ty::Unknown);
709 *ty_mut = f(ty);
710 });
711 self
712 }
713
714 /// Replaces type parameters in this type using the given `Substs`. (So e.g.
715 /// if `self` is `&[T]`, where type parameter T has index 0, and the
716 /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
717 fn subst(self, substs: &Substs) -> Self
718 where
719 Self: Sized,
720 {
721 self.fold(&mut |ty| match ty {
722 Ty::Param { idx, name } => {
723 substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name })
724 }
725 ty => ty,
726 })
727 }
728
729 /// Substitutes `Ty::Bound` vars (as opposed to type parameters).
730 fn subst_bound_vars(mut self, substs: &Substs) -> Self
731 where
732 Self: Sized,
733 {
734 self.walk_mut_binders(
735 &mut |ty, binders| match ty {
736 &mut Ty::Bound(idx) => {
737 if idx as usize >= binders && (idx as usize - binders) < substs.len() {
738 *ty = substs.0[idx as usize - binders].clone();
739 }
740 }
741 _ => {}
742 },
743 0,
744 );
745 self
746 }
747
748 /// Shifts up `Ty::Bound` vars by `n`.
749 fn shift_bound_vars(self, n: i32) -> Self
750 where
751 Self: Sized,
752 {
753 self.fold(&mut |ty| match ty {
754 Ty::Bound(idx) => {
755 assert!(idx as i32 >= -n);
756 Ty::Bound((idx as i32 + n) as u32)
757 }
758 ty => ty,
759 })
760 }
761}
762
763impl TypeWalk for Ty {
764 fn walk(&self, f: &mut impl FnMut(&Ty)) {
765 match self {
766 Ty::Apply(a_ty) => {
767 for t in a_ty.parameters.iter() {
768 t.walk(f);
769 }
770 }
771 Ty::Projection(p_ty) => {
772 for t in p_ty.parameters.iter() {
773 t.walk(f);
774 }
775 }
776 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
777 for p in predicates.iter() {
778 p.walk(f);
779 }
780 }
781 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
782 }
783 f(self);
784 }
785
786 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
787 match self {
788 Ty::Apply(a_ty) => {
789 a_ty.parameters.walk_mut_binders(f, binders);
790 }
791 Ty::Projection(p_ty) => {
792 p_ty.parameters.walk_mut_binders(f, binders);
793 }
794 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
795 for p in make_mut_slice(predicates) {
796 p.walk_mut_binders(f, binders + 1);
797 }
798 }
799 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
800 }
801 f(self, binders);
802 }
803}
804
805impl HirDisplay for &Ty {
806 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
807 HirDisplay::hir_fmt(*self, f)
808 }
809}
810
811impl HirDisplay for ApplicationTy {
812 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
813 if f.should_truncate() {
814 return write!(f, "…");
815 }
816
817 match self.ctor {
818 TypeCtor::Bool => write!(f, "bool")?,
819 TypeCtor::Char => write!(f, "char")?,
820 TypeCtor::Int(t) => write!(f, "{}", t)?,
821 TypeCtor::Float(t) => write!(f, "{}", t)?,
822 TypeCtor::Str => write!(f, "str")?,
823 TypeCtor::Slice => {
824 let t = self.parameters.as_single();
825 write!(f, "[{}]", t.display(f.db))?;
826 }
827 TypeCtor::Array => {
828 let t = self.parameters.as_single();
829 write!(f, "[{};_]", t.display(f.db))?;
830 }
831 TypeCtor::RawPtr(m) => {
832 let t = self.parameters.as_single();
833 write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?;
834 }
835 TypeCtor::Ref(m) => {
836 let t = self.parameters.as_single();
837 write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?;
838 }
839 TypeCtor::Never => write!(f, "!")?,
840 TypeCtor::Tuple { .. } => {
841 let ts = &self.parameters;
842 if ts.len() == 1 {
843 write!(f, "({},)", ts[0].display(f.db))?;
844 } else {
845 write!(f, "(")?;
846 f.write_joined(&*ts.0, ", ")?;
847 write!(f, ")")?;
848 }
849 }
850 TypeCtor::FnPtr { .. } => {
851 let sig = FnSig::from_fn_ptr_substs(&self.parameters);
852 write!(f, "fn(")?;
853 f.write_joined(sig.params(), ", ")?;
854 write!(f, ") -> {}", sig.ret().display(f.db))?;
855 }
856 TypeCtor::FnDef(def) => {
857 let sig = f.db.callable_item_signature(def);
858 let name = match def {
859 CallableDef::Function(ff) => ff.name(f.db),
860 CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing),
861 CallableDef::EnumVariant(e) => e.name(f.db).unwrap_or_else(Name::missing),
862 };
863 match def {
864 CallableDef::Function(_) => write!(f, "fn {}", name)?,
865 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?,
866 }
867 if self.parameters.len() > 0 {
868 write!(f, "<")?;
869 f.write_joined(&*self.parameters.0, ", ")?;
870 write!(f, ">")?;
871 }
872 write!(f, "(")?;
873 f.write_joined(sig.params(), ", ")?;
874 write!(f, ") -> {}", sig.ret().display(f.db))?;
875 }
876 TypeCtor::Adt(def_id) => {
877 let name = match def_id {
878 Adt::Struct(s) => s.name(f.db),
879 Adt::Union(u) => u.name(f.db),
880 Adt::Enum(e) => e.name(f.db),
881 }
882 .unwrap_or_else(Name::missing);
883 write!(f, "{}", name)?;
884 if self.parameters.len() > 0 {
885 write!(f, "<")?;
886 f.write_joined(&*self.parameters.0, ", ")?;
887 write!(f, ">")?;
888 }
889 }
890 TypeCtor::AssociatedType(type_alias) => {
891 let trait_name = type_alias
892 .parent_trait(f.db)
893 .and_then(|t| t.name(f.db))
894 .unwrap_or_else(Name::missing);
895 let name = type_alias.name(f.db);
896 write!(f, "{}::{}", trait_name, name)?;
897 if self.parameters.len() > 0 {
898 write!(f, "<")?;
899 f.write_joined(&*self.parameters.0, ", ")?;
900 write!(f, ">")?;
901 }
902 }
903 TypeCtor::Closure { .. } => {
904 let sig = self.parameters[0]
905 .callable_sig(f.db)
906 .expect("first closure parameter should contain signature");
907 write!(f, "|")?;
908 f.write_joined(sig.params(), ", ")?;
909 write!(f, "| -> {}", sig.ret().display(f.db))?;
910 }
911 }
912 Ok(())
913 }
914}
915
916impl HirDisplay for ProjectionTy {
917 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
918 if f.should_truncate() {
919 return write!(f, "…");
920 }
921
922 let trait_name = self
923 .associated_ty
924 .parent_trait(f.db)
925 .and_then(|t| t.name(f.db))
926 .unwrap_or_else(Name::missing);
927 write!(f, "<{} as {}", self.parameters[0].display(f.db), trait_name,)?;
928 if self.parameters.len() > 1 {
929 write!(f, "<")?;
930 f.write_joined(&self.parameters[1..], ", ")?;
931 write!(f, ">")?;
932 }
933 write!(f, ">::{}", self.associated_ty.name(f.db))?;
934 Ok(())
935 }
936}
937
938impl HirDisplay for Ty {
939 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
940 if f.should_truncate() {
941 return write!(f, "…");
942 }
943
944 match self {
945 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
946 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
947 Ty::Param { name, .. } => write!(f, "{}", name)?,
948 Ty::Bound(idx) => write!(f, "?{}", idx)?,
949 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
950 match self {
951 Ty::Dyn(_) => write!(f, "dyn ")?,
952 Ty::Opaque(_) => write!(f, "impl ")?,
953 _ => unreachable!(),
954 };
955 // Note: This code is written to produce nice results (i.e.
956 // corresponding to surface Rust) for types that can occur in
957 // actual Rust. It will have weird results if the predicates
958 // aren't as expected (i.e. self types = $0, projection
959 // predicates for a certain trait come after the Implemented
960 // predicate for that trait).
961 let mut first = true;
962 let mut angle_open = false;
963 for p in predicates.iter() {
964 match p {
965 GenericPredicate::Implemented(trait_ref) => {
966 if angle_open {
967 write!(f, ">")?;
968 }
969 if !first {
970 write!(f, " + ")?;
971 }
972 // We assume that the self type is $0 (i.e. the
973 // existential) here, which is the only thing that's
974 // possible in actual Rust, and hence don't print it
975 write!(
976 f,
977 "{}",
978 trait_ref.trait_.name(f.db).unwrap_or_else(Name::missing)
979 )?;
980 if trait_ref.substs.len() > 1 {
981 write!(f, "<")?;
982 f.write_joined(&trait_ref.substs[1..], ", ")?;
983 // there might be assoc type bindings, so we leave the angle brackets open
984 angle_open = true;
985 }
986 }
987 GenericPredicate::Projection(projection_pred) => {
988 // in types in actual Rust, these will always come
989 // after the corresponding Implemented predicate
990 if angle_open {
991 write!(f, ", ")?;
992 } else {
993 write!(f, "<")?;
994 angle_open = true;
995 }
996 let name = projection_pred.projection_ty.associated_ty.name(f.db);
997 write!(f, "{} = ", name)?;
998 projection_pred.ty.hir_fmt(f)?;
999 }
1000 GenericPredicate::Error => {
1001 if angle_open {
1002 // impl Trait<X, {error}>
1003 write!(f, ", ")?;
1004 } else if !first {
1005 // impl Trait + {error}
1006 write!(f, " + ")?;
1007 }
1008 p.hir_fmt(f)?;
1009 }
1010 }
1011 first = false;
1012 }
1013 if angle_open {
1014 write!(f, ">")?;
1015 }
1016 }
1017 Ty::Unknown => write!(f, "{{unknown}}")?,
1018 Ty::Infer(..) => write!(f, "_")?,
1019 }
1020 Ok(())
1021 }
1022}
1023
1024impl TraitRef {
1025 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
1026 if f.should_truncate() {
1027 return write!(f, "…");
1028 }
1029
1030 self.substs[0].hir_fmt(f)?;
1031 if use_as {
1032 write!(f, " as ")?;
1033 } else {
1034 write!(f, ": ")?;
1035 }
1036 write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?;
1037 if self.substs.len() > 1 {
1038 write!(f, "<")?;
1039 f.write_joined(&self.substs[1..], ", ")?;
1040 write!(f, ">")?;
1041 }
1042 Ok(())
1043 }
1044}
1045
1046impl HirDisplay for TraitRef {
1047 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1048 self.hir_fmt_ext(f, false)
1049 }
1050}
1051
1052impl HirDisplay for &GenericPredicate {
1053 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1054 HirDisplay::hir_fmt(*self, f)
1055 }
1056}
1057
1058impl HirDisplay for GenericPredicate {
1059 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1060 if f.should_truncate() {
1061 return write!(f, "…");
1062 }
1063
1064 match self {
1065 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
1066 GenericPredicate::Projection(projection_pred) => {
1067 write!(f, "<")?;
1068 projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
1069 write!(
1070 f,
1071 ">::{} = {}",
1072 projection_pred.projection_ty.associated_ty.name(f.db),
1073 projection_pred.ty.display(f.db)
1074 )?;
1075 }
1076 GenericPredicate::Error => write!(f, "{{error}}")?,
1077 }
1078 Ok(())
1079 }
1080}
1081
1082impl HirDisplay for Obligation {
1083 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1084 match self {
1085 Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)),
1086 Obligation::Projection(proj) => write!(
1087 f,
1088 "Normalize({} => {})",
1089 proj.projection_ty.display(f.db),
1090 proj.ty.display(f.db)
1091 ),
1092 }
1093 }
1094}
diff --git a/crates/ra_hir/src/util.rs b/crates/ra_hir/src/util.rs
deleted file mode 100644
index 0095ee45d..000000000
--- a/crates/ra_hir/src/util.rs
+++ /dev/null
@@ -1,12 +0,0 @@
1//! Internal utility functions.
2
3use std::sync::Arc;
4
5/// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices).
6/// The underlying values are cloned if there are other strong references.
7pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
8 if Arc::get_mut(a).is_none() {
9 *a = a.iter().cloned().collect();
10 }
11 Arc::get_mut(a).unwrap()
12}
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index c9f30923e..3666529b0 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -12,25 +12,25 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
12 12
13use crate::{ 13use crate::{
14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource, 14 db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource,
15 LocalEnumVariantId, LocalStructFieldId, StructOrUnionId, VariantId, 15 LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId,
16}; 16};
17 17
18/// Note that we use `StructData` for unions as well! 18/// Note that we use `StructData` for unions as well!
19#[derive(Debug, Clone, PartialEq, Eq)] 19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct StructData { 20pub struct StructData {
21 pub name: Option<Name>, 21 pub name: Name,
22 pub variant_data: Arc<VariantData>, 22 pub variant_data: Arc<VariantData>,
23} 23}
24 24
25#[derive(Debug, Clone, PartialEq, Eq)] 25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct EnumData { 26pub struct EnumData {
27 pub name: Option<Name>, 27 pub name: Name,
28 pub variants: Arena<LocalEnumVariantId, EnumVariantData>, 28 pub variants: Arena<LocalEnumVariantId, EnumVariantData>,
29} 29}
30 30
31#[derive(Debug, Clone, PartialEq, Eq)] 31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct EnumVariantData { 32pub struct EnumVariantData {
33 pub name: Option<Name>, 33 pub name: Name,
34 pub variant_data: Arc<VariantData>, 34 pub variant_data: Arc<VariantData>,
35} 35}
36 36
@@ -49,26 +49,38 @@ pub struct StructFieldData {
49} 49}
50 50
51impl StructData { 51impl StructData {
52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructOrUnionId) -> Arc<StructData> { 52 pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc<StructData> {
53 let src = id.source(db); 53 let src = id.source(db);
54 let name = src.value.name().map(|n| n.as_name()); 54 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
55 let variant_data = VariantData::new(src.value.kind()); 55 let variant_data = VariantData::new(src.value.kind());
56 let variant_data = Arc::new(variant_data); 56 let variant_data = Arc::new(variant_data);
57 Arc::new(StructData { name, variant_data }) 57 Arc::new(StructData { name, variant_data })
58 } 58 }
59 pub(crate) fn union_data_query(db: &impl DefDatabase, id: UnionId) -> Arc<StructData> {
60 let src = id.source(db);
61 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
62 let variant_data = VariantData::new(
63 src.value
64 .record_field_def_list()
65 .map(ast::StructKind::Record)
66 .unwrap_or(ast::StructKind::Unit),
67 );
68 let variant_data = Arc::new(variant_data);
69 Arc::new(StructData { name, variant_data })
70 }
59} 71}
60 72
61impl EnumData { 73impl EnumData {
62 pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc<EnumData> { 74 pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc<EnumData> {
63 let src = e.source(db); 75 let src = e.source(db);
64 let name = src.value.name().map(|n| n.as_name()); 76 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
65 let mut trace = Trace::new_for_arena(); 77 let mut trace = Trace::new_for_arena();
66 lower_enum(&mut trace, &src.value); 78 lower_enum(&mut trace, &src.value);
67 Arc::new(EnumData { name, variants: trace.into_arena() }) 79 Arc::new(EnumData { name, variants: trace.into_arena() })
68 } 80 }
69 81
70 pub(crate) fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> { 82 pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
71 let (id, _) = self.variants.iter().find(|(_id, data)| data.name.as_ref() == Some(name))?; 83 let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?;
72 Some(id) 84 Some(id)
73 } 85 }
74} 86}
@@ -92,7 +104,7 @@ fn lower_enum(
92 trace.alloc( 104 trace.alloc(
93 || var.clone(), 105 || var.clone(),
94 || EnumVariantData { 106 || EnumVariantData {
95 name: var.name().map(|it| it.as_name()), 107 name: var.name().map_or_else(Name::missing, |it| it.as_name()),
96 variant_data: Arc::new(VariantData::new(var.kind())), 108 variant_data: Arc::new(VariantData::new(var.kind())),
97 }, 109 },
98 ); 110 );
@@ -117,6 +129,10 @@ impl VariantData {
117 } 129 }
118 } 130 }
119 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
120 pub fn is_unit(&self) -> bool { 136 pub fn is_unit(&self) -> bool {
121 match self { 137 match self {
122 VariantData::Unit => true, 138 VariantData::Unit => true,
@@ -137,7 +153,12 @@ impl HasChildSource for VariantId {
137 let src = it.parent.child_source(db); 153 let src = it.parent.child_source(db);
138 src.map(|map| map[it.local_id].kind()) 154 src.map(|map| map[it.local_id].kind())
139 } 155 }
140 VariantId::StructId(it) => it.0.source(db).map(|it| it.kind()), 156 VariantId::StructId(it) => it.source(db).map(|it| it.kind()),
157 VariantId::UnionId(it) => it.source(db).map(|it| {
158 it.record_field_def_list()
159 .map(ast::StructKind::Record)
160 .unwrap_or(ast::StructKind::Unit)
161 }),
141 }; 162 };
142 let mut trace = Trace::new_for_map(); 163 let mut trace = Trace::new_for_map();
143 lower_struct(&mut trace, &src.value); 164 lower_struct(&mut trace, &src.value);
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 53456fc08..fffb22201 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -35,7 +35,7 @@ impl Attrs {
35 match def { 35 match def {
36 AttrDefId::ModuleId(module) => { 36 AttrDefId::ModuleId(module) => {
37 let def_map = db.crate_def_map(module.krate); 37 let def_map = db.crate_def_map(module.krate);
38 let src = match def_map[module.module_id].declaration_source(db) { 38 let src = match def_map[module.local_id].declaration_source(db) {
39 Some(it) => it, 39 Some(it) => it,
40 None => return Attrs::default(), 40 None => return Attrs::default(),
41 }; 41 };
@@ -54,9 +54,9 @@ impl Attrs {
54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) 54 Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
55 } 55 }
56 AttrDefId::AdtId(it) => match it { 56 AttrDefId::AdtId(it) => match it {
57 AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 57 AdtId::StructId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 58 AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
59 AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), 59 AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
60 }, 60 },
61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), 61 AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db),
62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), 62 AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db),
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index d77ccb272..a57a0176d 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -6,8 +6,7 @@ pub mod scope;
6use std::{ops::Index, sync::Arc}; 6use std::{ops::Index, sync::Arc};
7 7
8use hir_expand::{ 8use hir_expand::{
9 either::Either, hygiene::Hygiene, AstId, HirFileId, MacroCallLoc, MacroDefId, MacroFileKind, 9 either::Either, hygiene::Hygiene, AstId, HirFileId, MacroDefId, MacroFileKind, Source,
10 Source,
11}; 10};
12use ra_arena::{map::ArenaMap, Arena}; 11use ra_arena::{map::ArenaMap, Arena};
13use ra_syntax::{ast, AstNode, AstPtr}; 12use ra_syntax::{ast, AstNode, AstPtr};
@@ -47,7 +46,7 @@ impl Expander {
47 46
48 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { 47 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) {
49 if let Some(def) = self.resolve_path_as_macro(db, &path) { 48 if let Some(def) = self.resolve_path_as_macro(db, &path) {
50 let call_id = db.intern_macro(MacroCallLoc { def, ast_id }); 49 let call_id = def.as_call_id(db, ast_id);
51 let file_id = call_id.as_file(MacroFileKind::Expr); 50 let file_id = call_id.as_file(MacroFileKind::Expr);
52 if let Some(node) = db.parse_or_expand(file_id) { 51 if let Some(node) = db.parse_or_expand(file_id) {
53 if let Some(expr) = ast::Expr::cast(node) { 52 if let Some(expr) = ast::Expr::cast(node) {
@@ -83,7 +82,7 @@ impl Expander {
83 } 82 }
84 83
85 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
86 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.take_macros() 85 self.crate_def_map.resolve_path(db, self.module.local_id, path).0.take_macros()
87 } 86 }
88} 87}
89 88
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 68bea34df..fee10b237 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -86,39 +86,53 @@ impl TypeAliasData {
86 86
87#[derive(Debug, Clone, PartialEq, Eq)] 87#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct TraitData { 88pub struct TraitData {
89 pub name: Option<Name>, 89 pub name: Name,
90 pub items: Vec<AssocItemId>, 90 pub items: Vec<(Name, AssocItemId)>,
91 pub auto: bool, 91 pub auto: bool,
92} 92}
93 93
94impl TraitData { 94impl TraitData {
95 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> { 95 pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc<TraitData> {
96 let src = tr.source(db); 96 let src = tr.source(db);
97 let name = src.value.name().map(|n| n.as_name()); 97 let name = src.value.name().map_or_else(Name::missing, |n| n.as_name());
98 let auto = src.value.is_auto(); 98 let auto = src.value.is_auto();
99 let ast_id_map = db.ast_id_map(src.file_id); 99 let ast_id_map = db.ast_id_map(src.file_id);
100
101 let container = ContainerId::TraitId(tr);
100 let items = if let Some(item_list) = src.value.item_list() { 102 let items = if let Some(item_list) = src.value.item_list() {
101 item_list 103 item_list
102 .impl_items() 104 .impl_items()
103 .map(|item_node| match item_node { 105 .map(|item_node| match item_node {
104 ast::ImplItem::FnDef(it) => FunctionLoc { 106 ast::ImplItem::FnDef(it) => {
105 container: ContainerId::TraitId(tr), 107 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
106 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 108 let def = FunctionLoc {
109 container,
110 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
111 }
112 .intern(db)
113 .into();
114 (name, def)
107 } 115 }
108 .intern(db) 116 ast::ImplItem::ConstDef(it) => {
109 .into(), 117 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
110 ast::ImplItem::ConstDef(it) => ConstLoc { 118 let def = ConstLoc {
111 container: ContainerId::TraitId(tr), 119 container,
112 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 120 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
121 }
122 .intern(db)
123 .into();
124 (name, def)
113 } 125 }
114 .intern(db) 126 ast::ImplItem::TypeAliasDef(it) => {
115 .into(), 127 let name = it.name().map_or_else(Name::missing, |it| it.as_name());
116 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc { 128 let def = TypeAliasLoc {
117 container: ContainerId::TraitId(tr), 129 container,
118 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)), 130 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
131 }
132 .intern(db)
133 .into();
134 (name, def)
119 } 135 }
120 .intern(db)
121 .into(),
122 }) 136 })
123 .collect() 137 .collect()
124 } else { 138 } else {
@@ -128,11 +142,18 @@ impl TraitData {
128 } 142 }
129 143
130 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ { 144 pub fn associated_types(&self) -> impl Iterator<Item = TypeAliasId> + '_ {
131 self.items.iter().filter_map(|item| match item { 145 self.items.iter().filter_map(|(_name, item)| match item {
132 AssocItemId::TypeAliasId(t) => Some(*t), 146 AssocItemId::TypeAliasId(t) => Some(*t),
133 _ => None, 147 _ => None,
134 }) 148 })
135 } 149 }
150
151 pub fn associated_type_by_name(&self, name: &Name) -> Option<TypeAliasId> {
152 self.items.iter().find_map(|(item_name, item)| match item {
153 AssocItemId::TypeAliasId(t) if item_name == name => Some(*t),
154 _ => None,
155 })
156 }
136} 157}
137 158
138#[derive(Debug, Clone, PartialEq, Eq)] 159#[derive(Debug, Clone, PartialEq, Eq)]
@@ -193,6 +214,7 @@ impl ImplData {
193 214
194#[derive(Debug, Clone, PartialEq, Eq)] 215#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct ConstData { 216pub struct ConstData {
217 /// const _: () = ();
196 pub name: Option<Name>, 218 pub name: Option<Name>,
197 pub type_ref: TypeRef, 219 pub type_ref: TypeRef,
198} 220}
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 32adb11bd..ef5611ffc 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -18,8 +18,8 @@ use crate::{
18 CrateDefMap, 18 CrateDefMap,
19 }, 19 },
20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, 20 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId,
21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructOrUnionId, TraitId, TypeAliasId, 21 ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, TypeAliasLoc,
22 TypeAliasLoc, 22 UnionId,
23}; 23};
24 24
25#[salsa::query_group(InternDatabaseStorage)] 25#[salsa::query_group(InternDatabaseStorage)]
@@ -27,7 +27,9 @@ pub trait InternDatabase: SourceDatabase {
27 #[salsa::interned] 27 #[salsa::interned]
28 fn intern_function(&self, loc: FunctionLoc) -> FunctionId; 28 fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
29 #[salsa::interned] 29 #[salsa::interned]
30 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> StructOrUnionId; 30 fn intern_struct(&self, loc: ItemLoc<ast::StructDef>) -> StructId;
31 #[salsa::interned]
32 fn intern_union(&self, loc: ItemLoc<ast::UnionDef>) -> UnionId;
31 #[salsa::interned] 33 #[salsa::interned]
32 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId; 34 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> EnumId;
33 #[salsa::interned] 35 #[salsa::interned]
@@ -57,7 +59,9 @@ pub trait DefDatabase: InternDatabase + AstDatabase {
57 fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; 59 fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>;
58 60
59 #[salsa::invoke(StructData::struct_data_query)] 61 #[salsa::invoke(StructData::struct_data_query)]
60 fn struct_data(&self, id: StructOrUnionId) -> Arc<StructData>; 62 fn struct_data(&self, id: StructId) -> Arc<StructData>;
63 #[salsa::invoke(StructData::union_data_query)]
64 fn union_data(&self, id: UnionId) -> Arc<StructData>;
61 65
62 #[salsa::invoke(EnumData::enum_data_query)] 66 #[salsa::invoke(EnumData::enum_data_query)]
63 fn enum_data(&self, e: EnumId) -> Arc<EnumData>; 67 fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index 90a8627bc..34ed9b7a5 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -36,7 +36,7 @@ impl Documentation {
36 match def { 36 match def {
37 AttrDefId::ModuleId(module) => { 37 AttrDefId::ModuleId(module) => {
38 let def_map = db.crate_def_map(module.krate); 38 let def_map = db.crate_def_map(module.krate);
39 let src = def_map[module.module_id].declaration_source(db)?; 39 let src = def_map[module.local_id].declaration_source(db)?;
40 docs_from_ast(&src.value) 40 docs_from_ast(&src.value)
41 } 41 }
42 AttrDefId::StructFieldId(it) => { 42 AttrDefId::StructFieldId(it) => {
@@ -47,9 +47,9 @@ impl Documentation {
47 } 47 }
48 } 48 }
49 AttrDefId::AdtId(it) => match it { 49 AttrDefId::AdtId(it) => match it {
50 AdtId::StructId(it) => docs_from_ast(&it.0.source(db).value), 50 AdtId::StructId(it) => docs_from_ast(&it.source(db).value),
51 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value), 51 AdtId::EnumId(it) => docs_from_ast(&it.source(db).value),
52 AdtId::UnionId(it) => docs_from_ast(&it.0.source(db).value), 52 AdtId::UnionId(it) => docs_from_ast(&it.source(db).value),
53 }, 53 },
54 AttrDefId::EnumVariantId(it) => { 54 AttrDefId::EnumVariantId(it) => {
55 let src = it.parent.child_source(db); 55 let src = it.parent.child_source(db);
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 015fe772e..3f94e40e4 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -60,10 +60,8 @@ impl GenericParams {
60 // FIXME: add `: Sized` bound for everything except for `Self` in traits 60 // FIXME: add `: Sized` bound for everything except for `Self` in traits
61 match def { 61 match def {
62 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), 62 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start),
63 GenericDefId::AdtId(AdtId::StructId(it)) => { 63 GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start),
64 generics.fill(&it.0.source(db).value, start) 64 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start),
65 }
66 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start),
67 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), 65 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start),
68 GenericDefId::TraitId(it) => { 66 GenericDefId::TraitId(it) => {
69 // traits get the Self type as an implicit first type parameter 67 // traits get the Self type as an implicit first type parameter
diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs
index f15c23db9..f4fdbdcfc 100644
--- a/crates/ra_hir_def/src/lang_item.rs
+++ b/crates/ra_hir_def/src/lang_item.rs
@@ -41,7 +41,7 @@ impl LangItems {
41 crate_def_map 41 crate_def_map
42 .modules 42 .modules
43 .iter() 43 .iter()
44 .filter_map(|(module_id, _)| db.module_lang_items(ModuleId { krate, module_id })) 44 .filter_map(|(local_id, _)| db.module_lang_items(ModuleId { krate, local_id }))
45 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v)))); 45 .for_each(|it| lang_items.items.extend(it.items.iter().map(|(k, v)| (k.clone(), *v))));
46 46
47 Arc::new(lang_items) 47 Arc::new(lang_items)
@@ -80,7 +80,7 @@ impl LangItems {
80 fn collect_lang_items(&mut self, db: &impl DefDatabase, module: ModuleId) { 80 fn collect_lang_items(&mut self, db: &impl DefDatabase, module: ModuleId) {
81 // Look for impl targets 81 // Look for impl targets
82 let def_map = db.crate_def_map(module.krate); 82 let def_map = db.crate_def_map(module.krate);
83 let module_data = &def_map[module.module_id]; 83 let module_data = &def_map[module.local_id];
84 for &impl_block in module_data.impls.iter() { 84 for &impl_block in module_data.impls.iter() {
85 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId) 85 self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
86 } 86 }
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index 8e8c2d749..bc5530896 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -27,7 +27,7 @@ pub mod body;
27pub mod resolver; 27pub mod resolver;
28 28
29mod trace; 29mod trace;
30mod nameres; 30pub mod nameres;
31 31
32#[cfg(test)] 32#[cfg(test)]
33mod test_db; 33mod test_db;
@@ -50,7 +50,7 @@ impl_arena_id!(LocalImportId);
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
51pub struct ModuleId { 51pub struct ModuleId {
52 pub krate: CrateId, 52 pub krate: CrateId,
53 pub module_id: LocalModuleId, 53 pub local_id: LocalModuleId,
54} 54}
55 55
56/// An ID of a module, **local** to a specific crate 56/// An ID of a module, **local** to a specific crate
@@ -141,30 +141,26 @@ impl Lookup for FunctionId {
141} 141}
142 142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
144pub struct StructOrUnionId(salsa::InternId); 144pub struct StructId(salsa::InternId);
145impl_intern_key!(StructOrUnionId); 145impl_intern_key!(StructId);
146impl AstItemDef<ast::StructDef> for StructOrUnionId { 146impl AstItemDef<ast::StructDef> for StructId {
147 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self { 147 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self {
148 db.intern_struct_or_union(loc) 148 db.intern_struct(loc)
149 } 149 }
150 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> { 150 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> {
151 db.lookup_intern_struct_or_union(self) 151 db.lookup_intern_struct(self)
152 } 152 }
153} 153}
154 154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 155#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
156pub struct StructId(pub StructOrUnionId); 156pub struct UnionId(salsa::InternId);
157impl From<StructId> for StructOrUnionId { 157impl_intern_key!(UnionId);
158 fn from(id: StructId) -> StructOrUnionId { 158impl AstItemDef<ast::UnionDef> for UnionId {
159 id.0 159 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::UnionDef>) -> Self {
160 db.intern_union(loc)
160 } 161 }
161} 162 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::UnionDef> {
162 163 db.lookup_intern_union(self)
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
164pub struct UnionId(pub StructOrUnionId);
165impl From<UnionId> for StructOrUnionId {
166 fn from(id: UnionId) -> StructOrUnionId {
167 id.0
168 } 164 }
169} 165}
170 166
@@ -402,6 +398,16 @@ impl_froms!(
402 ConstId 398 ConstId
403); 399);
404 400
401impl From<AssocItemId> for GenericDefId {
402 fn from(item: AssocItemId) -> Self {
403 match item {
404 AssocItemId::FunctionId(f) => f.into(),
405 AssocItemId::ConstId(c) => c.into(),
406 AssocItemId::TypeAliasId(t) => t.into(),
407 }
408 }
409}
410
405#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 411#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
406pub enum AttrDefId { 412pub enum AttrDefId {
407 ModuleId(ModuleId), 413 ModuleId(ModuleId),
@@ -435,6 +441,7 @@ impl_froms!(
435pub enum VariantId { 441pub enum VariantId {
436 EnumVariantId(EnumVariantId), 442 EnumVariantId(EnumVariantId),
437 StructId(StructId), 443 StructId(StructId),
444 UnionId(UnionId),
438} 445}
439impl_froms!(VariantId: EnumVariantId, StructId); 446impl_froms!(VariantId: EnumVariantId, StructId);
440 447
@@ -485,13 +492,23 @@ impl HasModule for ConstLoc {
485impl HasModule for AdtId { 492impl HasModule for AdtId {
486 fn module(&self, db: &impl db::DefDatabase) -> ModuleId { 493 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
487 match self { 494 match self {
488 AdtId::StructId(it) => it.0.module(db), 495 AdtId::StructId(it) => it.module(db),
489 AdtId::UnionId(it) => it.0.module(db), 496 AdtId::UnionId(it) => it.module(db),
490 AdtId::EnumId(it) => it.module(db), 497 AdtId::EnumId(it) => it.module(db),
491 } 498 }
492 } 499 }
493} 500}
494 501
502impl HasModule for DefWithBodyId {
503 fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
504 match self {
505 DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
506 DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
507 DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
508 }
509 }
510}
511
495impl HasModule for StaticLoc { 512impl HasModule for StaticLoc {
496 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { 513 fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
497 self.container 514 self.container
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 41becf8df..fd8245113 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -6,7 +6,7 @@
6use hir_expand::{ 6use hir_expand::{
7 builtin_macro::find_builtin_macro, 7 builtin_macro::find_builtin_macro,
8 name::{self, AsName, Name}, 8 name::{self, AsName, Name},
9 HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFileKind, 9 HirFileId, MacroCallId, MacroDefId, MacroDefKind, MacroFileKind,
10}; 10};
11use ra_cfg::CfgOptions; 11use ra_cfg::CfgOptions;
12use ra_db::{CrateId, FileId}; 12use ra_db::{CrateId, FileId};
@@ -25,7 +25,7 @@ use crate::{
25 per_ns::PerNs, 25 per_ns::PerNs,
26 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, 26 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId,
27 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, 27 Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId,
28 StructOrUnionId, TraitId, TypeAliasLoc, UnionId, 28 TraitId, TypeAliasLoc, UnionId,
29}; 29};
30 30
31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { 31pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -37,7 +37,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C
37 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); 37 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
38 def_map.extern_prelude.insert( 38 def_map.extern_prelude.insert(
39 dep.as_name(), 39 dep.as_name(),
40 ModuleId { krate: dep.crate_id, module_id: dep_def_map.root }.into(), 40 ModuleId { krate: dep.crate_id, local_id: dep_def_map.root }.into(),
41 ); 41 );
42 42
43 // look for the prelude 43 // look for the prelude
@@ -323,7 +323,7 @@ where
323 tested_by!(glob_across_crates); 323 tested_by!(glob_across_crates);
324 // glob import from other crate => we can just import everything once 324 // glob import from other crate => we can just import everything once
325 let item_map = self.db.crate_def_map(m.krate); 325 let item_map = self.db.crate_def_map(m.krate);
326 let scope = &item_map[m.module_id].scope; 326 let scope = &item_map[m.local_id].scope;
327 327
328 // Module scoped macros is included 328 // Module scoped macros is included
329 let items = scope 329 let items = scope
@@ -337,7 +337,7 @@ where
337 // glob import from same crate => we do an initial 337 // glob import from same crate => we do an initial
338 // import, and then need to propagate any further 338 // import, and then need to propagate any further
339 // additions 339 // additions
340 let scope = &self.def_map[m.module_id].scope; 340 let scope = &self.def_map[m.local_id].scope;
341 341
342 // Module scoped macros is included 342 // Module scoped macros is included
343 let items = scope 343 let items = scope
@@ -349,7 +349,7 @@ where
349 self.update(module_id, Some(import_id), &items); 349 self.update(module_id, Some(import_id), &items);
350 // record the glob import in case we add further items 350 // record the glob import in case we add further items
351 self.glob_imports 351 self.glob_imports
352 .entry(m.module_id) 352 .entry(m.local_id)
353 .or_default() 353 .or_default()
354 .push((module_id, import_id)); 354 .push((module_id, import_id));
355 } 355 }
@@ -362,7 +362,7 @@ where
362 .variants 362 .variants
363 .iter() 363 .iter()
364 .filter_map(|(local_id, variant_data)| { 364 .filter_map(|(local_id, variant_data)| {
365 let name = variant_data.name.clone()?; 365 let name = variant_data.name.clone();
366 let variant = EnumVariantId { parent: e, local_id }; 366 let variant = EnumVariantId { parent: e, local_id };
367 let res = Resolution { 367 let res = Resolution {
368 def: PerNs::both(variant.into(), variant.into()), 368 def: PerNs::both(variant.into(), variant.into()),
@@ -480,7 +480,7 @@ where
480 ); 480 );
481 481
482 if let Some(def) = resolved_res.resolved_def.take_macros() { 482 if let Some(def) = resolved_res.resolved_def.take_macros() {
483 let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id: *ast_id }); 483 let call_id = def.as_call_id(self.db, *ast_id);
484 resolved.push((*module_id, call_id, def)); 484 resolved.push((*module_id, call_id, def));
485 res = ReachedFixedPoint::No; 485 res = ReachedFixedPoint::No;
486 return false; 486 return false;
@@ -590,7 +590,7 @@ where
590 raw::RawItemKind::Impl(imp) => { 590 raw::RawItemKind::Impl(imp) => {
591 let module = ModuleId { 591 let module = ModuleId {
592 krate: self.def_collector.def_map.krate, 592 krate: self.def_collector.def_map.krate,
593 module_id: self.module_id, 593 local_id: self.module_id,
594 }; 594 };
595 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); 595 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id);
596 let imp_id = ImplId::from_ast_id(ctx, self.raw_items[imp].ast_id); 596 let imp_id = ImplId::from_ast_id(ctx, self.raw_items[imp].ast_id);
@@ -673,7 +673,7 @@ where
673 modules[self.module_id].children.insert(name.clone(), res); 673 modules[self.module_id].children.insert(name.clone(), res);
674 let resolution = Resolution { 674 let resolution = Resolution {
675 def: PerNs::types( 675 def: PerNs::types(
676 ModuleId { krate: self.def_collector.def_map.krate, module_id: res }.into(), 676 ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(),
677 ), 677 ),
678 import: None, 678 import: None,
679 }; 679 };
@@ -682,8 +682,7 @@ where
682 } 682 }
683 683
684 fn define_def(&mut self, def: &raw::DefData) { 684 fn define_def(&mut self, def: &raw::DefData) {
685 let module = 685 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id };
686 ModuleId { krate: self.def_collector.def_map.krate, module_id: self.module_id };
687 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); 686 let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id);
688 687
689 let name = def.name.clone(); 688 let name = def.name.clone();
@@ -698,14 +697,12 @@ where
698 PerNs::values(def.into()) 697 PerNs::values(def.into())
699 } 698 }
700 raw::DefKind::Struct(ast_id) => { 699 raw::DefKind::Struct(ast_id) => {
701 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); 700 let id = StructId::from_ast_id(ctx, ast_id).into();
702 let s = StructId(id).into(); 701 PerNs::both(id, id)
703 PerNs::both(s, s)
704 } 702 }
705 raw::DefKind::Union(ast_id) => { 703 raw::DefKind::Union(ast_id) => {
706 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); 704 let id = UnionId::from_ast_id(ctx, ast_id).into();
707 let u = UnionId(id).into(); 705 PerNs::both(id, id)
708 PerNs::both(u, u)
709 } 706 }
710 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), 707 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
711 raw::DefKind::Const(ast_id) => { 708 raw::DefKind::Const(ast_id) => {
@@ -775,8 +772,7 @@ where
775 if let Some(macro_def) = mac.path.as_ident().and_then(|name| { 772 if let Some(macro_def) = mac.path.as_ident().and_then(|name| {
776 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) 773 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
777 }) { 774 }) {
778 let macro_call_id = 775 let macro_call_id = macro_def.as_call_id(self.def_collector.db, ast_id);
779 self.def_collector.db.intern_macro(MacroCallLoc { def: macro_def, ast_id });
780 776
781 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def); 777 self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def);
782 return; 778 return;
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 9455f22bb..b72c55bd1 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -74,19 +74,19 @@ impl CrateDefMap {
74 PathKind::DollarCrate(krate) => { 74 PathKind::DollarCrate(krate) => {
75 if krate == self.krate { 75 if krate == self.krate {
76 tested_by!(macro_dollar_crate_self); 76 tested_by!(macro_dollar_crate_self);
77 PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into()) 77 PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into())
78 } else { 78 } else {
79 let def_map = db.crate_def_map(krate); 79 let def_map = db.crate_def_map(krate);
80 let module = ModuleId { krate, module_id: def_map.root }; 80 let module = ModuleId { krate, local_id: def_map.root };
81 tested_by!(macro_dollar_crate_other); 81 tested_by!(macro_dollar_crate_other);
82 PerNs::types(module.into()) 82 PerNs::types(module.into())
83 } 83 }
84 } 84 }
85 PathKind::Crate => { 85 PathKind::Crate => {
86 PerNs::types(ModuleId { krate: self.krate, module_id: self.root }.into()) 86 PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into())
87 } 87 }
88 PathKind::Self_ => { 88 PathKind::Self_ => {
89 PerNs::types(ModuleId { krate: self.krate, module_id: original_module }.into()) 89 PerNs::types(ModuleId { krate: self.krate, local_id: original_module }.into())
90 } 90 }
91 // plain import or absolute path in 2015: crate-relative with 91 // plain import or absolute path in 2015: crate-relative with
92 // fallback to extern prelude (with the simplification in 92 // fallback to extern prelude (with the simplification in
@@ -113,7 +113,7 @@ impl CrateDefMap {
113 } 113 }
114 PathKind::Super => { 114 PathKind::Super => {
115 if let Some(p) = self.modules[original_module].parent { 115 if let Some(p) = self.modules[original_module].parent {
116 PerNs::types(ModuleId { krate: self.krate, module_id: p }.into()) 116 PerNs::types(ModuleId { krate: self.krate, local_id: p }.into())
117 } else { 117 } else {
118 log::debug!("super path in root module"); 118 log::debug!("super path in root module");
119 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 119 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
@@ -160,7 +160,7 @@ impl CrateDefMap {
160 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; 160 Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
161 log::debug!("resolving {:?} in other crate", path); 161 log::debug!("resolving {:?} in other crate", path);
162 let defp_map = db.crate_def_map(module.krate); 162 let defp_map = db.crate_def_map(module.krate);
163 let (def, s) = defp_map.resolve_path(db, module.module_id, &path); 163 let (def, s) = defp_map.resolve_path(db, module.local_id, &path);
164 return ResolvePathResult::with( 164 return ResolvePathResult::with(
165 def, 165 def,
166 ReachedFixedPoint::Yes, 166 ReachedFixedPoint::Yes,
@@ -169,7 +169,7 @@ impl CrateDefMap {
169 } 169 }
170 170
171 // Since it is a qualified path here, it should not contains legacy macros 171 // Since it is a qualified path here, it should not contains legacy macros
172 match self[module.module_id].scope.get(&segment.name) { 172 match self[module.local_id].scope.get(&segment.name) {
173 Some(res) => res.def, 173 Some(res) => res.def,
174 _ => { 174 _ => {
175 log::debug!("path segment {:?} not found", segment.name); 175 log::debug!("path segment {:?} not found", segment.name);
@@ -254,7 +254,7 @@ impl CrateDefMap {
254 keep = db.crate_def_map(prelude.krate); 254 keep = db.crate_def_map(prelude.krate);
255 &keep 255 &keep
256 }; 256 };
257 def_map[prelude.module_id].scope.get(name).map_or_else(PerNs::none, |res| res.def) 257 def_map[prelude.local_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
258 } else { 258 } else {
259 PerNs::none() 259 PerNs::none()
260 } 260 }
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 401af031c..6eb106094 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -176,7 +176,7 @@ pub(super) struct DefData {
176pub(super) enum DefKind { 176pub(super) enum DefKind {
177 Function(FileAstId<ast::FnDef>), 177 Function(FileAstId<ast::FnDef>),
178 Struct(FileAstId<ast::StructDef>), 178 Struct(FileAstId<ast::StructDef>),
179 Union(FileAstId<ast::StructDef>), 179 Union(FileAstId<ast::UnionDef>),
180 Enum(FileAstId<ast::EnumDef>), 180 Enum(FileAstId<ast::EnumDef>),
181 Const(FileAstId<ast::ConstDef>), 181 Const(FileAstId<ast::ConstDef>),
182 Static(FileAstId<ast::StaticDef>), 182 Static(FileAstId<ast::StaticDef>),
@@ -246,11 +246,12 @@ impl RawItemsCollector {
246 ast::ModuleItem::StructDef(it) => { 246 ast::ModuleItem::StructDef(it) => {
247 let id = self.source_ast_id_map.ast_id(&it); 247 let id = self.source_ast_id_map.ast_id(&it);
248 let name = it.name(); 248 let name = it.name();
249 if it.is_union() { 249 (DefKind::Struct(id), name)
250 (DefKind::Union(id), name) 250 }
251 } else { 251 ast::ModuleItem::UnionDef(it) => {
252 (DefKind::Struct(id), name) 252 let id = self.source_ast_id_map.ast_id(&it);
253 } 253 let name = it.name();
254 (DefKind::Union(id), name)
254 } 255 }
255 ast::ModuleItem::EnumDef(it) => { 256 ast::ModuleItem::EnumDef(it) => {
256 (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name()) 257 (DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name())
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index f502f1cb3..87fcd617c 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -82,6 +82,12 @@ fn crate_def_map_smoke_test() {
82 82
83 //- /foo/bar.rs 83 //- /foo/bar.rs
84 pub struct Baz; 84 pub struct Baz;
85
86 union U {
87 to_be: bool,
88 not_to_be: u8,
89 }
90
85 enum E { V } 91 enum E { V }
86 ", 92 ",
87 ); 93 );
@@ -99,6 +105,7 @@ fn crate_def_map_smoke_test() {
99 â‹®crate::foo::bar 105 â‹®crate::foo::bar
100 â‹®Baz: t v 106 â‹®Baz: t v
101 â‹®E: t 107 â‹®E: t
108 â‹®U: t v
102 "###) 109 "###)
103} 110}
104 111
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 0e606fd0e..6810a26db 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -97,7 +97,7 @@ impl Path {
97 97
98 /// Converts an `ast::Path` to `Path`. Works with use trees. 98 /// Converts an `ast::Path` to `Path`. Works with use trees.
99 /// It correctly handles `$crate` based path from macro call. 99 /// It correctly handles `$crate` based path from macro call.
100 pub(crate) fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> { 100 pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
101 let mut kind = PathKind::Plain; 101 let mut kind = PathKind::Plain;
102 let mut segments = Vec::new(); 102 let mut segments = Vec::new();
103 loop { 103 loop {
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index 95b3c926d..0847f6dcf 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -61,6 +61,8 @@ pub enum TypeNs {
61 GenericParam(u32), 61 GenericParam(u32),
62 AdtId(AdtId), 62 AdtId(AdtId),
63 AdtSelfType(AdtId), 63 AdtSelfType(AdtId),
64 // Yup, enum variants are added to the types ns, but any usage of variant as
65 // type is an error.
64 EnumVariantId(EnumVariantId), 66 EnumVariantId(EnumVariantId),
65 TypeAliasId(TypeAliasId), 67 TypeAliasId(TypeAliasId),
66 BuiltinType(BuiltinType), 68 BuiltinType(BuiltinType),
@@ -323,7 +325,7 @@ impl Resolver {
323 if let Scope::ModuleScope(m) = scope { 325 if let Scope::ModuleScope(m) = scope {
324 if let Some(prelude) = m.crate_def_map.prelude { 326 if let Some(prelude) = m.crate_def_map.prelude {
325 let prelude_def_map = db.crate_def_map(prelude.krate); 327 let prelude_def_map = db.crate_def_map(prelude.krate);
326 traits.extend(prelude_def_map[prelude.module_id].scope.traits()); 328 traits.extend(prelude_def_map[prelude.local_id].scope.traits());
327 } 329 }
328 traits.extend(m.crate_def_map[m.module_id].scope.traits()); 330 traits.extend(m.crate_def_map[m.module_id].scope.traits());
329 } 331 }
@@ -400,7 +402,7 @@ impl Scope {
400 }); 402 });
401 if let Some(prelude) = m.crate_def_map.prelude { 403 if let Some(prelude) = m.crate_def_map.prelude {
402 let prelude_def_map = db.crate_def_map(prelude.krate); 404 let prelude_def_map = db.crate_def_map(prelude.krate);
403 prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { 405 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, res)| {
404 f(name.clone(), ScopeDef::PerNs(res.def)); 406 f(name.clone(), ScopeDef::PerNs(res.def));
405 }); 407 });
406 } 408 }
@@ -482,7 +484,7 @@ impl Resolver {
482 } 484 }
483} 485}
484 486
485pub trait HasResolver { 487pub trait HasResolver: Copy {
486 /// Builds a resolver for type references inside this def. 488 /// Builds a resolver for type references inside this def.
487 fn resolver(self, db: &impl DefDatabase) -> Resolver; 489 fn resolver(self, db: &impl DefDatabase) -> Resolver;
488} 490}
@@ -490,7 +492,7 @@ pub trait HasResolver {
490impl HasResolver for ModuleId { 492impl HasResolver for ModuleId {
491 fn resolver(self, db: &impl DefDatabase) -> Resolver { 493 fn resolver(self, db: &impl DefDatabase) -> Resolver {
492 let def_map = db.crate_def_map(self.krate); 494 let def_map = db.crate_def_map(self.krate);
493 Resolver::default().push_module_scope(def_map, self.module_id) 495 Resolver::default().push_module_scope(def_map, self.local_id)
494 } 496 }
495} 497}
496 498
@@ -500,7 +502,7 @@ impl HasResolver for TraitId {
500 } 502 }
501} 503}
502 504
503impl<T: Into<AdtId>> HasResolver for T { 505impl<T: Into<AdtId> + Copy> HasResolver for T {
504 fn resolver(self, db: &impl DefDatabase) -> Resolver { 506 fn resolver(self, db: &impl DefDatabase) -> Resolver {
505 let def = self.into(); 507 let def = self.into();
506 def.module(db) 508 def.module(db)
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/lib.rs b/crates/ra_hir_expand/src/lib.rs
index 4f3ccf1d0..b6a739cda 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -135,6 +135,16 @@ pub struct MacroDefId {
135 pub kind: MacroDefKind, 135 pub kind: MacroDefKind,
136} 136}
137 137
138impl MacroDefId {
139 pub fn as_call_id(
140 self,
141 db: &dyn db::AstDatabase,
142 ast_id: AstId<ast::MacroCall>,
143 ) -> MacroCallId {
144 db.intern_macro(MacroCallLoc { def: self, ast_id })
145 }
146}
147
138#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 148#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
139pub enum MacroDefKind { 149pub enum MacroDefKind {
140 Declarative, 150 Declarative,
@@ -143,8 +153,8 @@ pub enum MacroDefKind {
143 153
144#[derive(Debug, Clone, PartialEq, Eq, Hash)] 154#[derive(Debug, Clone, PartialEq, Eq, Hash)]
145pub struct MacroCallLoc { 155pub struct MacroCallLoc {
146 pub def: MacroDefId, 156 pub(crate) def: MacroDefId,
147 pub ast_id: AstId<ast::MacroCall>, 157 pub(crate) ast_id: AstId<ast::MacroCall>,
148} 158}
149 159
150impl MacroCallId { 160impl MacroCallId {
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..429242870
--- /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]
11arrayvec = "0.5.1"
12ena = "0.13"
13log = "0.4.5"
14rustc-hash = "1.0"
15
16hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
17hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" }
18ra_arena = { path = "../ra_arena" }
19ra_db = { path = "../ra_db" }
20ra_prof = { path = "../ra_prof" }
21ra_syntax = { path = "../ra_syntax" }
22test_utils = { path = "../test_utils" }
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/src/ty/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs
index 41c99d227..9d1d4e48c 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir_ty/src/autoderef.rs
@@ -5,49 +5,56 @@
5 5
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; 8use hir_def::lang_item::LangItemTarget;
9use hir_expand::name; 9use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId;
11 12
12use crate::{db::HirDatabase, Trait}; 13use crate::db::HirDatabase;
13 14
14use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; 15use super::{
16 traits::{InEnvironment, Solution},
17 Canonical, Substs, Ty, TypeWalk,
18};
15 19
16const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
17 21
18pub(crate) fn autoderef<'a>( 22pub fn autoderef<'a>(
19 db: &'a impl HirDatabase, 23 db: &'a impl HirDatabase,
20 resolver: &'a Resolver, 24 krate: Option<CrateId>,
21 ty: Canonical<Ty>, 25 ty: InEnvironment<Canonical<Ty>>,
22) -> impl Iterator<Item = Canonical<Ty>> + 'a { 26) -> impl Iterator<Item = Canonical<Ty>> + 'a {
23 successors(Some(ty), move |ty| deref(db, resolver, ty)).take(AUTODEREF_RECURSION_LIMIT) 27 let InEnvironment { value: ty, environment } = ty;
28 successors(Some(ty), move |ty| {
29 deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() })
30 })
31 .take(AUTODEREF_RECURSION_LIMIT)
24} 32}
25 33
26pub(crate) fn deref( 34pub(crate) fn deref(
27 db: &impl HirDatabase, 35 db: &impl HirDatabase,
28 resolver: &Resolver, 36 krate: CrateId,
29 ty: &Canonical<Ty>, 37 ty: InEnvironment<&Canonical<Ty>>,
30) -> Option<Canonical<Ty>> { 38) -> Option<Canonical<Ty>> {
31 if let Some(derefed) = ty.value.builtin_deref() { 39 if let Some(derefed) = ty.value.value.builtin_deref() {
32 Some(Canonical { value: derefed, num_vars: ty.num_vars }) 40 Some(Canonical { value: derefed, num_vars: ty.value.num_vars })
33 } else { 41 } else {
34 deref_by_trait(db, resolver, ty) 42 deref_by_trait(db, krate, ty)
35 } 43 }
36} 44}
37 45
38fn deref_by_trait( 46fn deref_by_trait(
39 db: &impl HirDatabase, 47 db: &impl HirDatabase,
40 resolver: &Resolver, 48 krate: CrateId,
41 ty: &Canonical<Ty>, 49 ty: InEnvironment<&Canonical<Ty>>,
42) -> Option<Canonical<Ty>> { 50) -> Option<Canonical<Ty>> {
43 let krate = resolver.krate()?;
44 let deref_trait = match db.lang_item(krate.into(), "deref".into())? { 51 let deref_trait = match db.lang_item(krate.into(), "deref".into())? {
45 LangItemTarget::TraitId(t) => Trait::from(t), 52 LangItemTarget::TraitId(it) => it,
46 _ => return None, 53 _ => return None,
47 }; 54 };
48 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)?;
49 56
50 let generic_params = db.generic_params(target.id.into()); 57 let generic_params = db.generic_params(target.into());
51 if generic_params.count_params_including_parent() != 1 { 58 if generic_params.count_params_including_parent() != 1 {
52 // the Target type + Deref trait should only have one generic parameter, 59 // the Target type + Deref trait should only have one generic parameter,
53 // namely Deref's Self type 60 // namely Deref's Self type
@@ -56,10 +63,8 @@ fn deref_by_trait(
56 63
57 // FIXME make the Canonical handling nicer 64 // FIXME make the Canonical handling nicer
58 65
59 let env = super::lower::trait_env(db, resolver);
60
61 let parameters = Substs::build_for_generics(&generic_params) 66 let parameters = Substs::build_for_generics(&generic_params)
62 .push(ty.value.clone().shift_bound_vars(1)) 67 .push(ty.value.value.clone().shift_bound_vars(1))
63 .build(); 68 .build();
64 69
65 let projection = super::traits::ProjectionPredicate { 70 let projection = super::traits::ProjectionPredicate {
@@ -69,9 +74,9 @@ fn deref_by_trait(
69 74
70 let obligation = super::Obligation::Projection(projection); 75 let obligation = super::Obligation::Projection(projection);
71 76
72 let in_env = super::traits::InEnvironment { value: obligation, environment: env }; 77 let in_env = InEnvironment { value: obligation, environment: ty.environment };
73 78
74 let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env }; 79 let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env };
75 80
76 let solution = db.trait_solve(krate.into(), canonical)?; 81 let solution = db.trait_solve(krate.into(), canonical)?;
77 82
@@ -89,14 +94,14 @@ fn deref_by_trait(
89 // the case. 94 // the case.
90 for i in 1..vars.0.num_vars { 95 for i in 1..vars.0.num_vars {
91 if vars.0.value[i] != Ty::Bound((i - 1) as u32) { 96 if vars.0.value[i] != Ty::Bound((i - 1) as u32) {
92 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution); 97 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
93 return None; 98 return None;
94 } 99 }
95 } 100 }
96 Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) 101 Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars })
97 } 102 }
98 Solution::Ambig(_) => { 103 Solution::Ambig(_) => {
99 info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution); 104 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution);
100 None 105 None
101 } 106 }
102 } 107 }
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs
new file mode 100644
index 000000000..9ce154593
--- /dev/null
+++ b/crates/ra_hir_ty/src/db.rs
@@ -0,0 +1,119 @@
1//! FIXME: write short doc here
2
3use std::sync::Arc;
4
5use hir_def::{
6 db::DefDatabase, DefWithBodyId, GenericDefId, ImplId, LocalStructFieldId, TraitId, VariantId,
7};
8use ra_arena::map::ArenaMap;
9use ra_db::{salsa, CrateId};
10
11use crate::{
12 method_resolution::CrateImplBlocks,
13 traits::{AssocTyValue, Impl},
14 CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor,
15 ValueTyDefId,
16};
17
18#[salsa::query_group(HirDatabaseStorage)]
19#[salsa::requires(salsa::Database)]
20pub trait HirDatabase: DefDatabase {
21 #[salsa::invoke(crate::infer_query)]
22 fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
23
24 #[salsa::invoke(crate::lower::ty_query)]
25 fn ty(&self, def: TyDefId) -> Ty;
26
27 #[salsa::invoke(crate::lower::value_ty_query)]
28 fn value_ty(&self, def: ValueTyDefId) -> Ty;
29
30 #[salsa::invoke(crate::lower::impl_ty_query)]
31 fn impl_ty(&self, def: ImplId) -> ImplTy;
32
33 #[salsa::invoke(crate::lower::field_types_query)]
34 fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalStructFieldId, Ty>>;
35
36 #[salsa::invoke(crate::callable_item_sig)]
37 fn callable_item_signature(&self, def: CallableDef) -> FnSig;
38
39 #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
40 fn generic_predicates_for_param(
41 &self,
42 def: GenericDefId,
43 param_idx: u32,
44 ) -> Arc<[GenericPredicate]>;
45
46 #[salsa::invoke(crate::lower::generic_predicates_query)]
47 fn generic_predicates(&self, def: GenericDefId) -> Arc<[GenericPredicate]>;
48
49 #[salsa::invoke(crate::lower::generic_defaults_query)]
50 fn generic_defaults(&self, def: GenericDefId) -> Substs;
51
52 #[salsa::invoke(crate::method_resolution::CrateImplBlocks::impls_in_crate_query)]
53 fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplBlocks>;
54
55 #[salsa::invoke(crate::traits::impls_for_trait_query)]
56 fn impls_for_trait(&self, krate: CrateId, trait_: TraitId) -> Arc<[ImplId]>;
57
58 /// This provides the Chalk trait solver instance. Because Chalk always
59 /// works from a specific crate, this query is keyed on the crate; and
60 /// because Chalk does its own internal caching, the solver is wrapped in a
61 /// Mutex and the query does an untracked read internally, to make sure the
62 /// cached state is thrown away when input facts change.
63 #[salsa::invoke(crate::traits::trait_solver_query)]
64 fn trait_solver(&self, krate: CrateId) -> crate::traits::TraitSolver;
65
66 // Interned IDs for Chalk integration
67 #[salsa::interned]
68 fn intern_type_ctor(&self, type_ctor: TypeCtor) -> crate::TypeCtorId;
69 #[salsa::interned]
70 fn intern_chalk_impl(&self, impl_: Impl) -> crate::traits::GlobalImplId;
71 #[salsa::interned]
72 fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
73
74 #[salsa::invoke(crate::traits::chalk::associated_ty_data_query)]
75 fn associated_ty_data(
76 &self,
77 id: chalk_ir::TypeId,
78 ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>;
79
80 #[salsa::invoke(crate::traits::chalk::trait_datum_query)]
81 fn trait_datum(
82 &self,
83 krate: CrateId,
84 trait_id: chalk_ir::TraitId,
85 ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>;
86
87 #[salsa::invoke(crate::traits::chalk::struct_datum_query)]
88 fn struct_datum(
89 &self,
90 krate: CrateId,
91 struct_id: chalk_ir::StructId,
92 ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>;
93
94 #[salsa::invoke(crate::traits::chalk::impl_datum_query)]
95 fn impl_datum(
96 &self,
97 krate: CrateId,
98 impl_id: chalk_ir::ImplId,
99 ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>;
100
101 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
102 fn associated_ty_value(
103 &self,
104 krate: CrateId,
105 id: chalk_rust_ir::AssociatedTyValueId,
106 ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>;
107
108 #[salsa::invoke(crate::traits::trait_solve_query)]
109 fn trait_solve(
110 &self,
111 krate: CrateId,
112 goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>,
113 ) -> Option<crate::traits::Solution>;
114}
115
116#[test]
117fn hir_database_is_object_safe() {
118 fn _assert_object_safe(_: &dyn HirDatabase) {}
119}
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
new file mode 100644
index 000000000..4a13fac23
--- /dev/null
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -0,0 +1,91 @@
1//! FIXME: write short doc here
2
3use std::any::Any;
4
5use hir_expand::{db::AstDatabase, name::Name, HirFileId, Source};
6use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr};
7
8pub use hir_def::diagnostics::UnresolvedModule;
9pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink};
10
11#[derive(Debug)]
12pub struct NoSuchField {
13 pub file: HirFileId,
14 pub field: AstPtr<ast::RecordField>,
15}
16
17impl Diagnostic for NoSuchField {
18 fn message(&self) -> String {
19 "no such field".to_string()
20 }
21
22 fn source(&self) -> Source<SyntaxNodePtr> {
23 Source { file_id: self.file, value: self.field.into() }
24 }
25
26 fn as_any(&self) -> &(dyn Any + Send + 'static) {
27 self
28 }
29}
30
31#[derive(Debug)]
32pub struct MissingFields {
33 pub file: HirFileId,
34 pub field_list: AstPtr<ast::RecordFieldList>,
35 pub missed_fields: Vec<Name>,
36}
37
38impl Diagnostic for MissingFields {
39 fn message(&self) -> String {
40 use std::fmt::Write;
41 let mut message = String::from("Missing structure fields:\n");
42 for field in &self.missed_fields {
43 write!(message, "- {}\n", field).unwrap();
44 }
45 message
46 }
47 fn source(&self) -> Source<SyntaxNodePtr> {
48 Source { file_id: self.file, value: self.field_list.into() }
49 }
50 fn as_any(&self) -> &(dyn Any + Send + 'static) {
51 self
52 }
53}
54
55impl AstDiagnostic for MissingFields {
56 type AST = ast::RecordFieldList;
57
58 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
59 let root = db.parse_or_expand(self.source().file_id).unwrap();
60 let node = self.source().value.to_node(&root);
61 ast::RecordFieldList::cast(node).unwrap()
62 }
63}
64
65#[derive(Debug)]
66pub struct MissingOkInTailExpr {
67 pub file: HirFileId,
68 pub expr: AstPtr<ast::Expr>,
69}
70
71impl Diagnostic for MissingOkInTailExpr {
72 fn message(&self) -> String {
73 "wrap return expression in Ok".to_string()
74 }
75 fn source(&self) -> Source<SyntaxNodePtr> {
76 Source { file_id: self.file, value: self.expr.into() }
77 }
78 fn as_any(&self) -> &(dyn Any + Send + 'static) {
79 self
80 }
81}
82
83impl AstDiagnostic for MissingOkInTailExpr {
84 type AST = ast::Expr;
85
86 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
87 let root = db.parse_or_expand(self.file).unwrap();
88 let node = self.source().value.to_node(&root);
89 ast::Expr::cast(node).unwrap()
90 }
91}
diff --git a/crates/ra_hir/src/ty/display.rs b/crates/ra_hir_ty/src/display.rs
index 9bb3ece6c..9bb3ece6c 100644
--- a/crates/ra_hir/src/ty/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir_ty/src/expr.rs
index 43fedde7a..5c65f9370 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir_ty/src/expr.rs
@@ -2,8 +2,12 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use hir_def::{path::known, resolver::HasResolver}; 5use hir_def::{
6use hir_expand::diagnostics::DiagnosticSink; 6 path::{known, Path},
7 resolver::HasResolver,
8 AdtId, FunctionId,
9};
10use hir_expand::{diagnostics::DiagnosticSink, name::Name};
7use ra_syntax::ast; 11use ra_syntax::ast;
8use ra_syntax::AstPtr; 12use ra_syntax::AstPtr;
9use rustc_hash::FxHashSet; 13use rustc_hash::FxHashSet;
@@ -11,8 +15,7 @@ use rustc_hash::FxHashSet;
11use crate::{ 15use crate::{
12 db::HirDatabase, 16 db::HirDatabase,
13 diagnostics::{MissingFields, MissingOkInTailExpr}, 17 diagnostics::{MissingFields, MissingOkInTailExpr},
14 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, 18 ApplicationTy, InferenceResult, Ty, TypeCtor,
15 Adt, Function, Name, Path,
16}; 19};
17 20
18pub use hir_def::{ 21pub use hir_def::{
@@ -26,23 +29,23 @@ pub use hir_def::{
26 }, 29 },
27}; 30};
28 31
29pub(crate) struct ExprValidator<'a, 'b: 'a> { 32pub struct ExprValidator<'a, 'b: 'a> {
30 func: Function, 33 func: FunctionId,
31 infer: Arc<InferenceResult>, 34 infer: Arc<InferenceResult>,
32 sink: &'a mut DiagnosticSink<'b>, 35 sink: &'a mut DiagnosticSink<'b>,
33} 36}
34 37
35impl<'a, 'b> ExprValidator<'a, 'b> { 38impl<'a, 'b> ExprValidator<'a, 'b> {
36 pub(crate) fn new( 39 pub fn new(
37 func: Function, 40 func: FunctionId,
38 infer: Arc<InferenceResult>, 41 infer: Arc<InferenceResult>,
39 sink: &'a mut DiagnosticSink<'b>, 42 sink: &'a mut DiagnosticSink<'b>,
40 ) -> ExprValidator<'a, 'b> { 43 ) -> ExprValidator<'a, 'b> {
41 ExprValidator { func, infer, sink } 44 ExprValidator { func, infer, sink }
42 } 45 }
43 46
44 pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) { 47 pub fn validate_body(&mut self, db: &impl HirDatabase) {
45 let body = self.func.body(db); 48 let body = db.body(self.func.into());
46 49
47 for e in body.exprs.iter() { 50 for e in body.exprs.iter() {
48 if let (id, Expr::RecordLit { path, fields, spread }) = e { 51 if let (id, Expr::RecordLit { path, fields, spread }) = e {
@@ -69,16 +72,18 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
69 } 72 }
70 73
71 let struct_def = match self.infer[id].as_adt() { 74 let struct_def = match self.infer[id].as_adt() {
72 Some((Adt::Struct(s), _)) => s, 75 Some((AdtId::StructId(s), _)) => s,
73 _ => return, 76 _ => return,
74 }; 77 };
78 let struct_data = db.struct_data(struct_def);
75 79
76 let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 80 let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
77 let missed_fields: Vec<Name> = struct_def 81 let missed_fields: Vec<Name> = struct_data
78 .fields(db) 82 .variant_data
83 .fields()
79 .iter() 84 .iter()
80 .filter_map(|f| { 85 .filter_map(|(_f, d)| {
81 let name = f.name(db); 86 let name = d.name.clone();
82 if lit_fields.contains(&name) { 87 if lit_fields.contains(&name) {
83 None 88 None
84 } else { 89 } else {
@@ -89,7 +94,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
89 if missed_fields.is_empty() { 94 if missed_fields.is_empty() {
90 return; 95 return;
91 } 96 }
92 let source_map = self.func.body_source_map(db); 97 let (_, source_map) = db.body_with_source_map(self.func.into());
93 98
94 if let Some(source_ptr) = source_map.expr_syntax(id) { 99 if let Some(source_ptr) = source_map.expr_syntax(id) {
95 if let Some(expr) = source_ptr.value.a() { 100 if let Some(expr) = source_ptr.value.a() {
@@ -121,20 +126,20 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
121 126
122 let std_result_path = known::std_result_result(); 127 let std_result_path = known::std_result_result();
123 128
124 let resolver = self.func.id.resolver(db); 129 let resolver = self.func.resolver(db);
125 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { 130 let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
126 Some(it) => it, 131 Some(it) => it,
127 _ => return, 132 _ => return,
128 }; 133 };
129 134
130 let std_result_ctor = TypeCtor::Adt(Adt::Enum(std_result_enum.into())); 135 let std_result_ctor = TypeCtor::Adt(AdtId::EnumId(std_result_enum));
131 let params = match &mismatch.expected { 136 let params = match &mismatch.expected {
132 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters, 137 Ty::Apply(ApplicationTy { ctor, parameters }) if ctor == &std_result_ctor => parameters,
133 _ => return, 138 _ => return,
134 }; 139 };
135 140
136 if params.len() == 2 && &params[0] == &mismatch.actual { 141 if params.len() == 2 && &params[0] == &mismatch.actual {
137 let source_map = self.func.body_source_map(db); 142 let (_, source_map) = db.body_with_source_map(self.func.into());
138 143
139 if let Some(source_ptr) = source_map.expr_syntax(id) { 144 if let Some(source_ptr) = source_map.expr_syntax(id) {
140 if let Some(expr) = source_ptr.value.a() { 145 if let Some(expr) = source_ptr.value.a() {
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir_ty/src/infer.rs
index ddc7d262a..1e9f4b208 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -22,11 +22,13 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
22use rustc_hash::FxHashMap; 22use rustc_hash::FxHashMap;
23 23
24use hir_def::{ 24use hir_def::{
25 body::Body,
25 data::{ConstData, FunctionData}, 26 data::{ConstData, FunctionData},
26 path::known, 27 expr::{BindingAnnotation, ExprId, PatId},
28 path::{known, Path},
27 resolver::{HasResolver, Resolver, TypeNs}, 29 resolver::{HasResolver, Resolver, TypeNs},
28 type_ref::{Mutability, TypeRef}, 30 type_ref::{Mutability, TypeRef},
29 AdtId, DefWithBodyId, 31 AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId,
30}; 32};
31use hir_expand::{diagnostics::DiagnosticSink, name}; 33use hir_expand::{diagnostics::DiagnosticSink, name};
32use ra_arena::map::ArenaMap; 34use ra_arena::map::ArenaMap;
@@ -34,22 +36,16 @@ use ra_prof::profile;
34use test_utils::tested_by; 36use test_utils::tested_by;
35 37
36use super::{ 38use super::{
37 lower, 39 primitive::{FloatTy, IntTy},
38 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 40 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
39 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, 41 ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
40 TypeCtor, TypeWalk, Uncertain, 42 TypeWalk, Uncertain,
41};
42use crate::{
43 code_model::TypeAlias,
44 db::HirDatabase,
45 expr::{BindingAnnotation, Body, ExprId, PatId},
46 ty::infer::diagnostics::InferenceDiagnostic,
47 Adt, AssocItem, DefWithBody, FloatTy, Function, IntTy, Path, StructField, Trait, VariantDef,
48}; 43};
44use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
49 45
50macro_rules! ty_app { 46macro_rules! ty_app {
51 ($ctor:pat, $param:pat) => { 47 ($ctor:pat, $param:pat) => {
52 crate::ty::Ty::Apply(crate::ty::ApplicationTy { ctor: $ctor, parameters: $param }) 48 crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
53 }; 49 };
54 ($ctor:pat) => { 50 ($ctor:pat) => {
55 ty_app!($ctor, _) 51 ty_app!($ctor, _)
@@ -63,15 +59,15 @@ mod pat;
63mod coerce; 59mod coerce;
64 60
65/// The entry point of type inference. 61/// The entry point of type inference.
66pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 62pub fn infer_query(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
67 let _p = profile("infer_query"); 63 let _p = profile("infer_query");
68 let resolver = DefWithBodyId::from(def).resolver(db); 64 let resolver = def.resolver(db);
69 let mut ctx = InferenceContext::new(db, def, resolver); 65 let mut ctx = InferenceContext::new(db, def, resolver);
70 66
71 match &def { 67 match def {
72 DefWithBody::Const(c) => ctx.collect_const(&db.const_data(c.id)), 68 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
73 DefWithBody::Function(f) => ctx.collect_fn(&db.function_data(f.id)), 69 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)),
74 DefWithBody::Static(s) => ctx.collect_const(&db.static_data(s.id)), 70 DefWithBodyId::StaticId(s) => ctx.collect_const(&db.static_data(s)),
75 } 71 }
76 72
77 ctx.infer_body(); 73 ctx.infer_body();
@@ -122,50 +118,50 @@ pub struct TypeMismatch {
122#[derive(Clone, PartialEq, Eq, Debug, Default)] 118#[derive(Clone, PartialEq, Eq, Debug, Default)]
123pub struct InferenceResult { 119pub struct InferenceResult {
124 /// For each method call expr, records the function it resolves to. 120 /// For each method call expr, records the function it resolves to.
125 method_resolutions: FxHashMap<ExprId, Function>, 121 method_resolutions: FxHashMap<ExprId, FunctionId>,
126 /// For each field access expr, records the field it resolves to. 122 /// For each field access expr, records the field it resolves to.
127 field_resolutions: FxHashMap<ExprId, StructField>, 123 field_resolutions: FxHashMap<ExprId, StructFieldId>,
128 /// For each field in record literal, records the field it resolves to. 124 /// For each field in record literal, records the field it resolves to.
129 record_field_resolutions: FxHashMap<ExprId, StructField>, 125 record_field_resolutions: FxHashMap<ExprId, StructFieldId>,
130 /// For each struct literal, records the variant it resolves to. 126 /// For each struct literal, records the variant it resolves to.
131 variant_resolutions: FxHashMap<ExprOrPatId, VariantDef>, 127 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
132 /// For each associated item record what it resolves to 128 /// For each associated item record what it resolves to
133 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItem>, 129 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
134 diagnostics: Vec<InferenceDiagnostic>, 130 diagnostics: Vec<InferenceDiagnostic>,
135 pub(super) type_of_expr: ArenaMap<ExprId, Ty>, 131 pub type_of_expr: ArenaMap<ExprId, Ty>,
136 pub(super) type_of_pat: ArenaMap<PatId, Ty>, 132 pub type_of_pat: ArenaMap<PatId, Ty>,
137 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>, 133 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
138} 134}
139 135
140impl InferenceResult { 136impl InferenceResult {
141 pub fn method_resolution(&self, expr: ExprId) -> Option<Function> { 137 pub fn method_resolution(&self, expr: ExprId) -> Option<FunctionId> {
142 self.method_resolutions.get(&expr).copied() 138 self.method_resolutions.get(&expr).copied()
143 } 139 }
144 pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { 140 pub fn field_resolution(&self, expr: ExprId) -> Option<StructFieldId> {
145 self.field_resolutions.get(&expr).copied() 141 self.field_resolutions.get(&expr).copied()
146 } 142 }
147 pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructField> { 143 pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructFieldId> {
148 self.record_field_resolutions.get(&expr).copied() 144 self.record_field_resolutions.get(&expr).copied()
149 } 145 }
150 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantDef> { 146 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
151 self.variant_resolutions.get(&id.into()).copied() 147 self.variant_resolutions.get(&id.into()).copied()
152 } 148 }
153 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantDef> { 149 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {
154 self.variant_resolutions.get(&id.into()).copied() 150 self.variant_resolutions.get(&id.into()).copied()
155 } 151 }
156 pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<AssocItem> { 152 pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<AssocItemId> {
157 self.assoc_resolutions.get(&id.into()).copied() 153 self.assoc_resolutions.get(&id.into()).copied()
158 } 154 }
159 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<AssocItem> { 155 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<AssocItemId> {
160 self.assoc_resolutions.get(&id.into()).copied() 156 self.assoc_resolutions.get(&id.into()).copied()
161 } 157 }
162 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> { 158 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
163 self.type_mismatches.get(expr) 159 self.type_mismatches.get(expr)
164 } 160 }
165 pub(crate) fn add_diagnostics( 161 pub fn add_diagnostics(
166 &self, 162 &self,
167 db: &impl HirDatabase, 163 db: &impl HirDatabase,
168 owner: Function, 164 owner: FunctionId,
169 sink: &mut DiagnosticSink, 165 sink: &mut DiagnosticSink,
170 ) { 166 ) {
171 self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink)) 167 self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink))
@@ -192,7 +188,7 @@ impl Index<PatId> for InferenceResult {
192#[derive(Clone, Debug)] 188#[derive(Clone, Debug)]
193struct InferenceContext<'a, D: HirDatabase> { 189struct InferenceContext<'a, D: HirDatabase> {
194 db: &'a D, 190 db: &'a D,
195 owner: DefWithBody, 191 owner: DefWithBodyId,
196 body: Arc<Body>, 192 body: Arc<Body>,
197 resolver: Resolver, 193 resolver: Resolver,
198 var_unification_table: InPlaceUnificationTable<TypeVarId>, 194 var_unification_table: InPlaceUnificationTable<TypeVarId>,
@@ -210,13 +206,13 @@ struct InferenceContext<'a, D: HirDatabase> {
210} 206}
211 207
212impl<'a, D: HirDatabase> InferenceContext<'a, D> { 208impl<'a, D: HirDatabase> InferenceContext<'a, D> {
213 fn new(db: &'a D, owner: DefWithBody, resolver: Resolver) -> Self { 209 fn new(db: &'a D, owner: DefWithBodyId, resolver: Resolver) -> Self {
214 InferenceContext { 210 InferenceContext {
215 result: InferenceResult::default(), 211 result: InferenceResult::default(),
216 var_unification_table: InPlaceUnificationTable::new(), 212 var_unification_table: InPlaceUnificationTable::new(),
217 obligations: Vec::default(), 213 obligations: Vec::default(),
218 return_ty: Ty::Unknown, // set in collect_fn_signature 214 return_ty: Ty::Unknown, // set in collect_fn_signature
219 trait_env: lower::trait_env(db, &resolver), 215 trait_env: TraitEnvironment::lower(db, &resolver),
220 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), 216 coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver),
221 db, 217 db,
222 owner, 218 owner,
@@ -244,20 +240,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
244 self.result.type_of_expr.insert(expr, ty); 240 self.result.type_of_expr.insert(expr, ty);
245 } 241 }
246 242
247 fn write_method_resolution(&mut self, expr: ExprId, func: Function) { 243 fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId) {
248 self.result.method_resolutions.insert(expr, func); 244 self.result.method_resolutions.insert(expr, func);
249 } 245 }
250 246
251 fn write_field_resolution(&mut self, expr: ExprId, field: StructField) { 247 fn write_field_resolution(&mut self, expr: ExprId, field: StructFieldId) {
252 self.result.field_resolutions.insert(expr, field); 248 self.result.field_resolutions.insert(expr, field);
253 } 249 }
254 250
255 fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantDef) { 251 fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {
256 self.result.variant_resolutions.insert(id, variant); 252 self.result.variant_resolutions.insert(id, variant);
257 } 253 }
258 254
259 fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItem) { 255 fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItemId) {
260 self.result.assoc_resolutions.insert(id, item); 256 self.result.assoc_resolutions.insert(id, item.into());
261 } 257 }
262 258
263 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { 259 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
@@ -515,51 +511,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
515 }) 511 })
516 } 512 }
517 513
518 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { 514 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
519 let path = match path { 515 let path = match path {
520 Some(path) => path, 516 Some(path) => path,
521 None => return (Ty::Unknown, None), 517 None => return (Ty::Unknown, None),
522 }; 518 };
523 let resolver = &self.resolver; 519 let resolver = &self.resolver;
524 let def: TypableDef = 520 // FIXME: this should resolve assoc items as well, see this example:
525 // FIXME: this should resolve assoc items as well, see this example: 521 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
526 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 522 match resolver.resolve_path_in_type_ns_fully(self.db, &path) {
527 match resolver.resolve_path_in_type_ns_fully(self.db, &path) { 523 Some(TypeNs::AdtId(AdtId::StructId(strukt))) => {
528 Some(TypeNs::AdtId(AdtId::StructId(it))) => it.into(), 524 let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into());
529 Some(TypeNs::AdtId(AdtId::UnionId(it))) => it.into(), 525 let ty = self.db.ty(strukt.into());
530 Some(TypeNs::AdtSelfType(adt)) => adt.into(),
531 Some(TypeNs::EnumVariantId(it)) => it.into(),
532 Some(TypeNs::TypeAliasId(it)) => it.into(),
533
534 Some(TypeNs::SelfType(_)) |
535 Some(TypeNs::GenericParam(_)) |
536 Some(TypeNs::BuiltinType(_)) |
537 Some(TypeNs::TraitId(_)) |
538 Some(TypeNs::AdtId(AdtId::EnumId(_))) |
539 None => {
540 return (Ty::Unknown, None)
541 }
542 };
543 // FIXME remove the duplication between here and `Ty::from_path`?
544 let substs = Ty::substs_from_path(self.db, resolver, path, def);
545 match def {
546 TypableDef::Adt(Adt::Struct(s)) => {
547 let ty = s.ty(self.db);
548 let ty = self.insert_type_vars(ty.apply_substs(substs)); 526 let ty = self.insert_type_vars(ty.apply_substs(substs));
549 (ty, Some(s.into())) 527 (ty, Some(strukt.into()))
550 } 528 }
551 TypableDef::EnumVariant(var) => { 529 Some(TypeNs::EnumVariantId(var)) => {
552 let ty = var.parent_enum(self.db).ty(self.db); 530 let substs = Ty::substs_from_path(self.db, resolver, path, var.into());
531 let ty = self.db.ty(var.parent.into());
553 let ty = self.insert_type_vars(ty.apply_substs(substs)); 532 let ty = self.insert_type_vars(ty.apply_substs(substs));
554 (ty, Some(var.into())) 533 (ty, Some(var.into()))
555 } 534 }
556 TypableDef::Adt(Adt::Enum(_)) 535 Some(_) | None => (Ty::Unknown, None),
557 | TypableDef::Adt(Adt::Union(_))
558 | TypableDef::TypeAlias(_)
559 | TypableDef::Function(_)
560 | TypableDef::Const(_)
561 | TypableDef::Static(_)
562 | TypableDef::BuiltinType(_) => (Ty::Unknown, None),
563 } 536 }
564 } 537 }
565 538
@@ -581,28 +554,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
581 self.infer_expr(self.body.body_expr, &Expectation::has_type(self.return_ty.clone())); 554 self.infer_expr(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
582 } 555 }
583 556
584 fn resolve_into_iter_item(&self) -> Option<TypeAlias> { 557 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
585 let path = known::std_iter_into_iterator(); 558 let path = known::std_iter_into_iterator();
586 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 559 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
587 trait_.associated_type_by_name(self.db, &name::ITEM_TYPE) 560 self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE)
588 } 561 }
589 562
590 fn resolve_ops_try_ok(&self) -> Option<TypeAlias> { 563 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
591 let path = known::std_ops_try(); 564 let path = known::std_ops_try();
592 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 565 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
593 trait_.associated_type_by_name(self.db, &name::OK_TYPE) 566 self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE)
594 } 567 }
595 568
596 fn resolve_future_future_output(&self) -> Option<TypeAlias> { 569 fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
597 let path = known::std_future_future(); 570 let path = known::std_future_future();
598 let trait_: Trait = self.resolver.resolve_known_trait(self.db, &path)?.into(); 571 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
599 trait_.associated_type_by_name(self.db, &name::OUTPUT_TYPE) 572 self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE)
600 } 573 }
601 574
602 fn resolve_boxed_box(&self) -> Option<Adt> { 575 fn resolve_boxed_box(&self) -> Option<AdtId> {
603 let path = known::std_boxed_box(); 576 let path = known::std_boxed_box();
604 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 577 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
605 Some(Adt::Struct(struct_.into())) 578 Some(struct_.into())
606 } 579 }
607} 580}
608 581
@@ -720,9 +693,10 @@ impl Expectation {
720} 693}
721 694
722mod diagnostics { 695mod diagnostics {
696 use hir_def::{expr::ExprId, FunctionId, HasSource, Lookup};
723 use hir_expand::diagnostics::DiagnosticSink; 697 use hir_expand::diagnostics::DiagnosticSink;
724 698
725 use crate::{db::HirDatabase, diagnostics::NoSuchField, expr::ExprId, Function, HasSource}; 699 use crate::{db::HirDatabase, diagnostics::NoSuchField};
726 700
727 #[derive(Debug, PartialEq, Eq, Clone)] 701 #[derive(Debug, PartialEq, Eq, Clone)]
728 pub(super) enum InferenceDiagnostic { 702 pub(super) enum InferenceDiagnostic {
@@ -733,13 +707,14 @@ mod diagnostics {
733 pub(super) fn add_to( 707 pub(super) fn add_to(
734 &self, 708 &self,
735 db: &impl HirDatabase, 709 db: &impl HirDatabase,
736 owner: Function, 710 owner: FunctionId,
737 sink: &mut DiagnosticSink, 711 sink: &mut DiagnosticSink,
738 ) { 712 ) {
739 match self { 713 match self {
740 InferenceDiagnostic::NoSuchField { expr, field } => { 714 InferenceDiagnostic::NoSuchField { expr, field } => {
741 let file = owner.source(db).file_id; 715 let file = owner.lookup(db).source(db).file_id;
742 let field = owner.body_source_map(db).field_syntax(*expr, *field); 716 let (_, source_map) = db.body_with_source_map(owner.into());
717 let field = source_map.field_syntax(*expr, *field);
743 sink.push(NoSuchField { file, field }) 718 sink.push(NoSuchField { file, field })
744 } 719 }
745 } 720 }
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 54765da35..719a0f395 100644
--- a/crates/ra_hir/src/ty/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -4,17 +4,13 @@
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, type_ref::Mutability, 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::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk};
12 db::HirDatabase,
13 ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk},
14 Adt, Mutability,
15};
16 12
17use super::{InferTy, InferenceContext, TypeVarValue}; 13use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
18 14
19impl<'a, D: HirDatabase> InferenceContext<'a, D> { 15impl<'a, D: HirDatabase> InferenceContext<'a, D> {
20 /// Unify two types, but may coerce the first one to the second one 16 /// Unify two types, but may coerce the first one to the second one
@@ -57,9 +53,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
57 53
58 impls 54 impls
59 .iter() 55 .iter()
60 .filter_map(|impl_block| { 56 .filter_map(|&impl_id| {
57 let trait_ref = match db.impl_ty(impl_id) {
58 ImplTy::TraitRef(it) => it,
59 ImplTy::Inherent(_) => return None,
60 };
61
61 // `CoerseUnsized` has one generic parameter for the target type. 62 // `CoerseUnsized` has one generic parameter for the target type.
62 let trait_ref = impl_block.target_trait_ref(db)?;
63 let cur_from_ty = trait_ref.substs.0.get(0)?; 63 let cur_from_ty = trait_ref.substs.0.get(0)?;
64 let cur_to_ty = trait_ref.substs.0.get(1)?; 64 let cur_to_ty = trait_ref.substs.0.get(1)?;
65 65
@@ -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.0); 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()?;
@@ -320,9 +320,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
320 let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); 320 let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone());
321 let to_ty = self.resolve_ty_shallow(&to_ty); 321 let to_ty = self.resolve_ty_shallow(&to_ty);
322 // FIXME: Auto DerefMut 322 // FIXME: Auto DerefMut
323 for derefed_ty in 323 for derefed_ty in autoderef::autoderef(
324 autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) 324 self.db,
325 { 325 self.resolver.krate(),
326 InEnvironment {
327 value: canonicalized.value.clone(),
328 environment: self.trait_env.clone(),
329 },
330 ) {
326 let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); 331 let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value);
327 match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { 332 match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) {
328 // Stop when constructor matches. 333 // Stop when constructor matches.
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 663ff9435..2f9ca4bbb 100644
--- a/crates/ra_hir/src/ty/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -5,21 +5,18 @@ use std::sync::Arc;
5 5
6use hir_def::{ 6use hir_def::{
7 builtin_type::Signedness, 7 builtin_type::Signedness,
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
8 generics::GenericParams, 9 generics::GenericParams,
9 path::{GenericArg, GenericArgs}, 10 path::{GenericArg, GenericArgs},
10 resolver::resolver_for_expr, 11 resolver::resolver_for_expr,
12 AdtId, ContainerId, Lookup, StructFieldId,
11}; 13};
12use hir_expand::name; 14use hir_expand::name::{self, Name};
13 15
14use crate::{ 16use crate::{
15 db::HirDatabase, 17 autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data,
16 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 18 CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs,
17 ty::{ 19 TraitRef, Ty, TypeCtor, TypeWalk, Uncertain,
18 autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace,
19 Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
20 Uncertain,
21 },
22 Adt, Name,
23}; 20};
24 21
25use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; 22use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
@@ -136,8 +133,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
136 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 133 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
137 Substs(sig_tys.into()), 134 Substs(sig_tys.into()),
138 ); 135 );
139 let closure_ty = 136 let closure_ty = Ty::apply_one(
140 Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); 137 TypeCtor::Closure { def: self.owner.into(), expr: tgt_expr },
138 sig_ty,
139 );
141 140
142 // Eagerly try to relate the closure type with the expected 141 // Eagerly try to relate the closure type with the expected
143 // type, otherwise we often won't have enough information to 142 // type, otherwise we often won't have enough information to
@@ -216,22 +215,26 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
216 let substs = ty.substs().unwrap_or_else(Substs::empty); 215 let substs = ty.substs().unwrap_or_else(Substs::empty);
217 let field_types = 216 let field_types =
218 def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default(); 217 def_id.map(|it| self.db.field_types(it.into())).unwrap_or_default();
218 let variant_data = def_id.map(|it| variant_data(self.db, it));
219 for (field_idx, field) in fields.iter().enumerate() { 219 for (field_idx, field) in fields.iter().enumerate() {
220 let field_def = def_id.and_then(|it| match it.field(self.db, &field.name) { 220 let field_def =
221 Some(field) => Some(field), 221 variant_data.as_ref().and_then(|it| match it.field(&field.name) {
222 None => { 222 Some(local_id) => {
223 self.push_diagnostic(InferenceDiagnostic::NoSuchField { 223 Some(StructFieldId { parent: def_id.unwrap(), local_id })
224 expr: tgt_expr, 224 }
225 field: field_idx, 225 None => {
226 }); 226 self.push_diagnostic(InferenceDiagnostic::NoSuchField {
227 None 227 expr: tgt_expr,
228 } 228 field: field_idx,
229 }); 229 });
230 None
231 }
232 });
230 if let Some(field_def) = field_def { 233 if let Some(field_def) = field_def {
231 self.result.record_field_resolutions.insert(field.expr, field_def); 234 self.result.record_field_resolutions.insert(field.expr, field_def);
232 } 235 }
233 let field_ty = field_def 236 let field_ty = field_def
234 .map_or(Ty::Unknown, |it| field_types[it.id].clone()) 237 .map_or(Ty::Unknown, |it| field_types[it.local_id].clone())
235 .subst(&substs); 238 .subst(&substs);
236 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); 239 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
237 } 240 }
@@ -245,20 +248,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
245 let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); 248 let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty);
246 let ty = autoderef::autoderef( 249 let ty = autoderef::autoderef(
247 self.db, 250 self.db,
248 &self.resolver.clone(), 251 self.resolver.krate(),
249 canonicalized.value.clone(), 252 InEnvironment {
253 value: canonicalized.value.clone(),
254 environment: self.trait_env.clone(),
255 },
250 ) 256 )
251 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { 257 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
252 Ty::Apply(a_ty) => match a_ty.ctor { 258 Ty::Apply(a_ty) => match a_ty.ctor {
253 TypeCtor::Tuple { .. } => name 259 TypeCtor::Tuple { .. } => name
254 .as_tuple_index() 260 .as_tuple_index()
255 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()), 261 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()),
256 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { 262 TypeCtor::Adt(AdtId::StructId(s)) => {
257 self.write_field_resolution(tgt_expr, field); 263 self.db.struct_data(s).variant_data.field(name).map(|local_id| {
258 self.db.field_types(s.id.into())[field.id] 264 let field = StructFieldId { parent: s.into(), local_id }.into();
259 .clone() 265 self.write_field_resolution(tgt_expr, field);
260 .subst(&a_ty.parameters) 266 self.db.field_types(s.into())[field.local_id]
261 }), 267 .clone()
268 .subst(&a_ty.parameters)
269 })
270 }
271 // FIXME:
272 TypeCtor::Adt(AdtId::UnionId(_)) => None,
262 _ => None, 273 _ => None,
263 }, 274 },
264 _ => None, 275 _ => None,
@@ -337,16 +348,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
337 Expr::UnaryOp { expr, op } => { 348 Expr::UnaryOp { expr, op } => {
338 let inner_ty = self.infer_expr(*expr, &Expectation::none()); 349 let inner_ty = self.infer_expr(*expr, &Expectation::none());
339 match op { 350 match op {
340 UnaryOp::Deref => { 351 UnaryOp::Deref => match self.resolver.krate() {
341 let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); 352 Some(krate) => {
342 if let Some(derefed_ty) = 353 let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty);
343 autoderef::deref(self.db, &self.resolver, &canonicalized.value) 354 match autoderef::deref(
344 { 355 self.db,
345 canonicalized.decanonicalize_ty(derefed_ty.value) 356 krate,
346 } else { 357 InEnvironment {
347 Ty::Unknown 358 value: &canonicalized.value,
359 environment: self.trait_env.clone(),
360 },
361 ) {
362 Some(derefed_ty) => {
363 canonicalized.decanonicalize_ty(derefed_ty.value)
364 }
365 None => Ty::Unknown,
366 }
348 } 367 }
349 } 368 None => Ty::Unknown,
369 },
350 UnaryOp::Neg => { 370 UnaryOp::Neg => {
351 match &inner_ty { 371 match &inner_ty {
352 Ty::Apply(a_ty) => match a_ty.ctor { 372 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -538,11 +558,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
538 Some((ty, func)) => { 558 Some((ty, func)) => {
539 let ty = canonicalized_receiver.decanonicalize_ty(ty); 559 let ty = canonicalized_receiver.decanonicalize_ty(ty);
540 self.write_method_resolution(tgt_expr, func); 560 self.write_method_resolution(tgt_expr, func);
541 ( 561 (ty, self.db.value_ty(func.into()), Some(self.db.generic_params(func.into())))
542 ty,
543 self.db.type_for_def(func.into(), Namespace::Values),
544 Some(self.db.generic_params(func.id.into())),
545 )
546 } 562 }
547 None => (receiver_ty, Ty::Unknown, None), 563 None => (receiver_ty, Ty::Unknown, None),
548 }; 564 };
@@ -648,18 +664,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
648 } 664 }
649 // add obligation for trait implementation, if this is a trait method 665 // add obligation for trait implementation, if this is a trait method
650 match def { 666 match def {
651 CallableDef::Function(f) => { 667 CallableDef::FunctionId(f) => {
652 if let Some(trait_) = f.parent_trait(self.db) { 668 if let ContainerId::TraitId(trait_) = f.lookup(self.db).container {
653 // construct a TraitDef 669 // construct a TraitDef
654 let substs = a_ty.parameters.prefix( 670 let substs = a_ty.parameters.prefix(
655 self.db 671 self.db
656 .generic_params(trait_.id.into()) 672 .generic_params(trait_.into())
657 .count_params_including_parent(), 673 .count_params_including_parent(),
658 ); 674 );
659 self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); 675 self.obligations.push(Obligation::Trait(TraitRef {
676 trait_: trait_.into(),
677 substs,
678 }));
660 } 679 }
661 } 680 }
662 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {} 681 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {}
663 } 682 }
664 } 683 }
665 } 684 }
diff --git a/crates/ra_hir/src/ty/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs
index 641d61e87..1ebb36239 100644
--- a/crates/ra_hir/src/ty/infer/pat.rs
+++ b/crates/ra_hir_ty/src/infer/pat.rs
@@ -3,15 +3,16 @@
3use std::iter::repeat; 3use std::iter::repeat;
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use hir_def::{
7 expr::{BindingAnnotation, Pat, PatId, RecordFieldPat},
8 path::Path,
9 type_ref::Mutability,
10};
11use hir_expand::name::Name;
6use test_utils::tested_by; 12use test_utils::tested_by;
7 13
8use super::{BindingMode, InferenceContext}; 14use super::{BindingMode, InferenceContext};
9use crate::{ 15use crate::{db::HirDatabase, utils::variant_data, Substs, Ty, TypeCtor, TypeWalk};
10 db::HirDatabase,
11 expr::{BindingAnnotation, Pat, PatId, RecordFieldPat},
12 ty::{Mutability, Substs, Ty, TypeCtor, TypeWalk},
13 Name, Path,
14};
15 16
16impl<'a, D: HirDatabase> InferenceContext<'a, D> { 17impl<'a, D: HirDatabase> InferenceContext<'a, D> {
17 fn infer_tuple_struct_pat( 18 fn infer_tuple_struct_pat(
@@ -22,16 +23,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
22 default_bm: BindingMode, 23 default_bm: BindingMode,
23 ) -> Ty { 24 ) -> Ty {
24 let (ty, def) = self.resolve_variant(path); 25 let (ty, def) = self.resolve_variant(path);
25 26 let var_data = def.map(|it| variant_data(self.db, it));
26 self.unify(&ty, expected); 27 self.unify(&ty, expected);
27 28
28 let substs = ty.substs().unwrap_or_else(Substs::empty); 29 let substs = ty.substs().unwrap_or_else(Substs::empty);
29 30
30 let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); 31 let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default();
32
31 for (i, &subpat) in subpats.iter().enumerate() { 33 for (i, &subpat) in subpats.iter().enumerate() {
32 let expected_ty = def 34 let expected_ty = var_data
33 .and_then(|d| d.field(self.db, &Name::new_tuple_field(i))) 35 .as_ref()
34 .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) 36 .and_then(|d| d.field(&Name::new_tuple_field(i)))
37 .map_or(Ty::Unknown, |field| field_tys[field].clone())
35 .subst(&substs); 38 .subst(&substs);
36 let expected_ty = self.normalize_associated_types_in(expected_ty); 39 let expected_ty = self.normalize_associated_types_in(expected_ty);
37 self.infer_pat(subpat, &expected_ty, default_bm); 40 self.infer_pat(subpat, &expected_ty, default_bm);
@@ -49,6 +52,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
49 id: PatId, 52 id: PatId,
50 ) -> Ty { 53 ) -> Ty {
51 let (ty, def) = self.resolve_variant(path); 54 let (ty, def) = self.resolve_variant(path);
55 let var_data = def.map(|it| variant_data(self.db, it));
52 if let Some(variant) = def { 56 if let Some(variant) = def {
53 self.write_variant_resolution(id.into(), variant); 57 self.write_variant_resolution(id.into(), variant);
54 } 58 }
@@ -59,10 +63,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
59 63
60 let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default(); 64 let field_tys = def.map(|it| self.db.field_types(it.into())).unwrap_or_default();
61 for subpat in subpats { 65 for subpat in subpats {
62 let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); 66 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
63 let expected_ty = matching_field 67 let expected_ty =
64 .map_or(Ty::Unknown, |field| field_tys[field.id].clone()) 68 matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone()).subst(&substs);
65 .subst(&substs);
66 let expected_ty = self.normalize_associated_types_in(expected_ty); 69 let expected_ty = self.normalize_associated_types_in(expected_ty);
67 self.infer_pat(subpat.pat, &expected_ty, default_bm); 70 self.infer_pat(subpat.pat, &expected_ty, default_bm);
68 } 71 }
diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index ee54d8217..14be66836 100644
--- a/crates/ra_hir/src/ty/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -1,15 +1,13 @@
1//! Path expression resolution. 1//! Path expression resolution.
2 2
3use hir_def::{ 3use hir_def::{
4 path::PathSegment, 4 path::{Path, PathKind, PathSegment},
5 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 5 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
6 AssocItemId, ContainerId, Lookup,
6}; 7};
8use hir_expand::name::Name;
7 9
8use crate::{ 10use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId};
9 db::HirDatabase,
10 ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk},
11 AssocItem, Container, Function, Name, Path,
12};
13 11
14use super::{ExprOrPatId, InferenceContext, TraitRef}; 12use super::{ExprOrPatId, InferenceContext, TraitRef};
15 13
@@ -32,7 +30,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
32 path: &Path, 30 path: &Path,
33 id: ExprOrPatId, 31 id: ExprOrPatId,
34 ) -> Option<Ty> { 32 ) -> Option<Ty> {
35 let (value, self_subst) = if let crate::PathKind::Type(type_ref) = &path.kind { 33 let (value, self_subst) = if let PathKind::Type(type_ref) = &path.kind {
36 if path.segments.is_empty() { 34 if path.segments.is_empty() {
37 // This can't actually happen syntax-wise 35 // This can't actually happen syntax-wise
38 return None; 36 return None;
@@ -56,7 +54,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
56 } 54 }
57 }; 55 };
58 56
59 let typable: TypableDef = match value { 57 let typable: ValueTyDefId = match value {
60 ValueNs::LocalBinding(pat) => { 58 ValueNs::LocalBinding(pat) => {
61 let ty = self.result.type_of_pat.get(pat)?.clone(); 59 let ty = self.result.type_of_pat.get(pat)?.clone();
62 let ty = self.resolve_ty_as_possible(&mut vec![], ty); 60 let ty = self.resolve_ty_as_possible(&mut vec![], ty);
@@ -69,11 +67,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
69 ValueNs::EnumVariantId(it) => it.into(), 67 ValueNs::EnumVariantId(it) => it.into(),
70 }; 68 };
71 69
72 let mut ty = self.db.type_for_def(typable, Namespace::Values); 70 let mut ty = self.db.value_ty(typable);
73 if let Some(self_subst) = self_subst { 71 if let Some(self_subst) = self_subst {
74 ty = ty.subst(&self_subst); 72 ty = ty.subst(&self_subst);
75 } 73 }
76
77 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); 74 let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable);
78 let ty = ty.subst(&substs); 75 let ty = ty.subst(&substs);
79 Some(ty) 76 Some(ty)
@@ -143,28 +140,35 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
143 id: ExprOrPatId, 140 id: ExprOrPatId,
144 ) -> Option<(ValueNs, Option<Substs>)> { 141 ) -> Option<(ValueNs, Option<Substs>)> {
145 let trait_ = trait_ref.trait_; 142 let trait_ = trait_ref.trait_;
146 let item = trait_.items(self.db).iter().copied().find_map(|item| match item { 143 let item = self
147 AssocItem::Function(func) => { 144 .db
148 if segment.name == func.name(self.db) { 145 .trait_data(trait_)
149 Some(AssocItem::Function(func)) 146 .items
150 } else { 147 .iter()
151 None 148 .map(|(_name, id)| (*id).into())
149 .find_map(|item| match item {
150 AssocItemId::FunctionId(func) => {
151 if segment.name == self.db.function_data(func).name {
152 Some(AssocItemId::FunctionId(func))
153 } else {
154 None
155 }
152 } 156 }
153 }
154 157
155 AssocItem::Const(konst) => { 158 AssocItemId::ConstId(konst) => {
156 if konst.name(self.db).map_or(false, |n| n == segment.name) { 159 if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == &segment.name)
157 Some(AssocItem::Const(konst)) 160 {
158 } else { 161 Some(AssocItemId::ConstId(konst))
159 None 162 } else {
163 None
164 }
160 } 165 }
161 } 166 AssocItemId::TypeAliasId(_) => None,
162 AssocItem::TypeAlias(_) => None, 167 })?;
163 })?;
164 let def = match item { 168 let def = match item {
165 AssocItem::Function(f) => ValueNs::FunctionId(f.id), 169 AssocItemId::FunctionId(f) => ValueNs::FunctionId(f),
166 AssocItem::Const(c) => ValueNs::ConstId(c.id), 170 AssocItemId::ConstId(c) => ValueNs::ConstId(c),
167 AssocItem::TypeAlias(_) => unreachable!(), 171 AssocItemId::TypeAliasId(_) => unreachable!(),
168 }; 172 };
169 let substs = Substs::build_for_def(self.db, item) 173 let substs = Substs::build_for_def(self.db, item)
170 .use_parent_substs(&trait_ref.substs) 174 .use_parent_substs(&trait_ref.substs)
@@ -194,16 +198,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
194 Some(name), 198 Some(name),
195 method_resolution::LookupMode::Path, 199 method_resolution::LookupMode::Path,
196 move |_ty, item| { 200 move |_ty, item| {
197 let def = match item { 201 let (def, container) = match item {
198 AssocItem::Function(f) => ValueNs::FunctionId(f.id), 202 AssocItemId::FunctionId(f) => {
199 AssocItem::Const(c) => ValueNs::ConstId(c.id), 203 (ValueNs::FunctionId(f), f.lookup(self.db).container)
200 AssocItem::TypeAlias(_) => unreachable!(), 204 }
205 AssocItemId::ConstId(c) => (ValueNs::ConstId(c), c.lookup(self.db).container),
206 AssocItemId::TypeAliasId(_) => unreachable!(),
201 }; 207 };
202 let substs = match item.container(self.db) { 208 let substs = match container {
203 Container::ImplBlock(_) => self.find_self_types(&def, ty.clone()), 209 ContainerId::ImplId(_) => self.find_self_types(&def, ty.clone()),
204 Container::Trait(t) => { 210 ContainerId::TraitId(trait_) => {
205 // we're picking this method 211 // we're picking this method
206 let trait_substs = Substs::build_for_def(self.db, t) 212 let trait_substs = Substs::build_for_def(self.db, trait_)
207 .push(ty.clone()) 213 .push(ty.clone())
208 .fill(std::iter::repeat_with(|| self.new_type_var())) 214 .fill(std::iter::repeat_with(|| self.new_type_var()))
209 .build(); 215 .build();
@@ -212,37 +218,41 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
212 .fill_with_params() 218 .fill_with_params()
213 .build(); 219 .build();
214 self.obligations.push(super::Obligation::Trait(TraitRef { 220 self.obligations.push(super::Obligation::Trait(TraitRef {
215 trait_: t, 221 trait_,
216 substs: trait_substs, 222 substs: trait_substs,
217 })); 223 }));
218 Some(substs) 224 Some(substs)
219 } 225 }
226 ContainerId::ModuleId(_) => None,
220 }; 227 };
221 228
222 self.write_assoc_resolution(id, item); 229 self.write_assoc_resolution(id, item.into());
223 Some((def, substs)) 230 Some((def, substs))
224 }, 231 },
225 ) 232 )
226 } 233 }
227 234
228 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> { 235 fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option<Substs> {
229 if let ValueNs::FunctionId(func) = def { 236 if let ValueNs::FunctionId(func) = *def {
230 let func = Function::from(*func);
231 // We only do the infer if parent has generic params 237 // We only do the infer if parent has generic params
232 let gen = self.db.generic_params(func.id.into()); 238 let gen = self.db.generic_params(func.into());
233 if gen.count_parent_params() == 0 { 239 if gen.count_parent_params() == 0 {
234 return None; 240 return None;
235 } 241 }
236 242
237 let impl_block = func.impl_block(self.db)?.target_ty(self.db); 243 let impl_id = match func.lookup(self.db).container {
238 let impl_block_substs = impl_block.substs()?; 244 ContainerId::ImplId(it) => it,
245 _ => return None,
246 };
247 let self_ty = self.db.impl_ty(impl_id).self_type().clone();
248 let self_ty_substs = self_ty.substs()?;
239 let actual_substs = actual_def_ty.substs()?; 249 let actual_substs = actual_def_ty.substs()?;
240 250
241 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()]; 251 let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()];
242 252
243 // The following code *link up* the function actual parma type 253 // The following code *link up* the function actual parma type
244 // and impl_block type param index 254 // and impl_block type param index
245 impl_block_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| { 255 self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| {
246 if let Ty::Param { idx, .. } = param { 256 if let Ty::Param { idx, .. } = param {
247 if let Some(s) = new_substs.get_mut(*idx as usize) { 257 if let Some(s) = new_substs.get_mut(*idx as usize) {
248 *s = pty.clone(); 258 *s = pty.clone();
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index 64d9394cf..f3a875678 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -1,12 +1,10 @@
1//! Unification and canonicalization logic. 1//! Unification and canonicalization logic.
2 2
3use super::{InferenceContext, Obligation}; 3use super::{InferenceContext, Obligation};
4use crate::db::HirDatabase; 4use crate::{
5use crate::ty::{ 5 db::HirDatabase, utils::make_mut_slice, Canonical, InEnvironment, InferTy, ProjectionPredicate,
6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, 6 ProjectionTy, Substs, TraitRef, Ty, TypeWalk,
7 TypeWalk,
8}; 7};
9use crate::util::make_mut_slice;
10 8
11impl<'a, D: HirDatabase> InferenceContext<'a, D> { 9impl<'a, D: HirDatabase> InferenceContext<'a, D> {
12 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b, D> 10 pub(super) fn canonicalizer<'b>(&'b mut self) -> Canonicalizer<'a, 'b, D>
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
new file mode 100644
index 000000000..b45c8f82f
--- /dev/null
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -0,0 +1,1138 @@
1//! The type system. We currently use this to infer types for completion, hover
2//! information and various assists.
3
4macro_rules! impl_froms {
5 ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => {
6 $(
7 impl From<$v> for $e {
8 fn from(it: $v) -> $e {
9 $e::$v(it)
10 }
11 }
12 $($(
13 impl From<$sv> for $e {
14 fn from(it: $sv) -> $e {
15 $e::$v($v::$sv(it))
16 }
17 }
18 )*)?
19 )*
20 }
21}
22
23mod autoderef;
24pub mod primitive;
25pub mod traits;
26pub mod method_resolution;
27mod op;
28mod lower;
29mod infer;
30pub mod display;
31pub(crate) mod utils;
32pub mod db;
33pub mod diagnostics;
34pub mod expr;
35
36#[cfg(test)]
37mod tests;
38#[cfg(test)]
39mod test_db;
40mod marks;
41
42use std::ops::Deref;
43use std::sync::Arc;
44use std::{fmt, iter, mem};
45
46use hir_def::{
47 expr::ExprId, generics::GenericParams, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId,
48 GenericDefId, HasModule, Lookup, TraitId, TypeAliasId,
49};
50use hir_expand::name::Name;
51use ra_db::{impl_intern_key, salsa, CrateId};
52
53use crate::{
54 db::HirDatabase,
55 primitive::{FloatTy, IntTy, Uncertain},
56 utils::make_mut_slice,
57};
58use display::{HirDisplay, HirFormatter};
59
60pub use autoderef::autoderef;
61pub use infer::{infer_query, InferTy, InferenceResult};
62pub use lower::CallableDef;
63pub use lower::{callable_item_sig, TyDefId, ValueTyDefId};
64pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
65
66/// A type constructor or type name: this might be something like the primitive
67/// type `bool`, a struct like `Vec`, or things like function pointers or
68/// tuples.
69#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
70pub enum TypeCtor {
71 /// The primitive boolean type. Written as `bool`.
72 Bool,
73
74 /// The primitive character type; holds a Unicode scalar value
75 /// (a non-surrogate code point). Written as `char`.
76 Char,
77
78 /// A primitive integer type. For example, `i32`.
79 Int(Uncertain<IntTy>),
80
81 /// A primitive floating-point type. For example, `f64`.
82 Float(Uncertain<FloatTy>),
83
84 /// Structures, enumerations and unions.
85 Adt(AdtId),
86
87 /// The pointee of a string slice. Written as `str`.
88 Str,
89
90 /// The pointee of an array slice. Written as `[T]`.
91 Slice,
92
93 /// An array with the given length. Written as `[T; n]`.
94 Array,
95
96 /// A raw pointer. Written as `*mut T` or `*const T`
97 RawPtr(Mutability),
98
99 /// A reference; a pointer with an associated lifetime. Written as
100 /// `&'a mut T` or `&'a T`.
101 Ref(Mutability),
102
103 /// The anonymous type of a function declaration/definition. Each
104 /// function has a unique type, which is output (for a function
105 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
106 ///
107 /// This includes tuple struct / enum variant constructors as well.
108 ///
109 /// For example the type of `bar` here:
110 ///
111 /// ```
112 /// fn foo() -> i32 { 1 }
113 /// let bar = foo; // bar: fn() -> i32 {foo}
114 /// ```
115 FnDef(CallableDef),
116
117 /// A pointer to a function. Written as `fn() -> i32`.
118 ///
119 /// For example the type of `bar` here:
120 ///
121 /// ```
122 /// fn foo() -> i32 { 1 }
123 /// let bar: fn() -> i32 = foo;
124 /// ```
125 FnPtr { num_args: u16 },
126
127 /// The never type `!`.
128 Never,
129
130 /// A tuple type. For example, `(i32, bool)`.
131 Tuple { cardinality: u16 },
132
133 /// Represents an associated item like `Iterator::Item`. This is used
134 /// when we have tried to normalize a projection like `T::Item` but
135 /// couldn't find a better representation. In that case, we generate
136 /// an **application type** like `(Iterator::Item)<T>`.
137 AssociatedType(TypeAliasId),
138
139 /// The type of a specific closure.
140 ///
141 /// The closure signature is stored in a `FnPtr` type in the first type
142 /// parameter.
143 Closure { def: DefWithBodyId, expr: ExprId },
144}
145
146/// This exists just for Chalk, because Chalk just has a single `StructId` where
147/// we have different kinds of ADTs, primitive types and special type
148/// constructors like tuples and function pointers.
149#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
150pub struct TypeCtorId(salsa::InternId);
151impl_intern_key!(TypeCtorId);
152
153impl TypeCtor {
154 pub fn num_ty_params(self, db: &impl HirDatabase) -> usize {
155 match self {
156 TypeCtor::Bool
157 | TypeCtor::Char
158 | TypeCtor::Int(_)
159 | TypeCtor::Float(_)
160 | TypeCtor::Str
161 | TypeCtor::Never => 0,
162 TypeCtor::Slice
163 | TypeCtor::Array
164 | TypeCtor::RawPtr(_)
165 | TypeCtor::Ref(_)
166 | TypeCtor::Closure { .. } // 1 param representing the signature of the closure
167 => 1,
168 TypeCtor::Adt(adt) => {
169 let generic_params = db.generic_params(AdtId::from(adt).into());
170 generic_params.count_params_including_parent()
171 }
172 TypeCtor::FnDef(callable) => {
173 let generic_params = db.generic_params(callable.into());
174 generic_params.count_params_including_parent()
175 }
176 TypeCtor::AssociatedType(type_alias) => {
177 let generic_params = db.generic_params(type_alias.into());
178 generic_params.count_params_including_parent()
179 }
180 TypeCtor::FnPtr { num_args } => num_args as usize + 1,
181 TypeCtor::Tuple { cardinality } => cardinality as usize,
182 }
183 }
184
185 pub fn krate(self, db: &impl HirDatabase) -> Option<CrateId> {
186 match self {
187 TypeCtor::Bool
188 | TypeCtor::Char
189 | TypeCtor::Int(_)
190 | TypeCtor::Float(_)
191 | TypeCtor::Str
192 | TypeCtor::Never
193 | TypeCtor::Slice
194 | TypeCtor::Array
195 | TypeCtor::RawPtr(_)
196 | TypeCtor::Ref(_)
197 | TypeCtor::FnPtr { .. }
198 | TypeCtor::Tuple { .. } => None,
199 // Closure's krate is irrelevant for coherence I would think?
200 TypeCtor::Closure { .. } => None,
201 TypeCtor::Adt(adt) => Some(adt.module(db).krate),
202 TypeCtor::FnDef(callable) => Some(callable.krate(db)),
203 TypeCtor::AssociatedType(type_alias) => Some(type_alias.lookup(db).module(db).krate),
204 }
205 }
206
207 pub fn as_generic_def(self) -> Option<GenericDefId> {
208 match self {
209 TypeCtor::Bool
210 | TypeCtor::Char
211 | TypeCtor::Int(_)
212 | TypeCtor::Float(_)
213 | TypeCtor::Str
214 | TypeCtor::Never
215 | TypeCtor::Slice
216 | TypeCtor::Array
217 | TypeCtor::RawPtr(_)
218 | TypeCtor::Ref(_)
219 | TypeCtor::FnPtr { .. }
220 | TypeCtor::Tuple { .. }
221 | TypeCtor::Closure { .. } => None,
222 TypeCtor::Adt(adt) => Some(adt.into()),
223 TypeCtor::FnDef(callable) => Some(callable.into()),
224 TypeCtor::AssociatedType(type_alias) => Some(type_alias.into()),
225 }
226 }
227}
228
229/// A nominal type with (maybe 0) type parameters. This might be a primitive
230/// type like `bool`, a struct, tuple, function pointer, reference or
231/// several other things.
232#[derive(Clone, PartialEq, Eq, Debug, Hash)]
233pub struct ApplicationTy {
234 pub ctor: TypeCtor,
235 pub parameters: Substs,
236}
237
238/// A "projection" type corresponds to an (unnormalized)
239/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
240/// trait and all its parameters are fully known.
241#[derive(Clone, PartialEq, Eq, Debug, Hash)]
242pub struct ProjectionTy {
243 pub associated_ty: TypeAliasId,
244 pub parameters: Substs,
245}
246
247impl ProjectionTy {
248 pub fn trait_ref(&self, db: &impl HirDatabase) -> TraitRef {
249 TraitRef { trait_: self.trait_(db).into(), substs: self.parameters.clone() }
250 }
251
252 fn trait_(&self, db: &impl HirDatabase) -> TraitId {
253 match self.associated_ty.lookup(db).container {
254 ContainerId::TraitId(it) => it,
255 _ => panic!("projection ty without parent trait"),
256 }
257 }
258}
259
260impl TypeWalk for ProjectionTy {
261 fn walk(&self, f: &mut impl FnMut(&Ty)) {
262 self.parameters.walk(f);
263 }
264
265 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
266 self.parameters.walk_mut_binders(f, binders);
267 }
268}
269
270/// A type.
271///
272/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
273/// the same thing (but in a different way).
274///
275/// This should be cheap to clone.
276#[derive(Clone, PartialEq, Eq, Debug, Hash)]
277pub enum Ty {
278 /// A nominal type with (maybe 0) type parameters. This might be a primitive
279 /// type like `bool`, a struct, tuple, function pointer, reference or
280 /// several other things.
281 Apply(ApplicationTy),
282
283 /// A "projection" type corresponds to an (unnormalized)
284 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
285 /// trait and all its parameters are fully known.
286 Projection(ProjectionTy),
287
288 /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
289 Param {
290 /// The index of the parameter (starting with parameters from the
291 /// surrounding impl, then the current function).
292 idx: u32,
293 /// The name of the parameter, for displaying.
294 // FIXME get rid of this
295 name: Name,
296 },
297
298 /// A bound type variable. Used during trait resolution to represent Chalk
299 /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type.
300 Bound(u32),
301
302 /// A type variable used during type checking. Not to be confused with a
303 /// type parameter.
304 Infer(InferTy),
305
306 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
307 ///
308 /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
309 /// represents the `Self` type inside the bounds. This is currently
310 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
311 /// didn't seem worth the overhead yet.
312 Dyn(Arc<[GenericPredicate]>),
313
314 /// An opaque type (`impl Trait`).
315 ///
316 /// The predicates are quantified over the `Self` type; see `Ty::Dyn` for
317 /// more.
318 Opaque(Arc<[GenericPredicate]>),
319
320 /// A placeholder for a type which could not be computed; this is propagated
321 /// to avoid useless error messages. Doubles as a placeholder where type
322 /// variables are inserted before type checking, since we want to try to
323 /// infer a better type here anyway -- for the IDE use case, we want to try
324 /// to infer as much as possible even in the presence of type errors.
325 Unknown,
326}
327
328/// A list of substitutions for generic parameters.
329#[derive(Clone, PartialEq, Eq, Debug, Hash)]
330pub struct Substs(Arc<[Ty]>);
331
332impl TypeWalk for Substs {
333 fn walk(&self, f: &mut impl FnMut(&Ty)) {
334 for t in self.0.iter() {
335 t.walk(f);
336 }
337 }
338
339 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
340 for t in make_mut_slice(&mut self.0) {
341 t.walk_mut_binders(f, binders);
342 }
343 }
344}
345
346impl Substs {
347 pub fn empty() -> Substs {
348 Substs(Arc::new([]))
349 }
350
351 pub fn single(ty: Ty) -> Substs {
352 Substs(Arc::new([ty]))
353 }
354
355 pub fn prefix(&self, n: usize) -> Substs {
356 Substs(self.0[..std::cmp::min(self.0.len(), n)].into())
357 }
358
359 pub fn as_single(&self) -> &Ty {
360 if self.0.len() != 1 {
361 panic!("expected substs of len 1, got {:?}", self);
362 }
363 &self.0[0]
364 }
365
366 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
367 pub fn identity(generic_params: &GenericParams) -> Substs {
368 Substs(
369 generic_params
370 .params_including_parent()
371 .into_iter()
372 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
373 .collect(),
374 )
375 }
376
377 /// Return Substs that replace each parameter by a bound variable.
378 pub fn bound_vars(generic_params: &GenericParams) -> Substs {
379 Substs(
380 generic_params
381 .params_including_parent()
382 .into_iter()
383 .map(|p| Ty::Bound(p.idx))
384 .collect(),
385 )
386 }
387
388 pub fn build_for_def(db: &impl HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
389 let def = def.into();
390 let params = db.generic_params(def);
391 let param_count = params.count_params_including_parent();
392 Substs::builder(param_count)
393 }
394
395 pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder {
396 Substs::builder(generic_params.count_params_including_parent())
397 }
398
399 pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder {
400 Substs::builder(type_ctor.num_ty_params(db))
401 }
402
403 fn builder(param_count: usize) -> SubstsBuilder {
404 SubstsBuilder { vec: Vec::with_capacity(param_count), param_count }
405 }
406}
407
408#[derive(Debug, Clone)]
409pub struct SubstsBuilder {
410 vec: Vec<Ty>,
411 param_count: usize,
412}
413
414impl SubstsBuilder {
415 pub fn build(self) -> Substs {
416 assert_eq!(self.vec.len(), self.param_count);
417 Substs(self.vec.into())
418 }
419
420 pub fn push(mut self, ty: Ty) -> Self {
421 self.vec.push(ty);
422 self
423 }
424
425 fn remaining(&self) -> usize {
426 self.param_count - self.vec.len()
427 }
428
429 pub fn fill_with_bound_vars(self, starting_from: u32) -> Self {
430 self.fill((starting_from..).map(Ty::Bound))
431 }
432
433 pub fn fill_with_params(self) -> Self {
434 let start = self.vec.len() as u32;
435 self.fill((start..).map(|idx| Ty::Param { idx, name: Name::missing() }))
436 }
437
438 pub fn fill_with_unknown(self) -> Self {
439 self.fill(iter::repeat(Ty::Unknown))
440 }
441
442 pub fn fill(mut self, filler: impl Iterator<Item = Ty>) -> Self {
443 self.vec.extend(filler.take(self.remaining()));
444 assert_eq!(self.remaining(), 0);
445 self
446 }
447
448 pub fn use_parent_substs(mut self, parent_substs: &Substs) -> Self {
449 assert!(self.vec.is_empty());
450 assert!(parent_substs.len() <= self.param_count);
451 self.vec.extend(parent_substs.iter().cloned());
452 self
453 }
454}
455
456impl Deref for Substs {
457 type Target = [Ty];
458
459 fn deref(&self) -> &[Ty] {
460 &self.0
461 }
462}
463
464/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
465/// Name to be bikeshedded: TraitBound? TraitImplements?
466#[derive(Clone, PartialEq, Eq, Debug, Hash)]
467pub struct TraitRef {
468 /// FIXME name?
469 pub trait_: TraitId,
470 pub substs: Substs,
471}
472
473impl TraitRef {
474 pub fn self_ty(&self) -> &Ty {
475 &self.substs[0]
476 }
477}
478
479impl TypeWalk for TraitRef {
480 fn walk(&self, f: &mut impl FnMut(&Ty)) {
481 self.substs.walk(f);
482 }
483
484 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
485 self.substs.walk_mut_binders(f, binders);
486 }
487}
488
489#[derive(Clone, PartialEq, Eq, Debug)]
490pub enum ImplTy {
491 Inherent(Ty),
492 TraitRef(TraitRef),
493}
494
495impl ImplTy {
496 pub(crate) fn self_type(&self) -> &Ty {
497 match self {
498 ImplTy::Inherent(it) => it,
499 ImplTy::TraitRef(tr) => &tr.substs[0],
500 }
501 }
502}
503
504/// Like `generics::WherePredicate`, but with resolved types: A condition on the
505/// parameters of a generic item.
506#[derive(Debug, Clone, PartialEq, Eq, Hash)]
507pub enum GenericPredicate {
508 /// The given trait needs to be implemented for its type parameters.
509 Implemented(TraitRef),
510 /// An associated type bindings like in `Iterator<Item = T>`.
511 Projection(ProjectionPredicate),
512 /// We couldn't resolve the trait reference. (If some type parameters can't
513 /// be resolved, they will just be Unknown).
514 Error,
515}
516
517impl GenericPredicate {
518 pub fn is_error(&self) -> bool {
519 match self {
520 GenericPredicate::Error => true,
521 _ => false,
522 }
523 }
524
525 pub fn is_implemented(&self) -> bool {
526 match self {
527 GenericPredicate::Implemented(_) => true,
528 _ => false,
529 }
530 }
531
532 pub fn trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
533 match self {
534 GenericPredicate::Implemented(tr) => Some(tr.clone()),
535 GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)),
536 GenericPredicate::Error => None,
537 }
538 }
539}
540
541impl TypeWalk for GenericPredicate {
542 fn walk(&self, f: &mut impl FnMut(&Ty)) {
543 match self {
544 GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
545 GenericPredicate::Projection(projection_pred) => projection_pred.walk(f),
546 GenericPredicate::Error => {}
547 }
548 }
549
550 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
551 match self {
552 GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
553 GenericPredicate::Projection(projection_pred) => {
554 projection_pred.walk_mut_binders(f, binders)
555 }
556 GenericPredicate::Error => {}
557 }
558 }
559}
560
561/// Basically a claim (currently not validated / checked) that the contained
562/// type / trait ref contains no inference variables; any inference variables it
563/// contained have been replaced by bound variables, and `num_vars` tells us how
564/// many there are. This is used to erase irrelevant differences between types
565/// before using them in queries.
566#[derive(Debug, Clone, PartialEq, Eq, Hash)]
567pub struct Canonical<T> {
568 pub value: T,
569 pub num_vars: usize,
570}
571
572/// A function signature as seen by type inference: Several parameter types and
573/// one return type.
574#[derive(Clone, PartialEq, Eq, Debug)]
575pub struct FnSig {
576 params_and_return: Arc<[Ty]>,
577}
578
579impl FnSig {
580 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig {
581 params.push(ret);
582 FnSig { params_and_return: params.into() }
583 }
584
585 pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig {
586 FnSig { params_and_return: Arc::clone(&substs.0) }
587 }
588
589 pub fn params(&self) -> &[Ty] {
590 &self.params_and_return[0..self.params_and_return.len() - 1]
591 }
592
593 pub fn ret(&self) -> &Ty {
594 &self.params_and_return[self.params_and_return.len() - 1]
595 }
596}
597
598impl TypeWalk for FnSig {
599 fn walk(&self, f: &mut impl FnMut(&Ty)) {
600 for t in self.params_and_return.iter() {
601 t.walk(f);
602 }
603 }
604
605 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
606 for t in make_mut_slice(&mut self.params_and_return) {
607 t.walk_mut_binders(f, binders);
608 }
609 }
610}
611
612impl Ty {
613 pub fn simple(ctor: TypeCtor) -> Ty {
614 Ty::Apply(ApplicationTy { ctor, parameters: Substs::empty() })
615 }
616 pub fn apply_one(ctor: TypeCtor, param: Ty) -> Ty {
617 Ty::Apply(ApplicationTy { ctor, parameters: Substs::single(param) })
618 }
619 pub fn apply(ctor: TypeCtor, parameters: Substs) -> Ty {
620 Ty::Apply(ApplicationTy { ctor, parameters })
621 }
622 pub fn unit() -> Self {
623 Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty())
624 }
625
626 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
627 match self {
628 Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => {
629 Some((parameters.as_single(), *mutability))
630 }
631 _ => None,
632 }
633 }
634
635 pub fn as_adt(&self) -> Option<(AdtId, &Substs)> {
636 match self {
637 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_def), parameters }) => {
638 Some((*adt_def, parameters))
639 }
640 _ => None,
641 }
642 }
643
644 pub fn as_tuple(&self) -> Option<&Substs> {
645 match self {
646 Ty::Apply(ApplicationTy { ctor: TypeCtor::Tuple { .. }, parameters }) => {
647 Some(parameters)
648 }
649 _ => None,
650 }
651 }
652
653 pub fn as_callable(&self) -> Option<(CallableDef, &Substs)> {
654 match self {
655 Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(callable_def), parameters }) => {
656 Some((*callable_def, parameters))
657 }
658 _ => None,
659 }
660 }
661
662 fn builtin_deref(&self) -> Option<Ty> {
663 match self {
664 Ty::Apply(a_ty) => match a_ty.ctor {
665 TypeCtor::Ref(..) => Some(Ty::clone(a_ty.parameters.as_single())),
666 TypeCtor::RawPtr(..) => Some(Ty::clone(a_ty.parameters.as_single())),
667 _ => None,
668 },
669 _ => None,
670 }
671 }
672
673 fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
674 match self {
675 Ty::Apply(a_ty) => match a_ty.ctor {
676 TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)),
677 TypeCtor::FnDef(def) => {
678 let sig = db.callable_item_signature(def);
679 Some(sig.subst(&a_ty.parameters))
680 }
681 TypeCtor::Closure { .. } => {
682 let sig_param = &a_ty.parameters[0];
683 sig_param.callable_sig(db)
684 }
685 _ => None,
686 },
687 _ => None,
688 }
689 }
690
691 /// If this is a type with type parameters (an ADT or function), replaces
692 /// the `Substs` for these type parameters with the given ones. (So e.g. if
693 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
694 /// `Option<u32>` afterwards.)
695 pub fn apply_substs(self, substs: Substs) -> Ty {
696 match self {
697 Ty::Apply(ApplicationTy { ctor, parameters: previous_substs }) => {
698 assert_eq!(previous_substs.len(), substs.len());
699 Ty::Apply(ApplicationTy { ctor, parameters: substs })
700 }
701 _ => self,
702 }
703 }
704
705 /// Returns the type parameters of this type if it has some (i.e. is an ADT
706 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
707 pub fn substs(&self) -> Option<Substs> {
708 match self {
709 Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()),
710 _ => None,
711 }
712 }
713
714 /// If this is an `impl Trait` or `dyn Trait`, returns that trait.
715 pub fn inherent_trait(&self) -> Option<TraitId> {
716 match self {
717 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
718 predicates.iter().find_map(|pred| match pred {
719 GenericPredicate::Implemented(tr) => Some(tr.trait_),
720 _ => None,
721 })
722 }
723 _ => None,
724 }
725 }
726}
727
728/// This allows walking structures that contain types to do something with those
729/// types, similar to Chalk's `Fold` trait.
730pub trait TypeWalk {
731 fn walk(&self, f: &mut impl FnMut(&Ty));
732 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
733 self.walk_mut_binders(&mut |ty, _binders| f(ty), 0);
734 }
735 /// Walk the type, counting entered binders.
736 ///
737 /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers
738 /// to the innermost binder, 1 to the next, etc.. So when we want to
739 /// substitute a certain bound variable, we can't just walk the whole type
740 /// and blindly replace each instance of a certain index; when we 'enter'
741 /// things that introduce new bound variables, we have to keep track of
742 /// that. Currently, the only thing that introduces bound variables on our
743 /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound
744 /// variable for the self type.
745 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize);
746
747 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
748 where
749 Self: Sized,
750 {
751 self.walk_mut(&mut |ty_mut| {
752 let ty = mem::replace(ty_mut, Ty::Unknown);
753 *ty_mut = f(ty);
754 });
755 self
756 }
757
758 /// Replaces type parameters in this type using the given `Substs`. (So e.g.
759 /// if `self` is `&[T]`, where type parameter T has index 0, and the
760 /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
761 fn subst(self, substs: &Substs) -> Self
762 where
763 Self: Sized,
764 {
765 self.fold(&mut |ty| match ty {
766 Ty::Param { idx, name } => {
767 substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name })
768 }
769 ty => ty,
770 })
771 }
772
773 /// Substitutes `Ty::Bound` vars (as opposed to type parameters).
774 fn subst_bound_vars(mut self, substs: &Substs) -> Self
775 where
776 Self: Sized,
777 {
778 self.walk_mut_binders(
779 &mut |ty, binders| match ty {
780 &mut Ty::Bound(idx) => {
781 if idx as usize >= binders && (idx as usize - binders) < substs.len() {
782 *ty = substs.0[idx as usize - binders].clone();
783 }
784 }
785 _ => {}
786 },
787 0,
788 );
789 self
790 }
791
792 /// Shifts up `Ty::Bound` vars by `n`.
793 fn shift_bound_vars(self, n: i32) -> Self
794 where
795 Self: Sized,
796 {
797 self.fold(&mut |ty| match ty {
798 Ty::Bound(idx) => {
799 assert!(idx as i32 >= -n);
800 Ty::Bound((idx as i32 + n) as u32)
801 }
802 ty => ty,
803 })
804 }
805}
806
807impl TypeWalk for Ty {
808 fn walk(&self, f: &mut impl FnMut(&Ty)) {
809 match self {
810 Ty::Apply(a_ty) => {
811 for t in a_ty.parameters.iter() {
812 t.walk(f);
813 }
814 }
815 Ty::Projection(p_ty) => {
816 for t in p_ty.parameters.iter() {
817 t.walk(f);
818 }
819 }
820 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
821 for p in predicates.iter() {
822 p.walk(f);
823 }
824 }
825 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
826 }
827 f(self);
828 }
829
830 fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) {
831 match self {
832 Ty::Apply(a_ty) => {
833 a_ty.parameters.walk_mut_binders(f, binders);
834 }
835 Ty::Projection(p_ty) => {
836 p_ty.parameters.walk_mut_binders(f, binders);
837 }
838 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
839 for p in make_mut_slice(predicates) {
840 p.walk_mut_binders(f, binders + 1);
841 }
842 }
843 Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
844 }
845 f(self, binders);
846 }
847}
848
849impl HirDisplay for &Ty {
850 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
851 HirDisplay::hir_fmt(*self, f)
852 }
853}
854
855impl HirDisplay for ApplicationTy {
856 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
857 if f.should_truncate() {
858 return write!(f, "…");
859 }
860
861 match self.ctor {
862 TypeCtor::Bool => write!(f, "bool")?,
863 TypeCtor::Char => write!(f, "char")?,
864 TypeCtor::Int(t) => write!(f, "{}", t)?,
865 TypeCtor::Float(t) => write!(f, "{}", t)?,
866 TypeCtor::Str => write!(f, "str")?,
867 TypeCtor::Slice => {
868 let t = self.parameters.as_single();
869 write!(f, "[{}]", t.display(f.db))?;
870 }
871 TypeCtor::Array => {
872 let t = self.parameters.as_single();
873 write!(f, "[{};_]", t.display(f.db))?;
874 }
875 TypeCtor::RawPtr(m) => {
876 let t = self.parameters.as_single();
877 write!(f, "*{}{}", m.as_keyword_for_ptr(), t.display(f.db))?;
878 }
879 TypeCtor::Ref(m) => {
880 let t = self.parameters.as_single();
881 write!(f, "&{}{}", m.as_keyword_for_ref(), t.display(f.db))?;
882 }
883 TypeCtor::Never => write!(f, "!")?,
884 TypeCtor::Tuple { .. } => {
885 let ts = &self.parameters;
886 if ts.len() == 1 {
887 write!(f, "({},)", ts[0].display(f.db))?;
888 } else {
889 write!(f, "(")?;
890 f.write_joined(&*ts.0, ", ")?;
891 write!(f, ")")?;
892 }
893 }
894 TypeCtor::FnPtr { .. } => {
895 let sig = FnSig::from_fn_ptr_substs(&self.parameters);
896 write!(f, "fn(")?;
897 f.write_joined(sig.params(), ", ")?;
898 write!(f, ") -> {}", sig.ret().display(f.db))?;
899 }
900 TypeCtor::FnDef(def) => {
901 let sig = f.db.callable_item_signature(def);
902 let name = match def {
903 CallableDef::FunctionId(ff) => f.db.function_data(ff).name.clone(),
904 CallableDef::StructId(s) => f.db.struct_data(s).name.clone(),
905 CallableDef::EnumVariantId(e) => {
906 let enum_data = f.db.enum_data(e.parent);
907 enum_data.variants[e.local_id].name.clone()
908 }
909 };
910 match def {
911 CallableDef::FunctionId(_) => write!(f, "fn {}", name)?,
912 CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {
913 write!(f, "{}", name)?
914 }
915 }
916 if self.parameters.len() > 0 {
917 write!(f, "<")?;
918 f.write_joined(&*self.parameters.0, ", ")?;
919 write!(f, ">")?;
920 }
921 write!(f, "(")?;
922 f.write_joined(sig.params(), ", ")?;
923 write!(f, ") -> {}", sig.ret().display(f.db))?;
924 }
925 TypeCtor::Adt(def_id) => {
926 let name = match def_id {
927 AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
928 AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
929 AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
930 };
931 write!(f, "{}", name)?;
932 if self.parameters.len() > 0 {
933 write!(f, "<")?;
934 f.write_joined(&*self.parameters.0, ", ")?;
935 write!(f, ">")?;
936 }
937 }
938 TypeCtor::AssociatedType(type_alias) => {
939 let trait_ = match type_alias.lookup(f.db).container {
940 ContainerId::TraitId(it) => it,
941 _ => panic!("not an associated type"),
942 };
943 let trait_name = f.db.trait_data(trait_).name.clone();
944 let name = f.db.type_alias_data(type_alias).name.clone();
945 write!(f, "{}::{}", trait_name, name)?;
946 if self.parameters.len() > 0 {
947 write!(f, "<")?;
948 f.write_joined(&*self.parameters.0, ", ")?;
949 write!(f, ">")?;
950 }
951 }
952 TypeCtor::Closure { .. } => {
953 let sig = self.parameters[0]
954 .callable_sig(f.db)
955 .expect("first closure parameter should contain signature");
956 write!(f, "|")?;
957 f.write_joined(sig.params(), ", ")?;
958 write!(f, "| -> {}", sig.ret().display(f.db))?;
959 }
960 }
961 Ok(())
962 }
963}
964
965impl HirDisplay for ProjectionTy {
966 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
967 if f.should_truncate() {
968 return write!(f, "…");
969 }
970
971 let trait_name = f.db.trait_data(self.trait_(f.db)).name.clone();
972 write!(f, "<{} as {}", self.parameters[0].display(f.db), trait_name,)?;
973 if self.parameters.len() > 1 {
974 write!(f, "<")?;
975 f.write_joined(&self.parameters[1..], ", ")?;
976 write!(f, ">")?;
977 }
978 write!(f, ">::{}", f.db.type_alias_data(self.associated_ty).name)?;
979 Ok(())
980 }
981}
982
983impl HirDisplay for Ty {
984 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
985 if f.should_truncate() {
986 return write!(f, "…");
987 }
988
989 match self {
990 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
991 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
992 Ty::Param { name, .. } => write!(f, "{}", name)?,
993 Ty::Bound(idx) => write!(f, "?{}", idx)?,
994 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
995 match self {
996 Ty::Dyn(_) => write!(f, "dyn ")?,
997 Ty::Opaque(_) => write!(f, "impl ")?,
998 _ => unreachable!(),
999 };
1000 // Note: This code is written to produce nice results (i.e.
1001 // corresponding to surface Rust) for types that can occur in
1002 // actual Rust. It will have weird results if the predicates
1003 // aren't as expected (i.e. self types = $0, projection
1004 // predicates for a certain trait come after the Implemented
1005 // predicate for that trait).
1006 let mut first = true;
1007 let mut angle_open = false;
1008 for p in predicates.iter() {
1009 match p {
1010 GenericPredicate::Implemented(trait_ref) => {
1011 if angle_open {
1012 write!(f, ">")?;
1013 }
1014 if !first {
1015 write!(f, " + ")?;
1016 }
1017 // We assume that the self type is $0 (i.e. the
1018 // existential) here, which is the only thing that's
1019 // possible in actual Rust, and hence don't print it
1020 write!(f, "{}", f.db.trait_data(trait_ref.trait_).name.clone())?;
1021 if trait_ref.substs.len() > 1 {
1022 write!(f, "<")?;
1023 f.write_joined(&trait_ref.substs[1..], ", ")?;
1024 // there might be assoc type bindings, so we leave the angle brackets open
1025 angle_open = true;
1026 }
1027 }
1028 GenericPredicate::Projection(projection_pred) => {
1029 // in types in actual Rust, these will always come
1030 // after the corresponding Implemented predicate
1031 if angle_open {
1032 write!(f, ", ")?;
1033 } else {
1034 write!(f, "<")?;
1035 angle_open = true;
1036 }
1037 let name =
1038 f.db.type_alias_data(projection_pred.projection_ty.associated_ty)
1039 .name
1040 .clone();
1041 write!(f, "{} = ", name)?;
1042 projection_pred.ty.hir_fmt(f)?;
1043 }
1044 GenericPredicate::Error => {
1045 if angle_open {
1046 // impl Trait<X, {error}>
1047 write!(f, ", ")?;
1048 } else if !first {
1049 // impl Trait + {error}
1050 write!(f, " + ")?;
1051 }
1052 p.hir_fmt(f)?;
1053 }
1054 }
1055 first = false;
1056 }
1057 if angle_open {
1058 write!(f, ">")?;
1059 }
1060 }
1061 Ty::Unknown => write!(f, "{{unknown}}")?,
1062 Ty::Infer(..) => write!(f, "_")?,
1063 }
1064 Ok(())
1065 }
1066}
1067
1068impl TraitRef {
1069 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
1070 if f.should_truncate() {
1071 return write!(f, "…");
1072 }
1073
1074 self.substs[0].hir_fmt(f)?;
1075 if use_as {
1076 write!(f, " as ")?;
1077 } else {
1078 write!(f, ": ")?;
1079 }
1080 write!(f, "{}", f.db.trait_data(self.trait_).name.clone())?;
1081 if self.substs.len() > 1 {
1082 write!(f, "<")?;
1083 f.write_joined(&self.substs[1..], ", ")?;
1084 write!(f, ">")?;
1085 }
1086 Ok(())
1087 }
1088}
1089
1090impl HirDisplay for TraitRef {
1091 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1092 self.hir_fmt_ext(f, false)
1093 }
1094}
1095
1096impl HirDisplay for &GenericPredicate {
1097 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1098 HirDisplay::hir_fmt(*self, f)
1099 }
1100}
1101
1102impl HirDisplay for GenericPredicate {
1103 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1104 if f.should_truncate() {
1105 return write!(f, "…");
1106 }
1107
1108 match self {
1109 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
1110 GenericPredicate::Projection(projection_pred) => {
1111 write!(f, "<")?;
1112 projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
1113 write!(
1114 f,
1115 ">::{} = {}",
1116 f.db.type_alias_data(projection_pred.projection_ty.associated_ty).name,
1117 projection_pred.ty.display(f.db)
1118 )?;
1119 }
1120 GenericPredicate::Error => write!(f, "{{error}}")?,
1121 }
1122 Ok(())
1123 }
1124}
1125
1126impl HirDisplay for Obligation {
1127 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1128 match self {
1129 Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)),
1130 Obligation::Projection(proj) => write!(
1131 f,
1132 "Normalize({} => {})",
1133 proj.projection_ty.display(f.db),
1134 proj.ty.display(f.db)
1135 ),
1136 }
1137 }
1138}
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir_ty/src/lower.rs
index a39beb2a0..091c60f4f 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -9,43 +9,30 @@ 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, Path, PathKind, PathSegment},
15 resolver::{HasResolver, Resolver, TypeNs}, 15 resolver::{HasResolver, Resolver, TypeNs},
16 type_ref::{TypeBound, TypeRef}, 16 type_ref::{TypeBound, TypeRef},
17 AdtId, GenericDefId, LocalStructFieldId, VariantId, 17 AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId,
18 LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
18}; 19};
19use ra_arena::map::ArenaMap; 20use ra_arena::map::ArenaMap;
21use ra_db::CrateId;
20 22
21use super::{
22 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
23 TypeWalk,
24};
25use crate::{ 23use crate::{
26 db::HirDatabase, 24 db::HirDatabase,
27 ty::{ 25 primitive::{FloatTy, IntTy},
28 primitive::{FloatTy, IntTy, Uncertain}, 26 utils::{
29 Adt, 27 all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice,
28 variant_data,
30 }, 29 },
31 util::make_mut_slice, 30 FnSig, GenericPredicate, ImplTy, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment,
32 Const, Enum, EnumVariant, Function, GenericDef, ImplBlock, ModuleDef, Path, Static, Struct, 31 TraitRef, Ty, TypeCtor, TypeWalk,
33 Trait, TypeAlias, Union,
34}; 32};
35 33
36// FIXME: this is only really used in `type_for_def`, which contains a bunch of
37// impossible cases. Perhaps we should recombine `TypeableDef` and `Namespace`
38// into a `AsTypeDef`, `AsValueDef` enums?
39#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub enum Namespace {
41 Types,
42 Values,
43 // Note that only type inference uses this enum, and it doesn't care about macros.
44 // Macro,
45}
46
47impl Ty { 34impl Ty {
48 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { 35 pub fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
49 match type_ref { 36 match type_ref {
50 TypeRef::Never => Ty::simple(TypeCtor::Never), 37 TypeRef::Never => Ty::simple(TypeCtor::Never),
51 TypeRef::Tuple(inner) => { 38 TypeRef::Tuple(inner) => {
@@ -114,7 +101,7 @@ impl Ty {
114 TypeRef::Path(path) => path, 101 TypeRef::Path(path) => path,
115 _ => return None, 102 _ => return None,
116 }; 103 };
117 if let crate::PathKind::Type(_) = &path.kind { 104 if let PathKind::Type(_) = &path.kind {
118 return None; 105 return None;
119 } 106 }
120 if path.segments.len() > 1 { 107 if path.segments.len() > 1 {
@@ -158,19 +145,16 @@ impl Ty {
158 ) -> Ty { 145 ) -> Ty {
159 let ty = match resolution { 146 let ty = match resolution {
160 TypeNs::TraitId(trait_) => { 147 TypeNs::TraitId(trait_) => {
161 let trait_ref = TraitRef::from_resolved_path( 148 let trait_ref =
162 db, 149 TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None);
163 resolver,
164 trait_.into(),
165 resolved_segment,
166 None,
167 );
168 return if remaining_segments.len() == 1 { 150 return if remaining_segments.len() == 1 {
169 let segment = &remaining_segments[0]; 151 let segment = &remaining_segments[0];
170 match trait_ref 152 let associated_ty = associated_type_by_name_including_super_traits(
171 .trait_ 153 db,
172 .associated_type_by_name_including_super_traits(db, &segment.name) 154 trait_ref.trait_,
173 { 155 &segment.name,
156 );
157 match associated_ty {
174 Some(associated_ty) => { 158 Some(associated_ty) => {
175 // FIXME handle type parameters on the segment 159 // FIXME handle type parameters on the segment
176 Ty::Projection(ProjectionTy { 160 Ty::Projection(ProjectionTy {
@@ -195,8 +179,8 @@ impl Ty {
195 let name = resolved_segment.name.clone(); 179 let name = resolved_segment.name.clone();
196 Ty::Param { idx, name } 180 Ty::Param { idx, name }
197 } 181 }
198 TypeNs::SelfType(impl_block) => ImplBlock::from(impl_block).target_ty(db), 182 TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(),
199 TypeNs::AdtSelfType(adt) => Adt::from(adt).ty(db), 183 TypeNs::AdtSelfType(adt) => db.ty(adt.into()),
200 184
201 TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), 185 TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()),
202 TypeNs::BuiltinType(it) => { 186 TypeNs::BuiltinType(it) => {
@@ -214,7 +198,7 @@ impl Ty {
214 198
215 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 199 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
216 // Resolve the path (in type namespace) 200 // Resolve the path (in type namespace)
217 if let crate::PathKind::Type(type_ref) = &path.kind { 201 if let PathKind::Type(type_ref) = &path.kind {
218 let ty = Ty::from_hir(db, resolver, &type_ref); 202 let ty = Ty::from_hir(db, resolver, &type_ref);
219 let remaining_segments = &path.segments[..]; 203 let remaining_segments = &path.segments[..];
220 return Ty::from_type_relative_path(db, resolver, ty, remaining_segments); 204 return Ty::from_type_relative_path(db, resolver, ty, remaining_segments);
@@ -258,9 +242,9 @@ impl Ty {
258 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), 242 GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_),
259 _ => None, 243 _ => None,
260 }); 244 });
261 let traits = traits_from_env.flat_map(|t| t.all_super_traits(db)); 245 let traits = traits_from_env.flat_map(|t| all_super_traits(db, t));
262 for t in traits { 246 for t in traits {
263 if let Some(associated_ty) = t.associated_type_by_name(db, &segment.name) { 247 if let Some(associated_ty) = db.trait_data(t).associated_type_by_name(&segment.name) {
264 let substs = 248 let substs =
265 Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build(); 249 Substs::build_for_def(db, t).push(self_ty.clone()).fill_with_unknown().build();
266 // FIXME handle type parameters on the segment 250 // FIXME handle type parameters on the segment
@@ -274,27 +258,15 @@ impl Ty {
274 db: &impl HirDatabase, 258 db: &impl HirDatabase,
275 resolver: &Resolver, 259 resolver: &Resolver,
276 segment: &PathSegment, 260 segment: &PathSegment,
277 typable: TypableDef, 261 typable: TyDefId,
278 ) -> Ty { 262 ) -> Ty {
279 let ty = db.type_for_def(typable, Namespace::Types); 263 let generic_def = match typable {
280 let substs = Ty::substs_from_path_segment(db, resolver, segment, typable); 264 TyDefId::BuiltinType(_) => None,
281 ty.subst(&substs) 265 TyDefId::AdtId(it) => Some(it.into()),
282 } 266 TyDefId::TypeAliasId(it) => Some(it.into()),
283
284 pub(super) fn substs_from_path_segment(
285 db: &impl HirDatabase,
286 resolver: &Resolver,
287 segment: &PathSegment,
288 resolved: TypableDef,
289 ) -> Substs {
290 let def_generic: Option<GenericDef> = match resolved {
291 TypableDef::Function(func) => Some(func.into()),
292 TypableDef::Adt(adt) => Some(adt.into()),
293 TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()),
294 TypableDef::TypeAlias(t) => Some(t.into()),
295 TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None,
296 }; 267 };
297 substs_from_path_segment(db, resolver, segment, def_generic, false) 268 let substs = substs_from_path_segment(db, resolver, segment, generic_def, false);
269 db.ty(typable).subst(&substs)
298 } 270 }
299 271
300 /// Collect generic arguments from a path into a `Substs`. See also 272 /// Collect generic arguments from a path into a `Substs`. See also
@@ -303,17 +275,18 @@ impl Ty {
303 db: &impl HirDatabase, 275 db: &impl HirDatabase,
304 resolver: &Resolver, 276 resolver: &Resolver,
305 path: &Path, 277 path: &Path,
306 resolved: TypableDef, 278 // Note that we don't call `db.value_type(resolved)` here,
279 // `ValueTyDefId` is just a convenient way to pass generics and
280 // special-case enum variants
281 resolved: ValueTyDefId,
307 ) -> Substs { 282 ) -> Substs {
308 let last = path.segments.last().expect("path should have at least one segment"); 283 let last = path.segments.last().expect("path should have at least one segment");
309 let segment = match resolved { 284 let (segment, generic_def) = match resolved {
310 TypableDef::Function(_) 285 ValueTyDefId::FunctionId(it) => (last, Some(it.into())),
311 | TypableDef::Adt(_) 286 ValueTyDefId::StructId(it) => (last, Some(it.into())),
312 | TypableDef::Const(_) 287 ValueTyDefId::ConstId(it) => (last, Some(it.into())),
313 | TypableDef::Static(_) 288 ValueTyDefId::StaticId(_) => (last, None),
314 | TypableDef::TypeAlias(_) 289 ValueTyDefId::EnumVariantId(var) => {
315 | TypableDef::BuiltinType(_) => last,
316 TypableDef::EnumVariant(_) => {
317 // the generic args for an enum variant may be either specified 290 // the generic args for an enum variant may be either specified
318 // on the segment referring to the enum, or on the segment 291 // on the segment referring to the enum, or on the segment
319 // referring to the variant. So `Option::<T>::None` and 292 // referring to the variant. So `Option::<T>::None` and
@@ -327,10 +300,10 @@ impl Ty {
327 // Option::None::<T> 300 // Option::None::<T>
328 last 301 last
329 }; 302 };
330 segment 303 (segment, Some(var.parent.into()))
331 } 304 }
332 }; 305 };
333 Ty::substs_from_path_segment(db, resolver, segment, resolved) 306 substs_from_path_segment(db, resolver, segment, generic_def, false)
334 } 307 }
335} 308}
336 309
@@ -338,7 +311,7 @@ pub(super) fn substs_from_path_segment(
338 db: &impl HirDatabase, 311 db: &impl HirDatabase,
339 resolver: &Resolver, 312 resolver: &Resolver,
340 segment: &PathSegment, 313 segment: &PathSegment,
341 def_generic: Option<GenericDef>, 314 def_generic: Option<GenericDefId>,
342 add_self_param: bool, 315 add_self_param: bool,
343) -> Substs { 316) -> Substs {
344 let mut substs = Vec::new(); 317 let mut substs = Vec::new();
@@ -376,7 +349,7 @@ pub(super) fn substs_from_path_segment(
376 349
377 // handle defaults 350 // handle defaults
378 if let Some(def_generic) = def_generic { 351 if let Some(def_generic) = def_generic {
379 let default_substs = db.generic_defaults(def_generic); 352 let default_substs = db.generic_defaults(def_generic.into());
380 assert_eq!(substs.len(), default_substs.len()); 353 assert_eq!(substs.len(), default_substs.len());
381 354
382 for (i, default_ty) in default_substs.iter().enumerate() { 355 for (i, default_ty) in default_substs.iter().enumerate() {
@@ -390,7 +363,7 @@ pub(super) fn substs_from_path_segment(
390} 363}
391 364
392impl TraitRef { 365impl TraitRef {
393 pub(crate) fn from_path( 366 fn from_path(
394 db: &impl HirDatabase, 367 db: &impl HirDatabase,
395 resolver: &Resolver, 368 resolver: &Resolver,
396 path: &Path, 369 path: &Path,
@@ -404,10 +377,10 @@ impl TraitRef {
404 Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) 377 Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty))
405 } 378 }
406 379
407 pub(super) fn from_resolved_path( 380 pub(crate) fn from_resolved_path(
408 db: &impl HirDatabase, 381 db: &impl HirDatabase,
409 resolver: &Resolver, 382 resolver: &Resolver,
410 resolved: Trait, 383 resolved: TraitId,
411 segment: &PathSegment, 384 segment: &PathSegment,
412 explicit_self_ty: Option<Ty>, 385 explicit_self_ty: Option<Ty>,
413 ) -> Self { 386 ) -> Self {
@@ -418,7 +391,7 @@ impl TraitRef {
418 TraitRef { trait_: resolved, substs } 391 TraitRef { trait_: resolved, substs }
419 } 392 }
420 393
421 pub(crate) fn from_hir( 394 fn from_hir(
422 db: &impl HirDatabase, 395 db: &impl HirDatabase,
423 resolver: &Resolver, 396 resolver: &Resolver,
424 type_ref: &TypeRef, 397 type_ref: &TypeRef,
@@ -435,18 +408,13 @@ impl TraitRef {
435 db: &impl HirDatabase, 408 db: &impl HirDatabase,
436 resolver: &Resolver, 409 resolver: &Resolver,
437 segment: &PathSegment, 410 segment: &PathSegment,
438 resolved: Trait, 411 resolved: TraitId,
439 ) -> Substs { 412 ) -> Substs {
440 let has_self_param = 413 let has_self_param =
441 segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false); 414 segment.args_and_bindings.as_ref().map(|a| a.has_self_type).unwrap_or(false);
442 substs_from_path_segment(db, resolver, segment, Some(resolved.into()), !has_self_param) 415 substs_from_path_segment(db, resolver, segment, Some(resolved.into()), !has_self_param)
443 } 416 }
444 417
445 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef {
446 let substs = Substs::identity(&db.generic_params(trait_.id.into()));
447 TraitRef { trait_, substs }
448 }
449
450 pub(crate) fn from_type_bound( 418 pub(crate) fn from_type_bound(
451 db: &impl HirDatabase, 419 db: &impl HirDatabase,
452 resolver: &Resolver, 420 resolver: &Resolver,
@@ -502,10 +470,11 @@ fn assoc_type_bindings_from_type_bound<'a>(
502 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 470 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
503 .map(move |(name, type_ref)| { 471 .map(move |(name, type_ref)| {
504 let associated_ty = 472 let associated_ty =
505 match trait_ref.trait_.associated_type_by_name_including_super_traits(db, &name) { 473 associated_type_by_name_including_super_traits(db, trait_ref.trait_, &name);
506 None => return GenericPredicate::Error, 474 let associated_ty = match associated_ty {
507 Some(t) => t, 475 None => return GenericPredicate::Error,
508 }; 476 Some(t) => t,
477 };
509 let projection_ty = 478 let projection_ty =
510 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; 479 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
511 let ty = Ty::from_hir(db, resolver, type_ref); 480 let ty = Ty::from_hir(db, resolver, type_ref);
@@ -514,39 +483,12 @@ fn assoc_type_bindings_from_type_bound<'a>(
514 }) 483 })
515} 484}
516 485
517/// Build the declared type of an item. This depends on the namespace; e.g. for
518/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
519/// the constructor function `(usize) -> Foo` which lives in the values
520/// namespace.
521pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
522 match (def, ns) {
523 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
524 (TypableDef::Adt(Adt::Struct(s)), Namespace::Values) => type_for_struct_constructor(db, s),
525 (TypableDef::Adt(adt), Namespace::Types) => type_for_adt(db, adt),
526 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
527 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
528 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c),
529 (TypableDef::Static(c), Namespace::Values) => type_for_static(db, c),
530 (TypableDef::BuiltinType(t), Namespace::Types) => type_for_builtin(t),
531
532 // 'error' cases:
533 (TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
534 (TypableDef::Adt(Adt::Union(_)), Namespace::Values) => Ty::Unknown,
535 (TypableDef::Adt(Adt::Enum(_)), Namespace::Values) => Ty::Unknown,
536 (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
537 (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown,
538 (TypableDef::Const(_), Namespace::Types) => Ty::Unknown,
539 (TypableDef::Static(_), Namespace::Types) => Ty::Unknown,
540 (TypableDef::BuiltinType(_), Namespace::Values) => Ty::Unknown,
541 }
542}
543
544/// Build the signature of a callable item (function, struct or enum variant). 486/// Build the signature of a callable item (function, struct or enum variant).
545pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig { 487pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig {
546 match def { 488 match def {
547 CallableDef::Function(f) => fn_sig_for_fn(db, f), 489 CallableDef::FunctionId(f) => fn_sig_for_fn(db, f),
548 CallableDef::Struct(s) => fn_sig_for_struct_constructor(db, s), 490 CallableDef::StructId(s) => fn_sig_for_struct_constructor(db, s),
549 CallableDef::EnumVariant(e) => fn_sig_for_enum_variant_constructor(db, e), 491 CallableDef::EnumVariantId(e) => fn_sig_for_enum_variant_constructor(db, e),
550 } 492 }
551} 493}
552 494
@@ -555,12 +497,11 @@ pub(crate) fn field_types_query(
555 db: &impl HirDatabase, 497 db: &impl HirDatabase,
556 variant_id: VariantId, 498 variant_id: VariantId,
557) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { 499) -> Arc<ArenaMap<LocalStructFieldId, Ty>> {
558 let (resolver, var_data) = match variant_id { 500 let var_data = variant_data(db, variant_id);
559 VariantId::StructId(it) => (it.resolver(db), db.struct_data(it.0).variant_data.clone()), 501 let resolver = match variant_id {
560 VariantId::EnumVariantId(it) => ( 502 VariantId::StructId(it) => it.resolver(db),
561 it.parent.resolver(db), 503 VariantId::UnionId(it) => it.resolver(db),
562 db.enum_data(it.parent).variants[it.local_id].variant_data.clone(), 504 VariantId::EnumVariantId(it) => it.parent.resolver(db),
563 ),
564 }; 505 };
565 let mut res = ArenaMap::default(); 506 let mut res = ArenaMap::default();
566 for (field_id, field_data) in var_data.fields().iter() { 507 for (field_id, field_data) in var_data.fields().iter() {
@@ -579,10 +520,10 @@ pub(crate) fn field_types_query(
579/// these are fine: `T: Foo<U::Item>, U: Foo<()>`. 520/// these are fine: `T: Foo<U::Item>, U: Foo<()>`.
580pub(crate) fn generic_predicates_for_param_query( 521pub(crate) fn generic_predicates_for_param_query(
581 db: &impl HirDatabase, 522 db: &impl HirDatabase,
582 def: GenericDef, 523 def: GenericDefId,
583 param_idx: u32, 524 param_idx: u32,
584) -> Arc<[GenericPredicate]> { 525) -> Arc<[GenericPredicate]> {
585 let resolver = GenericDefId::from(def).resolver(db); 526 let resolver = def.resolver(db);
586 resolver 527 resolver
587 .where_predicates_in_scope() 528 .where_predicates_in_scope()
588 // we have to filter out all other predicates *first*, before attempting to lower them 529 // we have to filter out all other predicates *first*, before attempting to lower them
@@ -591,24 +532,23 @@ pub(crate) fn generic_predicates_for_param_query(
591 .collect() 532 .collect()
592} 533}
593 534
594pub(crate) fn trait_env( 535impl TraitEnvironment {
595 db: &impl HirDatabase, 536 pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> {
596 resolver: &Resolver, 537 let predicates = resolver
597) -> Arc<super::TraitEnvironment> { 538 .where_predicates_in_scope()
598 let predicates = resolver 539 .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
599 .where_predicates_in_scope() 540 .collect::<Vec<_>>();
600 .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
601 .collect::<Vec<_>>();
602 541
603 Arc::new(super::TraitEnvironment { predicates }) 542 Arc::new(TraitEnvironment { predicates })
543 }
604} 544}
605 545
606/// Resolve the where clause(s) of an item with generics. 546/// Resolve the where clause(s) of an item with generics.
607pub(crate) fn generic_predicates_query( 547pub(crate) fn generic_predicates_query(
608 db: &impl HirDatabase, 548 db: &impl HirDatabase,
609 def: GenericDef, 549 def: GenericDefId,
610) -> Arc<[GenericPredicate]> { 550) -> Arc<[GenericPredicate]> {
611 let resolver = GenericDefId::from(def).resolver(db); 551 let resolver = def.resolver(db);
612 resolver 552 resolver
613 .where_predicates_in_scope() 553 .where_predicates_in_scope()
614 .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) 554 .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
@@ -616,8 +556,8 @@ pub(crate) fn generic_predicates_query(
616} 556}
617 557
618/// Resolve the default type params from generics 558/// Resolve the default type params from generics
619pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> Substs { 559pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs {
620 let resolver = GenericDefId::from(def).resolver(db); 560 let resolver = def.resolver(db);
621 let generic_params = db.generic_params(def.into()); 561 let generic_params = db.generic_params(def.into());
622 562
623 let defaults = generic_params 563 let defaults = generic_params
@@ -629,9 +569,9 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) ->
629 Substs(defaults) 569 Substs(defaults)
630} 570}
631 571
632fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { 572fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig {
633 let data = db.function_data(def.id); 573 let data = db.function_data(def);
634 let resolver = def.id.resolver(db); 574 let resolver = def.resolver(db);
635 let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); 575 let params = data.params.iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
636 let ret = Ty::from_hir(db, &resolver, &data.ret_type); 576 let ret = Ty::from_hir(db, &resolver, &data.ret_type);
637 FnSig::from_params_and_return(params, ret) 577 FnSig::from_params_and_return(params, ret)
@@ -639,24 +579,24 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
639 579
640/// Build the declared type of a function. This should not need to look at the 580/// Build the declared type of a function. This should not need to look at the
641/// function body. 581/// function body.
642fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 582fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty {
643 let generics = db.generic_params(def.id.into()); 583 let generics = db.generic_params(def.into());
644 let substs = Substs::identity(&generics); 584 let substs = Substs::identity(&generics);
645 Ty::apply(TypeCtor::FnDef(def.into()), substs) 585 Ty::apply(TypeCtor::FnDef(def.into()), substs)
646} 586}
647 587
648/// Build the declared type of a const. 588/// Build the declared type of a const.
649fn type_for_const(db: &impl HirDatabase, def: Const) -> Ty { 589fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Ty {
650 let data = db.const_data(def.id); 590 let data = db.const_data(def);
651 let resolver = def.id.resolver(db); 591 let resolver = def.resolver(db);
652 592
653 Ty::from_hir(db, &resolver, &data.type_ref) 593 Ty::from_hir(db, &resolver, &data.type_ref)
654} 594}
655 595
656/// Build the declared type of a static. 596/// Build the declared type of a static.
657fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { 597fn type_for_static(db: &impl HirDatabase, def: StaticId) -> Ty {
658 let data = db.static_data(def.id); 598 let data = db.static_data(def);
659 let resolver = def.id.resolver(db); 599 let resolver = def.resolver(db);
660 600
661 Ty::from_hir(db, &resolver, &data.type_ref) 601 Ty::from_hir(db, &resolver, &data.type_ref)
662} 602}
@@ -672,160 +612,148 @@ fn type_for_builtin(def: BuiltinType) -> Ty {
672 }) 612 })
673} 613}
674 614
675impl From<BuiltinInt> for IntTy { 615fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> FnSig {
676 fn from(t: BuiltinInt) -> Self { 616 let struct_data = db.struct_data(def.into());
677 IntTy { signedness: t.signedness, bitness: t.bitness }
678 }
679}
680
681impl From<BuiltinFloat> for FloatTy {
682 fn from(t: BuiltinFloat) -> Self {
683 FloatTy { bitness: t.bitness }
684 }
685}
686
687impl From<Option<BuiltinInt>> for Uncertain<IntTy> {
688 fn from(t: Option<BuiltinInt>) -> Self {
689 match t {
690 None => Uncertain::Unknown,
691 Some(t) => Uncertain::Known(t.into()),
692 }
693 }
694}
695
696impl From<Option<BuiltinFloat>> for Uncertain<FloatTy> {
697 fn from(t: Option<BuiltinFloat>) -> Self {
698 match t {
699 None => Uncertain::Unknown,
700 Some(t) => Uncertain::Known(t.into()),
701 }
702 }
703}
704
705fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
706 let struct_data = db.struct_data(def.id.into());
707 let fields = struct_data.variant_data.fields(); 617 let fields = struct_data.variant_data.fields();
708 let resolver = def.id.resolver(db); 618 let resolver = def.resolver(db);
709 let params = fields 619 let params = fields
710 .iter() 620 .iter()
711 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 621 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
712 .collect::<Vec<_>>(); 622 .collect::<Vec<_>>();
713 let ret = type_for_adt(db, def); 623 let ret = type_for_adt(db, def.into());
714 FnSig::from_params_and_return(params, ret) 624 FnSig::from_params_and_return(params, ret)
715} 625}
716 626
717/// Build the type of a tuple struct constructor. 627/// Build the type of a tuple struct constructor.
718fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 628fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty {
719 let struct_data = db.struct_data(def.id.into()); 629 let struct_data = db.struct_data(def.into());
720 if struct_data.variant_data.is_unit() { 630 if struct_data.variant_data.is_unit() {
721 return type_for_adt(db, def); // Unit struct 631 return type_for_adt(db, def.into()); // Unit struct
722 } 632 }
723 let generics = db.generic_params(def.id.into()); 633 let generics = db.generic_params(def.into());
724 let substs = Substs::identity(&generics); 634 let substs = Substs::identity(&generics);
725 Ty::apply(TypeCtor::FnDef(def.into()), substs) 635 Ty::apply(TypeCtor::FnDef(def.into()), substs)
726} 636}
727 637
728fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { 638fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> FnSig {
729 let var_data = def.variant_data(db); 639 let enum_data = db.enum_data(def.parent);
730 let fields = var_data.fields(); 640 let var_data = &enum_data.variants[def.local_id];
731 let resolver = def.parent.id.resolver(db); 641 let fields = var_data.variant_data.fields();
642 let resolver = def.parent.resolver(db);
732 let params = fields 643 let params = fields
733 .iter() 644 .iter()
734 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 645 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
735 .collect::<Vec<_>>(); 646 .collect::<Vec<_>>();
736 let generics = db.generic_params(def.parent_enum(db).id.into()); 647 let generics = db.generic_params(def.parent.into());
737 let substs = Substs::identity(&generics); 648 let substs = Substs::identity(&generics);
738 let ret = type_for_adt(db, def.parent_enum(db)).subst(&substs); 649 let ret = type_for_adt(db, def.parent.into()).subst(&substs);
739 FnSig::from_params_and_return(params, ret) 650 FnSig::from_params_and_return(params, ret)
740} 651}
741 652
742/// Build the type of a tuple enum variant constructor. 653/// Build the type of a tuple enum variant constructor.
743fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { 654fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) -> Ty {
744 let var_data = def.variant_data(db); 655 let enum_data = db.enum_data(def.parent);
656 let var_data = &enum_data.variants[def.local_id].variant_data;
745 if var_data.is_unit() { 657 if var_data.is_unit() {
746 return type_for_adt(db, def.parent_enum(db)); // Unit variant 658 return type_for_adt(db, def.parent.into()); // Unit variant
747 } 659 }
748 let generics = db.generic_params(def.parent_enum(db).id.into()); 660 let generics = db.generic_params(def.parent.into());
749 let substs = Substs::identity(&generics); 661 let substs = Substs::identity(&generics);
750 Ty::apply(TypeCtor::FnDef(def.into()), substs) 662 Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs)
751} 663}
752 664
753fn type_for_adt(db: &impl HirDatabase, adt: impl Into<Adt>) -> Ty { 665fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty {
754 let adt = adt.into(); 666 let generics = db.generic_params(adt.into());
755 let adt_id: AdtId = adt.into();
756 let generics = db.generic_params(adt_id.into());
757 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) 667 Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics))
758} 668}
759 669
760fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 670fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty {
761 let generics = db.generic_params(t.id.into()); 671 let generics = db.generic_params(t.into());
762 let resolver = t.id.resolver(db); 672 let resolver = t.resolver(db);
763 let type_ref = t.type_ref(db); 673 let type_ref = &db.type_alias_data(t).type_ref;
764 let substs = Substs::identity(&generics); 674 let substs = Substs::identity(&generics);
765 let inner = Ty::from_hir(db, &resolver, &type_ref.unwrap_or(TypeRef::Error)); 675 let inner = Ty::from_hir(db, &resolver, type_ref.as_ref().unwrap_or(&TypeRef::Error));
766 inner.subst(&substs) 676 inner.subst(&substs)
767} 677}
768 678
769#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 679#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
770pub enum TypableDef {
771 Function(Function),
772 Adt(Adt),
773 EnumVariant(EnumVariant),
774 TypeAlias(TypeAlias),
775 Const(Const),
776 Static(Static),
777 BuiltinType(BuiltinType),
778}
779impl_froms!(
780 TypableDef: Function,
781 Adt(Struct, Enum, Union),
782 EnumVariant,
783 TypeAlias,
784 Const,
785 Static,
786 BuiltinType
787);
788
789impl From<ModuleDef> for Option<TypableDef> {
790 fn from(def: ModuleDef) -> Option<TypableDef> {
791 let res = match def {
792 ModuleDef::Function(f) => f.into(),
793 ModuleDef::Adt(adt) => adt.into(),
794 ModuleDef::EnumVariant(v) => v.into(),
795 ModuleDef::TypeAlias(t) => t.into(),
796 ModuleDef::Const(v) => v.into(),
797 ModuleDef::Static(v) => v.into(),
798 ModuleDef::BuiltinType(t) => t.into(),
799 ModuleDef::Module(_) | ModuleDef::Trait(_) => return None,
800 };
801 Some(res)
802 }
803}
804
805#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
806pub enum CallableDef { 680pub enum CallableDef {
807 Function(Function), 681 FunctionId(FunctionId),
808 Struct(Struct), 682 StructId(StructId),
809 EnumVariant(EnumVariant), 683 EnumVariantId(EnumVariantId),
810} 684}
811impl_froms!(CallableDef: Function, Struct, EnumVariant); 685impl_froms!(CallableDef: FunctionId, StructId, EnumVariantId);
812 686
813impl CallableDef { 687impl CallableDef {
814 pub fn krate(self, db: &impl HirDatabase) -> Option<crate::Crate> { 688 pub fn krate(self, db: &impl HirDatabase) -> CrateId {
815 match self { 689 match self {
816 CallableDef::Function(f) => f.krate(db), 690 CallableDef::FunctionId(f) => f.lookup(db).module(db).krate,
817 CallableDef::Struct(s) => s.krate(db), 691 CallableDef::StructId(s) => s.module(db).krate,
818 CallableDef::EnumVariant(e) => e.parent_enum(db).krate(db), 692 CallableDef::EnumVariantId(e) => e.parent.module(db).krate,
819 } 693 }
820 } 694 }
821} 695}
822 696
823impl From<CallableDef> for GenericDef { 697impl From<CallableDef> for GenericDefId {
824 fn from(def: CallableDef) -> GenericDef { 698 fn from(def: CallableDef) -> GenericDefId {
825 match def { 699 match def {
826 CallableDef::Function(f) => f.into(), 700 CallableDef::FunctionId(f) => f.into(),
827 CallableDef::Struct(s) => s.into(), 701 CallableDef::StructId(s) => s.into(),
828 CallableDef::EnumVariant(e) => e.into(), 702 CallableDef::EnumVariantId(e) => e.into(),
703 }
704 }
705}
706
707#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
708pub enum TyDefId {
709 BuiltinType(BuiltinType),
710 AdtId(AdtId),
711 TypeAliasId(TypeAliasId),
712}
713impl_froms!(TyDefId: BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId);
714
715#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
716pub enum ValueTyDefId {
717 FunctionId(FunctionId),
718 StructId(StructId),
719 EnumVariantId(EnumVariantId),
720 ConstId(ConstId),
721 StaticId(StaticId),
722}
723impl_froms!(ValueTyDefId: FunctionId, StructId, EnumVariantId, ConstId, StaticId);
724
725/// Build the declared type of an item. This depends on the namespace; e.g. for
726/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
727/// the constructor function `(usize) -> Foo` which lives in the values
728/// namespace.
729pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty {
730 match def {
731 TyDefId::BuiltinType(it) => type_for_builtin(it),
732 TyDefId::AdtId(it) => type_for_adt(db, it),
733 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
734 }
735}
736pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty {
737 match def {
738 ValueTyDefId::FunctionId(it) => type_for_fn(db, it),
739 ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it),
740 ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it),
741 ValueTyDefId::ConstId(it) => type_for_const(db, it),
742 ValueTyDefId::StaticId(it) => type_for_static(db, it),
743 }
744}
745
746pub(crate) fn impl_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> ImplTy {
747 let impl_data = db.impl_data(impl_id);
748 let resolver = impl_id.resolver(db);
749 let self_ty = Ty::from_hir(db, &resolver, &impl_data.target_type);
750 match impl_data.target_trait.as_ref() {
751 Some(trait_ref) => {
752 match TraitRef::from_hir(db, &resolver, trait_ref, Some(self_ty.clone())) {
753 Some(it) => ImplTy::TraitRef(it),
754 None => ImplTy::Inherent(self_ty),
755 }
829 } 756 }
757 None => ImplTy::Inherent(self_ty),
830 } 758 }
831} 759}
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir_ty/src/marks.rs
index 0f754eb9c..0f754eb9c 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir_ty/src/marks.rs
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index caa5f5f74..ee1936b0e 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -5,18 +5,23 @@
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::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
10 FunctionId, HasModule, ImplId, TraitId,
11};
12use hir_expand::name::Name;
13use ra_db::CrateId;
14use ra_prof::profile;
9use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
10 16
11use crate::{ 17use crate::{
18 autoderef,
12 db::HirDatabase, 19 db::HirDatabase,
13 ty::primitive::{FloatBitness, Uncertain}, 20 primitive::{FloatBitness, Uncertain},
14 ty::{Ty, TypeCtor}, 21 utils::all_super_traits,
15 AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, 22 Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor,
16}; 23};
17 24
18use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
19
20/// This is used as a key for indexing impls. 25/// This is used as a key for indexing impls.
21#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 26#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
22pub enum TyFingerprint { 27pub enum TyFingerprint {
@@ -37,99 +42,101 @@ 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 match db.impl_ty(impl_id) {
62 ImplTy::TraitRef(tr) => {
63 res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
64 }
65 ImplTy::Inherent(self_ty) => {
66 if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) {
67 res.impls.entry(self_ty_fp).or_default().push(impl_id);
68 }
69 }
70 }
71 }
53 } 72 }
54 Arc::new(crate_impl_blocks) 73
74 Arc::new(res)
55 } 75 }
56 pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplBlock> + '_ { 76 pub fn lookup_impl_blocks(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
57 let fingerprint = TyFingerprint::for_impl(ty); 77 let fingerprint = TyFingerprint::for_impl(ty);
58 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied() 78 fingerprint.and_then(|f| self.impls.get(&f)).into_iter().flatten().copied()
59 } 79 }
60 80
61 pub fn lookup_impl_blocks_for_trait(&self, tr: Trait) -> impl Iterator<Item = ImplBlock> + '_ { 81 pub fn lookup_impl_blocks_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ {
62 self.impls_by_trait.get(&tr).into_iter().flatten().copied() 82 self.impls_by_trait.get(&tr).into_iter().flatten().copied()
63 } 83 }
64 84
65 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplBlock> + 'a { 85 pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a {
66 self.impls.values().chain(self.impls_by_trait.values()).flatten().copied() 86 self.impls.values().chain(self.impls_by_trait.values()).flatten().copied()
67 } 87 }
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} 88}
89 89
90fn def_crates(db: &impl HirDatabase, cur_crate: Crate, ty: &Ty) -> Option<ArrayVec<[Crate; 2]>> { 90impl Ty {
91 // Types like slice can have inherent impls in several crates, (core and alloc). 91 pub fn def_crates(
92 // The corresponding impls are marked with lang items, so we can use them to find the required crates. 92 &self,
93 macro_rules! lang_item_crate { 93 db: &impl HirDatabase,
94 cur_crate: CrateId,
95 ) -> Option<ArrayVec<[CrateId; 2]>> {
96 // Types like slice can have inherent impls in several crates, (core and alloc).
97 // The corresponding impls are marked with lang items, so we can use them to find the required crates.
98 macro_rules! lang_item_crate {
94 ($($name:expr),+ $(,)?) => {{ 99 ($($name:expr),+ $(,)?) => {{
95 let mut v = ArrayVec::<[LangItemTarget; 2]>::new(); 100 let mut v = ArrayVec::<[LangItemTarget; 2]>::new();
96 $( 101 $(
97 v.extend(db.lang_item(cur_crate.crate_id, $name.into())); 102 v.extend(db.lang_item(cur_crate, $name.into()));
98 )+ 103 )+
99 v 104 v
100 }}; 105 }};
101 } 106 }
102 107
103 let lang_item_targets = match ty { 108 let lang_item_targets = match self {
104 Ty::Apply(a_ty) => match a_ty.ctor { 109 Ty::Apply(a_ty) => match a_ty.ctor {
105 TypeCtor::Adt(def_id) => return Some(std::iter::once(def_id.krate(db)?).collect()), 110 TypeCtor::Adt(def_id) => {
106 TypeCtor::Bool => lang_item_crate!("bool"), 111 return Some(std::iter::once(def_id.module(db).krate).collect())
107 TypeCtor::Char => lang_item_crate!("char"), 112 }
108 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness { 113 TypeCtor::Bool => lang_item_crate!("bool"),
109 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) 114 TypeCtor::Char => lang_item_crate!("char"),
110 FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"), 115 TypeCtor::Float(Uncertain::Known(f)) => match f.bitness {
111 FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"), 116 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
117 FloatBitness::X32 => lang_item_crate!("f32", "f32_runtime"),
118 FloatBitness::X64 => lang_item_crate!("f64", "f64_runtime"),
119 },
120 TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()),
121 TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
122 TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
123 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
124 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
125 _ => return None,
112 }, 126 },
113 TypeCtor::Int(Uncertain::Known(i)) => lang_item_crate!(i.ty_to_string()),
114 TypeCtor::Str => lang_item_crate!("str_alloc", "str"),
115 TypeCtor::Slice => lang_item_crate!("slice_alloc", "slice"),
116 TypeCtor::RawPtr(Mutability::Shared) => lang_item_crate!("const_ptr"),
117 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
118 _ => return None, 127 _ => return None,
119 }, 128 };
120 _ => return None, 129 let res = lang_item_targets
121 }; 130 .into_iter()
122 let res = lang_item_targets 131 .filter_map(|it| match it {
123 .into_iter() 132 LangItemTarget::ImplBlockId(it) => Some(it),
124 .filter_map(|it| match it { 133 _ => None,
125 LangItemTarget::ImplBlockId(it) => Some(it), 134 })
126 _ => None, 135 .map(|it| it.module(db).krate)
127 }) 136 .collect();
128 .map(|it| it.module(db).krate.into()) 137 Some(res)
129 .collect(); 138 }
130 Some(res)
131} 139}
132
133/// Look up the method with the given name, returning the actual autoderefed 140/// Look up the method with the given name, returning the actual autoderefed
134/// receiver type (but without autoref applied yet). 141/// receiver type (but without autoref applied yet).
135pub(crate) fn lookup_method( 142pub(crate) fn lookup_method(
@@ -137,10 +144,10 @@ pub(crate) fn lookup_method(
137 db: &impl HirDatabase, 144 db: &impl HirDatabase,
138 name: &Name, 145 name: &Name,
139 resolver: &Resolver, 146 resolver: &Resolver,
140) -> Option<(Ty, Function)> { 147) -> Option<(Ty, FunctionId)> {
141 iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f 148 iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f
142 { 149 {
143 AssocItem::Function(f) => Some((ty.clone(), f)), 150 AssocItemId::FunctionId(f) => Some((ty.clone(), f)),
144 _ => None, 151 _ => None,
145 }) 152 })
146} 153}
@@ -160,13 +167,13 @@ pub enum LookupMode {
160// This would be nicer if it just returned an iterator, but that runs into 167// This would be nicer if it just returned an iterator, but that runs into
161// lifetime problems, because we need to borrow temp `CrateImplBlocks`. 168// lifetime problems, because we need to borrow temp `CrateImplBlocks`.
162// FIXME add a context type here? 169// FIXME add a context type here?
163pub(crate) fn iterate_method_candidates<T>( 170pub fn iterate_method_candidates<T>(
164 ty: &Canonical<Ty>, 171 ty: &Canonical<Ty>,
165 db: &impl HirDatabase, 172 db: &impl HirDatabase,
166 resolver: &Resolver, 173 resolver: &Resolver,
167 name: Option<&Name>, 174 name: Option<&Name>,
168 mode: LookupMode, 175 mode: LookupMode,
169 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 176 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
170) -> Option<T> { 177) -> Option<T> {
171 let krate = resolver.krate()?; 178 let krate = resolver.krate()?;
172 match mode { 179 match mode {
@@ -179,16 +186,12 @@ pub(crate) fn iterate_method_candidates<T>(
179 // Also note that when we've got a receiver like &S, even if the method we 186 // Also note that when we've got a receiver like &S, even if the method we
180 // find in the end takes &self, we still do the autoderef step (just as 187 // find in the end takes &self, we still do the autoderef step (just as
181 // rustc does an autoderef and then autoref again). 188 // rustc does an autoderef and then autoref again).
182 189 let environment = TraitEnvironment::lower(db, resolver);
183 for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { 190 let ty = InEnvironment { value: ty.clone(), environment };
184 if let Some(result) = iterate_inherent_methods( 191 for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) {
185 &derefed_ty, 192 if let Some(result) =
186 db, 193 iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback)
187 name, 194 {
188 mode,
189 krate.into(),
190 &mut callback,
191 ) {
192 return Some(result); 195 return Some(result);
193 } 196 }
194 if let Some(result) = iterate_trait_method_candidates( 197 if let Some(result) = iterate_trait_method_candidates(
@@ -226,30 +229,29 @@ fn iterate_trait_method_candidates<T>(
226 resolver: &Resolver, 229 resolver: &Resolver,
227 name: Option<&Name>, 230 name: Option<&Name>,
228 mode: LookupMode, 231 mode: LookupMode,
229 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 232 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
230) -> Option<T> { 233) -> Option<T> {
231 let krate = resolver.krate()?; 234 let krate = resolver.krate()?;
232 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) 235 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
233 let env = lower::trait_env(db, resolver); 236 let env = TraitEnvironment::lower(db, resolver);
234 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope 237 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
235 let inherent_trait = ty.value.inherent_trait().into_iter(); 238 let inherent_trait = ty.value.inherent_trait().into_iter();
236 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 239 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
237 let traits_from_env = env 240 let traits_from_env = env
238 .trait_predicates_for_self_ty(&ty.value) 241 .trait_predicates_for_self_ty(&ty.value)
239 .map(|tr| tr.trait_) 242 .map(|tr| tr.trait_)
240 .flat_map(|t| t.all_super_traits(db)); 243 .flat_map(|t| all_super_traits(db, t));
241 let traits = inherent_trait 244 let traits =
242 .chain(traits_from_env) 245 inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter());
243 .chain(resolver.traits_in_scope(db).into_iter().map(Trait::from));
244 'traits: for t in traits { 246 'traits: for t in traits {
245 let data = db.trait_data(t.id); 247 let data = db.trait_data(t);
246 248
247 // we'll be lazy about checking whether the type implements the 249 // we'll be lazy about checking whether the type implements the
248 // trait, but if we find out it doesn't, we'll skip the rest of the 250 // trait, but if we find out it doesn't, we'll skip the rest of the
249 // iteration 251 // iteration
250 let mut known_implemented = false; 252 let mut known_implemented = false;
251 for &item in data.items.iter() { 253 for (_name, item) in data.items.iter() {
252 if !is_valid_candidate(db, name, mode, item.into()) { 254 if !is_valid_candidate(db, name, mode, (*item).into()) {
253 continue; 255 continue;
254 } 256 }
255 if !known_implemented { 257 if !known_implemented {
@@ -259,7 +261,7 @@ fn iterate_trait_method_candidates<T>(
259 } 261 }
260 } 262 }
261 known_implemented = true; 263 known_implemented = true;
262 if let Some(result) = callback(&ty.value, item.into()) { 264 if let Some(result) = callback(&ty.value, (*item).into()) {
263 return Some(result); 265 return Some(result);
264 } 266 }
265 } 267 }
@@ -272,18 +274,18 @@ fn iterate_inherent_methods<T>(
272 db: &impl HirDatabase, 274 db: &impl HirDatabase,
273 name: Option<&Name>, 275 name: Option<&Name>,
274 mode: LookupMode, 276 mode: LookupMode,
275 krate: Crate, 277 krate: CrateId,
276 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 278 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
277) -> Option<T> { 279) -> Option<T> {
278 for krate in def_crates(db, krate, &ty.value)? { 280 for krate in ty.value.def_crates(db, krate)? {
279 let impls = db.impls_in_crate(krate); 281 let impls = db.impls_in_crate(krate);
280 282
281 for impl_block in impls.lookup_impl_blocks(&ty.value) { 283 for impl_block in impls.lookup_impl_blocks(&ty.value) {
282 for item in impl_block.items(db) { 284 for &item in db.impl_data(impl_block).items.iter() {
283 if !is_valid_candidate(db, name, mode, item) { 285 if !is_valid_candidate(db, name, mode, item) {
284 continue; 286 continue;
285 } 287 }
286 if let Some(result) = callback(&ty.value, item) { 288 if let Some(result) = callback(&ty.value, item.into()) {
287 return Some(result); 289 return Some(result);
288 } 290 }
289 } 291 }
@@ -296,71 +298,47 @@ fn is_valid_candidate(
296 db: &impl HirDatabase, 298 db: &impl HirDatabase,
297 name: Option<&Name>, 299 name: Option<&Name>,
298 mode: LookupMode, 300 mode: LookupMode,
299 item: AssocItem, 301 item: AssocItemId,
300) -> bool { 302) -> bool {
301 match item { 303 match item {
302 AssocItem::Function(m) => { 304 AssocItemId::FunctionId(m) => {
303 let data = db.function_data(m.id); 305 let data = db.function_data(m);
304 name.map_or(true, |name| data.name == *name) 306 name.map_or(true, |name| &data.name == name)
305 && (data.has_self_param || mode == LookupMode::Path) 307 && (data.has_self_param || mode == LookupMode::Path)
306 } 308 }
307 AssocItem::Const(c) => { 309 AssocItemId::ConstId(c) => {
308 name.map_or(true, |name| Some(name) == c.name(db).as_ref()) 310 let data = db.const_data(c);
309 && (mode == LookupMode::Path) 311 name.map_or(true, |name| data.name.as_ref() == Some(name)) && (mode == LookupMode::Path)
310 } 312 }
311 _ => false, 313 _ => false,
312 } 314 }
313} 315}
314 316
315pub(crate) fn implements_trait( 317pub fn implements_trait(
316 ty: &Canonical<Ty>, 318 ty: &Canonical<Ty>,
317 db: &impl HirDatabase, 319 db: &impl HirDatabase,
318 resolver: &Resolver, 320 resolver: &Resolver,
319 krate: Crate, 321 krate: CrateId,
320 trait_: Trait, 322 trait_: TraitId,
321) -> bool { 323) -> bool {
322 if ty.value.inherent_trait() == Some(trait_) { 324 if ty.value.inherent_trait() == Some(trait_) {
323 // FIXME this is a bit of a hack, since Chalk should say the same thing 325 // FIXME this is a bit of a hack, since Chalk should say the same thing
324 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet 326 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
325 return true; 327 return true;
326 } 328 }
327 let env = lower::trait_env(db, resolver); 329 let env = TraitEnvironment::lower(db, resolver);
328 let goal = generic_implements_goal(db, env, trait_, ty.clone()); 330 let goal = generic_implements_goal(db, env, trait_, ty.clone());
329 let solution = db.trait_solve(krate, goal); 331 let solution = db.trait_solve(krate.into(), goal);
330 332
331 solution.is_some() 333 solution.is_some()
332} 334}
333 335
334impl Ty {
335 // This would be nicer if it just returned an iterator, but that runs into
336 // lifetime problems, because we need to borrow temp `CrateImplBlocks`.
337 pub fn iterate_impl_items<T>(
338 self,
339 db: &impl HirDatabase,
340 krate: Crate,
341 mut callback: impl FnMut(AssocItem) -> Option<T>,
342 ) -> Option<T> {
343 for krate in def_crates(db, krate, &self)? {
344 let impls = db.impls_in_crate(krate);
345
346 for impl_block in impls.lookup_impl_blocks(&self) {
347 for item in impl_block.items(db) {
348 if let Some(result) = callback(item) {
349 return Some(result);
350 }
351 }
352 }
353 }
354 None
355 }
356}
357
358/// This creates Substs for a trait with the given Self type and type variables 336/// This creates Substs for a trait with the given Self type and type variables
359/// for all other parameters, to query Chalk with it. 337/// for all other parameters, to query Chalk with it.
360fn generic_implements_goal( 338fn generic_implements_goal(
361 db: &impl HirDatabase, 339 db: &impl HirDatabase,
362 env: Arc<TraitEnvironment>, 340 env: Arc<TraitEnvironment>,
363 trait_: Trait, 341 trait_: TraitId,
364 self_ty: Canonical<Ty>, 342 self_ty: Canonical<Ty>,
365) -> Canonical<InEnvironment<super::Obligation>> { 343) -> Canonical<InEnvironment<super::Obligation>> {
366 let num_vars = self_ty.num_vars; 344 let num_vars = self_ty.num_vars;
diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir_ty/src/op.rs
index bcfa3a6a2..09c47a76d 100644
--- a/crates/ra_hir/src/ty/op.rs
+++ b/crates/ra_hir_ty/src/op.rs
@@ -1,10 +1,8 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use hir_def::expr::{BinaryOp, CmpOp};
2 3
3use super::{InferTy, Ty, TypeCtor}; 4use super::{InferTy, Ty, TypeCtor};
4use crate::{ 5use crate::ApplicationTy;
5 expr::{BinaryOp, CmpOp},
6 ty::ApplicationTy,
7};
8 6
9pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { 7pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty {
10 match op { 8 match op {
diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir_ty/src/primitive.rs
index 47789db87..02a8179d9 100644
--- a/crates/ra_hir/src/ty/primitive.rs
+++ b/crates/ra_hir_ty/src/primitive.rs
@@ -1,8 +1,11 @@
1//! FIXME: write short doc here 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.
2 5
3use std::fmt; 6use std::fmt;
4 7
5pub use hir_def::builtin_type::{FloatBitness, IntBitness, Signedness}; 8pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, FloatBitness, IntBitness, Signedness};
6 9
7#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] 10#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
8pub enum Uncertain<T> { 11pub enum Uncertain<T> {
@@ -107,7 +110,7 @@ impl IntTy {
107 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 } 110 IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 }
108 } 111 }
109 112
110 pub(crate) fn ty_to_string(self) -> &'static str { 113 pub fn ty_to_string(self) -> &'static str {
111 match (self.signedness, self.bitness) { 114 match (self.signedness, self.bitness) {
112 (Signedness::Signed, IntBitness::Xsize) => "isize", 115 (Signedness::Signed, IntBitness::Xsize) => "isize",
113 (Signedness::Signed, IntBitness::X8) => "i8", 116 (Signedness::Signed, IntBitness::X8) => "i8",
@@ -151,10 +154,40 @@ impl FloatTy {
151 FloatTy { bitness: FloatBitness::X64 } 154 FloatTy { bitness: FloatBitness::X64 }
152 } 155 }
153 156
154 pub(crate) fn ty_to_string(self) -> &'static str { 157 pub fn ty_to_string(self) -> &'static str {
155 match self.bitness { 158 match self.bitness {
156 FloatBitness::X32 => "f32", 159 FloatBitness::X32 => "f32",
157 FloatBitness::X64 => "f64", 160 FloatBitness::X64 => "f64",
158 } 161 }
159 } 162 }
160} 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_hir/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index efee2f658..1dc9793f9 100644
--- a/crates/ra_hir/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -1,21 +1,23 @@
1//! Database used for testing `hir`. 1//! Database used for testing `hir`.
2 2
3use std::{panic, sync::Arc}; 3use std::{
4 panic,
5 sync::{Arc, Mutex},
6};
4 7
5use hir_def::{db::DefDatabase, ModuleId}; 8use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId, ModuleId};
6use hir_expand::diagnostics::DiagnosticSink; 9use hir_expand::diagnostics::DiagnosticSink;
7use parking_lot::Mutex;
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase}; 10use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, SourceDatabase};
9 11
10use crate::{db, debug::HirDebugHelper}; 12use crate::{db::HirDatabase, expr::ExprValidator};
11 13
12#[salsa::database( 14#[salsa::database(
13 ra_db::SourceDatabaseExtStorage, 15 ra_db::SourceDatabaseExtStorage,
14 ra_db::SourceDatabaseStorage, 16 ra_db::SourceDatabaseStorage,
15 db::InternDatabaseStorage, 17 hir_expand::db::AstDatabaseStorage,
16 db::AstDatabaseStorage, 18 hir_def::db::InternDatabaseStorage,
17 db::DefDatabaseStorage, 19 hir_def::db::DefDatabaseStorage,
18 db::HirDatabaseStorage 20 crate::db::HirDatabaseStorage
19)] 21)]
20#[derive(Debug, Default)] 22#[derive(Debug, Default)]
21pub struct TestDB { 23pub struct TestDB {
@@ -28,8 +30,12 @@ impl salsa::Database for TestDB {
28 &self.runtime 30 &self.runtime
29 } 31 }
30 32
33 fn salsa_runtime_mut(&mut self) -> &mut salsa::Runtime<Self> {
34 &mut self.runtime
35 }
36
31 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) { 37 fn salsa_event(&self, event: impl Fn() -> salsa::Event<TestDB>) {
32 let mut events = self.events.lock(); 38 let mut events = self.events.lock().unwrap();
33 if let Some(events) = &mut *events { 39 if let Some(events) = &mut *events {
34 events.push(event()); 40 events.push(event());
35 } 41 }
@@ -63,32 +69,53 @@ impl FileLoader for TestDB {
63 } 69 }
64} 70}
65 71
66// FIXME: improve `WithFixture` to bring useful hir debugging back 72impl TestDB {
67impl HirDebugHelper for TestDB { 73 pub fn module_for_file(&self, file_id: FileId) -> ModuleId {
68 fn crate_name(&self, _krate: CrateId) -> Option<String> { 74 for &krate in self.relevant_crates(file_id).iter() {
69 None 75 let crate_def_map = self.crate_def_map(krate);
76 for (local_id, data) in crate_def_map.modules.iter() {
77 if data.definition == Some(file_id) {
78 return ModuleId { krate, local_id };
79 }
80 }
81 }
82 panic!("Can't find module for file")
70 } 83 }
71 84
72 fn file_path(&self, _file_id: FileId) -> Option<String> { 85 // FIXME: don't duplicate this
73 None
74 }
75}
76
77impl TestDB {
78 pub fn diagnostics(&self) -> String { 86 pub fn diagnostics(&self) -> String {
79 let mut buf = String::new(); 87 let mut buf = String::new();
80 let crate_graph = self.crate_graph(); 88 let crate_graph = self.crate_graph();
81 for krate in crate_graph.iter().next() { 89 for krate in crate_graph.iter().next() {
82 let crate_def_map = self.crate_def_map(krate); 90 let crate_def_map = self.crate_def_map(krate);
91
92 let mut fns = Vec::new();
83 for (module_id, _) in crate_def_map.modules.iter() { 93 for (module_id, _) in crate_def_map.modules.iter() {
84 let module_id = ModuleId { krate, module_id }; 94 for decl in crate_def_map[module_id].scope.declarations() {
85 let module = crate::Module::from(module_id); 95 match decl {
86 module.diagnostics( 96 ModuleDefId::FunctionId(f) => fns.push(f),
87 self, 97 _ => (),
88 &mut DiagnosticSink::new(|d| { 98 }
89 buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message()); 99 }
90 }), 100
91 ) 101 for &impl_id in crate_def_map[module_id].impls.iter() {
102 let impl_data = self.impl_data(impl_id);
103 for item in impl_data.items.iter() {
104 if let AssocItemId::FunctionId(f) = item {
105 fns.push(*f)
106 }
107 }
108 }
109 }
110
111 for f in fns {
112 let infer = self.infer(f.into());
113 let mut sink = DiagnosticSink::new(|d| {
114 buf += &format!("{:?}: {}\n", d.syntax_node(self).text(), d.message());
115 });
116 infer.add_diagnostics(self, f, &mut sink);
117 let mut validator = ExprValidator::new(f, infer, &mut sink);
118 validator.validate_body(self);
92 } 119 }
93 } 120 }
94 buf 121 buf
@@ -97,9 +124,9 @@ impl TestDB {
97 124
98impl TestDB { 125impl TestDB {
99 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> { 126 pub fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event<TestDB>> {
100 *self.events.lock() = Some(Vec::new()); 127 *self.events.lock().unwrap() = Some(Vec::new());
101 f(); 128 f();
102 self.events.lock().take().unwrap() 129 self.events.lock().unwrap().take().unwrap()
103 } 130 }
104 131
105 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> { 132 pub fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 3209c66bd..c8461b447 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -4,20 +4,20 @@ mod coercion;
4use std::fmt::Write; 4use std::fmt::Write;
5use std::sync::Arc; 5use std::sync::Arc;
6 6
7use hir_def::{
8 body::BodySourceMap, db::DefDatabase, nameres::CrateDefMap, AssocItemId, DefWithBodyId,
9 LocalModuleId, Lookup, ModuleDefId,
10};
11use hir_expand::Source;
7use insta::assert_snapshot; 12use insta::assert_snapshot;
8use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; 13use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
9use ra_syntax::{ 14use ra_syntax::{
10 algo, 15 algo,
11 ast::{self, AstNode}, 16 ast::{self, AstNode},
12 SyntaxKind::*,
13}; 17};
14use rustc_hash::FxHashSet;
15use test_utils::covers; 18use test_utils::covers;
16 19
17use crate::{ 20use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult};
18 expr::BodySourceMap, test_db::TestDB, ty::display::HirDisplay, ty::InferenceResult, Source,
19 SourceAnalyzer,
20};
21 21
22// These tests compare the inference results for all expressions in a file 22// These tests compare the inference results for all expressions in a file
23// against snapshots of the expected results using insta. Use cargo-insta to 23// against snapshots of the expected results using insta. Use cargo-insta to
@@ -4674,10 +4674,20 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
4674fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { 4674fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
4675 let file = db.parse(pos.file_id).ok().unwrap(); 4675 let file = db.parse(pos.file_id).ok().unwrap();
4676 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 4676 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
4677 let analyzer = 4677
4678 SourceAnalyzer::new(db, Source::new(pos.file_id.into(), expr.syntax()), Some(pos.offset)); 4678 let module = db.module_for_file(pos.file_id);
4679 let ty = analyzer.type_of(db, &expr).unwrap(); 4679 let crate_def_map = db.crate_def_map(module.krate);
4680 ty.display(db).to_string() 4680 for decl in crate_def_map[module.local_id].scope.declarations() {
4681 if let ModuleDefId::FunctionId(func) = decl {
4682 let (_body, source_map) = db.body_with_source_map(func.into());
4683 if let Some(expr_id) = source_map.node_expr(Source::new(pos.file_id.into(), &expr)) {
4684 let infer = db.infer(func.into());
4685 let ty = &infer[expr_id];
4686 return ty.display(db).to_string();
4687 }
4688 }
4689 }
4690 panic!("Can't find expression")
4681} 4691}
4682 4692
4683fn type_at(content: &str) -> String { 4693fn type_at(content: &str) -> String {
@@ -4687,7 +4697,6 @@ fn type_at(content: &str) -> String {
4687 4697
4688fn infer(content: &str) -> String { 4698fn infer(content: &str) -> String {
4689 let (db, file_id) = TestDB::with_single_file(content); 4699 let (db, file_id) = TestDB::with_single_file(content);
4690 let source_file = db.parse(file_id).ok().unwrap();
4691 4700
4692 let mut acc = String::new(); 4701 let mut acc = String::new();
4693 4702
@@ -4740,20 +4749,69 @@ fn infer(content: &str) -> String {
4740 } 4749 }
4741 }; 4750 };
4742 4751
4743 let mut analyzed = FxHashSet::default(); 4752 let module = db.module_for_file(file_id);
4744 for node in source_file.syntax().descendants() { 4753 let crate_def_map = db.crate_def_map(module.krate);
4745 if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { 4754
4746 let analyzer = SourceAnalyzer::new(&db, Source::new(file_id.into(), &node), None); 4755 let mut defs: Vec<DefWithBodyId> = Vec::new();
4747 if analyzed.insert(analyzer.analyzed_declaration()) { 4756 visit_module(&db, &crate_def_map, module.local_id, &mut |it| defs.push(it));
4748 infer_def(analyzer.inference_result(), analyzer.body_source_map()); 4757 defs.sort_by_key(|def| match def {
4749 } 4758 DefWithBodyId::FunctionId(it) => {
4759 it.lookup(&db).ast_id.to_node(&db).syntax().text_range().start()
4760 }
4761 DefWithBodyId::ConstId(it) => {
4762 it.lookup(&db).ast_id.to_node(&db).syntax().text_range().start()
4763 }
4764 DefWithBodyId::StaticId(it) => {
4765 it.lookup(&db).ast_id.to_node(&db).syntax().text_range().start()
4750 } 4766 }
4767 });
4768 for def in defs {
4769 let (_body, source_map) = db.body_with_source_map(def);
4770 let infer = db.infer(def);
4771 infer_def(infer, source_map);
4751 } 4772 }
4752 4773
4753 acc.truncate(acc.trim_end().len()); 4774 acc.truncate(acc.trim_end().len());
4754 acc 4775 acc
4755} 4776}
4756 4777
4778fn visit_module(
4779 db: &TestDB,
4780 crate_def_map: &CrateDefMap,
4781 module_id: LocalModuleId,
4782 cb: &mut dyn FnMut(DefWithBodyId),
4783) {
4784 for decl in crate_def_map[module_id].scope.declarations() {
4785 match decl {
4786 ModuleDefId::FunctionId(it) => cb(it.into()),
4787 ModuleDefId::ConstId(it) => cb(it.into()),
4788 ModuleDefId::StaticId(it) => cb(it.into()),
4789 ModuleDefId::TraitId(it) => {
4790 let trait_data = db.trait_data(it);
4791 for &(_, item) in trait_data.items.iter() {
4792 match item {
4793 AssocItemId::FunctionId(it) => cb(it.into()),
4794 AssocItemId::ConstId(it) => cb(it.into()),
4795 AssocItemId::TypeAliasId(_) => (),
4796 }
4797 }
4798 }
4799 ModuleDefId::ModuleId(it) => visit_module(db, crate_def_map, it.local_id, cb),
4800 _ => (),
4801 }
4802 }
4803 for &impl_id in crate_def_map[module_id].impls.iter() {
4804 let impl_data = db.impl_data(impl_id);
4805 for &item in impl_data.items.iter() {
4806 match item {
4807 AssocItemId::FunctionId(it) => cb(it.into()),
4808 AssocItemId::ConstId(it) => cb(it.into()),
4809 AssocItemId::TypeAliasId(_) => (),
4810 }
4811 }
4812 }
4813}
4814
4757fn ellipsize(mut text: String, max_len: usize) -> String { 4815fn ellipsize(mut text: String, max_len: usize) -> String {
4758 if text.len() <= max_len { 4816 if text.len() <= max_len {
4759 return text; 4817 return text;
@@ -4783,10 +4841,12 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
4783 ", 4841 ",
4784 ); 4842 );
4785 { 4843 {
4786 let file = db.parse(pos.file_id).ok().unwrap();
4787 let node = file.syntax().token_at_offset(pos.offset).right_biased().unwrap().parent();
4788 let events = db.log_executed(|| { 4844 let events = db.log_executed(|| {
4789 SourceAnalyzer::new(&db, Source::new(pos.file_id.into(), &node), None); 4845 let module = db.module_for_file(pos.file_id);
4846 let crate_def_map = db.crate_def_map(module.krate);
4847 visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
4848 db.infer(def);
4849 });
4790 }); 4850 });
4791 assert!(format!("{:?}", events).contains("infer")) 4851 assert!(format!("{:?}", events).contains("infer"))
4792 } 4852 }
@@ -4803,10 +4863,12 @@ fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
4803 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text)); 4863 db.query_mut(ra_db::FileTextQuery).set(pos.file_id, Arc::new(new_text));
4804 4864
4805 { 4865 {
4806 let file = db.parse(pos.file_id).ok().unwrap();
4807 let node = file.syntax().token_at_offset(pos.offset).right_biased().unwrap().parent();
4808 let events = db.log_executed(|| { 4866 let events = db.log_executed(|| {
4809 SourceAnalyzer::new(&db, Source::new(pos.file_id.into(), &node), None); 4867 let module = db.module_for_file(pos.file_id);
4868 let crate_def_map = db.crate_def_map(module.krate);
4869 visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
4870 db.infer(def);
4871 });
4810 }); 4872 });
4811 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events) 4873 assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
4812 } 4874 }
@@ -4832,7 +4894,8 @@ fn no_such_field_diagnostics() {
4832 4894
4833 assert_snapshot!(diagnostics, @r###" 4895 assert_snapshot!(diagnostics, @r###"
4834 "baz: 62": no such field 4896 "baz: 62": no such field
4835 "{\n foo: 92,\n baz: 62,\n }": fill structure fields 4897 "{\n foo: 92,\n baz: 62,\n }": Missing structure fields:
4898 - bar
4836 "### 4899 "###
4837 ); 4900 );
4838} 4901}
diff --git a/crates/ra_hir/src/ty/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs
index 1530fcc63..1530fcc63 100644
--- a/crates/ra_hir/src/ty/tests/coercion.rs
+++ b/crates/ra_hir_ty/src/tests/coercion.rs
diff --git a/crates/ra_hir/src/ty/tests/never_type.rs b/crates/ra_hir_ty/src/tests/never_type.rs
index c202f545a..c202f545a 100644
--- a/crates/ra_hir/src/ty/tests/never_type.rs
+++ b/crates/ra_hir_ty/src/tests/never_type.rs
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir_ty/src/traits.rs
index 268fa09e4..76189a60b 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir_ty/src/traits.rs
@@ -2,13 +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::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId};
5use log::debug; 6use log::debug;
6use ra_db::{impl_intern_key, salsa}; 7use ra_db::{impl_intern_key, salsa, CrateId};
7use ra_prof::profile; 8use ra_prof::profile;
8use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
9 10
11use crate::db::HirDatabase;
12
10use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 13use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
11use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait, TypeAlias};
12 14
13use self::chalk::{from_chalk, ToChalk}; 15use self::chalk::{from_chalk, ToChalk};
14 16
@@ -16,7 +18,7 @@ pub(crate) mod chalk;
16 18
17#[derive(Debug, Clone)] 19#[derive(Debug, Clone)]
18pub struct TraitSolver { 20pub struct TraitSolver {
19 krate: Crate, 21 krate: CrateId,
20 inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>, 22 inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>,
21} 23}
22 24
@@ -58,12 +60,12 @@ const CHALK_SOLVER_MAX_SIZE: usize = 4;
58#[derive(Debug, Copy, Clone)] 60#[derive(Debug, Copy, Clone)]
59struct ChalkContext<'a, DB> { 61struct ChalkContext<'a, DB> {
60 db: &'a DB, 62 db: &'a DB,
61 krate: Crate, 63 krate: CrateId,
62} 64}
63 65
64pub(crate) fn trait_solver_query( 66pub(crate) fn trait_solver_query(
65 db: &(impl HirDatabase + salsa::Database), 67 db: &(impl HirDatabase + salsa::Database),
66 krate: Crate, 68 krate: CrateId,
67) -> TraitSolver { 69) -> TraitSolver {
68 db.salsa_runtime().report_untracked_read(); 70 db.salsa_runtime().report_untracked_read();
69 // krate parameter is just so we cache a unique solver per crate 71 // krate parameter is just so we cache a unique solver per crate
@@ -75,17 +77,17 @@ pub(crate) fn trait_solver_query(
75/// Collects impls for the given trait in the whole dependency tree of `krate`. 77/// Collects impls for the given trait in the whole dependency tree of `krate`.
76pub(crate) fn impls_for_trait_query( 78pub(crate) fn impls_for_trait_query(
77 db: &impl HirDatabase, 79 db: &impl HirDatabase,
78 krate: Crate, 80 krate: CrateId,
79 trait_: Trait, 81 trait_: TraitId,
80) -> Arc<[ImplBlock]> { 82) -> Arc<[ImplId]> {
81 let mut impls = FxHashSet::default(); 83 let mut impls = FxHashSet::default();
82 // We call the query recursively here. On the one hand, this means we can 84 // We call the query recursively here. On the one hand, this means we can
83 // reuse results from queries for different crates; on the other hand, this 85 // reuse results from queries for different crates; on the other hand, this
84 // will only ever get called for a few crates near the root of the tree (the 86 // will only ever get called for a few crates near the root of the tree (the
85 // ones the user is editing), so this may actually be a waste of memory. I'm 87 // ones the user is editing), so this may actually be a waste of memory. I'm
86 // doing it like this mainly for simplicity for now. 88 // doing it like this mainly for simplicity for now.
87 for dep in krate.dependencies(db) { 89 for dep in db.crate_graph().dependencies(krate) {
88 impls.extend(db.impls_for_trait(dep.krate, trait_).iter()); 90 impls.extend(db.impls_for_trait(dep.crate_id, trait_).iter());
89 } 91 }
90 let crate_impl_blocks = db.impls_in_crate(krate); 92 let crate_impl_blocks = db.impls_in_crate(krate);
91 impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_)); 93 impls.extend(crate_impl_blocks.lookup_impl_blocks_for_trait(trait_));
@@ -174,7 +176,7 @@ impl TypeWalk for ProjectionPredicate {
174/// Solve a trait goal using Chalk. 176/// Solve a trait goal using Chalk.
175pub(crate) fn trait_solve_query( 177pub(crate) fn trait_solve_query(
176 db: &impl HirDatabase, 178 db: &impl HirDatabase,
177 krate: Crate, 179 krate: CrateId,
178 goal: Canonical<InEnvironment<Obligation>>, 180 goal: Canonical<InEnvironment<Obligation>>,
179) -> Option<Solution> { 181) -> Option<Solution> {
180 let _p = profile("trait_solve_query"); 182 let _p = profile("trait_solve_query");
@@ -290,7 +292,7 @@ impl FnTrait {
290 292
291#[derive(Debug, Clone, PartialEq, Eq, Hash)] 293#[derive(Debug, Clone, PartialEq, Eq, Hash)]
292pub struct ClosureFnTraitImplData { 294pub struct ClosureFnTraitImplData {
293 def: DefWithBody, 295 def: DefWithBodyId,
294 expr: ExprId, 296 expr: ExprId,
295 fn_trait: FnTrait, 297 fn_trait: FnTrait,
296} 298}
@@ -300,7 +302,7 @@ pub struct ClosureFnTraitImplData {
300#[derive(Debug, Clone, PartialEq, Eq, Hash)] 302#[derive(Debug, Clone, PartialEq, Eq, Hash)]
301pub enum Impl { 303pub enum Impl {
302 /// A normal impl from an impl block. 304 /// A normal impl from an impl block.
303 ImplBlock(ImplBlock), 305 ImplBlock(ImplId),
304 /// Closure types implement the Fn traits synthetically. 306 /// Closure types implement the Fn traits synthetically.
305 ClosureFnTraitImpl(ClosureFnTraitImplData), 307 ClosureFnTraitImpl(ClosureFnTraitImplData),
306} 308}
@@ -315,7 +317,7 @@ impl_intern_key!(GlobalImplId);
315#[derive(Debug, Clone, PartialEq, Eq, Hash)] 317#[derive(Debug, Clone, PartialEq, Eq, Hash)]
316pub enum AssocTyValue { 318pub enum AssocTyValue {
317 /// A normal assoc type value from an impl block. 319 /// A normal assoc type value from an impl block.
318 TypeAlias(TypeAlias), 320 TypeAlias(TypeAliasId),
319 /// The output type of the Fn trait implementation. 321 /// The output type of the Fn trait implementation.
320 ClosureFnTraitImplOutput(ClosureFnTraitImplData), 322 ClosureFnTraitImplOutput(ClosureFnTraitImplData),
321} 323}
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs
index 1a93e5e50..35de37e6b 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir_ty/src/traits/chalk.rs
@@ -4,22 +4,24 @@ use std::sync::Arc;
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{ 6use chalk_ir::{
7 cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, 7 cast::Cast, family::ChalkIr, Identifier, Parameter, PlaceholderIndex, TypeId, TypeKindId,
8 TypeKindId, TypeName, UniverseIndex, 8 TypeName, UniverseIndex,
9}; 9};
10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; 10use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum};
11use ra_db::CrateId;
11 12
12use hir_def::lang_item::LangItemTarget; 13use hir_def::{
14 expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId,
15 ImplId, Lookup, TraitId, TypeAliasId,
16};
13use hir_expand::name; 17use hir_expand::name;
14 18
15use ra_db::salsa::{InternId, InternKey}; 19use ra_db::salsa::{InternId, InternKey};
16 20
17use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; 21use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation};
18use crate::{ 22use crate::{
19 db::HirDatabase, 23 db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy,
20 ty::display::HirDisplay, 24 Substs, TraitRef, Ty, TypeCtor, TypeWalk,
21 ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk},
22 Crate, GenericDef, ImplBlock, Trait, 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
@@ -203,15 +205,15 @@ impl ToChalk for Impl {
203 } 205 }
204} 206}
205 207
206impl ToChalk for TypeAlias { 208impl ToChalk for TypeAliasId {
207 type Chalk = chalk_ir::TypeId; 209 type Chalk = chalk_ir::TypeId;
208 210
209 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { 211 fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId {
210 chalk_ir::TypeId(id_to_chalk(self.id)) 212 chalk_ir::TypeId(id_to_chalk(self))
211 } 213 }
212 214
213 fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAlias { 215 fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAliasId {
214 TypeAlias { id: id_from_chalk(type_alias_id.0) } 216 id_from_chalk(type_alias_id.0)
215 } 217 }
216} 218}
217 219
@@ -402,7 +404,7 @@ fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> {
402 404
403fn convert_where_clauses( 405fn convert_where_clauses(
404 db: &impl HirDatabase, 406 db: &impl HirDatabase,
405 def: GenericDef, 407 def: GenericDefId,
406 substs: &Substs, 408 substs: &Substs,
407) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> { 409) -> Vec<chalk_ir::QuantifiedWhereClause<ChalkIr>> {
408 let generic_predicates = db.generic_predicates(def); 410 let generic_predicates = db.generic_predicates(def);
@@ -431,25 +433,25 @@ where
431 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { 433 fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> {
432 self.db.struct_datum(self.krate, struct_id) 434 self.db.struct_datum(self.krate, struct_id)
433 } 435 }
434 fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum<ChalkIr>> { 436 fn impl_datum(&self, impl_id: chalk_ir::ImplId) -> Arc<ImplDatum<ChalkIr>> {
435 self.db.impl_datum(self.krate, impl_id) 437 self.db.impl_datum(self.krate, impl_id)
436 } 438 }
437 fn impls_for_trait( 439 fn impls_for_trait(
438 &self, 440 &self,
439 trait_id: chalk_ir::TraitId, 441 trait_id: chalk_ir::TraitId,
440 parameters: &[Parameter<ChalkIr>], 442 parameters: &[Parameter<ChalkIr>],
441 ) -> Vec<ImplId> { 443 ) -> Vec<chalk_ir::ImplId> {
442 debug!("impls_for_trait {:?}", trait_id); 444 debug!("impls_for_trait {:?}", trait_id);
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(|it| Impl::ImplBlock(it.into()))
453 .map(|impl_| impl_.to_chalk(self.db)) 455 .map(|impl_| impl_.to_chalk(self.db))
454 .collect(); 456 .collect();
455 457
@@ -485,7 +487,7 @@ where
485 &self, 487 &self,
486 id: chalk_rust_ir::AssociatedTyValueId, 488 id: chalk_rust_ir::AssociatedTyValueId,
487 ) -> Arc<AssociatedTyValue<ChalkIr>> { 489 ) -> Arc<AssociatedTyValue<ChalkIr>> {
488 self.db.associated_ty_value(self.krate, id) 490 self.db.associated_ty_value(self.krate.into(), id)
489 } 491 }
490 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { 492 fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> {
491 vec![] 493 vec![]
@@ -504,12 +506,12 @@ pub(crate) fn associated_ty_data_query(
504 id: TypeId, 506 id: TypeId,
505) -> Arc<AssociatedTyDatum<ChalkIr>> { 507) -> Arc<AssociatedTyDatum<ChalkIr>> {
506 debug!("associated_ty_data {:?}", id); 508 debug!("associated_ty_data {:?}", id);
507 let type_alias: TypeAlias = from_chalk(db, id); 509 let type_alias: TypeAliasId = from_chalk(db, id);
508 let trait_ = match type_alias.container(db) { 510 let trait_ = match type_alias.lookup(db).container {
509 Some(crate::Container::Trait(t)) => t, 511 ContainerId::TraitId(t) => t,
510 _ => panic!("associated type not in trait"), 512 _ => panic!("associated type not in trait"),
511 }; 513 };
512 let generic_params = db.generic_params(type_alias.id.into()); 514 let generic_params = db.generic_params(type_alias.into());
513 let bound_data = chalk_rust_ir::AssociatedTyDatumBound { 515 let bound_data = chalk_rust_ir::AssociatedTyDatumBound {
514 // FIXME add bounds and where clauses 516 // FIXME add bounds and where clauses
515 bounds: vec![], 517 bounds: vec![],
@@ -518,7 +520,7 @@ pub(crate) fn associated_ty_data_query(
518 let datum = AssociatedTyDatum { 520 let datum = AssociatedTyDatum {
519 trait_id: trait_.to_chalk(db), 521 trait_id: trait_.to_chalk(db),
520 id, 522 id,
521 name: lalrpop_intern::intern(&type_alias.name(db).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()),
523 }; 525 };
524 Arc::new(datum) 526 Arc::new(datum)
@@ -526,7 +528,7 @@ pub(crate) fn associated_ty_data_query(
526 528
527pub(crate) fn trait_datum_query( 529pub(crate) fn trait_datum_query(
528 db: &impl HirDatabase, 530 db: &impl HirDatabase,
529 krate: Crate, 531 krate: CrateId,
530 trait_id: chalk_ir::TraitId, 532 trait_id: chalk_ir::TraitId,
531) -> Arc<TraitDatum<ChalkIr>> { 533) -> Arc<TraitDatum<ChalkIr>> {
532 debug!("trait_datum {:?}", trait_id); 534 debug!("trait_datum {:?}", trait_id);
@@ -548,13 +550,14 @@ 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,
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
@@ -562,15 +565,8 @@ pub(crate) fn trait_datum_query(
562 fundamental: false, 565 fundamental: false,
563 }; 566 };
564 let where_clauses = convert_where_clauses(db, trait_.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),
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,
@@ -583,7 +579,7 @@ pub(crate) fn trait_datum_query(
583 579
584pub(crate) fn struct_datum_query( 580pub(crate) fn struct_datum_query(
585 db: &impl HirDatabase, 581 db: &impl HirDatabase,
586 krate: Crate, 582 krate: CrateId,
587 struct_id: chalk_ir::StructId, 583 struct_id: chalk_ir::StructId,
588) -> Arc<StructDatum<ChalkIr>> { 584) -> Arc<StructDatum<ChalkIr>> {
589 debug!("struct_datum {:?}", struct_id); 585 debug!("struct_datum {:?}", struct_id);
@@ -615,8 +611,8 @@ pub(crate) fn struct_datum_query(
615 611
616pub(crate) fn impl_datum_query( 612pub(crate) fn impl_datum_query(
617 db: &impl HirDatabase, 613 db: &impl HirDatabase,
618 krate: Crate, 614 krate: CrateId,
619 impl_id: ImplId, 615 impl_id: chalk_ir::ImplId,
620) -> Arc<ImplDatum<ChalkIr>> { 616) -> Arc<ImplDatum<ChalkIr>> {
621 let _p = ra_prof::profile("impl_datum"); 617 let _p = ra_prof::profile("impl_datum");
622 debug!("impl_datum {:?}", impl_id); 618 debug!("impl_datum {:?}", impl_id);
@@ -630,24 +626,30 @@ pub(crate) fn impl_datum_query(
630 626
631fn impl_block_datum( 627fn impl_block_datum(
632 db: &impl HirDatabase, 628 db: &impl HirDatabase,
633 krate: Crate, 629 krate: CrateId,
630 chalk_id: chalk_ir::ImplId,
634 impl_id: ImplId, 631 impl_id: ImplId,
635 impl_block: ImplBlock,
636) -> Option<Arc<ImplDatum<ChalkIr>>> { 632) -> Option<Arc<ImplDatum<ChalkIr>>> {
637 let generic_params = db.generic_params(impl_block.id.into()); 633 let trait_ref = match db.impl_ty(impl_id) {
634 ImplTy::TraitRef(it) => it,
635 ImplTy::Inherent(_) => return None,
636 };
637 let impl_data = db.impl_data(impl_id);
638
639 let generic_params = db.generic_params(impl_id.into());
638 let bound_vars = Substs::bound_vars(&generic_params); 640 let bound_vars = Substs::bound_vars(&generic_params);
639 let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); 641 let trait_ref = trait_ref.subst(&bound_vars);
640 let trait_ = trait_ref.trait_; 642 let trait_ = trait_ref.trait_;
641 let impl_type = if impl_block.krate(db) == krate { 643 let impl_type = if impl_id.module(db).krate == krate {
642 chalk_rust_ir::ImplType::Local 644 chalk_rust_ir::ImplType::Local
643 } else { 645 } else {
644 chalk_rust_ir::ImplType::External 646 chalk_rust_ir::ImplType::External
645 }; 647 };
646 let where_clauses = convert_where_clauses(db, impl_block.into(), &bound_vars); 648 let where_clauses = convert_where_clauses(db, impl_id.into(), &bound_vars);
647 let negative = impl_block.is_negative(db); 649 let negative = impl_data.is_negative;
648 debug!( 650 debug!(
649 "impl {:?}: {}{} where {:?}", 651 "impl {:?}: {}{} where {:?}",
650 impl_id, 652 chalk_id,
651 if negative { "!" } else { "" }, 653 if negative { "!" } else { "" },
652 trait_ref.display(db), 654 trait_ref.display(db),
653 where_clauses 655 where_clauses
@@ -661,16 +663,18 @@ fn impl_block_datum(
661 }; 663 };
662 664
663 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; 665 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses };
664 let associated_ty_value_ids = impl_block 666 let trait_data = db.trait_data(trait_);
665 .items(db) 667 let associated_ty_value_ids = impl_data
666 .into_iter() 668 .items
669 .iter()
667 .filter_map(|item| match item { 670 .filter_map(|item| match item {
668 crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), 671 AssocItemId::TypeAliasId(type_alias) => Some(*type_alias),
669 _ => None, 672 _ => None,
670 }) 673 })
671 .filter(|type_alias| { 674 .filter(|&type_alias| {
672 // don't include associated types that don't exist in the trait 675 // 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() 676 let name = &db.type_alias_data(type_alias).name;
677 trait_data.associated_type_by_name(name).is_some()
674 }) 678 })
675 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) 679 .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db))
676 .collect(); 680 .collect();
@@ -701,7 +705,7 @@ fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> {
701 705
702fn closure_fn_trait_impl_datum( 706fn closure_fn_trait_impl_datum(
703 db: &impl HirDatabase, 707 db: &impl HirDatabase,
704 krate: Crate, 708 krate: CrateId,
705 data: super::ClosureFnTraitImplData, 709 data: super::ClosureFnTraitImplData,
706) -> Option<Arc<ImplDatum<ChalkIr>>> { 710) -> Option<Arc<ImplDatum<ChalkIr>>> {
707 // for some closure |X, Y| -> Z: 711 // for some closure |X, Y| -> Z:
@@ -713,10 +717,10 @@ fn closure_fn_trait_impl_datum(
713 // and don't want to return a valid value only to find out later that FnOnce 717 // and don't want to return a valid value only to find out later that FnOnce
714 // is broken 718 // is broken
715 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; 719 let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
716 fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; 720 let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?;
717 721
718 let num_args: u16 = match &db.body(data.def.into())[data.expr] { 722 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
719 crate::expr::Expr::Lambda { args, .. } => args.len() as u16, 723 Expr::Lambda { args, .. } => args.len() as u16,
720 _ => { 724 _ => {
721 log::warn!("closure for closure type {:?} not found", data); 725 log::warn!("closure for closure type {:?} not found", data);
722 0 726 0
@@ -735,7 +739,7 @@ fn closure_fn_trait_impl_datum(
735 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); 739 let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty);
736 740
737 let trait_ref = TraitRef { 741 let trait_ref = TraitRef {
738 trait_, 742 trait_: trait_.into(),
739 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), 743 substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(),
740 }; 744 };
741 745
@@ -758,7 +762,7 @@ fn closure_fn_trait_impl_datum(
758 762
759pub(crate) fn associated_ty_value_query( 763pub(crate) fn associated_ty_value_query(
760 db: &impl HirDatabase, 764 db: &impl HirDatabase,
761 krate: Crate, 765 krate: CrateId,
762 id: chalk_rust_ir::AssociatedTyValueId, 766 id: chalk_rust_ir::AssociatedTyValueId,
763) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { 767) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> {
764 let data: AssocTyValue = from_chalk(db, id); 768 let data: AssocTyValue = from_chalk(db, id);
@@ -774,24 +778,31 @@ pub(crate) fn associated_ty_value_query(
774 778
775fn type_alias_associated_ty_value( 779fn type_alias_associated_ty_value(
776 db: &impl HirDatabase, 780 db: &impl HirDatabase,
777 _krate: Crate, 781 _krate: CrateId,
778 type_alias: TypeAlias, 782 type_alias: TypeAliasId,
779) -> Arc<AssociatedTyValue<ChalkIr>> { 783) -> Arc<AssociatedTyValue<ChalkIr>> {
780 let impl_block = type_alias.impl_block(db).expect("assoc ty value should be in impl"); 784 let type_alias_data = db.type_alias_data(type_alias);
781 let impl_id = Impl::ImplBlock(impl_block).to_chalk(db); 785 let impl_id = match type_alias.lookup(db).container {
782 let trait_ = impl_block 786 ContainerId::ImplId(it) => it,
783 .target_trait_ref(db) 787 _ => panic!("assoc ty value should be in impl"),
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 788 };
785 .trait_; 789
786 let assoc_ty = trait_ 790 let trait_ref = match db.impl_ty(impl_id) {
787 .associated_type_by_name(db, &type_alias.name(db)) 791 ImplTy::TraitRef(it) => it,
792 // we don't return any assoc ty values if the impl'd trait can't be resolved
793 ImplTy::Inherent(_) => panic!("assoc ty value should not exist"),
794 };
795
796 let assoc_ty = db
797 .trait_data(trait_ref.trait_)
798 .associated_type_by_name(&type_alias_data.name)
788 .expect("assoc ty value should not exist"); // validated when building the impl data as well 799 .expect("assoc ty value should not exist"); // validated when building the impl data as well
789 let generic_params = db.generic_params(impl_block.id.into()); 800 let generic_params = db.generic_params(impl_id.into());
790 let bound_vars = Substs::bound_vars(&generic_params); 801 let bound_vars = Substs::bound_vars(&generic_params);
791 let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); 802 let ty = db.ty(type_alias.into()).subst(&bound_vars);
792 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 803 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
793 let value = chalk_rust_ir::AssociatedTyValue { 804 let value = chalk_rust_ir::AssociatedTyValue {
794 impl_id, 805 impl_id: Impl::ImplBlock(impl_id.into()).to_chalk(db),
795 associated_ty_id: assoc_ty.to_chalk(db), 806 associated_ty_id: assoc_ty.to_chalk(db),
796 value: make_binders(value_bound, bound_vars.len()), 807 value: make_binders(value_bound, bound_vars.len()),
797 }; 808 };
@@ -800,13 +811,13 @@ fn type_alias_associated_ty_value(
800 811
801fn closure_fn_trait_output_assoc_ty_value( 812fn closure_fn_trait_output_assoc_ty_value(
802 db: &impl HirDatabase, 813 db: &impl HirDatabase,
803 krate: Crate, 814 krate: CrateId,
804 data: super::ClosureFnTraitImplData, 815 data: super::ClosureFnTraitImplData,
805) -> Arc<AssociatedTyValue<ChalkIr>> { 816) -> Arc<AssociatedTyValue<ChalkIr>> {
806 let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); 817 let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db);
807 818
808 let num_args: u16 = match &db.body(data.def.into())[data.expr] { 819 let num_args: u16 = match &db.body(data.def.into())[data.expr] {
809 crate::expr::Expr::Lambda { args, .. } => args.len() as u16, 820 Expr::Lambda { args, .. } => args.len() as u16,
810 _ => { 821 _ => {
811 log::warn!("closure for closure type {:?} not found", data); 822 log::warn!("closure for closure type {:?} not found", data);
812 0 823 0
@@ -818,8 +829,9 @@ fn closure_fn_trait_output_assoc_ty_value(
818 let fn_once_trait = 829 let fn_once_trait =
819 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); 830 get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist");
820 831
821 let output_ty_id = fn_once_trait 832 let output_ty_id = db
822 .associated_type_by_name(db, &name::OUTPUT_TYPE) 833 .trait_data(fn_once_trait)
834 .associated_type_by_name(&name::OUTPUT_TYPE)
823 .expect("assoc ty value should not exist"); 835 .expect("assoc ty value should not exist");
824 836
825 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; 837 let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) };
@@ -832,10 +844,14 @@ fn closure_fn_trait_output_assoc_ty_value(
832 Arc::new(value) 844 Arc::new(value)
833} 845}
834 846
835fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { 847fn get_fn_trait(
836 let target = db.lang_item(krate.crate_id, fn_trait.lang_item_name().into())?; 848 db: &impl HirDatabase,
849 krate: CrateId,
850 fn_trait: super::FnTrait,
851) -> Option<TraitId> {
852 let target = db.lang_item(krate, fn_trait.lang_item_name().into())?;
837 match target { 853 match target {
838 LangItemTarget::TraitId(t) => Some(t.into()), 854 LangItemTarget::TraitId(t) => Some(t),
839 _ => None, 855 _ => None,
840 } 856 }
841} 857}
@@ -847,38 +863,38 @@ fn id_to_chalk<T: InternKey>(salsa_id: T) -> chalk_ir::RawId {
847 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } 863 chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() }
848} 864}
849 865
850impl From<chalk_ir::StructId> for crate::ty::TypeCtorId { 866impl From<chalk_ir::StructId> for crate::TypeCtorId {
851 fn from(struct_id: chalk_ir::StructId) -> Self { 867 fn from(struct_id: chalk_ir::StructId) -> Self {
852 id_from_chalk(struct_id.0) 868 id_from_chalk(struct_id.0)
853 } 869 }
854} 870}
855 871
856impl From<crate::ty::TypeCtorId> for chalk_ir::StructId { 872impl From<crate::TypeCtorId> for chalk_ir::StructId {
857 fn from(type_ctor_id: crate::ty::TypeCtorId) -> Self { 873 fn from(type_ctor_id: crate::TypeCtorId) -> Self {
858 chalk_ir::StructId(id_to_chalk(type_ctor_id)) 874 chalk_ir::StructId(id_to_chalk(type_ctor_id))
859 } 875 }
860} 876}
861 877
862impl From<chalk_ir::ImplId> for crate::ty::traits::GlobalImplId { 878impl From<chalk_ir::ImplId> for crate::traits::GlobalImplId {
863 fn from(impl_id: chalk_ir::ImplId) -> Self { 879 fn from(impl_id: chalk_ir::ImplId) -> Self {
864 id_from_chalk(impl_id.0) 880 id_from_chalk(impl_id.0)
865 } 881 }
866} 882}
867 883
868impl From<crate::ty::traits::GlobalImplId> for chalk_ir::ImplId { 884impl From<crate::traits::GlobalImplId> for chalk_ir::ImplId {
869 fn from(impl_id: crate::ty::traits::GlobalImplId) -> Self { 885 fn from(impl_id: crate::traits::GlobalImplId) -> Self {
870 chalk_ir::ImplId(id_to_chalk(impl_id)) 886 chalk_ir::ImplId(id_to_chalk(impl_id))
871 } 887 }
872} 888}
873 889
874impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ty::traits::AssocTyValueId { 890impl From<chalk_rust_ir::AssociatedTyValueId> for crate::traits::AssocTyValueId {
875 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { 891 fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self {
876 id_from_chalk(id.0) 892 id_from_chalk(id.0)
877 } 893 }
878} 894}
879 895
880impl From<crate::ty::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { 896impl From<crate::traits::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId {
881 fn from(assoc_ty_value_id: crate::ty::traits::AssocTyValueId) -> Self { 897 fn from(assoc_ty_value_id: crate::traits::AssocTyValueId) -> Self {
882 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) 898 chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id))
883 } 899 }
884} 900}
diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs
new file mode 100644
index 000000000..e4ba890ef
--- /dev/null
+++ b/crates/ra_hir_ty/src/utils.rs
@@ -0,0 +1,84 @@
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`).
3use std::sync::Arc;
4
5use hir_def::{
6 adt::VariantData,
7 db::DefDatabase,
8 resolver::{HasResolver, TypeNs},
9 type_ref::TypeRef,
10 TraitId, TypeAliasId, VariantId,
11};
12use hir_expand::name::{self, Name};
13
14// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
15// We should return a `TraitREf` here.
16fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
17 let resolver = trait_.resolver(db);
18 // returning the iterator directly doesn't easily work because of
19 // lifetime problems, but since there usually shouldn't be more than a
20 // few direct traits this should be fine (we could even use some kind of
21 // SmallVec if performance is a concern)
22 db.generic_params(trait_.into())
23 .where_predicates
24 .iter()
25 .filter_map(|pred| match &pred.type_ref {
26 TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
27 _ => None,
28 })
29 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
30 Some(TypeNs::TraitId(t)) => Some(t),
31 _ => None,
32 })
33 .collect()
34}
35
36/// Returns an iterator over the whole super trait hierarchy (including the
37/// trait itself).
38pub(super) fn all_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
39 // we need to take care a bit here to avoid infinite loops in case of cycles
40 // (i.e. if we have `trait A: B; trait B: A;`)
41 let mut result = vec![trait_];
42 let mut i = 0;
43 while i < result.len() {
44 let t = result[i];
45 // yeah this is quadratic, but trait hierarchies should be flat
46 // enough that this doesn't matter
47 for tt in direct_super_traits(db, t) {
48 if !result.contains(&tt) {
49 result.push(tt);
50 }
51 }
52 i += 1;
53 }
54 result
55}
56
57pub(super) fn associated_type_by_name_including_super_traits(
58 db: &impl DefDatabase,
59 trait_: TraitId,
60 name: &Name,
61) -> Option<TypeAliasId> {
62 all_super_traits(db, trait_)
63 .into_iter()
64 .find_map(|t| db.trait_data(t).associated_type_by_name(name))
65}
66
67pub(super) fn variant_data(db: &impl DefDatabase, var: VariantId) -> Arc<VariantData> {
68 match var {
69 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
70 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
71 VariantId::EnumVariantId(it) => {
72 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
73 }
74 }
75}
76
77/// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices).
78/// The underlying values are cloned if there are other strong references.
79pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
80 if Arc::get_mut(a).is_none() {
81 *a = a.iter().cloned().collect();
82 }
83 Arc::get_mut(a).unwrap()
84}
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide/Cargo.toml
index 15346f388..e6383dd35 100644
--- a/crates/ra_ide_api/Cargo.toml
+++ b/crates/ra_ide/Cargo.toml
@@ -1,6 +1,6 @@
1[package] 1[package]
2edition = "2018" 2edition = "2018"
3name = "ra_ide_api" 3name = "ra_ide"
4version = "0.1.0" 4version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6 6
@@ -32,7 +32,7 @@ ra_prof = { path = "../ra_prof" }
32test_utils = { path = "../test_utils" } 32test_utils = { path = "../test_utils" }
33ra_assists = { path = "../ra_assists" } 33ra_assists = { path = "../ra_assists" }
34 34
35# ra_ide_api should depend only on the top-level `hir` package. if you need 35# ra_ide should depend only on the top-level `hir` package. if you need
36# something from some `hir_xxx` subpackage, reexport the API via `hir`. 36# something from some `hir_xxx` subpackage, reexport the API via `hir`.
37hir = { path = "../ra_hir", package = "ra_hir" } 37hir = { path = "../ra_hir", package = "ra_hir" }
38 38
diff --git a/crates/ra_ide_api/src/assists.rs b/crates/ra_ide/src/assists.rs
index e00589733..e00589733 100644
--- a/crates/ra_ide_api/src/assists.rs
+++ b/crates/ra_ide/src/assists.rs
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide/src/call_info.rs
index 7c367230e..d559dc4d0 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide/src/call_info.rs
@@ -18,22 +18,22 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
18 // Find the calling expression and it's NameRef 18 // Find the calling expression and it's NameRef
19 let calling_node = FnCallNode::with_node(&syntax, position.offset)?; 19 let calling_node = FnCallNode::with_node(&syntax, position.offset)?;
20 let name_ref = calling_node.name_ref()?; 20 let name_ref = calling_node.name_ref()?;
21 let name_ref = hir::Source::new(position.file_id.into(), name_ref.syntax());
21 22
22 let analyzer = hir::SourceAnalyzer::new( 23 let analyzer = hir::SourceAnalyzer::new(db, name_ref, None);
23 db,
24 hir::Source::new(position.file_id.into(), name_ref.syntax()),
25 None,
26 );
27 let (mut call_info, has_self) = match &calling_node { 24 let (mut call_info, has_self) = match &calling_node {
28 FnCallNode::CallExpr(expr) => { 25 FnCallNode::CallExpr(expr) => {
29 //FIXME: apply subst 26 //FIXME: Type::as_callable is broken
30 let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; 27 let callable_def = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
31 match callable_def { 28 match callable_def {
32 hir::CallableDef::Function(it) => { 29 hir::CallableDef::FunctionId(it) => {
33 (CallInfo::with_fn(db, it), it.has_self_param(db)) 30 let fn_def = it.into();
31 (CallInfo::with_fn(db, fn_def), fn_def.has_self_param(db))
32 }
33 hir::CallableDef::StructId(it) => (CallInfo::with_struct(db, it.into())?, false),
34 hir::CallableDef::EnumVariantId(it) => {
35 (CallInfo::with_enum_variant(db, it.into())?, false)
34 } 36 }
35 hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false),
36 hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false),
37 } 37 }
38 } 38 }
39 FnCallNode::MethodCallExpr(expr) => { 39 FnCallNode::MethodCallExpr(expr) => {
@@ -41,7 +41,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
41 (CallInfo::with_fn(db, function), function.has_self_param(db)) 41 (CallInfo::with_fn(db, function), function.has_self_param(db))
42 } 42 }
43 FnCallNode::MacroCallExpr(expr) => { 43 FnCallNode::MacroCallExpr(expr) => {
44 let macro_def = analyzer.resolve_macro_call(db, &expr)?; 44 let macro_def = analyzer.resolve_macro_call(db, name_ref.with_value(&expr))?;
45 (CallInfo::with_macro(db, macro_def)?, false) 45 (CallInfo::with_macro(db, macro_def)?, false)
46 } 46 }
47 }; 47 };
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide/src/change.rs
index 0f692460d..4a76d1dd8 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide/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());
@@ -323,7 +323,8 @@ impl RootDatabase {
323 hir::db::DocumentationQuery 323 hir::db::DocumentationQuery
324 hir::db::ExprScopesQuery 324 hir::db::ExprScopesQuery
325 hir::db::InferQuery 325 hir::db::InferQuery
326 hir::db::TypeForDefQuery 326 hir::db::TyQuery
327 hir::db::ValueTyQuery
327 hir::db::FieldTypesQuery 328 hir::db::FieldTypesQuery
328 hir::db::CallableItemSignatureQuery 329 hir::db::CallableItemSignatureQuery
329 hir::db::GenericPredicatesQuery 330 hir::db::GenericPredicatesQuery
diff --git a/crates/ra_ide_api/src/completion.rs b/crates/ra_ide/src/completion.rs
index abe1f36ce..abe1f36ce 100644
--- a/crates/ra_ide_api/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 5a3f9b5f6..b6fe48627 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide/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_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs
index 502458706..502458706 100644
--- a/crates/ra_ide_api/src/completion/complete_fn_param.rs
+++ b/crates/ra_ide/src/completion/complete_fn_param.rs
diff --git a/crates/ra_ide_api/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index eb7cd9ac2..eb7cd9ac2 100644
--- a/crates/ra_ide_api/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
diff --git a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
index faadd1e3f..faadd1e3f 100644
--- a/crates/ra_ide_api/src/completion/complete_macro_in_item_position.rs
+++ b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index 63e25e0bf..89e0009a1 100644
--- a/crates/ra_ide_api/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -50,7 +50,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
50 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 50 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
51 _ => unreachable!(), 51 _ => unreachable!(),
52 }; 52 };
53 ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| { 53 ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| {
54 match item { 54 match item {
55 hir::AssocItem::Function(func) => { 55 hir::AssocItem::Function(func) => {
56 if !func.has_self_param(ctx.db) { 56 if !func.has_self_param(ctx.db) {
diff --git a/crates/ra_ide_api/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs
index fd03b1c40..fd03b1c40 100644
--- a/crates/ra_ide_api/src/completion/complete_pattern.rs
+++ b/crates/ra_ide/src/completion/complete_pattern.rs
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs
index 17b75cf7e..646a30c76 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide/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/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/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/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/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/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs
index d5739b58a..d5739b58a 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide/src/completion/complete_scope.rs
diff --git a/crates/ra_ide_api/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs
index 1f2988b36..1f2988b36 100644
--- a/crates/ra_ide_api/src/completion/complete_snippet.rs
+++ b/crates/ra_ide/src/completion/complete_snippet.rs
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index b8345c91d..b8345c91d 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 93f336370..93f336370 100644
--- a/crates/ra_ide_api/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index bac3f7582..97475fc0b 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide/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
@@ -269,10 +267,7 @@ impl Completions {
269 267
270 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { 268 pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) {
271 let is_deprecated = is_deprecated(variant, ctx.db); 269 let is_deprecated = is_deprecated(variant, ctx.db);
272 let name = match variant.name(ctx.db) { 270 let name = variant.name(ctx.db);
273 Some(it) => it,
274 None => return,
275 };
276 let detail_types = variant.fields(ctx.db).into_iter().map(|field| field.ty(ctx.db)); 271 let detail_types = variant.fields(ctx.db).into_iter().map(|field| field.ty(ctx.db));
277 let detail = join(detail_types.map(|t| t.display(ctx.db).to_string())) 272 let detail = join(detail_types.map(|t| t.display(ctx.db).to_string()))
278 .separator(", ") 273 .separator(", ")
@@ -291,11 +286,6 @@ fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool {
291 node.attrs(db).by_key("deprecated").exists() 286 node.attrs(db).by_key("deprecated").exists()
292} 287}
293 288
294fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool {
295 let subst = db.generic_defaults(def);
296 subst.iter().any(|ty| ty == &Ty::Unknown)
297}
298
299#[cfg(test)] 289#[cfg(test)]
300mod tests { 290mod tests {
301 use insta::assert_debug_snapshot; 291 use insta::assert_debug_snapshot;
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide/src/db.rs
index c2a9dcdd1..f739ebecd 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide/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/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index cc1ccab4b..cc1ccab4b 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
diff --git a/crates/ra_ide_api/src/display.rs b/crates/ra_ide/src/display.rs
index 30617412a..30617412a 100644
--- a/crates/ra_ide_api/src/display.rs
+++ b/crates/ra_ide/src/display.rs
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs
index d96de4e4c..324ad9552 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide/src/display/function_signature.rs
@@ -93,12 +93,9 @@ impl FunctionSignature {
93 _ => (), 93 _ => (),
94 }; 94 };
95 95
96 let parent_name = match variant.parent_enum(db).name(db) { 96 let parent_name = variant.parent_enum(db).name(db).to_string();
97 Some(name) => name.to_string(),
98 None => "missing".into(),
99 };
100 97
101 let name = format!("{}::{}", parent_name, variant.name(db).unwrap()); 98 let name = format!("{}::{}", parent_name, variant.name(db));
102 99
103 let params = variant 100 let params = variant
104 .fields(db) 101 .fields(db)
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs
index 6ac60722b..6ac60722b 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide/src/display/navigation_target.rs
diff --git a/crates/ra_ide_api/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs
index 5d2bce3d2..9ffc9b980 100644
--- a/crates/ra_ide_api/src/display/short_label.rs
+++ b/crates/ra_ide/src/display/short_label.rs
@@ -19,6 +19,12 @@ impl ShortLabel for ast::StructDef {
19 } 19 }
20} 20}
21 21
22impl ShortLabel for ast::UnionDef {
23 fn short_label(&self) -> Option<String> {
24 short_label_from_node(self, "union ")
25 }
26}
27
22impl ShortLabel for ast::EnumDef { 28impl ShortLabel for ast::EnumDef {
23 fn short_label(&self) -> Option<String> { 29 fn short_label(&self) -> Option<String> {
24 short_label_from_node(self, "enum ") 30 short_label_from_node(self, "enum ")
diff --git a/crates/ra_ide_api/src/display/structure.rs b/crates/ra_ide/src/display/structure.rs
index a80d65ac7..a80d65ac7 100644
--- a/crates/ra_ide_api/src/display/structure.rs
+++ b/crates/ra_ide/src/display/structure.rs
diff --git a/crates/ra_ide_api/src/expand.rs b/crates/ra_ide/src/expand.rs
index 2f1abf509..2f1abf509 100644
--- a/crates/ra_ide_api/src/expand.rs
+++ b/crates/ra_ide/src/expand.rs
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs
index 0b540b8cd..abc602244 100644
--- a/crates/ra_ide_api/src/expand_macro.rs
+++ b/crates/ra_ide/src/expand_macro.rs
@@ -269,4 +269,27 @@ fn some_thing() -> u32 {
269 assert_eq!(res.name, "foo"); 269 assert_eq!(res.name, "foo");
270 assert_snapshot!(res.expansion, @r###"bar!()"###); 270 assert_snapshot!(res.expansion, @r###"bar!()"###);
271 } 271 }
272
273 #[test]
274 fn macro_expand_with_dollar_crate() {
275 let res = check_expand_macro(
276 r#"
277 //- /lib.rs
278 #[macro_export]
279 macro_rules! bar {
280 () => {0};
281 }
282 macro_rules! foo {
283 () => {$crate::bar!()};
284 }
285
286 fn main() {
287 let res = fo<|>o!();
288 }
289 "#,
290 );
291
292 assert_eq!(res.name, "foo");
293 assert_snapshot!(res.expansion, @r###"0"###);
294 }
272} 295}
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs
index 4b7bfc0b1..4b7bfc0b1 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide/src/extend_selection.rs
diff --git a/crates/ra_ide_api/src/feature_flags.rs b/crates/ra_ide/src/feature_flags.rs
index de4ae513d..de4ae513d 100644
--- a/crates/ra_ide_api/src/feature_flags.rs
+++ b/crates/ra_ide/src/feature_flags.rs
diff --git a/crates/ra_ide_api/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs
index 4eeb76d14..4eeb76d14 100644
--- a/crates/ra_ide_api/src/folding_ranges.rs
+++ b/crates/ra_ide/src/folding_ranges.rs
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index b6c72efdf..c10a6c844 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -71,10 +71,11 @@ pub(crate) fn reference_definition(
71 Some(nav) => return Exact(nav), 71 Some(nav) => return Exact(nav),
72 None => return Approximate(vec![]), 72 None => return Approximate(vec![]),
73 }, 73 },
74 Some(SelfType(ty)) => { 74 Some(SelfType(imp)) => {
75 if let Some((adt, _)) = ty.as_adt() { 75 // FIXME: ideally, this should point to the type in the impl, and
76 return Exact(adt.to_nav(db)); 76 // not at the whole impl. And goto **type** definition should bring
77 } 77 // us to the actual type
78 return Exact(imp.to_nav(db));
78 } 79 }
79 Some(Local(local)) => return Exact(local.to_nav(db)), 80 Some(Local(local)) => return Exact(local.to_nav(db)),
80 Some(GenericParam(_)) => { 81 Some(GenericParam(_)) => {
@@ -503,7 +504,7 @@ mod tests {
503 } 504 }
504 } 505 }
505 ", 506 ",
506 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", 507 "impl IMPL_BLOCK FileId(1) [12; 73)",
507 ); 508 );
508 509
509 check_goto( 510 check_goto(
@@ -516,7 +517,7 @@ mod tests {
516 } 517 }
517 } 518 }
518 ", 519 ",
519 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", 520 "impl IMPL_BLOCK FileId(1) [12; 73)",
520 ); 521 );
521 522
522 check_goto( 523 check_goto(
@@ -529,7 +530,7 @@ mod tests {
529 } 530 }
530 } 531 }
531 ", 532 ",
532 "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", 533 "impl IMPL_BLOCK FileId(1) [15; 75)",
533 ); 534 );
534 535
535 check_goto( 536 check_goto(
@@ -541,7 +542,7 @@ mod tests {
541 } 542 }
542 } 543 }
543 ", 544 ",
544 "Foo ENUM_DEF FileId(1) [0; 14) [5; 8)", 545 "impl IMPL_BLOCK FileId(1) [15; 62)",
545 ); 546 );
546 } 547 }
547 548
@@ -560,7 +561,7 @@ mod tests {
560 } 561 }
561 } 562 }
562 ", 563 ",
563 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", 564 "impl IMPL_BLOCK FileId(1) [49; 115)",
564 ); 565 );
565 566
566 check_goto( 567 check_goto(
@@ -572,11 +573,11 @@ mod tests {
572 } 573 }
573 impl Make for Foo { 574 impl Make for Foo {
574 fn new() -> Self<|> { 575 fn new() -> Self<|> {
575 Self{} 576 Self {}
576 } 577 }
577 } 578 }
578 ", 579 ",
579 "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", 580 "impl IMPL_BLOCK FileId(1) [49; 115)",
580 ); 581 );
581 } 582 }
582 583
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs
index 28a83a3e2..992a08809 100644
--- a/crates/ra_ide_api/src/goto_type_definition.rs
+++ b/crates/ra_ide/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/hover.rs b/crates/ra_ide/src/hover.rs
index 9839be985..260a7b869 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -133,20 +133,12 @@ fn hover_text_from_name_kind(
133 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), 133 hir::ModuleDef::TypeAlias(it) => from_def_source(db, it),
134 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), 134 hir::ModuleDef::BuiltinType(it) => Some(it.to_string()),
135 }, 135 },
136 SelfType(ty) => match ty.as_adt() {
137 Some((adt_def, _)) => match adt_def {
138 hir::Adt::Struct(it) => from_def_source(db, it),
139 hir::Adt::Union(it) => from_def_source(db, it),
140 hir::Adt::Enum(it) => from_def_source(db, it),
141 },
142 _ => None,
143 },
144 Local(_) => { 136 Local(_) => {
145 // Hover for these shows type names 137 // Hover for these shows type names
146 *no_fallback = true; 138 *no_fallback = true;
147 None 139 None
148 } 140 }
149 GenericParam(_) => { 141 GenericParam(_) | SelfType(_) => {
150 // FIXME: Hover for generic param 142 // FIXME: Hover for generic param
151 None 143 None
152 } 144 }
@@ -622,49 +614,52 @@ fn func(foo: i32) { if true { <|>foo; }; }
622 ", 614 ",
623 ); 615 );
624 let hover = analysis.hover(position).unwrap().unwrap(); 616 let hover = analysis.hover(position).unwrap().unwrap();
625 assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing")); 617 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing"));
626 assert_eq!(hover.info.is_exact(), true);
627
628 let (analysis, position) = single_file_with_position(
629 "
630 struct Thing { x: u32 }
631 impl Thing {
632 fn new() -> Self<|> {
633 Self { x: 0 }
634 }
635 }
636 ",
637 );
638 let hover = analysis.hover(position).unwrap().unwrap();
639 assert_eq!(trim_markup_opt(hover.info.first()), Some("struct Thing"));
640 assert_eq!(hover.info.is_exact(), true);
641
642 let (analysis, position) = single_file_with_position(
643 "
644 enum Thing { A }
645 impl Thing {
646 pub fn new() -> Self<|> {
647 Thing::A
648 }
649 }
650 ",
651 );
652 let hover = analysis.hover(position).unwrap().unwrap();
653 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
654 assert_eq!(hover.info.is_exact(), true); 618 assert_eq!(hover.info.is_exact(), true);
655 619
656 let (analysis, position) = single_file_with_position( 620 /* FIXME: revive these tests
657 " 621 let (analysis, position) = single_file_with_position(
658 enum Thing { A } 622 "
659 impl Thing { 623 struct Thing { x: u32 }
660 pub fn thing(a: Self<|>) { 624 impl Thing {
661 } 625 fn new() -> Self<|> {
662 } 626 Self { x: 0 }
663 ", 627 }
664 ); 628 }
665 let hover = analysis.hover(position).unwrap().unwrap(); 629 ",
666 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); 630 );
667 assert_eq!(hover.info.is_exact(), true); 631
632 let hover = analysis.hover(position).unwrap().unwrap();
633 assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing"));
634 assert_eq!(hover.info.is_exact(), true);
635
636 let (analysis, position) = single_file_with_position(
637 "
638 enum Thing { A }
639 impl Thing {
640 pub fn new() -> Self<|> {
641 Thing::A
642 }
643 }
644 ",
645 );
646 let hover = analysis.hover(position).unwrap().unwrap();
647 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
648 assert_eq!(hover.info.is_exact(), true);
649
650 let (analysis, position) = single_file_with_position(
651 "
652 enum Thing { A }
653 impl Thing {
654 pub fn thing(a: Self<|>) {
655 }
656 }
657 ",
658 );
659 let hover = analysis.hover(position).unwrap().unwrap();
660 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
661 assert_eq!(hover.info.is_exact(), true);
662 */
668 } 663 }
669 664
670 #[test] 665 #[test]
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide/src/impls.rs
index 3e3012559..aa480e399 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide/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::{FromSource, ImplBlock};
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
@@ -49,15 +49,19 @@ fn impls_for_def(
49 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; 49 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
50 hir::Enum::from_source(db, src)?.ty(db) 50 hir::Enum::from_source(db, src)?.ty(db)
51 } 51 }
52 ast::NominalDef::UnionDef(def) => {
53 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
54 hir::Union::from_source(db, src)?.ty(db)
55 }
52 }; 56 };
53 57
54 let krate = module.krate(); 58 let krate = module.krate();
55 let impls = db.impls_in_crate(krate); 59 let impls = ImplBlock::all_in_crate(db, krate);
56 60
57 Some( 61 Some(
58 impls 62 impls
59 .all_impls() 63 .into_iter()
60 .filter(|impl_block| is_equal_for_find_impls(&ty, &impl_block.target_ty(db))) 64 .filter(|impl_block| ty.is_equal_for_find_impls(&impl_block.target_ty(db)))
61 .map(|imp| imp.to_nav(db)) 65 .map(|imp| imp.to_nav(db))
62 .collect(), 66 .collect(),
63 ) 67 )
@@ -73,22 +77,9 @@ fn impls_for_trait(
73 let tr = hir::Trait::from_source(db, src)?; 77 let tr = hir::Trait::from_source(db, src)?;
74 78
75 let krate = module.krate(); 79 let krate = module.krate();
76 let impls = db.impls_in_crate(krate); 80 let impls = ImplBlock::for_trait(db, krate, tr);
77 81
78 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())
79}
80
81fn is_equal_for_find_impls(original_ty: &Ty, impl_ty: &Ty) -> bool {
82 match (original_ty, impl_ty) {
83 (Ty::Apply(a_original_ty), Ty::Apply(ApplicationTy { ctor, parameters })) => match ctor {
84 TypeCtor::Ref(..) => match parameters.as_single() {
85 Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor,
86 _ => false,
87 },
88 _ => a_original_ty.ctor == *ctor,
89 },
90 _ => false,
91 }
92} 83}
93 84
94#[cfg(test)] 85#[cfg(test)]
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs
index 24a7ca5e7..45149bf0c 100644
--- a/crates/ra_ide_api/src/inlay_hints.rs
+++ b/crates/ra_ide/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/join_lines.rs b/crates/ra_ide/src/join_lines.rs
index 7deeb3494..7deeb3494 100644
--- a/crates/ra_ide_api/src/join_lines.rs
+++ b/crates/ra_ide/src/join_lines.rs
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide/src/lib.rs
index cb6c24eaa..d1bff4a76 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -1,4 +1,4 @@
1//! ra_ide_api crate provides "ide-centric" APIs for the rust-analyzer. That is, 1//! ra_ide crate provides "ide-centric" APIs for the rust-analyzer. That is,
2//! it generally operates with files and text ranges, and returns results as 2//! it generally operates with files and text ranges, and returns results as
3//! Strings, suitable for displaying to the human. 3//! Strings, suitable for displaying to the human.
4//! 4//!
diff --git a/crates/ra_ide_api/src/line_index.rs b/crates/ra_ide/src/line_index.rs
index 710890d27..710890d27 100644
--- a/crates/ra_ide_api/src/line_index.rs
+++ b/crates/ra_ide/src/line_index.rs
diff --git a/crates/ra_ide_api/src/line_index_utils.rs b/crates/ra_ide/src/line_index_utils.rs
index bd1e08feb..bd1e08feb 100644
--- a/crates/ra_ide_api/src/line_index_utils.rs
+++ b/crates/ra_ide/src/line_index_utils.rs
diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide/src/marks.rs
index 848ae4dc7..848ae4dc7 100644
--- a/crates/ra_ide_api/src/marks.rs
+++ b/crates/ra_ide/src/marks.rs
diff --git a/crates/ra_ide_api/src/matching_brace.rs b/crates/ra_ide/src/matching_brace.rs
index d1204fac0..d1204fac0 100644
--- a/crates/ra_ide_api/src/matching_brace.rs
+++ b/crates/ra_ide/src/matching_brace.rs
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs
index bf8a54932..bf8a54932 100644
--- a/crates/ra_ide_api/src/mock_analysis.rs
+++ b/crates/ra_ide/src/mock_analysis.rs
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs
index 6027e7d54..6027e7d54 100644
--- a/crates/ra_ide_api/src/parent_module.rs
+++ b/crates/ra_ide/src/parent_module.rs
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide/src/references.rs
index cb343e59a..21a1ea69e 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide/src/references.rs
@@ -83,10 +83,7 @@ pub(crate) fn find_all_refs(
83 NameKind::Field(field) => field.to_nav(db), 83 NameKind::Field(field) => field.to_nav(db),
84 NameKind::AssocItem(assoc) => assoc.to_nav(db), 84 NameKind::AssocItem(assoc) => assoc.to_nav(db),
85 NameKind::Def(def) => NavigationTarget::from_def(db, def)?, 85 NameKind::Def(def) => NavigationTarget::from_def(db, def)?,
86 NameKind::SelfType(ref ty) => match ty.as_adt() { 86 NameKind::SelfType(imp) => imp.to_nav(db),
87 Some((adt, _)) => adt.to_nav(db),
88 None => return None,
89 },
90 NameKind::Local(local) => local.to_nav(db), 87 NameKind::Local(local) => local.to_nav(db),
91 NameKind::GenericParam(_) => return None, 88 NameKind::GenericParam(_) => return None,
92 }; 89 };
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index cab06dea9..5cea805ec 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -152,7 +152,7 @@ pub(crate) fn classify_name_ref(
152 152
153 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 153 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
154 tested_by!(goto_definition_works_for_macros); 154 tested_by!(goto_definition_works_for_macros);
155 if let Some(macro_def) = analyzer.resolve_macro_call(db, &macro_call) { 155 if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(&macro_call)) {
156 let kind = NameKind::Macro(macro_def); 156 let kind = NameKind::Macro(macro_def);
157 return Some(NameDefinition { kind, container, visibility }); 157 return Some(NameDefinition { kind, container, visibility });
158 } 158 }
@@ -178,8 +178,7 @@ pub(crate) fn classify_name_ref(
178 Some(NameDefinition { kind, container, visibility }) 178 Some(NameDefinition { kind, container, visibility })
179 } 179 }
180 PathResolution::SelfType(impl_block) => { 180 PathResolution::SelfType(impl_block) => {
181 let ty = impl_block.target_ty(db); 181 let kind = NameKind::SelfType(impl_block);
182 let kind = NameKind::SelfType(ty);
183 let container = impl_block.module(db); 182 let container = impl_block.module(db);
184 Some(NameDefinition { kind, container, visibility }) 183 Some(NameDefinition { kind, container, visibility })
185 } 184 }
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide/src/references/name_definition.rs
index aca23f79e..10d3a2364 100644
--- a/crates/ra_ide_api/src/references/name_definition.rs
+++ b/crates/ra_ide/src/references/name_definition.rs
@@ -4,8 +4,8 @@
4//! Note that the reference search is possible for not all of the classified items. 4//! Note that the reference search is possible for not all of the classified items.
5 5
6use hir::{ 6use hir::{
7 Adt, AssocItem, GenericParam, HasSource, Local, MacroDef, Module, ModuleDef, StructField, Ty, 7 Adt, AssocItem, GenericParam, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef,
8 VariantDef, 8 StructField, VariantDef,
9}; 9};
10use ra_syntax::{ast, ast::VisibilityOwner}; 10use ra_syntax::{ast, ast::VisibilityOwner};
11 11
@@ -17,7 +17,7 @@ pub enum NameKind {
17 Field(StructField), 17 Field(StructField),
18 AssocItem(AssocItem), 18 AssocItem(AssocItem),
19 Def(ModuleDef), 19 Def(ModuleDef),
20 SelfType(Ty), 20 SelfType(ImplBlock),
21 Local(Local), 21 Local(Local),
22 GenericParam(GenericParam), 22 GenericParam(GenericParam),
23} 23}
@@ -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/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index d58496049..d58496049 100644
--- a/crates/ra_ide_api/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs
index f5c9589f4..f5c9589f4 100644
--- a/crates/ra_ide_api/src/references/search_scope.rs
+++ b/crates/ra_ide/src/references/search_scope.rs
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide/src/runnables.rs
index 8039a5164..8039a5164 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide/src/runnables.rs
diff --git a/crates/ra_ide_api/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index b39c4d371..b39c4d371 100644
--- a/crates/ra_ide_api/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
diff --git a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html
index 79f11ea80..79f11ea80 100644
--- a/crates/ra_ide_api/src/snapshots/rainbow_highlighting.html
+++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html
diff --git a/crates/ra_ide_api/src/source_change.rs b/crates/ra_ide/src/source_change.rs
index f5f7f8807..f5f7f8807 100644
--- a/crates/ra_ide_api/src/source_change.rs
+++ b/crates/ra_ide/src/source_change.rs
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide/src/status.rs
index 1bb27eb85..1bb27eb85 100644
--- a/crates/ra_ide_api/src/status.rs
+++ b/crates/ra_ide/src/status.rs
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide/src/symbol_index.rs
index 5729eb5b3..5729eb5b3 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide/src/symbol_index.rs
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index 2b653fe8f..9a3e4c82f 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide/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 }
@@ -307,7 +306,7 @@ fn main() {
307"# 306"#
308 .trim(), 307 .trim(),
309 ); 308 );
310 let dst_file = project_dir().join("crates/ra_ide_api/src/snapshots/highlighting.html"); 309 let dst_file = project_dir().join("crates/ra_ide/src/snapshots/highlighting.html");
311 let actual_html = &analysis.highlight_as_html(file_id, false).unwrap(); 310 let actual_html = &analysis.highlight_as_html(file_id, false).unwrap();
312 let expected_html = &read_text(&dst_file); 311 let expected_html = &read_text(&dst_file);
313 std::fs::write(dst_file, &actual_html).unwrap(); 312 std::fs::write(dst_file, &actual_html).unwrap();
@@ -333,8 +332,7 @@ fn bar() {
333"# 332"#
334 .trim(), 333 .trim(),
335 ); 334 );
336 let dst_file = 335 let dst_file = project_dir().join("crates/ra_ide/src/snapshots/rainbow_highlighting.html");
337 project_dir().join("crates/ra_ide_api/src/snapshots/rainbow_highlighting.html");
338 let actual_html = &analysis.highlight_as_html(file_id, true).unwrap(); 336 let actual_html = &analysis.highlight_as_html(file_id, true).unwrap();
339 let expected_html = &read_text(&dst_file); 337 let expected_html = &read_text(&dst_file);
340 std::fs::write(dst_file, &actual_html).unwrap(); 338 std::fs::write(dst_file, &actual_html).unwrap();
diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs
index 4d0f0fc47..4d0f0fc47 100644
--- a/crates/ra_ide_api/src/syntax_tree.rs
+++ b/crates/ra_ide/src/syntax_tree.rs
diff --git a/crates/ra_ide_api/src/test_utils.rs b/crates/ra_ide/src/test_utils.rs
index 8adb214d4..8adb214d4 100644
--- a/crates/ra_ide_api/src/test_utils.rs
+++ b/crates/ra_ide/src/test_utils.rs
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide/src/typing.rs
index 21e5be9b3..21e5be9b3 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
diff --git a/crates/ra_ide_api/src/wasm_shims.rs b/crates/ra_ide/src/wasm_shims.rs
index 088cc9be4..088cc9be4 100644
--- a/crates/ra_ide_api/src/wasm_shims.rs
+++ b/crates/ra_ide/src/wasm_shims.rs
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 72dbe06dc..21aef842c 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -17,12 +17,12 @@ 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" }
24ra_text_edit = { path = "../ra_text_edit" } 24ra_text_edit = { path = "../ra_text_edit" }
25ra_ide_api = { path = "../ra_ide_api" } 25ra_ide = { path = "../ra_ide" }
26lsp-server = "0.3.0" 26lsp-server = "0.3.0"
27ra_project_model = { path = "../ra_project_model" } 27ra_project_model = { path = "../ra_project_model" }
28ra_prof = { path = "../ra_prof" } 28ra_prof = { path = "../ra_prof" }
diff --git a/crates/ra_lsp_server/src/cargo_target_spec.rs b/crates/ra_lsp_server/src/cargo_target_spec.rs
index d996b53de..c4a9e7101 100644
--- a/crates/ra_lsp_server/src/cargo_target_spec.rs
+++ b/crates/ra_lsp_server/src/cargo_target_spec.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_ide_api::{FileId, RunnableKind}; 3use ra_ide::{FileId, RunnableKind};
4use ra_project_model::{self, ProjectWorkspace, TargetKind}; 4use ra_project_model::{self, ProjectWorkspace, TargetKind};
5 5
6use crate::{world::WorldSnapshot, Result}; 6use crate::{world::WorldSnapshot, Result};
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 94ed619fa..b13093cfe 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -6,7 +6,7 @@ use lsp_types::{
6 SymbolKind, TextDocumentEdit, TextDocumentIdentifier, TextDocumentItem, 6 SymbolKind, TextDocumentEdit, TextDocumentIdentifier, TextDocumentItem,
7 TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, WorkspaceEdit, 7 TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, WorkspaceEdit,
8}; 8};
9use ra_ide_api::{ 9use ra_ide::{
10 translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition, 10 translate_offset_with_edit, CompletionItem, CompletionItemKind, FileId, FilePosition,
11 FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex, 11 FileRange, FileSystemEdit, Fold, FoldKind, InsertTextFormat, LineCol, LineIndex,
12 NavigationTarget, RangeInfo, Severity, SourceChange, SourceFileEdit, 12 NavigationTarget, RangeInfo, Severity, SourceChange, SourceFileEdit,
@@ -173,7 +173,7 @@ impl ConvWith<&LineIndex> for Range {
173 } 173 }
174} 174}
175 175
176impl Conv for ra_ide_api::Documentation { 176impl Conv for ra_ide::Documentation {
177 type Output = lsp_types::Documentation; 177 type Output = lsp_types::Documentation;
178 fn conv(self) -> Documentation { 178 fn conv(self) -> Documentation {
179 Documentation::MarkupContent(MarkupContent { 179 Documentation::MarkupContent(MarkupContent {
@@ -183,7 +183,7 @@ impl Conv for ra_ide_api::Documentation {
183 } 183 }
184} 184}
185 185
186impl Conv for ra_ide_api::FunctionSignature { 186impl Conv for ra_ide::FunctionSignature {
187 type Output = lsp_types::SignatureInformation; 187 type Output = lsp_types::SignatureInformation;
188 fn conv(self) -> Self::Output { 188 fn conv(self) -> Self::Output {
189 use lsp_types::{ParameterInformation, ParameterLabel, SignatureInformation}; 189 use lsp_types::{ParameterInformation, ParameterLabel, SignatureInformation};
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs
index 9c36402b0..2ca149fd5 100644
--- a/crates/ra_lsp_server/src/lib.rs
+++ b/crates/ra_lsp_server/src/lib.rs
@@ -1,6 +1,6 @@
1//! Implementation of the LSP for rust-analyzer. 1//! Implementation of the LSP for rust-analyzer.
2//! 2//!
3//! This crate takes Rust-specific analysis results from ra_ide_api and 3//! This crate takes Rust-specific analysis results from ra_ide and
4//! translates into LSP types. 4//! translates into LSP types.
5//! 5//!
6//! It also is the root of all state. `world` module defines the bulk of the 6//! It also is the root of all state. `world` module defines the bulk of the
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 0dc0aeee8..83845f1e0 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -9,7 +9,7 @@ use std::{error::Error, fmt, panic, path::PathBuf, sync::Arc, time::Instant};
9use crossbeam_channel::{select, unbounded, RecvError, Sender}; 9use crossbeam_channel::{select, unbounded, RecvError, Sender};
10use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; 10use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response};
11use lsp_types::{ClientCapabilities, NumberOrString}; 11use lsp_types::{ClientCapabilities, NumberOrString};
12use ra_ide_api::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId}; 12use ra_ide::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId};
13use ra_prof::profile; 13use ra_prof::profile;
14use ra_vfs::{VfsTask, Watch}; 14use ra_vfs::{VfsTask, Watch};
15use relative_path::RelativePathBuf; 15use relative_path::RelativePathBuf;
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index e552f2106..c81fa7f67 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -9,7 +9,7 @@ use lsp_types::{
9 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse, 9 Hover, HoverContents, Location, MarkupContent, MarkupKind, Position, PrepareRenameResponse,
10 Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit, 10 Range, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, WorkspaceEdit,
11}; 11};
12use ra_ide_api::{ 12use ra_ide::{
13 AssistId, FileId, FilePosition, FileRange, Query, Runnable, RunnableKind, SearchScope, 13 AssistId, FileId, FilePosition, FileRange, Query, Runnable, RunnableKind, SearchScope,
14}; 14};
15use ra_prof::profile; 15use ra_prof::profile;
@@ -162,7 +162,7 @@ pub fn handle_on_type_formatting(
162 let line_index = world.analysis().file_line_index(position.file_id)?; 162 let line_index = world.analysis().file_line_index(position.file_id)?;
163 let line_endings = world.file_line_endings(position.file_id); 163 let line_endings = world.file_line_endings(position.file_id);
164 164
165 // in `ra_ide_api`, the `on_type` invariant is that 165 // in `ra_ide`, the `on_type` invariant is that
166 // `text.char_at(position) == typed_char`. 166 // `text.char_at(position) == typed_char`.
167 position.offset = position.offset - TextUnit::of_char('.'); 167 position.offset = position.offset - TextUnit::of_char('.');
168 let char_typed = params.ch.chars().next().unwrap_or('\0'); 168 let char_typed = params.ch.chars().next().unwrap_or('\0');
@@ -894,7 +894,7 @@ pub fn handle_inlay_hints(
894 label: api_type.label.to_string(), 894 label: api_type.label.to_string(),
895 range: api_type.range.conv_with(&line_index), 895 range: api_type.range.conv_with(&line_index),
896 kind: match api_type.kind { 896 kind: match api_type.kind {
897 ra_ide_api::InlayKind::TypeHint => InlayKind::TypeHint, 897 ra_ide::InlayKind::TypeHint => InlayKind::TypeHint,
898 }, 898 },
899 }) 899 })
900 .collect()) 900 .collect())
diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
index 3856263b0..609b2adcc 100644
--- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs
+++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use ra_ide_api::FileId; 3use ra_ide::FileId;
4use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
5 5
6#[derive(Default, Debug)] 6#[derive(Default, Debug)]
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 9bdea70c7..927449b45 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -9,7 +9,7 @@ use crossbeam_channel::{unbounded, Receiver};
9use lsp_server::ErrorCode; 9use lsp_server::ErrorCode;
10use lsp_types::Url; 10use lsp_types::Url;
11use parking_lot::RwLock; 11use parking_lot::RwLock;
12use ra_ide_api::{ 12use ra_ide::{
13 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData, 13 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FeatureFlags, FileId, LibraryData,
14 SourceRootId, 14 SourceRootId,
15}; 15};
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 85f7eeb00..370990e21 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -1,13 +1,13 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3mod consts; 3mod consts;
4mod nominal; 4mod adt;
5mod traits; 5mod traits;
6mod use_item; 6mod use_item;
7 7
8pub(crate) use self::{ 8pub(crate) use self::{
9 adt::{enum_variant_list, record_field_def_list},
9 expressions::{match_arm_list, record_field_list}, 10 expressions::{match_arm_list, record_field_list},
10 nominal::{enum_variant_list, record_field_def_list},
11 traits::{impl_item_list, trait_item_list}, 11 traits::{impl_item_list, trait_item_list},
12 use_item::use_tree_list, 12 use_item::use_tree_list,
13}; 13};
@@ -247,7 +247,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
247 // a: i32, 247 // a: i32,
248 // b: f32, 248 // b: f32,
249 // } 249 // }
250 nominal::struct_def(p, m, T![struct]); 250 adt::struct_def(p, m);
251 } 251 }
252 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 252 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
253 // test union_items 253 // test union_items
@@ -256,9 +256,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
256 // a: i32, 256 // a: i32,
257 // b: f32, 257 // b: f32,
258 // } 258 // }
259 nominal::struct_def(p, m, T![union]); 259 adt::union_def(p, m);
260 } 260 }
261 T![enum] => nominal::enum_def(p, m), 261 T![enum] => adt::enum_def(p, m),
262 T![use] => use_item::use_item(p, m), 262 T![use] => use_item::use_item(p, m),
263 T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m), 263 T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m),
264 T![static] => consts::static_def(p, m), 264 T![static] => consts::static_def(p, m),
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/adt.rs
index 9d8fb8486..c777bc9d0 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/adt.rs
@@ -2,10 +2,19 @@
2 2
3use super::*; 3use super::*;
4 4
5pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) { 5pub(super) fn struct_def(p: &mut Parser, m: Marker) {
6 assert!(p.at(T![struct]) || p.at_contextual_kw("union")); 6 assert!(p.at(T![struct]));
7 p.bump_remap(kind); 7 p.bump(T![struct]);
8 struct_or_union(p, m, T![struct], STRUCT_DEF);
9}
10
11pub(super) fn union_def(p: &mut Parser, m: Marker) {
12 assert!(p.at_contextual_kw("union"));
13 p.bump_remap(T![union]);
14 struct_or_union(p, m, T![union], UNION_DEF);
15}
8 16
17fn struct_or_union(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
9 name_r(p, ITEM_RECOVERY_SET); 18 name_r(p, ITEM_RECOVERY_SET);
10 type_params::opt_type_param_list(p); 19 type_params::opt_type_param_list(p);
11 match p.current() { 20 match p.current() {
@@ -22,11 +31,11 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
22 } 31 }
23 } 32 }
24 } 33 }
25 T![;] if kind == T![struct] => { 34 T![;] if kw == T![struct] => {
26 p.bump(T![;]); 35 p.bump(T![;]);
27 } 36 }
28 T!['{'] => record_field_def_list(p), 37 T!['{'] => record_field_def_list(p),
29 T!['('] if kind == T![struct] => { 38 T!['('] if kw == T![struct] => {
30 tuple_field_def_list(p); 39 tuple_field_def_list(p);
31 // test tuple_struct_where 40 // test tuple_struct_where
32 // struct Test<T>(T) where T: Clone; 41 // struct Test<T>(T) where T: Clone;
@@ -34,14 +43,14 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
34 type_params::opt_where_clause(p); 43 type_params::opt_where_clause(p);
35 p.expect(T![;]); 44 p.expect(T![;]);
36 } 45 }
37 _ if kind == T![struct] => { 46 _ if kw == T![struct] => {
38 p.error("expected `;`, `{`, or `(`"); 47 p.error("expected `;`, `{`, or `(`");
39 } 48 }
40 _ => { 49 _ => {
41 p.error("expected `{`"); 50 p.error("expected `{`");
42 } 51 }
43 } 52 }
44 m.complete(p, STRUCT_DEF); 53 m.complete(p, def);
45} 54}
46 55
47pub(super) fn enum_def(p: &mut Parser, m: Marker) { 56pub(super) fn enum_def(p: &mut Parser, m: Marker) {
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 96b5bce88..fe0fcdb33 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -122,6 +122,7 @@ pub enum SyntaxKind {
122 R_DOLLAR, 122 R_DOLLAR,
123 SOURCE_FILE, 123 SOURCE_FILE,
124 STRUCT_DEF, 124 STRUCT_DEF,
125 UNION_DEF,
125 ENUM_DEF, 126 ENUM_DEF,
126 FN_DEF, 127 FN_DEF,
127 RET_TYPE, 128 RET_TYPE,
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 513ed7920..a8f625176 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -196,17 +196,6 @@ impl StructKind {
196} 196}
197 197
198impl ast::StructDef { 198impl ast::StructDef {
199 pub fn is_union(&self) -> bool {
200 for child in self.syntax().children_with_tokens() {
201 match child.kind() {
202 T![struct] => return false,
203 T![union] => return true,
204 _ => (),
205 }
206 }
207 false
208 }
209
210 pub fn kind(&self) -> StructKind { 199 pub fn kind(&self) -> StructKind {
211 StructKind::from_node(self) 200 StructKind::from_node(self)
212 } 201 }
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index de506d7cd..c06076e3d 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1856,6 +1856,7 @@ impl Module {
1856#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1856#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1857pub enum ModuleItem { 1857pub enum ModuleItem {
1858 StructDef(StructDef), 1858 StructDef(StructDef),
1859 UnionDef(UnionDef),
1859 EnumDef(EnumDef), 1860 EnumDef(EnumDef),
1860 FnDef(FnDef), 1861 FnDef(FnDef),
1861 TraitDef(TraitDef), 1862 TraitDef(TraitDef),
@@ -1872,6 +1873,11 @@ impl From<StructDef> for ModuleItem {
1872 ModuleItem::StructDef(node) 1873 ModuleItem::StructDef(node)
1873 } 1874 }
1874} 1875}
1876impl From<UnionDef> for ModuleItem {
1877 fn from(node: UnionDef) -> ModuleItem {
1878 ModuleItem::UnionDef(node)
1879 }
1880}
1875impl From<EnumDef> for ModuleItem { 1881impl From<EnumDef> for ModuleItem {
1876 fn from(node: EnumDef) -> ModuleItem { 1882 fn from(node: EnumDef) -> ModuleItem {
1877 ModuleItem::EnumDef(node) 1883 ModuleItem::EnumDef(node)
@@ -1925,14 +1931,15 @@ impl From<Module> for ModuleItem {
1925impl AstNode for ModuleItem { 1931impl AstNode for ModuleItem {
1926 fn can_cast(kind: SyntaxKind) -> bool { 1932 fn can_cast(kind: SyntaxKind) -> bool {
1927 match kind { 1933 match kind {
1928 STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF | IMPL_BLOCK | USE_ITEM 1934 STRUCT_DEF | UNION_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | TYPE_ALIAS_DEF
1929 | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true, 1935 | IMPL_BLOCK | USE_ITEM | EXTERN_CRATE_ITEM | CONST_DEF | STATIC_DEF | MODULE => true,
1930 _ => false, 1936 _ => false,
1931 } 1937 }
1932 } 1938 }
1933 fn cast(syntax: SyntaxNode) -> Option<Self> { 1939 fn cast(syntax: SyntaxNode) -> Option<Self> {
1934 let res = match syntax.kind() { 1940 let res = match syntax.kind() {
1935 STRUCT_DEF => ModuleItem::StructDef(StructDef { syntax }), 1941 STRUCT_DEF => ModuleItem::StructDef(StructDef { syntax }),
1942 UNION_DEF => ModuleItem::UnionDef(UnionDef { syntax }),
1936 ENUM_DEF => ModuleItem::EnumDef(EnumDef { syntax }), 1943 ENUM_DEF => ModuleItem::EnumDef(EnumDef { syntax }),
1937 FN_DEF => ModuleItem::FnDef(FnDef { syntax }), 1944 FN_DEF => ModuleItem::FnDef(FnDef { syntax }),
1938 TRAIT_DEF => ModuleItem::TraitDef(TraitDef { syntax }), 1945 TRAIT_DEF => ModuleItem::TraitDef(TraitDef { syntax }),
@@ -1950,6 +1957,7 @@ impl AstNode for ModuleItem {
1950 fn syntax(&self) -> &SyntaxNode { 1957 fn syntax(&self) -> &SyntaxNode {
1951 match self { 1958 match self {
1952 ModuleItem::StructDef(it) => &it.syntax, 1959 ModuleItem::StructDef(it) => &it.syntax,
1960 ModuleItem::UnionDef(it) => &it.syntax,
1953 ModuleItem::EnumDef(it) => &it.syntax, 1961 ModuleItem::EnumDef(it) => &it.syntax,
1954 ModuleItem::FnDef(it) => &it.syntax, 1962 ModuleItem::FnDef(it) => &it.syntax,
1955 ModuleItem::TraitDef(it) => &it.syntax, 1963 ModuleItem::TraitDef(it) => &it.syntax,
@@ -2038,6 +2046,7 @@ impl NeverType {}
2038pub enum NominalDef { 2046pub enum NominalDef {
2039 StructDef(StructDef), 2047 StructDef(StructDef),
2040 EnumDef(EnumDef), 2048 EnumDef(EnumDef),
2049 UnionDef(UnionDef),
2041} 2050}
2042impl From<StructDef> for NominalDef { 2051impl From<StructDef> for NominalDef {
2043 fn from(node: StructDef) -> NominalDef { 2052 fn from(node: StructDef) -> NominalDef {
@@ -2049,10 +2058,15 @@ impl From<EnumDef> for NominalDef {
2049 NominalDef::EnumDef(node) 2058 NominalDef::EnumDef(node)
2050 } 2059 }
2051} 2060}
2061impl From<UnionDef> for NominalDef {
2062 fn from(node: UnionDef) -> NominalDef {
2063 NominalDef::UnionDef(node)
2064 }
2065}
2052impl AstNode for NominalDef { 2066impl AstNode for NominalDef {
2053 fn can_cast(kind: SyntaxKind) -> bool { 2067 fn can_cast(kind: SyntaxKind) -> bool {
2054 match kind { 2068 match kind {
2055 STRUCT_DEF | ENUM_DEF => true, 2069 STRUCT_DEF | ENUM_DEF | UNION_DEF => true,
2056 _ => false, 2070 _ => false,
2057 } 2071 }
2058 } 2072 }
@@ -2060,6 +2074,7 @@ impl AstNode for NominalDef {
2060 let res = match syntax.kind() { 2074 let res = match syntax.kind() {
2061 STRUCT_DEF => NominalDef::StructDef(StructDef { syntax }), 2075 STRUCT_DEF => NominalDef::StructDef(StructDef { syntax }),
2062 ENUM_DEF => NominalDef::EnumDef(EnumDef { syntax }), 2076 ENUM_DEF => NominalDef::EnumDef(EnumDef { syntax }),
2077 UNION_DEF => NominalDef::UnionDef(UnionDef { syntax }),
2063 _ => return None, 2078 _ => return None,
2064 }; 2079 };
2065 Some(res) 2080 Some(res)
@@ -2068,6 +2083,7 @@ impl AstNode for NominalDef {
2068 match self { 2083 match self {
2069 NominalDef::StructDef(it) => &it.syntax, 2084 NominalDef::StructDef(it) => &it.syntax,
2070 NominalDef::EnumDef(it) => &it.syntax, 2085 NominalDef::EnumDef(it) => &it.syntax,
2086 NominalDef::UnionDef(it) => &it.syntax,
2071 } 2087 }
2072 } 2088 }
2073} 2089}
@@ -3789,6 +3805,38 @@ impl AstNode for TypeRef {
3789} 3805}
3790impl TypeRef {} 3806impl TypeRef {}
3791#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3807#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3808pub struct UnionDef {
3809 pub(crate) syntax: SyntaxNode,
3810}
3811impl AstNode for UnionDef {
3812 fn can_cast(kind: SyntaxKind) -> bool {
3813 match kind {
3814 UNION_DEF => true,
3815 _ => false,
3816 }
3817 }
3818 fn cast(syntax: SyntaxNode) -> Option<Self> {
3819 if Self::can_cast(syntax.kind()) {
3820 Some(Self { syntax })
3821 } else {
3822 None
3823 }
3824 }
3825 fn syntax(&self) -> &SyntaxNode {
3826 &self.syntax
3827 }
3828}
3829impl ast::VisibilityOwner for UnionDef {}
3830impl ast::NameOwner for UnionDef {}
3831impl ast::TypeParamsOwner for UnionDef {}
3832impl ast::AttrsOwner for UnionDef {}
3833impl ast::DocCommentsOwner for UnionDef {}
3834impl UnionDef {
3835 pub fn record_field_def_list(&self) -> Option<RecordFieldDefList> {
3836 AstChildren::new(&self.syntax).next()
3837 }
3838}
3839#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3792pub struct UseItem { 3840pub struct UseItem {
3793 pub(crate) syntax: SyntaxNode, 3841 pub(crate) syntax: SyntaxNode,
3794} 3842}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 88d1dc109..d1be40abe 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -126,6 +126,7 @@ Grammar(
126 "SOURCE_FILE", 126 "SOURCE_FILE",
127 127
128 "STRUCT_DEF", 128 "STRUCT_DEF",
129 "UNION_DEF",
129 "ENUM_DEF", 130 "ENUM_DEF",
130 "FN_DEF", 131 "FN_DEF",
131 "RET_TYPE", 132 "RET_TYPE",
@@ -285,6 +286,16 @@ Grammar(
285 "DocCommentsOwner" 286 "DocCommentsOwner"
286 ] 287 ]
287 ), 288 ),
289 "UnionDef": (
290 traits: [
291 "VisibilityOwner",
292 "NameOwner",
293 "TypeParamsOwner",
294 "AttrsOwner",
295 "DocCommentsOwner"
296 ],
297 options: ["RecordFieldDefList"],
298 ),
288 "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]), 299 "RecordFieldDefList": (collections: [("fields", "RecordFieldDef")]),
289 "RecordFieldDef": ( 300 "RecordFieldDef": (
290 traits: [ 301 traits: [
@@ -388,7 +399,7 @@ Grammar(
388 ]), 399 ]),
389 400
390 "NominalDef": ( 401 "NominalDef": (
391 enum: ["StructDef", "EnumDef"], 402 enum: ["StructDef", "EnumDef", "UnionDef"],
392 traits: [ 403 traits: [
393 "NameOwner", 404 "NameOwner",
394 "TypeParamsOwner", 405 "TypeParamsOwner",
@@ -396,9 +407,9 @@ Grammar(
396 ], 407 ],
397 ), 408 ),
398 "ModuleItem": ( 409 "ModuleItem": (
399 enum: ["StructDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", 410 enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
400 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ], 411 "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ],
401 traits: ["AttrsOwner"] 412 traits: ["AttrsOwner"],
402 ), 413 ),
403 "ImplItem": ( 414 "ImplItem": (
404 enum: ["FnDef", "TypeAliasDef", "ConstDef"], 415 enum: ["FnDef", "TypeAliasDef", "ConstDef"],
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
index f9ace02ee..9d7982684 100644
--- a/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0068_union_items.txt
@@ -1,5 +1,5 @@
1SOURCE_FILE@[0; 51) 1SOURCE_FILE@[0; 51)
2 STRUCT_DEF@[0; 12) 2 UNION_DEF@[0; 12)
3 UNION_KW@[0; 5) "union" 3 UNION_KW@[0; 5) "union"
4 WHITESPACE@[5; 6) " " 4 WHITESPACE@[5; 6) " "
5 NAME@[6; 9) 5 NAME@[6; 9)
@@ -9,7 +9,7 @@ SOURCE_FILE@[0; 51)
9 L_CURLY@[10; 11) "{" 9 L_CURLY@[10; 11) "{"
10 R_CURLY@[11; 12) "}" 10 R_CURLY@[11; 12) "}"
11 WHITESPACE@[12; 13) "\n" 11 WHITESPACE@[12; 13) "\n"
12 STRUCT_DEF@[13; 50) 12 UNION_DEF@[13; 50)
13 UNION_KW@[13; 18) "union" 13 UNION_KW@[13; 18) "union"
14 WHITESPACE@[18; 19) " " 14 WHITESPACE@[18; 19) " "
15 NAME@[19; 22) 15 NAME@[19; 22)
diff --git a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
index 3260cc589..90538b90d 100644
--- a/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
+++ b/crates/ra_syntax/test_data/parser/ok/0035_weird_exprs.txt
@@ -1592,7 +1592,7 @@ SOURCE_FILE@[0; 3813)
1592 BLOCK@[2845; 2906) 1592 BLOCK@[2845; 2906)
1593 L_CURLY@[2845; 2846) "{" 1593 L_CURLY@[2845; 2846) "{"
1594 WHITESPACE@[2846; 2851) "\n " 1594 WHITESPACE@[2846; 2851) "\n "
1595 STRUCT_DEF@[2851; 2904) 1595 UNION_DEF@[2851; 2904)
1596 UNION_KW@[2851; 2856) "union" 1596 UNION_KW@[2851; 2856) "union"
1597 WHITESPACE@[2856; 2857) " " 1597 WHITESPACE@[2856; 2857) " "
1598 NAME@[2857; 2862) 1598 NAME@[2857; 2862)