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());