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/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/context.rs65
-rw-r--r--crates/ide_completion/src/render.rs75
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs109
-rw-r--r--crates/test_utils/src/lib.rs50
-rw-r--r--docs/dev/debugging.md5
22 files changed, 792 insertions, 1207 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/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/context.rs b/crates/ide_completion/src/context.rs
index 4814bd64d..f0da98739 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -388,14 +388,19 @@ impl<'a> CompletionContext<'a> {
388 (ty, name) 388 (ty, name)
389 }, 389 },
390 ast::ArgList(_it) => { 390 ast::ArgList(_it) => {
391 cov_mark::hit!(expected_type_fn_param_with_leading_char); 391 cov_mark::hit!(expected_type_fn_param);
392 cov_mark::hit!(expected_type_fn_param_without_leading_char);
393 ActiveParameter::at_token( 392 ActiveParameter::at_token(
394 &self.sema, 393 &self.sema,
395 self.token.clone(), 394 self.token.clone(),
396 ).map(|ap| { 395 ).map(|ap| {
397 let name = ap.ident().map(NameOrNameRef::Name); 396 let name = ap.ident().map(NameOrNameRef::Name);
398 (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)
399 }) 404 })
400 .unwrap_or((None, None)) 405 .unwrap_or((None, None))
401 }, 406 },
@@ -700,6 +705,19 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
700 use_tree.path().zip(Some(true)) 705 use_tree.path().zip(Some(true))
701} 706}
702 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
703#[cfg(test)] 721#[cfg(test)]
704mod tests { 722mod tests {
705 use expect_test::{expect, Expect}; 723 use expect_test::{expect, Expect};
@@ -772,14 +790,18 @@ fn foo() {
772 } 790 }
773 791
774 #[test] 792 #[test]
775 fn expected_type_fn_param_without_leading_char() { 793 fn expected_type_fn_param() {
776 cov_mark::check!(expected_type_fn_param_without_leading_char); 794 cov_mark::check!(expected_type_fn_param);
777 check_expected_type_and_name( 795 check_expected_type_and_name(
778 r#" 796 r#"
779fn foo() { 797fn foo() { bar($0); }
780 bar($0); 798fn bar(x: u32) {}
781} 799"#,
782 800 expect![[r#"ty: u32, name: x"#]],
801 );
802 check_expected_type_and_name(
803 r#"
804fn foo() { bar(c$0); }
783fn bar(x: u32) {} 805fn bar(x: u32) {}
784"#, 806"#,
785 expect![[r#"ty: u32, name: x"#]], 807 expect![[r#"ty: u32, name: x"#]],
@@ -787,18 +809,29 @@ fn bar(x: u32) {}
787 } 809 }
788 810
789 #[test] 811 #[test]
790 fn expected_type_fn_param_with_leading_char() { 812 fn expected_type_fn_param_ref() {
791 cov_mark::check!(expected_type_fn_param_with_leading_char); 813 cov_mark::check!(expected_type_fn_param_ref);
792 check_expected_type_and_name( 814 check_expected_type_and_name(
793 r#" 815 r#"
794fn foo() { 816fn foo() { bar(&$0); }
795 bar(c$0); 817fn bar(x: &u32) {}
796}
797
798fn bar(x: u32) {}
799"#, 818"#,
800 expect![[r#"ty: u32, name: x"#]], 819 expect![[r#"ty: u32, name: x"#]],
801 ); 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 );
802 } 835 }
803 836
804 #[test] 837 #[test]
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_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/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).