aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/base_db/src/fixture.rs68
-rw-r--r--crates/base_db/src/lib.rs3
-rw-r--r--crates/cfg/src/tests.rs8
-rw-r--r--crates/hir/Cargo.toml2
-rw-r--r--crates/hir/src/db.rs10
-rw-r--r--crates/hir/src/display.rs27
-rw-r--r--crates/hir/src/lib.rs230
-rw-r--r--crates/hir/src/semantics.rs10
-rw-r--r--crates/hir/src/source_analyzer.rs63
-rw-r--r--crates/hir_def/Cargo.toml1
-rw-r--r--crates/hir_def/src/adt.rs9
-rw-r--r--crates/hir_def/src/attr.rs199
-rw-r--r--crates/hir_def/src/body.rs24
-rw-r--r--crates/hir_def/src/body/lower.rs83
-rw-r--r--crates/hir_def/src/body/tests.rs4
-rw-r--r--crates/hir_def/src/child_by_source.rs6
-rw-r--r--crates/hir_def/src/data.rs90
-rw-r--r--crates/hir_def/src/db.rs18
-rw-r--r--crates/hir_def/src/diagnostics.rs5
-rw-r--r--crates/hir_def/src/expr.rs19
-rw-r--r--crates/hir_def/src/find_path.rs604
-rw-r--r--crates/hir_def/src/generics.rs62
-rw-r--r--crates/hir_def/src/intern.rs216
-rw-r--r--crates/hir_def/src/item_scope.rs35
-rw-r--r--crates/hir_def/src/item_tree.rs159
-rw-r--r--crates/hir_def/src/item_tree/lower.rs123
-rw-r--r--crates/hir_def/src/lib.rs62
-rw-r--r--crates/hir_def/src/nameres.rs66
-rw-r--r--crates/hir_def/src/nameres/collector.rs136
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs59
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs26
-rw-r--r--crates/hir_def/src/path.rs22
-rw-r--r--crates/hir_def/src/path/lower.rs14
-rw-r--r--crates/hir_def/src/resolver.rs3
-rw-r--r--crates/hir_def/src/test_db.rs64
-rw-r--r--crates/hir_def/src/type_ref.rs17
-rw-r--r--crates/hir_def/src/visibility.rs6
-rw-r--r--crates/hir_expand/src/builtin_derive.rs10
-rw-r--r--crates/hir_expand/src/builtin_macro.rs36
-rw-r--r--crates/hir_expand/src/db.rs15
-rw-r--r--crates/hir_expand/src/eager.rs9
-rw-r--r--crates/hir_expand/src/lib.rs21
-rw-r--r--crates/hir_expand/src/name.rs11
-rw-r--r--crates/hir_expand/src/quote.rs1
-rw-r--r--crates/hir_ty/Cargo.toml2
-rw-r--r--crates/hir_ty/src/autoderef.rs105
-rw-r--r--crates/hir_ty/src/builder.rs223
-rw-r--r--crates/hir_ty/src/chalk_cast.rs53
-rw-r--r--crates/hir_ty/src/chalk_db.rs (renamed from crates/hir_ty/src/traits/chalk.rs)276
-rw-r--r--crates/hir_ty/src/chalk_ext.rs305
-rw-r--r--crates/hir_ty/src/db.rs87
-rw-r--r--crates/hir_ty/src/diagnostics.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs174
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs24
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs49
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs12
-rw-r--r--crates/hir_ty/src/display.rs321
-rw-r--r--crates/hir_ty/src/infer.rs198
-rw-r--r--crates/hir_ty/src/infer/coerce.rs64
-rw-r--r--crates/hir_ty/src/infer/expr.rs221
-rw-r--r--crates/hir_ty/src/infer/pat.rs92
-rw-r--r--crates/hir_ty/src/infer/path.rs39
-rw-r--r--crates/hir_ty/src/infer/unify.rs266
-rw-r--r--crates/hir_ty/src/interner.rs (renamed from crates/hir_ty/src/traits/chalk/interner.rs)170
-rw-r--r--crates/hir_ty/src/lib.rs1347
-rw-r--r--crates/hir_ty/src/lower.rs340
-rw-r--r--crates/hir_ty/src/mapping.rs154
-rw-r--r--crates/hir_ty/src/method_resolution.rs316
-rw-r--r--crates/hir_ty/src/op.rs74
-rw-r--r--crates/hir_ty/src/primitive.rs5
-rw-r--r--crates/hir_ty/src/tests.rs2
-rw-r--r--crates/hir_ty/src/tests/macros.rs28
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/tests/patterns.rs28
-rw-r--r--crates/hir_ty/src/tests/regression.rs38
-rw-r--r--crates/hir_ty/src/tests/simple.rs51
-rw-r--r--crates/hir_ty/src/tests/traits.rs1504
-rw-r--r--crates/hir_ty/src/tls.rs (renamed from crates/hir_ty/src/traits/chalk/tls.rs)14
-rw-r--r--crates/hir_ty/src/traits.rs140
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs560
-rw-r--r--crates/hir_ty/src/utils.rs73
-rw-r--r--crates/hir_ty/src/walk.rs150
-rw-r--r--crates/ide/src/annotations.rs2
-rw-r--r--crates/ide/src/diagnostics.rs158
-rw-r--r--crates/ide/src/diagnostics/field_shorthand.rs8
-rw-r--r--crates/ide/src/diagnostics/fixes.rs60
-rw-r--r--crates/ide/src/diagnostics/unlinked_file.rs14
-rw-r--r--crates/ide/src/doc_links.rs197
-rw-r--r--crates/ide/src/expand_macro.rs46
-rw-r--r--crates/ide/src/extend_selection.rs2
-rw-r--r--crates/ide/src/file_structure.rs3
-rw-r--r--crates/ide/src/folding_ranges.rs56
-rw-r--r--crates/ide/src/goto_definition.rs83
-rw-r--r--crates/ide/src/goto_implementation.rs2
-rw-r--r--crates/ide/src/goto_type_definition.rs2
-rw-r--r--crates/ide/src/hover.rs156
-rw-r--r--crates/ide/src/inlay_hints.rs4
-rw-r--r--crates/ide/src/join_lines.rs20
-rw-r--r--crates/ide/src/lib.rs36
-rw-r--r--crates/ide/src/matching_brace.rs2
-rw-r--r--crates/ide/src/move_item.rs348
-rw-r--r--crates/ide/src/parent_module.rs2
-rw-r--r--crates/ide/src/references.rs2
-rw-r--r--crates/ide/src/references/rename.rs4
-rw-r--r--crates/ide/src/runnables.rs3
-rw-r--r--crates/ide/src/status.rs1
-rw-r--r--crates/ide/src/syntax_highlighting.rs3
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs108
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs118
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs28
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html8
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html12
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html6
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs44
-rw-r--r--crates/ide/src/syntax_tree.rs1
-rw-r--r--crates/ide/src/typing.rs371
-rw-r--r--crates/ide/src/typing/on_enter.rs232
-rw-r--r--crates/ide/src/view_hir.rs1
-rw-r--r--crates/ide_assists/src/assist_context.rs5
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs2
-rw-r--r--crates/ide_assists/src/handlers/convert_into_to_from.rs355
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs176
-rw-r--r--crates/ide_assists/src/handlers/extract_type_alias.rs149
-rw-r--r--crates/ide_assists/src/handlers/extract_variable.rs73
-rw-r--r--crates/ide_assists/src/handlers/fill_match_arms.rs22
-rw-r--r--crates/ide_assists/src/handlers/flip_comma.rs18
-rw-r--r--crates/ide_assists/src/handlers/generate_default_from_new.rs2
-rw-r--r--crates/ide_assists/src/handlers/generate_is_empty_from_len.rs2
-rw-r--r--crates/ide_assists/src/handlers/remove_dbg.rs105
-rw-r--r--crates/ide_assists/src/handlers/reorder_fields.rs89
-rw-r--r--crates/ide_assists/src/lib.rs6
-rw-r--r--crates/ide_assists/src/tests.rs6
-rw-r--r--crates/ide_assists/src/tests/generated.rs51
-rw-r--r--crates/ide_assists/src/utils.rs4
-rw-r--r--crates/ide_completion/src/completions.rs2
-rw-r--r--crates/ide_completion/src/completions/flyimport.rs116
-rw-r--r--crates/ide_completion/src/completions/pattern.rs2
-rw-r--r--crates/ide_completion/src/completions/postfix/format_like.rs2
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs4
-rw-r--r--crates/ide_completion/src/item.rs2
-rw-r--r--crates/ide_completion/src/lib.rs30
-rw-r--r--crates/ide_db/src/apply_change.rs7
-rw-r--r--crates/ide_db/src/call_info.rs10
-rw-r--r--crates/ide_db/src/call_info/tests.rs27
-rw-r--r--crates/ide_db/src/defs.rs41
-rw-r--r--crates/ide_db/src/helpers.rs4
-rw-r--r--crates/ide_db/src/helpers/famous_defs_fixture.rs6
-rw-r--r--crates/ide_db/src/helpers/import_assets.rs24
-rw-r--r--crates/mbe/src/benchmark.rs2
-rw-r--r--crates/mbe/src/expander.rs6
-rw-r--r--crates/mbe/src/lib.rs6
-rw-r--r--crates/mbe/src/syntax_bridge.rs23
-rw-r--r--crates/mbe/src/tests.rs11
-rw-r--r--crates/mbe/src/tests/expand.rs33
-rw-r--r--crates/mbe/src/tests/rule.rs2
-rw-r--r--crates/mbe/src/tt_iter.rs11
-rw-r--r--crates/parser/src/grammar.rs37
-rw-r--r--crates/parser/src/grammar/attributes.rs28
-rw-r--r--crates/paths/src/lib.rs7
-rw-r--r--crates/proc_macro_srv/src/rustc_server.rs19
-rw-r--r--crates/profile/src/google_cpu_profiler.rs19
-rw-r--r--crates/profile/src/hprof.rs107
-rw-r--r--crates/profile/src/lib.rs39
-rw-r--r--crates/project_model/src/build_data.rs274
-rw-r--r--crates/project_model/src/workspace.rs10
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/build.rs3
-rw-r--r--crates/rust-analyzer/src/benchmarks.rs74
-rw-r--r--crates/rust-analyzer/src/bin/flags.rs56
-rw-r--r--crates/rust-analyzer/src/bin/main.rs31
-rw-r--r--crates/rust-analyzer/src/bin/rustc_wrapper.rs46
-rw-r--r--crates/rust-analyzer/src/caps.rs2
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs2
-rw-r--r--crates/rust-analyzer/src/cli.rs4
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs196
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs63
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs6
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs10
-rw-r--r--crates/rust-analyzer/src/cli/ssr.rs9
-rw-r--r--crates/rust-analyzer/src/config.rs23
-rw-r--r--crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt138
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs101
-rw-r--r--crates/rust-analyzer/src/from_proto.rs30
-rw-r--r--crates/rust-analyzer/src/global_state.rs63
-rw-r--r--crates/rust-analyzer/src/handlers.rs133
-rw-r--r--crates/rust-analyzer/src/lib.rs3
-rw-r--r--crates/rust-analyzer/src/lsp_ext.rs32
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs24
-rw-r--r--crates/rust-analyzer/src/main_loop.rs110
-rw-r--r--crates/rust-analyzer/src/op_queue.rs38
-rw-r--r--crates/rust-analyzer/src/reload.rs214
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs6
-rw-r--r--crates/rust-analyzer/src/to_proto.rs99
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/main.rs4
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/support.rs32
-rw-r--r--crates/stdx/src/lib.rs8
-rw-r--r--crates/syntax/Cargo.toml6
-rw-r--r--crates/syntax/src/ast/make.rs18
-rw-r--r--crates/test_utils/src/assert_linear.rs112
-rw-r--r--crates/test_utils/src/bench_fixture.rs3
-rw-r--r--crates/test_utils/src/fixture.rs62
-rw-r--r--crates/test_utils/src/lib.rs3
-rw-r--r--crates/vfs/Cargo.toml1
-rw-r--r--crates/vfs/src/path_interner.rs29
206 files changed, 9717 insertions, 6391 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index 8d4641355..0132565e4 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -1,62 +1,4 @@
1//! Fixtures are strings containing rust source code with optional metadata. 1//! A set of high-level utility fixture methods to use in tests.
2//! A fixture without metadata is parsed into a single source file.
3//! Use this to test functionality local to one file.
4//!
5//! Simple Example:
6//! ```
7//! r#"
8//! fn main() {
9//! println!("Hello World")
10//! }
11//! "#
12//! ```
13//!
14//! Metadata can be added to a fixture after a `//-` comment.
15//! The basic form is specifying filenames,
16//! which is also how to define multiple files in a single test fixture
17//!
18//! Example using two files in the same crate:
19//! ```
20//! "
21//! //- /main.rs
22//! mod foo;
23//! fn main() {
24//! foo::bar();
25//! }
26//!
27//! //- /foo.rs
28//! pub fn bar() {}
29//! "
30//! ```
31//!
32//! Example using two crates with one file each, with one crate depending on the other:
33//! ```
34//! r#"
35//! //- /main.rs crate:a deps:b
36//! fn main() {
37//! b::foo();
38//! }
39//! //- /lib.rs crate:b
40//! pub fn b() {
41//! println!("Hello World")
42//! }
43//! "#
44//! ```
45//!
46//! Metadata allows specifying all settings and variables
47//! that are available in a real rust project:
48//! - crate names via `crate:cratename`
49//! - dependencies via `deps:dep1,dep2`
50//! - configuration settings via `cfg:dbg=false,opt_level=2`
51//! - environment variables via `env:PATH=/bin,RUST_LOG=debug`
52//!
53//! Example using all available metadata:
54//! ```
55//! "
56//! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
57//! fn insert_source_code_here() {}
58//! "
59//! ```
60use std::{mem, str::FromStr, sync::Arc}; 2use std::{mem, str::FromStr, sync::Arc};
61 3
62use cfg::CfgOptions; 4use cfg::CfgOptions;
@@ -93,7 +35,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
93 fn with_position(ra_fixture: &str) -> (Self, FilePosition) { 35 fn with_position(ra_fixture: &str) -> (Self, FilePosition) {
94 let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); 36 let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture);
95 let offset = match range_or_offset { 37 let offset = match range_or_offset {
96 RangeOrOffset::Range(_) => panic!(), 38 RangeOrOffset::Range(_) => panic!("Expected a cursor position, got a range instead"),
97 RangeOrOffset::Offset(it) => it, 39 RangeOrOffset::Offset(it) => it,
98 }; 40 };
99 (db, FilePosition { file_id, offset }) 41 (db, FilePosition { file_id, offset })
@@ -103,7 +45,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
103 let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); 45 let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture);
104 let range = match range_or_offset { 46 let range = match range_or_offset {
105 RangeOrOffset::Range(it) => it, 47 RangeOrOffset::Range(it) => it,
106 RangeOrOffset::Offset(_) => panic!(), 48 RangeOrOffset::Offset(_) => panic!("Expected a cursor range, got a position instead"),
107 }; 49 };
108 (db, FileRange { file_id, range }) 50 (db, FileRange { file_id, range })
109 } 51 }
@@ -112,7 +54,9 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
112 let fixture = ChangeFixture::parse(ra_fixture); 54 let fixture = ChangeFixture::parse(ra_fixture);
113 let mut db = Self::default(); 55 let mut db = Self::default();
114 fixture.change.apply(&mut db); 56 fixture.change.apply(&mut db);
115 let (file_id, range_or_offset) = fixture.file_position.unwrap(); 57 let (file_id, range_or_offset) = fixture
58 .file_position
59 .expect("Could not find file position in fixture. Did you forget to add an `$0`?");
116 (db, file_id, range_or_offset) 60 (db, file_id, range_or_offset)
117 } 61 }
118 62
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs
index 5f77a0b1f..980a0ed98 100644
--- a/crates/base_db/src/lib.rs
+++ b/crates/base_db/src/lib.rs
@@ -59,6 +59,8 @@ pub trait CheckCanceled {
59 Self: Sized + panic::RefUnwindSafe, 59 Self: Sized + panic::RefUnwindSafe,
60 F: FnOnce(&Self) -> T + panic::UnwindSafe, 60 F: FnOnce(&Self) -> T + panic::UnwindSafe,
61 { 61 {
62 // Uncomment to debug missing cancellations.
63 // let _span = profile::heartbeat_span();
62 panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() { 64 panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() {
63 Ok(canceled) => *canceled, 65 Ok(canceled) => *canceled,
64 Err(payload) => panic::resume_unwind(payload), 66 Err(payload) => panic::resume_unwind(payload),
@@ -68,6 +70,7 @@ pub trait CheckCanceled {
68 70
69impl<T: salsa::Database> CheckCanceled for T { 71impl<T: salsa::Database> CheckCanceled for T {
70 fn check_canceled(&self) { 72 fn check_canceled(&self) {
73 // profile::heartbeat();
71 if self.salsa_runtime().is_current_revision_canceled() { 74 if self.salsa_runtime().is_current_revision_canceled() {
72 Canceled::throw() 75 Canceled::throw()
73 } 76 }
diff --git a/crates/cfg/src/tests.rs b/crates/cfg/src/tests.rs
index bd0f9ec48..d8736c893 100644
--- a/crates/cfg/src/tests.rs
+++ b/crates/cfg/src/tests.rs
@@ -8,7 +8,7 @@ fn assert_parse_result(input: &str, expected: CfgExpr) {
8 let (tt, _) = { 8 let (tt, _) = {
9 let source_file = ast::SourceFile::parse(input).ok().unwrap(); 9 let source_file = ast::SourceFile::parse(input).ok().unwrap();
10 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); 10 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
11 ast_to_token_tree(&tt).unwrap() 11 ast_to_token_tree(&tt)
12 }; 12 };
13 let cfg = CfgExpr::parse(&tt); 13 let cfg = CfgExpr::parse(&tt);
14 assert_eq!(cfg, expected); 14 assert_eq!(cfg, expected);
@@ -18,7 +18,7 @@ fn check_dnf(input: &str, expect: Expect) {
18 let (tt, _) = { 18 let (tt, _) = {
19 let source_file = ast::SourceFile::parse(input).ok().unwrap(); 19 let source_file = ast::SourceFile::parse(input).ok().unwrap();
20 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); 20 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
21 ast_to_token_tree(&tt).unwrap() 21 ast_to_token_tree(&tt)
22 }; 22 };
23 let cfg = CfgExpr::parse(&tt); 23 let cfg = CfgExpr::parse(&tt);
24 let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); 24 let actual = format!("#![cfg({})]", DnfExpr::new(cfg));
@@ -29,7 +29,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
29 let (tt, _) = { 29 let (tt, _) = {
30 let source_file = ast::SourceFile::parse(input).ok().unwrap(); 30 let source_file = ast::SourceFile::parse(input).ok().unwrap();
31 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); 31 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
32 ast_to_token_tree(&tt).unwrap() 32 ast_to_token_tree(&tt)
33 }; 33 };
34 let cfg = CfgExpr::parse(&tt); 34 let cfg = CfgExpr::parse(&tt);
35 let dnf = DnfExpr::new(cfg); 35 let dnf = DnfExpr::new(cfg);
@@ -42,7 +42,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) {
42 let (tt, _) = { 42 let (tt, _) = {
43 let source_file = ast::SourceFile::parse(input).ok().unwrap(); 43 let source_file = ast::SourceFile::parse(input).ok().unwrap();
44 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); 44 let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap();
45 ast_to_token_tree(&tt).unwrap() 45 ast_to_token_tree(&tt)
46 }; 46 };
47 let cfg = CfgExpr::parse(&tt); 47 let cfg = CfgExpr::parse(&tt);
48 let dnf = DnfExpr::new(cfg); 48 let dnf = DnfExpr::new(cfg);
diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml
index 2ef5bcbc9..9e329656f 100644
--- a/crates/hir/Cargo.toml
+++ b/crates/hir/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
13log = "0.4.8" 13log = "0.4.8"
14rustc-hash = "1.1.0" 14rustc-hash = "1.1.0"
15either = "1.5.3" 15either = "1.5.3"
16arrayvec = "0.6" 16arrayvec = "0.7"
17itertools = "0.10.0" 17itertools = "0.10.0"
18smallvec = "1.4.0" 18smallvec = "1.4.0"
19 19
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs
index 1902a8d16..df5758342 100644
--- a/crates/hir/src/db.rs
+++ b/crates/hir/src/db.rs
@@ -1,14 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3pub use hir_def::db::{ 3pub use hir_def::db::*;
4 AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery,
5 CrateDefMapQueryQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery,
6 ExprScopesQuery, FileItemTreeQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery,
7 ImportMapQuery, InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery,
8 InternFunctionQuery, InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery,
9 InternTypeAliasQuery, InternUnionQuery, LangItemQuery, StaticDataQuery, StructDataQuery,
10 TraitDataQuery, TypeAliasDataQuery, UnionDataQuery,
11};
12pub use hir_expand::db::{ 4pub use hir_expand::db::{
13 AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, 5 AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery,
14 InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, 6 InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery,
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 97a78ca25..01a4d205f 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -9,33 +9,33 @@ use hir_ty::display::{
9 write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, 9 write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
10 HirFormatter, 10 HirFormatter,
11}; 11};
12use hir_ty::Interner;
12use syntax::ast::{self, NameOwner}; 13use syntax::ast::{self, NameOwner};
13 14
14use crate::{ 15use crate::{
15 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, 16 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam,
16 Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant, 17 Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant,
17}; 18};
18 19
19impl HirDisplay for Function { 20impl HirDisplay for Function {
20 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 21 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
21 let data = f.db.function_data(self.id); 22 let data = f.db.function_data(self.id);
22 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; 23 write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
23 let qual = &data.qualifier; 24 if data.is_default() {
24 if qual.is_default {
25 write!(f, "default ")?; 25 write!(f, "default ")?;
26 } 26 }
27 if qual.is_const { 27 if data.is_const() {
28 write!(f, "const ")?; 28 write!(f, "const ")?;
29 } 29 }
30 if qual.is_async { 30 if data.is_async() {
31 write!(f, "async ")?; 31 write!(f, "async ")?;
32 } 32 }
33 if qual.is_unsafe { 33 if data.is_unsafe() {
34 write!(f, "unsafe ")?; 34 write!(f, "unsafe ")?;
35 } 35 }
36 if let Some(abi) = &qual.abi { 36 if let Some(abi) = &data.abi {
37 // FIXME: String escape? 37 // FIXME: String escape?
38 write!(f, "extern \"{}\" ", abi)?; 38 write!(f, "extern \"{}\" ", &**abi)?;
39 } 39 }
40 write!(f, "fn {}", data.name)?; 40 write!(f, "fn {}", data.name)?;
41 41
@@ -68,7 +68,7 @@ impl HirDisplay for Function {
68 write!(f, ", ")?; 68 write!(f, ", ")?;
69 } else { 69 } else {
70 first = false; 70 first = false;
71 if data.has_self_param { 71 if data.has_self_param() {
72 write_self_param(type_ref, f)?; 72 write_self_param(type_ref, f)?;
73 continue; 73 continue;
74 } 74 }
@@ -88,10 +88,10 @@ impl HirDisplay for Function {
88 // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. 88 // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns.
89 // Use ugly pattern match to strip the Future trait. 89 // Use ugly pattern match to strip the Future trait.
90 // Better way? 90 // Better way?
91 let ret_type = if !qual.is_async { 91 let ret_type = if !data.is_async() {
92 &data.ret_type 92 &data.ret_type
93 } else { 93 } else {
94 match &data.ret_type { 94 match &*data.ret_type {
95 TypeRef::ImplTrait(bounds) => match &bounds[0] { 95 TypeRef::ImplTrait(bounds) => match &bounds[0] {
96 TypeBound::Path(path) => { 96 TypeBound::Path(path) => {
97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings 97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
@@ -235,8 +235,9 @@ impl HirDisplay for TypeParam {
235 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 235 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
236 write!(f, "{}", self.name(f.db))?; 236 write!(f, "{}", self.name(f.db))?;
237 let bounds = f.db.generic_predicates_for_param(self.id); 237 let bounds = f.db.generic_predicates_for_param(self.id);
238 let substs = Substitution::type_params(f.db, self.id.parent); 238 let substs = TyBuilder::type_params_subst(f.db, self.id.parent);
239 let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); 239 let predicates =
240 bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>();
240 if !(predicates.is_empty() || f.omit_verbose_types()) { 241 if !(predicates.is_empty() || f.omit_verbose_types()) {
241 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; 242 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
242 } 243 }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 4ee08ef21..0acfa582a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -44,6 +44,7 @@ use hir_def::{
44 per_ns::PerNs, 44 per_ns::PerNs,
45 resolver::{HasResolver, Resolver}, 45 resolver::{HasResolver, Resolver},
46 src::HasSource as _, 46 src::HasSource as _,
47 type_ref::TraitRef,
47 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, 48 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
48 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, 49 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
49 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, 50 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
@@ -52,13 +53,14 @@ use hir_def::{
52use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; 53use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind};
53use hir_ty::{ 54use hir_ty::{
54 autoderef, could_unify, 55 autoderef, could_unify,
55 method_resolution::{self, TyFingerprint}, 56 method_resolution::{self, def_crates, TyFingerprint},
56 primitive::UintTy, 57 primitive::UintTy,
57 to_assoc_type_id, 58 subst_prefix,
58 traits::{FnTrait, Solution, SolutionVariables}, 59 traits::FnTrait,
59 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
60 DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, 61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, Substitution,
61 Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, 62 TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind,
63 WhereClause,
62}; 64};
63use itertools::Itertools; 65use itertools::Itertools;
64use rustc_hash::FxHashSet; 66use rustc_hash::FxHashSet;
@@ -514,8 +516,8 @@ impl Field {
514 VariantDef::Union(it) => it.id.into(), 516 VariantDef::Union(it) => it.id.into(),
515 VariantDef::Variant(it) => it.parent.id.into(), 517 VariantDef::Variant(it) => it.parent.id.into(),
516 }; 518 };
517 let substs = Substitution::type_params(db, generic_def_id); 519 let substs = TyBuilder::type_params_subst(db, generic_def_id);
518 let ty = db.field_types(var_id)[self.id].clone().subst(&substs); 520 let ty = db.field_types(var_id)[self.id].clone().substitute(&Interner, &substs);
519 Type::new(db, self.parent.module(db).id.krate(), var_id, ty) 521 Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
520 } 522 }
521 523
@@ -701,7 +703,7 @@ impl_from!(Struct, Union, Enum for Adt);
701impl Adt { 703impl Adt {
702 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 704 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
703 let subst = db.generic_defaults(self.into()); 705 let subst = db.generic_defaults(self.into());
704 subst.iter().any(|ty| ty.value.is_unknown()) 706 subst.iter().any(|ty| ty.skip_binders().is_unknown())
705 } 707 }
706 708
707 /// Turns this ADT into a type. Any type parameters of the ADT will be 709 /// Turns this ADT into a type. Any type parameters of the ADT will be
@@ -831,7 +833,7 @@ impl Function {
831 } 833 }
832 834
833 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { 835 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
834 if !db.function_data(self.id).has_self_param { 836 if !db.function_data(self.id).has_self_param() {
835 return None; 837 return None;
836 } 838 }
837 Some(SelfParam { func: self.id }) 839 Some(SelfParam { func: self.id })
@@ -863,7 +865,7 @@ impl Function {
863 } 865 }
864 866
865 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { 867 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
866 db.function_data(self.id).qualifier.is_unsafe 868 db.function_data(self.id).is_unsafe()
867 } 869 }
868 870
869 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 871 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -877,7 +879,7 @@ impl Function {
877 /// 879 ///
878 /// This is false in the case of required (not provided) trait methods. 880 /// This is false in the case of required (not provided) trait methods.
879 pub fn has_body(self, db: &dyn HirDatabase) -> bool { 881 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
880 db.function_data(self.id).has_body 882 db.function_data(self.id).has_body()
881 } 883 }
882 884
883 /// A textual representation of the HIR of this function for debugging purposes. 885 /// A textual representation of the HIR of this function for debugging purposes.
@@ -956,7 +958,7 @@ impl SelfParam {
956 func_data 958 func_data
957 .params 959 .params
958 .first() 960 .first()
959 .map(|param| match *param { 961 .map(|param| match &**param {
960 TypeRef::Reference(.., mutability) => match mutability { 962 TypeRef::Reference(.., mutability) => match mutability {
961 hir_def::type_ref::Mutability::Shared => Access::Shared, 963 hir_def::type_ref::Mutability::Shared => Access::Shared,
962 hir_def::type_ref::Mutability::Mut => Access::Exclusive, 964 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
@@ -1010,7 +1012,7 @@ impl Const {
1010 } 1012 }
1011 1013
1012 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { 1014 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef {
1013 db.const_data(self.id).type_ref.clone() 1015 db.const_data(self.id).type_ref.as_ref().clone()
1014 } 1016 }
1015} 1017}
1016 1018
@@ -1088,7 +1090,7 @@ pub struct TypeAlias {
1088impl TypeAlias { 1090impl TypeAlias {
1089 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { 1091 pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
1090 let subst = db.generic_defaults(self.id.into()); 1092 let subst = db.generic_defaults(self.id.into());
1091 subst.iter().any(|ty| ty.value.is_unknown()) 1093 subst.iter().any(|ty| ty.skip_binders().is_unknown())
1092 } 1094 }
1093 1095
1094 pub fn module(self, db: &dyn HirDatabase) -> Module { 1096 pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1100,7 +1102,7 @@ impl TypeAlias {
1100 } 1102 }
1101 1103
1102 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1104 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1103 db.type_alias_data(self.id).type_ref.clone() 1105 db.type_alias_data(self.id).type_ref.as_deref().cloned()
1104 } 1106 }
1105 1107
1106 pub fn ty(self, db: &dyn HirDatabase) -> Type { 1108 pub fn ty(self, db: &dyn HirDatabase) -> Type {
@@ -1128,7 +1130,7 @@ pub struct BuiltinType {
1128impl BuiltinType { 1130impl BuiltinType {
1129 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { 1131 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
1130 let resolver = module.id.resolver(db.upcast()); 1132 let resolver = module.id.resolver(db.upcast());
1131 Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) 1133 Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
1132 .expect("crate not present in resolver") 1134 .expect("crate not present in resolver")
1133 } 1135 }
1134 1136
@@ -1501,8 +1503,8 @@ impl TypeParam {
1501 let resolver = self.id.parent.resolver(db.upcast()); 1503 let resolver = self.id.parent.resolver(db.upcast());
1502 let krate = self.id.parent.module(db.upcast()).krate(); 1504 let krate = self.id.parent.module(db.upcast()).krate();
1503 let ty = params.get(local_idx)?.clone(); 1505 let ty = params.get(local_idx)?.clone();
1504 let subst = Substitution::type_params(db, self.id.parent); 1506 let subst = TyBuilder::type_params_subst(db, self.id.parent);
1505 let ty = ty.subst(&subst.prefix(local_idx)); 1507 let ty = ty.substitute(&Interner, &subst_prefix(&subst, local_idx));
1506 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) 1508 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
1507 } 1509 }
1508} 1510}
@@ -1567,22 +1569,35 @@ impl Impl {
1567 } 1569 }
1568 1570
1569 pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { 1571 pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> {
1570 let def_crates = match ty.def_crates(db, krate) { 1572 let def_crates = match def_crates(db, &ty, krate) {
1571 Some(def_crates) => def_crates, 1573 Some(def_crates) => def_crates,
1572 None => return Vec::new(), 1574 None => return Vec::new(),
1573 }; 1575 };
1574 1576
1575 let filter = |impl_def: &Impl| { 1577 let filter = |impl_def: &Impl| {
1576 let target_ty = impl_def.target_ty(db); 1578 let self_ty = impl_def.self_ty(db);
1577 let rref = target_ty.remove_ref(); 1579 let rref = self_ty.remove_ref();
1578 ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty)) 1580 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
1581 };
1582
1583 let fp = TyFingerprint::for_inherent_impl(&ty);
1584 let fp = if let Some(fp) = fp {
1585 fp
1586 } else {
1587 return Vec::new();
1579 }; 1588 };
1580 1589
1581 let mut all = Vec::new(); 1590 let mut all = Vec::new();
1582 def_crates.iter().for_each(|&id| { 1591 def_crates.iter().for_each(|&id| {
1583 all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) 1592 all.extend(
1593 db.inherent_impls_in_crate(id)
1594 .for_self_ty(&ty)
1595 .into_iter()
1596 .cloned()
1597 .map(Self::from)
1598 .filter(filter),
1599 )
1584 }); 1600 });
1585 let fp = TyFingerprint::for_impl(&ty);
1586 for id in def_crates 1601 for id in def_crates
1587 .iter() 1602 .iter()
1588 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) 1603 .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
@@ -1590,13 +1605,12 @@ impl Impl {
1590 .chain(def_crates.iter().copied()) 1605 .chain(def_crates.iter().copied())
1591 .unique() 1606 .unique()
1592 { 1607 {
1593 match fp { 1608 all.extend(
1594 Some(fp) => all.extend( 1609 db.trait_impls_in_crate(id)
1595 db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), 1610 .for_self_ty_without_blanket_impls(fp)
1596 ), 1611 .map(Self::from)
1597 None => all 1612 .filter(filter),
1598 .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)), 1613 );
1599 }
1600 } 1614 }
1601 all 1615 all
1602 } 1616 }
@@ -1613,16 +1627,16 @@ impl Impl {
1613 1627
1614 // FIXME: the return type is wrong. This should be a hir version of 1628 // FIXME: the return type is wrong. This should be a hir version of
1615 // `TraitRef` (ie, resolved `TypeRef`). 1629 // `TraitRef` (ie, resolved `TypeRef`).
1616 pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1630 pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> {
1617 db.impl_data(self.id).target_trait.clone() 1631 db.impl_data(self.id).target_trait.as_deref().cloned()
1618 } 1632 }
1619 1633
1620 pub fn target_ty(self, db: &dyn HirDatabase) -> Type { 1634 pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
1621 let impl_data = db.impl_data(self.id); 1635 let impl_data = db.impl_data(self.id);
1622 let resolver = self.id.resolver(db.upcast()); 1636 let resolver = self.id.resolver(db.upcast());
1623 let krate = self.id.lookup(db.upcast()).container.krate(); 1637 let krate = self.id.lookup(db.upcast()).container.krate();
1624 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 1638 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1625 let ty = ctx.lower_ty(&impl_data.target_type); 1639 let ty = ctx.lower_ty(&impl_data.self_ty);
1626 Type::new_with_resolver_inner(db, krate, &resolver, ty) 1640 Type::new_with_resolver_inner(db, krate, &resolver, ty)
1627 } 1641 }
1628 1642
@@ -1702,30 +1716,29 @@ impl Type {
1702 fn from_def( 1716 fn from_def(
1703 db: &dyn HirDatabase, 1717 db: &dyn HirDatabase,
1704 krate: CrateId, 1718 krate: CrateId,
1705 def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, 1719 def: impl HasResolver + Into<TyDefId>,
1706 ) -> Type { 1720 ) -> Type {
1707 let substs = Substitution::build_for_def(db, def).fill_with_unknown().build(); 1721 let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
1708 let ty = db.ty(def.into()).subst(&substs);
1709 Type::new(db, krate, def, ty) 1722 Type::new(db, krate, def, ty)
1710 } 1723 }
1711 1724
1712 pub fn is_unit(&self) -> bool { 1725 pub fn is_unit(&self) -> bool {
1713 matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..)) 1726 matches!(self.ty.kind(&Interner), TyKind::Tuple(0, ..))
1714 } 1727 }
1715 pub fn is_bool(&self) -> bool { 1728 pub fn is_bool(&self) -> bool {
1716 matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool)) 1729 matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Bool))
1717 } 1730 }
1718 1731
1719 pub fn is_mutable_reference(&self) -> bool { 1732 pub fn is_mutable_reference(&self) -> bool {
1720 matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) 1733 matches!(self.ty.kind(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
1721 } 1734 }
1722 1735
1723 pub fn is_usize(&self) -> bool { 1736 pub fn is_usize(&self) -> bool {
1724 matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) 1737 matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
1725 } 1738 }
1726 1739
1727 pub fn remove_ref(&self) -> Option<Type> { 1740 pub fn remove_ref(&self) -> Option<Type> {
1728 match &self.ty.interned(&Interner) { 1741 match &self.ty.kind(&Interner) {
1729 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), 1742 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
1730 _ => None, 1743 _ => None,
1731 } 1744 }
@@ -1784,16 +1797,13 @@ impl Type {
1784 } 1797 }
1785 1798
1786 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { 1799 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1787 let trait_ref = hir_ty::TraitRef { 1800 let trait_ref = TyBuilder::trait_ref(db, trait_.id)
1788 trait_id: hir_ty::to_chalk_trait_id(trait_.id), 1801 .push(self.ty.clone())
1789 substitution: Substitution::build_for_def(db, trait_.id) 1802 .fill(args.iter().map(|t| t.ty.clone()))
1790 .push(self.ty.clone()) 1803 .build();
1791 .fill(args.iter().map(|t| t.ty.clone()))
1792 .build(),
1793 };
1794 1804
1795 let goal = Canonical { 1805 let goal = Canonical {
1796 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), 1806 value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(&Interner)),
1797 binders: CanonicalVarKinds::empty(&Interner), 1807 binders: CanonicalVarKinds::empty(&Interner),
1798 }; 1808 };
1799 1809
@@ -1803,22 +1813,18 @@ impl Type {
1803 pub fn normalize_trait_assoc_type( 1813 pub fn normalize_trait_assoc_type(
1804 &self, 1814 &self,
1805 db: &dyn HirDatabase, 1815 db: &dyn HirDatabase,
1806 trait_: Trait,
1807 args: &[Type], 1816 args: &[Type],
1808 alias: TypeAlias, 1817 alias: TypeAlias,
1809 ) -> Option<Type> { 1818 ) -> Option<Type> {
1810 let subst = Substitution::build_for_def(db, trait_.id) 1819 let projection = TyBuilder::assoc_type_projection(db, alias.id)
1811 .push(self.ty.clone()) 1820 .push(self.ty.clone())
1812 .fill(args.iter().map(|t| t.ty.clone())) 1821 .fill(args.iter().map(|t| t.ty.clone()))
1813 .build(); 1822 .build();
1814 let goal = Canonical::new( 1823 let goal = hir_ty::make_canonical(
1815 InEnvironment::new( 1824 InEnvironment::new(
1816 self.env.env.clone(), 1825 &self.env.env,
1817 AliasEq { 1826 AliasEq {
1818 alias: AliasTy::Projection(ProjectionTy { 1827 alias: AliasTy::Projection(projection),
1819 associated_ty_id: to_assoc_type_id(alias.id),
1820 substitution: subst,
1821 }),
1822 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 1828 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
1823 .intern(&Interner), 1829 .intern(&Interner),
1824 } 1830 }
@@ -1828,9 +1834,12 @@ impl Type {
1828 ); 1834 );
1829 1835
1830 match db.trait_solve(self.krate, goal)? { 1836 match db.trait_solve(self.krate, goal)? {
1831 Solution::Unique(SolutionVariables(subst)) => { 1837 Solution::Unique(s) => s
1832 subst.value.first().map(|ty| self.derived(ty.clone())) 1838 .value
1833 } 1839 .subst
1840 .as_slice(&Interner)
1841 .first()
1842 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
1834 Solution::Ambig(_) => None, 1843 Solution::Ambig(_) => None,
1835 } 1844 }
1836 } 1845 }
@@ -1852,15 +1861,15 @@ impl Type {
1852 } 1861 }
1853 1862
1854 pub fn is_closure(&self) -> bool { 1863 pub fn is_closure(&self) -> bool {
1855 matches!(&self.ty.interned(&Interner), TyKind::Closure { .. }) 1864 matches!(&self.ty.kind(&Interner), TyKind::Closure { .. })
1856 } 1865 }
1857 1866
1858 pub fn is_fn(&self) -> bool { 1867 pub fn is_fn(&self) -> bool {
1859 matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) 1868 matches!(&self.ty.kind(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
1860 } 1869 }
1861 1870
1862 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { 1871 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1863 let adt_id = match self.ty.interned(&Interner) { 1872 let adt_id = match self.ty.kind(&Interner) {
1864 &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, 1873 &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
1865 _ => return false, 1874 _ => return false,
1866 }; 1875 };
@@ -1873,27 +1882,30 @@ impl Type {
1873 } 1882 }
1874 1883
1875 pub fn is_raw_ptr(&self) -> bool { 1884 pub fn is_raw_ptr(&self) -> bool {
1876 matches!(&self.ty.interned(&Interner), TyKind::Raw(..)) 1885 matches!(&self.ty.kind(&Interner), TyKind::Raw(..))
1877 } 1886 }
1878 1887
1879 pub fn contains_unknown(&self) -> bool { 1888 pub fn contains_unknown(&self) -> bool {
1880 return go(&self.ty); 1889 return go(&self.ty);
1881 1890
1882 fn go(ty: &Ty) -> bool { 1891 fn go(ty: &Ty) -> bool {
1883 match ty.interned(&Interner) { 1892 match ty.kind(&Interner) {
1884 TyKind::Unknown => true, 1893 TyKind::Error => true,
1885 1894
1886 TyKind::Adt(_, substs) 1895 TyKind::Adt(_, substs)
1887 | TyKind::AssociatedType(_, substs) 1896 | TyKind::AssociatedType(_, substs)
1888 | TyKind::Tuple(_, substs) 1897 | TyKind::Tuple(_, substs)
1889 | TyKind::OpaqueType(_, substs) 1898 | TyKind::OpaqueType(_, substs)
1890 | TyKind::FnDef(_, substs) 1899 | TyKind::FnDef(_, substs)
1891 | TyKind::Closure(_, substs) => substs.iter().any(go), 1900 | TyKind::Closure(_, substs) => {
1892 1901 substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go)
1893 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
1894 go(ty)
1895 } 1902 }
1896 1903
1904 TyKind::Array(ty, _)
1905 | TyKind::Slice(ty)
1906 | TyKind::Raw(_, ty)
1907 | TyKind::Ref(_, _, ty) => go(ty),
1908
1897 TyKind::Scalar(_) 1909 TyKind::Scalar(_)
1898 | TyKind::Str 1910 | TyKind::Str
1899 | TyKind::Never 1911 | TyKind::Never
@@ -1903,13 +1915,15 @@ impl Type {
1903 | TyKind::Dyn(_) 1915 | TyKind::Dyn(_)
1904 | TyKind::Function(_) 1916 | TyKind::Function(_)
1905 | TyKind::Alias(_) 1917 | TyKind::Alias(_)
1906 | TyKind::ForeignType(_) => false, 1918 | TyKind::Foreign(_)
1919 | TyKind::Generator(..)
1920 | TyKind::GeneratorWitness(..) => false,
1907 } 1921 }
1908 } 1922 }
1909 } 1923 }
1910 1924
1911 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { 1925 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
1912 let (variant_id, substs) = match self.ty.interned(&Interner) { 1926 let (variant_id, substs) = match self.ty.kind(&Interner) {
1913 &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), 1927 &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
1914 &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), 1928 &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
1915 _ => return Vec::new(), 1929 _ => return Vec::new(),
@@ -1919,15 +1933,18 @@ impl Type {
1919 .iter() 1933 .iter()
1920 .map(|(local_id, ty)| { 1934 .map(|(local_id, ty)| {
1921 let def = Field { parent: variant_id.into(), id: local_id }; 1935 let def = Field { parent: variant_id.into(), id: local_id };
1922 let ty = ty.clone().subst(substs); 1936 let ty = ty.clone().substitute(&Interner, substs);
1923 (def, self.derived(ty)) 1937 (def, self.derived(ty))
1924 }) 1938 })
1925 .collect() 1939 .collect()
1926 } 1940 }
1927 1941
1928 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { 1942 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
1929 if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { 1943 if let TyKind::Tuple(_, substs) = &self.ty.kind(&Interner) {
1930 substs.iter().map(|ty| self.derived(ty.clone())).collect() 1944 substs
1945 .iter(&Interner)
1946 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone()))
1947 .collect()
1931 } else { 1948 } else {
1932 Vec::new() 1949 Vec::new()
1933 } 1950 }
@@ -1953,7 +1970,7 @@ impl Type {
1953 krate: Crate, 1970 krate: Crate,
1954 mut callback: impl FnMut(AssocItem) -> Option<T>, 1971 mut callback: impl FnMut(AssocItem) -> Option<T>,
1955 ) -> Option<T> { 1972 ) -> Option<T> {
1956 for krate in self.ty.def_crates(db, krate.id)? { 1973 for krate in def_crates(db, &self.ty, krate.id)? {
1957 let impls = db.inherent_impls_in_crate(krate); 1974 let impls = db.inherent_impls_in_crate(krate);
1958 1975
1959 for impl_def in impls.for_self_ty(&self.ty) { 1976 for impl_def in impls.for_self_ty(&self.ty) {
@@ -1970,10 +1987,11 @@ impl Type {
1970 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { 1987 pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ {
1971 self.ty 1988 self.ty
1972 .strip_references() 1989 .strip_references()
1973 .substs() 1990 .as_adt()
1974 .into_iter() 1991 .into_iter()
1975 .flat_map(|substs| substs.iter()) 1992 .flat_map(|(_, substs)| substs.iter(&Interner))
1976 .map(move |ty| self.derived(ty.clone())) 1993 .filter_map(|arg| arg.ty(&Interner).cloned())
1994 .map(move |ty| self.derived(ty))
1977 } 1995 }
1978 1996
1979 pub fn iterate_method_candidates<T>( 1997 pub fn iterate_method_candidates<T>(
@@ -2048,6 +2066,18 @@ impl Type {
2048 self.ty.dyn_trait().map(Into::into) 2066 self.ty.dyn_trait().map(Into::into)
2049 } 2067 }
2050 2068
2069 /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
2070 /// or an empty iterator otherwise.
2071 pub fn applicable_inherent_traits<'a>(
2072 &'a self,
2073 db: &'a dyn HirDatabase,
2074 ) -> impl Iterator<Item = Trait> + 'a {
2075 self.autoderef(db)
2076 .filter_map(|derefed_type| derefed_type.ty.dyn_trait())
2077 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
2078 .map(Trait::from)
2079 }
2080
2051 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { 2081 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
2052 self.ty.impl_trait_bounds(db).map(|it| { 2082 self.ty.impl_trait_bounds(db).map(|it| {
2053 it.into_iter() 2083 it.into_iter()
@@ -2079,7 +2109,7 @@ impl Type {
2079 substs: &Substitution, 2109 substs: &Substitution,
2080 cb: &mut impl FnMut(Type), 2110 cb: &mut impl FnMut(Type),
2081 ) { 2111 ) {
2082 for ty in substs.iter() { 2112 for ty in substs.iter(&Interner).filter_map(|a| a.ty(&Interner)) {
2083 walk_type(db, &type_.derived(ty.clone()), cb); 2113 walk_type(db, &type_.derived(ty.clone()), cb);
2084 } 2114 }
2085 } 2115 }
@@ -2095,7 +2125,12 @@ impl Type {
2095 WhereClause::Implemented(trait_ref) => { 2125 WhereClause::Implemented(trait_ref) => {
2096 cb(type_.clone()); 2126 cb(type_.clone());
2097 // skip the self type. it's likely the type we just got the bounds from 2127 // skip the self type. it's likely the type we just got the bounds from
2098 for ty in trait_ref.substitution.iter().skip(1) { 2128 for ty in trait_ref
2129 .substitution
2130 .iter(&Interner)
2131 .skip(1)
2132 .filter_map(|a| a.ty(&Interner))
2133 {
2099 walk_type(db, &type_.derived(ty.clone()), cb); 2134 walk_type(db, &type_.derived(ty.clone()), cb);
2100 } 2135 }
2101 } 2136 }
@@ -2106,19 +2141,23 @@ impl Type {
2106 2141
2107 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { 2142 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
2108 let ty = type_.ty.strip_references(); 2143 let ty = type_.ty.strip_references();
2109 match ty.interned(&Interner) { 2144 match ty.kind(&Interner) {
2110 TyKind::Adt(..) => { 2145 TyKind::Adt(_, substs) => {
2111 cb(type_.derived(ty.clone())); 2146 cb(type_.derived(ty.clone()));
2147 walk_substs(db, type_, &substs, cb);
2112 } 2148 }
2113 TyKind::AssociatedType(..) => { 2149 TyKind::AssociatedType(_, substs) => {
2114 if let Some(_) = ty.associated_type_parent_trait(db) { 2150 if let Some(_) = ty.associated_type_parent_trait(db) {
2115 cb(type_.derived(ty.clone())); 2151 cb(type_.derived(ty.clone()));
2116 } 2152 }
2153 walk_substs(db, type_, &substs, cb);
2117 } 2154 }
2118 TyKind::OpaqueType(..) => { 2155 TyKind::OpaqueType(_, subst) => {
2119 if let Some(bounds) = ty.impl_trait_bounds(db) { 2156 if let Some(bounds) = ty.impl_trait_bounds(db) {
2120 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); 2157 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
2121 } 2158 }
2159
2160 walk_substs(db, type_, subst, cb);
2122 } 2161 }
2123 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { 2162 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
2124 if let Some(bounds) = ty.impl_trait_bounds(db) { 2163 if let Some(bounds) = ty.impl_trait_bounds(db) {
@@ -2141,15 +2180,24 @@ impl Type {
2141 ); 2180 );
2142 } 2181 }
2143 2182
2144 TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { 2183 TyKind::Ref(_, _, ty)
2184 | TyKind::Raw(_, ty)
2185 | TyKind::Array(ty, _)
2186 | TyKind::Slice(ty) => {
2145 walk_type(db, &type_.derived(ty.clone()), cb); 2187 walk_type(db, &type_.derived(ty.clone()), cb);
2146 } 2188 }
2147 2189
2190 TyKind::FnDef(_, substs)
2191 | TyKind::Tuple(_, substs)
2192 | TyKind::Closure(.., substs) => {
2193 walk_substs(db, type_, &substs, cb);
2194 }
2195 TyKind::Function(hir_ty::FnPointer { substitution, .. }) => {
2196 walk_substs(db, type_, &substitution.0, cb);
2197 }
2198
2148 _ => {} 2199 _ => {}
2149 } 2200 }
2150 if let Some(substs) = ty.substs() {
2151 walk_substs(db, type_, &substs, cb);
2152 }
2153 } 2201 }
2154 2202
2155 walk_type(db, self, &mut cb); 2203 walk_type(db, self, &mut cb);
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index d3caeef4e..7955bf0b5 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -76,9 +76,11 @@ impl PathResolution {
76 pub fn assoc_type_shorthand_candidates<R>( 76 pub fn assoc_type_shorthand_candidates<R>(
77 &self, 77 &self,
78 db: &dyn HirDatabase, 78 db: &dyn HirDatabase,
79 mut cb: impl FnMut(TypeAlias) -> Option<R>, 79 mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>,
80 ) -> Option<R> { 80 ) -> Option<R> {
81 associated_type_shorthand_candidates(db, self.in_type_ns()?, |_, _, id| cb(id.into())) 81 associated_type_shorthand_candidates(db, self.in_type_ns()?, |name, _, id| {
82 cb(name, id.into())
83 })
82 } 84 }
83} 85}
84 86
@@ -492,9 +494,9 @@ impl<'db> SemanticsImpl<'db> {
492 fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { 494 fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
493 // FIXME: this erases Substs 495 // FIXME: this erases Substs
494 let func = self.resolve_method_call(call)?; 496 let func = self.resolve_method_call(call)?;
495 let ty = self.db.value_ty(func.into()); 497 let (ty, _) = self.db.value_ty(func.into()).into_value_and_skipped_binders();
496 let resolver = self.analyze(call.syntax()).resolver; 498 let resolver = self.analyze(call.syntax()).resolver;
497 let ty = Type::new_with_resolver(self.db, &resolver, ty.value)?; 499 let ty = Type::new_with_resolver(self.db, &resolver, ty)?;
498 let mut res = ty.as_callable(self.db)?; 500 let mut res = ty.as_callable(self.db)?;
499 res.is_bound_method = true; 501 res.is_bound_method = true;
500 Some(res) 502 Some(res)
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 37d162b32..847d2537d 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -20,7 +20,7 @@ use hir_def::{
20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
21use hir_ty::{ 21use hir_ty::{
22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, 22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
23 InferenceResult, Substitution, 23 InferenceResult, Interner, Substitution, TyExt, TyLoweringContext,
24}; 24};
25use syntax::{ 25use syntax::{
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
@@ -161,14 +161,15 @@ impl SourceAnalyzer {
161 db: &dyn HirDatabase, 161 db: &dyn HirDatabase,
162 field: &ast::RecordExprField, 162 field: &ast::RecordExprField,
163 ) -> Option<(Field, Option<Local>)> { 163 ) -> Option<(Field, Option<Local>)> {
164 let expr_id = 164 let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
165 self.body_source_map.as_ref()?.node_field(InFile::new(self.file_id, field))?; 165 let expr = ast::Expr::from(record_expr);
166 let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?;
166 167
168 let local_name = field.field_name()?.as_name();
167 let local = if field.name_ref().is_some() { 169 let local = if field.name_ref().is_some() {
168 None 170 None
169 } else { 171 } else {
170 let local_name = field.field_name()?.as_name(); 172 let path = ModPath::from_segments(PathKind::Plain, once(local_name.clone()));
171 let path = ModPath::from_segments(PathKind::Plain, once(local_name));
172 match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) { 173 match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
173 Some(ValueNs::LocalBinding(pat_id)) => { 174 Some(ValueNs::LocalBinding(pat_id)) => {
174 Some(Local { pat_id, parent: self.resolver.body_owner()? }) 175 Some(Local { pat_id, parent: self.resolver.body_owner()? })
@@ -176,18 +177,24 @@ impl SourceAnalyzer {
176 _ => None, 177 _ => None,
177 } 178 }
178 }; 179 };
179 let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?; 180 let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?;
180 Some((struct_field.into(), local)) 181 let variant_data = variant.variant_data(db.upcast());
182 let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
183 Some((field.into(), local))
181 } 184 }
182 185
183 pub(crate) fn resolve_record_pat_field( 186 pub(crate) fn resolve_record_pat_field(
184 &self, 187 &self,
185 _db: &dyn HirDatabase, 188 db: &dyn HirDatabase,
186 field: &ast::RecordPatField, 189 field: &ast::RecordPatField,
187 ) -> Option<Field> { 190 ) -> Option<Field> {
188 let pat_id = self.pat_id(&field.pat()?)?; 191 let field_name = field.field_name()?.as_name();
189 let struct_field = self.infer.as_ref()?.record_pat_field_resolution(pat_id)?; 192 let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
190 Some(struct_field.into()) 193 let pat_id = self.pat_id(&record_pat.into())?;
194 let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?;
195 let variant_data = variant.variant_data(db.upcast());
196 let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
197 Some(field.into())
191 } 198 }
192 199
193 pub(crate) fn resolve_macro_call( 200 pub(crate) fn resolve_macro_call(
@@ -299,7 +306,7 @@ impl SourceAnalyzer {
299 let infer = self.infer.as_ref()?; 306 let infer = self.infer.as_ref()?;
300 307
301 let expr_id = self.expr_id(db, &literal.clone().into())?; 308 let expr_id = self.expr_id(db, &literal.clone().into())?;
302 let substs = infer.type_of_expr[expr_id].substs()?; 309 let substs = infer.type_of_expr[expr_id].as_adt()?.1;
303 310
304 let (variant, missing_fields, _exhaustive) = 311 let (variant, missing_fields, _exhaustive) =
305 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; 312 record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?;
@@ -317,7 +324,7 @@ impl SourceAnalyzer {
317 let infer = self.infer.as_ref()?; 324 let infer = self.infer.as_ref()?;
318 325
319 let pat_id = self.pat_id(&pattern.clone().into())?; 326 let pat_id = self.pat_id(&pattern.clone().into())?;
320 let substs = infer.type_of_pat[pat_id].substs()?; 327 let substs = infer.type_of_pat[pat_id].as_adt()?.1;
321 328
322 let (variant, missing_fields, _exhaustive) = 329 let (variant, missing_fields, _exhaustive) =
323 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; 330 record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?;
@@ -339,7 +346,7 @@ impl SourceAnalyzer {
339 .into_iter() 346 .into_iter()
340 .map(|local_id| { 347 .map(|local_id| {
341 let field = FieldId { parent: variant, local_id }; 348 let field = FieldId { parent: variant, local_id };
342 let ty = field_types[local_id].clone().subst(substs); 349 let ty = field_types[local_id].clone().substitute(&Interner, substs);
343 (field.into(), Type::new_with_resolver_inner(db, krate, &self.resolver, ty)) 350 (field.into(), Type::new_with_resolver_inner(db, krate, &self.resolver, ty))
344 }) 351 })
345 .collect() 352 .collect()
@@ -466,7 +473,21 @@ fn resolve_hir_path_(
466 prefer_value_ns: bool, 473 prefer_value_ns: bool,
467) -> Option<PathResolution> { 474) -> Option<PathResolution> {
468 let types = || { 475 let types = || {
469 resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { 476 let (ty, unresolved) = match path.type_anchor() {
477 Some(type_ref) => {
478 let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref);
479 res.map(|ty_ns| (ty_ns, path.segments().first()))
480 }
481 None => {
482 let (ty, remaining) =
483 resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
484 match remaining {
485 Some(remaining) if remaining > 1 => None,
486 _ => Some((ty, path.segments().get(1))),
487 }
488 }
489 }?;
490 let res = match ty {
470 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), 491 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
471 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), 492 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
472 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { 493 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
@@ -476,7 +497,17 @@ fn resolve_hir_path_(
476 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), 497 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
477 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), 498 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
478 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 499 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
479 }) 500 };
501 match unresolved {
502 Some(unresolved) => res
503 .assoc_type_shorthand_candidates(db, |name, alias| {
504 (name == unresolved.name).then(|| alias)
505 })
506 .map(TypeAlias::from)
507 .map(Into::into)
508 .map(PathResolution::Def),
509 None => Some(res),
510 }
480 }; 511 };
481 512
482 let body_owner = resolver.body_owner(); 513 let body_owner = resolver.body_owner();
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml
index 475d337f3..43324d8d9 100644
--- a/crates/hir_def/Cargo.toml
+++ b/crates/hir_def/Cargo.toml
@@ -11,6 +11,7 @@ doctest = false
11 11
12[dependencies] 12[dependencies]
13cov-mark = { version = "1.1", features = ["thread-local"] } 13cov-mark = { version = "1.1", features = ["thread-local"] }
14dashmap = { version = "4.0.2", features = ["raw-api"] }
14log = "0.4.8" 15log = "0.4.8"
15once_cell = "1.3.1" 16once_cell = "1.3.1"
16rustc-hash = "1.1.0" 17rustc-hash = "1.1.0"
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index 58e35353b..402fb1d8d 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -15,6 +15,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
15use crate::{ 15use crate::{
16 body::{CfgExpander, LowerCtx}, 16 body::{CfgExpander, LowerCtx},
17 db::DefDatabase, 17 db::DefDatabase,
18 intern::Interned,
18 item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId}, 19 item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
19 src::HasChildSource, 20 src::HasChildSource,
20 src::HasSource, 21 src::HasSource,
@@ -58,7 +59,7 @@ pub enum VariantData {
58#[derive(Debug, Clone, PartialEq, Eq)] 59#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct FieldData { 60pub struct FieldData {
60 pub name: Name, 61 pub name: Name,
61 pub type_ref: TypeRef, 62 pub type_ref: Interned<TypeRef>,
62 pub visibility: RawVisibility, 63 pub visibility: RawVisibility,
63} 64}
64 65
@@ -292,7 +293,7 @@ fn lower_struct(
292 || Either::Left(fd.clone()), 293 || Either::Left(fd.clone()),
293 || FieldData { 294 || FieldData {
294 name: Name::new_tuple_field(i), 295 name: Name::new_tuple_field(i),
295 type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), 296 type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
296 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 297 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
297 }, 298 },
298 ); 299 );
@@ -309,7 +310,7 @@ fn lower_struct(
309 || Either::Right(fd.clone()), 310 || Either::Right(fd.clone()),
310 || FieldData { 311 || FieldData {
311 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 312 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
312 type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), 313 type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
313 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 314 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
314 }, 315 },
315 ); 316 );
@@ -358,7 +359,7 @@ fn lower_field(
358) -> FieldData { 359) -> FieldData {
359 FieldData { 360 FieldData {
360 name: field.name.clone(), 361 name: field.name.clone(),
361 type_ref: item_tree[field.type_ref].clone(), 362 type_ref: field.type_ref.clone(),
362 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), 363 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
363 } 364 }
364} 365}
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 52a2bce9b..786fad6e1 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -1,23 +1,28 @@
1//! A higher level attributes based on TokenTree, with also some shortcuts. 1//! A higher level attributes based on TokenTree, with also some shortcuts.
2 2
3use std::{ops, sync::Arc}; 3use std::{
4 convert::{TryFrom, TryInto},
5 ops,
6 sync::Arc,
7};
4 8
5use base_db::CrateId; 9use base_db::CrateId;
6use cfg::{CfgExpr, CfgOptions}; 10use cfg::{CfgExpr, CfgOptions};
7use either::Either; 11use either::Either;
8use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; 12use hir_expand::{hygiene::Hygiene, name::AsName, AstId, AttrId, InFile};
9use itertools::Itertools; 13use itertools::Itertools;
10use la_arena::ArenaMap; 14use la_arena::ArenaMap;
11use mbe::ast_to_token_tree; 15use mbe::ast_to_token_tree;
12use smallvec::{smallvec, SmallVec}; 16use smallvec::{smallvec, SmallVec};
13use syntax::{ 17use syntax::{
14 ast::{self, AstNode, AttrsOwner}, 18 ast::{self, AstNode, AttrsOwner},
15 match_ast, AstToken, SmolStr, SyntaxNode, 19 match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
16}; 20};
17use tt::Subtree; 21use tt::Subtree;
18 22
19use crate::{ 23use crate::{
20 db::DefDatabase, 24 db::DefDatabase,
25 intern::Interned,
21 item_tree::{ItemTreeId, ItemTreeNode}, 26 item_tree::{ItemTreeId, ItemTreeNode},
22 nameres::ModuleSource, 27 nameres::ModuleSource,
23 path::{ModPath, PathKind}, 28 path::{ModPath, PathKind},
@@ -93,13 +98,16 @@ impl RawAttrs {
93 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self { 98 pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self {
94 let entries = collect_attrs(owner) 99 let entries = collect_attrs(owner)
95 .enumerate() 100 .enumerate()
96 .flat_map(|(i, attr)| match attr { 101 .flat_map(|(i, attr)| {
97 Either::Left(attr) => Attr::from_src(attr, hygiene, i as u32), 102 let index = AttrId(i as u32);
98 Either::Right(comment) => comment.doc_comment().map(|doc| Attr { 103 match attr {
99 index: i as u32, 104 Either::Left(attr) => Attr::from_src(attr, hygiene, index),
100 input: Some(AttrInput::Literal(SmolStr::new(doc))), 105 Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
101 path: ModPath::from(hir_expand::name!(doc)), 106 id: index,
102 }), 107 input: Some(AttrInput::Literal(SmolStr::new(doc))),
108 path: Interned::new(ModPath::from(hir_expand::name!(doc))),
109 }),
110 }
103 }) 111 })
104 .collect::<Arc<_>>(); 112 .collect::<Arc<_>>();
105 113
@@ -156,7 +164,7 @@ impl RawAttrs {
156 let cfg = parts.next().unwrap(); 164 let cfg = parts.next().unwrap();
157 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; 165 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
158 let cfg = CfgExpr::parse(&cfg); 166 let cfg = CfgExpr::parse(&cfg);
159 let index = attr.index; 167 let index = attr.id;
160 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { 168 let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
161 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; 169 let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
162 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; 170 let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
@@ -210,12 +218,11 @@ impl Attrs {
210 let mut res = ArenaMap::default(); 218 let mut res = ArenaMap::default();
211 219
212 for (id, fld) in src.value.iter() { 220 for (id, fld) in src.value.iter() {
213 let attrs = match fld { 221 let owner: &dyn AttrsOwner = match fld {
214 Either::Left(_tuple) => Attrs::default(), 222 Either::Left(tuple) => tuple,
215 Either::Right(record) => { 223 Either::Right(record) => record,
216 RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate)
217 }
218 }; 224 };
225 let attrs = RawAttrs::from_attrs_owner(db, src.with_value(owner)).filter(db, krate);
219 226
220 res.insert(id, attrs); 227 res.insert(id, attrs);
221 } 228 }
@@ -399,10 +406,14 @@ impl AttrsWithOwner {
399 return AttrSourceMap { attrs }; 406 return AttrSourceMap { attrs };
400 } 407 }
401 AttrDefId::FieldId(id) => { 408 AttrDefId::FieldId(id) => {
402 id.parent.child_source(db).map(|source| match &source[id.local_id] { 409 let map = db.fields_attrs_source_map(id.parent);
403 Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), 410 let file_id = id.parent.file_id(db);
404 Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), 411 let root = db.parse_or_expand(file_id).unwrap();
405 }) 412 let owner = match &map[id.local_id] {
413 Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
414 Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
415 };
416 InFile::new(file_id, owner)
406 } 417 }
407 AttrDefId::AdtId(adt) => match adt { 418 AttrDefId::AdtId(adt) => match adt {
408 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 419 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -410,10 +421,12 @@ impl AttrsWithOwner {
410 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 421 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
411 }, 422 },
412 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 423 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
413 AttrDefId::EnumVariantId(id) => id 424 AttrDefId::EnumVariantId(id) => {
414 .parent 425 let map = db.variants_attrs_source_map(id.parent);
415 .child_source(db) 426 let file_id = id.parent.lookup(db).id.file_id();
416 .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), 427 let root = db.parse_or_expand(file_id).unwrap();
428 InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root)))
429 }
417 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 430 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
418 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 431 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
419 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 432 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -451,6 +464,55 @@ impl AttrsWithOwner {
451 .collect(), 464 .collect(),
452 } 465 }
453 } 466 }
467
468 pub fn docs_with_rangemap(
469 &self,
470 db: &dyn DefDatabase,
471 ) -> Option<(Documentation, DocsRangeMap)> {
472 // FIXME: code duplication in `docs` above
473 let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? {
474 AttrInput::Literal(s) => Some((s, attr.id)),
475 AttrInput::TokenTree(_) => None,
476 });
477 let indent = docs
478 .clone()
479 .flat_map(|(s, _)| s.lines())
480 .filter(|line| !line.chars().all(|c| c.is_whitespace()))
481 .map(|line| line.chars().take_while(|c| c.is_whitespace()).count())
482 .min()
483 .unwrap_or(0);
484 let mut buf = String::new();
485 let mut mapping = Vec::new();
486 for (doc, idx) in docs {
487 // str::lines doesn't yield anything for the empty string
488 if !doc.is_empty() {
489 for line in doc.split('\n') {
490 let line = line.trim_end();
491 let line_len = line.len();
492 let (offset, line) = match line.char_indices().nth(indent) {
493 Some((offset, _)) => (offset, &line[offset..]),
494 None => (0, line),
495 };
496 let buf_offset = buf.len();
497 buf.push_str(line);
498 mapping.push((
499 TextRange::new(buf_offset.try_into().ok()?, buf.len().try_into().ok()?),
500 idx,
501 TextRange::new(offset.try_into().ok()?, line_len.try_into().ok()?),
502 ));
503 buf.push('\n');
504 }
505 } else {
506 buf.push('\n');
507 }
508 }
509 buf.pop();
510 if buf.is_empty() {
511 None
512 } else {
513 Some((Documentation(buf), DocsRangeMap { mapping, source: self.source_map(db).attrs }))
514 }
515 }
454} 516}
455 517
456fn inner_attributes( 518fn inner_attributes(
@@ -501,16 +563,54 @@ impl AttrSourceMap {
501 /// the attribute represented by `Attr`. 563 /// the attribute represented by `Attr`.
502 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> { 564 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
503 self.attrs 565 self.attrs
504 .get(attr.index as usize) 566 .get(attr.id.0 as usize)
505 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) 567 .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", attr.id))
506 .as_ref() 568 .as_ref()
507 } 569 }
508} 570}
509 571
572/// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree.
573pub struct DocsRangeMap {
574 source: Vec<InFile<Either<ast::Attr, ast::Comment>>>,
575 // (docstring-line-range, attr_index, attr-string-range)
576 // a mapping from the text range of a line of the [`Documentation`] to the attribute index and
577 // the original (untrimmed) syntax doc line
578 mapping: Vec<(TextRange, AttrId, TextRange)>,
579}
580
581impl DocsRangeMap {
582 pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> {
583 let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?;
584 let (line_docs_range, idx, original_line_src_range) = self.mapping[found].clone();
585 if !line_docs_range.contains_range(range) {
586 return None;
587 }
588
589 let relative_range = range - line_docs_range.start();
590
591 let &InFile { file_id, value: ref source } = &self.source[idx.0 as usize];
592 match source {
593 Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here
594 // as well as for whats done in syntax highlight doc injection
595 Either::Right(comment) => {
596 let text_range = comment.syntax().text_range();
597 let range = TextRange::at(
598 text_range.start()
599 + TextSize::try_from(comment.prefix().len()).ok()?
600 + original_line_src_range.start()
601 + relative_range.start(),
602 text_range.len().min(range.len()),
603 );
604 Some(InFile { file_id, value: range })
605 }
606 }
607 }
608}
609
510#[derive(Debug, Clone, PartialEq, Eq)] 610#[derive(Debug, Clone, PartialEq, Eq)]
511pub struct Attr { 611pub struct Attr {
512 index: u32, 612 pub(crate) id: AttrId,
513 pub(crate) path: ModPath, 613 pub(crate) path: Interned<ModPath>,
514 pub(crate) input: Option<AttrInput>, 614 pub(crate) input: Option<AttrInput>,
515} 615}
516 616
@@ -523,8 +623,8 @@ pub enum AttrInput {
523} 623}
524 624
525impl Attr { 625impl Attr {
526 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { 626 fn from_src(ast: ast::Attr, hygiene: &Hygiene, id: AttrId) -> Option<Attr> {
527 let path = ModPath::from_src(ast.path()?, hygiene)?; 627 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?);
528 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { 628 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
529 let value = match lit.kind() { 629 let value = match lit.kind() {
530 ast::LiteralKind::String(string) => string.value()?.into(), 630 ast::LiteralKind::String(string) => string.value()?.into(),
@@ -532,11 +632,11 @@ impl Attr {
532 }; 632 };
533 Some(AttrInput::Literal(value)) 633 Some(AttrInput::Literal(value))
534 } else if let Some(tt) = ast.token_tree() { 634 } else if let Some(tt) = ast.token_tree() {
535 Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) 635 Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0))
536 } else { 636 } else {
537 None 637 None
538 }; 638 };
539 Some(Attr { index, path, input }) 639 Some(Attr { id, path, input })
540 } 640 }
541 641
542 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths 642 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
@@ -651,7 +751,38 @@ fn collect_attrs(
651 .chain(inner_docs.into_iter().flatten()) 751 .chain(inner_docs.into_iter().flatten())
652 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text))); 752 .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
653 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved 753 // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
654 let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); 754 docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).map(|(_, attr)| attr)
755}
756
757pub(crate) fn variants_attrs_source_map(
758 db: &dyn DefDatabase,
759 def: EnumId,
760) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
761 let mut res = ArenaMap::default();
762 let child_source = def.child_source(db);
763
764 for (idx, variant) in child_source.value.iter() {
765 res.insert(idx, AstPtr::new(variant));
766 }
767
768 Arc::new(res)
769}
770
771pub(crate) fn fields_attrs_source_map(
772 db: &dyn DefDatabase,
773 def: VariantId,
774) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> {
775 let mut res = ArenaMap::default();
776 let child_source = def.child_source(db);
777
778 for (idx, variant) in child_source.value.iter() {
779 res.insert(
780 idx,
781 variant
782 .as_ref()
783 .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))),
784 );
785 }
655 786
656 attrs.into_iter().map(|(_, attr)| attr) 787 Arc::new(res)
657} 788}
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 1080d9c2c..96b959967 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -226,7 +226,7 @@ pub struct Body {
226 /// The `ExprId` of the actual body expression. 226 /// The `ExprId` of the actual body expression.
227 pub body_expr: ExprId, 227 pub body_expr: ExprId,
228 /// Block expressions in this body that may contain inner items. 228 /// Block expressions in this body that may contain inner items.
229 pub block_scopes: Vec<BlockId>, 229 block_scopes: Vec<BlockId>,
230 _c: Count<Self>, 230 _c: Count<Self>,
231} 231}
232 232
@@ -302,7 +302,8 @@ impl Body {
302 } 302 }
303 }; 303 };
304 let expander = Expander::new(db, file_id, module); 304 let expander = Expander::new(db, file_id, module);
305 let (body, source_map) = Body::new(db, expander, params, body); 305 let (mut body, source_map) = Body::new(db, expander, params, body);
306 body.shrink_to_fit();
306 (Arc::new(body), Arc::new(source_map)) 307 (Arc::new(body), Arc::new(source_map))
307 } 308 }
308 309
@@ -310,6 +311,16 @@ impl Body {
310 db.body_with_source_map(def).0 311 db.body_with_source_map(def).0
311 } 312 }
312 313
314 /// Returns an iterator over all block expressions in this body that define inner items.
315 pub fn blocks<'a>(
316 &'a self,
317 db: &'a dyn DefDatabase,
318 ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ {
319 self.block_scopes
320 .iter()
321 .map(move |block| (*block, db.block_def_map(*block).expect("block ID without DefMap")))
322 }
323
313 fn new( 324 fn new(
314 db: &dyn DefDatabase, 325 db: &dyn DefDatabase,
315 expander: Expander, 326 expander: Expander,
@@ -318,6 +329,15 @@ impl Body {
318 ) -> (Body, BodySourceMap) { 329 ) -> (Body, BodySourceMap) {
319 lower::lower(db, expander, params, body) 330 lower::lower(db, expander, params, body)
320 } 331 }
332
333 fn shrink_to_fit(&mut self) {
334 let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats } = self;
335 block_scopes.shrink_to_fit();
336 exprs.shrink_to_fit();
337 labels.shrink_to_fit();
338 params.shrink_to_fit();
339 pats.shrink_to_fit();
340 }
321} 341}
322 342
323impl Index<ExprId> for Body { 343impl Index<ExprId> for Body {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 229e81dd4..c0b0b7841 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -30,6 +30,7 @@ use crate::{
30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, 30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
31 Statement, 31 Statement,
32 }, 32 },
33 intern::Interned,
33 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
34 path::{GenericArgs, Path}, 35 path::{GenericArgs, Path},
35 type_ref::{Mutability, Rawness, TypeRef}, 36 type_ref::{Mutability, Rawness, TypeRef},
@@ -322,8 +323,10 @@ impl ExprCollector<'_> {
322 Vec::new() 323 Vec::new()
323 }; 324 };
324 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
325 let generic_args = 326 let generic_args = e
326 e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 327 .generic_arg_list()
328 .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
329 .map(Box::new);
327 self.alloc_expr( 330 self.alloc_expr(
328 Expr::MethodCall { receiver, method_name, args, generic_args }, 331 Expr::MethodCall { receiver, method_name, args, generic_args },
329 syntax_ptr, 332 syntax_ptr,
@@ -385,7 +388,7 @@ impl ExprCollector<'_> {
385 self.alloc_expr(Expr::Yield { expr }, syntax_ptr) 388 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
386 } 389 }
387 ast::Expr::RecordExpr(e) => { 390 ast::Expr::RecordExpr(e) => {
388 let path = e.path().and_then(|path| self.expander.parse_path(path)); 391 let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
389 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 392 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
390 let fields = nfl 393 let fields = nfl
391 .fields() 394 .fields()
@@ -430,7 +433,7 @@ impl ExprCollector<'_> {
430 } 433 }
431 ast::Expr::CastExpr(e) => { 434 ast::Expr::CastExpr(e) => {
432 let expr = self.collect_expr_opt(e.expr()); 435 let expr = self.collect_expr_opt(e.expr());
433 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); 436 let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
434 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 437 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
435 } 438 }
436 ast::Expr::RefExpr(e) => { 439 ast::Expr::RefExpr(e) => {
@@ -464,13 +467,16 @@ impl ExprCollector<'_> {
464 if let Some(pl) = e.param_list() { 467 if let Some(pl) = e.param_list() {
465 for param in pl.params() { 468 for param in pl.params() {
466 let pat = self.collect_pat_opt(param.pat()); 469 let pat = self.collect_pat_opt(param.pat());
467 let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 470 let type_ref =
471 param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
468 args.push(pat); 472 args.push(pat);
469 arg_types.push(type_ref); 473 arg_types.push(type_ref);
470 } 474 }
471 } 475 }
472 let ret_type = 476 let ret_type = e
473 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); 477 .ret_type()
478 .and_then(|r| r.ty())
479 .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
474 let body = self.collect_expr_opt(e.body()); 480 let body = self.collect_expr_opt(e.body());
475 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 481 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
476 } 482 }
@@ -525,8 +531,9 @@ impl ExprCollector<'_> {
525 } 531 }
526 } 532 }
527 ast::Expr::MacroCall(e) => { 533 ast::Expr::MacroCall(e) => {
534 let macro_ptr = AstPtr::new(&e);
528 let mut ids = vec![]; 535 let mut ids = vec![];
529 self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| { 536 self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
530 ids.push(match expansion { 537 ids.push(match expansion {
531 Some(it) => this.collect_expr(it), 538 Some(it) => this.collect_expr(it),
532 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), 539 None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
@@ -549,7 +556,7 @@ impl ExprCollector<'_> {
549 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>( 556 fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>(
550 &mut self, 557 &mut self,
551 e: ast::MacroCall, 558 e: ast::MacroCall,
552 syntax_ptr: AstPtr<ast::Expr>, 559 syntax_ptr: AstPtr<ast::MacroCall>,
553 is_error_recoverable: bool, 560 is_error_recoverable: bool,
554 mut collector: F, 561 mut collector: F,
555 ) { 562 ) {
@@ -561,9 +568,13 @@ impl ExprCollector<'_> {
561 568
562 let res = match res { 569 let res = match res {
563 Ok(res) => res, 570 Ok(res) => res,
564 Err(UnresolvedMacro) => { 571 Err(UnresolvedMacro { path }) => {
565 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall( 572 self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall(
566 UnresolvedMacroCall { file: outer_file, node: syntax_ptr.cast().unwrap() }, 573 UnresolvedMacroCall {
574 file: outer_file,
575 node: syntax_ptr.cast().unwrap(),
576 path,
577 },
567 )); 578 ));
568 collector(self, None); 579 collector(self, None);
569 return; 580 return;
@@ -625,7 +636,8 @@ impl ExprCollector<'_> {
625 return; 636 return;
626 } 637 }
627 let pat = self.collect_pat_opt(stmt.pat()); 638 let pat = self.collect_pat_opt(stmt.pat());
628 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 639 let type_ref =
640 stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
629 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 641 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
630 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer }); 642 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
631 } 643 }
@@ -636,10 +648,14 @@ impl ExprCollector<'_> {
636 648
637 // Note that macro could be expended to multiple statements 649 // Note that macro could be expended to multiple statements
638 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { 650 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
651 let macro_ptr = AstPtr::new(&m);
639 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); 652 let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
640 653
641 self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { 654 self.collect_macro_call(
642 match expansion { 655 m,
656 macro_ptr,
657 false,
658 |this, expansion| match expansion {
643 Some(expansion) => { 659 Some(expansion) => {
644 let statements: ast::MacroStmts = expansion; 660 let statements: ast::MacroStmts = expansion;
645 661
@@ -653,8 +669,8 @@ impl ExprCollector<'_> {
653 let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); 669 let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
654 this.statements_in_scope.push(Statement::Expr(expr)); 670 this.statements_in_scope.push(Statement::Expr(expr));
655 } 671 }
656 } 672 },
657 }); 673 );
658 } else { 674 } else {
659 let expr = self.collect_expr_opt(stmt.expr()); 675 let expr = self.collect_expr_opt(stmt.expr());
660 self.statements_in_scope.push(Statement::Expr(expr)); 676 self.statements_in_scope.push(Statement::Expr(expr));
@@ -673,12 +689,14 @@ impl ExprCollector<'_> {
673 let block_loc = 689 let block_loc =
674 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; 690 BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
675 let block_id = self.db.intern_block(block_loc); 691 let block_id = self.db.intern_block(block_loc);
676 self.body.block_scopes.push(block_id);
677 692
678 let opt_def_map = self.db.block_def_map(block_id); 693 let (module, def_map) = match self.db.block_def_map(block_id) {
679 let has_def_map = opt_def_map.is_some(); 694 Some(def_map) => {
680 let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); 695 self.body.block_scopes.push(block_id);
681 let module = if has_def_map { def_map.root() } else { self.expander.module }; 696 (def_map.root(), def_map)
697 }
698 None => (self.expander.module, self.expander.def_map.clone()),
699 };
682 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); 700 let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
683 let prev_local_module = mem::replace(&mut self.expander.module, module); 701 let prev_local_module = mem::replace(&mut self.expander.module, module);
684 let prev_statements = std::mem::take(&mut self.statements_in_scope); 702 let prev_statements = std::mem::take(&mut self.statements_in_scope);
@@ -753,7 +771,7 @@ impl ExprCollector<'_> {
753 } 771 }
754 } 772 }
755 ast::Pat::TupleStructPat(p) => { 773 ast::Pat::TupleStructPat(p) => {
756 let path = p.path().and_then(|path| self.expander.parse_path(path)); 774 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
757 let (args, ellipsis) = self.collect_tuple_pat(p.fields()); 775 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
758 Pat::TupleStruct { path, args, ellipsis } 776 Pat::TupleStruct { path, args, ellipsis }
759 } 777 }
@@ -763,7 +781,7 @@ impl ExprCollector<'_> {
763 Pat::Ref { pat, mutability } 781 Pat::Ref { pat, mutability }
764 } 782 }
765 ast::Pat::PathPat(p) => { 783 ast::Pat::PathPat(p) => {
766 let path = p.path().and_then(|path| self.expander.parse_path(path)); 784 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
767 path.map(Pat::Path).unwrap_or(Pat::Missing) 785 path.map(Pat::Path).unwrap_or(Pat::Missing)
768 } 786 }
769 ast::Pat::OrPat(p) => { 787 ast::Pat::OrPat(p) => {
@@ -777,7 +795,7 @@ impl ExprCollector<'_> {
777 } 795 }
778 ast::Pat::WildcardPat(_) => Pat::Wild, 796 ast::Pat::WildcardPat(_) => Pat::Wild,
779 ast::Pat::RecordPat(p) => { 797 ast::Pat::RecordPat(p) => {
780 let path = p.path().and_then(|path| self.expander.parse_path(path)); 798 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
781 let args: Vec<_> = p 799 let args: Vec<_> = p
782 .record_pat_field_list() 800 .record_pat_field_list()
783 .expect("every struct should have a field list") 801 .expect("every struct should have a field list")
@@ -839,8 +857,23 @@ impl ExprCollector<'_> {
839 Pat::Missing 857 Pat::Missing
840 } 858 }
841 } 859 }
860 ast::Pat::MacroPat(mac) => match mac.macro_call() {
861 Some(call) => {
862 let macro_ptr = AstPtr::new(&call);
863 let mut pat = None;
864 self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
865 pat = Some(this.collect_pat_opt(expanded_pat));
866 });
867
868 match pat {
869 Some(pat) => return pat,
870 None => Pat::Missing,
871 }
872 }
873 None => Pat::Missing,
874 },
842 // FIXME: implement 875 // FIXME: implement
843 ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, 876 ast::Pat::RangePat(_) => Pat::Missing,
844 }; 877 };
845 let ptr = AstPtr::new(&pat); 878 let ptr = AstPtr::new(&pat);
846 self.alloc_pat(pattern, Either::Left(ptr)) 879 self.alloc_pat(pattern, Either::Left(ptr))
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs
index faa133297..63f5fe88d 100644
--- a/crates/hir_def/src/body/tests.rs
+++ b/crates/hir_def/src/body/tests.rs
@@ -143,7 +143,7 @@ fn f() {
143 //^^^^^^^^^^^^^ could not convert tokens 143 //^^^^^^^^^^^^^ could not convert tokens
144 144
145 env!("OUT_DIR"); 145 env!("OUT_DIR");
146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix 146 //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix
147 147
148 compile_error!("compile_error works"); 148 compile_error!("compile_error works");
149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works 149 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works
@@ -180,7 +180,7 @@ fn unresolved_macro_diag() {
180 r#" 180 r#"
181fn f() { 181fn f() {
182 m!(); 182 m!();
183 //^^^^ unresolved macro call 183 //^^^^ unresolved macro `m!`
184} 184}
185 "#, 185 "#,
186 ); 186 );
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs
index 2a331dcaf..f2e809ca9 100644
--- a/crates/hir_def/src/child_by_source.rs
+++ b/crates/hir_def/src/child_by_source.rs
@@ -80,6 +80,10 @@ impl ChildBySource for ModuleId {
80impl ChildBySource for ItemScope { 80impl ChildBySource for ItemScope {
81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { 81 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
82 self.declarations().for_each(|item| add_module_def(db, res, item)); 82 self.declarations().for_each(|item| add_module_def(db, res, item));
83 self.unnamed_consts().for_each(|konst| {
84 let src = konst.lookup(db).source(db);
85 res[keys::CONST].insert(src, konst);
86 });
83 self.impls().for_each(|imp| add_impl(db, res, imp)); 87 self.impls().for_each(|imp| add_impl(db, res, imp));
84 88
85 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { 89 fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
@@ -160,7 +164,7 @@ impl ChildBySource for EnumId {
160impl ChildBySource for DefWithBodyId { 164impl ChildBySource for DefWithBodyId {
161 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { 165 fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
162 let body = db.body(*self); 166 let body = db.body(*self);
163 for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { 167 for (_, def_map) in body.blocks(db) {
164 // All block expressions are merged into the same map, because they logically all add 168 // All block expressions are merged into the same map, because they logically all add
165 // inner items to the containing `DefWithBodyId`. 169 // inner items to the containing `DefWithBodyId`.
166 def_map[def_map.root()].scope.child_by_source_to(db, res); 170 def_map[def_map.root()].scope.child_by_source_to(db, res);
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index 0be868ba2..135a6698e 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -9,8 +9,9 @@ use crate::{
9 attr::Attrs, 9 attr::Attrs,
10 body::Expander, 10 body::Expander,
11 db::DefDatabase, 11 db::DefDatabase,
12 item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, 12 intern::Interned,
13 type_ref::{TypeBound, TypeRef}, 13 item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param},
14 type_ref::{TraitRef, TypeBound, TypeRef},
14 visibility::RawVisibility, 15 visibility::RawVisibility,
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, 16 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
16 Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 17 Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
@@ -19,17 +20,12 @@ use crate::{
19#[derive(Debug, Clone, PartialEq, Eq)] 20#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct FunctionData { 21pub struct FunctionData {
21 pub name: Name, 22 pub name: Name,
22 pub params: Vec<TypeRef>, 23 pub params: Vec<Interned<TypeRef>>,
23 pub ret_type: TypeRef, 24 pub ret_type: Interned<TypeRef>,
24 pub attrs: Attrs, 25 pub attrs: Attrs,
25 /// True if the first param is `self`. This is relevant to decide whether this
26 /// can be called as a method.
27 pub has_self_param: bool,
28 pub has_body: bool,
29 pub qualifier: FunctionQualifier,
30 pub is_in_extern_block: bool,
31 pub is_varargs: bool,
32 pub visibility: RawVisibility, 26 pub visibility: RawVisibility,
27 pub abi: Option<Interned<str>>,
28 flags: FnFlags,
33} 29}
34 30
35impl FunctionData { 31impl FunctionData {
@@ -52,31 +48,67 @@ impl FunctionData {
52 .next_back() 48 .next_back()
53 .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); 49 .map_or(false, |param| matches!(item_tree[param], Param::Varargs));
54 50
51 let mut flags = func.flags;
52 if is_varargs {
53 flags.bits |= FnFlags::IS_VARARGS;
54 }
55
55 Arc::new(FunctionData { 56 Arc::new(FunctionData {
56 name: func.name.clone(), 57 name: func.name.clone(),
57 params: enabled_params 58 params: enabled_params
58 .clone() 59 .clone()
59 .filter_map(|id| match &item_tree[id] { 60 .filter_map(|id| match &item_tree[id] {
60 Param::Normal(ty) => Some(item_tree[*ty].clone()), 61 Param::Normal(ty) => Some(ty.clone()),
61 Param::Varargs => None, 62 Param::Varargs => None,
62 }) 63 })
63 .collect(), 64 .collect(),
64 ret_type: item_tree[func.ret_type].clone(), 65 ret_type: func.ret_type.clone(),
65 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), 66 attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
66 has_self_param: func.has_self_param,
67 has_body: func.has_body,
68 qualifier: func.qualifier.clone(),
69 is_in_extern_block: func.is_in_extern_block,
70 is_varargs,
71 visibility: item_tree[func.visibility].clone(), 67 visibility: item_tree[func.visibility].clone(),
68 abi: func.abi.clone(),
69 flags,
72 }) 70 })
73 } 71 }
72
73 pub fn has_body(&self) -> bool {
74 self.flags.bits & FnFlags::HAS_BODY != 0
75 }
76
77 /// True if the first param is `self`. This is relevant to decide whether this
78 /// can be called as a method.
79 pub fn has_self_param(&self) -> bool {
80 self.flags.bits & FnFlags::HAS_SELF_PARAM != 0
81 }
82
83 pub fn is_default(&self) -> bool {
84 self.flags.bits & FnFlags::IS_DEFAULT != 0
85 }
86
87 pub fn is_const(&self) -> bool {
88 self.flags.bits & FnFlags::IS_CONST != 0
89 }
90
91 pub fn is_async(&self) -> bool {
92 self.flags.bits & FnFlags::IS_ASYNC != 0
93 }
94
95 pub fn is_unsafe(&self) -> bool {
96 self.flags.bits & FnFlags::IS_UNSAFE != 0
97 }
98
99 pub fn is_in_extern_block(&self) -> bool {
100 self.flags.bits & FnFlags::IS_IN_EXTERN_BLOCK != 0
101 }
102
103 pub fn is_varargs(&self) -> bool {
104 self.flags.bits & FnFlags::IS_VARARGS != 0
105 }
74} 106}
75 107
76#[derive(Debug, Clone, PartialEq, Eq)] 108#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct TypeAliasData { 109pub struct TypeAliasData {
78 pub name: Name, 110 pub name: Name,
79 pub type_ref: Option<TypeRef>, 111 pub type_ref: Option<Interned<TypeRef>>,
80 pub visibility: RawVisibility, 112 pub visibility: RawVisibility,
81 pub is_extern: bool, 113 pub is_extern: bool,
82 /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). 114 /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
@@ -94,7 +126,7 @@ impl TypeAliasData {
94 126
95 Arc::new(TypeAliasData { 127 Arc::new(TypeAliasData {
96 name: typ.name.clone(), 128 name: typ.name.clone(),
97 type_ref: typ.type_ref.map(|id| item_tree[id].clone()), 129 type_ref: typ.type_ref.clone(),
98 visibility: item_tree[typ.visibility].clone(), 130 visibility: item_tree[typ.visibility].clone(),
99 is_extern: typ.is_extern, 131 is_extern: typ.is_extern,
100 bounds: typ.bounds.to_vec(), 132 bounds: typ.bounds.to_vec(),
@@ -156,8 +188,8 @@ impl TraitData {
156 188
157#[derive(Debug, Clone, PartialEq, Eq)] 189#[derive(Debug, Clone, PartialEq, Eq)]
158pub struct ImplData { 190pub struct ImplData {
159 pub target_trait: Option<TypeRef>, 191 pub target_trait: Option<Interned<TraitRef>>,
160 pub target_type: TypeRef, 192 pub self_ty: Interned<TypeRef>,
161 pub items: Vec<AssocItemId>, 193 pub items: Vec<AssocItemId>,
162 pub is_negative: bool, 194 pub is_negative: bool,
163} 195}
@@ -169,8 +201,8 @@ impl ImplData {
169 201
170 let item_tree = impl_loc.id.item_tree(db); 202 let item_tree = impl_loc.id.item_tree(db);
171 let impl_def = &item_tree[impl_loc.id.value]; 203 let impl_def = &item_tree[impl_loc.id.value];
172 let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); 204 let target_trait = impl_def.target_trait.clone();
173 let target_type = item_tree[impl_def.target_type].clone(); 205 let self_ty = impl_def.self_ty.clone();
174 let is_negative = impl_def.is_negative; 206 let is_negative = impl_def.is_negative;
175 let module_id = impl_loc.container; 207 let module_id = impl_loc.container;
176 let container = AssocContainerId::ImplId(id); 208 let container = AssocContainerId::ImplId(id);
@@ -187,7 +219,7 @@ impl ImplData {
187 ); 219 );
188 let items = items.into_iter().map(|(_, item)| item).collect(); 220 let items = items.into_iter().map(|(_, item)| item).collect();
189 221
190 Arc::new(ImplData { target_trait, target_type, items, is_negative }) 222 Arc::new(ImplData { target_trait, self_ty, items, is_negative })
191 } 223 }
192} 224}
193 225
@@ -195,7 +227,7 @@ impl ImplData {
195pub struct ConstData { 227pub struct ConstData {
196 /// const _: () = (); 228 /// const _: () = ();
197 pub name: Option<Name>, 229 pub name: Option<Name>,
198 pub type_ref: TypeRef, 230 pub type_ref: Interned<TypeRef>,
199 pub visibility: RawVisibility, 231 pub visibility: RawVisibility,
200} 232}
201 233
@@ -207,7 +239,7 @@ impl ConstData {
207 239
208 Arc::new(ConstData { 240 Arc::new(ConstData {
209 name: konst.name.clone(), 241 name: konst.name.clone(),
210 type_ref: item_tree[konst.type_ref].clone(), 242 type_ref: konst.type_ref.clone(),
211 visibility: item_tree[konst.visibility].clone(), 243 visibility: item_tree[konst.visibility].clone(),
212 }) 244 })
213 } 245 }
@@ -216,7 +248,7 @@ impl ConstData {
216#[derive(Debug, Clone, PartialEq, Eq)] 248#[derive(Debug, Clone, PartialEq, Eq)]
217pub struct StaticData { 249pub struct StaticData {
218 pub name: Option<Name>, 250 pub name: Option<Name>,
219 pub type_ref: TypeRef, 251 pub type_ref: Interned<TypeRef>,
220 pub visibility: RawVisibility, 252 pub visibility: RawVisibility,
221 pub mutable: bool, 253 pub mutable: bool,
222 pub is_extern: bool, 254 pub is_extern: bool,
@@ -230,7 +262,7 @@ impl StaticData {
230 262
231 Arc::new(StaticData { 263 Arc::new(StaticData {
232 name: Some(statik.name.clone()), 264 name: Some(statik.name.clone()),
233 type_ref: item_tree[statik.type_ref].clone(), 265 type_ref: statik.type_ref.clone(),
234 visibility: item_tree[statik.visibility].clone(), 266 visibility: item_tree[statik.visibility].clone(),
235 mutable: statik.mutable, 267 mutable: statik.mutable,
236 is_extern: statik.is_extern, 268 is_extern: statik.is_extern,
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 068b2ee38..7eadc8e0d 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -2,9 +2,10 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use base_db::{salsa, CrateId, SourceDatabase, Upcast}; 4use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5use either::Either;
5use hir_expand::{db::AstDatabase, HirFileId}; 6use hir_expand::{db::AstDatabase, HirFileId};
6use la_arena::ArenaMap; 7use la_arena::ArenaMap;
7use syntax::SmolStr; 8use syntax::{ast, AstPtr, SmolStr};
8 9
9use crate::{ 10use crate::{
10 adt::{EnumData, StructData}, 11 adt::{EnumData, StructData},
@@ -13,6 +14,7 @@ use crate::{
13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, 14 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
14 generics::GenericParams, 15 generics::GenericParams,
15 import_map::ImportMap, 16 import_map::ImportMap,
17 intern::Interned,
16 item_tree::ItemTree, 18 item_tree::ItemTree,
17 lang_item::{LangItemTarget, LangItems}, 19 lang_item::{LangItemTarget, LangItems},
18 nameres::DefMap, 20 nameres::DefMap,
@@ -113,7 +115,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
113 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; 115 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
114 116
115 #[salsa::invoke(GenericParams::generic_params_query)] 117 #[salsa::invoke(GenericParams::generic_params_query)]
116 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; 118 fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>;
117 119
118 #[salsa::invoke(Attrs::variants_attrs_query)] 120 #[salsa::invoke(Attrs::variants_attrs_query)]
119 fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; 121 fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>;
@@ -121,6 +123,18 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
121 #[salsa::invoke(Attrs::fields_attrs_query)] 123 #[salsa::invoke(Attrs::fields_attrs_query)]
122 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; 124 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
123 125
126 #[salsa::invoke(crate::attr::variants_attrs_source_map)]
127 fn variants_attrs_source_map(
128 &self,
129 def: EnumId,
130 ) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>;
131
132 #[salsa::invoke(crate::attr::fields_attrs_source_map)]
133 fn fields_attrs_source_map(
134 &self,
135 def: VariantId,
136 ) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>>;
137
124 #[salsa::invoke(AttrsWithOwner::attrs_query)] 138 #[salsa::invoke(AttrsWithOwner::attrs_query)]
125 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; 139 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner;
126 140
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs
index 97abf8653..a71ae2668 100644
--- a/crates/hir_def/src/diagnostics.rs
+++ b/crates/hir_def/src/diagnostics.rs
@@ -8,7 +8,7 @@ use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink};
8use hir_expand::{HirFileId, InFile}; 8use hir_expand::{HirFileId, InFile};
9use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; 9use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
10 10
11use crate::{db::DefDatabase, DefWithBodyId}; 11use crate::{db::DefDatabase, path::ModPath, DefWithBodyId};
12 12
13pub fn validate_body(db: &dyn DefDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) { 13pub fn validate_body(db: &dyn DefDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) {
14 let source_map = db.body_with_source_map(owner).1; 14 let source_map = db.body_with_source_map(owner).1;
@@ -103,6 +103,7 @@ impl Diagnostic for UnresolvedImport {
103pub struct UnresolvedMacroCall { 103pub struct UnresolvedMacroCall {
104 pub file: HirFileId, 104 pub file: HirFileId,
105 pub node: AstPtr<ast::MacroCall>, 105 pub node: AstPtr<ast::MacroCall>,
106 pub path: ModPath,
106} 107}
107 108
108impl Diagnostic for UnresolvedMacroCall { 109impl Diagnostic for UnresolvedMacroCall {
@@ -110,7 +111,7 @@ impl Diagnostic for UnresolvedMacroCall {
110 DiagnosticCode("unresolved-macro-call") 111 DiagnosticCode("unresolved-macro-call")
111 } 112 }
112 fn message(&self) -> String { 113 fn message(&self) -> String {
113 "unresolved macro call".to_string() 114 format!("unresolved macro `{}!`", self.path)
114 } 115 }
115 fn display_source(&self) -> InFile<SyntaxNodePtr> { 116 fn display_source(&self) -> InFile<SyntaxNodePtr> {
116 InFile::new(self.file, self.node.clone().into()) 117 InFile::new(self.file, self.node.clone().into())
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 6c7376fad..b4ad984bd 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -18,6 +18,7 @@ use syntax::ast::RangeOp;
18 18
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, 20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
21 intern::Interned,
21 path::{GenericArgs, Path}, 22 path::{GenericArgs, Path},
22 type_ref::{Mutability, Rawness, TypeRef}, 23 type_ref::{Mutability, Rawness, TypeRef},
23 BlockId, 24 BlockId,
@@ -86,7 +87,7 @@ pub enum Expr {
86 receiver: ExprId, 87 receiver: ExprId,
87 method_name: Name, 88 method_name: Name,
88 args: Vec<ExprId>, 89 args: Vec<ExprId>,
89 generic_args: Option<GenericArgs>, 90 generic_args: Option<Box<GenericArgs>>,
90 }, 91 },
91 Match { 92 Match {
92 expr: ExprId, 93 expr: ExprId,
@@ -106,7 +107,7 @@ pub enum Expr {
106 expr: Option<ExprId>, 107 expr: Option<ExprId>,
107 }, 108 },
108 RecordLit { 109 RecordLit {
109 path: Option<Path>, 110 path: Option<Box<Path>>,
110 fields: Vec<RecordLitField>, 111 fields: Vec<RecordLitField>,
111 spread: Option<ExprId>, 112 spread: Option<ExprId>,
112 }, 113 },
@@ -131,7 +132,7 @@ pub enum Expr {
131 }, 132 },
132 Cast { 133 Cast {
133 expr: ExprId, 134 expr: ExprId,
134 type_ref: TypeRef, 135 type_ref: Interned<TypeRef>,
135 }, 136 },
136 Ref { 137 Ref {
137 expr: ExprId, 138 expr: ExprId,
@@ -161,8 +162,8 @@ pub enum Expr {
161 }, 162 },
162 Lambda { 163 Lambda {
163 args: Vec<PatId>, 164 args: Vec<PatId>,
164 arg_types: Vec<Option<TypeRef>>, 165 arg_types: Vec<Option<Interned<TypeRef>>>,
165 ret_type: Option<TypeRef>, 166 ret_type: Option<Interned<TypeRef>>,
166 body: ExprId, 167 body: ExprId,
167 }, 168 },
168 Tuple { 169 Tuple {
@@ -240,7 +241,7 @@ pub struct RecordLitField {
240 241
241#[derive(Debug, Clone, Eq, PartialEq)] 242#[derive(Debug, Clone, Eq, PartialEq)]
242pub enum Statement { 243pub enum Statement {
243 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> }, 244 Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> },
244 Expr(ExprId), 245 Expr(ExprId),
245} 246}
246 247
@@ -412,13 +413,13 @@ pub enum Pat {
412 Wild, 413 Wild,
413 Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, 414 Tuple { args: Vec<PatId>, ellipsis: Option<usize> },
414 Or(Vec<PatId>), 415 Or(Vec<PatId>),
415 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, 416 Record { path: Option<Box<Path>>, args: Vec<RecordFieldPat>, ellipsis: bool },
416 Range { start: ExprId, end: ExprId }, 417 Range { start: ExprId, end: ExprId },
417 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, 418 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
418 Path(Path), 419 Path(Box<Path>),
419 Lit(ExprId), 420 Lit(ExprId),
420 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, 421 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
421 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, 422 TupleStruct { path: Option<Box<Path>>, args: Vec<PatId>, ellipsis: Option<usize> },
422 Ref { pat: PatId, mutability: Mutability }, 423 Ref { pat: PatId, mutability: Mutability },
423 Box { inner: PatId }, 424 Box { inner: PatId },
424 ConstBlock(ExprId), 425 ConstBlock(ExprId),
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index 109d3552f..2c4bbe585 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -425,106 +425,142 @@ mod tests {
425 425
426 #[test] 426 #[test]
427 fn same_module() { 427 fn same_module() {
428 let code = r#" 428 check_found_path(
429 //- /main.rs 429 r#"
430 struct S; 430struct S;
431 $0 431$0
432 "#; 432 "#,
433 check_found_path(code, "S", "S", "crate::S", "self::S"); 433 "S",
434 "S",
435 "crate::S",
436 "self::S",
437 );
434 } 438 }
435 439
436 #[test] 440 #[test]
437 fn enum_variant() { 441 fn enum_variant() {
438 let code = r#" 442 check_found_path(
439 //- /main.rs 443 r#"
440 enum E { A } 444enum E { A }
441 $0 445$0
442 "#; 446 "#,
443 check_found_path(code, "E::A", "E::A", "E::A", "E::A"); 447 "E::A",
448 "E::A",
449 "E::A",
450 "E::A",
451 );
444 } 452 }
445 453
446 #[test] 454 #[test]
447 fn sub_module() { 455 fn sub_module() {
448 let code = r#" 456 check_found_path(
449 //- /main.rs 457 r#"
450 mod foo { 458mod foo {
451 pub struct S; 459 pub struct S;
452 } 460}
453 $0 461$0
454 "#; 462 "#,
455 check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); 463 "foo::S",
464 "foo::S",
465 "crate::foo::S",
466 "self::foo::S",
467 );
456 } 468 }
457 469
458 #[test] 470 #[test]
459 fn super_module() { 471 fn super_module() {
460 let code = r#" 472 check_found_path(
461 //- /main.rs 473 r#"
462 mod foo; 474//- /main.rs
463 //- /foo.rs 475mod foo;
464 mod bar; 476//- /foo.rs
465 struct S; 477mod bar;
466 //- /foo/bar.rs 478struct S;
467 $0 479//- /foo/bar.rs
468 "#; 480$0
469 check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); 481 "#,
482 "super::S",
483 "super::S",
484 "crate::foo::S",
485 "super::S",
486 );
470 } 487 }
471 488
472 #[test] 489 #[test]
473 fn self_module() { 490 fn self_module() {
474 let code = r#" 491 check_found_path(
475 //- /main.rs 492 r#"
476 mod foo; 493//- /main.rs
477 //- /foo.rs 494mod foo;
478 $0 495//- /foo.rs
479 "#; 496$0
480 check_found_path(code, "self", "self", "crate::foo", "self"); 497 "#,
498 "self",
499 "self",
500 "crate::foo",
501 "self",
502 );
481 } 503 }
482 504
483 #[test] 505 #[test]
484 fn crate_root() { 506 fn crate_root() {
485 let code = r#" 507 check_found_path(
486 //- /main.rs 508 r#"
487 mod foo; 509//- /main.rs
488 //- /foo.rs 510mod foo;
489 $0 511//- /foo.rs
490 "#; 512$0
491 check_found_path(code, "crate", "crate", "crate", "crate"); 513 "#,
514 "crate",
515 "crate",
516 "crate",
517 "crate",
518 );
492 } 519 }
493 520
494 #[test] 521 #[test]
495 fn same_crate() { 522 fn same_crate() {
496 let code = r#" 523 check_found_path(
497 //- /main.rs 524 r#"
498 mod foo; 525//- /main.rs
499 struct S; 526mod foo;
500 //- /foo.rs 527struct S;
501 $0 528//- /foo.rs
502 "#; 529$0
503 check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); 530 "#,
531 "crate::S",
532 "crate::S",
533 "crate::S",
534 "crate::S",
535 );
504 } 536 }
505 537
506 #[test] 538 #[test]
507 fn different_crate() { 539 fn different_crate() {
508 let code = r#" 540 check_found_path(
509 //- /main.rs crate:main deps:std 541 r#"
510 $0 542//- /main.rs crate:main deps:std
511 //- /std.rs crate:std 543$0
512 pub struct S; 544//- /std.rs crate:std
513 "#; 545pub struct S;
514 check_found_path(code, "std::S", "std::S", "std::S", "std::S"); 546 "#,
547 "std::S",
548 "std::S",
549 "std::S",
550 "std::S",
551 );
515 } 552 }
516 553
517 #[test] 554 #[test]
518 fn different_crate_renamed() { 555 fn different_crate_renamed() {
519 let code = r#"
520 //- /main.rs crate:main deps:std
521 extern crate std as std_renamed;
522 $0
523 //- /std.rs crate:std
524 pub struct S;
525 "#;
526 check_found_path( 556 check_found_path(
527 code, 557 r#"
558//- /main.rs crate:main deps:std
559extern crate std as std_renamed;
560$0
561//- /std.rs crate:std
562pub struct S;
563 "#,
528 "std_renamed::S", 564 "std_renamed::S",
529 "std_renamed::S", 565 "std_renamed::S",
530 "std_renamed::S", 566 "std_renamed::S",
@@ -537,41 +573,38 @@ mod tests {
537 cov_mark::check!(partially_imported); 573 cov_mark::check!(partially_imported);
538 // Tests that short paths are used even for external items, when parts of the path are 574 // Tests that short paths are used even for external items, when parts of the path are
539 // already in scope. 575 // already in scope.
540 let code = r#" 576 check_found_path(
541 //- /main.rs crate:main deps:syntax 577 r#"
578//- /main.rs crate:main deps:syntax
542 579
543 use syntax::ast; 580use syntax::ast;
544 $0 581$0
545 582
546 //- /lib.rs crate:syntax 583//- /lib.rs crate:syntax
547 pub mod ast { 584pub mod ast {
548 pub enum ModuleItem { 585 pub enum ModuleItem {
549 A, B, C, 586 A, B, C,
550 } 587 }
551 } 588}
552 "#; 589 "#,
553 check_found_path(
554 code,
555 "ast::ModuleItem", 590 "ast::ModuleItem",
556 "syntax::ast::ModuleItem", 591 "syntax::ast::ModuleItem",
557 "syntax::ast::ModuleItem", 592 "syntax::ast::ModuleItem",
558 "syntax::ast::ModuleItem", 593 "syntax::ast::ModuleItem",
559 ); 594 );
560 595
561 let code = r#"
562 //- /main.rs crate:main deps:syntax
563
564 $0
565
566 //- /lib.rs crate:syntax
567 pub mod ast {
568 pub enum ModuleItem {
569 A, B, C,
570 }
571 }
572 "#;
573 check_found_path( 596 check_found_path(
574 code, 597 r#"
598//- /main.rs crate:main deps:syntax
599$0
600
601//- /lib.rs crate:syntax
602pub mod ast {
603 pub enum ModuleItem {
604 A, B, C,
605 }
606}
607 "#,
575 "syntax::ast::ModuleItem", 608 "syntax::ast::ModuleItem",
576 "syntax::ast::ModuleItem", 609 "syntax::ast::ModuleItem",
577 "syntax::ast::ModuleItem", 610 "syntax::ast::ModuleItem",
@@ -581,68 +614,86 @@ mod tests {
581 614
582 #[test] 615 #[test]
583 fn same_crate_reexport() { 616 fn same_crate_reexport() {
584 let code = r#" 617 check_found_path(
585 //- /main.rs 618 r#"
586 mod bar { 619mod bar {
587 mod foo { pub(super) struct S; } 620 mod foo { pub(super) struct S; }
588 pub(crate) use foo::*; 621 pub(crate) use foo::*;
589 } 622}
590 $0 623$0
591 "#; 624 "#,
592 check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); 625 "bar::S",
626 "bar::S",
627 "crate::bar::S",
628 "self::bar::S",
629 );
593 } 630 }
594 631
595 #[test] 632 #[test]
596 fn same_crate_reexport_rename() { 633 fn same_crate_reexport_rename() {
597 let code = r#" 634 check_found_path(
598 //- /main.rs 635 r#"
599 mod bar { 636mod bar {
600 mod foo { pub(super) struct S; } 637 mod foo { pub(super) struct S; }
601 pub(crate) use foo::S as U; 638 pub(crate) use foo::S as U;
602 } 639}
603 $0 640$0
604 "#; 641 "#,
605 check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); 642 "bar::U",
643 "bar::U",
644 "crate::bar::U",
645 "self::bar::U",
646 );
606 } 647 }
607 648
608 #[test] 649 #[test]
609 fn different_crate_reexport() { 650 fn different_crate_reexport() {
610 let code = r#" 651 check_found_path(
611 //- /main.rs crate:main deps:std 652 r#"
612 $0 653//- /main.rs crate:main deps:std
613 //- /std.rs crate:std deps:core 654$0
614 pub use core::S; 655//- /std.rs crate:std deps:core
615 //- /core.rs crate:core 656pub use core::S;
616 pub struct S; 657//- /core.rs crate:core
617 "#; 658pub struct S;
618 check_found_path(code, "std::S", "std::S", "std::S", "std::S"); 659 "#,
660 "std::S",
661 "std::S",
662 "std::S",
663 "std::S",
664 );
619 } 665 }
620 666
621 #[test] 667 #[test]
622 fn prelude() { 668 fn prelude() {
623 let code = r#" 669 check_found_path(
624 //- /main.rs crate:main deps:std 670 r#"
625 $0 671//- /main.rs crate:main deps:std
626 //- /std.rs crate:std 672$0
627 pub mod prelude { pub struct S; } 673//- /std.rs crate:std
628 #[prelude_import] 674pub mod prelude { pub struct S; }
629 pub use prelude::*; 675#[prelude_import]
630 "#; 676pub use prelude::*;
631 check_found_path(code, "S", "S", "S", "S"); 677 "#,
678 "S",
679 "S",
680 "S",
681 "S",
682 );
632 } 683 }
633 684
634 #[test] 685 #[test]
635 fn enum_variant_from_prelude() { 686 fn enum_variant_from_prelude() {
636 let code = r#" 687 let code = r#"
637 //- /main.rs crate:main deps:std 688//- /main.rs crate:main deps:std
638 $0 689$0
639 //- /std.rs crate:std 690//- /std.rs crate:std
640 pub mod prelude { 691pub mod prelude {
641 pub enum Option<T> { Some(T), None } 692 pub enum Option<T> { Some(T), None }
642 pub use Option::*; 693 pub use Option::*;
643 } 694}
644 #[prelude_import] 695#[prelude_import]
645 pub use prelude::*; 696pub use prelude::*;
646 "#; 697 "#;
647 check_found_path(code, "None", "None", "None", "None"); 698 check_found_path(code, "None", "None", "None", "None");
648 check_found_path(code, "Some", "Some", "Some", "Some"); 699 check_found_path(code, "Some", "Some", "Some", "Some");
@@ -650,71 +701,85 @@ mod tests {
650 701
651 #[test] 702 #[test]
652 fn shortest_path() { 703 fn shortest_path() {
653 let code = r#" 704 check_found_path(
654 //- /main.rs 705 r#"
655 pub mod foo; 706//- /main.rs
656 pub mod baz; 707pub mod foo;
657 struct S; 708pub mod baz;
658 $0 709struct S;
659 //- /foo.rs 710$0
660 pub mod bar { pub struct S; } 711//- /foo.rs
661 //- /baz.rs 712pub mod bar { pub struct S; }
662 pub use crate::foo::bar::S; 713//- /baz.rs
663 "#; 714pub use crate::foo::bar::S;
664 check_found_path(code, "baz::S", "baz::S", "crate::baz::S", "self::baz::S"); 715 "#,
716 "baz::S",
717 "baz::S",
718 "crate::baz::S",
719 "self::baz::S",
720 );
665 } 721 }
666 722
667 #[test] 723 #[test]
668 fn discount_private_imports() { 724 fn discount_private_imports() {
669 let code = r#" 725 check_found_path(
670 //- /main.rs 726 r#"
671 mod foo; 727//- /main.rs
672 pub mod bar { pub struct S; } 728mod foo;
673 use bar::S; 729pub mod bar { pub struct S; }
674 //- /foo.rs 730use bar::S;
675 $0 731//- /foo.rs
676 "#; 732$0
677 // crate::S would be shorter, but using private imports seems wrong 733 "#,
678 check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); 734 // crate::S would be shorter, but using private imports seems wrong
735 "crate::bar::S",
736 "crate::bar::S",
737 "crate::bar::S",
738 "crate::bar::S",
739 );
679 } 740 }
680 741
681 #[test] 742 #[test]
682 fn import_cycle() { 743 fn import_cycle() {
683 let code = r#" 744 check_found_path(
684 //- /main.rs 745 r#"
685 pub mod foo; 746//- /main.rs
686 pub mod bar; 747pub mod foo;
687 pub mod baz; 748pub mod bar;
688 //- /bar.rs 749pub mod baz;
689 $0 750//- /bar.rs
690 //- /foo.rs 751$0
691 pub use super::baz; 752//- /foo.rs
692 pub struct S; 753pub use super::baz;
693 //- /baz.rs 754pub struct S;
694 pub use super::foo; 755//- /baz.rs
695 "#; 756pub use super::foo;
696 check_found_path(code, "crate::foo::S", "crate::foo::S", "crate::foo::S", "crate::foo::S"); 757 "#,
758 "crate::foo::S",
759 "crate::foo::S",
760 "crate::foo::S",
761 "crate::foo::S",
762 );
697 } 763 }
698 764
699 #[test] 765 #[test]
700 fn prefer_std_paths_over_alloc() { 766 fn prefer_std_paths_over_alloc() {
701 cov_mark::check!(prefer_std_paths); 767 cov_mark::check!(prefer_std_paths);
702 let code = r#" 768 check_found_path(
703 //- /main.rs crate:main deps:alloc,std 769 r#"
704 $0 770//- /main.rs crate:main deps:alloc,std
771$0
705 772
706 //- /std.rs crate:std deps:alloc 773//- /std.rs crate:std deps:alloc
707 pub mod sync { 774pub mod sync {
708 pub use alloc::sync::Arc; 775 pub use alloc::sync::Arc;
709 } 776}
710 777
711 //- /zzz.rs crate:alloc 778//- /zzz.rs crate:alloc
712 pub mod sync { 779pub mod sync {
713 pub struct Arc; 780 pub struct Arc;
714 } 781}
715 "#; 782 "#,
716 check_found_path(
717 code,
718 "std::sync::Arc", 783 "std::sync::Arc",
719 "std::sync::Arc", 784 "std::sync::Arc",
720 "std::sync::Arc", 785 "std::sync::Arc",
@@ -725,26 +790,25 @@ mod tests {
725 #[test] 790 #[test]
726 fn prefer_core_paths_over_std() { 791 fn prefer_core_paths_over_std() {
727 cov_mark::check!(prefer_no_std_paths); 792 cov_mark::check!(prefer_no_std_paths);
728 let code = r#" 793 check_found_path(
729 //- /main.rs crate:main deps:core,std 794 r#"
730 #![no_std] 795//- /main.rs crate:main deps:core,std
796#![no_std]
731 797
732 $0 798$0
733 799
734 //- /std.rs crate:std deps:core 800//- /std.rs crate:std deps:core
735 801
736 pub mod fmt { 802pub mod fmt {
737 pub use core::fmt::Error; 803 pub use core::fmt::Error;
738 } 804}
739 805
740 //- /zzz.rs crate:core 806//- /zzz.rs crate:core
741 807
742 pub mod fmt { 808pub mod fmt {
743 pub struct Error; 809 pub struct Error;
744 } 810}
745 "#; 811 "#,
746 check_found_path(
747 code,
748 "core::fmt::Error", 812 "core::fmt::Error",
749 "core::fmt::Error", 813 "core::fmt::Error",
750 "core::fmt::Error", 814 "core::fmt::Error",
@@ -754,26 +818,25 @@ mod tests {
754 818
755 #[test] 819 #[test]
756 fn prefer_alloc_paths_over_std() { 820 fn prefer_alloc_paths_over_std() {
757 let code = r#" 821 check_found_path(
758 //- /main.rs crate:main deps:alloc,std 822 r#"
759 #![no_std] 823//- /main.rs crate:main deps:alloc,std
824#![no_std]
760 825
761 $0 826$0
762 827
763 //- /std.rs crate:std deps:alloc 828//- /std.rs crate:std deps:alloc
764 829
765 pub mod sync { 830pub mod sync {
766 pub use alloc::sync::Arc; 831 pub use alloc::sync::Arc;
767 } 832}
768 833
769 //- /zzz.rs crate:alloc 834//- /zzz.rs crate:alloc
770 835
771 pub mod sync { 836pub mod sync {
772 pub struct Arc; 837 pub struct Arc;
773 } 838}
774 "#; 839 "#,
775 check_found_path(
776 code,
777 "alloc::sync::Arc", 840 "alloc::sync::Arc",
778 "alloc::sync::Arc", 841 "alloc::sync::Arc",
779 "alloc::sync::Arc", 842 "alloc::sync::Arc",
@@ -783,20 +846,19 @@ mod tests {
783 846
784 #[test] 847 #[test]
785 fn prefer_shorter_paths_if_not_alloc() { 848 fn prefer_shorter_paths_if_not_alloc() {
786 let code = r#" 849 check_found_path(
787 //- /main.rs crate:main deps:megaalloc,std 850 r#"
788 $0 851//- /main.rs crate:main deps:megaalloc,std
852$0
789 853
790 //- /std.rs crate:std deps:megaalloc 854//- /std.rs crate:std deps:megaalloc
791 pub mod sync { 855pub mod sync {
792 pub use megaalloc::sync::Arc; 856 pub use megaalloc::sync::Arc;
793 } 857}
794 858
795 //- /zzz.rs crate:megaalloc 859//- /zzz.rs crate:megaalloc
796 pub struct Arc; 860pub struct Arc;
797 "#; 861 "#,
798 check_found_path(
799 code,
800 "megaalloc::Arc", 862 "megaalloc::Arc",
801 "megaalloc::Arc", 863 "megaalloc::Arc",
802 "megaalloc::Arc", 864 "megaalloc::Arc",
@@ -807,12 +869,11 @@ mod tests {
807 #[test] 869 #[test]
808 fn builtins_are_in_scope() { 870 fn builtins_are_in_scope() {
809 let code = r#" 871 let code = r#"
810 //- /main.rs 872$0
811 $0
812 873
813 pub mod primitive { 874pub mod primitive {
814 pub use u8; 875 pub use u8;
815 } 876}
816 "#; 877 "#;
817 check_found_path(code, "u8", "u8", "u8", "u8"); 878 check_found_path(code, "u8", "u8", "u8", "u8");
818 check_found_path(code, "u16", "u16", "u16", "u16"); 879 check_found_path(code, "u16", "u16", "u16", "u16");
@@ -822,10 +883,10 @@ mod tests {
822 fn inner_items() { 883 fn inner_items() {
823 check_found_path( 884 check_found_path(
824 r#" 885 r#"
825 fn main() { 886fn main() {
826 struct Inner {} 887 struct Inner {}
827 $0 888 $0
828 } 889}
829 "#, 890 "#,
830 "Inner", 891 "Inner",
831 "Inner", 892 "Inner",
@@ -838,12 +899,12 @@ mod tests {
838 fn inner_items_from_outer_scope() { 899 fn inner_items_from_outer_scope() {
839 check_found_path( 900 check_found_path(
840 r#" 901 r#"
841 fn main() { 902fn main() {
842 struct Struct {} 903 struct Struct {}
843 { 904 {
844 $0 905 $0
845 } 906 }
846 } 907}
847 "#, 908 "#,
848 "Struct", 909 "Struct",
849 "Struct", 910 "Struct",
@@ -857,14 +918,14 @@ mod tests {
857 cov_mark::check!(prefixed_in_block_expression); 918 cov_mark::check!(prefixed_in_block_expression);
858 check_found_path( 919 check_found_path(
859 r#" 920 r#"
860 fn main() { 921fn main() {
861 mod module { 922 mod module {
862 struct Struct {} 923 struct Struct {}
863 } 924 }
864 { 925 {
865 $0 926 $0
866 } 927 }
867 } 928}
868 "#, 929 "#,
869 "module::Struct", 930 "module::Struct",
870 "module::Struct", 931 "module::Struct",
@@ -877,14 +938,14 @@ mod tests {
877 fn outer_items_with_inner_items_present() { 938 fn outer_items_with_inner_items_present() {