diff options
-rw-r--r-- | crates/hir_ty/src/test_db.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 151 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/coercion.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 27 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 264 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 11 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 18 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 244 |
9 files changed, 353 insertions, 380 deletions
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 | ||
88 | impl TestDB { | 88 | impl 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..c4f981b44 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -59,14 +59,16 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> { | |||
59 | } | 59 | } |
60 | 60 | ||
61 | fn check_types(ra_fixture: &str) { | 61 | fn check_types(ra_fixture: &str) { |
62 | check_types_impl(ra_fixture, false) | 62 | check_impl(ra_fixture, false, true) |
63 | } | 63 | } |
64 | 64 | ||
65 | fn check_types_source_code(ra_fixture: &str) { | 65 | fn check_types_source_code(ra_fixture: &str) { |
66 | // TODO | ||
66 | check_types_impl(ra_fixture, true) | 67 | check_types_impl(ra_fixture, true) |
67 | } | 68 | } |
68 | 69 | ||
69 | fn check_types_impl(ra_fixture: &str, display_source: bool) { | 70 | fn check_types_impl(ra_fixture: &str, display_source: bool) { |
71 | // TODO | ||
70 | let _tracing = setup_tracing(); | 72 | let _tracing = setup_tracing(); |
71 | let db = TestDB::with_files(ra_fixture); | 73 | let db = TestDB::with_files(ra_fixture); |
72 | let mut checked_one = false; | 74 | let mut checked_one = false; |
@@ -88,22 +90,47 @@ fn check_types_impl(ra_fixture: &str, display_source: bool) { | |||
88 | } | 90 | } |
89 | 91 | ||
90 | fn check_no_mismatches(ra_fixture: &str) { | 92 | fn check_no_mismatches(ra_fixture: &str) { |
91 | check_mismatches_impl(ra_fixture, true) | 93 | check_impl(ra_fixture, true, false) |
92 | } | 94 | } |
93 | 95 | ||
94 | #[allow(unused)] | 96 | fn check(ra_fixture: &str) { |
95 | fn check_mismatches(ra_fixture: &str) { | 97 | check_impl(ra_fixture, false, false) |
96 | check_mismatches_impl(ra_fixture, false) | ||
97 | } | 98 | } |
98 | 99 | ||
99 | fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | 100 | fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool) { |
100 | let _tracing = setup_tracing(); | 101 | let _tracing = setup_tracing(); |
101 | let (db, file_id) = TestDB::with_single_file(ra_fixture); | 102 | let (db, files) = TestDB::with_many_files(ra_fixture); |
102 | let module = db.module_for_file(file_id); | 103 | |
103 | let def_map = module.def_map(&db); | 104 | let mut had_annotations = false; |
105 | let mut mismatches = HashMap::new(); | ||
106 | let mut types = HashMap::new(); | ||
107 | for (file_id, annotations) in db.extract_annotations() { | ||
108 | for (range, expected) in annotations { | ||
109 | let file_range = FileRange { file_id, range }; | ||
110 | if only_types { | ||
111 | types.insert(file_range, expected); | ||
112 | } else if expected.starts_with("type: ") { | ||
113 | types.insert(file_range, expected.trim_start_matches("type: ").to_string()); | ||
114 | } else if expected.starts_with("expected") { | ||
115 | mismatches.insert(file_range, expected); | ||
116 | } else { | ||
117 | panic!("unexpected annotation: {}", expected); | ||
118 | } | ||
119 | had_annotations = true; | ||
120 | } | ||
121 | } | ||
122 | assert!(had_annotations || allow_none, "no `//^` annotations found"); | ||
104 | 123 | ||
105 | let mut defs: Vec<DefWithBodyId> = Vec::new(); | 124 | let mut defs: Vec<DefWithBodyId> = Vec::new(); |
106 | visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it)); | 125 | for file_id in files { |
126 | let module = db.module_for_file_opt(file_id); | ||
127 | let module = match module { | ||
128 | Some(m) => m, | ||
129 | None => continue, | ||
130 | }; | ||
131 | let def_map = module.def_map(&db); | ||
132 | visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it)); | ||
133 | } | ||
107 | defs.sort_by_key(|def| match def { | 134 | defs.sort_by_key(|def| match def { |
108 | DefWithBodyId::FunctionId(it) => { | 135 | DefWithBodyId::FunctionId(it) => { |
109 | let loc = it.lookup(&db); | 136 | let loc = it.lookup(&db); |
@@ -118,25 +145,46 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | |||
118 | loc.source(&db).value.syntax().text_range().start() | 145 | loc.source(&db).value.syntax().text_range().start() |
119 | } | 146 | } |
120 | }); | 147 | }); |
121 | let mut mismatches = HashMap::new(); | 148 | 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 { | 149 | for def in defs { |
136 | let (_body, body_source_map) = db.body_with_source_map(def); | 150 | let (_body, body_source_map) = db.body_with_source_map(def); |
137 | let inference_result = db.infer(def); | 151 | let inference_result = db.infer(def); |
152 | |||
153 | for (pat, ty) in inference_result.type_of_pat.iter() { | ||
154 | let node = match body_source_map.pat_syntax(pat) { | ||
155 | Ok(sp) => { | ||
156 | let root = db.parse_or_expand(sp.file_id).unwrap(); | ||
157 | sp.map(|ptr| { | ||
158 | ptr.either( | ||
159 | |it| it.to_node(&root).syntax().clone(), | ||
160 | |it| it.to_node(&root).syntax().clone(), | ||
161 | ) | ||
162 | }) | ||
163 | } | ||
164 | Err(SyntheticSyntax) => continue, | ||
165 | }; | ||
166 | let range = node.as_ref().original_file_range(&db); | ||
167 | if let Some(annotation) = types.remove(&range) { | ||
168 | assert_eq!(ty.display_test(&db).to_string(), annotation); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | for (expr, ty) in inference_result.type_of_expr.iter() { | ||
173 | let node = match body_source_map.expr_syntax(expr) { | ||
174 | Ok(sp) => { | ||
175 | let root = db.parse_or_expand(sp.file_id).unwrap(); | ||
176 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | ||
177 | } | ||
178 | Err(SyntheticSyntax) => continue, | ||
179 | }; | ||
180 | let range = node.as_ref().original_file_range(&db); | ||
181 | if let Some(annotation) = types.remove(&range) { | ||
182 | assert_eq!(ty.display_test(&db).to_string(), annotation); | ||
183 | } | ||
184 | } | ||
185 | |||
138 | for (pat, mismatch) in inference_result.pat_type_mismatches() { | 186 | for (pat, mismatch) in inference_result.pat_type_mismatches() { |
139 | let syntax_ptr = match body_source_map.pat_syntax(pat) { | 187 | let node = match body_source_map.pat_syntax(pat) { |
140 | Ok(sp) => { | 188 | Ok(sp) => { |
141 | let root = db.parse_or_expand(sp.file_id).unwrap(); | 189 | let root = db.parse_or_expand(sp.file_id).unwrap(); |
142 | sp.map(|ptr| { | 190 | sp.map(|ptr| { |
@@ -148,7 +196,17 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | |||
148 | } | 196 | } |
149 | Err(SyntheticSyntax) => continue, | 197 | Err(SyntheticSyntax) => continue, |
150 | }; | 198 | }; |
151 | push_mismatch(syntax_ptr, mismatch.clone()); | 199 | let range = node.as_ref().original_file_range(&db); |
200 | let actual = format!( | ||
201 | "expected {}, got {}", | ||
202 | mismatch.expected.display_test(&db), | ||
203 | mismatch.actual.display_test(&db) | ||
204 | ); | ||
205 | if let Some(annotation) = mismatches.remove(&range) { | ||
206 | assert_eq!(actual, annotation); | ||
207 | } else { | ||
208 | format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual); | ||
209 | } | ||
152 | } | 210 | } |
153 | for (expr, mismatch) in inference_result.expr_type_mismatches() { | 211 | for (expr, mismatch) in inference_result.expr_type_mismatches() { |
154 | let node = match body_source_map.expr_syntax(expr) { | 212 | let node = match body_source_map.expr_syntax(expr) { |
@@ -158,28 +216,37 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | |||
158 | } | 216 | } |
159 | Err(SyntheticSyntax) => continue, | 217 | Err(SyntheticSyntax) => continue, |
160 | }; | 218 | }; |
161 | push_mismatch(node, mismatch.clone()); | 219 | let range = node.as_ref().original_file_range(&db); |
162 | } | 220 | let actual = format!( |
163 | } | 221 | "expected {}, got {}", |
164 | let mut checked_one = false; | 222 | mismatch.expected.display_test(&db), |
165 | for (file_id, annotations) in db.extract_annotations() { | 223 | mismatch.actual.display_test(&db) |
166 | for (range, expected) in annotations { | 224 | ); |
167 | let file_range = FileRange { file_id, range }; | 225 | if let Some(annotation) = mismatches.remove(&range) { |
168 | if let Some(mismatch) = mismatches.remove(&file_range) { | 226 | assert_eq!(actual, annotation); |
169 | assert_eq!(mismatch, expected); | ||
170 | } else { | 227 | } else { |
171 | assert!(false, "Expected mismatch not encountered: {}\n", expected); | 228 | format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual); |
172 | } | 229 | } |
173 | checked_one = true; | ||
174 | } | 230 | } |
175 | } | 231 | } |
232 | |||
176 | let mut buf = String::new(); | 233 | let mut buf = String::new(); |
177 | for (range, mismatch) in mismatches { | 234 | if !unexpected_type_mismatches.is_empty() { |
178 | format_to!(buf, "{:?}: {}\n", range.range, mismatch,); | 235 | format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches); |
179 | } | 236 | } |
180 | assert!(buf.is_empty(), "Unexpected type mismatches:\n{}", buf); | 237 | if !mismatches.is_empty() { |
181 | 238 | format_to!(buf, "Unchecked mismatch annotations:\n"); | |
182 | assert!(checked_one || allow_none, "no `//^` annotations found"); | 239 | for m in mismatches { |
240 | format_to!(buf, "{:?}: {}\n", m.0.range, m.1); | ||
241 | } | ||
242 | } | ||
243 | if !types.is_empty() { | ||
244 | format_to!(buf, "Unchecked type annotations:\n"); | ||
245 | for t in types { | ||
246 | format_to!(buf, "{:?}: type {}\n", t.0.range, t.1); | ||
247 | } | ||
248 | } | ||
249 | assert!(buf.is_empty(), "{}", buf); | ||
183 | } | 250 | } |
184 | 251 | ||
185 | fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { | 252 | fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { |
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs index 713b74165..24ce5bcca 100644 --- a/crates/hir_ty/src/tests/coercion.rs +++ b/crates/hir_ty/src/tests/coercion.rs | |||
@@ -842,9 +842,9 @@ fn infer_two_closures_lub() { | |||
842 | fn foo(c: i32) { | 842 | fn foo(c: i32) { |
843 | let add = |a: i32, b: i32| a + b; | 843 | let add = |a: i32, b: i32| a + b; |
844 | let sub = |a, b| a - b; | 844 | let sub = |a, b| a - b; |
845 | //^ |i32, i32| -> i32 | 845 | //^^^^^^^^^^^^ |i32, i32| -> i32 |
846 | if c > 42 { add } else { sub }; | 846 | if c > 42 { add } else { sub }; |
847 | //^ fn(i32, i32) -> i32 | 847 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32 |
848 | } | 848 | } |
849 | "#, | 849 | "#, |
850 | ) | 850 | ) |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index d14103aab..6c3d46caf 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() { | |||
435 | macro_rules! m { | 435 | macro_rules! m { |
436 | ($ident:ident) => (impl Trait for $ident {}) | 436 | ($ident:ident) => (impl Trait for $ident {}) |
437 | } | 437 | } |
438 | trait Trait { fn foo(self) -> u128 {} } | 438 | trait Trait { fn foo(self) -> u128 { 0 } } |
439 | struct S; | 439 | struct S; |
440 | m!(S); | 440 | m!(S); |
441 | fn test() { S.foo(); } | 441 | fn test() { S.foo(); } |
442 | //^ u128 | 442 | //^^^^^^^ u128 |
443 | "#, | 443 | "#, |
444 | ); | 444 | ); |
445 | } | 445 | } |
@@ -457,7 +457,7 @@ impl S { | |||
457 | } | 457 | } |
458 | 458 | ||
459 | fn test() { S.foo(); } | 459 | fn test() { S.foo(); } |
460 | //^ u128 | 460 | //^^^^^^^ u128 |
461 | "#, | 461 | "#, |
462 | ); | 462 | ); |
463 | } | 463 | } |
@@ -479,7 +479,7 @@ impl S { | |||
479 | } | 479 | } |
480 | 480 | ||
481 | fn test() { S.foo(); } | 481 | fn test() { S.foo(); } |
482 | //^ u128 | 482 | //^^^^^^^ u128 |
483 | "#, | 483 | "#, |
484 | ); | 484 | ); |
485 | } | 485 | } |
@@ -743,7 +743,7 @@ include!("foo.rs"); | |||
743 | 743 | ||
744 | fn main() { | 744 | fn main() { |
745 | bar(); | 745 | bar(); |
746 | } //^ u32 | 746 | } //^^^^^ u32 |
747 | 747 | ||
748 | //- /foo.rs | 748 | //- /foo.rs |
749 | fn bar() -> u32 {0} | 749 | fn bar() -> u32 {0} |
@@ -781,7 +781,7 @@ include!("f/foo.rs"); | |||
781 | 781 | ||
782 | fn main() { | 782 | fn main() { |
783 | bar::bar(); | 783 | bar::bar(); |
784 | } //^ u32 | 784 | } //^^^^^^^^^^ u32 |
785 | 785 | ||
786 | //- /f/foo.rs | 786 | //- /f/foo.rs |
787 | pub mod bar; | 787 | pub mod bar; |
@@ -879,7 +879,7 @@ include!(concat!("f", "oo.rs")); | |||
879 | 879 | ||
880 | fn main() { | 880 | fn main() { |
881 | bar(); | 881 | bar(); |
882 | } //^ u32 | 882 | } //^^^^^ u32 |
883 | 883 | ||
884 | //- /foo.rs | 884 | //- /foo.rs |
885 | fn bar() -> u32 {0} | 885 | fn bar() -> u32 {0} |
@@ -905,7 +905,7 @@ include!(concat!(env!("OUT_DIR"), "/foo.rs")); | |||
905 | 905 | ||
906 | fn main() { | 906 | fn main() { |
907 | bar(); | 907 | bar(); |
908 | } //^ {unknown} | 908 | } //^^^^^ {unknown} |
909 | 909 | ||
910 | //- /foo.rs | 910 | //- /foo.rs |
911 | fn bar() -> u32 {0} | 911 | fn bar() -> u32 {0} |
@@ -923,7 +923,7 @@ macro_rules! include {() => {}} | |||
923 | include!("main.rs"); | 923 | include!("main.rs"); |
924 | 924 | ||
925 | fn main() { | 925 | fn main() { |
926 | 0 | 926 | 0; |
927 | } //^ i32 | 927 | } //^ i32 |
928 | "#, | 928 | "#, |
929 | ); | 929 | ); |
@@ -979,7 +979,7 @@ fn infer_derive_clone_simple() { | |||
979 | struct S; | 979 | struct S; |
980 | fn test() { | 980 | fn test() { |
981 | S.clone(); | 981 | S.clone(); |
982 | } //^ S | 982 | } //^^^^^^^^^ S |
983 | 983 | ||
984 | //- /lib.rs crate:core | 984 | //- /lib.rs crate:core |
985 | pub mod prelude { | 985 | pub mod prelude { |
@@ -1028,7 +1028,7 @@ pub struct S; | |||
1028 | use core::S; | 1028 | use core::S; |
1029 | fn test() { | 1029 | fn test() { |
1030 | S.clone(); | 1030 | S.clone(); |
1031 | } //^ S | 1031 | } //^^^^^^^^^ S |
1032 | "#, | 1032 | "#, |
1033 | ); | 1033 | ); |
1034 | } | 1034 | } |
@@ -1044,7 +1044,8 @@ struct S; | |||
1044 | struct Wrapper<T>(T); | 1044 | struct Wrapper<T>(T); |
1045 | struct NonClone; | 1045 | struct NonClone; |
1046 | fn test() { | 1046 | fn 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 | ||
1080 | fn test() { | 1081 | fn 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() { | |||
257 | mod foo { | 257 | mod 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] |
268 | fn infer_trait_method_simple() { | 268 | fn 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 { | 272 | trait Trait1 { |
273 | fn method(&self) -> u32; | 273 | fn method(&self) -> u32; |
274 | } | 274 | } |
275 | struct S1; | 275 | struct S1; |
276 | impl Trait1 for S1 {} | 276 | impl Trait1 for S1 {} |
277 | trait Trait2 { | 277 | trait Trait2 { |
278 | fn method(&self) -> i128; | 278 | fn method(&self) -> i128; |
279 | } | 279 | } |
280 | struct S2; | 280 | struct S2; |
281 | impl Trait2 for S2 {} | 281 | impl Trait2 for S2 {} |
282 | fn test() { | 282 | fn 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] |
300 | fn infer_trait_method_scoped() { | 293 | fn 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; | 297 | struct S; |
305 | mod foo { | 298 | mod 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 { | 304 | mod 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 { | 311 | mod 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 { | 320 | mod 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] |
348 | fn infer_trait_method_generic_1() { | 333 | fn 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> { | 337 | trait Trait<T> { |
353 | fn method(&self) -> T; | 338 | fn method(&self) -> T; |
354 | } | 339 | } |
355 | struct S; | 340 | struct S; |
356 | impl Trait<u32> for S {} | 341 | impl Trait<u32> for S {} |
357 | fn test() { | 342 | fn 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] |
371 | fn infer_trait_method_generic_more_params() { | 351 | fn 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> { | 355 | trait 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; | 359 | struct S1; |
380 | impl Trait<u8, u16, u32> for S1 {} | 360 | impl Trait<u8, u16, u32> for S1 {} |
381 | struct S2; | 361 | struct S2; |
382 | impl<T> Trait<i8, i16, T> for S2 {} | 362 | impl<T> Trait<i8, i16, T> for S2 {} |
383 | fn test() { | 363 | fn 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] |
407 | fn infer_trait_method_generic_2() { | 378 | fn 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> { | 382 | trait Trait<T> { |
412 | fn method(&self) -> T; | 383 | fn method(&self) -> T; |
413 | } | 384 | } |
414 | struct S<T>(T); | 385 | struct S<T>(T); |
415 | impl<U> Trait<U> for S<U> {} | 386 | impl<U> Trait<U> for S<U> {} |
416 | fn test() { | 387 | fn 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#" |
687 | struct S<T>; | 651 | struct S<T>; |
688 | impl S<u32> { fn foo(&self) -> u8 {} } | 652 | impl S<u32> { fn foo(&self) -> u8 { 0 } } |
689 | impl S<i32> { fn foo(&self) -> i8 {} } | 653 | impl S<i32> { fn foo(&self) -> i8 { 0 } } |
690 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } | 654 | fn 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; | |||
702 | impl S { fn foo(&self) -> i8 { 0 } } | 666 | impl S { fn foo(&self) -> i8 { 0 } } |
703 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 667 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
704 | fn test() { S.foo(); } | 668 | fn test() { S.foo(); } |
705 | //^ u128 | 669 | //^^^^^^^ u128 |
706 | "#, | 670 | "#, |
707 | ); | 671 | ); |
708 | } | 672 | } |
@@ -716,7 +680,7 @@ struct S; | |||
716 | impl Clone for S {} | 680 | impl Clone for S {} |
717 | impl Clone for &S {} | 681 | impl Clone for &S {} |
718 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } | 682 | fn 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; | |||
730 | impl S { fn foo(self) -> i8 { 0 } } | 694 | impl S { fn foo(self) -> i8 { 0 } } |
731 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 695 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
732 | fn test() { (&S).foo(); } | 696 | fn test() { (&S).foo(); } |
733 | //^ u128 | 697 | //^^^^^^^^^^ u128 |
734 | "#, | 698 | "#, |
735 | ); | 699 | ); |
736 | } | 700 | } |
@@ -744,7 +708,7 @@ struct S; | |||
744 | impl S { fn foo(self) -> i8 { 0 } } | 708 | impl S { fn foo(self) -> i8 { 0 } } |
745 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 709 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
746 | fn test() { S.foo(); } | 710 | fn test() { S.foo(); } |
747 | //^ i8 | 711 | //^^^^^^^ i8 |
748 | "#, | 712 | "#, |
749 | ); | 713 | ); |
750 | } | 714 | } |
@@ -758,7 +722,7 @@ struct S; | |||
758 | impl S { fn foo(&self) -> i8 { 0 } } | 722 | impl S { fn foo(&self) -> i8 { 0 } } |
759 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 723 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
760 | fn test() { S.foo(); } | 724 | fn test() { S.foo(); } |
761 | //^ i8 | 725 | //^^^^^^^ i8 |
762 | "#, | 726 | "#, |
763 | ); | 727 | ); |
764 | } | 728 | } |
@@ -771,7 +735,7 @@ trait Trait { fn foo(self) -> u128; } | |||
771 | struct S; | 735 | struct S; |
772 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 736 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
773 | fn test() { (&S).foo(); } | 737 | fn test() { (&S).foo(); } |
774 | //^ u128 | 738 | //^^^^^^^^^^ u128 |
775 | "#, | 739 | "#, |
776 | ); | 740 | ); |
777 | } | 741 | } |
@@ -784,7 +748,7 @@ fn method_resolution_unsize_array() { | |||
784 | fn test() { | 748 | fn 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 | ||
800 | fn test() { | 764 | fn 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; } | |||
823 | struct S; | 787 | struct S; |
824 | impl<T> Trait for T where T: UnknownTrait {} | 788 | impl<T> Trait for T where T: UnknownTrait {} |
825 | fn test() { (&S).foo(); } | 789 | fn test() { (&S).foo(); } |
826 | //^ u128 | 790 | //^^^^^^^^^^ u128 |
827 | "#, | 791 | "#, |
828 | ); | 792 | ); |
829 | } | 793 | } |
@@ -841,7 +805,7 @@ trait Trait { fn foo(self) -> u128; } | |||
841 | struct S; | 805 | struct S; |
842 | impl<T> Trait for T where T: Clone {} | 806 | impl<T> Trait for T where T: Clone {} |
843 | fn test() { (&S).foo(); } | 807 | fn test() { (&S).foo(); } |
844 | //^ {unknown} | 808 | //^^^^^^^^^^ {unknown} |
845 | "#, | 809 | "#, |
846 | ); | 810 | ); |
847 | } | 811 | } |
@@ -856,7 +820,7 @@ trait Trait { fn foo(self) -> u128; } | |||
856 | struct S; | 820 | struct S; |
857 | impl<T: Clone> Trait for T {} | 821 | impl<T: Clone> Trait for T {} |
858 | fn test() { (&S).foo(); } | 822 | fn test() { (&S).foo(); } |
859 | //^ {unknown} | 823 | //^^^^^^^^^^ {unknown} |
860 | "#, | 824 | "#, |
861 | ); | 825 | ); |
862 | } | 826 | } |
@@ -871,7 +835,7 @@ struct S; | |||
871 | impl Clone for S {} | 835 | impl Clone for S {} |
872 | impl<T> Trait for T where T: Clone {} | 836 | impl<T> Trait for T where T: Clone {} |
873 | fn test() { S.foo(); } | 837 | fn test() { S.foo(); } |
874 | //^ u128 | 838 | //^^^^^^^ u128 |
875 | "#, | 839 | "#, |
876 | ); | 840 | ); |
877 | } | 841 | } |
@@ -887,7 +851,7 @@ struct S2; | |||
887 | impl From<S2> for S1 {} | 851 | impl From<S2> for S1 {} |
888 | impl<T, U> Into<U> for T where U: From<T> {} | 852 | impl<T, U> Into<U> for T where U: From<T> {} |
889 | fn test() { S2.into(); } | 853 | fn test() { S2.into(); } |
890 | //^ {unknown} | 854 | //^^^^^^^^^ {unknown} |
891 | "#, | 855 | "#, |
892 | ); | 856 | ); |
893 | } | 857 | } |
@@ -903,7 +867,7 @@ struct S2; | |||
903 | impl From<S2> for S1 {} | 867 | impl From<S2> for S1 {} |
904 | impl<T, U: From<T>> Into<U> for T {} | 868 | impl<T, U: From<T>> Into<U> for T {} |
905 | fn test() { S2.into(); } | 869 | fn 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() { | |||
947 | fn foo() {} | 911 | fn foo() {} |
948 | trait FnOnce { fn call(self); } | 912 | trait FnOnce { fn call(self); } |
949 | fn test() { foo.call(); } | 913 | fn 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 | ||
1031 | fn main() { | 995 | fn 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 {} | |||
1058 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | 1022 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} |
1059 | 1023 | ||
1060 | fn test() { (S {}).method(); } | 1024 | fn test() { (S {}).method(); } |
1061 | //^ () | 1025 | //^^^^^^^^^^^^^^^ () |
1062 | "#, | 1026 | "#, |
1063 | ); | 1027 | ); |
1064 | } | 1028 | } |
@@ -1143,8 +1107,8 @@ impl<T> Slice<T> { | |||
1143 | 1107 | ||
1144 | fn main() { | 1108 | fn 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 + '_ { | |||
1165 | fn main() { | 1129 | fn 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 | ||
1377 | impl<T> IntoIterator for [T; 1] { | 1341 | impl<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 | } |
1381 | impl<'a, T> IntoIterator for &'a [T] { | 1345 | impl<'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 @@ | |||
1 | use expect_test::expect; | 1 | use expect_test::expect; |
2 | 2 | ||
3 | use super::{check_infer, check_infer_with_mismatches, check_mismatches, check_types}; | 3 | use super::{check, check_infer, check_infer_with_mismatches, check_types}; |
4 | 4 | ||
5 | #[test] | 5 | #[test] |
6 | fn infer_pattern() { | 6 | fn infer_pattern() { |
@@ -518,7 +518,7 @@ fn infer_generics_in_patterns() { | |||
518 | 518 | ||
519 | #[test] | 519 | #[test] |
520 | fn infer_const_pattern() { | 520 | fn infer_const_pattern() { |
521 | check_mismatches( | 521 | check( |
522 | r#" | 522 | r#" |
523 | enum Option<T> { None } | 523 | enum Option<T> { None } |
524 | use Option::None; | 524 | use 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 @@ | |||
1 | use expect_test::expect; | 1 | use expect_test::expect; |
2 | 2 | ||
3 | use super::{check_infer, check_types}; | 3 | use super::{check_infer, check_no_mismatches, check_types}; |
4 | 4 | ||
5 | #[test] | 5 | #[test] |
6 | fn bug_484() { | 6 | fn bug_484() { |
@@ -422,20 +422,20 @@ fn issue_2683_chars_impl() { | |||
422 | pub struct Chars<'a> {} | 422 | pub struct Chars<'a> {} |
423 | impl<'a> Iterator for Chars<'a> { | 423 | impl<'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 | ||
428 | fn test() { | 428 | fn 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] |
437 | fn issue_3642_bad_macro_stackover() { | 437 | fn issue_3642_bad_macro_stackover() { |
438 | check_types( | 438 | check_no_mismatches( |
439 | r#" | 439 | r#" |
440 | #[macro_export] | 440 | #[macro_export] |
441 | macro_rules! match_ast { | 441 | macro_rules! match_ast { |
@@ -452,7 +452,6 @@ macro_rules! match_ast { | |||
452 | 452 | ||
453 | fn main() { | 453 | fn 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 | ||
957 | fn clone_iter<T>(s: Iter<T>) { | 956 | fn 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 } | |||
60 | fn test() { | 60 | fn 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 } | |||
138 | fn test() { | 138 | fn 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 } } | |||
1745 | fn main() { | 1745 | fn 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 | ||
1782 | fn main() { | 1782 | fn 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 | ||
1800 | fn main() { | 1800 | fn 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 | ||
1826 | fn main() { | 1826 | fn 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 |
2678 | fn f() { | 2678 | fn 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 @@ | |||
1 | use cov_mark::check; | ||
1 | use expect_test::expect; | 2 | use expect_test::expect; |
2 | 3 | ||
3 | use super::{check_infer, check_infer_with_mismatches, check_types}; | 4 | use super::{check, check_infer, check_infer_with_mismatches, check_types}; |
4 | 5 | ||
5 | #[test] | 6 | #[test] |
6 | fn infer_await() { | 7 | fn infer_await() { |
@@ -285,7 +286,7 @@ mod ops { | |||
285 | 286 | ||
286 | #[test] | 287 | #[test] |
287 | fn infer_from_bound_1() { | 288 | fn infer_from_bound_1() { |
288 | check_infer( | 289 | check_types( |
289 | r#" | 290 | r#" |
290 | trait Trait<T> {} | 291 | trait Trait<T> {} |
291 | struct S<T>(T); | 292 | struct S<T>(T); |
@@ -293,99 +294,62 @@ impl<U> Trait<U> for S<U> {} | |||
293 | fn foo<T: Trait<u32>>(t: T) {} | 294 | fn foo<T: Trait<u32>>(t: T) {} |
294 | fn test() { | 295 | fn 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] |
314 | fn infer_from_bound_2() { | 304 | fn infer_from_bound_2() { |
315 | check_infer( | 305 | check_types( |
316 | r#" | 306 | r#" |
317 | trait Trait<T> {} | 307 | trait Trait<T> {} |
318 | struct S<T>(T); | 308 | struct S<T>(T); |
319 | impl<U> Trait<U> for S<U> {} | 309 | impl<U> Trait<U> for S<U> {} |
320 | fn foo<U, T: Trait<U>>(t: T) -> U {} | 310 | fn foo<U, T: Trait<U>>(t: T) -> U { loop {} } |
321 | fn test() { | 311 | fn 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] |
342 | fn trait_default_method_self_bound_implements_trait() { | 320 | fn 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#" |
346 | trait Trait { | 324 | trait 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] |
364 | fn trait_default_method_self_bound_implements_super_trait() { | 335 | fn trait_default_method_self_bound_implements_super_trait() { |
365 | check_infer( | 336 | check( |
366 | r#" | 337 | r#" |
367 | trait SuperTrait { | 338 | trait SuperTrait { |
368 | fn foo(&self) -> i64; | 339 | fn foo(&self) -> i64; |
369 | } | 340 | } |
370 | trait Trait: SuperTrait { | 341 | trait 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] |
387 | fn infer_project_associated_type() { | 351 | fn infer_project_associated_type() { |
388 | check_infer( | 352 | check_types( |
389 | r#" | 353 | r#" |
390 | trait Iterable { | 354 | trait Iterable { |
391 | type Item; | 355 | type Item; |
@@ -394,89 +358,62 @@ struct S; | |||
394 | impl Iterable for S { type Item = u32; } | 358 | impl Iterable for S { type Item = u32; } |
395 | fn test<T: Iterable>() { | 359 | fn 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] |
416 | fn infer_return_associated_type() { | 373 | fn infer_return_associated_type() { |
417 | check_infer( | 374 | check_types( |
418 | r#" | 375 | r#" |
419 | trait Iterable { | 376 | trait Iterable { |
420 | type Item; | 377 | type Item; |
421 | } | 378 | } |
422 | struct S; | 379 | struct S; |
423 | impl Iterable for S { type Item = u32; } | 380 | impl Iterable for S { type Item = u32; } |
424 | fn foo1<T: Iterable>(t: T) -> T::Item {} | 381 | fn foo1<T: Iterable>(t: T) -> T::Item { loop {} } |
425 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} | 382 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item { loop {} } |
426 | fn foo3<T: Iterable>(t: T) -> <T>::Item {} | 383 | fn foo3<T: Iterable>(t: T) -> <T>::Item { loop {} } |
427 | fn test() { | 384 | fn 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] |
457 | fn infer_associated_type_bound() { | 396 | fn infer_associated_type_bound() { |
458 | check_infer( | 397 | check_types( |
459 | r#" | 398 | r#" |
460 | trait Iterable { | 399 | trait Iterable { |
461 | type Item; | 400 | type Item; |
462 | } | 401 | } |
463 | fn test<T: Iterable<Item=u32>>() { | 402 | fn 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] |
475 | fn infer_const_body() { | 410 | fn infer_const_body() { |
411 | // FIXME make check_types work with other bodies | ||
476 | check_infer( | 412 | check_infer( |
477 | r#" | 413 | r#" |
478 | const A: u32 = 1 + 1; | 414 | const A: u32 = 1 + 1; |
479 | static B: u64 = { let x = 1; x };"#, | 415 | static 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 | ||
638 | struct S; | 575 | struct S; |
639 | impl S { | 576 | impl S { |
640 | fn foo(&self) -> u128 {} | 577 | fn foo(&self) -> u128 { 0 } |
641 | } | 578 | } |
642 | 579 | ||
643 | fn test(s: Arc<S>) { | 580 | fn 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 |
655 | struct Arc<T>; | 592 | struct Arc<T>; |
656 | fn new_arc<T>() -> Arc<T> {} | 593 | fn new_arc<T>() -> Arc<T> { Arc } |
657 | impl<T> core::ops::Deref for Arc<T> { | 594 | impl<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 | ||
664 | fn test() { | 601 | fn 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 | ||
685 | fn test(s: S) { | 622 | fn 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 | ||
702 | struct S; | 639 | struct S; |
703 | impl S { | 640 | impl S { |
704 | fn foo(&self) -> u128 {} | 641 | fn foo(&self) -> u128 { 0 } |
705 | } | 642 | } |
706 | 643 | ||
707 | fn test(s: Arc<S>) { | 644 | fn 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; | |||
720 | trait Trait<T> {} | 657 | trait Trait<T> {} |
721 | impl Trait<u32> for S {} | 658 | impl Trait<u32> for S {} |
722 | 659 | ||
723 | fn foo<T: Trait<U>, U>(t: T) -> U {} | 660 | fn foo<T: Trait<U>, U>(t: T) -> U { loop {} } |
724 | 661 | ||
725 | fn test(s: S) { | 662 | fn 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 | ||
742 | struct O; | 679 | struct O; |
743 | impl O { | 680 | impl 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 | ||
747 | fn test() { | 684 | fn 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> {} | |||
761 | impl Trait<i64> for S {} | 698 | impl Trait<i64> for S {} |
762 | 699 | ||
763 | impl S { | 700 | impl 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 | ||
767 | fn test() { | 704 | fn 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 | ||
783 | struct O<T>; | 720 | struct O<T>; |
784 | impl<U, T: Trait<U>> O<T> { | 721 | impl<U, T: Trait<U>> O<T> { |
785 | fn foo(&self) -> U {} | 722 | fn foo(&self) -> U { loop {} } |
786 | } | 723 | } |
787 | 724 | ||
788 | fn test(o: O<S>) { | 725 | fn 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; | |||
802 | impl Clone for S {} | 739 | impl Clone for S {} |
803 | impl<T> Trait for T where T: Clone {} | 740 | impl<T> Trait for T where T: Clone {} |
804 | fn test<T: Clone>(t: T) { t.foo(); } | 741 | fn test<T: Clone>(t: T) { t.foo(); } |
805 | //^ u128 | 742 | //^^^^^^^ u128 |
806 | "#, | 743 | "#, |
807 | ); | 744 | ); |
808 | } | 745 | } |
@@ -818,7 +755,7 @@ struct S; | |||
818 | impl Clone for S {} | 755 | impl Clone for S {} |
819 | impl<T> Trait for T where T: Clone {} | 756 | impl<T> Trait for T where T: Clone {} |
820 | fn test<T>(t: T) { t.foo(); } | 757 | fn 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; } | |||
831 | struct S; | 768 | struct S; |
832 | impl Trait for S {} | 769 | impl Trait for S {} |
833 | fn test<T: Trait>(t: T) { t.foo(); } | 770 | fn 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; } | |||
844 | struct S; | 781 | struct S; |
845 | impl Trait for S {} | 782 | impl Trait for S {} |
846 | fn test<T>(t: T) { t.foo(); } | 783 | fn test<T>(t: T) { t.foo(); } |
847 | //^ {unknown} | 784 | //^^^^^^^ {unknown} |
848 | "#, | 785 | "#, |
849 | ); | 786 | ); |
850 | } | 787 | } |
@@ -858,8 +795,8 @@ trait Trait {} | |||
858 | impl<T> core::ops::Deref for T where T: Trait { | 795 | impl<T> core::ops::Deref for T where T: Trait { |
859 | type Target = i128; | 796 | type Target = i128; |
860 | } | 797 | } |
861 | fn test<T: Trait>(t: T) { (*t); } | 798 | fn 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#" |
1382 | trait Trait { | 1319 | trait Trait { |
1383 | fn foo(&self) -> u32 {} | 1320 | fn foo(&self) -> u32 { 0 } |
1384 | } | 1321 | } |
1385 | 1322 | ||
1386 | fn test(x: (impl Trait + UnknownTrait)) { | 1323 | fn 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 { | |||
1476 | fn api_walkthrough() { | 1413 | fn 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#" |
1514 | mod foo { | 1451 | mod foo { |
1515 | trait Trait { | 1452 | trait Trait { |
1516 | fn foo(&self) -> u32 {} | 1453 | fn foo(&self) -> u32 { 0 } |
1517 | } | 1454 | } |
1518 | } | 1455 | } |
1519 | 1456 | ||
1520 | fn test<T: foo::Trait>(x: T) { | 1457 | fn 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 |
1983 | struct S; | 1920 | struct S; |
1984 | 1921 | ||
1985 | fn foo() -> S {} | 1922 | fn foo() -> S { S } |
1986 | 1923 | ||
1987 | fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } | 1924 | fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } |
1988 | 1925 | ||
@@ -2009,7 +1946,7 @@ trait Trait2 { | |||
2009 | fn test<T: Trait>() where T::Item: Trait2 { | 1946 | fn 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 { | |||
2029 | fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { | 1966 | fn 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 | ||
2093 | fn test() { | 2030 | fn test() { |
2094 | S.f(); | 2031 | S.f(); |
2095 | } //^ u32 | 2032 | } //^^^^^ u32 |
2096 | "#, | 2033 | "#, |
2097 | ); | 2034 | ); |
2098 | } | 2035 | } |
@@ -2120,7 +2057,7 @@ where | |||
2120 | 2057 | ||
2121 | fn foo<I: Interner>(interner: &I, t: Ty<I>) { | 2058 | fn 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 | ||
2140 | fn test() { | 2077 | fn 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 | ||
2159 | fn test() { | 2096 | fn 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 | ||
2177 | fn test<T: Trait>() where T: Trait2<T::Item> { | 2114 | fn 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 | ||
2194 | fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | 2131 | fn 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 | ||
2212 | fn test<T>() where T: Trait<OtherItem = T::Item> { | 2149 | fn 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> { | |||
2268 | fn test<I: Iterator<Item: OtherTrait<u32>>>() { | 2205 | fn 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> { | |||
2470 | fn test<T: Trait>() { | 2407 | fn 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 | ||
2491 | fn test(x: Box<dyn Trait>) { | 2428 | fn 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 | } |
2510 | fn test() { | 2447 | fn 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 | ||
2650 | fn main() { | 2587 | fn 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 | } |
3479 | impl Convert for u32 { | 3416 | impl Convert for u32 { |
3480 | fn new() -> Self { | 3417 | fn new() -> Self { 0 } |
3481 | 0 | ||
3482 | } | ||
3483 | } | 3418 | } |
3484 | 3419 | ||
3485 | async fn get_accounts() -> Result<u32, ()> { | 3420 | async 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] |
3495 | fn local_impl_1() { | 3430 | fn local_impl_1() { |
3431 | check!(block_local_impls); | ||
3496 | check_types( | 3432 | check_types( |
3497 | r#" | 3433 | r#" |
3498 | trait Trait<T> { | 3434 | trait Trait<T> { |
@@ -3502,7 +3438,7 @@ trait Trait<T> { | |||
3502 | fn test() { | 3438 | fn 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] |
3516 | fn local_impl_2() { | 3452 | fn local_impl_2() { |
3453 | check!(block_local_impls); | ||
3517 | check_types( | 3454 | check_types( |
3518 | r#" | 3455 | r#" |
3519 | struct S; | 3456 | struct 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] |
3537 | fn local_impl_3() { | 3474 | fn local_impl_3() { |
3475 | check!(block_local_impls); | ||
3538 | check_types( | 3476 | check_types( |
3539 | r#" | 3477 | r#" |
3540 | trait Trait<T> { | 3478 | trait 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(); |