aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock48
-rw-r--r--crates/base_db/src/fixture.rs2
-rw-r--r--crates/hir_ty/src/chalk_db.rs5
-rw-r--r--crates/hir_ty/src/test_db.rs10
-rw-r--r--crates/hir_ty/src/tests.rs235
-rw-r--r--crates/hir_ty/src/tests/coercion.rs673
-rw-r--r--crates/hir_ty/src/tests/display_source_code.rs10
-rw-r--r--crates/hir_ty/src/tests/macros.rs29
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs264
-rw-r--r--crates/hir_ty/src/tests/patterns.rs4
-rw-r--r--crates/hir_ty/src/tests/regression.rs11
-rw-r--r--crates/hir_ty/src/tests/simple.rs18
-rw-r--r--crates/hir_ty/src/tests/traits.rs244
-rw-r--r--crates/ide/src/goto_implementation.rs7
-rw-r--r--crates/ide/src/hover.rs2
-rw-r--r--crates/ide/src/rename.rs46
-rw-r--r--crates/ide/src/typing.rs36
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs58
-rw-r--r--crates/ide_completion/src/completions/keyword.rs28
-rw-r--r--crates/ide_completion/src/completions/pattern.rs395
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs76
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs147
-rw-r--r--crates/ide_completion/src/context.rs72
-rw-r--r--crates/ide_completion/src/patterns.rs9
-rw-r--r--crates/ide_completion/src/render.rs75
-rw-r--r--crates/ide_completion/src/tests.rs15
-rw-r--r--crates/ide_completion/src/tests/items.rs32
-rw-r--r--crates/ide_completion/src/tests/pattern.rs348
-rw-r--r--crates/ide_completion/src/tests/type_pos.rs177
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs109
-rw-r--r--crates/project_model/src/sysroot.rs11
-rw-r--r--crates/test_utils/src/lib.rs50
-rw-r--r--docs/dev/debugging.md5
33 files changed, 1355 insertions, 1896 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5066d5f0f..238c21f52 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -37,9 +37,9 @@ dependencies = [
37 37
38[[package]] 38[[package]]
39name = "anyhow" 39name = "anyhow"
40version = "1.0.40" 40version = "1.0.41"
41source = "registry+https://github.com/rust-lang/crates.io-index" 41source = "registry+https://github.com/rust-lang/crates.io-index"
42checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" 42checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
43 43
44[[package]] 44[[package]]
45name = "anymap" 45name = "anymap"
@@ -49,9 +49,9 @@ checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
49 49
50[[package]] 50[[package]]
51name = "arrayvec" 51name = "arrayvec"
52version = "0.7.0" 52version = "0.7.1"
53source = "registry+https://github.com/rust-lang/crates.io-index" 53source = "registry+https://github.com/rust-lang/crates.io-index"
54checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7" 54checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
55 55
56[[package]] 56[[package]]
57name = "atty" 57name = "atty"
@@ -333,9 +333,9 @@ dependencies = [
333 333
334[[package]] 334[[package]]
335name = "env_logger" 335name = "env_logger"
336version = "0.8.3" 336version = "0.8.4"
337source = "registry+https://github.com/rust-lang/crates.io-index" 337source = "registry+https://github.com/rust-lang/crates.io-index"
338checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" 338checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
339dependencies = [ 339dependencies = [
340 "log", 340 "log",
341] 341]
@@ -421,9 +421,9 @@ dependencies = [
421 421
422[[package]] 422[[package]]
423name = "fst" 423name = "fst"
424version = "0.4.6" 424version = "0.4.7"
425source = "registry+https://github.com/rust-lang/crates.io-index" 425source = "registry+https://github.com/rust-lang/crates.io-index"
426checksum = "e398fae362f4124bbe630d99519fb2d68a03e2e3a23b441028cdcdc4f4895687" 426checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a"
427 427
428[[package]] 428[[package]]
429name = "gimli" 429name = "gimli"
@@ -741,9 +741,9 @@ dependencies = [
741 741
742[[package]] 742[[package]]
743name = "itertools" 743name = "itertools"
744version = "0.10.0" 744version = "0.10.1"
745source = "registry+https://github.com/rust-lang/crates.io-index" 745source = "registry+https://github.com/rust-lang/crates.io-index"
746checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" 746checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
747dependencies = [ 747dependencies = [
748 "either", 748 "either",
749] 749]
@@ -788,9 +788,9 @@ dependencies = [
788 788
789[[package]] 789[[package]]
790name = "libmimalloc-sys" 790name = "libmimalloc-sys"
791version = "0.1.21" 791version = "0.1.22"
792source = "registry+https://github.com/rust-lang/crates.io-index" 792source = "registry+https://github.com/rust-lang/crates.io-index"
793checksum = "2396cf99d2f58611cd69f0efeee4af3d2e2c7b61bed433515029163aa567e65c" 793checksum = "1d1b8479c593dba88c2741fc50b92e13dbabbbe0bd504d979f244ccc1a5b1c01"
794dependencies = [ 794dependencies = [
795 "cc", 795 "cc",
796] 796]
@@ -827,9 +827,9 @@ dependencies = [
827 827
828[[package]] 828[[package]]
829name = "lsp-types" 829name = "lsp-types"
830version = "0.89.1" 830version = "0.89.2"
831source = "registry+https://github.com/rust-lang/crates.io-index" 831source = "registry+https://github.com/rust-lang/crates.io-index"
832checksum = "48b8a871b0a450bcec0e26d74a59583c8173cb9fb7d7f98889e18abb84838e0f" 832checksum = "852e0dedfd52cc32325598b2631e0eba31b7b708959676a9f837042f276b09a2"
833dependencies = [ 833dependencies = [
834 "bitflags", 834 "bitflags",
835 "serde", 835 "serde",
@@ -895,9 +895,9 @@ dependencies = [
895 895
896[[package]] 896[[package]]
897name = "mimalloc" 897name = "mimalloc"
898version = "0.1.25" 898version = "0.1.26"
899source = "registry+https://github.com/rust-lang/crates.io-index" 899source = "registry+https://github.com/rust-lang/crates.io-index"
900checksum = "1e7c6b11afd1e5e689ac96b6d18b1fc763398fe3d7eed99e8773426bc2033dfb" 900checksum = "fb74897ce508e6c49156fd1476fc5922cbc6e75183c65e399c765a09122e5130"
901dependencies = [ 901dependencies = [
902 "libmimalloc-sys", 902 "libmimalloc-sys",
903] 903]
@@ -978,9 +978,9 @@ checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170"
978 978
979[[package]] 979[[package]]
980name = "once_cell" 980name = "once_cell"
981version = "1.7.2" 981version = "1.8.0"
982source = "registry+https://github.com/rust-lang/crates.io-index" 982source = "registry+https://github.com/rust-lang/crates.io-index"
983checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" 983checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
984 984
985[[package]] 985[[package]]
986name = "oorandom" 986name = "oorandom"
@@ -1204,9 +1204,9 @@ dependencies = [
1204 1204
1205[[package]] 1205[[package]]
1206name = "pulldown-cmark-to-cmark" 1206name = "pulldown-cmark-to-cmark"
1207version = "6.0.0" 1207version = "6.0.1"
1208source = "registry+https://github.com/rust-lang/crates.io-index" 1208source = "registry+https://github.com/rust-lang/crates.io-index"
1209checksum = "e8f2b9878102358ec65434fdd1a9a161f8648bb2f531acc9260e4d094c96de23" 1209checksum = "6a95f396125c68d833fc40cca35532c49ab7394382f7b0e46144a4761896ce80"
1210dependencies = [ 1210dependencies = [
1211 "pulldown-cmark", 1211 "pulldown-cmark",
1212] 1212]
@@ -1909,18 +1909,18 @@ checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3"
1909 1909
1910[[package]] 1910[[package]]
1911name = "xflags" 1911name = "xflags"
1912version = "0.2.1" 1912version = "0.2.2"
1913source = "registry+https://github.com/rust-lang/crates.io-index" 1913source = "registry+https://github.com/rust-lang/crates.io-index"
1914checksum = "59ad6ce6a0b7224130015b4ebac796478ac04e0079f5d222a690efea06a9208a" 1914checksum = "a25b85ca0fcf2d003f2b0cfdce73897c54ec3d793dfe008a64de5040209363c9"
1915dependencies = [ 1915dependencies = [
1916 "xflags-macros", 1916 "xflags-macros",
1917] 1917]
1918 1918
1919[[package]] 1919[[package]]
1920name = "xflags-macros" 1920name = "xflags-macros"
1921version = "0.2.1" 1921version = "0.2.2"
1922source = "registry+https://github.com/rust-lang/crates.io-index" 1922source = "registry+https://github.com/rust-lang/crates.io-index"
1923checksum = "c8037d3ca14996158b03c0fa905d0834906ef0fc7044df72c1f5ff690e5e62c9" 1923checksum = "00055208d8839f11689012fecb42bbc024e25bf3af91b3b9879739d3cda65bf0"
1924dependencies = [ 1924dependencies = [
1925 "proc-macro2", 1925 "proc-macro2",
1926] 1926]
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index d0c946d83..6ce377710 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -106,7 +106,7 @@ impl ChangeFixture {
106 let (range_or_offset, text) = extract_range_or_offset(&entry.text); 106 let (range_or_offset, text) = extract_range_or_offset(&entry.text);
107 assert!(file_position.is_none()); 107 assert!(file_position.is_none());
108 file_position = Some((file_id, range_or_offset)); 108 file_position = Some((file_id, range_or_offset));
109 text.to_string() 109 text
110 } 110 }
111 } else { 111 } else {
112 entry.text.clone() 112 entry.text.clone()
diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs
index a4c09c742..a55b99de0 100644
--- a/crates/hir_ty/src/chalk_db.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -2,6 +2,7 @@
2//! about the code that Chalk needs. 2//! about the code that Chalk needs.
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use cov_mark::hit;
5use log::debug; 6use log::debug;
6 7
7use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds}; 8use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
@@ -106,7 +107,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
106 }; 107 };
107 108
108 fn local_impls(db: &dyn HirDatabase, module: ModuleId) -> Option<Arc<TraitImpls>> { 109 fn local_impls(db: &dyn HirDatabase, module: ModuleId) -> Option<Arc<TraitImpls>> {
109 db.trait_impls_in_block(module.containing_block()?) 110 let block = module.containing_block()?;
111 hit!(block_local_impls);
112 db.trait_impls_in_block(block)
110 } 113 }
111 114
112 // Note: Since we're using impls_for_trait, only impls where the trait 115 // Note: Since we're using impls_for_trait, only impls where the trait
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs
index 4640ea821..b99a03492 100644
--- a/crates/hir_ty/src/test_db.rs
+++ b/crates/hir_ty/src/test_db.rs
@@ -86,16 +86,20 @@ impl FileLoader for TestDB {
86} 86}
87 87
88impl TestDB { 88impl TestDB {
89 pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { 89 pub(crate) fn module_for_file_opt(&self, file_id: FileId) -> Option<ModuleId> {
90 for &krate in self.relevant_crates(file_id).iter() { 90 for &krate in self.relevant_crates(file_id).iter() {
91 let crate_def_map = self.crate_def_map(krate); 91 let crate_def_map = self.crate_def_map(krate);
92 for (local_id, data) in crate_def_map.modules() { 92 for (local_id, data) in crate_def_map.modules() {
93 if data.origin.file_id() == Some(file_id) { 93 if data.origin.file_id() == Some(file_id) {
94 return crate_def_map.module_id(local_id); 94 return Some(crate_def_map.module_id(local_id));
95 } 95 }
96 } 96 }
97 } 97 }
98 panic!("Can't find module for file") 98 None
99 }
100
101 pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId {
102 self.module_for_file_opt(file_id).unwrap()
99 } 103 }
100 104
101 pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { 105 pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> {
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index b873585c4..0651f34ae 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -11,23 +11,21 @@ mod incremental;
11 11
12use std::{collections::HashMap, env, sync::Arc}; 12use std::{collections::HashMap, env, sync::Arc};
13 13
14use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; 14use base_db::{fixture::WithFixture, FileRange, SourceDatabaseExt};
15use expect_test::Expect; 15use expect_test::Expect;
16use hir_def::{ 16use hir_def::{
17 body::{Body, BodySourceMap, SyntheticSyntax}, 17 body::{Body, BodySourceMap, SyntheticSyntax},
18 child_by_source::ChildBySource,
19 db::DefDatabase, 18 db::DefDatabase,
19 expr::{ExprId, PatId},
20 item_scope::ItemScope, 20 item_scope::ItemScope,
21 keys,
22 nameres::DefMap, 21 nameres::DefMap,
23 src::HasSource, 22 src::HasSource,
24 AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, 23 AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId,
25}; 24};
26use hir_expand::{db::AstDatabase, InFile}; 25use hir_expand::{db::AstDatabase, InFile};
27use once_cell::race::OnceBool; 26use once_cell::race::OnceBool;
28use stdx::format_to; 27use stdx::format_to;
29use syntax::{ 28use syntax::{
30 algo,
31 ast::{self, AstNode, NameOwner}, 29 ast::{self, AstNode, NameOwner},
32 SyntaxNode, 30 SyntaxNode,
33}; 31};
@@ -59,51 +57,55 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
59} 57}
60 58
61fn check_types(ra_fixture: &str) { 59fn check_types(ra_fixture: &str) {
62 check_types_impl(ra_fixture, false) 60 check_impl(ra_fixture, false, true, false)
63} 61}
64 62
65fn check_types_source_code(ra_fixture: &str) { 63fn check_types_source_code(ra_fixture: &str) {
66 check_types_impl(ra_fixture, true) 64 check_impl(ra_fixture, false, true, true)
67}
68
69fn check_types_impl(ra_fixture: &str, display_source: bool) {
70 let _tracing = setup_tracing();
71 let db = TestDB::with_files(ra_fixture);
72 let mut checked_one = false;
73 for (file_id, annotations) in db.extract_annotations() {
74 for (range, expected) in annotations {
75 let ty = type_at_range(&db, FileRange { file_id, range });
76 let actual = if display_source {
77 let module = db.module_for_file(file_id);
78 ty.display_source_code(&db, module).unwrap()
79 } else {
80 ty.display_test(&db).to_string()
81 };
82 assert_eq!(expected, actual);
83 checked_one = true;
84 }
85 }
86
87 assert!(checked_one, "no `//^` annotations found");
88} 65}
89 66
90fn check_no_mismatches(ra_fixture: &str) { 67fn check_no_mismatches(ra_fixture: &str) {
91 check_mismatches_impl(ra_fixture, true) 68 check_impl(ra_fixture, true, false, false)
92} 69}
93 70
94#[allow(unused)] 71fn check(ra_fixture: &str) {
95fn check_mismatches(ra_fixture: &str) { 72 check_impl(ra_fixture, false, false, false)
96 check_mismatches_impl(ra_fixture, false)
97} 73}
98 74
99fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { 75fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) {
100 let _tracing = setup_tracing(); 76 let _tracing = setup_tracing();
101 let (db, file_id) = TestDB::with_single_file(ra_fixture); 77 let (db, files) = TestDB::with_many_files(ra_fixture);
102 let module = db.module_for_file(file_id); 78
103 let def_map = module.def_map(&db); 79 let mut had_annotations = false;
80 let mut mismatches = HashMap::new();
81 let mut types = HashMap::new();
82 for (file_id, annotations) in db.extract_annotations() {
83 for (range, expected) in annotations {
84 let file_range = FileRange { file_id, range };
85 if only_types {
86 types.insert(file_range, expected);
87 } else if expected.starts_with("type: ") {
88 types.insert(file_range, expected.trim_start_matches("type: ").to_string());
89 } else if expected.starts_with("expected") {
90 mismatches.insert(file_range, expected);
91 } else {
92 panic!("unexpected annotation: {}", expected);
93 }
94 had_annotations = true;
95 }
96 }
97 assert!(had_annotations || allow_none, "no `//^` annotations found");
104 98
105 let mut defs: Vec<DefWithBodyId> = Vec::new(); 99 let mut defs: Vec<DefWithBodyId> = Vec::new();
106 visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it)); 100 for file_id in files {
101 let module = db.module_for_file_opt(file_id);
102 let module = match module {
103 Some(m) => m,
104 None => continue,
105 };
106 let def_map = module.def_map(&db);
107 visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it));
108 }
107 defs.sort_by_key(|def| match def { 109 defs.sort_by_key(|def| match def {
108 DefWithBodyId::FunctionId(it) => { 110 DefWithBodyId::FunctionId(it) => {
109 let loc = it.lookup(&db); 111 let loc = it.lookup(&db);
@@ -118,37 +120,59 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) {
118 loc.source(&db).value.syntax().text_range().start() 120 loc.source(&db).value.syntax().text_range().start()
119 } 121 }
120 }); 122 });
121 let mut mismatches = HashMap::new(); 123 let mut unexpected_type_mismatches = String::new();
122 let mut push_mismatch = |src_ptr: InFile<SyntaxNode>, mismatch: TypeMismatch| {
123 let range = src_ptr.value.text_range();
124 if src_ptr.file_id.call_node(&db).is_some() {
125 panic!("type mismatch in macro expansion");
126 }
127 let file_range = FileRange { file_id: src_ptr.file_id.original_file(&db), range };
128 let actual = format!(
129 "expected {}, got {}",
130 mismatch.expected.display_test(&db),
131 mismatch.actual.display_test(&db)
132 );
133 mismatches.insert(file_range, actual);
134 };
135 for def in defs { 124 for def in defs {
136 let (_body, body_source_map) = db.body_with_source_map(def); 125 let (_body, body_source_map) = db.body_with_source_map(def);
137 let inference_result = db.infer(def); 126 let inference_result = db.infer(def);
127
128 for (pat, ty) in inference_result.type_of_pat.iter() {
129 let node = match pat_node(&body_source_map, pat, &db) {
130 Some(value) => value,
131 None => continue,
132 };
133 let range = node.as_ref().original_file_range(&db);
134 if let Some(expected) = types.remove(&range) {
135 let actual = if display_source {
136 ty.display_source_code(&db, def.module(&db)).unwrap()
137 } else {
138 ty.display_test(&db).to_string()
139 };
140 assert_eq!(actual, expected);
141 }
142 }
143
144 for (expr, ty) in inference_result.type_of_expr.iter() {
145 let node = match expr_node(&body_source_map, expr, &db) {
146 Some(value) => value,
147 None => continue,
148 };
149 let range = node.as_ref().original_file_range(&db);
150 if let Some(expected) = types.remove(&range) {
151 let actual = if display_source {
152 ty.display_source_code(&db, def.module(&db)).unwrap()
153 } else {
154 ty.display_test(&db).to_string()
155 };
156 assert_eq!(actual, expected);
157 }
158 }
159
138 for (pat, mismatch) in inference_result.pat_type_mismatches() { 160 for (pat, mismatch) in inference_result.pat_type_mismatches() {
139 let syntax_ptr = match body_source_map.pat_syntax(pat) { 161 let node = match pat_node(&body_source_map, pat, &db) {
140 Ok(sp) => { 162 Some(value) => value,
141 let root = db.parse_or_expand(sp.file_id).unwrap(); 163 None => continue,
142 sp.map(|ptr| {
143 ptr.either(
144 |it| it.to_node(&root).syntax().clone(),
145 |it| it.to_node(&root).syntax().clone(),
146 )
147 })
148 }
149 Err(SyntheticSyntax) => continue,
150 }; 164 };
151 push_mismatch(syntax_ptr, mismatch.clone()); 165 let range = node.as_ref().original_file_range(&db);
166 let actual = format!(
167 "expected {}, got {}",
168 mismatch.expected.display_test(&db),
169 mismatch.actual.display_test(&db)
170 );
171 if let Some(annotation) = mismatches.remove(&range) {
172 assert_eq!(actual, annotation);
173 } else {
174 format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual);
175 }
152 } 176 }
153 for (expr, mismatch) in inference_result.expr_type_mismatches() { 177 for (expr, mismatch) in inference_result.expr_type_mismatches() {
154 let node = match body_source_map.expr_syntax(expr) { 178 let node = match body_source_map.expr_syntax(expr) {
@@ -158,45 +182,70 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) {
158 } 182 }
159 Err(SyntheticSyntax) => continue, 183 Err(SyntheticSyntax) => continue,
160 }; 184 };
161 push_mismatch(node, mismatch.clone()); 185 let range = node.as_ref().original_file_range(&db);
162 } 186 let actual = format!(
163 } 187 "expected {}, got {}",
164 let mut checked_one = false; 188 mismatch.expected.display_test(&db),
165 for (file_id, annotations) in db.extract_annotations() { 189 mismatch.actual.display_test(&db)
166 for (range, expected) in annotations { 190 );
167 let file_range = FileRange { file_id, range }; 191 if let Some(annotation) = mismatches.remove(&range) {
168 if let Some(mismatch) = mismatches.remove(&file_range) { 192 assert_eq!(actual, annotation);
169 assert_eq!(mismatch, expected);
170 } else { 193 } else {
171 assert!(false, "Expected mismatch not encountered: {}\n", expected); 194 format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual);
172 } 195 }
173 checked_one = true;
174 } 196 }
175 } 197 }
198
176 let mut buf = String::new(); 199 let mut buf = String::new();
177 for (range, mismatch) in mismatches { 200 if !unexpected_type_mismatches.is_empty() {
178 format_to!(buf, "{:?}: {}\n", range.range, mismatch,); 201 format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches);
202 }
203 if !mismatches.is_empty() {
204 format_to!(buf, "Unchecked mismatch annotations:\n");
205 for m in mismatches {
206 format_to!(buf, "{:?}: {}\n", m.0.range, m.1);
207 }
179 } 208 }
180 assert!(buf.is_empty(), "Unexpected type mismatches:\n{}", buf); 209 if !types.is_empty() {
210 format_to!(buf, "Unchecked type annotations:\n");
211 for t in types {
212 format_to!(buf, "{:?}: type {}\n", t.0.range, t.1);
213 }
214 }
215 assert!(buf.is_empty(), "{}", buf);
216}
181 217
182 assert!(checked_one || allow_none, "no `//^` annotations found"); 218fn expr_node(
219 body_source_map: &BodySourceMap,
220 expr: ExprId,
221 db: &TestDB,
222) -> Option<InFile<SyntaxNode>> {
223 Some(match body_source_map.expr_syntax(expr) {
224 Ok(sp) => {
225 let root = db.parse_or_expand(sp.file_id).unwrap();
226 sp.map(|ptr| ptr.to_node(&root).syntax().clone())
227 }
228 Err(SyntheticSyntax) => return None,
229 })
183} 230}
184 231
185fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { 232fn pat_node(
186 let file = db.parse(pos.file_id).ok().unwrap(); 233 body_source_map: &BodySourceMap,
187 let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap(); 234 pat: PatId,
188 let fn_def = expr.syntax().ancestors().find_map(ast::Fn::cast).unwrap(); 235 db: &TestDB,
189 let module = db.module_for_file(pos.file_id); 236) -> Option<InFile<SyntaxNode>> {
190 let func = *module.child_by_source(db)[keys::FUNCTION] 237 Some(match body_source_map.pat_syntax(pat) {
191 .get(&InFile::new(pos.file_id.into(), fn_def)) 238 Ok(sp) => {
192 .unwrap(); 239 let root = db.parse_or_expand(sp.file_id).unwrap();
193 240 sp.map(|ptr| {
194 let (_body, source_map) = db.body_with_source_map(func.into()); 241 ptr.either(
195 if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { 242 |it| it.to_node(&root).syntax().clone(),
196 let infer = db.infer(func.into()); 243 |it| it.to_node(&root).syntax().clone(),
197 return infer[expr_id].clone(); 244 )
198 } 245 })
199 panic!("Can't find expression") 246 }
247 Err(SyntheticSyntax) => return None,
248 })
200} 249}
201 250
202fn infer(ra_fixture: &str) -> String { 251fn infer(ra_fixture: &str) -> String {
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs
index 713b74165..87089f09d 100644
--- a/crates/hir_ty/src/tests/coercion.rs
+++ b/crates/hir_ty/src/tests/coercion.rs
@@ -1,27 +1,22 @@
1use expect_test::expect; 1use super::{check, check_no_mismatches, check_types};
2
3use super::{check_infer, check_infer_with_mismatches, check_no_mismatches, check_types};
4 2
5#[test] 3#[test]
6fn infer_block_expr_type_mismatch() { 4fn block_expr_type_mismatch() {
7 check_infer( 5 // FIXME fix double type mismatch
6 check(
8 r" 7 r"
9 fn test() { 8fn test() {
10 let a: i32 = { 1i64 }; 9 let a: i32 = { 1i64 };
11 } 10 // ^^^^^^^^ expected i32, got i64
11 // ^^^^ expected i32, got i64
12}
12 ", 13 ",
13 expect![[r"
14 10..40 '{ ...4 }; }': ()
15 20..21 'a': i32
16 29..37 '{ 1i64 }': i64
17 31..35 '1i64': i64
18 "]],
19 ); 14 );
20} 15}
21 16
22#[test] 17#[test]
23fn coerce_places() { 18fn coerce_places() {
24 check_infer( 19 check_no_mismatches(
25 r#" 20 r#"
26//- minicore: coerce_unsized 21//- minicore: coerce_unsized
27struct S<T> { a: T } 22struct S<T> { a: T }
@@ -46,81 +41,25 @@ fn test2() {
46 let g: (&[_], &[_]) = (arr, arr); 41 let g: (&[_], &[_]) = (arr, arr);
47} 42}
48"#, 43"#,
49 expect![[r#"
50 30..31 '_': &[T]
51 44..55 '{ loop {} }': T
52 46..53 'loop {}': !
53 51..53 '{}': ()
54 64..65 '_': S<&[T]>
55 81..92 '{ loop {} }': T
56 83..90 'loop {}': !
57 88..90 '{}': ()
58 121..132 '{ loop {} }': *mut [T; 2]
59 123..130 'loop {}': !
60 128..130 '{}': ()
61 159..172 '{ gen() }': *mut [U]
62 165..168 'gen': fn gen<U>() -> *mut [U; 2]
63 165..170 'gen()': *mut [U; 2]
64 185..419 '{ ...rr); }': ()
65 195..198 'arr': &[u8; 1]
66 211..215 '&[1]': &[u8; 1]
67 212..215 '[1]': [u8; 1]
68 213..214 '1': u8
69 226..227 'a': &[u8]
70 236..239 'arr': &[u8; 1]
71 249..250 'b': u8
72 253..254 'f': fn f<u8>(&[u8]) -> u8
73 253..259 'f(arr)': u8
74 255..258 'arr': &[u8; 1]
75 269..270 'c': &[u8]
76 279..286 '{ arr }': &[u8]
77 281..284 'arr': &[u8; 1]
78 296..297 'd': u8
79 300..301 'g': fn g<u8>(S<&[u8]>) -> u8
80 300..315 'g(S { a: arr })': u8
81 302..314 'S { a: arr }': S<&[u8]>
82 309..312 'arr': &[u8; 1]
83 325..326 'e': [&[u8]; 1]
84 340..345 '[arr]': [&[u8]; 1]
85 341..344 'arr': &[u8; 1]
86 355..356 'f': [&[u8]; 2]
87 370..378 '[arr; 2]': [&[u8]; 2]
88 371..374 'arr': &[u8; 1]
89 376..377 '2': usize
90 388..389 'g': (&[u8], &[u8])
91 406..416 '(arr, arr)': (&[u8], &[u8])
92 407..410 'arr': &[u8; 1]
93 412..415 'arr': &[u8; 1]
94 "#]],
95 ); 44 );
96} 45}
97 46
98#[test] 47#[test]
99fn infer_let_stmt_coerce() { 48fn let_stmt_coerce() {
100 check_infer( 49 check_no_mismatches(
101 r" 50 r"
102 fn test() { 51//- minicore: coerce_unsized
103 let x: &[isize] = &[1]; 52fn test() {
104 let x: *const [isize] = &[1]; 53 let x: &[isize] = &[1];
105 } 54 let x: *const [isize] = &[1];
106 ", 55}
107 expect![[r#" 56",
108 10..75 '{ ...[1]; }': ()
109 20..21 'x': &[isize]
110 34..38 '&[1]': &[isize; 1]
111 35..38 '[1]': [isize; 1]
112 36..37 '1': isize
113 48..49 'x': *const [isize]
114 68..72 '&[1]': &[isize; 1]
115 69..72 '[1]': [isize; 1]
116 70..71 '1': isize
117 "#]],
118 ); 57 );
119} 58}
120 59
121#[test] 60#[test]
122fn infer_custom_coerce_unsized() { 61fn custom_coerce_unsized() {
123 check_infer( 62 check(
124 r#" 63 r#"
125//- minicore: coerce_unsized 64//- minicore: coerce_unsized
126use core::{marker::Unsize, ops::CoerceUnsized}; 65use core::{marker::Unsize, ops::CoerceUnsized};
@@ -138,46 +77,22 @@ fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
138 77
139fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { 78fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
140 let d = foo1(a); 79 let d = foo1(a);
80 // ^ expected A<[{unknown}]>, got A<[u8; 2]>
141 let e = foo2(b); 81 let e = foo2(b);
82 // ^ type: B<[u8]>
142 let f = foo3(c); 83 let f = foo3(c);
84 // ^ type: C<[u8]>
143} 85}
144"#, 86"#,
145 expect![[r#"
146 306..307 'x': A<[T]>
147 327..332 '{ x }': A<[T]>
148 329..330 'x': A<[T]>
149 344..345 'x': B<[T]>
150 365..370 '{ x }': B<[T]>
151 367..368 'x': B<[T]>
152 382..383 'x': C<[T]>
153 403..408 '{ x }': C<[T]>
154 405..406 'x': C<[T]>
155 418..419 'a': A<[u8; 2]>
156 433..434 'b': B<[u8; 2]>
157 448..449 'c': C<[u8; 2]>
158 463..529 '{ ...(c); }': ()
159 473..474 'd': A<[{unknown}]>
160 477..481 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
161 477..484 'foo1(a)': A<[{unknown}]>
162 482..483 'a': A<[u8; 2]>
163 494..495 'e': B<[u8]>
164 498..502 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
165 498..505 'foo2(b)': B<[u8]>
166 503..504 'b': B<[u8; 2]>
167 515..516 'f': C<[u8]>
168 519..523 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
169 519..526 'foo3(c)': C<[u8]>
170 524..525 'c': C<[u8; 2]>
171 "#]],
172 ); 87 );
173} 88}
174 89
175#[test] 90#[test]
176fn infer_if_coerce() { 91fn if_coerce() {
177 check_infer( 92 check_no_mismatches(
178 r#" 93 r#"
179//- minicore: unsize 94//- minicore: coerce_unsized
180fn foo<T>(x: &[T]) -> &[T] { loop {} } 95fn foo<T>(x: &[T]) -> &[T] { x }
181fn test() { 96fn test() {
182 let x = if true { 97 let x = if true {
183 foo(&[1]) 98 foo(&[1])
@@ -186,35 +101,15 @@ fn test() {
186 }; 101 };
187} 102}
188"#, 103"#,
189 expect![[r#"
190 10..11 'x': &[T]
191 27..38 '{ loop {} }': &[T]
192 29..36 'loop {}': !
193 34..36 '{}': ()
194 49..125 '{ ... }; }': ()
195 59..60 'x': &[i32]
196 63..122 'if tru... }': &[i32]
197 66..70 'true': bool
198 71..96 '{ ... }': &[i32]
199 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32]
200 81..90 'foo(&[1])': &[i32]
201 85..89 '&[1]': &[i32; 1]
202 86..89 '[1]': [i32; 1]
203 87..88 '1': i32
204 102..122 '{ ... }': &[i32; 1]
205 112..116 '&[1]': &[i32; 1]
206 113..116 '[1]': [i32; 1]
207 114..115 '1': i32
208 "#]],
209 ); 104 );
210} 105}
211 106
212#[test] 107#[test]
213fn infer_if_else_coerce() { 108fn if_else_coerce() {
214 check_infer( 109 check_no_mismatches(
215 r#" 110 r#"
216//- minicore: coerce_unsized 111//- minicore: coerce_unsized
217fn foo<T>(x: &[T]) -> &[T] { loop {} } 112fn foo<T>(x: &[T]) -> &[T] { x }
218fn test() { 113fn test() {
219 let x = if true { 114 let x = if true {
220 &[1] 115 &[1]
@@ -223,35 +118,15 @@ fn test() {
223 }; 118 };
224} 119}
225"#, 120"#,
226 expect![[r#"
227 10..11 'x': &[T]
228 27..38 '{ loop {} }': &[T]
229 29..36 'loop {}': !
230 34..36 '{}': ()
231 49..125 '{ ... }; }': ()
232 59..60 'x': &[i32]
233 63..122 'if tru... }': &[i32]
234 66..70 'true': bool
235 71..91 '{ ... }': &[i32; 1]
236 81..85 '&[1]': &[i32; 1]
237 82..85 '[1]': [i32; 1]
238 83..84 '1': i32
239 97..122 '{ ... }': &[i32]
240 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32]
241 107..116 'foo(&[1])': &[i32]
242 111..115 '&[1]': &[i32; 1]
243 112..115 '[1]': [i32; 1]
244 113..114 '1': i32
245 "#]],
246 ) 121 )
247} 122}
248 123
249#[test] 124#[test]
250fn infer_match_first_coerce() { 125fn match_first_coerce() {
251 check_infer( 126 check_no_mismatches(
252 r#" 127 r#"
253//- minicore: unsize 128//- minicore: coerce_unsized
254fn foo<T>(x: &[T]) -> &[T] { loop {} } 129fn foo<T>(x: &[T]) -> &[T] { x }
255fn test(i: i32) { 130fn test(i: i32) {
256 let x = match i { 131 let x = match i {
257 2 => foo(&[2]), 132 2 => foo(&[2]),
@@ -260,39 +135,12 @@ fn test(i: i32) {
260 }; 135 };
261} 136}
262"#, 137"#,
263 expect![[r#"
264 10..11 'x': &[T]
265 27..38 '{ loop {} }': &[T]
266 29..36 'loop {}': !
267 34..36 '{}': ()
268 47..48 'i': i32
269 55..149 '{ ... }; }': ()
270 65..66 'x': &[i32]
271 69..146 'match ... }': &[i32]
272 75..76 'i': i32
273 87..88 '2': i32
274 87..88 '2': i32
275 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32]
276 92..101 'foo(&[2])': &[i32]
277 96..100 '&[2]': &[i32; 1]
278 97..100 '[2]': [i32; 1]
279 98..99 '2': i32
280 111..112 '1': i32
281 111..112 '1': i32
282 116..120 '&[1]': &[i32; 1]
283 117..120 '[1]': [i32; 1]
284 118..119 '1': i32
285 130..131 '_': i32
286 135..139 '&[3]': &[i32; 1]
287 136..139 '[3]': [i32; 1]
288 137..138 '3': i32
289 "#]],
290 ); 138 );
291} 139}
292 140
293#[test] 141#[test]
294fn infer_match_second_coerce() { 142fn match_second_coerce() {
295 check_infer( 143 check_no_mismatches(
296 r#" 144 r#"
297//- minicore: coerce_unsized 145//- minicore: coerce_unsized
298fn foo<T>(x: &[T]) -> &[T] { loop {} } 146fn foo<T>(x: &[T]) -> &[T] { loop {} }
@@ -304,33 +152,6 @@ fn test(i: i32) {
304 }; 152 };
305} 153}
306"#, 154"#,
307 expect![[r#"
308 10..11 'x': &[T]
309 27..38 '{ loop {} }': &[T]
310 29..36 'loop {}': !
311 34..36 '{}': ()
312 47..48 'i': i32
313 55..149 '{ ... }; }': ()
314 65..66 'x': &[i32]
315 69..146 'match ... }': &[i32]
316 75..76 'i': i32
317 87..88 '1': i32
318 87..88 '1': i32
319 92..96 '&[1]': &[i32; 1]
320 93..96 '[1]': [i32; 1]
321 94..95 '1': i32
322 106..107 '2': i32
323 106..107 '2': i32
324 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32]
325 111..120 'foo(&[2])': &[i32]
326 115..119 '&[2]': &[i32; 1]
327 116..119 '[2]': [i32; 1]
328 117..118 '2': i32
329 130..131 '_': i32
330 135..139 '&[3]': &[i32; 1]
331 136..139 '[3]': [i32; 1]
332 137..138 '3': i32
333 "#]],
334 ); 155 );
335} 156}
336 157
@@ -338,94 +159,52 @@ fn test(i: i32) {
338fn coerce_merge_one_by_one1() { 159fn coerce_merge_one_by_one1() {
339 cov_mark::check!(coerce_merge_fail_fallback); 160 cov_mark::check!(coerce_merge_fail_fallback);
340 161
341 check_infer( 162 check(
342 r" 163 r"
343 fn test() { 164fn test() {
344 let t = &mut 1; 165 let t = &mut 1;
345 let x = match 1 { 166 let x = match 1 {
346 1 => t as *mut i32, 167 1 => t as *mut i32,
347 2 => t as &i32, 168 2 => t as &i32,
348 _ => t as *const i32, 169 //^^^^^^^^^ expected *mut i32, got &i32
349 }; 170 _ => t as *const i32,
350 } 171 };
172 x;
173 //^ type: *const i32
174}
351 ", 175 ",
352 expect![[r"
353 10..144 '{ ... }; }': ()
354 20..21 't': &mut i32
355 24..30 '&mut 1': &mut i32
356 29..30 '1': i32
357 40..41 'x': *const i32
358 44..141 'match ... }': *const i32
359 50..51 '1': i32
360 62..63 '1': i32
361 62..63 '1': i32
362 67..68 't': &mut i32
363 67..80 't as *mut i32': *mut i32
364 90..91 '2': i32
365 90..91 '2': i32
366 95..96 't': &mut i32
367 95..104 't as &i32': &i32
368 114..115 '_': i32
369 119..120 't': &mut i32
370 119..134 't as *const i32': *const i32
371 "]],
372 ); 176 );
373} 177}
374 178
375#[test] 179#[test]
376fn return_coerce_unknown() { 180fn return_coerce_unknown() {
377 check_infer_with_mismatches( 181 check_types(
378 r" 182 r"
379 fn foo() -> u32 { 183fn foo() -> u32 {
380 return unknown; 184 return unknown;
381 } 185 //^^^^^^^ u32
186}
382 ", 187 ",
383 expect![[r"
384 16..39 '{ ...own; }': u32
385 22..36 'return unknown': !
386 29..36 'unknown': u32
387 "]],
388 ); 188 );
389} 189}
390 190
391#[test] 191#[test]
392fn coerce_autoderef() { 192fn coerce_autoderef() {
393 check_infer_with_mismatches( 193 check_no_mismatches(
394 r" 194 r"
395 struct Foo; 195struct Foo;
396 fn takes_ref_foo(x: &Foo) {} 196fn takes_ref_foo(x: &Foo) {}
397 fn test() { 197fn test() {
398 takes_ref_foo(&Foo); 198 takes_ref_foo(&Foo);
399 takes_ref_foo(&&Foo); 199 takes_ref_foo(&&Foo);
400 takes_ref_foo(&&&Foo); 200 takes_ref_foo(&&&Foo);
401 } 201}",
402 ",
403 expect![[r"
404 29..30 'x': &Foo
405 38..40 '{}': ()
406 51..132 '{ ...oo); }': ()
407 57..70 'takes_ref_foo': fn takes_ref_foo(&Foo)
408 57..76 'takes_...(&Foo)': ()
409 71..75 '&Foo': &Foo
410 72..75 'Foo': Foo
411 82..95 'takes_ref_foo': fn takes_ref_foo(&Foo)
412 82..102 'takes_...&&Foo)': ()
413 96..101 '&&Foo': &&Foo
414 97..101 '&Foo': &Foo
415 98..101 'Foo': Foo
416 108..121 'takes_ref_foo': fn takes_ref_foo(&Foo)
417 108..129 'takes_...&&Foo)': ()
418 122..128 '&&&Foo': &&&Foo
419 123..128 '&&Foo': &&Foo
420 124..128 '&Foo': &Foo
421 125..128 'Foo': Foo
422 "]],
423 ); 202 );
424} 203}
425 204
426#[test] 205#[test]
427fn coerce_autoderef_generic() { 206fn coerce_autoderef_generic() {
428 check_infer_with_mismatches( 207 check_no_mismatches(
429 r#" 208 r#"
430struct Foo; 209struct Foo;
431fn takes_ref<T>(x: &T) -> T { *x } 210fn takes_ref<T>(x: &T) -> T { *x }
@@ -435,34 +214,12 @@ fn test() {
435 takes_ref(&&&Foo); 214 takes_ref(&&&Foo);
436} 215}
437"#, 216"#,
438 expect![[r"
439 28..29 'x': &T
440 40..46 '{ *x }': T
441 42..44 '*x': T
442 43..44 'x': &T
443 57..126 '{ ...oo); }': ()
444 63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo
445 63..78 'takes_ref(&Foo)': Foo
446 73..77 '&Foo': &Foo
447 74..77 'Foo': Foo
448 84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo
449 84..100 'takes_...&&Foo)': &Foo
450 94..99 '&&Foo': &&Foo
451 95..99 '&Foo': &Foo
452 96..99 'Foo': Foo
453 106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo
454 106..123 'takes_...&&Foo)': &&Foo
455 116..122 '&&&Foo': &&&Foo
456 117..122 '&&Foo': &&Foo
457 118..122 '&Foo': &Foo
458 119..122 'Foo': Foo
459 "]],
460 ); 217 );
461} 218}
462 219
463#[test] 220#[test]
464fn coerce_autoderef_block() { 221fn coerce_autoderef_block() {
465 check_infer_with_mismatches( 222 check_no_mismatches(
466 r#" 223 r#"
467//- minicore: deref 224//- minicore: deref
468struct String {} 225struct String {}
@@ -473,71 +230,32 @@ fn test() {
473 takes_ref_str(&{ returns_string() }); 230 takes_ref_str(&{ returns_string() });
474} 231}
475"#, 232"#,
476 expect![[r#"
477 90..91 'x': &str
478 99..101 '{}': ()
479 132..143 '{ loop {} }': String
480 134..141 'loop {}': !
481 139..141 '{}': ()
482 154..199 '{ ... }); }': ()
483 160..173 'takes_ref_str': fn takes_ref_str(&str)
484 160..196 'takes_...g() })': ()
485 174..195 '&{ ret...ng() }': &String
486 175..195 '{ retu...ng() }': String
487 177..191 'returns_string': fn returns_string() -> String
488 177..193 'return...ring()': String
489 "#]],
490 ); 233 );
491} 234}
492 235
493#[test] 236#[test]
494fn closure_return_coerce() { 237fn closure_return_coerce() {
495 check_infer_with_mismatches( 238 check_no_mismatches(
496 r" 239 r"
497 fn foo() { 240fn foo() {
498 let x = || { 241 let x = || {
499 if true { 242 if true {
500 return &1u32; 243 return &1u32;
501 }
502 &&1u32
503 };
504 } 244 }
505 ", 245 &&1u32
506 expect![[r" 246 };
507 9..105 '{ ... }; }': () 247}",
508 19..20 'x': || -> &u32
509 23..102 '|| { ... }': || -> &u32
510 26..102 '{ ... }': &u32
511 36..81 'if tru... }': ()
512 39..43 'true': bool
513 44..81 '{ ... }': ()
514 58..70 'return &1u32': !
515 65..70 '&1u32': &u32
516 66..70 '1u32': u32
517 90..96 '&&1u32': &&u32
518 91..96 '&1u32': &u32
519 92..96 '1u32': u32
520 "]],
521 ); 248 );
522} 249}
523 250
524#[test] 251#[test]
525fn coerce_fn_item_to_fn_ptr() { 252fn coerce_fn_item_to_fn_ptr() {
526 check_infer_with_mismatches( 253 check_no_mismatches(
527 r" 254 r"
528 fn foo(x: u32) -> isize { 1 } 255fn foo(x: u32) -> isize { 1 }
529 fn test() { 256fn test() {
530 let f: fn(u32) -> isize = foo; 257 let f: fn(u32) -> isize = foo;
531 } 258}",
532 ",
533 expect![[r"
534 7..8 'x': u32
535 24..29 '{ 1 }': isize
536 26..27 '1': isize
537 40..78 '{ ...foo; }': ()
538 50..51 'f': fn(u32) -> isize
539 72..75 'foo': fn foo(u32) -> isize
540 "]],
541 ); 259 );
542} 260}
543 261
@@ -545,110 +263,62 @@ fn coerce_fn_item_to_fn_ptr() {
545fn coerce_fn_items_in_match_arms() { 263fn coerce_fn_items_in_match_arms() {
546 cov_mark::check!(coerce_fn_reification); 264 cov_mark::check!(coerce_fn_reification);
547 265
548 check_infer_with_mismatches( 266 check_types(
549 r" 267 r"
550 fn foo1(x: u32) -> isize { 1 } 268fn foo1(x: u32) -> isize { 1 }
551 fn foo2(x: u32) -> isize { 2 } 269fn foo2(x: u32) -> isize { 2 }
552 fn foo3(x: u32) -> isize { 3 } 270fn foo3(x: u32) -> isize { 3 }
553 fn test() { 271fn test() {
554 let x = match 1 { 272 let x = match 1 {
555 1 => foo1, 273 1 => foo1,
556 2 => foo2, 274 2 => foo2,
557 _ => foo3, 275 _ => foo3,
558 }; 276 };
559 } 277 x;
560 ", 278 //^ fn(u32) -> isize
561 expect![[r" 279}",
562 8..9 'x': u32
563 25..30 '{ 1 }': isize
564 27..28 '1': isize
565 39..40 'x': u32
566 56..61 '{ 2 }': isize
567 58..59 '2': isize
568 70..71 'x': u32
569 87..92 '{ 3 }': isize
570 89..90 '3': isize
571 103..192 '{ ... }; }': ()
572 113..114 'x': fn(u32) -> isize
573 117..189 'match ... }': fn(u32) -> isize
574 123..124 '1': i32
575 135..136 '1': i32
576 135..136 '1': i32
577 140..144 'foo1': fn foo1(u32) -> isize
578 154..155 '2': i32
579 154..155 '2': i32
580 159..163 'foo2': fn foo2(u32) -> isize
581 173..174 '_': i32
582 178..182 'foo3': fn foo3(u32) -> isize
583 "]],
584 ); 280 );
585} 281}
586 282
587#[test] 283#[test]
588fn coerce_closure_to_fn_ptr() { 284fn coerce_closure_to_fn_ptr() {
589 check_infer_with_mismatches( 285 check_no_mismatches(
590 r" 286 r"
591 fn test() { 287fn test() {
592 let f: fn(u32) -> isize = |x| { 1 }; 288 let f: fn(u32) -> isize = |x| { 1 };
593 } 289}",
594 ",
595 expect![[r"
596 10..54 '{ ...1 }; }': ()
597 20..21 'f': fn(u32) -> isize
598 42..51 '|x| { 1 }': |u32| -> isize
599 43..44 'x': u32
600 46..51 '{ 1 }': isize
601 48..49 '1': isize
602 "]],
603 ); 290 );
604} 291}
605 292
606#[test] 293#[test]
607fn coerce_placeholder_ref() { 294fn coerce_placeholder_ref() {
608 // placeholders should unify, even behind references 295 // placeholders should unify, even behind references
609 check_infer_with_mismatches( 296 check_no_mismatches(
610 r" 297 r"
611 struct S<T> { t: T } 298struct S<T> { t: T }
612 impl<TT> S<TT> { 299impl<TT> S<TT> {
613 fn get(&self) -> &TT { 300 fn get(&self) -> &TT {
614 &self.t 301 &self.t
615 } 302 }
616 } 303}",
617 ",
618 expect![[r"
619 50..54 'self': &S<TT>
620 63..86 '{ ... }': &TT
621 73..80 '&self.t': &TT
622 74..78 'self': &S<TT>
623 74..80 'self.t': TT
624 "]],
625 ); 304 );
626} 305}
627 306
628#[test] 307#[test]
629fn coerce_unsize_array() { 308fn coerce_unsize_array() {
630 check_infer_with_mismatches( 309 check_types(
631 r#" 310 r#"
632//- minicore: coerce_unsized 311//- minicore: coerce_unsized
633fn test() { 312fn test() {
634 let f: &[usize] = &[1, 2, 3]; 313 let f: &[usize] = &[1, 2, 3];
635} 314 //^ usize
636 "#, 315}"#,
637 expect![[r#"
638 10..47 '{ ... 3]; }': ()
639 20..21 'f': &[usize]
640 34..44 '&[1, 2, 3]': &[usize; 3]
641 35..44 '[1, 2, 3]': [usize; 3]
642 36..37 '1': usize
643 39..40 '2': usize
644 42..43 '3': usize
645 "#]],
646 ); 316 );
647} 317}
648 318
649#[test] 319#[test]
650fn coerce_unsize_trait_object_simple() { 320fn coerce_unsize_trait_object_simple() {
651 check_infer_with_mismatches( 321 check_types(
652 r#" 322 r#"
653//- minicore: coerce_unsized 323//- minicore: coerce_unsized
654trait Foo<T, U> {} 324trait Foo<T, U> {}
@@ -662,88 +332,18 @@ impl<T, X> Baz<T, X> for S<T, X> {}
662 332
663fn test() { 333fn test() {
664 let obj: &dyn Baz<i8, i16> = &S; 334 let obj: &dyn Baz<i8, i16> = &S;
335 //^ S<i8, i16>
665 let obj: &dyn Bar<_, i8, i16> = &S; 336 let obj: &dyn Bar<_, i8, i16> = &S;
337 //^ S<i8, i16>
666 let obj: &dyn Foo<i8, _> = &S; 338 let obj: &dyn Foo<i8, _> = &S;
667} 339 //^ S<i8, {unknown}>
668"#, 340}"#,
669 expect![[r#"
670 236..351 '{ ... &S; }': ()
671 246..249 'obj': &dyn Baz<i8, i16>
672 271..273 '&S': &S<i8, i16>
673 272..273 'S': S<i8, i16>
674 283..286 'obj': &dyn Bar<usize, i8, i16>
675 311..313 '&S': &S<i8, i16>
676 312..313 'S': S<i8, i16>
677 323..326 'obj': &dyn Foo<i8, usize>
678 346..348 '&S': &S<i8, {unknown}>
679 347..348 'S': S<i8, {unknown}>
680 "#]],
681 );
682}
683
684#[test]
685fn coerce_unsize_trait_object_to_trait_object() {
686 // FIXME: The rust reference says this should be possible, but rustc doesn't
687 // implement it. We used to support it, but Chalk doesn't. Here's the
688 // correct expect:
689 //
690 // 424..609 '{ ...bj2; }': ()
691 // 434..437 'obj': &dyn Baz<i8, i16>
692 // 459..461 '&S': &S<i8, i16>
693 // 460..461 'S': S<i8, i16>
694 // 471..474 'obj': &dyn Bar<usize, i8, i16>
695 // 496..499 'obj': &dyn Baz<i8, i16>
696 // 509..512 'obj': &dyn Foo<i8, usize>
697 // 531..534 'obj': &dyn Bar<usize, i8, i16>
698 // 544..548 'obj2': &dyn Baz<i8, i16>
699 // 570..572 '&S': &S<i8, i16>
700 // 571..572 'S': S<i8, i16>
701 // 582..583 '_': &dyn Foo<i8, usize>
702 // 602..606 'obj2': &dyn Baz<i8, i16>
703 check_infer_with_mismatches(
704 r#"
705//- minicore: coerce_unsized
706trait Foo<T, U> {}
707trait Bar<U, T, X>: Foo<T, U> {}
708trait Baz<T, X>: Bar<usize, T, X> {}
709
710struct S<T, X>;
711impl<T, X> Foo<T, usize> for S<T, X> {}
712impl<T, X> Bar<usize, T, X> for S<T, X> {}
713impl<T, X> Baz<T, X> for S<T, X> {}
714
715fn test() {
716 let obj: &dyn Baz<i8, i16> = &S;
717 let obj: &dyn Bar<_, _, _> = obj;
718 let obj: &dyn Foo<_, _> = obj;
719 let obj2: &dyn Baz<i8, i16> = &S;
720 let _: &dyn Foo<_, _> = obj2;
721}
722"#,
723 expect![[r#"
724 236..421 '{ ...bj2; }': ()
725 246..249 'obj': &dyn Baz<i8, i16>
726 271..273 '&S': &S<i8, i16>
727 272..273 'S': S<i8, i16>
728 283..286 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
729 308..311 'obj': &dyn Baz<i8, i16>
730 321..324 'obj': &dyn Foo<{unknown}, {unknown}>
731 343..346 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
732 356..360 'obj2': &dyn Baz<i8, i16>
733 382..384 '&S': &S<i8, i16>
734 383..384 'S': S<i8, i16>
735 394..395 '_': &dyn Foo<{unknown}, {unknown}>
736 414..418 'obj2': &dyn Baz<i8, i16>
737 308..311: expected &dyn Bar<{unknown}, {unknown}, {unknown}>, got &dyn Baz<i8, i16>
738 343..346: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Bar<{unknown}, {unknown}, {unknown}>
739 414..418: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Baz<i8, i16>
740 "#]],
741 ); 341 );
742} 342}
743 343
744#[test] 344#[test]
745fn coerce_unsize_super_trait_cycle() { 345fn coerce_unsize_super_trait_cycle() {
746 check_infer_with_mismatches( 346 check_no_mismatches(
747 r#" 347 r#"
748//- minicore: coerce_unsized 348//- minicore: coerce_unsized
749trait A {} 349trait A {}
@@ -762,22 +362,13 @@ fn test() {
762 let obj: &dyn A = &S; 362 let obj: &dyn A = &S;
763} 363}
764"#, 364"#,
765 expect![[r#"
766 140..195 '{ ... &S; }': ()
767 150..153 'obj': &dyn D
768 164..166 '&S': &S
769 165..166 'S': S
770 176..179 'obj': &dyn A
771 190..192 '&S': &S
772 191..192 'S': S
773 "#]],
774 ); 365 );
775} 366}
776 367
777#[test] 368#[test]
778fn coerce_unsize_generic() { 369fn coerce_unsize_generic() {
779 // FIXME: fix the type mismatches here 370 // FIXME: fix the type mismatches here
780 check_infer_with_mismatches( 371 check(
781 r#" 372 r#"
782//- minicore: coerce_unsized 373//- minicore: coerce_unsized
783struct Foo<T> { t: T }; 374struct Foo<T> { t: T };
@@ -785,73 +376,47 @@ struct Bar<T>(Foo<T>);
785 376
786fn test() { 377fn test() {
787 let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; 378 let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
379 //^^^^^^^^^ expected [usize], got [usize; 3]
788 let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); 380 let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
381 //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]>
789} 382}
790"#, 383"#,
791 expect![[r#"
792 58..166 '{ ... }); }': ()
793 68..69 '_': &Foo<[usize]>
794 87..108 '&Foo {..., 3] }': &Foo<[usize]>
795 88..108 'Foo { ..., 3] }': Foo<[usize]>
796 97..106 '[1, 2, 3]': [usize; 3]
797 98..99 '1': usize
798 101..102 '2': usize
799 104..105 '3': usize
800 118..119 '_': &Bar<[usize]>
801 137..163 '&Bar(F... 3] })': &Bar<[i32; 3]>
802 138..141 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]>
803 138..163 'Bar(Fo... 3] })': Bar<[i32; 3]>
804 142..162 'Foo { ..., 3] }': Foo<[i32; 3]>
805 151..160 '[1, 2, 3]': [i32; 3]
806 152..153 '1': i32
807 155..156 '2': i32
808 158..159 '3': i32
809 97..106: expected [usize], got [usize; 3]
810 137..163: expected &Bar<[usize]>, got &Bar<[i32; 3]>
811 "#]],
812 ); 384 );
813} 385}
814 386
815#[test] 387#[test]
816fn coerce_unsize_apit() { 388fn coerce_unsize_apit() {
817 // FIXME: #8984 389 // FIXME: #8984
818 check_infer_with_mismatches( 390 check(
819 r#" 391 r#"
820//- minicore: coerce_unsized 392//- minicore: coerce_unsized
821trait Foo {} 393trait Foo {}
822 394
823fn test(f: impl Foo) { 395fn test(f: impl Foo) {
824 let _: &dyn Foo = &f; 396 let _: &dyn Foo = &f;
397 //^^ expected &dyn Foo, got &impl Foo
825} 398}
826 "#, 399 "#,
827 expect![[r#"
828 22..23 'f': impl Foo
829 35..64 '{ ... &f; }': ()
830 45..46 '_': &dyn Foo
831 59..61 '&f': &impl Foo
832 60..61 'f': impl Foo
833 59..61: expected &dyn Foo, got &impl Foo
834 "#]],
835 ); 400 );
836} 401}
837 402
838#[test] 403#[test]
839fn infer_two_closures_lub() { 404fn two_closures_lub() {
840 check_types( 405 check_types(
841 r#" 406 r#"
842fn foo(c: i32) { 407fn foo(c: i32) {
843 let add = |a: i32, b: i32| a + b; 408 let add = |a: i32, b: i32| a + b;
844 let sub = |a, b| a - b; 409 let sub = |a, b| a - b;
845 //^ |i32, i32| -> i32 410 //^^^^^^^^^^^^ |i32, i32| -> i32
846 if c > 42 { add } else { sub }; 411 if c > 42 { add } else { sub };
847 //^ fn(i32, i32) -> i32 412 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32
848} 413}
849 "#, 414 "#,
850 ) 415 )
851} 416}
852 417
853#[test] 418#[test]
854fn infer_match_diverging_branch_1() { 419fn match_diverging_branch_1() {
855 check_types( 420 check_types(
856 r#" 421 r#"
857enum Result<T> { Ok(T), Err } 422enum Result<T> { Ok(T), Err }
@@ -870,7 +435,7 @@ fn test() -> i32 {
870} 435}
871 436
872#[test] 437#[test]
873fn infer_match_diverging_branch_2() { 438fn match_diverging_branch_2() {
874 // same as 1 except for order of branches 439 // same as 1 except for order of branches
875 check_types( 440 check_types(
876 r#" 441 r#"
diff --git a/crates/hir_ty/src/tests/display_source_code.rs b/crates/hir_ty/src/tests/display_source_code.rs
index 3d29021aa..058cd02d7 100644
--- a/crates/hir_ty/src/tests/display_source_code.rs
+++ b/crates/hir_ty/src/tests/display_source_code.rs
@@ -10,8 +10,8 @@ mod foo {
10 10
11fn bar() { 11fn bar() {
12 let foo: foo::Foo = foo::Foo; 12 let foo: foo::Foo = foo::Foo;
13 foo 13 foo;
14} //^ foo::Foo 14} //^^^ foo::Foo
15 15
16"#, 16"#,
17 ); 17 );
@@ -25,7 +25,7 @@ struct Foo<T = u8> { t: T }
25fn main() { 25fn main() {
26 let foo = Foo { t: 5u8 }; 26 let foo = Foo { t: 5u8 };
27 foo; 27 foo;
28} //^ Foo 28} //^^^ Foo
29"#, 29"#,
30 ); 30 );
31 31
@@ -35,7 +35,7 @@ struct Foo<K, T = u8> { k: K, t: T }
35fn main() { 35fn main() {
36 let foo = Foo { k: 400, t: 5u8 }; 36 let foo = Foo { k: 400, t: 5u8 };
37 foo; 37 foo;
38} //^ Foo<i32> 38} //^^^ Foo<i32>
39"#, 39"#,
40 ); 40 );
41} 41}
@@ -50,7 +50,7 @@ fn foo() -> *const (impl Unpin + Sized) { loop {} }
50fn main() { 50fn main() {
51 let foo = foo(); 51 let foo = foo();
52 foo; 52 foo;
53} //^ *const (impl Unpin + Sized) 53} //^^^ *const (impl Unpin + Sized)
54"#, 54"#,
55 ); 55 );
56} 56}
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index d14103aab..2cf41e49e 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -435,11 +435,11 @@ fn processes_impls_generated_by_macros() {
435macro_rules! m { 435macro_rules! m {
436 ($ident:ident) => (impl Trait for $ident {}) 436 ($ident:ident) => (impl Trait for $ident {})
437} 437}
438trait Trait { fn foo(self) -> u128 {} } 438trait Trait { fn foo(self) -> u128 { 0 } }
439struct S; 439struct S;
440m!(S); 440m!(S);
441fn test() { S.foo(); } 441fn test() { S.foo(); }
442 //^ u128 442 //^^^^^^^ u128
443"#, 443"#,
444 ); 444 );
445} 445}
@@ -457,7 +457,7 @@ impl S {
457} 457}
458 458
459fn test() { S.foo(); } 459fn test() { S.foo(); }
460 //^ u128 460 //^^^^^^^ u128
461"#, 461"#,
462 ); 462 );
463} 463}
@@ -479,7 +479,7 @@ impl S {
479} 479}
480 480
481fn test() { S.foo(); } 481fn test() { S.foo(); }
482 //^ u128 482 //^^^^^^^ u128
483"#, 483"#,
484 ); 484 );
485} 485}
@@ -743,7 +743,7 @@ include!("foo.rs");
743 743
744fn main() { 744fn main() {
745 bar(); 745 bar();
746} //^ u32 746} //^^^^^ u32
747 747
748//- /foo.rs 748//- /foo.rs
749fn bar() -> u32 {0} 749fn bar() -> u32 {0}
@@ -781,7 +781,7 @@ include!("f/foo.rs");
781 781
782fn main() { 782fn main() {
783 bar::bar(); 783 bar::bar();
784} //^ u32 784} //^^^^^^^^^^ u32
785 785
786//- /f/foo.rs 786//- /f/foo.rs
787pub mod bar; 787pub mod bar;
@@ -853,7 +853,7 @@ include!("foo.rs");
853 853
854fn main() { 854fn main() {
855 RegisterBlock { }; 855 RegisterBlock { };
856 //^ RegisterBlock 856 //^^^^^^^^^^^^^^^^^ RegisterBlock
857} 857}
858 "#; 858 "#;
859 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data); 859 let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data);
@@ -879,7 +879,7 @@ include!(concat!("f", "oo.rs"));
879 879
880fn main() { 880fn main() {
881 bar(); 881 bar();
882} //^ u32 882} //^^^^^ u32
883 883
884//- /foo.rs 884//- /foo.rs
885fn bar() -> u32 {0} 885fn bar() -> u32 {0}
@@ -905,7 +905,7 @@ include!(concat!(env!("OUT_DIR"), "/foo.rs"));
905 905
906fn main() { 906fn main() {
907 bar(); 907 bar();
908} //^ {unknown} 908} //^^^^^ {unknown}
909 909
910//- /foo.rs 910//- /foo.rs
911fn bar() -> u32 {0} 911fn bar() -> u32 {0}
@@ -923,7 +923,7 @@ macro_rules! include {() => {}}
923include!("main.rs"); 923include!("main.rs");
924 924
925fn main() { 925fn main() {
926 0 926 0;
927} //^ i32 927} //^ i32
928"#, 928"#,
929 ); 929 );
@@ -979,7 +979,7 @@ fn infer_derive_clone_simple() {
979struct S; 979struct S;
980fn test() { 980fn test() {
981 S.clone(); 981 S.clone();
982} //^ S 982} //^^^^^^^^^ S
983 983
984//- /lib.rs crate:core 984//- /lib.rs crate:core
985pub mod prelude { 985pub mod prelude {
@@ -1028,7 +1028,7 @@ pub struct S;
1028use core::S; 1028use core::S;
1029fn test() { 1029fn test() {
1030 S.clone(); 1030 S.clone();
1031} //^ S 1031} //^^^^^^^^^ S
1032"#, 1032"#,
1033 ); 1033 );
1034} 1034}
@@ -1044,7 +1044,8 @@ struct S;
1044struct Wrapper<T>(T); 1044struct Wrapper<T>(T);
1045struct NonClone; 1045struct NonClone;
1046fn test() { 1046fn test() {
1047 (Wrapper(S).clone(), Wrapper(NonClone).clone()); 1047 let x = (Wrapper(S).clone(), Wrapper(NonClone).clone());
1048 x;
1048 //^ (Wrapper<S>, {unknown}) 1049 //^ (Wrapper<S>, {unknown})
1049} 1050}
1050 1051
@@ -1079,7 +1080,7 @@ struct S{}
1079 1080
1080fn test() { 1081fn test() {
1081 S{}; 1082 S{};
1082} //^ S 1083} //^^^ S
1083"#, 1084"#,
1084 ); 1085 );
1085} 1086}
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index d9b5ee9cf..3f7a37295 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -257,7 +257,7 @@ fn test() {
257mod foo { 257mod foo {
258 struct S; 258 struct S;
259 impl S { 259 impl S {
260 fn thing() -> i128 {} 260 fn thing() -> i128 { 0 }
261 } 261 }
262} 262}
263"#, 263"#,
@@ -267,164 +267,128 @@ mod foo {
267#[test] 267#[test]
268fn infer_trait_method_simple() { 268fn infer_trait_method_simple() {
269 // the trait implementation is intentionally incomplete -- it shouldn't matter 269 // the trait implementation is intentionally incomplete -- it shouldn't matter
270 check_infer( 270 check_types(
271 r#" 271 r#"
272 trait Trait1 { 272trait Trait1 {
273 fn method(&self) -> u32; 273 fn method(&self) -> u32;
274 } 274}
275 struct S1; 275struct S1;
276 impl Trait1 for S1 {} 276impl Trait1 for S1 {}
277 trait Trait2 { 277trait Trait2 {
278 fn method(&self) -> i128; 278 fn method(&self) -> i128;
279 } 279}
280 struct S2; 280struct S2;
281 impl Trait2 for S2 {} 281impl Trait2 for S2 {}
282 fn test() { 282fn test() {
283 S1.method(); // -> u32 283 S1.method();
284 S2.method(); // -> i128 284 //^^^^^^^^^^^ u32
285 } 285 S2.method(); // -> i128
286 //^^^^^^^^^^^ i128
287}
286 "#, 288 "#,
287 expect![[r#"
288 30..34 'self': &Self
289 109..113 'self': &Self
290 169..227 '{ ...i128 }': ()
291 175..177 'S1': S1
292 175..186 'S1.method()': u32
293 202..204 'S2': S2
294 202..213 'S2.method()': i128
295 "#]],
296 ); 289 );
297} 290}
298 291
299#[test] 292#[test]
300fn infer_trait_method_scoped() { 293fn infer_trait_method_scoped() {
301 // the trait implementation is intentionally incomplete -- it shouldn't matter 294 // the trait implementation is intentionally incomplete -- it shouldn't matter
302 check_infer( 295 check_types(
303 r#" 296 r#"
304 struct S; 297struct S;
305 mod foo { 298mod foo {
306 pub trait Trait1 { 299 pub trait Trait1 {
307 fn method(&self) -> u32; 300 fn method(&self) -> u32;
308 } 301 }
309 impl Trait1 for super::S {} 302 impl Trait1 for super::S {}
310 } 303}
311 mod bar { 304mod bar {
312 pub trait Trait2 { 305 pub trait Trait2 {
313 fn method(&self) -> i128; 306 fn method(&self) -> i128;
314 } 307 }
315 impl Trait2 for super::S {} 308 impl Trait2 for super::S {}
316 } 309}
317 310
318 mod foo_test { 311mod foo_test {
319 use super::S; 312 use super::S;
320 use super::foo::Trait1; 313 use super::foo::Trait1;
321 fn test() { 314 fn test() {
322 S.method(); // -> u32 315 S.method();
323 } 316 //^^^^^^^^^^ u32
324 } 317 }
318}
325 319
326 mod bar_test { 320mod bar_test {
327 use super::S; 321 use super::S;
328 use super::bar::Trait2; 322 use super::bar::Trait2;
329 fn test() { 323 fn test() {
330 S.method(); // -> i128 324 S.method();
331 } 325 //^^^^^^^^^^ i128
332 } 326 }
327}
333 "#, 328 "#,
334 expect![[r#"
335 62..66 'self': &Self
336 168..172 'self': &Self
337 299..336 '{ ... }': ()
338 309..310 'S': S
339 309..319 'S.method()': u32
340 415..453 '{ ... }': ()
341 425..426 'S': S
342 425..435 'S.method()': i128
343 "#]],
344 ); 329 );
345} 330}
346 331
347#[test] 332#[test]
348fn infer_trait_method_generic_1() { 333fn infer_trait_method_generic_1() {
349 // the trait implementation is intentionally incomplete -- it shouldn't matter 334 // the trait implementation is intentionally incomplete -- it shouldn't matter
350 check_infer( 335 check_types(
351 r#" 336 r#"
352 trait Trait<T> { 337trait Trait<T> {
353 fn method(&self) -> T; 338 fn method(&self) -> T;
354 } 339}
355 struct S; 340struct S;
356 impl Trait<u32> for S {} 341impl Trait<u32> for S {}
357 fn test() { 342fn test() {
358 S.method(); 343 S.method();
359 } 344 //^^^^^^^^^^ u32
345}
360 "#, 346 "#,
361 expect![[r#"
362 32..36 'self': &Self
363 91..110 '{ ...d(); }': ()
364 97..98 'S': S
365 97..107 'S.method()': u32
366 "#]],
367 ); 347 );
368} 348}
369 349
370#[test] 350#[test]
371fn infer_trait_method_generic_more_params() { 351fn infer_trait_method_generic_more_params() {
372 // the trait implementation is intentionally incomplete -- it shouldn't matter 352 // the trait implementation is intentionally incomplete -- it shouldn't matter
373 check_infer( 353 check_types(
374 r#" 354 r#"
375 trait Trait<T1, T2, T3> { 355trait Trait<T1, T2, T3> {
376 fn method1(&self) -> (T1, T2, T3); 356 fn method1(&self) -> (T1, T2, T3);
377 fn method2(&self) -> (T3, T2, T1); 357 fn method2(&self) -> (T3, T2, T1);
378 } 358}
379 struct S1; 359struct S1;
380 impl Trait<u8, u16, u32> for S1 {} 360impl Trait<u8, u16, u32> for S1 {}
381 struct S2; 361struct S2;
382 impl<T> Trait<i8, i16, T> for S2 {} 362impl<T> Trait<i8, i16, T> for S2 {}
383 fn test() { 363fn test() {
384 S1.method1(); // u8, u16, u32 364 S1.method1();
385 S1.method2(); // u32, u16, u8 365 //^^^^^^^^^^^^ (u8, u16, u32)
386 S2.method1(); // i8, i16, {unknown} 366 S1.method2();
387 S2.method2(); // {unknown}, i16, i8 367 //^^^^^^^^^^^^ (u32, u16, u8)
388 } 368 S2.method1();
369 //^^^^^^^^^^^^ (i8, i16, {unknown})
370 S2.method2();
371 //^^^^^^^^^^^^ ({unknown}, i16, i8)
372}
389 "#, 373 "#,
390 expect![[r#"
391 42..46 'self': &Self
392 81..85 'self': &Self
393 209..360 '{ ..., i8 }': ()
394 215..217 'S1': S1
395 215..227 'S1.method1()': (u8, u16, u32)
396 249..251 'S1': S1
397 249..261 'S1.method2()': (u32, u16, u8)
398 283..285 'S2': S2
399 283..295 'S2.method1()': (i8, i16, {unknown})
400 323..325 'S2': S2
401 323..335 'S2.method2()': ({unknown}, i16, i8)
402 "#]],
403 ); 374 );
404} 375}
405 376
406#[test] 377#[test]
407fn infer_trait_method_generic_2() { 378fn infer_trait_method_generic_2() {
408 // the trait implementation is intentionally incomplete -- it shouldn't matter 379 // the trait implementation is intentionally incomplete -- it shouldn't matter
409 check_infer( 380 check_types(
410 r#" 381 r#"
411 trait Trait<T> { 382trait Trait<T> {
412 fn method(&self) -> T; 383 fn method(&self) -> T;
413 } 384}
414 struct S<T>(T); 385struct S<T>(T);
415 impl<U> Trait<U> for S<U> {} 386impl<U> Trait<U> for S<U> {}
416 fn test() { 387fn test() {
417 S(1u32).method(); 388 S(1u32).method();
418 } 389 //^^^^^^^^^^^^^^^^ u32
390}
419 "#, 391 "#,
420 expect![[r#"
421 32..36 'self': &Self
422 101..126 '{ ...d(); }': ()
423 107..108 'S': S<u32>(u32) -> S<u32>
424 107..114 'S(1u32)': S<u32>
425 107..123 'S(1u32...thod()': u32
426 109..113 '1u32': u32
427 "#]],
428 ); 392 );
429} 393}
430 394
@@ -685,10 +649,10 @@ fn method_resolution_unify_impl_self_type() {
685 check_types( 649 check_types(
686 r#" 650 r#"
687struct S<T>; 651struct S<T>;
688impl S<u32> { fn foo(&self) -> u8 {} } 652impl S<u32> { fn foo(&self) -> u8 { 0 } }
689impl S<i32> { fn foo(&self) -> i8 {} } 653impl S<i32> { fn foo(&self) -> i8 { 0 } }
690fn test() { (S::<u32>.foo(), S::<i32>.foo()); } 654fn test() { (S::<u32>.foo(), S::<i32>.foo()); }
691 //^ (u8, i8) 655 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (u8, i8)
692"#, 656"#,
693 ); 657 );
694} 658}
@@ -702,7 +666,7 @@ struct S;
702impl S { fn foo(&self) -> i8 { 0 } } 666impl S { fn foo(&self) -> i8 { 0 } }
703impl Trait for S { fn foo(self) -> u128 { 0 } } 667impl Trait for S { fn foo(self) -> u128 { 0 } }
704fn test() { S.foo(); } 668fn test() { S.foo(); }
705 //^ u128 669 //^^^^^^^ u128
706"#, 670"#,
707 ); 671 );
708} 672}
@@ -716,7 +680,7 @@ struct S;
716impl Clone for S {} 680impl Clone for S {}
717impl Clone for &S {} 681impl Clone for &S {}
718fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } 682fn test() { (S.clone(), (&S).clone(), (&&S).clone()); }
719 //^ (S, S, &S) 683 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (S, S, &S)
720"#, 684"#,
721 ); 685 );
722} 686}
@@ -730,7 +694,7 @@ struct S;
730impl S { fn foo(self) -> i8 { 0 } } 694impl S { fn foo(self) -> i8 { 0 } }
731impl Trait for &S { fn foo(self) -> u128 { 0 } } 695impl Trait for &S { fn foo(self) -> u128 { 0 } }
732fn test() { (&S).foo(); } 696fn test() { (&S).foo(); }
733 //^ u128 697 //^^^^^^^^^^ u128
734"#, 698"#,
735 ); 699 );
736} 700}
@@ -744,7 +708,7 @@ struct S;
744impl S { fn foo(self) -> i8 { 0 } } 708impl S { fn foo(self) -> i8 { 0 } }
745impl Trait for S { fn foo(self) -> u128 { 0 } } 709impl Trait for S { fn foo(self) -> u128 { 0 } }
746fn test() { S.foo(); } 710fn test() { S.foo(); }
747 //^ i8 711 //^^^^^^^ i8
748"#, 712"#,
749 ); 713 );
750} 714}
@@ -758,7 +722,7 @@ struct S;
758impl S { fn foo(&self) -> i8 { 0 } } 722impl S { fn foo(&self) -> i8 { 0 } }
759impl Trait for &S { fn foo(self) -> u128 { 0 } } 723impl Trait for &S { fn foo(self) -> u128 { 0 } }
760fn test() { S.foo(); } 724fn test() { S.foo(); }
761 //^ i8 725 //^^^^^^^ i8
762"#, 726"#,
763 ); 727 );
764} 728}
@@ -771,7 +735,7 @@ trait Trait { fn foo(self) -> u128; }
771struct S; 735struct S;
772impl Trait for S { fn foo(self) -> u128 { 0 } } 736impl Trait for S { fn foo(self) -> u128 { 0 } }
773fn test() { (&S).foo(); } 737fn test() { (&S).foo(); }
774 //^ u128 738 //^^^^^^^^^^ u128
775"#, 739"#,
776 ); 740 );
777} 741}
@@ -784,7 +748,7 @@ fn method_resolution_unsize_array() {
784fn test() { 748fn test() {
785 let a = [1, 2, 3]; 749 let a = [1, 2, 3];
786 a.len(); 750 a.len();
787} //^ usize 751} //^^^^^^^ usize
788"#, 752"#,
789 ); 753 );
790} 754}
@@ -799,7 +763,7 @@ impl Clone for S {}
799 763
800fn test() { 764fn test() {
801 S.clone(); 765 S.clone();
802 //^ S 766 //^^^^^^^^^ S
803} 767}
804 768
805//- /lib.rs crate:core 769//- /lib.rs crate:core
@@ -823,7 +787,7 @@ trait Trait { fn foo(self) -> u128; }
823struct S; 787struct S;
824impl<T> Trait for T where T: UnknownTrait {} 788impl<T> Trait for T where T: UnknownTrait {}
825fn test() { (&S).foo(); } 789fn test() { (&S).foo(); }
826 //^ u128 790 //^^^^^^^^^^ u128
827"#, 791"#,
828 ); 792 );
829} 793}
@@ -841,7 +805,7 @@ trait Trait { fn foo(self) -> u128; }
841struct S; 805struct S;
842impl<T> Trait for T where T: Clone {} 806impl<T> Trait for T where T: Clone {}
843fn test() { (&S).foo(); } 807fn test() { (&S).foo(); }
844 //^ {unknown} 808 //^^^^^^^^^^ {unknown}
845"#, 809"#,
846 ); 810 );
847} 811}
@@ -856,7 +820,7 @@ trait Trait { fn foo(self) -> u128; }
856struct S; 820struct S;
857impl<T: Clone> Trait for T {} 821impl<T: Clone> Trait for T {}
858fn test() { (&S).foo(); } 822fn test() { (&S).foo(); }
859 //^ {unknown} 823 //^^^^^^^^^^ {unknown}
860"#, 824"#,
861 ); 825 );
862} 826}
@@ -871,7 +835,7 @@ struct S;
871impl Clone for S {} 835impl Clone for S {}
872impl<T> Trait for T where T: Clone {} 836impl<T> Trait for T where T: Clone {}
873fn test() { S.foo(); } 837fn test() { S.foo(); }
874 //^ u128 838 //^^^^^^^ u128
875"#, 839"#,
876 ); 840 );
877} 841}
@@ -887,7 +851,7 @@ struct S2;
887impl From<S2> for S1 {} 851impl From<S2> for S1 {}
888impl<T, U> Into<U> for T where U: From<T> {} 852impl<T, U> Into<U> for T where U: From<T> {}
889fn test() { S2.into(); } 853fn test() { S2.into(); }
890 //^ {unknown} 854 //^^^^^^^^^ {unknown}
891"#, 855"#,
892 ); 856 );
893} 857}
@@ -903,7 +867,7 @@ struct S2;
903impl From<S2> for S1 {} 867impl From<S2> for S1 {}
904impl<T, U: From<T>> Into<U> for T {} 868impl<T, U: From<T>> Into<U> for T {}
905fn test() { S2.into(); } 869fn test() { S2.into(); }
906 //^ {unknown} 870 //^^^^^^^^^ {unknown}
907"#, 871"#,
908 ); 872 );
909} 873}
@@ -933,7 +897,7 @@ fn main() {
933 let a = Wrapper::<Foo<f32>>::new(1.0); 897 let a = Wrapper::<Foo<f32>>::new(1.0);
934 let b = Wrapper::<Bar<f32>>::new(1.0); 898 let b = Wrapper::<Bar<f32>>::new(1.0);
935 (a, b); 899 (a, b);
936 //^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) 900 //^^^^^^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>)
937} 901}
938"#, 902"#,
939 ); 903 );
@@ -947,7 +911,7 @@ fn method_resolution_encountering_fn_type() {
947fn foo() {} 911fn foo() {}
948trait FnOnce { fn call(self); } 912trait FnOnce { fn call(self); }
949fn test() { foo.call(); } 913fn test() { foo.call(); }
950 //^ {unknown} 914 //^^^^^^^^^^ {unknown}
951"#, 915"#,
952 ); 916 );
953} 917}
@@ -1013,7 +977,7 @@ where
1013 Wrapper<T>: a::Foo, 977 Wrapper<T>: a::Foo,
1014{ 978{
1015 t.foo(); 979 t.foo();
1016} //^ {unknown} 980} //^^^^^^^ {unknown}
1017"#, 981"#,
1018 ); 982 );
1019} 983}
@@ -1030,7 +994,7 @@ impl A<i32> {
1030 994
1031fn main() { 995fn main() {
1032 A::from(3); 996 A::from(3);
1033} //^ A<i32> 997} //^^^^^^^^^^ A<i32>
1034"#, 998"#,
1035 ); 999 );
1036} 1000}
@@ -1058,7 +1022,7 @@ trait FnX {}
1058impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} 1022impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {}
1059 1023
1060fn test() { (S {}).method(); } 1024fn test() { (S {}).method(); }
1061 //^ () 1025 //^^^^^^^^^^^^^^^ ()
1062"#, 1026"#,
1063 ); 1027 );
1064} 1028}
@@ -1143,8 +1107,8 @@ impl<T> Slice<T> {
1143 1107
1144fn main() { 1108fn main() {
1145 let foo: Slice<u32>; 1109 let foo: Slice<u32>;
1146 (foo.into_vec()); // we don't actually support arbitrary self types, but we shouldn't crash at least 1110 foo.into_vec(); // we shouldn't crash on this at least
1147} //^ {unknown} 1111} //^^^^^^^^^^^^^^ {unknown}
1148"#, 1112"#,
1149 ); 1113 );
1150} 1114}
@@ -1165,7 +1129,7 @@ impl dyn Foo + '_ {
1165fn main() { 1129fn main() {
1166 let f = &42u32 as &dyn Foo; 1130 let f = &42u32 as &dyn Foo;
1167 f.dyn_foo(); 1131 f.dyn_foo();
1168 // ^u32 1132 // ^^^^^^^^^^^ u32
1169} 1133}
1170"#, 1134"#,
1171 ); 1135 );
@@ -1376,11 +1340,11 @@ pub trait IntoIterator {
1376 1340
1377impl<T> IntoIterator for [T; 1] { 1341impl<T> IntoIterator for [T; 1] {
1378 type Out = T; 1342 type Out = T;
1379 fn into_iter(self) -> Self::Out {} 1343 fn into_iter(self) -> Self::Out { loop {} }
1380} 1344}
1381impl<'a, T> IntoIterator for &'a [T] { 1345impl<'a, T> IntoIterator for &'a [T] {
1382 type Out = &'a T; 1346 type Out = &'a T;
1383 fn into_iter(self) -> Self::Out {} 1347 fn into_iter(self) -> Self::Out { loop {} }
1384} 1348}
1385 "#, 1349 "#,
1386 ); 1350 );
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index 5adbe9c45..47aa30d2e 100644
--- a/crates/hir_ty/src/tests/patterns.rs
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -1,6 +1,6 @@
1use expect_test::expect; 1use expect_test::expect;
2 2
3use super::{check_infer, check_infer_with_mismatches, check_mismatches, check_types}; 3use super::{check, check_infer, check_infer_with_mismatches, check_types};
4 4
5#[test] 5#[test]
6fn infer_pattern() { 6fn infer_pattern() {
@@ -518,7 +518,7 @@ fn infer_generics_in_patterns() {
518 518
519#[test] 519#[test]
520fn infer_const_pattern() { 520fn infer_const_pattern() {
521 check_mismatches( 521 check(
522 r#" 522 r#"
523enum Option<T> { None } 523enum Option<T> { None }
524use Option::None; 524use Option::None;
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index 0f418ea49..8c5e8954c 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -1,6 +1,6 @@
1use expect_test::expect; 1use expect_test::expect;
2 2
3use super::{check_infer, check_types}; 3use super::{check_infer, check_no_mismatches, check_types};
4 4
5#[test] 5#[test]
6fn bug_484() { 6fn bug_484() {
@@ -422,20 +422,20 @@ fn issue_2683_chars_impl() {
422pub struct Chars<'a> {} 422pub struct Chars<'a> {}
423impl<'a> Iterator for Chars<'a> { 423impl<'a> Iterator for Chars<'a> {
424 type Item = char; 424 type Item = char;
425 fn next(&mut self) -> Option<char> {} 425 fn next(&mut self) -> Option<char> { loop {} }
426} 426}
427 427
428fn test() { 428fn test() {
429 let chars: Chars<'_>; 429 let chars: Chars<'_>;
430 (chars.next(), chars.nth(1)); 430 (chars.next(), chars.nth(1));
431} //^ (Option<char>, Option<char>) 431} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (Option<char>, Option<char>)
432"#, 432"#,
433 ); 433 );
434} 434}
435 435
436#[test] 436#[test]
437fn issue_3642_bad_macro_stackover() { 437fn issue_3642_bad_macro_stackover() {
438 check_types( 438 check_no_mismatches(
439 r#" 439 r#"
440#[macro_export] 440#[macro_export]
441macro_rules! match_ast { 441macro_rules! match_ast {
@@ -452,7 +452,6 @@ macro_rules! match_ast {
452 452
453fn main() { 453fn main() {
454 let anchor = match_ast! { 454 let anchor = match_ast! {
455 //^ ()
456 match parent { 455 match parent {
457 as => {}, 456 as => {},
458 _ => return None 457 _ => return None
@@ -956,7 +955,7 @@ trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
956 955
957fn clone_iter<T>(s: Iter<T>) { 956fn clone_iter<T>(s: Iter<T>) {
958 s.inner.clone_box(); 957 s.inner.clone_box();
959 //^^^^^^^^^^^^^^^^^^^ () 958 //^^^^^^^^^^^^^^^^^^^ ()
960} 959}
961"#, 960"#,
962 ) 961 )
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 108ff3179..b4bcc6d95 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -60,7 +60,7 @@ enum Nat { Succ(Self), Demo(Nat), Zero }
60fn test() { 60fn test() {
61 let foo: Nat = Nat::Zero; 61 let foo: Nat = Nat::Zero;
62 if let Nat::Succ(x) = foo { 62 if let Nat::Succ(x) = foo {
63 x 63 x;
64 } //^ Nat 64 } //^ Nat
65} 65}
66"#, 66"#,
@@ -138,7 +138,7 @@ enum Option<T> { Some(T), None }
138fn test() { 138fn test() {
139 let foo: Option<f32> = None; 139 let foo: Option<f32> = None;
140 while let Option::Some(x) = foo { 140 while let Option::Some(x) = foo {
141 x 141 x;
142 } //^ f32 142 } //^ f32
143} 143}
144"#, 144"#,
@@ -1745,7 +1745,7 @@ impl i32 { fn foo(&self) -> Foo { Foo } }
1745fn main() { 1745fn main() {
1746 let x: i32 = i32; 1746 let x: i32 = i32;
1747 x.foo(); 1747 x.foo();
1748 //^ Foo 1748 //^^^^^^^ Foo
1749}"#, 1749}"#,
1750 ); 1750 );
1751} 1751}
@@ -1763,7 +1763,7 @@ fn main() {
1763 fn inner() {} 1763 fn inner() {}
1764 let x: i32 = i32; 1764 let x: i32 = i32;
1765 x.foo(); 1765 x.foo();
1766 //^ Foo 1766 //^^^^^^^ Foo
1767}"#, 1767}"#,
1768 ); 1768 );
1769} 1769}
@@ -1781,7 +1781,7 @@ fn foo() -> &'static str { "" }
1781 1781
1782fn main() { 1782fn main() {
1783 foo(); 1783 foo();
1784 //^ &str 1784 //^^^^^ &str
1785}"#, 1785}"#,
1786 ); 1786 );
1787} 1787}
@@ -1799,7 +1799,7 @@ fn foo() -> &'static str { "" }
1799 1799
1800fn main() { 1800fn main() {
1801 str::foo(); 1801 str::foo();
1802 //^ u32 1802 //^^^^^^^^^^ u32
1803}"#, 1803}"#,
1804 ); 1804 );
1805} 1805}
@@ -1825,9 +1825,9 @@ mod d {
1825 1825
1826fn main() { 1826fn main() {
1827 d::foo(); 1827 d::foo();
1828 //^ u8 1828 //^^^^^^^^ u8
1829 d::foo{a:0}; 1829 d::foo{a:0};
1830 //^ u8 1830 //^^^^^^^^^^^ foo
1831}"#, 1831}"#,
1832 ); 1832 );
1833} 1833}
@@ -2677,7 +2677,7 @@ fn prelude_2015() {
2677//- /main.rs edition:2015 crate:main deps:core 2677//- /main.rs edition:2015 crate:main deps:core
2678fn f() { 2678fn f() {
2679 Rust; 2679 Rust;
2680 //^ Rust 2680 //^^^^ Rust
2681} 2681}
2682 2682
2683//- /core.rs crate:core 2683//- /core.rs crate:core
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 279a1354a..a0ddad570 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -1,6 +1,7 @@
1use cov_mark::check;
1use expect_test::expect; 2use expect_test::expect;
2 3
3use super::{check_infer, check_infer_with_mismatches, check_types}; 4use super::{check, check_infer, check_infer_with_mismatches, check_types};
4 5
5#[test] 6#[test]
6fn infer_await() { 7fn infer_await() {
@@ -285,7 +286,7 @@ mod ops {
285 286
286#[test] 287#[test]
287fn infer_from_bound_1() { 288fn infer_from_bound_1() {
288 check_infer( 289 check_types(
289 r#" 290 r#"
290trait Trait<T> {} 291trait Trait<T> {}
291struct S<T>(T); 292struct S<T>(T);
@@ -293,99 +294,62 @@ impl<U> Trait<U> for S<U> {}
293fn foo<T: Trait<u32>>(t: T) {} 294fn foo<T: Trait<u32>>(t: T) {}
294fn test() { 295fn test() {
295 let s = S(unknown); 296 let s = S(unknown);
297 // ^^^^^^^ u32
296 foo(s); 298 foo(s);
297}"#, 299}"#,
298 expect![[r#"
299 85..86 't': T
300 91..93 '{}': ()
301 104..143 '{ ...(s); }': ()
302 114..115 's': S<u32>
303 118..119 'S': S<u32>(u32) -> S<u32>
304 118..128 'S(unknown)': S<u32>
305 120..127 'unknown': u32
306 134..137 'foo': fn foo<S<u32>>(S<u32>)
307 134..140 'foo(s)': ()
308 138..139 's': S<u32>
309 "#]],
310 ); 300 );
311} 301}
312 302
313#[test] 303#[test]
314fn infer_from_bound_2() { 304fn infer_from_bound_2() {
315 check_infer( 305 check_types(
316 r#" 306 r#"
317trait Trait<T> {} 307trait Trait<T> {}
318struct S<T>(T); 308struct S<T>(T);
319impl<U> Trait<U> for S<U> {} 309impl<U> Trait<U> for S<U> {}
320fn foo<U, T: Trait<U>>(t: T) -> U {} 310fn foo<U, T: Trait<U>>(t: T) -> U { loop {} }
321fn test() { 311fn test() {
322 let s = S(unknown); 312 let s = S(unknown);
313 // ^^^^^^^ u32
323 let x: u32 = foo(s); 314 let x: u32 = foo(s);
324}"#, 315}"#,
325 expect![[r#"
326 86..87 't': T
327 97..99 '{}': ()
328 110..162 '{ ...(s); }': ()
329 120..121 's': S<u32>
330 124..125 'S': S<u32>(u32) -> S<u32>
331 124..134 'S(unknown)': S<u32>
332 126..133 'unknown': u32
333 144..145 'x': u32
334 153..156 'foo': fn foo<u32, S<u32>>(S<u32>) -> u32
335 153..159 'foo(s)': u32
336 157..158 's': S<u32>
337 "#]],
338 ); 316 );
339} 317}
340 318
341#[test] 319#[test]
342fn trait_default_method_self_bound_implements_trait() { 320fn trait_default_method_self_bound_implements_trait() {
343 cov_mark::check!(trait_self_implements_self); 321 cov_mark::check!(trait_self_implements_self);
344 check_infer( 322 check(
345 r#" 323 r#"
346trait Trait { 324trait Trait {
347 fn foo(&self) -> i64; 325 fn foo(&self) -> i64;
348 fn bar(&self) -> { 326 fn bar(&self) -> () {
349 let x = self.foo(); 327 self.foo();
328 // ^^^^^^^^^^ type: i64
350 } 329 }
351}"#, 330}"#,
352 expect![[r#"
353 26..30 'self': &Self
354 52..56 'self': &Self
355 61..96 '{ ... }': ()
356 75..76 'x': i64
357 79..83 'self': &Self
358 79..89 'self.foo()': i64
359 "#]],
360 ); 331 );
361} 332}
362 333
363#[test] 334#[test]
364fn trait_default_method_self_bound_implements_super_trait() { 335fn trait_default_method_self_bound_implements_super_trait() {
365 check_infer( 336 check(
366 r#" 337 r#"
367trait SuperTrait { 338trait SuperTrait {
368 fn foo(&self) -> i64; 339 fn foo(&self) -> i64;
369} 340}
370trait Trait: SuperTrait { 341trait Trait: SuperTrait {
371 fn bar(&self) -> { 342 fn bar(&self) -> () {
372 let x = self.foo(); 343 self.foo();
344 // ^^^^^^^^^^ type: i64
373 } 345 }
374}"#, 346}"#,
375 expect![[r#"
376 31..35 'self': &Self
377 85..89 'self': &Self
378 94..129 '{ ... }': ()
379 108..109 'x': i64
380 112..116 'self': &Self
381 112..122 'self.foo()': i64
382 "#]],
383 ); 347 );
384} 348}
385 349
386#[test] 350#[test]
387fn infer_project_associated_type() { 351fn infer_project_associated_type() {
388 check_infer( 352 check_types(
389 r#" 353 r#"
390trait Iterable { 354trait Iterable {
391 type Item; 355 type Item;
@@ -394,89 +358,62 @@ struct S;
394impl Iterable for S { type Item = u32; } 358impl Iterable for S { type Item = u32; }
395fn test<T: Iterable>() { 359fn test<T: Iterable>() {
396 let x: <S as Iterable>::Item = 1; 360 let x: <S as Iterable>::Item = 1;
397 let y: <T as Iterable>::Item = no_matter; 361 // ^ u32
398 let z: T::Item = no_matter; 362 let y: <T as Iterable>::Item = u;
399 let a: <T>::Item = no_matter; 363 // ^ Iterable::Item<T>
364 let z: T::Item = u;
365 // ^ Iterable::Item<T>
366 let a: <T>::Item = u;
367 // ^ Iterable::Item<T>
400}"#, 368}"#,
401 expect![[r#"
402 108..261 '{ ...ter; }': ()
403 118..119 'x': u32
404 145..146 '1': u32
405 156..157 'y': Iterable::Item<T>
406 183..192 'no_matter': Iterable::Item<T>
407 202..203 'z': Iterable::Item<T>
408 215..224 'no_matter': Iterable::Item<T>
409 234..235 'a': Iterable::Item<T>
410 249..258 'no_matter': Iterable::Item<T>
411 "#]],
412 ); 369 );
413} 370}
414 371
415#[test] 372#[test]
416fn infer_return_associated_type() { 373fn infer_return_associated_type() {
417 check_infer( 374 check_types(
418 r#" 375 r#"
419trait Iterable { 376trait Iterable {
420 type Item; 377 type Item;
421} 378}
422struct S; 379struct S;
423impl Iterable for S { type Item = u32; } 380impl Iterable for S { type Item = u32; }
424fn foo1<T: Iterable>(t: T) -> T::Item {} 381fn foo1<T: Iterable>(t: T) -> T::Item { loop {} }
425fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} 382fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item { loop {} }
426fn foo3<T: Iterable>(t: T) -> <T>::Item {} 383fn foo3<T: Iterable>(t: T) -> <T>::Item { loop {} }
427fn test() { 384fn test() {
428 let x = foo1(S); 385 foo1(S);
429 let y = foo2(S); 386 // ^^^^^^^ u32
430 let z = foo3(S); 387 foo2(S);
388 // ^^^^^^^ u32
389 foo3(S);
390 // ^^^^^^^ u32
431}"#, 391}"#,
432 expect![[r#"
433 106..107 't': T
434 123..125 '{}': ()
435 147..148 't': T
436 178..180 '{}': ()
437 202..203 't': T
438 221..223 '{}': ()
439 234..300 '{ ...(S); }': ()
440 244..245 'x': u32
441 248..252 'foo1': fn foo1<S>(S) -> <S as Iterable>::Item
442 248..255 'foo1(S)': u32
443 253..254 'S': S
444 265..266 'y': u32
445 269..273 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item
446 269..276 'foo2(S)': u32
447 274..275 'S': S
448 286..287 'z': u32
449 290..294 'foo3': fn foo3<S>(S) -> <S as Iterable>::Item
450 290..297 'foo3(S)': u32
451 295..296 'S': S
452 "#]],
453 ); 392 );
454} 393}
455 394
456#[test] 395#[test]
457fn infer_associated_type_bound() { 396fn infer_associated_type_bound() {
458 check_infer( 397 check_types(
459 r#" 398 r#"
460trait Iterable { 399trait Iterable {
461 type Item; 400 type Item;
462} 401}
463fn test<T: Iterable<Item=u32>>() { 402fn test<T: Iterable<Item=u32>>() {
464 let y: T::Item = unknown; 403 let y: T::Item = unknown;
404 // ^^^^^^^ u32
465}"#, 405}"#,
466 expect![[r#"
467 67..100 '{ ...own; }': ()
468 77..78 'y': u32
469 90..97 'unknown': u32
470 "#]],
471 ); 406 );
472} 407}
473 408
474#[test] 409#[test]
475fn infer_const_body() { 410fn infer_const_body() {
411 // FIXME make check_types work with other bodies
476 check_infer( 412 check_infer(
477 r#" 413 r#"
478const A: u32 = 1 + 1; 414const A: u32 = 1 + 1;
479static B: u64 = { let x = 1; x };"#, 415static B: u64 = { let x = 1; x };
416"#,
480 expect![[r#" 417 expect![[r#"
481 15..16 '1': u32 418 15..16 '1': u32
482 15..20 '1 + 1': u32 419 15..20 '1 + 1': u32
@@ -637,12 +574,12 @@ impl<T> core::ops::Deref for Arc<T> {
637 574
638struct S; 575struct S;
639impl S { 576impl S {
640 fn foo(&self) -> u128 {} 577 fn foo(&self) -> u128 { 0 }
641} 578}
642 579
643fn test(s: Arc<S>) { 580fn test(s: Arc<S>) {
644 (*s, s.foo()); 581 (*s, s.foo());
645} //^ (S, u128) 582} //^^^^^^^^^^^^^ (S, u128)
646"#, 583"#,
647 ); 584 );
648} 585}
@@ -653,7 +590,7 @@ fn deref_trait_with_inference_var() {
653 r#" 590 r#"
654//- minicore: deref 591//- minicore: deref
655struct Arc<T>; 592struct Arc<T>;
656fn new_arc<T>() -> Arc<T> {} 593fn new_arc<T>() -> Arc<T> { Arc }
657impl<T> core::ops::Deref for Arc<T> { 594impl<T> core::ops::Deref for Arc<T> {
658 type Target = T; 595 type Target = T;
659} 596}
@@ -663,8 +600,8 @@ fn foo(a: Arc<S>) {}
663 600
664fn test() { 601fn test() {
665 let a = new_arc(); 602 let a = new_arc();
666 let b = (*a); 603 let b = *a;
667 //^ S 604 //^^ S
668 foo(a); 605 foo(a);
669} 606}
670"#, 607"#,
@@ -684,7 +621,7 @@ impl core::ops::Deref for S {
684 621
685fn test(s: S) { 622fn test(s: S) {
686 s.foo(); 623 s.foo();
687} //^ {unknown} 624} //^^^^^^^ {unknown}
688"#, 625"#,
689 ); 626 );
690} 627}
@@ -701,12 +638,12 @@ impl<T: ?Sized> core::ops::Deref for Arc<T> {
701 638
702struct S; 639struct S;
703impl S { 640impl S {
704 fn foo(&self) -> u128 {} 641 fn foo(&self) -> u128 { 0 }
705} 642}
706 643
707fn test(s: Arc<S>) { 644fn test(s: Arc<S>) {
708 (*s, s.foo()); 645 (*s, s.foo());
709} //^ (S, u128) 646} //^^^^^^^^^^^^^ (S, u128)
710"#, 647"#,
711 ); 648 );
712} 649}
@@ -720,11 +657,11 @@ struct S;
720trait Trait<T> {} 657trait Trait<T> {}
721impl Trait<u32> for S {} 658impl Trait<u32> for S {}
722 659
723fn foo<T: Trait<U>, U>(t: T) -> U {} 660fn foo<T: Trait<U>, U>(t: T) -> U { loop {} }
724 661
725fn test(s: S) { 662fn test(s: S) {
726 (foo(s)); 663 foo(s);
727} //^ u32 664} //^^^^^^ u32
728"#, 665"#,
729 ); 666 );
730} 667}
@@ -741,12 +678,12 @@ impl Trait<isize> for S {}
741 678
742struct O; 679struct O;
743impl O { 680impl O {
744 fn foo<T: Trait<U>, U>(&self, t: T) -> U {} 681 fn foo<T: Trait<U>, U>(&self, t: T) -> U { loop {} }
745} 682}
746 683
747fn test() { 684fn test() {
748 O.foo(S); 685 O.foo(S);
749} //^ isize 686} //^^^^^^^^ isize
750"#, 687"#,
751 ); 688 );
752} 689}
@@ -761,12 +698,12 @@ trait Trait<T> {}
761impl Trait<i64> for S {} 698impl Trait<i64> for S {}
762 699
763impl S { 700impl S {
764 fn foo<U>(&self) -> U where Self: Trait<U> {} 701 fn foo<U>(&self) -> U where Self: Trait<U> { loop {} }
765} 702}
766 703
767fn test() { 704fn test() {
768 S.foo(); 705 S.foo();
769} //^ i64 706} //^^^^^^^ i64
770"#, 707"#,
771 ); 708 );
772} 709}
@@ -782,12 +719,12 @@ impl Trait<&str> for S {}
782 719
783struct O<T>; 720struct O<T>;
784impl<U, T: Trait<U>> O<T> { 721impl<U, T: Trait<U>> O<T> {
785 fn foo(&self) -> U {} 722 fn foo(&self) -> U { loop {} }
786} 723}
787 724
788fn test(o: O<S>) { 725fn test(o: O<S>) {
789 o.foo(); 726 o.foo();
790} //^ &str 727} //^^^^^^^ &str
791"#, 728"#,
792 ); 729 );
793} 730}
@@ -802,7 +739,7 @@ struct S;
802impl Clone for S {} 739impl Clone for S {}
803impl<T> Trait for T where T: Clone {} 740impl<T> Trait for T where T: Clone {}
804fn test<T: Clone>(t: T) { t.foo(); } 741fn test<T: Clone>(t: T) { t.foo(); }
805 //^ u128 742 //^^^^^^^ u128
806"#, 743"#,
807 ); 744 );
808} 745}
@@ -818,7 +755,7 @@ struct S;
818impl Clone for S {} 755impl Clone for S {}
819impl<T> Trait for T where T: Clone {} 756impl<T> Trait for T where T: Clone {}
820fn test<T>(t: T) { t.foo(); } 757fn test<T>(t: T) { t.foo(); }
821 //^ {unknown} 758 //^^^^^^^ {unknown}
822"#, 759"#,
823 ); 760 );
824} 761}
@@ -831,7 +768,7 @@ trait Trait { fn foo(self) -> u128; }
831struct S; 768struct S;
832impl Trait for S {} 769impl Trait for S {}
833fn test<T: Trait>(t: T) { t.foo(); } 770fn test<T: Trait>(t: T) { t.foo(); }
834 //^ u128 771 //^^^^^^^ u128
835"#, 772"#,
836 ); 773 );
837} 774}
@@ -844,7 +781,7 @@ trait Trait { fn foo(self) -> u128; }
844struct S; 781struct S;
845impl Trait for S {} 782impl Trait for S {}
846fn test<T>(t: T) { t.foo(); } 783fn test<T>(t: T) { t.foo(); }
847 //^ {unknown} 784 //^^^^^^^ {unknown}
848"#, 785"#,
849 ); 786 );
850} 787}
@@ -858,8 +795,8 @@ trait Trait {}
858impl<T> core::ops::Deref for T where T: Trait { 795impl<T> core::ops::Deref for T where T: Trait {
859 type Target = i128; 796 type Target = i128;
860} 797}
861fn test<T: Trait>(t: T) { (*t); } 798fn test<T: Trait>(t: T) { *t; }
862 //^ i128 799 //^^ i128
863"#, 800"#,
864 ); 801 );
865} 802}
@@ -1380,12 +1317,12 @@ fn error_bound_chalk() {
1380 check_types( 1317 check_types(
1381 r#" 1318 r#"
1382trait Trait { 1319trait Trait {
1383 fn foo(&self) -> u32 {} 1320 fn foo(&self) -> u32 { 0 }
1384} 1321}
1385 1322
1386fn test(x: (impl Trait + UnknownTrait)) { 1323fn test(x: (impl Trait + UnknownTrait)) {
1387 x.foo(); 1324 x.foo();
1388} //^ u32 1325} //^^^^^^^ u32
1389"#, 1326"#,
1390 ); 1327 );
1391} 1328}
@@ -1476,7 +1413,7 @@ trait Clone {
1476fn api_walkthrough() { 1413fn api_walkthrough() {
1477 for node in foo() { 1414 for node in foo() {
1478 node.clone(); 1415 node.clone();
1479 } //^ {unknown} 1416 } //^^^^^^^^^^^^ {unknown}
1480} 1417}
1481"#, 1418"#,
1482 ); 1419 );
@@ -1513,13 +1450,13 @@ fn where_clause_trait_in_scope_for_method_resolution() {
1513 r#" 1450 r#"
1514mod foo { 1451mod foo {
1515 trait Trait { 1452 trait Trait {
1516 fn foo(&self) -> u32 {} 1453 fn foo(&self) -> u32 { 0 }
1517 } 1454 }
1518} 1455}
1519 1456
1520fn test<T: foo::Trait>(x: T) { 1457fn test<T: foo::Trait>(x: T) {
1521 x.foo(); 1458 x.foo();
1522} //^ u32 1459} //^^^^^^^ u32
1523"#, 1460"#,
1524 ); 1461 );
1525} 1462}
@@ -1982,7 +1919,7 @@ fn fn_item_fn_trait() {
1982//- minicore: fn 1919//- minicore: fn
1983struct S; 1920struct S;
1984 1921
1985fn foo() -> S {} 1922fn foo() -> S { S }
1986 1923
1987fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } 1924fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() }
1988 1925
@@ -2009,7 +1946,7 @@ trait Trait2 {
2009fn test<T: Trait>() where T::Item: Trait2 { 1946fn test<T: Trait>() where T::Item: Trait2 {
2010 let x: T::Item = no_matter; 1947 let x: T::Item = no_matter;
2011 x.foo(); 1948 x.foo();
2012} //^ u32 1949} //^^^^^^^ u32
2013"#, 1950"#,
2014 ); 1951 );
2015} 1952}
@@ -2029,7 +1966,7 @@ trait Trait2 {
2029fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { 1966fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
2030 let x: T::Item = no_matter; 1967 let x: T::Item = no_matter;
2031 x.foo(); 1968 x.foo();
2032} //^ u32 1969} //^^^^^^^ u32
2033"#, 1970"#,
2034 ); 1971 );
2035} 1972}
@@ -2092,7 +2029,7 @@ impl Trait for S {
2092 2029
2093fn test() { 2030fn test() {
2094 S.f(); 2031 S.f();
2095} //^ u32 2032} //^^^^^ u32
2096"#, 2033"#,
2097 ); 2034 );
2098} 2035}
@@ -2120,7 +2057,7 @@ where
2120 2057
2121fn foo<I: Interner>(interner: &I, t: Ty<I>) { 2058fn foo<I: Interner>(interner: &I, t: Ty<I>) {
2122 fold(interner, t); 2059 fold(interner, t);
2123} //^ Ty<I> 2060} //^^^^^^^^^^^^^^^^^ Ty<I>
2124"#, 2061"#,
2125 ); 2062 );
2126} 2063}
@@ -2139,7 +2076,7 @@ impl Trait<Self> for S {}
2139 2076
2140fn test() { 2077fn test() {
2141 S.foo(); 2078 S.foo();
2142} //^ () 2079} //^^^^^^^ ()
2143"#, 2080"#,
2144 ); 2081 );
2145} 2082}
@@ -2158,7 +2095,7 @@ impl Trait for S<Self> {}
2158 2095
2159fn test() { 2096fn test() {
2160 S.foo(); 2097 S.foo();
2161} //^ {unknown} 2098} //^^^^^^^ {unknown}
2162"#, 2099"#,
2163 ); 2100 );
2164} 2101}
@@ -2176,7 +2113,7 @@ trait Trait2<T> {}
2176 2113
2177fn test<T: Trait>() where T: Trait2<T::Item> { 2114fn test<T: Trait>() where T: Trait2<T::Item> {
2178 let x: T::Item = no_matter; 2115 let x: T::Item = no_matter;
2179} //^ {unknown} 2116} //^^^^^^^^^ {unknown}
2180"#, 2117"#,
2181 ); 2118 );
2182} 2119}
@@ -2193,7 +2130,7 @@ trait Trait<T> {
2193 2130
2194fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { 2131fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
2195 let x: T::Item = no_matter; 2132 let x: T::Item = no_matter;
2196} //^ {unknown} 2133} //^^^^^^^^^ {unknown}
2197"#, 2134"#,
2198 ); 2135 );
2199} 2136}
@@ -2211,7 +2148,7 @@ trait Trait {
2211 2148
2212fn test<T>() where T: Trait<OtherItem = T::Item> { 2149fn test<T>() where T: Trait<OtherItem = T::Item> {
2213 let x: T::Item = no_matter; 2150 let x: T::Item = no_matter;
2214} //^ Trait::Item<T> 2151} //^^^^^^^^^ Trait::Item<T>
2215"#, 2152"#,
2216 ); 2153 );
2217} 2154}
@@ -2243,7 +2180,7 @@ fn test<T>(t: T) where T: UnificationStoreMut {
2243 t.push(x); 2180 t.push(x);
2244 let y: Key<T>; 2181 let y: Key<T>;
2245 (x, y); 2182 (x, y);
2246} //^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) 2183} //^^^^^^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>)
2247"#, 2184"#,
2248 ); 2185 );
2249} 2186}
@@ -2268,7 +2205,7 @@ impl<T: Iterator> Iterator for S<T> {
2268fn test<I: Iterator<Item: OtherTrait<u32>>>() { 2205fn test<I: Iterator<Item: OtherTrait<u32>>>() {
2269 let x: <S<I> as Iterator>::Item; 2206 let x: <S<I> as Iterator>::Item;
2270 x.foo(); 2207 x.foo();
2271} //^ u32 2208} //^^^^^^^ u32
2272"#, 2209"#,
2273 ); 2210 );
2274} 2211}
@@ -2470,7 +2407,7 @@ impl<T: Trait> Trait for S<T> {
2470fn test<T: Trait>() { 2407fn test<T: Trait>() {
2471 let y: <S<T> as Trait>::Item = no_matter; 2408 let y: <S<T> as Trait>::Item = no_matter;
2472 y.foo(); 2409 y.foo();
2473} //^ u32 2410} //^^^^^^^ u32
2474"#, 2411"#,
2475 ); 2412 );
2476} 2413}
@@ -2490,7 +2427,7 @@ trait Trait {
2490 2427
2491fn test(x: Box<dyn Trait>) { 2428fn test(x: Box<dyn Trait>) {
2492 x.foo(); 2429 x.foo();
2493} //^ () 2430} //^^^^^^^ ()
2494"#, 2431"#,
2495 ); 2432 );
2496} 2433}
@@ -2509,7 +2446,7 @@ impl ToOwned for str {
2509} 2446}
2510fn test() { 2447fn test() {
2511 "foo".to_owned(); 2448 "foo".to_owned();
2512} //^ String 2449} //^^^^^^^^^^^^^^^^ String
2513"#, 2450"#,
2514 ); 2451 );
2515} 2452}
@@ -2649,7 +2586,7 @@ impl<T:A> B for T {
2649 2586
2650fn main() { 2587fn main() {
2651 Bar::foo(); 2588 Bar::foo();
2652} //^ Foo 2589} //^^^^^^^^^^ Foo
2653"#, 2590"#,
2654 ); 2591 );
2655} 2592}
@@ -3002,7 +2939,7 @@ fn test() {
3002 S.get(1); 2939 S.get(1);
3003 //^^^^^^^^ u128 2940 //^^^^^^^^ u128
3004 S.get(1.); 2941 S.get(1.);
3005 //^^^^^^^^ f32 2942 //^^^^^^^^^ f32
3006} 2943}
3007 "#, 2944 "#,
3008 ); 2945 );
@@ -3477,14 +3414,12 @@ trait Convert {
3477 fn new() -> Self; 3414 fn new() -> Self;
3478} 3415}
3479impl Convert for u32 { 3416impl Convert for u32 {
3480 fn new() -> Self { 3417 fn new() -> Self { 0 }
3481 0
3482 }
3483} 3418}
3484 3419
3485async fn get_accounts() -> Result<u32, ()> { 3420async fn get_accounts() -> Result<u32, ()> {
3486 let ret = Fooey.collect(); 3421 let ret = Fooey.collect();
3487 // ^ u32 3422 // ^^^^^^^^^^^^^^^ u32
3488 Ok(ret) 3423 Ok(ret)
3489} 3424}
3490"#, 3425"#,
@@ -3493,6 +3428,7 @@ async fn get_accounts() -> Result<u32, ()> {
3493 3428
3494#[test] 3429#[test]
3495fn local_impl_1() { 3430fn local_impl_1() {
3431 check!(block_local_impls);
3496 check_types( 3432 check_types(
3497 r#" 3433 r#"
3498trait Trait<T> { 3434trait Trait<T> {
@@ -3502,7 +3438,7 @@ trait Trait<T> {
3502fn test() { 3438fn test() {
3503 struct S; 3439 struct S;
3504 impl Trait<u32> for S { 3440 impl Trait<u32> for S {
3505 fn foo(&self) { 0 } 3441 fn foo(&self) -> u32 { 0 }
3506 } 3442 }
3507 3443
3508 S.foo(); 3444 S.foo();
@@ -3514,6 +3450,7 @@ fn test() {
3514 3450
3515#[test] 3451#[test]
3516fn local_impl_2() { 3452fn local_impl_2() {
3453 check!(block_local_impls);
3517 check_types( 3454 check_types(
3518 r#" 3455 r#"
3519struct S; 3456struct S;
@@ -3523,7 +3460,7 @@ fn test() {
3523 fn foo(&self) -> T; 3460 fn foo(&self) -> T;
3524 } 3461 }
3525 impl Trait<u32> for S { 3462 impl Trait<u32> for S {
3526 fn foo(&self) { 0 } 3463 fn foo(&self) -> u32 { 0 }
3527 } 3464 }
3528 3465
3529 S.foo(); 3466 S.foo();
@@ -3535,6 +3472,7 @@ fn test() {
3535 3472
3536#[test] 3473#[test]
3537fn local_impl_3() { 3474fn local_impl_3() {
3475 check!(block_local_impls);
3538 check_types( 3476 check_types(
3539 r#" 3477 r#"
3540trait Trait<T> { 3478trait Trait<T> {
@@ -3547,7 +3485,7 @@ fn test() {
3547 struct S2; 3485 struct S2;
3548 3486
3549 impl Trait<S1> for S2 { 3487 impl Trait<S1> for S2 {
3550 fn foo(&self) { S1 } 3488 fn foo(&self) -> S1 { S1 }
3551 } 3489 }
3552 3490
3553 S2.foo(); 3491 S2.foo();
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 0013820b4..07686017d 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -236,15 +236,10 @@ impl T for &Foo {}
236 fn goto_implementation_to_builtin_derive() { 236 fn goto_implementation_to_builtin_derive() {
237 check( 237 check(
238 r#" 238 r#"
239//- minicore: copy, derive
239 #[derive(Copy)] 240 #[derive(Copy)]
240//^^^^^^^^^^^^^^^ 241//^^^^^^^^^^^^^^^
241struct Foo$0; 242struct Foo$0;
242
243mod marker {
244 trait Copy {}
245}
246#[rustc_builtin_macro]
247macro Copy {}
248"#, 243"#,
249 ); 244 );
250 } 245 }
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 05a2b1293..2e1359eef 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -2258,7 +2258,7 @@ pub fn fo$0o() {}
2258 case 13. collapsed link: foo 2258 case 13. collapsed link: foo
2259 case 14. shortcut link: foo 2259 case 14. shortcut link: foo
2260 case 15. inline without URL: foo 2260 case 15. inline without URL: foo
2261 case 16. just escaped text: \[foo] 2261 case 16. just escaped text: \[foo\]
2262 case 17. inline link: Foo 2262 case 17. inline link: Foo
2263 2263
2264 [^example]: https://www.example.com/ 2264 [^example]: https://www.example.com/
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 8096dfa0e..96bd07708 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -10,7 +10,7 @@ use ide_db::{
10 rename::{bail, format_err, source_edit_from_references, IdentifierKind}, 10 rename::{bail, format_err, source_edit_from_references, IdentifierKind},
11 RootDatabase, 11 RootDatabase,
12}; 12};
13use stdx::never; 13use stdx::{always, never};
14use syntax::{ast, AstNode, SyntaxNode}; 14use syntax::{ast, AstNode, SyntaxNode};
15 15
16use text_edit::TextEdit; 16use text_edit::TextEdit;
@@ -31,10 +31,13 @@ pub(crate) fn prepare_rename(
31 let source_file = sema.parse(position.file_id); 31 let source_file = sema.parse(position.file_id);
32 let syntax = source_file.syntax(); 32 let syntax = source_file.syntax();
33 33
34 let def = find_definition(&sema, syntax, position)?; 34 let (name_like, def) = find_definition(&sema, syntax, position)?;
35 let frange = def 35 if def.range_for_rename(&sema).is_none() {
36 .range_for_rename(&sema) 36 bail!("No references found at position")
37 .ok_or_else(|| format_err!("No references found at position"))?; 37 }
38
39 let frange = sema.original_range(name_like.syntax());
40 always!(frange.range.contains_inclusive(position.offset) && frange.file_id == position.file_id);
38 Ok(RangeInfo::new(frange.range, ())) 41 Ok(RangeInfo::new(frange.range, ()))
39} 42}
40 43
@@ -55,31 +58,23 @@ pub(crate) fn rename(
55 new_name: &str, 58 new_name: &str,
56) -> RenameResult<SourceChange> { 59) -> RenameResult<SourceChange> {
57 let sema = Semantics::new(db); 60 let sema = Semantics::new(db);
58 rename_with_semantics(&sema, position, new_name)
59}
60
61pub(crate) fn rename_with_semantics(
62 sema: &Semantics<RootDatabase>,
63 position: FilePosition,
64 new_name: &str,
65) -> RenameResult<SourceChange> {
66 let source_file = sema.parse(position.file_id); 61 let source_file = sema.parse(position.file_id);
67 let syntax = source_file.syntax(); 62 let syntax = source_file.syntax();
68 63
69 let def = find_definition(sema, syntax, position)?; 64 let (_name_like, def) = find_definition(&sema, syntax, position)?;
70 65
71 if let Definition::Local(local) = def { 66 if let Definition::Local(local) = def {
72 if let Some(self_param) = local.as_self_param(sema.db) { 67 if let Some(self_param) = local.as_self_param(sema.db) {
73 cov_mark::hit!(rename_self_to_param); 68 cov_mark::hit!(rename_self_to_param);
74 return rename_self_to_param(sema, local, self_param, new_name); 69 return rename_self_to_param(&sema, local, self_param, new_name);
75 } 70 }
76 if new_name == "self" { 71 if new_name == "self" {
77 cov_mark::hit!(rename_to_self); 72 cov_mark::hit!(rename_to_self);
78 return rename_to_self(sema, local); 73 return rename_to_self(&sema, local);
79 } 74 }
80 } 75 }
81 76
82 def.rename(sema, new_name) 77 def.rename(&sema, new_name)
83} 78}
84 79
85/// Called by the client when it is about to rename a file. 80/// Called by the client when it is about to rename a file.
@@ -100,11 +95,12 @@ fn find_definition(
100 sema: &Semantics<RootDatabase>, 95 sema: &Semantics<RootDatabase>,
101 syntax: &SyntaxNode, 96 syntax: &SyntaxNode,
102 position: FilePosition, 97 position: FilePosition,
103) -> RenameResult<Definition> { 98) -> RenameResult<(ast::NameLike, Definition)> {
104 match sema 99 let name_like = sema
105 .find_node_at_offset_with_descend(syntax, position.offset) 100 .find_node_at_offset_with_descend::<ast::NameLike>(syntax, position.offset)
106 .ok_or_else(|| format_err!("No references found at position"))? 101 .ok_or_else(|| format_err!("No references found at position"))?;
107 { 102
103 let def = match &name_like {
108 // renaming aliases would rename the item being aliased as the HIR doesn't track aliases yet 104 // renaming aliases would rename the item being aliased as the HIR doesn't track aliases yet
109 ast::NameLike::Name(name) 105 ast::NameLike::Name(name)
110 if name.syntax().parent().map_or(false, |it| ast::Rename::can_cast(it.kind())) => 106 if name.syntax().parent().map_or(false, |it| ast::Rename::can_cast(it.kind())) =>
@@ -134,7 +130,9 @@ fn find_definition(
134 .map(|it| it.referenced_or_defined(sema.db)) 130 .map(|it| it.referenced_or_defined(sema.db))
135 }), 131 }),
136 } 132 }
137 .ok_or_else(|| format_err!("No references found at position")) 133 .ok_or_else(|| format_err!("No references found at position"))?;
134
135 Ok((name_like, def))
138} 136}
139 137
140fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> { 138fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> {
@@ -328,7 +326,7 @@ mod tests {
328 fn test_prepare_rename_namelikes() { 326 fn test_prepare_rename_namelikes() {
329 check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]); 327 check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]);
330 check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]); 328 check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]);
331 check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"3..7: name"#]]); 329 check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]);
332 } 330 }
333 331
334 #[test] 332 #[test]
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index 4ad49eca0..37ae92350 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -23,7 +23,7 @@ use syntax::{
23 algo::find_node_at_offset, 23 algo::find_node_at_offset,
24 ast::{self, edit::IndentLevel, AstToken}, 24 ast::{self, edit::IndentLevel, AstToken},
25 AstNode, Parse, SourceFile, 25 AstNode, Parse, SourceFile,
26 SyntaxKind::{FIELD_EXPR, METHOD_CALL_EXPR}, 26 SyntaxKind::{self, FIELD_EXPR, METHOD_CALL_EXPR},
27 TextRange, TextSize, 27 TextRange, TextSize,
28}; 28};
29 29
@@ -95,9 +95,16 @@ fn on_opening_brace_typed(file: &Parse<SourceFile>, offset: TextSize) -> Option<
95 } 95 }
96 96
97 let brace_token = file.tree().syntax().token_at_offset(offset).right_biased()?; 97 let brace_token = file.tree().syntax().token_at_offset(offset).right_biased()?;
98 if brace_token.kind() != SyntaxKind::L_CURLY {
99 return None;
100 }
98 101
99 // Remove the `{` to get a better parse tree, and reparse 102 // Remove the `{` to get a better parse tree, and reparse.
100 let file = file.reparse(&Indel::delete(brace_token.text_range())); 103 let range = brace_token.text_range();
104 if !stdx::always!(range.len() == TextSize::of('{')) {
105 return None;
106 }
107 let file = file.reparse(&Indel::delete(range));
101 108
102 if let Some(edit) = brace_expr(&file.tree(), offset) { 109 if let Some(edit) = brace_expr(&file.tree(), offset) {
103 return Some(edit); 110 return Some(edit);
@@ -550,6 +557,29 @@ fn f() {
550 } 557 }
551 558
552 #[test] 559 #[test]
560 fn noop_in_string_literal() {
561 // Regression test for #9351
562 type_char_noop(
563 '{',
564 r##"
565fn check_with(ra_fixture: &str, expect: Expect) {
566 let base = r#"
567enum E { T(), R$0, C }
568use self::E::X;
569const Z: E = E::C;
570mod m {}
571asdasdasdasdasdasda
572sdasdasdasdasdasda
573sdasdasdasdasd
574"#;
575 let actual = completion_list(&format!("{}\n{}", base, ra_fixture));
576 expect.assert_eq(&actual)
577}
578 "##,
579 );
580 }
581
582 #[test]
553 fn adds_closing_brace_for_use_tree() { 583 fn adds_closing_brace_for_use_tree() {
554 type_char( 584 type_char(
555 '{', 585 '{',
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index 8df8b060d..accc345fc 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -995,62 +995,4 @@ const _: () = {
995"#, 995"#,
996 ); 996 );
997 } 997 }
998
999 #[test]
1000 fn respects_cfg_attr() {
1001 check_assist(
1002 auto_import,
1003 r#"
1004mod bar {
1005 pub struct Bar;
1006}
1007
1008#[cfg(test)]
1009fn foo() {
1010 Bar$0
1011}
1012"#,
1013 r#"
1014mod bar {
1015 pub struct Bar;
1016}
1017
1018#[cfg(test)]
1019fn foo() {
1020use bar::Bar;
1021
1022 Bar
1023}
1024"#,
1025 );
1026 }
1027
1028 #[test]
1029 fn respects_cfg_attr2() {
1030 check_assist(
1031 auto_import,
1032 r#"
1033mod bar {
1034 pub struct Bar;
1035}
1036
1037#[cfg(test)]
1038const FOO: Bar = {
1039 Bar$0
1040}
1041"#,
1042 r#"
1043mod bar {
1044 pub struct Bar;
1045}
1046
1047#[cfg(test)]
1048const FOO: Bar = {
1049use bar::Bar;
1050
1051 Bar
1052}
1053"#,
1054 );
1055 }
1056} 998}
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 07541c79c..407f796ef 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -92,7 +92,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
92 } 92 }
93 93
94 if !ctx.has_visibility_prev_sibling() 94 if !ctx.has_visibility_prev_sibling()
95 && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field()) 95 && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
96 { 96 {
97 add_keyword("pub(crate)", "pub(crate) "); 97 add_keyword("pub(crate)", "pub(crate) ");
98 add_keyword("pub", "pub "); 98 add_keyword("pub", "pub ");
@@ -122,6 +122,10 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
122 add_keyword("union", "union $1 {\n $0\n}"); 122 add_keyword("union", "union $1 {\n $0\n}");
123 } 123 }
124 124
125 if ctx.expects_type() {
126 return;
127 }
128
125 if ctx.expects_expression() { 129 if ctx.expects_expression() {
126 if !has_block_expr_parent { 130 if !has_block_expr_parent {
127 add_keyword("unsafe", "unsafe {\n $0\n}"); 131 add_keyword("unsafe", "unsafe {\n $0\n}");
@@ -373,28 +377,6 @@ fn quux() -> i32 {
373 } 377 }
374 378
375 #[test] 379 #[test]
376 fn test_mut_in_ref_and_in_fn_parameters_list() {
377 check(
378 r"fn my_fn(&$0) {}",
379 expect![[r#"
380 kw mut
381 "#]],
382 );
383 check(
384 r"fn my_fn($0) {}",
385 expect![[r#"
386 kw mut
387 "#]],
388 );
389 check(
390 r"fn my_fn() { let &$0 }",
391 expect![[r#"
392 kw mut
393 "#]],
394 );
395 }
396
397 #[test]
398 fn no_keyword_completion_in_comments() { 380 fn no_keyword_completion_in_comments() {
399 cov_mark::check!(no_keyword_completion_in_comments); 381 cov_mark::check!(no_keyword_completion_in_comments);
400 check( 382 check(
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs
index efe3c957a..bd13a62d7 100644
--- a/crates/ide_completion/src/completions/pattern.rs
+++ b/crates/ide_completion/src/completions/pattern.rs
@@ -55,398 +55,3 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
55 } 55 }
56 }); 56 });
57} 57}
58
59#[cfg(test)]
60mod tests {
61 use expect_test::{expect, Expect};
62
63 use crate::{
64 tests::{check_edit, filtered_completion_list},
65 CompletionKind,
66 };
67
68 fn check(ra_fixture: &str, expect: Expect) {
69 let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference);
70 expect.assert_eq(&actual)
71 }
72
73 fn check_snippet(ra_fixture: &str, expect: Expect) {
74 let actual = filtered_completion_list(ra_fixture, CompletionKind::Snippet);
75 expect.assert_eq(&actual)
76 }
77
78 #[test]
79 fn completes_enum_variants_and_modules() {
80 check(
81 r#"
82enum E { X }
83use self::E::X;
84const Z: E = E::X;
85mod m {}
86
87static FOO: E = E::X;
88struct Bar { f: u32 }
89
90fn foo() {
91 match E::X { a$0 }
92}
93"#,
94 expect![[r#"
95 en E
96 ct Z
97 st Bar
98 ev X
99 md m
100 "#]],
101 );
102 }
103
104 #[test]
105 fn does_not_complete_non_fn_macros() {
106 check(
107 r#"
108macro_rules! m { ($e:expr) => { $e } }
109enum E { X }
110
111#[rustc_builtin_macro]
112macro Clone {}
113
114fn foo() {
115 match E::X { $0 }
116}
117"#,
118 expect![[r#"
119 ev E::X ()
120 en E
121 ma m!(…) macro_rules! m
122 "#]],
123 );
124 }
125
126 #[test]
127 fn completes_in_simple_macro_call() {
128 check(
129 r#"
130macro_rules! m { ($e:expr) => { $e } }
131enum E { X }
132
133fn foo() {
134 m!(match E::X { a$0 })
135}
136"#,
137 expect![[r#"
138 ev E::X ()
139 en E
140 ma m!(…) macro_rules! m
141 "#]],
142 );
143 }
144
145 #[test]
146 fn completes_in_irrefutable_let() {
147 check(
148 r#"
149enum E { X }
150use self::E::X;
151const Z: E = E::X;
152mod m {}
153
154static FOO: E = E::X;
155struct Bar { f: u32 }
156
157fn foo() {
158 let a$0
159}
160"#,
161 expect![[r#"
162 st Bar
163 "#]],
164 );
165 }
166
167 #[test]
168 fn completes_in_param() {
169 check(
170 r#"
171enum E { X }
172
173static FOO: E = E::X;
174struct Bar { f: u32 }
175
176fn foo(a$0) {
177}
178"#,
179 expect![[r#"
180 st Bar
181 "#]],
182 );
183 }
184
185 #[test]
186 fn completes_pat_in_let() {
187 check_snippet(
188 r#"
189struct Bar { f: u32 }
190
191fn foo() {
192 let a$0
193}
194"#,
195 expect![[r#"
196 bn Bar Bar { f$1 }$0
197 "#]],
198 );
199 }
200
201 #[test]
202 fn completes_param_pattern() {
203 check_snippet(
204 r#"
205struct Foo { bar: String, baz: String }
206struct Bar(String, String);
207struct Baz;
208fn outer(a$0) {}
209"#,
210 expect![[r#"
211 bn Foo Foo { bar$1, baz$2 }: Foo$0
212 bn Bar Bar($1, $2): Bar$0
213 "#]],
214 )
215 }
216
217 #[test]
218 fn completes_let_pattern() {
219 check_snippet(
220 r#"
221struct Foo { bar: String, baz: String }
222struct Bar(String, String);
223struct Baz;
224fn outer() {
225 let a$0
226}
227"#,
228 expect![[r#"
229 bn Foo Foo { bar$1, baz$2 }$0
230 bn Bar Bar($1, $2)$0
231 "#]],
232 )
233 }
234
235 #[test]
236 fn completes_refutable_pattern() {
237 check_snippet(
238 r#"
239struct Foo { bar: i32, baz: i32 }
240struct Bar(String, String);
241struct Baz;
242fn outer() {
243 match () {
244 a$0
245 }
246}
247"#,
248 expect![[r#"
249 bn Foo Foo { bar$1, baz$2 }$0
250 bn Bar Bar($1, $2)$0
251 "#]],
252 )
253 }
254
255 #[test]
256 fn omits_private_fields_pat() {
257 check_snippet(
258 r#"
259mod foo {
260 pub struct Foo { pub bar: i32, baz: i32 }
261 pub struct Bar(pub String, String);
262 pub struct Invisible(String, String);
263}
264use foo::*;
265
266fn outer() {
267 match () {
268 a$0
269 }
270}
271"#,
272 expect![[r#"
273 bn Foo Foo { bar$1, .. }$0
274 bn Bar Bar($1, ..)$0
275 "#]],
276 )
277 }
278
279 #[test]
280 fn only_shows_ident_completion() {
281 check_edit(
282 "Foo",
283 r#"
284struct Foo(i32);
285fn main() {
286 match Foo(92) {
287 a$0(92) => (),
288 }
289}
290"#,
291 r#"
292struct Foo(i32);
293fn main() {
294 match Foo(92) {
295 Foo(92) => (),
296 }
297}
298"#,
299 );
300 }
301
302 #[test]
303 fn completes_self_pats() {
304 check_snippet(
305 r#"
306struct Foo(i32);
307impl Foo {
308 fn foo() {
309 match () {
310 a$0
311 }
312 }
313}
314 "#,
315 expect![[r#"
316 bn Self Self($1)$0
317 bn Foo Foo($1)$0
318 "#]],
319 )
320 }
321
322 #[test]
323 fn completes_qualified_variant() {
324 check_snippet(
325 r#"
326enum Foo {
327 Bar { baz: i32 }
328}
329impl Foo {
330 fn foo() {
331 match {Foo::Bar { baz: 0 }} {
332 B$0
333 }
334 }
335}
336 "#,
337 expect![[r#"
338 bn Self::Bar Self::Bar { baz$1 }$0
339 bn Foo::Bar Foo::Bar { baz$1 }$0
340 "#]],
341 )
342 }
343
344 #[test]
345 fn completes_enum_variant_matcharm() {
346 check(
347 r#"
348enum Foo { Bar, Baz, Quux }
349
350fn main() {
351 let foo = Foo::Quux;
352 match foo { Qu$0 }
353}
354"#,
355 expect![[r#"
356 ev Foo::Bar ()
357 ev Foo::Baz ()
358 ev Foo::Quux ()
359 en Foo
360 "#]],
361 )
362 }
363
364 #[test]
365 fn completes_enum_variant_matcharm_ref() {
366 check(
367 r#"
368enum Foo { Bar, Baz, Quux }
369
370fn main() {
371 let foo = Foo::Quux;
372 match &foo { Qu$0 }
373}
374"#,
375 expect![[r#"
376 ev Foo::Bar ()
377 ev Foo::Baz ()
378 ev Foo::Quux ()
379 en Foo
380 "#]],
381 )
382 }
383
384 #[test]
385 fn completes_enum_variant_iflet() {
386 check(
387 r#"
388enum Foo { Bar, Baz, Quux }
389
390fn main() {
391 let foo = Foo::Quux;
392 if let Qu$0 = foo { }
393}
394"#,
395 expect![[r#"
396 ev Foo::Bar ()
397 ev Foo::Baz ()
398 ev Foo::Quux ()
399 en Foo
400 "#]],
401 )
402 }
403
404 #[test]
405 fn completes_enum_variant_impl() {
406 check(
407 r#"
408enum Foo { Bar, Baz, Quux }
409impl Foo {
410 fn foo() { match Foo::Bar { Q$0 } }
411}
412"#,
413 expect![[r#"
414 ev Self::Bar ()
415 ev Self::Baz ()
416 ev Self::Quux ()
417 ev Foo::Bar ()
418 ev Foo::Baz ()
419 ev Foo::Quux ()
420 sp Self
421 en Foo
422 "#]],
423 )
424 }
425
426 #[test]
427 fn completes_in_record_field_pat() {
428 check_snippet(
429 r#"
430struct Foo { bar: Bar }
431struct Bar(u32);
432fn outer(Foo { bar: $0 }: Foo) {}
433"#,
434 expect![[r#"
435 bn Foo Foo { bar$1 }$0
436 bn Bar Bar($1)$0
437 "#]],
438 )
439 }
440
441 #[test]
442 fn skips_in_record_field_pat_name() {
443 check_snippet(
444 r#"
445struct Foo { bar: Bar }
446struct Bar(u32);
447fn outer(Foo { bar$0 }: Foo) {}
448"#,
449 expect![[r#""#]],
450 )
451 }
452}
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index f5dbd203b..1b8997ecf 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -219,36 +219,6 @@ mod tests {
219 } 219 }
220 220
221 #[test] 221 #[test]
222 fn dont_complete_values_in_type_pos() {
223 check(
224 r#"
225const FOO: () = ();
226static BAR: () = ();
227struct Baz;
228fn foo() {
229 let _: self::$0;
230}
231"#,
232 expect![[r#"
233 st Baz
234 "#]],
235 );
236 }
237
238 #[test]
239 fn dont_complete_enum_variants_in_type_pos() {
240 check(
241 r#"
242enum Foo { Bar }
243fn foo() {
244 let _: Foo::$0;
245}
246"#,
247 expect![[r#""#]],
248 );
249 }
250
251 #[test]
252 fn dont_complete_primitive_in_use() { 222 fn dont_complete_primitive_in_use() {
253 check_builtin(r#"use self::$0;"#, expect![[""]]); 223 check_builtin(r#"use self::$0;"#, expect![[""]]);
254 } 224 }
@@ -259,32 +229,6 @@ fn foo() {
259 } 229 }
260 230
261 #[test] 231 #[test]
262 fn completes_primitives() {
263 check_builtin(
264 r#"fn main() { let _: $0 = 92; }"#,
265 expect![[r#"
266 bt u32
267 bt bool
268 bt u8
269 bt isize
270 bt u16
271 bt u64
272 bt u128
273 bt f32
274 bt i128
275 bt i16
276 bt str
277 bt i64
278 bt char
279 bt f64
280 bt i32
281 bt i8
282 bt usize
283 "#]],
284 );
285 }
286
287 #[test]
288 fn completes_enum_variant() { 232 fn completes_enum_variant() {
289 check( 233 check(
290 r#" 234 r#"
@@ -749,24 +693,4 @@ fn main() {
749 "#]], 693 "#]],
750 ); 694 );
751 } 695 }
752
753 #[test]
754 fn completes_types_and_const_in_arg_list() {
755 check(
756 r#"
757mod foo {
758 pub const CONST: () = ();
759 pub type Type = ();
760}
761
762struct Foo<T>(t);
763
764fn foo(_: Foo<foo::$0>) {}
765"#,
766 expect![[r#"
767 ta Type
768 ct CONST
769 "#]],
770 );
771 }
772} 696}
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index 81c4fb305..380c1e079 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -113,78 +113,6 @@ mod tests {
113 } 113 }
114 114
115 #[test] 115 #[test]
116 fn dont_complete_values_in_type_pos() {
117 check(
118 r#"
119const FOO: () = ();
120static BAR: () = ();
121enum Foo {
122 Bar
123}
124struct Baz;
125fn foo() {
126 let local = ();
127 let _: $0;
128}
129"#,
130 expect![[r#"
131 en Foo
132 st Baz
133 "#]],
134 );
135 }
136
137 #[test]
138 fn bind_pat_and_path_ignore_at() {
139 check(
140 r#"
141enum Enum { A, B }
142fn quux(x: Option<Enum>) {
143 match x {
144 None => (),
145 Some(en$0 @ Enum::A) => (),
146 }
147}
148"#,
149 expect![[r#""#]],
150 );
151 }
152
153 #[test]
154 fn bind_pat_and_path_ignore_ref() {
155 check(
156 r#"
157enum Enum { A, B }
158fn quux(x: Option<Enum>) {
159 match x {
160 None => (),
161 Some(ref en$0) => (),
162 }
163}
164"#,
165 expect![[r#""#]],
166 );
167 }
168
169 #[test]
170 fn bind_pat_and_path() {
171 check(
172 r#"
173enum Enum { A, B }
174fn quux(x: Option<Enum>) {
175 match x {
176 None => (),
177 Some(En$0) => (),
178 }
179}
180"#,
181 expect![[r#"
182 en Enum
183 "#]],
184 );
185 }
186
187 #[test]
188 fn completes_bindings_from_let() { 116 fn completes_bindings_from_let() {
189 check( 117 check(
190 r#" 118 r#"
@@ -289,29 +217,6 @@ fn main() {
289 } 217 }
290 218
291 #[test] 219 #[test]
292 fn completes_generic_params_in_struct() {
293 check(
294 r#"struct S<T> { x: $0}"#,
295 expect![[r#"
296 sp Self
297 tp T
298 st S<…>
299 "#]],
300 );
301 }
302
303 #[test]
304 fn completes_self_in_enum() {
305 check(
306 r#"enum X { Y($0) }"#,
307 expect![[r#"
308 sp Self
309 en X
310 "#]],
311 );
312 }
313
314 #[test]
315 fn completes_module_items() { 220 fn completes_module_items() {
316 check( 221 check(
317 r#" 222 r#"
@@ -365,19 +270,6 @@ mod m {
365 } 270 }
366 271
367 #[test] 272 #[test]
368 fn completes_return_type() {
369 check(
370 r#"
371struct Foo;
372fn x() -> $0
373"#,
374 expect![[r#"
375 st Foo
376 "#]],
377 );
378 }
379
380 #[test]
381 fn dont_show_both_completions_for_shadowing() { 273 fn dont_show_both_completions_for_shadowing() {
382 check( 274 check(
383 r#" 275 r#"
@@ -559,19 +451,6 @@ fn foo() { $0 }
559 } 451 }
560 452
561 #[test] 453 #[test]
562 fn completes_macros_as_type() {
563 check(
564 r#"
565macro_rules! foo { () => {} }
566fn main() { let x: $0 }
567"#,
568 expect![[r#"
569 ma foo!(…) macro_rules! foo
570 "#]],
571 );
572 }
573
574 #[test]
575 fn completes_macros_as_stmt() { 454 fn completes_macros_as_stmt() {
576 check( 455 check(
577 r#" 456 r#"
@@ -716,30 +595,4 @@ fn f() {}
716 expect![[""]], 595 expect![[""]],
717 ) 596 )
718 } 597 }
719
720 #[test]
721 fn completes_types_and_const_in_arg_list() {
722 check(
723 r#"
724enum Bar {
725 Baz
726}
727trait Foo {
728 type Bar;
729}
730
731const CONST: () = ();
732
733fn foo<T: Foo<$0>, const CONST_PARAM: usize>(_: T) {}
734"#,
735 expect![[r#"
736 ta Bar = type Bar;
737 tp T
738 cp CONST_PARAM
739 tt Foo
740 en Bar
741 ct CONST
742 "#]],
743 );
744 }
745} 598}
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index e49e434fa..f0da98739 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -286,8 +286,11 @@ impl<'a> CompletionContext<'a> {
286 ) 286 )
287 } 287 }
288 288
289 pub(crate) fn expect_record_field(&self) -> bool { 289 pub(crate) fn expect_field(&self) -> bool {
290 matches!(self.completion_location, Some(ImmediateLocation::RecordField)) 290 matches!(
291 self.completion_location,
292 Some(ImmediateLocation::RecordField | ImmediateLocation::TupleField)
293 )
291 } 294 }
292 295
293 pub(crate) fn in_use_tree(&self) -> bool { 296 pub(crate) fn in_use_tree(&self) -> bool {
@@ -385,14 +388,19 @@ impl<'a> CompletionContext<'a> {
385 (ty, name) 388 (ty, name)
386 }, 389 },
387 ast::ArgList(_it) => { 390 ast::ArgList(_it) => {
388 cov_mark::hit!(expected_type_fn_param_with_leading_char); 391 cov_mark::hit!(expected_type_fn_param);
389 cov_mark::hit!(expected_type_fn_param_without_leading_char);
390 ActiveParameter::at_token( 392 ActiveParameter::at_token(
391 &self.sema, 393 &self.sema,
392 self.token.clone(), 394 self.token.clone(),
393 ).map(|ap| { 395 ).map(|ap| {
394 let name = ap.ident().map(NameOrNameRef::Name); 396 let name = ap.ident().map(NameOrNameRef::Name);
395 (Some(ap.ty), name) 397 let ty = if has_ref(&self.token) {
398 cov_mark::hit!(expected_type_fn_param_ref);
399 ap.ty.remove_ref()
400 } else {
401 Some(ap.ty)
402 };
403 (ty, name)
396 }) 404 })
397 .unwrap_or((None, None)) 405 .unwrap_or((None, None))
398 }, 406 },
@@ -697,6 +705,19 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
697 use_tree.path().zip(Some(true)) 705 use_tree.path().zip(Some(true))
698} 706}
699 707
708fn has_ref(token: &SyntaxToken) -> bool {
709 let mut token = token.clone();
710 for skip in [WHITESPACE, IDENT, T![mut]] {
711 if token.kind() == skip {
712 token = match token.prev_token() {
713 Some(it) => it,
714 None => return false,
715 }
716 }
717 }
718 token.kind() == T![&]
719}
720
700#[cfg(test)] 721#[cfg(test)]
701mod tests { 722mod tests {
702 use expect_test::{expect, Expect}; 723 use expect_test::{expect, Expect};
@@ -769,14 +790,18 @@ fn foo() {
769 } 790 }
770 791
771 #[test] 792 #[test]
772 fn expected_type_fn_param_without_leading_char() { 793 fn expected_type_fn_param() {
773 cov_mark::check!(expected_type_fn_param_without_leading_char); 794 cov_mark::check!(expected_type_fn_param);
774 check_expected_type_and_name( 795 check_expected_type_and_name(
775 r#" 796 r#"
776fn foo() { 797fn foo() { bar($0); }
777 bar($0); 798fn bar(x: u32) {}
778} 799"#,
779 800 expect![[r#"ty: u32, name: x"#]],
801 );
802 check_expected_type_and_name(
803 r#"
804fn foo() { bar(c$0); }
780fn bar(x: u32) {} 805fn bar(x: u32) {}
781"#, 806"#,
782 expect![[r#"ty: u32, name: x"#]], 807 expect![[r#"ty: u32, name: x"#]],
@@ -784,18 +809,29 @@ fn bar(x: u32) {}
784 } 809 }
785 810
786 #[test] 811 #[test]
787 fn expected_type_fn_param_with_leading_char() { 812 fn expected_type_fn_param_ref() {
788 cov_mark::check!(expected_type_fn_param_with_leading_char); 813 cov_mark::check!(expected_type_fn_param_ref);
789 check_expected_type_and_name( 814 check_expected_type_and_name(
790 r#" 815 r#"
791fn foo() { 816fn foo() { bar(&$0); }
792 bar(c$0); 817fn bar(x: &u32) {}
793}
794
795fn bar(x: u32) {}
796"#, 818"#,
797 expect![[r#"ty: u32, name: x"#]], 819 expect![[r#"ty: u32, name: x"#]],
798 ); 820 );
821 check_expected_type_and_name(
822 r#"
823fn foo() { bar(&mut $0); }
824fn bar(x: &mut u32) {}
825"#,
826 expect![[r#"ty: u32, name: x"#]],
827 );
828 check_expected_type_and_name(
829 r#"
830fn foo() { bar(&c$0); }
831fn bar(x: &u32) {}
832 "#,
833 expect![[r#"ty: u32, name: x"#]],
834 );
799 } 835 }
800 836
801 #[test] 837 #[test]
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs
index 271409c38..757c9a3da 100644
--- a/crates/ide_completion/src/patterns.rs
+++ b/crates/ide_completion/src/patterns.rs
@@ -31,6 +31,7 @@ pub(crate) enum ImmediateLocation {
31 Impl, 31 Impl,
32 Trait, 32 Trait,
33 RecordField, 33 RecordField,
34 TupleField,
34 RefExpr, 35 RefExpr,
35 IdentPat, 36 IdentPat,
36 BlockExpr, 37 BlockExpr,
@@ -187,7 +188,13 @@ pub(crate) fn determine_location(
187 ast::SourceFile(_it) => ImmediateLocation::ItemList, 188 ast::SourceFile(_it) => ImmediateLocation::ItemList,
188 ast::ItemList(_it) => ImmediateLocation::ItemList, 189 ast::ItemList(_it) => ImmediateLocation::ItemList,
189 ast::RefExpr(_it) => ImmediateLocation::RefExpr, 190 ast::RefExpr(_it) => ImmediateLocation::RefExpr,
190 ast::RecordField(_it) => ImmediateLocation::RecordField, 191 ast::RecordField(it) => if it.ty().map_or(false, |it| it.syntax().text_range().contains(offset)) {
192 return None;
193 } else {
194 ImmediateLocation::RecordField
195 },
196 ast::TupleField(_it) => ImmediateLocation::TupleField,
197 ast::TupleFieldList(_it) => ImmediateLocation::TupleField,
191 ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) { 198 ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) {
192 Some(IMPL) => ImmediateLocation::Impl, 199 Some(IMPL) => ImmediateLocation::Impl,
193 Some(TRAIT) => ImmediateLocation::Trait, 200 Some(TRAIT) => ImmediateLocation::Trait,
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 9bec03e17..1a9b6212a 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -1057,7 +1057,7 @@ fn f() {
1057 #[test] 1057 #[test]
1058 fn suggest_ref_mut() { 1058 fn suggest_ref_mut() {
1059 cov_mark::check!(suggest_ref); 1059 cov_mark::check!(suggest_ref);
1060 check( 1060 check_relevance(
1061 r#" 1061 r#"
1062struct S; 1062struct S;
1063fn foo(s: &mut S) {} 1063fn foo(s: &mut S) {}
@@ -1067,58 +1067,29 @@ fn main() {
1067} 1067}
1068 "#, 1068 "#,
1069 expect![[r#" 1069 expect![[r#"
1070 [ 1070 lc s [name+local]
1071 CompletionItem { 1071 lc &mut s [type+name+local]
1072 label: "S", 1072 st S []
1073 source_range: 70..70, 1073 fn main() []
1074 delete: 70..70, 1074 fn foo(…) []
1075 insert: "S",
1076 kind: SymbolKind(
1077 Struct,
1078 ),
1079 },
1080 CompletionItem {
1081 label: "foo(…)",
1082 source_range: 70..70,
1083 delete: 70..70,
1084 insert: "foo(${1:&mut s})$0",
1085 kind: SymbolKind(
1086 Function,
1087 ),
1088 lookup: "foo",
1089 detail: "fn(&mut S)",
1090 trigger_call_info: true,
1091 },
1092 CompletionItem {
1093 label: "main()",
1094 source_range: 70..70,
1095 delete: 70..70,
1096 insert: "main()$0",
1097 kind: SymbolKind(
1098 Function,
1099 ),
1100 lookup: "main",
1101 detail: "fn()",
1102 },
1103 CompletionItem {
1104 label: "s",
1105 source_range: 70..70,
1106 delete: 70..70,
1107 insert: "s",
1108 kind: SymbolKind(
1109 Local,
1110 ),
1111 detail: "S",
1112 relevance: CompletionRelevance {
1113 exact_name_match: true,
1114 type_match: None,
1115 is_local: true,
1116 },
1117 ref_match: "&mut ",
1118 },
1119 ]
1120 "#]], 1075 "#]],
1121 ) 1076 );
1077 check_relevance(
1078 r#"
1079struct S;
1080fn foo(s: &mut S) {}
1081fn main() {
1082 let mut s = S;
1083 foo(&mut $0);
1084}
1085 "#,
1086 expect![[r#"
1087 lc s [type+name+local]
1088 st S []
1089 fn main() []
1090 fn foo(…) []
1091 "#]],
1092 );
1122 } 1093 }
1123 1094
1124 #[test] 1095 #[test]
diff --git a/crates/ide_completion/src/tests.rs b/crates/ide_completion/src/tests.rs
index 211c89c40..97298ff27 100644
--- a/crates/ide_completion/src/tests.rs
+++ b/crates/ide_completion/src/tests.rs
@@ -7,6 +7,10 @@
7mod item_list; 7mod item_list;
8mod use_tree; 8mod use_tree;
9mod items; 9mod items;
10mod pattern;
11mod type_pos;
12
13use std::mem;
10 14
11use hir::{PrefixKind, Semantics}; 15use hir::{PrefixKind, Semantics};
12use ide_db::{ 16use ide_db::{
@@ -45,7 +49,16 @@ pub(crate) fn completion_list(code: &str) -> String {
45} 49}
46 50
47fn completion_list_with_config(config: CompletionConfig, code: &str) -> String { 51fn completion_list_with_config(config: CompletionConfig, code: &str) -> String {
48 render_completion_list(get_all_items(config, code)) 52 // filter out all but one builtintype completion for smaller test outputs
53 let items = get_all_items(config, code);
54 let mut bt_seen = false;
55 let items = items
56 .into_iter()
57 .filter(|it| {
58 it.completion_kind != CompletionKind::BuiltinType || !mem::replace(&mut bt_seen, true)
59 })
60 .collect();
61 render_completion_list(items)
49} 62}
50 63
51/// Creates analysis from a multi-file fixture, returns positions marked with $0. 64/// Creates analysis from a multi-file fixture, returns positions marked with $0.
diff --git a/crates/ide_completion/src/tests/items.rs b/crates/ide_completion/src/tests/items.rs
index 8dfb8221b..b98baffd6 100644
--- a/crates/ide_completion/src/tests/items.rs
+++ b/crates/ide_completion/src/tests/items.rs
@@ -35,22 +35,6 @@ impl Tra$0
35 ma foo!(…) #[macro_export] macro_rules! foo 35 ma foo!(…) #[macro_export] macro_rules! foo
36 ma foo!(…) #[macro_export] macro_rules! foo 36 ma foo!(…) #[macro_export] macro_rules! foo
37 bt u32 37 bt u32
38 bt bool
39 bt u8
40 bt isize
41 bt u16
42 bt u64
43 bt u128
44 bt f32
45 bt i128
46 bt i16
47 bt str
48 bt i64
49 bt char
50 bt f64
51 bt i32
52 bt i8
53 bt usize
54 "##]], 38 "##]],
55 ) 39 )
56} 40}
@@ -69,22 +53,6 @@ impl Trait for Str$0
69 ma foo!(…) #[macro_export] macro_rules! foo 53 ma foo!(…) #[macro_export] macro_rules! foo
70 ma foo!(…) #[macro_export] macro_rules! foo 54 ma foo!(…) #[macro_export] macro_rules! foo
71 bt u32 55 bt u32
72 bt bool
73 bt u8
74 bt isize
75 bt u16
76 bt u64
77 bt u128
78 bt f32
79 bt i128
80 bt i16
81 bt str
82 bt i64
83 bt char
84 bt f64
85 bt i32
86 bt i8
87 bt usize
88 "##]], 56 "##]],
89 ) 57 )
90} 58}
diff --git a/crates/ide_completion/src/tests/pattern.rs b/crates/ide_completion/src/tests/pattern.rs
new file mode 100644
index 000000000..1ad5ccd97
--- /dev/null
+++ b/crates/ide_completion/src/tests/pattern.rs
@@ -0,0 +1,348 @@
1//! Completions tests for pattern position.
2use expect_test::{expect, Expect};
3
4use crate::tests::completion_list;
5
6fn check(ra_fixture: &str, expect: Expect) {
7 let actual = completion_list(ra_fixture);
8 expect.assert_eq(&actual)
9}
10
11fn check_with(ra_fixture: &str, expect: Expect) {
12 let base = r#"
13enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV }
14use self::Enum::TupleV;
15mod module {}
16
17static STATIC: Unit = Unit;
18const CONST: Unit = Unit;
19struct Record { field: u32 }
20struct Tuple(u32);
21struct Unit
22macro_rules! makro {}
23"#;
24 let actual = completion_list(&format!("{}\n{}", base, ra_fixture));
25 expect.assert_eq(&actual)
26}
27
28#[test]
29fn ident_rebind_pat() {
30 check(
31 r#"
32fn quux() {
33 let en$0 @ x
34}
35"#,
36 expect![[r#"
37 kw mut
38 "#]],
39 );
40}
41
42#[test]
43fn ident_ref_pat() {
44 check(
45 r#"
46fn quux() {
47 let ref en$0
48}
49"#,
50 expect![[r#"
51 kw mut
52 "#]],
53 );
54 check(
55 r#"
56fn quux() {
57 let ref en$0 @ x
58}
59"#,
60 expect![[r#"
61 kw mut
62 "#]],
63 );
64}
65
66#[test]
67fn ident_ref_mut_pat() {
68 // FIXME mut is already here, don't complete it again
69 check(
70 r#"
71fn quux() {
72 let ref mut en$0
73}
74"#,
75 expect![[r#"
76 kw mut
77 "#]],
78 );
79 check(
80 r#"
81fn quux() {
82 let ref mut en$0 @ x
83}
84"#,
85 expect![[r#"
86 kw mut
87 "#]],
88 );
89}
90
91#[test]
92fn ref_pat() {
93 check(
94 r#"
95fn quux() {
96 let &en$0
97}
98"#,
99 expect![[r#"
100 kw mut
101 "#]],
102 );
103 // FIXME mut is already here, don't complete it again
104 check(
105 r#"
106fn quux() {
107 let &mut en$0
108}
109"#,
110 expect![[r#"
111 kw mut
112 "#]],
113 );
114}
115
116#[test]
117fn refutable() {
118 check_with(
119 r#"
120fn foo() {
121 if let a$0
122}
123"#,
124 expect![[r#"
125 kw mut
126 bn Record Record { field$1 }$0
127 st Record
128 en Enum
129 bn Tuple Tuple($1)$0
130 st Tuple
131 md module
132 bn TupleV TupleV($1)$0
133 ev TupleV
134 st Unit
135 ct CONST
136 ma makro!(…) macro_rules! makro
137 "#]],
138 );
139}
140
141#[test]
142fn irrefutable() {
143 check_with(
144 r#"
145fn foo() {
146 let a$0
147}
148"#,
149 expect![[r#"
150 kw mut
151 bn Record Record { field$1 }$0
152 st Record
153 bn Tuple Tuple($1)$0
154 st Tuple
155 st Unit
156 ma makro!(…) macro_rules! makro
157 "#]],
158 );
159}
160
161#[test]
162fn in_param() {
163 check_with(
164 r#"
165fn foo(a$0) {
166}
167"#,
168 expect![[r#"
169 kw mut
170 bn Record Record { field$1 }: Record$0
171 st Record
172 bn Tuple Tuple($1): Tuple$0
173 st Tuple
174 st Unit
175 ma makro!(…) macro_rules! makro
176 "#]],
177 );
178}
179
180#[test]
181fn only_fn_like_macros() {
182 check(
183 r#"
184macro_rules! m { ($e:expr) => { $e } }
185
186#[rustc_builtin_macro]
187macro Clone {}
188
189fn foo() {
190 let x$0
191}
192"#,
193 expect![[r#"
194 kw mut
195 ma m!(…) macro_rules! m
196 "#]],
197 );
198}
199
200#[test]
201fn in_simple_macro_call() {
202 check(
203 r#"
204macro_rules! m { ($e:expr) => { $e } }
205enum E { X }
206
207fn foo() {
208 m!(match E::X { a$0 })
209}
210"#,
211 expect![[r#"
212 kw mut
213 ev E::X ()
214 en E
215 ma m!(…) macro_rules! m
216 "#]],
217 );
218}
219
220#[test]
221fn omits_private_fields_pat() {
222 check(
223 r#"
224mod foo {
225 pub struct Record { pub field: i32, _field: i32 }
226 pub struct Tuple(pub u32, u32);
227 pub struct Invisible(u32, u32);
228}
229use foo::*;
230
231fn outer() {
232 if let a$0
233}
234"#,
235 expect![[r#"
236 kw mut
237 bn Record Record { field$1, .. }$0
238 st Record
239 bn Tuple Tuple($1, ..)$0
240 st Tuple
241 st Invisible
242 md foo
243 "#]],
244 )
245}
246
247// #[test]
248// fn only_shows_ident_completion() {
249// check_edit(
250// "Foo",
251// r#"
252// struct Foo(i32);
253// fn main() {
254// match Foo(92) {
255// a$0(92) => (),
256// }
257// }
258// "#,
259// r#"
260// struct Foo(i32);
261// fn main() {
262// match Foo(92) {
263// Foo(92) => (),
264// }
265// }
266// "#,
267// );
268// }
269
270#[test]
271fn completes_self_pats() {
272 check(
273 r#"
274struct Foo(i32);
275impl Foo {
276 fn foo() {
277 match Foo(0) {
278 a$0
279 }
280 }
281}
282 "#,
283 expect![[r#"
284 kw mut
285 bn Self Self($1)$0
286 sp Self
287 bn Foo Foo($1)$0
288 st Foo
289 "#]],
290 )
291}
292
293#[test]
294fn completes_qualified_variant() {
295 check(
296 r#"
297enum Foo {
298 Bar { baz: i32 }
299}
300impl Foo {
301 fn foo() {
302 match {Foo::Bar { baz: 0 }} {
303 B$0
304 }
305 }
306}
307 "#,
308 expect![[r#"
309 kw mut
310 bn Self::Bar Self::Bar { baz$1 }$0
311 ev Self::Bar { baz: i32 }
312 bn Foo::Bar Foo::Bar { baz$1 }$0
313 ev Foo::Bar { baz: i32 }
314 sp Self
315 en Foo
316 "#]],
317 )
318}
319
320#[test]
321fn completes_in_record_field_pat() {
322 check(
323 r#"
324struct Foo { bar: Bar }
325struct Bar(u32);
326fn outer(Foo { bar: $0 }: Foo) {}
327"#,
328 expect![[r#"
329 kw mut
330 bn Foo Foo { bar$1 }$0
331 st Foo
332 bn Bar Bar($1)$0
333 st Bar
334 "#]],
335 )
336}
337
338#[test]
339fn skips_in_record_field_pat_name() {
340 check(
341 r#"
342struct Foo { bar: Bar }
343struct Bar(u32);
344fn outer(Foo { bar$0 }: Foo) {}
345"#,
346 expect![[r#""#]],
347 )
348}
diff --git a/crates/ide_completion/src/tests/type_pos.rs b/crates/ide_completion/src/tests/type_pos.rs
new file mode 100644
index 000000000..1ab47b27e
--- /dev/null
+++ b/crates/ide_completion/src/tests/type_pos.rs
@@ -0,0 +1,177 @@
1//! Completions tests for type position.
2use expect_test::{expect, Expect};
3
4use crate::tests::completion_list;
5
6fn check_with(ra_fixture: &str, expect: Expect) {
7 let base = r#"
8enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV }
9use self::Enum::TupleV;
10mod module {}
11
12trait Trait {}
13static STATIC: Unit = Unit;
14const CONST: Unit = Unit;
15struct Record { field: u32 }
16struct Tuple(u32);
17struct Unit
18macro_rules! makro {}
19"#;
20 let actual = completion_list(&format!("{}\n{}", base, ra_fixture));
21 expect.assert_eq(&actual)
22}
23
24#[test]
25fn record_field_ty() {
26 check_with(
27 r#"
28struct Foo<'lt, T, const C: usize> {
29 f: $0
30}
31"#,
32 expect![[r#"
33 sp Self
34 tp T
35 tt Trait
36 en Enum
37 st Record
38 st Tuple
39 md module
40 st Foo<…>
41 st Unit
42 ma makro!(…) macro_rules! makro
43 bt u32
44 "#]],
45 )
46}
47
48#[test]
49fn tuple_struct_field() {
50 check_with(
51 r#"
52struct Foo<'lt, T, const C: usize>(f$0);
53"#,
54 expect![[r#"
55 kw pub(crate)
56 kw pub
57 sp Self
58 tp T
59 tt Trait
60 en Enum
61 st Record
62 st Tuple
63 md module
64 st Foo<…>
65 st Unit
66 ma makro!(…) macro_rules! makro
67 bt u32
68 "#]],
69 )
70}
71
72#[test]
73fn fn_return_type() {
74 check_with(
75 r#"
76fn x<'lt, T, const C: usize>() -> $0
77"#,
78 expect![[r#"
79 tp T
80 tt Trait
81 en Enum
82 st Record
83 st Tuple
84 md module
85 st Unit
86 ma makro!(…) macro_rules! makro
87 bt u32
88 "#]],
89 );
90}
91
92#[test]
93fn body_type_pos() {
94 check_with(
95 r#"
96fn foo<'lt, T, const C: usize>() {
97 let local = ();
98 let _: $0;
99}
100"#,
101 expect![[r#"
102 tp T
103 tt Trait
104 en Enum
105 st Record
106 st Tuple
107 md module
108 st Unit
109 ma makro!(…) macro_rules! makro
110 bt u32
111 "#]],
112 );
113 check_with(
114 r#"
115fn foo<'lt, T, const C: usize>() {
116 let local = ();
117 let _: self::$0;
118}
119"#,
120 expect![[r#"
121 tt Trait
122 en Enum
123 st Record
124 st Tuple
125 md module
126 st Unit
127 "#]],
128 );
129}
130
131#[test]
132fn completes_types_and_const_in_arg_list() {
133 // FIXME: we should complete the lifetime here for now
134 check_with(
135 r#"
136trait Trait2 {
137 type Foo;
138}
139
140fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
141"#,
142 expect![[r#"
143 ta Foo = type Foo;
144 tp T
145 cp CONST_PARAM
146 tt Trait
147 en Enum
148 st Record
149 st Tuple
150 tt Trait2
151 md module
152 st Unit
153 ct CONST
154 ma makro!(…) macro_rules! makro
155 bt u32
156 "#]],
157 );
158 check_with(
159 r#"
160trait Trait2 {
161 type Foo;
162}
163
164fn foo<'lt, T: Trait2<self::$0>, const CONST_PARAM: usize>(_: T) {}
165 "#,
166 expect![[r#"
167 tt Trait
168 en Enum
169 st Record
170 st Tuple
171 tt Trait2
172 md module
173 st Unit
174 ct CONST
175 "#]],
176 );
177}
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs
index 263edcdc9..01894630a 100644
--- a/crates/ide_db/src/helpers/insert_use/tests.rs
+++ b/crates/ide_db/src/helpers/insert_use/tests.rs
@@ -1,7 +1,43 @@
1use super::*; 1use super::*;
2 2
3use hir::PrefixKind; 3use hir::PrefixKind;
4use test_utils::assert_eq_text; 4use test_utils::{assert_eq_text, extract_range_or_offset, CURSOR_MARKER};
5
6#[test]
7fn respects_cfg_attr_fn() {
8 check(
9 r"bar::Bar",
10 r#"
11#[cfg(test)]
12fn foo() {$0}
13"#,
14 r#"
15#[cfg(test)]
16fn foo() {
17use bar::Bar;
18}
19"#,
20 ImportGranularity::Crate,
21 );
22}
23
24#[test]
25fn respects_cfg_attr_const() {
26 check(
27 r"bar::Bar",
28 r#"
29#[cfg(test)]
30const FOO: Bar = {$0};
31"#,
32 r#"
33#[cfg(test)]
34const FOO: Bar = {
35use bar::Bar;
36};
37"#,
38 ImportGranularity::Crate,
39 );
40}
5 41
6#[test] 42#[test]
7fn insert_skips_lone_glob_imports() { 43fn insert_skips_lone_glob_imports() {
@@ -15,15 +51,13 @@ use foo::bar::*;
15use foo::baz::A; 51use foo::baz::A;
16", 52",
17 ImportGranularity::Crate, 53 ImportGranularity::Crate,
18 false,
19 false,
20 ); 54 );
21} 55}
22 56
23#[test] 57#[test]
24fn insert_not_group() { 58fn insert_not_group() {
25 cov_mark::check!(insert_no_grouping_last); 59 cov_mark::check!(insert_no_grouping_last);
26 check( 60 check_with_config(
27 "use external_crate2::bar::A", 61 "use external_crate2::bar::A",
28 r" 62 r"
29use std::bar::B; 63use std::bar::B;
@@ -38,24 +72,32 @@ use crate::bar::A;
38use self::bar::A; 72use self::bar::A;
39use super::bar::A; 73use super::bar::A;
40use external_crate2::bar::A;", 74use external_crate2::bar::A;",
41 ImportGranularity::Item, 75 &InsertUseConfig {
42 false, 76 granularity: ImportGranularity::Item,
43 false, 77 enforce_granularity: true,
78 prefix_kind: PrefixKind::Plain,
79 group: false,
80 skip_glob_imports: true,
81 },
44 ); 82 );
45} 83}
46 84
47#[test] 85#[test]
48fn insert_not_group_empty() { 86fn insert_not_group_empty() {
49 cov_mark::check!(insert_no_grouping_last2); 87 cov_mark::check!(insert_no_grouping_last2);
50 check( 88 check_with_config(
51 "use external_crate2::bar::A", 89 "use external_crate2::bar::A",
52 r"", 90 r"",
53 r"use external_crate2::bar::A; 91 r"use external_crate2::bar::A;
54 92
55", 93",
56 ImportGranularity::Item, 94 &InsertUseConfig {
57 false, 95 granularity: ImportGranularity::Item,
58 false, 96 enforce_granularity: true,
97 prefix_kind: PrefixKind::Plain,
98 group: false,
99 skip_glob_imports: true,
100 },
59 ); 101 );
60} 102}
61 103
@@ -294,13 +336,15 @@ fn insert_empty_module() {
294 cov_mark::check!(insert_group_empty_module); 336 cov_mark::check!(insert_group_empty_module);
295 check( 337 check(
296 "foo::bar", 338 "foo::bar",
297 "mod x {}", 339 r"
298 r"{ 340mod x {$0}
341",
342 r"
343mod x {
299 use foo::bar; 344 use foo::bar;
300}", 345}
346",
301 ImportGranularity::Item, 347 ImportGranularity::Item,
302 true,
303 true,
304 ) 348 )
305} 349}
306 350
@@ -555,7 +599,6 @@ fn merge_mod_into_glob() {
555 "token::TokenKind", 599 "token::TokenKind",
556 r"use token::TokenKind::*;", 600 r"use token::TokenKind::*;",
557 r"use token::TokenKind::{*, self};", 601 r"use token::TokenKind::{*, self};",
558 false,
559 &InsertUseConfig { 602 &InsertUseConfig {
560 granularity: ImportGranularity::Crate, 603 granularity: ImportGranularity::Crate,
561 enforce_granularity: true, 604 enforce_granularity: true,
@@ -573,7 +616,6 @@ fn merge_self_glob() {
573 "self", 616 "self",
574 r"use self::*;", 617 r"use self::*;",
575 r"use self::{*, self};", 618 r"use self::{*, self};",
576 false,
577 &InsertUseConfig { 619 &InsertUseConfig {
578 granularity: ImportGranularity::Crate, 620 granularity: ImportGranularity::Crate,
579 enforce_granularity: true, 621 enforce_granularity: true,
@@ -798,14 +840,20 @@ fn check_with_config(
798 path: &str, 840 path: &str,
799 ra_fixture_before: &str, 841 ra_fixture_before: &str,
800 ra_fixture_after: &str, 842 ra_fixture_after: &str,
801 module: bool,
802 config: &InsertUseConfig, 843 config: &InsertUseConfig,
803) { 844) {
804 let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone(); 845 let (text, pos) = if ra_fixture_before.contains(CURSOR_MARKER) {
805 if module { 846 let (range_or_offset, text) = extract_range_or_offset(ra_fixture_before);
806 syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone(); 847 (text, Some(range_or_offset))
807 } 848 } else {
808 let file = super::ImportScope::from(syntax.clone_for_update()).unwrap(); 849 (ra_fixture_before.to_owned(), None)
850 };
851 let syntax = ast::SourceFile::parse(&text).tree().syntax().clone_for_update();
852 let file = pos
853 .and_then(|pos| syntax.token_at_offset(pos.expect_offset()).next()?.parent())
854 .and_then(|it| super::ImportScope::find_insert_use_container(&it))
855 .or_else(|| super::ImportScope::from(syntax))
856 .unwrap();
809 let path = ast::SourceFile::parse(&format!("use {};", path)) 857 let path = ast::SourceFile::parse(&format!("use {};", path))
810 .tree() 858 .tree()
811 .syntax() 859 .syntax()
@@ -814,7 +862,7 @@ fn check_with_config(
814 .unwrap(); 862 .unwrap();
815 863
816 insert_use(&file, path, config); 864 insert_use(&file, path, config);
817 let result = file.as_syntax_node().to_string(); 865 let result = file.as_syntax_node().ancestors().last().unwrap().to_string();
818 assert_eq_text!(ra_fixture_after, &result); 866 assert_eq_text!(ra_fixture_after, &result);
819} 867}
820 868
@@ -823,34 +871,31 @@ fn check(
823 ra_fixture_before: &str, 871 ra_fixture_before: &str,
824 ra_fixture_after: &str, 872 ra_fixture_after: &str,
825 granularity: ImportGranularity, 873 granularity: ImportGranularity,
826 module: bool,
827 group: bool,
828) { 874) {
829 check_with_config( 875 check_with_config(
830 path, 876 path,
831 ra_fixture_before, 877 ra_fixture_before,
832 ra_fixture_after, 878 ra_fixture_after,
833 module,
834 &InsertUseConfig { 879 &InsertUseConfig {
835 granularity, 880 granularity,
836 enforce_granularity: true, 881 enforce_granularity: true,
837 prefix_kind: PrefixKind::Plain, 882 prefix_kind: PrefixKind::Plain,
838 group, 883 group: true,
839 skip_glob_imports: true, 884 skip_glob_imports: true,
840 }, 885 },
841 ) 886 )
842} 887}
843 888
844fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 889fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
845 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate, false, true) 890 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate)
846} 891}
847 892
848fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 893fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
849 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module, false, true) 894 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module)
850} 895}
851 896
852fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 897fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
853 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item, false, true) 898 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item)
854} 899}
855 900
856fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) { 901fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) {
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs
index a22f79c15..006263da8 100644
--- a/crates/project_model/src/sysroot.rs
+++ b/crates/project_model/src/sysroot.rs
@@ -68,8 +68,9 @@ impl Sysroot {
68 pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> { 68 pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
69 let mut sysroot = Sysroot { crates: Arena::default() }; 69 let mut sysroot = Sysroot { crates: Arena::default() };
70 70
71 for name in SYSROOT_CRATES.trim().lines() { 71 for path in SYSROOT_CRATES.trim().lines() {
72 let root = [format!("{}/src/lib.rs", name), format!("lib{}/lib.rs", name)] 72 let name = path.split('/').last().unwrap();
73 let root = [format!("{}/src/lib.rs", path), format!("lib{}/lib.rs", path)]
73 .iter() 74 .iter()
74 .map(|it| sysroot_src_dir.join(it)) 75 .map(|it| sysroot_src_dir.join(it))
75 .find(|it| it.exists()); 76 .find(|it| it.exists());
@@ -191,9 +192,8 @@ panic_abort
191panic_unwind 192panic_unwind
192proc_macro 193proc_macro
193profiler_builtins 194profiler_builtins
194rtstartup
195std 195std
196stdarch 196stdarch/crates/std_detect
197term 197term
198test 198test
199unwind"; 199unwind";
@@ -204,9 +204,8 @@ core
204panic_abort 204panic_abort
205panic_unwind 205panic_unwind
206profiler_builtins 206profiler_builtins
207rtstartup
208proc_macro 207proc_macro
209stdarch 208std_detect
210term 209term
211test 210test
212unwind"; 211unwind";
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index d55bae62a..d9c22c180 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -11,6 +11,7 @@ mod fixture;
11mod assert_linear; 11mod assert_linear;
12 12
13use std::{ 13use std::{
14 collections::BTreeMap,
14 convert::{TryFrom, TryInto}, 15 convert::{TryFrom, TryInto},
15 env, fs, 16 env, fs,
16 path::{Path, PathBuf}, 17 path::{Path, PathBuf},
@@ -205,14 +206,25 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
205/// 206///
206/// // ^^^ first line 207/// // ^^^ first line
207/// // | second line 208/// // | second line
209///
210/// Annotations point to the last line that actually was long enough for the
211/// range, not counting annotations themselves. So overlapping annotations are
212/// possible:
213/// ```no_run
214/// // stuff other stuff
215/// // ^^ 'st'
216/// // ^^^^^ 'stuff'
217/// // ^^^^^^^^^^^ 'other stuff'
218/// ```
208pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { 219pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
209 let mut res = Vec::new(); 220 let mut res = Vec::new();
210 let mut prev_line_start: Option<TextSize> = Some(0.into()); 221 // map from line length to beginning of last line that had that length
222 let mut line_start_map = BTreeMap::new();
211 let mut line_start: TextSize = 0.into(); 223 let mut line_start: TextSize = 0.into();
212 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); 224 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
213 for line in text.split_inclusive('\n') { 225 for line in text.split_inclusive('\n') {
214 let mut this_line_annotations = Vec::new(); 226 let mut this_line_annotations = Vec::new();
215 if let Some(idx) = line.find("//") { 227 let line_length = if let Some(idx) = line.find("//") {
216 let annotation_offset = TextSize::of(&line[..idx + "//".len()]); 228 let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
217 for annotation in extract_line_annotations(&line[idx + "//".len()..]) { 229 for annotation in extract_line_annotations(&line[idx + "//".len()..]) {
218 match annotation { 230 match annotation {
@@ -222,7 +234,9 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
222 let range = if file { 234 let range = if file {
223 TextRange::up_to(TextSize::of(text)) 235 TextRange::up_to(TextSize::of(text))
224 } else { 236 } else {
225 range + prev_line_start.unwrap() 237 let line_start = line_start_map.range(range.end()..).next().unwrap();
238
239 range + line_start.1
226 }; 240 };
227 res.push((range, content)) 241 res.push((range, content))
228 } 242 }
@@ -238,9 +252,14 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
238 } 252 }
239 } 253 }
240 } 254 }
241 } 255 idx.try_into().unwrap()
256 } else {
257 TextSize::of(line)
258 };
259
260 line_start_map = line_start_map.split_off(&line_length);
261 line_start_map.insert(line_length, line_start);
242 262
243 prev_line_start = Some(line_start);
244 line_start += TextSize::of(line); 263 line_start += TextSize::of(line);
245 264
246 prev_line_annotations = this_line_annotations; 265 prev_line_annotations = this_line_annotations;
@@ -296,7 +315,7 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> {
296} 315}
297 316
298#[test] 317#[test]
299fn test_extract_annotations() { 318fn test_extract_annotations_1() {
300 let text = stdx::trim_indent( 319 let text = stdx::trim_indent(
301 r#" 320 r#"
302fn main() { 321fn main() {
@@ -321,6 +340,25 @@ fn main() {
321 assert_eq!(res[3].0.len(), 115); 340 assert_eq!(res[3].0.len(), 115);
322} 341}
323 342
343#[test]
344fn test_extract_annotations_2() {
345 let text = stdx::trim_indent(
346 r#"
347fn main() {
348 (x, y);
349 //^ a
350 // ^ b
351 //^^^^^^^^ c
352}"#,
353 );
354 let res = extract_annotations(&text)
355 .into_iter()
356 .map(|(range, ann)| (&text[range], ann))
357 .collect::<Vec<_>>();
358
359 assert_eq!(res, [("x", "a".into()), ("y", "b".into()), ("(x, y)", "c".into())]);
360}
361
324/// Returns `false` if slow tests should not run, otherwise returns `true` and 362/// Returns `false` if slow tests should not run, otherwise returns `true` and
325/// also creates a file at `./target/.slow_tests_cookie` which serves as a flag 363/// also creates a file at `./target/.slow_tests_cookie` which serves as a flag
326/// that slow tests did run. 364/// that slow tests did run.
diff --git a/docs/dev/debugging.md b/docs/dev/debugging.md
index 5876e71bc..48caec1d8 100644
--- a/docs/dev/debugging.md
+++ b/docs/dev/debugging.md
@@ -65,6 +65,11 @@ If you need to debug the server from the very beginning, including its initializ
65 } 65 }
66``` 66```
67 67
68However for this to work, you will need to enable debug_assertions in your build
69```rust
70RUSTFLAGS='--cfg debug_assertions' cargo build --release
71```
72
68## Demo 73## Demo
69 74
70- [Debugging TypeScript VScode extension](https://www.youtube.com/watch?v=T-hvpK6s4wM). 75- [Debugging TypeScript VScode extension](https://www.youtube.com/watch?v=T-hvpK6s4wM).