aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock70
-rw-r--r--crates/base_db/src/fixture.rs39
-rw-r--r--crates/hir/src/has_source.rs2
-rw-r--r--crates/hir_def/src/generics.rs10
-rw-r--r--crates/hir_def/src/item_tree/lower.rs2
-rw-r--r--crates/hir_def/src/nameres/collector.rs39
-rw-r--r--crates/hir_ty/Cargo.toml2
-rw-r--r--crates/hir_ty/src/tests/coercion.rs650
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs99
-rw-r--r--crates/hir_ty/src/tests/regression.rs98
-rw-r--r--crates/hir_ty/src/tests/simple.rs767
-rw-r--r--crates/hir_ty/src/tests/traits.rs125
-rw-r--r--crates/ide/Cargo.toml1
-rw-r--r--crates/ide/src/diagnostics.rs498
-rw-r--r--crates/ide/src/display/navigation_target.rs6
-rw-r--r--crates/ide/src/doc_links.rs18
-rw-r--r--crates/ide/src/fixture.rs8
-rw-r--r--crates/ide/src/goto_definition.rs10
-rw-r--r--crates/ide/src/goto_type_definition.rs62
-rw-r--r--crates/ide/src/hover.rs20
-rw-r--r--crates/ide/src/lib.rs26
-rw-r--r--crates/ide/src/references.rs2
-rw-r--r--crates/ide/src/rename.rs (renamed from crates/ide/src/references/rename.rs)459
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs50
-rw-r--r--crates/ide/src/syntax_highlighting/html.rs1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_injection.html1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_strings.html1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/injection.html1
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/rainbow_highlighting.html1
-rw-r--r--crates/ide/src/syntax_highlighting/tests.rs5
-rw-r--r--crates/ide_assists/src/handlers/fix_visibility.rs34
-rw-r--r--crates/ide_assists/src/handlers/generate_function.rs49
-rw-r--r--crates/ide_assists/src/handlers/qualify_path.rs1201
-rw-r--r--crates/ide_assists/src/handlers/replace_impl_trait_with_generic.rs5
-rw-r--r--crates/ide_assists/src/lib.rs163
-rw-r--r--crates/ide_assists/src/tests.rs26
-rw-r--r--crates/ide_completion/src/completions/attribute/derive.rs49
-rw-r--r--crates/ide_completion/src/completions/keyword.rs20
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs18
-rw-r--r--crates/ide_completion/src/render.rs12
-rw-r--r--crates/ide_db/src/assists.rs136
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs7
-rw-r--r--crates/ide_db/src/lib.rs5
-rw-r--r--crates/ide_db/src/rename.rs468
-rw-r--r--crates/ide_diagnostics/Cargo.toml29
-rw-r--r--crates/ide_diagnostics/src/handlers/break_outside_of_loop.rs (renamed from crates/ide/src/diagnostics/break_outside_of_loop.rs)8
-rw-r--r--crates/ide_diagnostics/src/handlers/field_shorthand.rs (renamed from crates/ide/src/diagnostics/field_shorthand.rs)6
-rw-r--r--crates/ide_diagnostics/src/handlers/inactive_code.rs (renamed from crates/ide/src/diagnostics/inactive_code.rs)35
-rw-r--r--crates/ide_diagnostics/src/handlers/incorrect_case.rs (renamed from crates/ide/src/diagnostics/incorrect_case.rs)115
-rw-r--r--crates/ide_diagnostics/src/handlers/macro_error.rs (renamed from crates/ide/src/diagnostics/macro_error.rs)26
-rw-r--r--crates/ide_diagnostics/src/handlers/mismatched_arg_count.rs (renamed from crates/ide/src/diagnostics/mismatched_arg_count.rs)28
-rw-r--r--crates/ide_diagnostics/src/handlers/missing_fields.rs (renamed from crates/ide/src/diagnostics/missing_fields.rs)42
-rw-r--r--crates/ide_diagnostics/src/handlers/missing_match_arms.rs (renamed from crates/ide/src/diagnostics/missing_match_arms.rs)106
-rw-r--r--crates/ide_diagnostics/src/handlers/missing_ok_or_some_in_tail_expr.rs (renamed from crates/ide/src/diagnostics/missing_ok_or_some_in_tail_expr.rs)9
-rw-r--r--crates/ide_diagnostics/src/handlers/missing_unsafe.rs (renamed from crates/ide/src/diagnostics/missing_unsafe.rs)16
-rw-r--r--crates/ide_diagnostics/src/handlers/no_such_field.rs (renamed from crates/ide/src/diagnostics/no_such_field.rs)13
-rw-r--r--crates/ide_diagnostics/src/handlers/remove_this_semicolon.rs (renamed from crates/ide/src/diagnostics/remove_this_semicolon.rs)11
-rw-r--r--crates/ide_diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs (renamed from crates/ide/src/diagnostics/replace_filter_map_next_with_find_map.rs)25
-rw-r--r--crates/ide_diagnostics/src/handlers/unimplemented_builtin_macro.rs (renamed from crates/ide/src/diagnostics/unimplemented_builtin_macro.rs)7
-rw-r--r--crates/ide_diagnostics/src/handlers/unlinked_file.rs (renamed from crates/ide/src/diagnostics/unlinked_file.rs)30
-rw-r--r--crates/ide_diagnostics/src/handlers/unresolved_extern_crate.rs (renamed from crates/ide/src/diagnostics/unresolved_extern_crate.rs)10
-rw-r--r--crates/ide_diagnostics/src/handlers/unresolved_import.rs (renamed from crates/ide/src/diagnostics/unresolved_import.rs)24
-rw-r--r--crates/ide_diagnostics/src/handlers/unresolved_macro_call.rs (renamed from crates/ide/src/diagnostics/unresolved_macro_call.rs)14
-rw-r--r--crates/ide_diagnostics/src/handlers/unresolved_module.rs (renamed from crates/ide/src/diagnostics/unresolved_module.rs)11
-rw-r--r--crates/ide_diagnostics/src/handlers/unresolved_proc_macro.rs (renamed from crates/ide/src/diagnostics/unresolved_proc_macro.rs)7
-rw-r--r--crates/ide_diagnostics/src/handlers/useless_braces.rs148
-rw-r--r--crates/ide_diagnostics/src/lib.rs374
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/tests/slow-tests/support.rs4
-rw-r--r--crates/syntax/src/ast/node_ext.rs9
-rw-r--r--crates/syntax/test_data/parser/ok/0011_outer_attribute.rast2
-rw-r--r--crates/syntax/test_data/parser/ok/0011_outer_attribute.rs2
-rw-r--r--crates/test_utils/src/fixture.rs168
-rw-r--r--crates/test_utils/src/lib.rs5
-rw-r--r--crates/test_utils/src/minicore.rs204
-rw-r--r--docs/dev/style.md7
-rw-r--r--docs/user/.gitignore1
-rw-r--r--docs/user/manual.adoc9
-rw-r--r--editors/code/package.json4
-rw-r--r--editors/code/src/main.ts14
-rw-r--r--editors/code/src/net.ts18
-rw-r--r--editors/code/src/toolchain.ts16
-rw-r--r--xtask/src/dist.rs4
-rw-r--r--xtask/src/tidy.rs31
89 files changed, 3612 insertions, 3260 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e47b87964..5066d5f0f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -216,20 +216,6 @@ dependencies = [
216 "petgraph", 216 "petgraph",
217 "rustc-hash", 217 "rustc-hash",
218 "tracing", 218 "tracing",
219 "tracing-subscriber",
220 "tracing-tree",
221]
222
223[[package]]
224name = "chrono"
225version = "0.4.19"
226source = "registry+https://github.com/rust-lang/crates.io-index"
227checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
228dependencies = [
229 "libc",
230 "num-integer",
231 "num-traits",
232 "winapi",
233] 219]
234 220
235[[package]] 221[[package]]
@@ -591,6 +577,7 @@ dependencies = [
591 "ide_assists", 577 "ide_assists",
592 "ide_completion", 578 "ide_completion",
593 "ide_db", 579 "ide_db",
580 "ide_diagnostics",
594 "ide_ssr", 581 "ide_ssr",
595 "indexmap", 582 "indexmap",
596 "itertools", 583 "itertools",
@@ -669,6 +656,25 @@ dependencies = [
669] 656]
670 657
671[[package]] 658[[package]]
659name = "ide_diagnostics"
660version = "0.0.0"
661dependencies = [
662 "cfg",
663 "cov-mark",
664 "either",
665 "expect-test",
666 "hir",
667 "ide_db",
668 "itertools",
669 "profile",
670 "rustc-hash",
671 "stdx",
672 "syntax",
673 "test_utils",
674 "text_edit",
675]
676
677[[package]]
672name = "ide_ssr" 678name = "ide_ssr"
673version = "0.0.0" 679version = "0.0.0"
674dependencies = [ 680dependencies = [
@@ -955,25 +961,6 @@ dependencies = [
955] 961]
956 962
957[[package]] 963[[package]]
958name = "num-integer"
959version = "0.1.44"
960source = "registry+https://github.com/rust-lang/crates.io-index"
961checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
962dependencies = [
963 "autocfg",
964 "num-traits",
965]
966
967[[package]]
968name = "num-traits"
969version = "0.2.14"
970source = "registry+https://github.com/rust-lang/crates.io-index"
971checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
972dependencies = [
973 "autocfg",
974]
975
976[[package]]
977name = "num_cpus" 964name = "num_cpus"
978version = "1.13.0" 965version = "1.13.0"
979source = "registry+https://github.com/rust-lang/crates.io-index" 966source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1742,35 +1729,18 @@ dependencies = [
1742] 1729]
1743 1730
1744[[package]] 1731[[package]]
1745name = "tracing-serde"
1746version = "0.1.2"
1747source = "registry+https://github.com/rust-lang/crates.io-index"
1748checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
1749dependencies = [
1750 "serde",
1751 "tracing-core",
1752]
1753
1754[[package]]
1755name = "tracing-subscriber" 1732name = "tracing-subscriber"
1756version = "0.2.18" 1733version = "0.2.18"
1757source = "registry+https://github.com/rust-lang/crates.io-index" 1734source = "registry+https://github.com/rust-lang/crates.io-index"
1758checksum = "aa5553bf0883ba7c9cbe493b085c29926bd41b66afc31ff72cf17ff4fb60dcd5" 1735checksum = "aa5553bf0883ba7c9cbe493b085c29926bd41b66afc31ff72cf17ff4fb60dcd5"
1759dependencies = [ 1736dependencies = [
1760 "ansi_term",
1761 "chrono",
1762 "lazy_static", 1737 "lazy_static",
1763 "matchers", 1738 "matchers",
1764 "regex", 1739 "regex",
1765 "serde",
1766 "serde_json",
1767 "sharded-slab", 1740 "sharded-slab",
1768 "smallvec",
1769 "thread_local", 1741 "thread_local",
1770 "tracing", 1742 "tracing",
1771 "tracing-core", 1743 "tracing-core",
1772 "tracing-log",
1773 "tracing-serde",
1774] 1744]
1775 1745
1776[[package]] 1746[[package]]
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index da4afb5eb..d56b20b83 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -9,8 +9,8 @@ use test_utils::{
9use vfs::{file_set::FileSet, VfsPath}; 9use vfs::{file_set::FileSet, VfsPath};
10 10
11use crate::{ 11use crate::{
12 input::CrateName, Change, CrateGraph, CrateId, Edition, Env, FileId, FilePosition, FileRange, 12 input::CrateName, Change, CrateDisplayName, CrateGraph, CrateId, Edition, Env, FileId,
13 SourceDatabaseExt, SourceRoot, SourceRootId, 13 FilePosition, FileRange, SourceDatabaseExt, SourceRoot, SourceRootId,
14}; 14};
15 15
16pub const WORKSPACE: SourceRootId = SourceRootId(0); 16pub const WORKSPACE: SourceRootId = SourceRootId(0);
@@ -24,6 +24,14 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
24 (db, fixture.files[0]) 24 (db, fixture.files[0])
25 } 25 }
26 26
27 fn with_many_files(ra_fixture: &str) -> (Self, Vec<FileId>) {
28 let fixture = ChangeFixture::parse(ra_fixture);
29 let mut db = Self::default();
30 fixture.change.apply(&mut db);
31 assert!(fixture.file_position.is_none());
32 (db, fixture.files)
33 }
34
27 fn with_files(ra_fixture: &str) -> Self { 35 fn with_files(ra_fixture: &str) -> Self {
28 let fixture = ChangeFixture::parse(ra_fixture); 36 let fixture = ChangeFixture::parse(ra_fixture);
29 let mut db = Self::default(); 37 let mut db = Self::default();
@@ -73,7 +81,7 @@ pub struct ChangeFixture {
73 81
74impl ChangeFixture { 82impl ChangeFixture {
75 pub fn parse(ra_fixture: &str) -> ChangeFixture { 83 pub fn parse(ra_fixture: &str) -> ChangeFixture {
76 let fixture = Fixture::parse(ra_fixture); 84 let (mini_core, fixture) = Fixture::parse(ra_fixture);
77 let mut change = Change::new(); 85 let mut change = Change::new();
78 86
79 let mut files = Vec::new(); 87 let mut files = Vec::new();
@@ -158,6 +166,31 @@ impl ChangeFixture {
158 } 166 }
159 } 167 }
160 168
169 if let Some(mini_core) = mini_core {
170 let core_file = file_id;
171 file_id.0 += 1;
172
173 let mut fs = FileSet::default();
174 fs.insert(core_file, VfsPath::new_virtual_path("/sysroot/core/lib.rs".to_string()));
175 roots.push(SourceRoot::new_library(fs));
176
177 change.change_file(core_file, Some(Arc::new(mini_core.source_code())));
178
179 let all_crates = crate_graph.crates_in_topological_order();
180
181 let core_crate = crate_graph.add_crate_root(
182 core_file,
183 Edition::Edition2021,
184 Some(CrateDisplayName::from_canonical_name("core".to_string())),
185 CfgOptions::default(),
186 Env::default(),
187 Vec::new(),
188 );
189
190 for krate in all_crates {
191 crate_graph.add_dep(krate, CrateName::new("core").unwrap(), core_crate).unwrap();
192 }
193 }
161 roots.push(SourceRoot::new_local(mem::take(&mut file_set))); 194 roots.push(SourceRoot::new_local(mem::take(&mut file_set)));
162 change.set_roots(roots); 195 change.set_roots(roots);
163 change.set_crate_graph(crate_graph); 196 change.set_crate_graph(crate_graph);
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index dc10a4d0f..197149c5e 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -127,7 +127,7 @@ impl HasSource for Impl {
127} 127}
128 128
129impl HasSource for TypeParam { 129impl HasSource for TypeParam {
130 type Ast = Either<ast::Trait, ast::TypeParam>; 130 type Ast = Either<ast::TypeParam, ast::Trait>;
131 fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { 131 fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> {
132 let child_source = self.id.parent.child_source(db.upcast()); 132 let child_source = self.id.parent.child_source(db.upcast());
133 Some(child_source.map(|it| it[self.id.local_id].clone())) 133 Some(child_source.map(|it| it[self.id.local_id].clone()))
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 6933f6e3c..0f04b2bae 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -92,7 +92,7 @@ pub enum WherePredicateTypeTarget {
92 92
93#[derive(Default)] 93#[derive(Default)]
94pub(crate) struct SourceMap { 94pub(crate) struct SourceMap {
95 pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>, 95 pub(crate) type_params: ArenaMap<LocalTypeParamId, Either<ast::TypeParam, ast::Trait>>,
96 lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>, 96 lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
97 const_params: ArenaMap<LocalConstParamId, ast::ConstParam>, 97 const_params: ArenaMap<LocalConstParamId, ast::ConstParam>,
98} 98}
@@ -199,7 +199,7 @@ impl GenericParams {
199 default: None, 199 default: None,
200 provenance: TypeParamProvenance::TraitSelf, 200 provenance: TypeParamProvenance::TraitSelf,
201 }); 201 });
202 sm.type_params.insert(self_param_id, Either::Left(src.value.clone())); 202 sm.type_params.insert(self_param_id, Either::Right(src.value.clone()));
203 // add super traits as bounds on Self 203 // add super traits as bounds on Self
204 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 204 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
205 let self_param = TypeRef::Path(name![Self].into()); 205 let self_param = TypeRef::Path(name![Self].into());
@@ -277,7 +277,7 @@ impl GenericParams {
277 provenance: TypeParamProvenance::TypeParamList, 277 provenance: TypeParamProvenance::TypeParamList,
278 }; 278 };
279 let param_id = self.types.alloc(param); 279 let param_id = self.types.alloc(param);
280 sm.type_params.insert(param_id, Either::Right(type_param.clone())); 280 sm.type_params.insert(param_id, Either::Left(type_param.clone()));
281 281
282 let type_ref = TypeRef::Path(name.into()); 282 let type_ref = TypeRef::Path(name.into());
283 self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref)); 283 self.fill_bounds(lower_ctx, &type_param, Either::Left(type_ref));
@@ -413,7 +413,7 @@ impl GenericParams {
413} 413}
414 414
415impl HasChildSource<LocalTypeParamId> for GenericDefId { 415impl HasChildSource<LocalTypeParamId> for GenericDefId {
416 type Value = Either<ast::Trait, ast::TypeParam>; 416 type Value = Either<ast::TypeParam, ast::Trait>;
417 fn child_source( 417 fn child_source(
418 &self, 418 &self,
419 db: &dyn DefDatabase, 419 db: &dyn DefDatabase,
@@ -449,7 +449,7 @@ impl ChildBySource for GenericDefId {
449 let sm = sm.as_ref(); 449 let sm = sm.as_ref();
450 for (local_id, src) in sm.value.type_params.iter() { 450 for (local_id, src) in sm.value.type_params.iter() {
451 let id = TypeParamId { parent: *self, local_id }; 451 let id = TypeParamId { parent: *self, local_id };
452 if let Either::Right(type_param) = src { 452 if let Either::Left(type_param) = src {
453 res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id) 453 res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id)
454 } 454 }
455 } 455 }
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 3f90bda74..5b1386406 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -674,7 +674,7 @@ impl<'a> Ctx<'a> {
674 default: None, 674 default: None,
675 provenance: TypeParamProvenance::TraitSelf, 675 provenance: TypeParamProvenance::TraitSelf,
676 }); 676 });
677 sm.type_params.insert(self_param_id, Either::Left(trait_def.clone())); 677 sm.type_params.insert(self_param_id, Either::Right(trait_def.clone()));
678 // add super traits as bounds on Self 678 // add super traits as bounds on Self
679 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 679 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
680 let self_param = TypeRef::Path(name![Self].into()); 680 let self_param = TypeRef::Path(name![Self].into());
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 6fab58f15..fc2c50fb8 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1992,8 +1992,8 @@ mod tests {
1992 collector.def_map 1992 collector.def_map
1993 } 1993 }
1994 1994
1995 fn do_resolve(code: &str) -> DefMap { 1995 fn do_resolve(not_ra_fixture: &str) -> DefMap {
1996 let (db, _file_id) = TestDB::with_single_file(code); 1996 let (db, _file_id) = TestDB::with_single_file(not_ra_fixture);
1997 let krate = db.test_crate(); 1997 let krate = db.test_crate();
1998 1998
1999 let edition = db.crate_graph()[krate].edition; 1999 let edition = db.crate_graph()[krate].edition;
@@ -2005,24 +2005,37 @@ mod tests {
2005 fn test_macro_expand_will_stop_1() { 2005 fn test_macro_expand_will_stop_1() {
2006 do_resolve( 2006 do_resolve(
2007 r#" 2007 r#"
2008 macro_rules! foo { 2008macro_rules! foo {
2009 ($($ty:ty)*) => { foo!($($ty)*); } 2009 ($($ty:ty)*) => { foo!($($ty)*); }
2010 } 2010}
2011 foo!(KABOOM); 2011foo!(KABOOM);
2012 "#, 2012"#,
2013 );
2014 do_resolve(
2015 r#"
2016macro_rules! foo {
2017 ($($ty:ty)*) => { foo!(() $($ty)*); }
2018}
2019foo!(KABOOM);
2020"#,
2013 ); 2021 );
2014 } 2022 }
2015 2023
2016 #[ignore] // this test does succeed, but takes quite a while :/ 2024 #[ignore]
2017 #[test] 2025 #[test]
2018 fn test_macro_expand_will_stop_2() { 2026 fn test_macro_expand_will_stop_2() {
2027 // FIXME: this test does succeed, but takes quite a while: 90 seconds in
2028 // the release mode. That's why the argument is not an ra_fixture --
2029 // otherwise injection highlighting gets stuck.
2030 //
2031 // We need to find a way to fail this faster.
2019 do_resolve( 2032 do_resolve(
2020 r#" 2033 r#"
2021 macro_rules! foo { 2034macro_rules! foo {
2022 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); } 2035 ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
2023 } 2036}
2024 foo!(KABOOM); 2037foo!(KABOOM);
2025 "#, 2038"#,
2026 ); 2039 );
2027 } 2040 }
2028} 2041}
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index a1894e8d8..74129eb21 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -20,7 +20,7 @@ rustc-hash = "1.1.0"
20scoped-tls = "1" 20scoped-tls = "1"
21chalk-solve = { version = "0.68", default-features = false } 21chalk-solve = { version = "0.68", default-features = false }
22chalk-ir = "0.68" 22chalk-ir = "0.68"
23chalk-recursive = "0.68" 23chalk-recursive = { version = "0.68", default-features = false }
24la-arena = { version = "0.2.0", path = "../../lib/arena" } 24la-arena = { version = "0.2.0", path = "../../lib/arena" }
25once_cell = { version = "1.5.0" } 25once_cell = { version = "1.5.0" }
26 26
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs
index 71047703d..713b74165 100644
--- a/crates/hir_ty/src/tests/coercion.rs
+++ b/crates/hir_ty/src/tests/coercion.rs
@@ -23,38 +23,29 @@ fn infer_block_expr_type_mismatch() {
23fn coerce_places() { 23fn coerce_places() {
24 check_infer( 24 check_infer(
25 r#" 25 r#"
26 struct S<T> { a: T } 26//- minicore: coerce_unsized
27struct S<T> { a: T }
27 28
28 fn f<T>(_: &[T]) -> T { loop {} } 29fn f<T>(_: &[T]) -> T { loop {} }
29 fn g<T>(_: S<&[T]>) -> T { loop {} } 30fn g<T>(_: S<&[T]>) -> T { loop {} }
30 31
31 fn gen<T>() -> *mut [T; 2] { loop {} } 32fn gen<T>() -> *mut [T; 2] { loop {} }
32 fn test1<U>() -> *mut [U] { 33fn test1<U>() -> *mut [U] {
33 gen() 34 gen()
34 } 35}
35
36 fn test2() {
37 let arr: &[u8; 1] = &[1];
38
39 let a: &[_] = arr;
40 let b = f(arr);
41 let c: &[_] = { arr };
42 let d = g(S { a: arr });
43 let e: [&[_]; 1] = [arr];
44 let f: [&[_]; 2] = [arr; 2];
45 let g: (&[_], &[_]) = (arr, arr);
46 }
47 36
48 #[lang = "sized"] 37fn test2() {
49 pub trait Sized {} 38 let arr: &[u8; 1] = &[1];
50 #[lang = "unsize"]
51 pub trait Unsize<T: ?Sized> {}
52 #[lang = "coerce_unsized"]
53 pub trait CoerceUnsized<T> {}
54 39
55 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} 40 let a: &[_] = arr;
56 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} 41 let b = f(arr);
57 "#, 42 let c: &[_] = { arr };
43 let d = g(S { a: arr });
44 let e: [&[_]; 1] = [arr];
45 let f: [&[_]; 2] = [arr; 2];
46 let g: (&[_], &[_]) = (arr, arr);
47}
48"#,
58 expect![[r#" 49 expect![[r#"
59 30..31 '_': &[T] 50 30..31 '_': &[T]
60 44..55 '{ loop {} }': T 51 44..55 '{ loop {} }': T
@@ -131,60 +122,52 @@ fn infer_let_stmt_coerce() {
131fn infer_custom_coerce_unsized() { 122fn infer_custom_coerce_unsized() {
132 check_infer( 123 check_infer(
133 r#" 124 r#"
134 struct A<T: ?Sized>(*const T); 125//- minicore: coerce_unsized
135 struct B<T: ?Sized>(*const T); 126use core::{marker::Unsize, ops::CoerceUnsized};
136 struct C<T: ?Sized> { inner: *const T }
137 127
138 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} 128struct A<T: ?Sized>(*const T);
139 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} 129struct B<T: ?Sized>(*const T);
130struct C<T: ?Sized> { inner: *const T }
140 131
141 fn foo1<T>(x: A<[T]>) -> A<[T]> { x } 132impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
142 fn foo2<T>(x: B<[T]>) -> B<[T]> { x } 133impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
143 fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
144 134
145 fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { 135fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
146 let d = foo1(a); 136fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
147 let e = foo2(b); 137fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
148 let f = foo3(c);
149 }
150
151
152 #[lang = "sized"]
153 pub trait Sized {}
154 #[lang = "unsize"]
155 pub trait Unsize<T: ?Sized> {}
156 #[lang = "coerce_unsized"]
157 pub trait CoerceUnsized<T> {}
158 138
159 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} 139fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
160 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} 140 let d = foo1(a);
161 "#, 141 let e = foo2(b);
142 let f = foo3(c);
143}
144"#,
162 expect![[r#" 145 expect![[r#"
163 257..258 'x': A<[T]> 146 306..307 'x': A<[T]>
164 278..283 '{ x }': A<[T]> 147 327..332 '{ x }': A<[T]>
165 280..281 'x': A<[T]> 148 329..330 'x': A<[T]>
166 295..296 'x': B<[T]> 149 344..345 'x': B<[T]>
167 316..321 '{ x }': B<[T]> 150 365..370 '{ x }': B<[T]>
168 318..319 'x': B<[T]> 151 367..368 'x': B<[T]>
169 333..334 'x': C<[T]> 152 382..383 'x': C<[T]>
170 354..359 '{ x }': C<[T]> 153 403..408 '{ x }': C<[T]>
171 356..357 'x': C<[T]> 154 405..406 'x': C<[T]>
172 369..370 'a': A<[u8; 2]> 155 418..419 'a': A<[u8; 2]>
173 384..385 'b': B<[u8; 2]> 156 433..434 'b': B<[u8; 2]>
174 399..400 'c': C<[u8; 2]> 157 448..449 'c': C<[u8; 2]>
175 414..480 '{ ...(c); }': () 158 463..529 '{ ...(c); }': ()
176 424..425 'd': A<[{unknown}]> 159 473..474 'd': A<[{unknown}]>
177 428..432 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> 160 477..481 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]>
178 428..435 'foo1(a)': A<[{unknown}]> 161 477..484 'foo1(a)': A<[{unknown}]>
179 433..434 'a': A<[u8; 2]> 162 482..483 'a': A<[u8; 2]>
180 445..446 'e': B<[u8]> 163 494..495 'e': B<[u8]>
181 449..453 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> 164 498..502 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]>
182 449..456 'foo2(b)': B<[u8]> 165 498..505 'foo2(b)': B<[u8]>
183 454..455 'b': B<[u8; 2]> 166 503..504 'b': B<[u8; 2]>
184 466..467 'f': C<[u8]> 167 515..516 'f': C<[u8]>
185 470..474 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> 168 519..523 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]>
186 470..477 'foo3(c)': C<[u8]> 169 519..526 'foo3(c)': C<[u8]>
187 475..476 'c': C<[u8; 2]> 170 524..525 'c': C<[u8; 2]>
188 "#]], 171 "#]],
189 ); 172 );
190} 173}
@@ -193,21 +176,16 @@ fn infer_custom_coerce_unsized() {
193fn infer_if_coerce() { 176fn infer_if_coerce() {
194 check_infer( 177 check_infer(
195 r#" 178 r#"
196 fn foo<T>(x: &[T]) -> &[T] { loop {} } 179//- minicore: unsize
197 fn test() { 180fn foo<T>(x: &[T]) -> &[T] { loop {} }
198 let x = if true { 181fn test() {
199 foo(&[1]) 182 let x = if true {
200 } else { 183 foo(&[1])
201 &[1] 184 } else {
202 }; 185 &[1]
203 } 186 };
204 187}
205 188"#,
206 #[lang = "sized"]
207 pub trait Sized {}
208 #[lang = "unsize"]
209 pub trait Unsize<T: ?Sized> {}
210 "#,
211 expect![[r#" 189 expect![[r#"
212 10..11 'x': &[T] 190 10..11 'x': &[T]
213 27..38 '{ loop {} }': &[T] 191 27..38 '{ loop {} }': &[T]
@@ -235,25 +213,16 @@ fn infer_if_coerce() {
235fn infer_if_else_coerce() { 213fn infer_if_else_coerce() {
236 check_infer( 214 check_infer(
237 r#" 215 r#"
238 fn foo<T>(x: &[T]) -> &[T] { loop {} } 216//- minicore: coerce_unsized
239 fn test() { 217fn foo<T>(x: &[T]) -> &[T] { loop {} }
240 let x = if true { 218fn test() {
241 &[1] 219 let x = if true {
242 } else { 220 &[1]
243 foo(&[1]) 221 } else {
244 }; 222 foo(&[1])
245 } 223 };
246 224}
247 #[lang = "sized"] 225"#,
248 pub trait Sized {}
249 #[lang = "unsize"]
250 pub trait Unsize<T: ?Sized> {}
251 #[lang = "coerce_unsized"]
252 pub trait CoerceUnsized<T> {}
253
254 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
255 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
256 "#,
257 expect![[r#" 226 expect![[r#"
258 10..11 'x': &[T] 227 10..11 'x': &[T]
259 27..38 '{ loop {} }': &[T] 228 27..38 '{ loop {} }': &[T]
@@ -281,20 +250,16 @@ fn infer_if_else_coerce() {
281fn infer_match_first_coerce() { 250fn infer_match_first_coerce() {
282 check_infer( 251 check_infer(
283 r#" 252 r#"
284 fn foo<T>(x: &[T]) -> &[T] { loop {} } 253//- minicore: unsize
285 fn test(i: i32) { 254fn foo<T>(x: &[T]) -> &[T] { loop {} }
286 let x = match i { 255fn test(i: i32) {
287 2 => foo(&[2]), 256 let x = match i {
288 1 => &[1], 257 2 => foo(&[2]),
289 _ => &[3], 258 1 => &[1],
290 }; 259 _ => &[3],
291 } 260 };
292 261}
293 #[lang = "sized"] 262"#,
294 pub trait Sized {}
295 #[lang = "unsize"]
296 pub trait Unsize<T: ?Sized> {}
297 "#,
298 expect![[r#" 263 expect![[r#"
299 10..11 'x': &[T] 264 10..11 'x': &[T]
300 27..38 '{ loop {} }': &[T] 265 27..38 '{ loop {} }': &[T]
@@ -329,25 +294,16 @@ fn infer_match_first_coerce() {
329fn infer_match_second_coerce() { 294fn infer_match_second_coerce() {
330 check_infer( 295 check_infer(
331 r#" 296 r#"
332 fn foo<T>(x: &[T]) -> &[T] { loop {} } 297//- minicore: coerce_unsized
333 fn test(i: i32) { 298fn foo<T>(x: &[T]) -> &[T] { loop {} }
334 let x = match i { 299fn test(i: i32) {
335 1 => &[1], 300 let x = match i {
336 2 => foo(&[2]), 301 1 => &[1],
337 _ => &[3], 302 2 => foo(&[2]),
338 }; 303 _ => &[3],
339 } 304 };
340 305}
341 #[lang = "sized"] 306"#,
342 pub trait Sized {}
343 #[lang = "unsize"]
344 pub trait Unsize<T: ?Sized> {}
345 #[lang = "coerce_unsized"]
346 pub trait CoerceUnsized<T> {}
347
348 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
349 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<*mut U> for *mut T {}
350 "#,
351 expect![[r#" 307 expect![[r#"
352 10..11 'x': &[T] 308 10..11 'x': &[T]
353 27..38 '{ loop {} }': &[T] 309 27..38 '{ loop {} }': &[T]
@@ -470,15 +426,15 @@ fn coerce_autoderef() {
470#[test] 426#[test]
471fn coerce_autoderef_generic() { 427fn coerce_autoderef_generic() {
472 check_infer_with_mismatches( 428 check_infer_with_mismatches(
473 r" 429 r#"
474 struct Foo; 430struct Foo;
475 fn takes_ref<T>(x: &T) -> T { *x } 431fn takes_ref<T>(x: &T) -> T { *x }
476 fn test() { 432fn test() {
477 takes_ref(&Foo); 433 takes_ref(&Foo);
478 takes_ref(&&Foo); 434 takes_ref(&&Foo);
479 takes_ref(&&&Foo); 435 takes_ref(&&&Foo);
480 } 436}
481 ", 437"#,
482 expect![[r" 438 expect![[r"
483 28..29 'x': &T 439 28..29 'x': &T
484 40..46 '{ *x }': T 440 40..46 '{ *x }': T
@@ -508,30 +464,29 @@ fn coerce_autoderef_generic() {
508fn coerce_autoderef_block() { 464fn coerce_autoderef_block() {
509 check_infer_with_mismatches( 465 check_infer_with_mismatches(
510 r#" 466 r#"
511 struct String {} 467//- minicore: deref
512 #[lang = "deref"] 468struct String {}
513 trait Deref { type Target; } 469impl core::ops::Deref for String { type Target = str; }
514 impl Deref for String { type Target = str; } 470fn takes_ref_str(x: &str) {}
515 fn takes_ref_str(x: &str) {} 471fn returns_string() -> String { loop {} }
516 fn returns_string() -> String { loop {} } 472fn test() {
517 fn test() { 473 takes_ref_str(&{ returns_string() });
518 takes_ref_str(&{ returns_string() }); 474}
519 } 475"#,
520 "#, 476 expect![[r#"
521 expect![[r" 477 90..91 'x': &str
522 126..127 'x': &str 478 99..101 '{}': ()
523 135..137 '{}': () 479 132..143 '{ loop {} }': String
524 168..179 '{ loop {} }': String 480 134..141 'loop {}': !
525 170..177 'loop {}': ! 481 139..141 '{}': ()
526 175..177 '{}': () 482 154..199 '{ ... }); }': ()
527 190..235 '{ ... }); }': () 483 160..173 'takes_ref_str': fn takes_ref_str(&str)
528 196..209 'takes_ref_str': fn takes_ref_str(&str) 484 160..196 'takes_...g() })': ()
529 196..232 'takes_...g() })': () 485 174..195 '&{ ret...ng() }': &String
530 210..231 '&{ ret...ng() }': &String 486 175..195 '{ retu...ng() }': String
531 211..231 '{ retu...ng() }': String 487 177..191 'returns_string': fn returns_string() -> String
532 213..227 'returns_string': fn returns_string() -> String 488 177..193 'return...ring()': String
533 213..229 'return...ring()': String 489 "#]],
534 "]],
535 ); 490 );
536} 491}
537 492
@@ -674,25 +629,19 @@ fn coerce_placeholder_ref() {
674fn coerce_unsize_array() { 629fn coerce_unsize_array() {
675 check_infer_with_mismatches( 630 check_infer_with_mismatches(
676 r#" 631 r#"
677 #[lang = "unsize"] 632//- minicore: coerce_unsized
678 pub trait Unsize<T> {} 633fn test() {
679 #[lang = "coerce_unsized"] 634 let f: &[usize] = &[1, 2, 3];
680 pub trait CoerceUnsized<T> {} 635}
681
682 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
683
684 fn test() {
685 let f: &[usize] = &[1, 2, 3];
686 }
687 "#, 636 "#,
688 expect![[r#" 637 expect![[r#"
689 161..198 '{ ... 3]; }': () 638 10..47 '{ ... 3]; }': ()
690 171..172 'f': &[usize] 639 20..21 'f': &[usize]
691 185..195 '&[1, 2, 3]': &[usize; 3] 640 34..44 '&[1, 2, 3]': &[usize; 3]
692 186..195 '[1, 2, 3]': [usize; 3] 641 35..44 '[1, 2, 3]': [usize; 3]
693 187..188 '1': usize 642 36..37 '1': usize
694 190..191 '2': usize 643 39..40 '2': usize
695 193..194 '3': usize 644 42..43 '3': usize
696 "#]], 645 "#]],
697 ); 646 );
698} 647}
@@ -701,93 +650,94 @@ fn coerce_unsize_array() {
701fn coerce_unsize_trait_object_simple() { 650fn coerce_unsize_trait_object_simple() {
702 check_infer_with_mismatches( 651 check_infer_with_mismatches(
703 r#" 652 r#"
704 #[lang = "sized"] 653//- minicore: coerce_unsized
705 pub trait Sized {} 654trait Foo<T, U> {}
706 #[lang = "unsize"] 655trait Bar<U, T, X>: Foo<T, U> {}
707 pub trait Unsize<T> {} 656trait Baz<T, X>: Bar<usize, T, X> {}
708 #[lang = "coerce_unsized"] 657
709 pub trait CoerceUnsized<T> {} 658struct S<T, X>;
710 659impl<T, X> Foo<T, usize> for S<T, X> {}
711 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} 660impl<T, X> Bar<usize, T, X> for S<T, X> {}
712 661impl<T, X> Baz<T, X> for S<T, X> {}
713 trait Foo<T, U> {} 662
714 trait Bar<U, T, X>: Foo<T, U> {} 663fn test() {
715 trait Baz<T, X>: Bar<usize, T, X> {} 664 let obj: &dyn Baz<i8, i16> = &S;
716 665 let obj: &dyn Bar<_, i8, i16> = &S;
717 struct S<T, X>; 666 let obj: &dyn Foo<i8, _> = &S;
718 impl<T, X> Foo<T, usize> for S<T, X> {} 667}
719 impl<T, X> Bar<usize, T, X> for S<T, X> {} 668"#,
720 impl<T, X> Baz<T, X> for S<T, X> {} 669 expect![[r#"
721 670 236..351 '{ ... &S; }': ()
722 fn test() { 671 246..249 'obj': &dyn Baz<i8, i16>
723 let obj: &dyn Baz<i8, i16> = &S; 672 271..273 '&S': &S<i8, i16>
724 let obj: &dyn Bar<_, i8, i16> = &S; 673 272..273 'S': S<i8, i16>
725 let obj: &dyn Foo<i8, _> = &S; 674 283..286 'obj': &dyn Bar<usize, i8, i16>
726 } 675 311..313 '&S': &S<i8, i16>
727 "#, 676 312..313 'S': S<i8, i16>
728 expect![[r" 677 323..326 'obj': &dyn Foo<i8, usize>
729 424..539 '{ ... &S; }': () 678 346..348 '&S': &S<i8, {unknown}>
730 434..437 'obj': &dyn Baz<i8, i16> 679 347..348 'S': S<i8, {unknown}>
731 459..461 '&S': &S<i8, i16> 680 "#]],
732 460..461 'S': S<i8, i16>
733 471..474 'obj': &dyn Bar<usize, i8, i16>
734 499..501 '&S': &S<i8, i16>
735 500..501 'S': S<i8, i16>
736 511..514 'obj': &dyn Foo<i8, usize>
737 534..536 '&S': &S<i8, {unknown}>
738 535..536 'S': S<i8, {unknown}>
739 "]],
740 ); 681 );
741} 682}
742 683
743#[test] 684#[test]
744// The rust reference says this should be possible, but rustc doesn't implement
745// it. We used to support it, but Chalk doesn't.
746#[ignore]
747fn coerce_unsize_trait_object_to_trait_object() { 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>
748 check_infer_with_mismatches( 703 check_infer_with_mismatches(
749 r#" 704 r#"
750 #[lang = "sized"] 705//- minicore: coerce_unsized
751 pub trait Sized {} 706trait Foo<T, U> {}
752 #[lang = "unsize"] 707trait Bar<U, T, X>: Foo<T, U> {}
753 pub trait Unsize<T> {} 708trait Baz<T, X>: Bar<usize, T, X> {}
754 #[lang = "coerce_unsized"] 709
755 pub trait CoerceUnsized<T> {} 710struct S<T, X>;
756 711impl<T, X> Foo<T, usize> for S<T, X> {}
757 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} 712impl<T, X> Bar<usize, T, X> for S<T, X> {}
758 713impl<T, X> Baz<T, X> for S<T, X> {}
759 trait Foo<T, U> {} 714
760 trait Bar<U, T, X>: Foo<T, U> {} 715fn test() {
761 trait Baz<T, X>: Bar<usize, T, X> {} 716 let obj: &dyn Baz<i8, i16> = &S;
762 717 let obj: &dyn Bar<_, _, _> = obj;
763 struct S<T, X>; 718 let obj: &dyn Foo<_, _> = obj;
764 impl<T, X> Foo<T, usize> for S<T, X> {} 719 let obj2: &dyn Baz<i8, i16> = &S;
765 impl<T, X> Bar<usize, T, X> for S<T, X> {} 720 let _: &dyn Foo<_, _> = obj2;
766 impl<T, X> Baz<T, X> for S<T, X> {} 721}
767 722"#,
768 fn test() { 723 expect![[r#"
769 let obj: &dyn Baz<i8, i16> = &S; 724 236..421 '{ ...bj2; }': ()
770 let obj: &dyn Bar<_, _, _> = obj; 725 246..249 'obj': &dyn Baz<i8, i16>
771 let obj: &dyn Foo<_, _> = obj; 726 271..273 '&S': &S<i8, i16>
772 let obj2: &dyn Baz<i8, i16> = &S; 727 272..273 'S': S<i8, i16>
773 let _: &dyn Foo<_, _> = obj2; 728 283..286 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
774 } 729 308..311 'obj': &dyn Baz<i8, i16>
775 "#, 730 321..324 'obj': &dyn Foo<{unknown}, {unknown}>
776 expect![[r" 731 343..346 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}>
777 424..609 '{ ...bj2; }': () 732 356..360 'obj2': &dyn Baz<i8, i16>
778 434..437 'obj': &dyn Baz<i8, i16> 733 382..384 '&S': &S<i8, i16>
779 459..461 '&S': &S<i8, i16> 734 383..384 'S': S<i8, i16>
780 460..461 'S': S<i8, i16> 735 394..395 '_': &dyn Foo<{unknown}, {unknown}>
781 471..474 'obj': &dyn Bar<usize, i8, i16> 736 414..418 'obj2': &dyn Baz<i8, i16>
782 496..499 'obj': &dyn Baz<i8, i16> 737 308..311: expected &dyn Bar<{unknown}, {unknown}, {unknown}>, got &dyn Baz<i8, i16>
783 509..512 'obj': &dyn Foo<i8, usize> 738 343..346: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Bar<{unknown}, {unknown}, {unknown}>
784 531..534 'obj': &dyn Bar<usize, i8, i16> 739 414..418: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Baz<i8, i16>
785 544..548 'obj2': &dyn Baz<i8, i16> 740 "#]],
786 570..572 '&S': &S<i8, i16>
787 571..572 'S': S<i8, i16>
788 582..583 '_': &dyn Foo<i8, usize>
789 602..606 'obj2': &dyn Baz<i8, i16>
790 "]],
791 ); 741 );
792} 742}
793 743
@@ -795,40 +745,32 @@ fn coerce_unsize_trait_object_to_trait_object() {
795fn coerce_unsize_super_trait_cycle() { 745fn coerce_unsize_super_trait_cycle() {
796 check_infer_with_mismatches( 746 check_infer_with_mismatches(
797 r#" 747 r#"
798 #[lang = "sized"] 748//- minicore: coerce_unsized
799 pub trait Sized {} 749trait A {}
800 #[lang = "unsize"] 750trait B: C + A {}
801 pub trait Unsize<T> {} 751trait C: B {}
802 #[lang = "coerce_unsized"] 752trait D: C
803 pub trait CoerceUnsized<T> {} 753
804 754struct S;
805 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {} 755impl A for S {}
806 756impl B for S {}
807 trait A {} 757impl C for S {}
808 trait B: C + A {} 758impl D for S {}
809 trait C: B {} 759
810 trait D: C 760fn test() {
811 761 let obj: &dyn D = &S;
812 struct S; 762 let obj: &dyn A = &S;
813 impl A for S {} 763}
814 impl B for S {} 764"#,
815 impl C for S {} 765 expect![[r#"
816 impl D for S {} 766 140..195 '{ ... &S; }': ()
817 767 150..153 'obj': &dyn D
818 fn test() { 768 164..166 '&S': &S
819 let obj: &dyn D = &S; 769 165..166 'S': S
820 let obj: &dyn A = &S; 770 176..179 'obj': &dyn A
821 } 771 190..192 '&S': &S
822 "#, 772 191..192 'S': S
823 expect![[r" 773 "#]],
824 328..383 '{ ... &S; }': ()
825 338..341 'obj': &dyn D
826 352..354 '&S': &S
827 353..354 'S': S
828 364..367 'obj': &dyn A
829 378..380 '&S': &S
830 379..380 'S': S
831 "]],
832 ); 774 );
833} 775}
834 776
@@ -837,41 +779,35 @@ fn coerce_unsize_generic() {
837 // FIXME: fix the type mismatches here 779 // FIXME: fix the type mismatches here
838 check_infer_with_mismatches( 780 check_infer_with_mismatches(
839 r#" 781 r#"
840 #[lang = "unsize"] 782//- minicore: coerce_unsized
841 pub trait Unsize<T> {} 783struct Foo<T> { t: T };
842 #[lang = "coerce_unsized"] 784struct Bar<T>(Foo<T>);
843 pub trait CoerceUnsized<T> {}
844
845 impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
846 785
847 struct Foo<T> { t: T }; 786fn test() {
848 struct Bar<T>(Foo<T>); 787 let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
849 788 let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
850 fn test() { 789}
851 let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; 790"#,
852 let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
853 }
854 "#,
855 expect![[r#" 791 expect![[r#"
856 209..317 '{ ... }); }': () 792 58..166 '{ ... }); }': ()
857 219..220 '_': &Foo<[usize]> 793 68..69 '_': &Foo<[usize]>
858 238..259 '&Foo {..., 3] }': &Foo<[usize]> 794 87..108 '&Foo {..., 3] }': &Foo<[usize]>
859 239..259 'Foo { ..., 3] }': Foo<[usize]> 795 88..108 'Foo { ..., 3] }': Foo<[usize]>
860 248..257 '[1, 2, 3]': [usize; 3] 796 97..106 '[1, 2, 3]': [usize; 3]
861 249..250 '1': usize 797 98..99 '1': usize
862 252..253 '2': usize 798 101..102 '2': usize
863 255..256 '3': usize 799 104..105 '3': usize
864 269..270 '_': &Bar<[usize]> 800 118..119 '_': &Bar<[usize]>
865 288..314 '&Bar(F... 3] })': &Bar<[i32; 3]> 801 137..163 '&Bar(F... 3] })': &Bar<[i32; 3]>
866 289..292 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]> 802 138..141 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]>
867 289..314 'Bar(Fo... 3] })': Bar<[i32; 3]> 803 138..163 'Bar(Fo... 3] })': Bar<[i32; 3]>
868 293..313 'Foo { ..., 3] }': Foo<[i32; 3]> 804 142..162 'Foo { ..., 3] }': Foo<[i32; 3]>
869 302..311 '[1, 2, 3]': [i32; 3] 805 151..160 '[1, 2, 3]': [i32; 3]
870 303..304 '1': i32 806 152..153 '1': i32
871 306..307 '2': i32 807 155..156 '2': i32
872 309..310 '3': i32 808 158..159 '3': i32
873 248..257: expected [usize], got [usize; 3] 809 97..106: expected [usize], got [usize; 3]
874 288..314: expected &Bar<[usize]>, got &Bar<[i32; 3]> 810 137..163: expected &Bar<[usize]>, got &Bar<[i32; 3]>
875 "#]], 811 "#]],
876 ); 812 );
877} 813}
@@ -881,15 +817,7 @@ fn coerce_unsize_apit() {
881 // FIXME: #8984 817 // FIXME: #8984
882 check_infer_with_mismatches( 818 check_infer_with_mismatches(
883 r#" 819 r#"
884#[lang = "sized"] 820//- minicore: coerce_unsized
885pub trait Sized {}
886#[lang = "unsize"]
887pub trait Unsize<T> {}
888#[lang = "coerce_unsized"]
889pub trait CoerceUnsized<T> {}
890
891impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
892
893trait Foo {} 821trait Foo {}
894 822
895fn test(f: impl Foo) { 823fn test(f: impl Foo) {
@@ -897,12 +825,12 @@ fn test(f: impl Foo) {
897} 825}
898 "#, 826 "#,
899 expect![[r#" 827 expect![[r#"
900 210..211 'f': impl Foo 828 22..23 'f': impl Foo
901 223..252 '{ ... &f; }': () 829 35..64 '{ ... &f; }': ()
902 233..234 '_': &dyn Foo 830 45..46 '_': &dyn Foo
903 247..249 '&f': &impl Foo 831 59..61 '&f': &impl Foo
904 248..249 'f': impl Foo 832 60..61 'f': impl Foo
905 247..249: expected &dyn Foo, got &impl Foo 833 59..61: expected &dyn Foo, got &impl Foo
906 "#]], 834 "#]],
907 ); 835 );
908} 836}
@@ -998,15 +926,7 @@ fn main() {
998fn coerce_unsize_expected_type() { 926fn coerce_unsize_expected_type() {
999 check_no_mismatches( 927 check_no_mismatches(
1000 r#" 928 r#"
1001#[lang = "sized"] 929//- minicore: coerce_unsized
1002pub trait Sized {}
1003#[lang = "unsize"]
1004pub trait Unsize<T> {}
1005#[lang = "coerce_unsized"]
1006pub trait CoerceUnsized<T> {}
1007
1008impl<T: Unsize<U>, U> CoerceUnsized<&U> for &T {}
1009
1010fn main() { 930fn main() {
1011 let foo: &[u32] = &[1, 2]; 931 let foo: &[u32] = &[1, 2];
1012 let foo: &[u32] = match true { 932 let foo: &[u32] = match true {
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index f26b2c8a7..d9b5ee9cf 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -780,10 +780,7 @@ fn test() { (&S).foo(); }
780fn method_resolution_unsize_array() { 780fn method_resolution_unsize_array() {
781 check_types( 781 check_types(
782 r#" 782 r#"
783#[lang = "slice"] 783//- minicore: slice
784impl<T> [T] {
785 fn len(&self) -> usize { loop {} }
786}
787fn test() { 784fn test() {
788 let a = [1, 2, 3]; 785 let a = [1, 2, 3];
789 a.len(); 786 a.len();
@@ -1178,11 +1175,7 @@ fn main() {
1178fn autoderef_visibility_field() { 1175fn autoderef_visibility_field() {
1179 check_infer( 1176 check_infer(
1180 r#" 1177 r#"
1181#[lang = "deref"] 1178//- minicore: deref
1182pub trait Deref {
1183 type Target;
1184 fn deref(&self) -> &Self::Target;
1185}
1186mod a { 1179mod a {
1187 pub struct Foo(pub char); 1180 pub struct Foo(pub char);
1188 pub struct Bar(i32); 1181 pub struct Bar(i32);
@@ -1191,7 +1184,7 @@ mod a {
1191 Self(0) 1184 Self(0)
1192 } 1185 }
1193 } 1186 }
1194 impl super::Deref for Bar { 1187 impl core::ops::Deref for Bar {
1195 type Target = Foo; 1188 type Target = Foo;
1196 fn deref(&self) -> &Foo { 1189 fn deref(&self) -> &Foo {
1197 &Foo('z') 1190 &Foo('z')
@@ -1205,22 +1198,21 @@ mod b {
1205} 1198}
1206 "#, 1199 "#,
1207 expect![[r#" 1200 expect![[r#"
1208 67..71 'self': &Self 1201 107..138 '{ ... }': Bar
1209 200..231 '{ ... }': Bar 1202 121..125 'Self': Bar(i32) -> Bar
1210 214..218 'Self': Bar(i32) -> Bar 1203 121..128 'Self(0)': Bar
1211 214..221 'Self(0)': Bar 1204 126..127 '0': i32
1212 219..220 '0': i32 1205 226..230 'self': &Bar
1213 315..319 'self': &Bar 1206 240..273 '{ ... }': &Foo
1214 329..362 '{ ... }': &Foo 1207 254..263 '&Foo('z')': &Foo
1215 343..352 '&Foo('z')': &Foo 1208 255..258 'Foo': Foo(char) -> Foo
1216 344..347 'Foo': Foo(char) -> Foo 1209 255..263 'Foo('z')': Foo
1217 344..352 'Foo('z')': Foo 1210 259..262 ''z'': char
1218 348..351 ''z'': char 1211 303..350 '{ ... }': ()
1219 392..439 '{ ... }': () 1212 317..318 'x': char
1220 406..407 'x': char 1213 321..339 'super:...r::new': fn new() -> Bar
1221 410..428 'super:...r::new': fn new() -> Bar 1214 321..341 'super:...:new()': Bar
1222 410..430 'super:...:new()': Bar 1215 321..343 'super:...ew().0': char
1223 410..432 'super:...ew().0': char
1224 "#]], 1216 "#]],
1225 ) 1217 )
1226} 1218}
@@ -1230,11 +1222,7 @@ fn autoderef_visibility_method() {
1230 cov_mark::check!(autoderef_candidate_not_visible); 1222 cov_mark::check!(autoderef_candidate_not_visible);
1231 check_infer( 1223 check_infer(
1232 r#" 1224 r#"
1233#[lang = "deref"] 1225//- minicore: deref
1234pub trait Deref {
1235 type Target;
1236 fn deref(&self) -> &Self::Target;
1237}
1238mod a { 1226mod a {
1239 pub struct Foo(pub char); 1227 pub struct Foo(pub char);
1240 impl Foo { 1228 impl Foo {
@@ -1251,7 +1239,7 @@ mod a {
1251 self.0 1239 self.0
1252 } 1240 }
1253 } 1241 }
1254 impl super::Deref for Bar { 1242 impl core::ops::Deref for Bar {
1255 type Target = Foo; 1243 type Target = Foo;
1256 fn deref(&self) -> &Foo { 1244 fn deref(&self) -> &Foo {
1257 &Foo('z') 1245 &Foo('z')
@@ -1265,30 +1253,29 @@ mod b {
1265} 1253}
1266 "#, 1254 "#,
1267 expect![[r#" 1255 expect![[r#"
1268 67..71 'self': &Self 1256 75..79 'self': &Foo
1269 168..172 'self': &Foo 1257 89..119 '{ ... }': char
1270 182..212 '{ ... }': char 1258 103..107 'self': &Foo
1271 196..200 'self': &Foo 1259 103..109 'self.0': char
1272 196..202 'self.0': char 1260 195..226 '{ ... }': Bar
1273 288..319 '{ ... }': Bar 1261 209..213 'Self': Bar(i32) -> Bar
1274 302..306 'Self': Bar(i32) -> Bar 1262 209..216 'Self(0)': Bar
1275 302..309 'Self(0)': Bar 1263 214..215 '0': i32
1276 307..308 '0': i32 1264 245..249 'self': &Bar
1277 338..342 'self': &Bar 1265 258..288 '{ ... }': i32
1278 351..381 '{ ... }': i32 1266 272..276 'self': &Bar
1279 365..369 'self': &Bar 1267 272..278 'self.0': i32
1280 365..371 'self.0': i32 1268 376..380 'self': &Bar
1281 465..469 'self': &Bar 1269 390..423 '{ ... }': &Foo
1282 479..512 '{ ... }': &Foo 1270 404..413 '&Foo('z')': &Foo
1283 493..502 '&Foo('z')': &Foo 1271 405..408 'Foo': Foo(char) -> Foo
1284 494..497 'Foo': Foo(char) -> Foo 1272 405..413 'Foo('z')': Foo
1285 494..502 'Foo('z')': Foo 1273 409..412 ''z'': char
1286 498..501 ''z'': char 1274 453..506 '{ ... }': ()
1287 542..595 '{ ... }': () 1275 467..468 'x': char
1288 556..557 'x': char 1276 471..489 'super:...r::new': fn new() -> Bar
1289 560..578 'super:...r::new': fn new() -> Bar 1277 471..491 'super:...:new()': Bar
1290 560..580 'super:...:new()': Bar 1278 471..499 'super:...ango()': char
1291 560..588 'super:...ango()': char
1292 "#]], 1279 "#]],
1293 ) 1280 )
1294} 1281}
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index 1019e783b..abd9c385a 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -927,35 +927,33 @@ fn issue_6628() {
927fn issue_6852() { 927fn issue_6852() {
928 check_infer( 928 check_infer(
929 r#" 929 r#"
930 #[lang = "deref"] 930//- minicore: deref
931 pub trait Deref { 931use core::ops::Deref;
932 type Target;
933 }
934 932
935 struct BufWriter {} 933struct BufWriter {}
936 934
937 struct Mutex<T> {} 935struct Mutex<T> {}
938 struct MutexGuard<'a, T> {} 936struct MutexGuard<'a, T> {}
939 impl<T> Mutex<T> { 937impl<T> Mutex<T> {
940 fn lock(&self) -> MutexGuard<'_, T> {} 938 fn lock(&self) -> MutexGuard<'_, T> {}
941 } 939}
942 impl<'a, T: 'a> Deref for MutexGuard<'a, T> { 940impl<'a, T: 'a> Deref for MutexGuard<'a, T> {
943 type Target = T; 941 type Target = T;
944 } 942}
945 fn flush(&self) { 943fn flush(&self) {
946 let w: &Mutex<BufWriter>; 944 let w: &Mutex<BufWriter>;
947 *(w.lock()); 945 *(w.lock());
948 } 946}
949 "#, 947"#,
950 expect![[r#" 948 expect![[r#"
951 156..160 'self': &Mutex<T> 949 123..127 'self': &Mutex<T>
952 183..185 '{}': () 950 150..152 '{}': ()
953 267..271 'self': &{unknown} 951 234..238 'self': &{unknown}
954 273..323 '{ ...()); }': () 952 240..290 '{ ...()); }': ()
955 283..284 'w': &Mutex<BufWriter> 953 250..251 'w': &Mutex<BufWriter>
956 309..320 '*(w.lock())': BufWriter 954 276..287 '*(w.lock())': BufWriter
957 311..312 'w': &Mutex<BufWriter> 955 278..279 'w': &Mutex<BufWriter>
958 311..319 'w.lock()': MutexGuard<BufWriter> 956 278..286 'w.lock()': MutexGuard<BufWriter>
959 "#]], 957 "#]],
960 ); 958 );
961} 959}
@@ -977,37 +975,33 @@ fn param_overrides_fn() {
977fn lifetime_from_chalk_during_deref() { 975fn lifetime_from_chalk_during_deref() {
978 check_types( 976 check_types(
979 r#" 977 r#"
980 #[lang = "deref"] 978//- minicore: deref
981 pub trait Deref { 979struct Box<T: ?Sized> {}
982 type Target; 980impl<T> core::ops::Deref for Box<T> {
983 } 981 type Target = T;
984
985 struct Box<T: ?Sized> {}
986 impl<T> Deref for Box<T> {
987 type Target = T;
988 982
989 fn deref(&self) -> &Self::Target { 983 fn deref(&self) -> &Self::Target {
990 loop {} 984 loop {}
991 } 985 }
992 } 986}
993 987
994 trait Iterator { 988trait Iterator {
995 type Item; 989 type Item;
996 } 990}
997 991
998 pub struct Iter<'a, T: 'a> { 992pub struct Iter<'a, T: 'a> {
999 inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>, 993 inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
1000 } 994}
1001 995
1002 trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> { 996trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
1003 fn clone_box(&self); 997 fn clone_box(&self);
1004 } 998}
1005 999
1006 fn clone_iter<T>(s: Iter<T>) { 1000fn clone_iter<T>(s: Iter<T>) {
1007 s.inner.clone_box(); 1001 s.inner.clone_box();
1008 //^^^^^^^^^^^^^^^^^^^ () 1002 //^^^^^^^^^^^^^^^^^^^ ()
1009 } 1003}
1010 "#, 1004"#,
1011 ) 1005 )
1012} 1006}
1013 1007
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 3418ed21e..68776f3c0 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -113,7 +113,7 @@ fn type_alias_in_struct_lit() {
113fn infer_ranges() { 113fn infer_ranges() {
114 check_types( 114 check_types(
115 r#" 115 r#"
116//- /main.rs crate:main deps:core 116//- minicore: range
117fn test() { 117fn test() {
118 let a = ..; 118 let a = ..;
119 let b = 1..; 119 let b = 1..;
@@ -125,32 +125,6 @@ fn test() {
125 let t = (a, b, c, d, e, f); 125 let t = (a, b, c, d, e, f);
126 t; 126 t;
127} //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>) 127} //^ (RangeFull, RangeFrom<i32>, RangeTo<u32>, Range<usize>, RangeToInclusive<i32>, RangeInclusive<char>)
128
129//- /core.rs crate:core
130#[prelude_import] use prelude::*;
131mod prelude {}
132
133pub mod ops {
134 pub struct Range<Idx> {
135 pub start: Idx,
136 pub end: Idx,
137 }
138 pub struct RangeFrom<Idx> {
139 pub start: Idx,
140 }
141 struct RangeFull;
142 pub struct RangeInclusive<Idx> {
143 start: Idx,
144 end: Idx,
145 is_empty: u8,
146 }
147 pub struct RangeTo<Idx> {
148 pub end: Idx,
149 }
150 pub struct RangeToInclusive<Idx> {
151 pub end: Idx,
152 }
153}
154"#, 128"#,
155 ); 129 );
156} 130}
@@ -175,16 +149,17 @@ fn test() {
175fn infer_basics() { 149fn infer_basics() {
176 check_infer( 150 check_infer(
177 r#" 151 r#"
178 fn test(a: u32, b: isize, c: !, d: &str) { 152fn test(a: u32, b: isize, c: !, d: &str) {
179 a; 153 a;
180 b; 154 b;
181 c; 155 c;
182 d; 156 d;
183 1usize; 157 1usize;
184 1isize; 158 1isize;
185 "test"; 159 "test";
186 1.0f32; 160 1.0f32;
187 }"#, 161}
162"#,
188 expect![[r#" 163 expect![[r#"
189 8..9 'a': u32 164 8..9 'a': u32
190 16..17 'b': isize 165 16..17 'b': isize
@@ -207,15 +182,15 @@ fn infer_basics() {
207fn infer_let() { 182fn infer_let() {
208 check_infer( 183 check_infer(
209 r#" 184 r#"
210 fn test() { 185fn test() {
211 let a = 1isize; 186 let a = 1isize;
212 let b: usize = 1; 187 let b: usize = 1;
213 let c = b; 188 let c = b;
214 let d: u32; 189 let d: u32;
215 let e; 190 let e;
216 let f: i32 = e; 191 let f: i32 = e;
217 } 192}
218 "#, 193"#,
219 expect![[r#" 194 expect![[r#"
220 10..117 '{ ...= e; }': () 195 10..117 '{ ...= e; }': ()
221 20..21 'a': isize 196 20..21 'a': isize
@@ -236,17 +211,17 @@ fn infer_let() {
236fn infer_paths() { 211fn infer_paths() {
237 check_infer( 212 check_infer(
238 r#" 213 r#"
239 fn a() -> u32 { 1 } 214fn a() -> u32 { 1 }
240 215
241 mod b { 216mod b {
242 fn c() -> u32 { 1 } 217 fn c() -> u32 { 1 }
243 } 218}
244 219
245 fn test() { 220fn test() {
246 a(); 221 a();
247 b::c(); 222 b::c();
248 } 223}
249 "#, 224"#,
250 expect![[r#" 225 expect![[r#"
251 14..19 '{ 1 }': u32 226 14..19 '{ 1 }': u32
252 16..17 '1': u32 227 16..17 '1': u32
@@ -265,17 +240,17 @@ fn infer_paths() {
265fn infer_path_type() { 240fn infer_path_type() {
266 check_infer( 241 check_infer(
267 r#" 242 r#"
268 struct S; 243struct S;
269 244
270 impl S { 245impl S {
271 fn foo() -> i32 { 1 } 246 fn foo() -> i32 { 1 }
272 } 247}
273 248
274 fn test() { 249fn test() {
275 S::foo(); 250 S::foo();
276 <S>::foo(); 251 <S>::foo();
277 } 252}
278 "#, 253"#,
279 expect![[r#" 254 expect![[r#"
280 40..45 '{ 1 }': i32 255 40..45 '{ 1 }': i32
281 42..43 '1': i32 256 42..43 '1': i32
@@ -292,21 +267,21 @@ fn infer_path_type() {
292fn infer_struct() { 267fn infer_struct() {
293 check_infer( 268 check_infer(
294 r#" 269 r#"
295 struct A { 270struct A {
296 b: B, 271 b: B,
297 c: C, 272 c: C,
298 } 273}
299 struct B; 274struct B;
300 struct C(usize); 275struct C(usize);
301 276
302 fn test() { 277fn test() {
303 let c = C(1); 278 let c = C(1);
304 B; 279 B;
305 let a: A = A { b: B, c: C(1) }; 280 let a: A = A { b: B, c: C(1) };
306 a.b; 281 a.b;
307 a.c; 282 a.c;
308 } 283}
309 "#, 284"#,
310 expect![[r#" 285 expect![[r#"
311 71..153 '{ ...a.c; }': () 286 71..153 '{ ...a.c; }': ()
312 81..82 'c': C 287 81..82 'c': C
@@ -332,14 +307,15 @@ fn infer_struct() {
332fn infer_enum() { 307fn infer_enum() {
333 check_infer( 308 check_infer(
334 r#" 309 r#"
335 enum E { 310enum E {
336 V1 { field: u32 }, 311 V1 { field: u32 },
337 V2 312 V2
338 } 313}
339 fn test() { 314fn test() {
340 E::V1 { field: 1 }; 315 E::V1 { field: 1 };
341 E::V2; 316 E::V2;
342 }"#, 317}
318"#,
343 expect![[r#" 319 expect![[r#"
344 51..89 '{ ...:V2; }': () 320 51..89 '{ ...:V2; }': ()
345 57..75 'E::V1 ...d: 1 }': E 321 57..75 'E::V1 ...d: 1 }': E
@@ -353,23 +329,23 @@ fn infer_enum() {
353fn infer_union() { 329fn infer_union() {
354 check_infer( 330 check_infer(
355 r#" 331 r#"
356 union MyUnion { 332union MyUnion {
357 foo: u32, 333 foo: u32,
358 bar: f32, 334 bar: f32,
359 } 335}
360 336
361 fn test() { 337fn test() {
362 let u = MyUnion { foo: 0 }; 338 let u = MyUnion { foo: 0 };
363 unsafe { baz(u); } 339 unsafe { baz(u); }
364 let u = MyUnion { bar: 0.0 }; 340 let u = MyUnion { bar: 0.0 };
365 unsafe { baz(u); } 341 unsafe { baz(u); }
366 } 342}
367 343
368 unsafe fn baz(u: MyUnion) { 344unsafe fn baz(u: MyUnion) {
369 let inner = u.foo; 345 let inner = u.foo;
370 let inner = u.bar; 346 let inner = u.bar;
371 } 347}
372 "#, 348"#,
373 expect![[r#" 349 expect![[r#"
374 57..172 '{ ...); } }': () 350 57..172 '{ ...); } }': ()
375 67..68 'u': MyUnion 351 67..68 'u': MyUnion
@@ -404,19 +380,19 @@ fn infer_union() {
404fn infer_refs() { 380fn infer_refs() {
405 check_infer( 381 check_infer(
406 r#" 382 r#"
407 fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { 383fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
408 a; 384 a;
409 *a; 385 *a;
410 &a; 386 &a;
411 &mut a; 387 &mut a;
412 b; 388 b;
413 *b; 389 *b;
414 &b; 390 &b;
415 c; 391 c;
416 *c; 392 *c;
417 d; 393 d;
418 *d; 394 *d;
419 } 395}
420 "#, 396 "#,
421 expect![[r#" 397 expect![[r#"
422 8..9 'a': &u32 398 8..9 'a': &u32
@@ -450,11 +426,11 @@ fn infer_refs() {
450fn infer_raw_ref() { 426fn infer_raw_ref() {
451 check_infer( 427 check_infer(
452 r#" 428 r#"
453 fn test(a: i32) { 429fn test(a: i32) {
454 &raw mut a; 430 &raw mut a;
455 &raw const a; 431 &raw const a;
456 } 432}
457 "#, 433"#,
458 expect![[r#" 434 expect![[r#"
459 8..9 'a': i32 435 8..9 'a': i32
460 16..53 '{ ...t a; }': () 436 16..53 '{ ...t a; }': ()
@@ -524,26 +500,26 @@ h";
524fn infer_unary_op() { 500fn infer_unary_op() {
525 check_infer( 501 check_infer(
526 r#" 502 r#"
527 enum SomeType {} 503enum SomeType {}
528 504
529 fn test(x: SomeType) { 505fn test(x: SomeType) {
530 let b = false; 506 let b = false;
531 let c = !b; 507 let c = !b;
532 let a = 100; 508 let a = 100;
533 let d: i128 = -a; 509 let d: i128 = -a;
534 let e = -100; 510 let e = -100;
535 let f = !!!true; 511 let f = !!!true;
536 let g = !42; 512 let g = !42;
537 let h = !10u32; 513 let h = !10u32;
538 let j = !a; 514 let j = !a;
539 -3.14; 515 -3.14;
540 !3; 516 !3;
541 -x; 517 -x;
542 !x; 518 !x;
543 -"hello"; 519 -"hello";
544 !"hello"; 520 !"hello";
545 } 521}
546 "#, 522"#,
547 expect![[r#" 523 expect![[r#"
548 26..27 'x': SomeType 524 26..27 'x': SomeType
549 39..271 '{ ...lo"; }': () 525 39..271 '{ ...lo"; }': ()
@@ -594,19 +570,19 @@ fn infer_unary_op() {
594fn infer_backwards() { 570fn infer_backwards() {
595 check_infer( 571 check_infer(
596 r#" 572 r#"
597 fn takes_u32(x: u32) {} 573fn takes_u32(x: u32) {}
598 574
599 struct S { i32_field: i32 } 575struct S { i32_field: i32 }
600 576
601 fn test() -> &mut &f64 { 577fn test() -> &mut &f64 {
602 let a = unknown_function(); 578 let a = unknown_function();
603 takes_u32(a); 579 takes_u32(a);
604 let b = unknown_function(); 580 let b = unknown_function();
605 S { i32_field: b }; 581 S { i32_field: b };
606 let c = unknown_function(); 582 let c = unknown_function();
607 &mut &c 583 &mut &c
608 } 584}
609 "#, 585"#,
610 expect![[r#" 586 expect![[r#"
611 13..14 'x': u32 587 13..14 'x': u32
612 21..23 '{}': () 588 21..23 '{}': ()
@@ -636,23 +612,23 @@ fn infer_backwards() {
636fn infer_self() { 612fn infer_self() {
637 check_infer( 613 check_infer(
638 r#" 614 r#"
639 struct S; 615struct S;
640 616
641 impl S { 617impl S {
642 fn test(&self) { 618 fn test(&self) {
643 self; 619 self;
644 } 620 }
645 fn test2(self: &Self) { 621 fn test2(self: &Self) {
646 self; 622 self;
647 } 623 }
648 fn test3() -> Self { 624 fn test3() -> Self {
649 S {} 625 S {}
650 } 626 }
651 fn test4() -> Self { 627 fn test4() -> Self {
652 Self {} 628 Self {}
653 } 629 }
654 } 630}
655 "#, 631"#,
656 expect![[r#" 632 expect![[r#"
657 33..37 'self': &S 633 33..37 'self': &S
658 39..60 '{ ... }': () 634 39..60 '{ ... }': ()
@@ -672,30 +648,30 @@ fn infer_self() {
672fn infer_self_as_path() { 648fn infer_self_as_path() {
673 check_infer( 649 check_infer(
674 r#" 650 r#"
675 struct S1; 651struct S1;
676 struct S2(isize); 652struct S2(isize);
677 enum E { 653enum E {
678 V1, 654 V1,
679 V2(u32), 655 V2(u32),
680 } 656}
681 657
682 impl S1 { 658impl S1 {
683 fn test() { 659 fn test() {
684 Self; 660 Self;
685 } 661 }
686 } 662}
687 impl S2 { 663impl S2 {
688 fn test() { 664 fn test() {
689 Self(1); 665 Self(1);
690 } 666 }
691 } 667}
692 impl E { 668impl E {
693 fn test() { 669 fn test() {
694 Self::V1; 670 Self::V1;
695 Self::V2(1); 671 Self::V2(1);
696 } 672 }
697 } 673}
698 "#, 674"#,
699 expect![[r#" 675 expect![[r#"
700 86..107 '{ ... }': () 676 86..107 '{ ... }': ()
701 96..100 'Self': S1 677 96..100 'Self': S1
@@ -716,26 +692,26 @@ fn infer_self_as_path() {
716fn infer_binary_op() { 692fn infer_binary_op() {
717 check_infer( 693 check_infer(
718 r#" 694 r#"
719 fn f(x: bool) -> i32 { 695fn f(x: bool) -> i32 {
720 0i32 696 0i32
721 } 697}
722 698
723 fn test() -> bool { 699fn test() -> bool {
724 let x = a && b; 700 let x = a && b;
725 let y = true || false; 701 let y = true || false;
726 let z = x == y; 702 let z = x == y;
727 let t = x != y; 703 let t = x != y;
728 let minus_forty: isize = -40isize; 704 let minus_forty: isize = -40isize;
729 let h = minus_forty <= CONST_2; 705 let h = minus_forty <= CONST_2;
730 let c = f(z || y) + 5; 706 let c = f(z || y) + 5;
731 let d = b; 707 let d = b;
732 let g = minus_forty ^= i; 708 let g = minus_forty ^= i;
733 let ten: usize = 10; 709 let ten: usize = 10;
734 let ten_is_eleven = ten == some_num; 710 let ten_is_eleven = ten == some_num;
735 711
736 ten < 3 712 ten < 3
737 } 713}
738 "#, 714"#,
739 expect![[r#" 715 expect![[r#"
740 5..6 'x': bool 716 5..6 'x': bool
741 21..33 '{ 0i32 }': i32 717 21..33 '{ 0i32 }': i32
@@ -795,11 +771,11 @@ fn infer_binary_op() {
795fn infer_shift_op() { 771fn infer_shift_op() {
796 check_infer( 772 check_infer(
797 r#" 773 r#"
798 fn test() { 774fn test() {
799 1u32 << 5u8; 775 1u32 << 5u8;
800 1u32 >> 5u8; 776 1u32 >> 5u8;
801 } 777}
802 "#, 778"#,
803 expect![[r#" 779 expect![[r#"
804 10..47 '{ ...5u8; }': () 780 10..47 '{ ...5u8; }': ()
805 16..20 '1u32': u32 781 16..20 '1u32': u32
@@ -816,29 +792,29 @@ fn infer_shift_op() {
816fn infer_field_autoderef() { 792fn infer_field_autoderef() {
817 check_infer( 793 check_infer(
818 r#" 794 r#"
819 struct A { 795struct A {
820 b: B, 796 b: B,
821 } 797}
822 struct B; 798struct B;
823
824 fn test1(a: A) {
825 let a1 = a;
826 a1.b;
827 let a2 = &a;
828 a2.b;
829 let a3 = &mut a;
830 a3.b;
831 let a4 = &&&&&&&a;
832 a4.b;
833 let a5 = &mut &&mut &&mut a;
834 a5.b;
835 }
836 799
837 fn test2(a1: *const A, a2: *mut A) { 800fn test1(a: A) {
838 a1.b; 801 let a1 = a;
839 a2.b; 802 a1.b;
840 } 803 let a2 = &a;
841 "#, 804 a2.b;
805 let a3 = &mut a;
806 a3.b;
807 let a4 = &&&&&&&a;
808 a4.b;
809 let a5 = &mut &&mut &&mut a;
810 a5.b;
811}
812
813fn test2(a1: *const A, a2: *mut A) {
814 a1.b;
815 a2.b;
816}
817"#,
842 expect![[r#" 818 expect![[r#"
843 43..44 'a': A 819 43..44 'a': A
844 49..212 '{ ...5.b; }': () 820 49..212 '{ ...5.b; }': ()
@@ -891,58 +867,53 @@ fn infer_field_autoderef() {
891fn infer_argument_autoderef() { 867fn infer_argument_autoderef() {
892 check_infer( 868 check_infer(
893 r#" 869 r#"
894 #[lang = "deref"] 870//- minicore: deref
895 pub trait Deref { 871use core::ops::Deref;
896 type Target; 872struct A<T>(T);
897 fn deref(&self) -> &Self::Target;
898 }
899
900 struct A<T>(T);
901 873
902 impl<T> A<T> { 874impl<T> A<T> {
903 fn foo(&self) -> &T { 875 fn foo(&self) -> &T {
904 &self.0 876 &self.0
905 } 877 }
906 } 878}
907 879
908 struct B<T>(T); 880struct B<T>(T);
909 881
910 impl<T> Deref for B<T> { 882impl<T> Deref for B<T> {
911 type Target = T; 883 type Target = T;
912 fn deref(&self) -> &Self::Target { 884 fn deref(&self) -> &Self::Target {
913 &self.0 885 &self.0
914 } 886 }
915 } 887}
916 888
917 fn test() { 889fn test() {
918 let t = A::foo(&&B(B(A(42)))); 890 let t = A::foo(&&B(B(A(42))));
919 } 891}
920 "#, 892"#,
921 expect![[r#" 893 expect![[r#"
922 67..71 'self': &Self 894 66..70 'self': &A<T>
923 138..142 'self': &A<T> 895 78..101 '{ ... }': &T
924 150..173 '{ ... }': &T 896 88..95 '&self.0': &T
925 160..167 '&self.0': &T 897 89..93 'self': &A<T>
926 161..165 'self': &A<T> 898 89..95 'self.0': T
927 161..167 'self.0': T 899 182..186 'self': &B<T>
928 254..258 'self': &B<T> 900 205..228 '{ ... }': &T
929 277..300 '{ ... }': &T 901 215..222 '&self.0': &T
930 287..294 '&self.0': &T 902 216..220 'self': &B<T>
931 288..292 'self': &B<T> 903 216..222 'self.0': T
932 288..294 'self.0': T 904 242..280 '{ ...))); }': ()
933 314..352 '{ ...))); }': () 905 252..253 't': &i32
934 324..325 't': &i32 906 256..262 'A::foo': fn foo<i32>(&A<i32>) -> &i32
935 328..334 'A::foo': fn foo<i32>(&A<i32>) -> &i32 907 256..277 'A::foo...42))))': &i32
936 328..349 'A::foo...42))))': &i32 908 263..276 '&&B(B(A(42)))': &&B<B<A<i32>>>
937 335..348 '&&B(B(A(42)))': &&B<B<A<i32>>> 909 264..276 '&B(B(A(42)))': &B<B<A<i32>>>
938 336..348 '&B(B(A(42)))': &B<B<A<i32>>> 910 265..266 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
939 337..338 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> 911 265..276 'B(B(A(42)))': B<B<A<i32>>>
940 337..348 'B(B(A(42)))': B<B<A<i32>>> 912 267..268 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
941 339..340 'B': B<A<i32>>(A<i32>) -> B<A<i32>> 913 267..275 'B(A(42))': B<A<i32>>
942 339..347 'B(A(42))': B<A<i32>> 914 269..270 'A': A<i32>(i32) -> A<i32>
943 341..342 'A': A<i32>(i32) -> A<i32> 915 269..274 'A(42)': A<i32>
944 341..346 'A(42)': A<i32> 916 271..273 '42': i32
945 343..345 '42': i32
946 "#]], 917 "#]],
947 ); 918 );
948} 919}
@@ -951,62 +922,57 @@ fn infer_argument_autoderef() {
951fn infer_method_argument_autoderef() { 922fn infer_method_argument_autoderef() {
952 check_infer( 923 check_infer(
953 r#" 924 r#"
954 #[lang = "deref"] 925//- minicore: deref
955 pub trait Deref { 926use core::ops::Deref;
956 type Target; 927struct A<T>(*mut T);
957 fn deref(&self) -> &Self::Target;
958 }
959 928
960 struct A<T>(*mut T); 929impl<T> A<T> {
961 930 fn foo(&self, x: &A<T>) -> &T {
962 impl<T> A<T> { 931 &*x.0
963 fn foo(&self, x: &A<T>) -> &T { 932 }
964 &*x.0 933}
965 }
966 }
967 934
968 struct B<T>(T); 935struct B<T>(T);
969 936
970 impl<T> Deref for B<T> { 937impl<T> Deref for B<T> {
971 type Target = T; 938 type Target = T;
972 fn deref(&self) -> &Self::Target { 939 fn deref(&self) -> &Self::Target {
973 &self.0 940 &self.0
974 } 941 }
975 } 942}
976 943
977 fn test(a: A<i32>) { 944fn test(a: A<i32>) {
978 let t = A(0 as *mut _).foo(&&B(B(a))); 945 let t = A(0 as *mut _).foo(&&B(B(a)));
979 } 946}
980 "#, 947"#,
981 expect![[r#" 948 expect![[r#"
982 67..71 'self': &Self 949 71..75 'self': &A<T>
983 143..147 'self': &A<T> 950 77..78 'x': &A<T>
984 149..150 'x': &A<T> 951 93..114 '{ ... }': &T
985 165..186 '{ ... }': &T 952 103..108 '&*x.0': &T
986 175..180 '&*x.0': &T 953 104..108 '*x.0': T
987 176..180 '*x.0': T 954 105..106 'x': &A<T>
988 177..178 'x': &A<T> 955 105..108 'x.0': *mut T
989 177..180 'x.0': *mut T 956 195..199 'self': &B<T>
990 267..271 'self': &B<T> 957 218..241 '{ ... }': &T
991 290..313 '{ ... }': &T 958 228..235 '&self.0': &T
992 300..307 '&self.0': &T 959 229..233 'self': &B<T>
993 301..305 'self': &B<T> 960 229..235 'self.0': T
994 301..307 'self.0': T 961 253..254 'a': A<i32>
995 325..326 'a': A<i32> 962 264..310 '{ ...))); }': ()
996 336..382 '{ ...))); }': () 963 274..275 't': &i32
997 346..347 't': &i32 964 278..279 'A': A<i32>(*mut i32) -> A<i32>
998 350..351 'A': A<i32>(*mut i32) -> A<i32> 965 278..292 'A(0 as *mut _)': A<i32>
999 350..364 'A(0 as *mut _)': A<i32> 966 278..307 'A(0 as...B(a)))': &i32
1000 350..379 'A(0 as...B(a)))': &i32 967 280..281 '0': i32
1001 352..353 '0': i32 968 280..291 '0 as *mut _': *mut i32
1002 352..363 '0 as *mut _': *mut i32 969 297..306 '&&B(B(a))': &&B<B<A<i32>>>
1003 369..378 '&&B(B(a))': &&B<B<A<i32>>> 970 298..306 '&B(B(a))': &B<B<A<i32>>>
1004 370..378 '&B(B(a))': &B<B<A<i32>>> 971 299..300 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
1005 371..372 'B': B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>> 972 299..306 'B(B(a))': B<B<A<i32>>>
1006 371..378 'B(B(a))': B<B<A<i32>>> 973 301..302 'B': B<A<i32>>(A<i32>) -> B<A<i32>>
1007 373..374 'B': B<A<i32>>(A<i32>) -> B<A<i32>> 974 301..305 'B(a)': B<A<i32>>
1008 373..377 'B(a)': B<A<i32>> 975 303..304 'a': A<i32>
1009 375..376 'a': A<i32>
1010 "#]], 976 "#]],
1011 ); 977 );
1012} 978}
@@ -1015,15 +981,15 @@ fn infer_method_argument_autoderef() {
1015fn infer_in_elseif() { 981fn infer_in_elseif() {
1016 check_infer( 982 check_infer(
1017 r#" 983 r#"
1018 struct Foo { field: i32 } 984struct Foo { field: i32 }
1019 fn main(foo: Foo) { 985fn main(foo: Foo) {
1020 if true { 986 if true {
1021 987
1022 } else if false { 988 } else if false {
1023 foo.field 989 foo.field
1024 } 990 }
1025 } 991}
1026 "#, 992"#,
1027 expect![[r#" 993 expect![[r#"
1028 34..37 'foo': Foo 994 34..37 'foo': Foo
1029 44..108 '{ ... } }': () 995 44..108 '{ ... } }': ()
@@ -1043,28 +1009,29 @@ fn infer_in_elseif() {
1043fn infer_if_match_with_return() { 1009fn infer_if_match_with_return() {
1044 check_infer( 1010 check_infer(
1045 r#" 1011 r#"
1046 fn foo() { 1012fn foo() {
1047 let _x1 = if true { 1013 let _x1 = if true {
1048 1 1014 1
1049 } else { 1015 } else {
1050 return; 1016 return;
1051 }; 1017 };
1052 let _x2 = if true { 1018 let _x2 = if true {
1053 2 1019 2
1054 } else { 1020 } else {
1055 return 1021 return
1056 }; 1022 };
1057 let _x3 = match true { 1023 let _x3 = match true {
1058 true => 3, 1024 true => 3,
1059 _ => { 1025 _ => {
1060 return; 1026 return;
1061 } 1027 }
1062 }; 1028 };
1063 let _x4 = match true { 1029 let _x4 = match true {
1064 true => 4, 1030 true => 4,
1065 _ => return 1031 _ => return
1066 }; 1032 };
1067 }"#, 1033}
1034"#,
1068 expect![[r#" 1035 expect![[r#"
1069 9..322 '{ ... }; }': () 1036 9..322 '{ ... }; }': ()
1070 19..22 '_x1': i32 1037 19..22 '_x1': i32
@@ -2639,11 +2606,8 @@ fn f() {
2639fn infer_boxed_self_receiver() { 2606fn infer_boxed_self_receiver() {
2640 check_infer( 2607 check_infer(
2641 r#" 2608 r#"
2642#[lang = "deref"] 2609//- minicore: deref
2643pub trait Deref { 2610use core::ops::Deref;
2644 type Target;
2645 fn deref(&self) -> &Self::Target;
2646}
2647 2611
2648struct Box<T>(T); 2612struct Box<T>(T);
2649 2613
@@ -2675,40 +2639,39 @@ fn main() {
2675} 2639}
2676 "#, 2640 "#,
2677 expect![[r#" 2641 expect![[r#"
2678 67..71 'self': &Self 2642 104..108 'self': &Box<T>
2679 175..179 'self': &Box<T> 2643 188..192 'self': &Box<Foo<T>>
2680 259..263 'self': &Box<Foo<T>> 2644 218..220 '{}': ()
2681 289..291 '{}': () 2645 242..246 'self': &Box<Foo<T>>
2682 313..317 'self': &Box<Foo<T>> 2646 275..277 '{}': ()
2683 346..348 '{}': () 2647 297..301 'self': Box<Foo<T>>
2684 368..372 'self': Box<Foo<T>> 2648 322..324 '{}': ()
2685 393..395 '{}': () 2649 338..559 '{ ...r(); }': ()
2686 409..630 '{ ...r(); }': () 2650 348..353 'boxed': Box<Foo<i32>>
2687 419..424 'boxed': Box<Foo<i32>> 2651 356..359 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>
2688 427..430 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>> 2652 356..371 'Box(Foo(0_i32))': Box<Foo<i32>>
2689 427..442 'Box(Foo(0_i32))': Box<Foo<i32>> 2653 360..363 'Foo': Foo<i32>(i32) -> Foo<i32>
2690 431..434 'Foo': Foo<i32>(i32) -> Foo<i32> 2654 360..370 'Foo(0_i32)': Foo<i32>
2691 431..441 'Foo(0_i32)': Foo<i32> 2655 364..369 '0_i32': i32
2692 435..440 '0_i32': i32 2656 382..386 'bad1': &i32
2693 453..457 'bad1': &i32 2657 389..394 'boxed': Box<Foo<i32>>
2694 460..465 'boxed': Box<Foo<i32>> 2658 389..406 'boxed....nner()': &i32
2695 460..477 'boxed....nner()': &i32 2659 416..421 'good1': &i32
2696 487..492 'good1': &i32 2660 424..438 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32
2697 495..509 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32 2661 424..446 'Foo::g...boxed)': &i32
2698 495..517 'Foo::g...boxed)': &i32 2662 439..445 '&boxed': &Box<Foo<i32>>
2699 510..516 '&boxed': &Box<Foo<i32>> 2663 440..445 'boxed': Box<Foo<i32>>
2700 511..516 'boxed': Box<Foo<i32>> 2664 457..461 'bad2': &Foo<i32>
2701 528..532 'bad2': &Foo<i32> 2665 464..469 'boxed': Box<Foo<i32>>
2702 535..540 'boxed': Box<Foo<i32>> 2666 464..480 'boxed....self()': &Foo<i32>
2703 535..551 'boxed....self()': &Foo<i32> 2667 490..495 'good2': &Foo<i32>
2704 561..566 'good2': &Foo<i32> 2668 498..511 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32>
2705 569..582 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32> 2669 498..519 'Foo::g...boxed)': &Foo<i32>
2706 569..590 'Foo::g...boxed)': &Foo<i32> 2670 512..518 '&boxed': &Box<Foo<i32>>
2707 583..589 '&boxed': &Box<Foo<i32>> 2671 513..518 'boxed': Box<Foo<i32>>
2708 584..589 'boxed': Box<Foo<i32>> 2672 530..535 'inner': Foo<i32>
2709 601..606 'inner': Foo<i32> 2673 538..543 'boxed': Box<Foo<i32>>
2710 609..614 'boxed': Box<Foo<i32>> 2674 538..556 'boxed....nner()': Foo<i32>
2711 609..627 'boxed....nner()': Foo<i32>
2712 "#]], 2675 "#]],
2713 ); 2676 );
2714} 2677}
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 6bcede4c4..65fed02d2 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -6,10 +6,10 @@ use super::{check_infer, check_infer_with_mismatches, check_types};
6fn infer_await() { 6fn infer_await() {
7 check_types( 7 check_types(
8 r#" 8 r#"
9//- /main.rs crate:main deps:core 9//- minicore: future
10struct IntFuture; 10struct IntFuture;
11 11
12impl Future for IntFuture { 12impl core::future::Future for IntFuture {
13 type Output = u64; 13 type Output = u64;
14} 14}
15 15
@@ -18,16 +18,6 @@ fn test() {
18 let v = r.await; 18 let v = r.await;
19 v; 19 v;
20} //^ u64 20} //^ u64
21
22//- /core.rs crate:core
23pub mod prelude {
24 pub mod rust_2018 {
25 #[lang = "future_trait"]
26 pub trait Future {
27 type Output;
28 }
29 }
30}
31"#, 21"#,
32 ); 22 );
33} 23}
@@ -36,25 +26,14 @@ pub mod prelude {
36fn infer_async() { 26fn infer_async() {
37 check_types( 27 check_types(
38 r#" 28 r#"
39//- /main.rs crate:main deps:core 29//- minicore: future
40async fn foo() -> u64 { 30async fn foo() -> u64 { 128 }
41 128
42}
43 31
44fn test() { 32fn test() {
45 let r = foo(); 33 let r = foo();
46 let v = r.await; 34 let v = r.await;
47 v; 35 v;
48} //^ u64 36} //^ u64
49
50//- /core.rs crate:core
51#[prelude_import] use future::*;
52mod future {
53 #[lang = "future_trait"]
54 trait Future {
55 type Output;
56 }
57}
58"#, 37"#,
59 ); 38 );
60} 39}
@@ -63,24 +42,13 @@ mod future {
63fn infer_desugar_async() { 42fn infer_desugar_async() {
64 check_types( 43 check_types(
65 r#" 44 r#"
66//- /main.rs crate:main deps:core 45//- minicore: future
67async fn foo() -> u64 { 46async fn foo() -> u64 { 128 }
68 128
69}
70 47
71fn test() { 48fn test() {
72 let r = foo(); 49 let r = foo();
73 r; 50 r;
74} //^ impl Future<Output = u64> 51} //^ impl Future<Output = u64>
75
76//- /core.rs crate:core
77#[prelude_import] use future::*;
78mod future {
79 trait Future {
80 type Output;
81 }
82}
83
84"#, 52"#,
85 ); 53 );
86} 54}
@@ -89,7 +57,7 @@ mod future {
89fn infer_async_block() { 57fn infer_async_block() {
90 check_types( 58 check_types(
91 r#" 59 r#"
92//- /main.rs crate:main deps:core 60//- minicore: future, option
93async fn test() { 61async fn test() {
94 let a = async { 42 }; 62 let a = async { 42 };
95 a; 63 a;
@@ -101,7 +69,7 @@ async fn test() {
101 b; 69 b;
102// ^ () 70// ^ ()
103 let c = async { 71 let c = async {
104 let y = Option::None; 72 let y = None;
105 y 73 y
106 // ^ Option<u64> 74 // ^ Option<u64>
107 }; 75 };
@@ -109,18 +77,6 @@ async fn test() {
109 c; 77 c;
110// ^ impl Future<Output = Option<u64>> 78// ^ impl Future<Output = Option<u64>>
111} 79}
112
113enum Option<T> { None, Some(T) }
114
115//- /core.rs crate:core
116#[prelude_import] use future::*;
117mod future {
118 #[lang = "future_trait"]
119 trait Future {
120 type Output;
121 }
122}
123
124"#, 80"#,
125 ); 81 );
126} 82}
@@ -704,14 +660,9 @@ mod ops {
704fn deref_trait() { 660fn deref_trait() {
705 check_types( 661 check_types(
706 r#" 662 r#"
707#[lang = "deref"] 663//- minicore: deref
708trait Deref {
709 type Target;
710 fn deref(&self) -> &Self::Target;
711}
712
713struct Arc<T>; 664struct Arc<T>;
714impl<T> Deref for Arc<T> { 665impl<T> core::ops::Deref for Arc<T> {
715 type Target = T; 666 type Target = T;
716} 667}
717 668
@@ -731,16 +682,10 @@ fn test(s: Arc<S>) {
731fn deref_trait_with_inference_var() { 682fn deref_trait_with_inference_var() {
732 check_types( 683 check_types(
733 r#" 684 r#"
734//- /main.rs 685//- minicore: deref
735#[lang = "deref"]
736trait Deref {
737 type Target;
738 fn deref(&self) -> &Self::Target;
739}
740
741struct Arc<T>; 686struct Arc<T>;
742fn new_arc<T>() -> Arc<T> {} 687fn new_arc<T>() -> Arc<T> {}
743impl<T> Deref for Arc<T> { 688impl<T> core::ops::Deref for Arc<T> {
744 type Target = T; 689 type Target = T;
745} 690}
746 691
@@ -761,15 +706,10 @@ fn test() {
761fn deref_trait_infinite_recursion() { 706fn deref_trait_infinite_recursion() {
762 check_types( 707 check_types(
763 r#" 708 r#"
764#[lang = "deref"] 709//- minicore: deref
765trait Deref {
766 type Target;
767 fn deref(&self) -> &Self::Target;
768}
769
770struct S; 710struct S;
771 711
772impl Deref for S { 712impl core::ops::Deref for S {
773 type Target = S; 713 type Target = S;
774} 714}
775 715
@@ -784,14 +724,9 @@ fn test(s: S) {
784fn deref_trait_with_question_mark_size() { 724fn deref_trait_with_question_mark_size() {
785 check_types( 725 check_types(
786 r#" 726 r#"
787#[lang = "deref"] 727//- minicore: deref
788trait Deref {
789 type Target;
790 fn deref(&self) -> &Self::Target;
791}
792
793struct Arc<T>; 728struct Arc<T>;
794impl<T> Deref for Arc<T> { 729impl<T: ?Sized> core::ops::Deref for Arc<T> {
795 type Target = T; 730 type Target = T;
796} 731}
797 732
@@ -1475,7 +1410,6 @@ fn test(
1475} 1410}
1476 1411
1477#[test] 1412#[test]
1478#[ignore]
1479fn error_bound_chalk() { 1413fn error_bound_chalk() {
1480 check_types( 1414 check_types(
1481 r#" 1415 r#"
@@ -2626,12 +2560,9 @@ fn test<T: Trait>() {
2626fn dyn_trait_through_chalk() { 2560fn dyn_trait_through_chalk() {
2627 check_types( 2561 check_types(
2628 r#" 2562 r#"
2563//- minicore: deref
2629struct Box<T> {} 2564struct Box<T> {}
2630#[lang = "deref"] 2565impl<T> core::ops::Deref for Box<T> {
2631trait Deref {
2632 type Target;
2633}
2634impl<T> Deref for Box<T> {
2635 type Target = T; 2566 type Target = T;
2636} 2567}
2637trait Trait { 2568trait Trait {
@@ -3696,16 +3627,7 @@ impl foo::Foo for u32 {
3696fn infer_async_ret_type() { 3627fn infer_async_ret_type() {
3697 check_types( 3628 check_types(
3698 r#" 3629 r#"
3699//- /main.rs crate:main deps:core 3630//- minicore: future, result
3700
3701enum Result<T, E> {
3702 Ok(T),
3703 Err(E),
3704}
3705
3706use Result::*;
3707
3708
3709struct Fooey; 3631struct Fooey;
3710 3632
3711impl Fooey { 3633impl Fooey {
@@ -3728,15 +3650,6 @@ async fn get_accounts() -> Result<u32, ()> {
3728 // ^ u32 3650 // ^ u32
3729 Ok(ret) 3651 Ok(ret)
3730} 3652}
3731
3732//- /core.rs crate:core
3733#[prelude_import] use future::*;
3734mod future {
3735 #[lang = "future_trait"]
3736 trait Future {
3737 type Output;
3738 }
3739}
3740"#, 3653"#,
3741 ); 3654 );
3742} 3655}
diff --git a/crates/ide/Cargo.toml b/crates/ide/Cargo.toml
index f12928225..0e8447394 100644
--- a/crates/ide/Cargo.toml
+++ b/crates/ide/Cargo.toml
@@ -29,6 +29,7 @@ ide_db = { path = "../ide_db", version = "0.0.0" }
29cfg = { path = "../cfg", version = "0.0.0" } 29cfg = { path = "../cfg", version = "0.0.0" }
30profile = { path = "../profile", version = "0.0.0" } 30profile = { path = "../profile", version = "0.0.0" }
31ide_assists = { path = "../ide_assists", version = "0.0.0" } 31ide_assists = { path = "../ide_assists", version = "0.0.0" }
32ide_diagnostics = { path = "../ide_diagnostics", version = "0.0.0" }
32ide_ssr = { path = "../ide_ssr", version = "0.0.0" } 33ide_ssr = { path = "../ide_ssr", version = "0.0.0" }
33ide_completion = { path = "../ide_completion", version = "0.0.0" } 34ide_completion = { path = "../ide_completion", version = "0.0.0" }
34 35
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
deleted file mode 100644
index 815a633e5..000000000
--- a/crates/ide/src/diagnostics.rs
+++ /dev/null
@@ -1,498 +0,0 @@
1//! Collects diagnostics & fixits for a single file.
2//!
3//! The tricky bit here is that diagnostics are produced by hir in terms of
4//! macro-expanded files, but we need to present them to the users in terms of
5//! original files. So we need to map the ranges.
6
7mod break_outside_of_loop;
8mod inactive_code;
9mod incorrect_case;
10mod macro_error;
11mod mismatched_arg_count;
12mod missing_fields;
13mod missing_match_arms;
14mod missing_ok_or_some_in_tail_expr;
15mod missing_unsafe;
16mod no_such_field;
17mod remove_this_semicolon;
18mod replace_filter_map_next_with_find_map;
19mod unimplemented_builtin_macro;
20mod unlinked_file;
21mod unresolved_extern_crate;
22mod unresolved_import;
23mod unresolved_macro_call;
24mod unresolved_module;
25mod unresolved_proc_macro;
26
27mod field_shorthand;
28
29use hir::{diagnostics::AnyDiagnostic, Semantics};
30use ide_assists::AssistResolveStrategy;
31use ide_db::{base_db::SourceDatabase, RootDatabase};
32use itertools::Itertools;
33use rustc_hash::FxHashSet;
34use syntax::{
35 ast::{self, AstNode},
36 SyntaxNode, TextRange,
37};
38use text_edit::TextEdit;
39use unlinked_file::UnlinkedFile;
40
41use crate::{Assist, AssistId, AssistKind, FileId, Label, SourceChange};
42
43#[derive(Copy, Clone, Debug, PartialEq)]
44pub struct DiagnosticCode(pub &'static str);
45
46impl DiagnosticCode {
47 pub fn as_str(&self) -> &str {
48 self.0
49 }
50}
51
52#[derive(Debug)]
53pub struct Diagnostic {
54 pub code: DiagnosticCode,
55 pub message: String,
56 pub range: TextRange,
57 pub severity: Severity,
58 pub unused: bool,
59 pub experimental: bool,
60 pub fixes: Option<Vec<Assist>>,
61}
62
63impl Diagnostic {
64 fn new(code: &'static str, message: impl Into<String>, range: TextRange) -> Diagnostic {
65 let message = message.into();
66 Diagnostic {
67 code: DiagnosticCode(code),
68 message,
69 range,
70 severity: Severity::Error,
71 unused: false,
72 experimental: false,
73 fixes: None,
74 }
75 }
76
77 fn experimental(mut self) -> Diagnostic {
78 self.experimental = true;
79 self
80 }
81
82 fn severity(mut self, severity: Severity) -> Diagnostic {
83 self.severity = severity;
84 self
85 }
86
87 fn with_fixes(mut self, fixes: Option<Vec<Assist>>) -> Diagnostic {
88 self.fixes = fixes;
89 self
90 }
91
92 fn with_unused(mut self, unused: bool) -> Diagnostic {
93 self.unused = unused;
94 self
95 }
96}
97
98#[derive(Debug, Copy, Clone)]
99pub enum Severity {
100 Error,
101 WeakWarning,
102}
103
104#[derive(Default, Debug, Clone)]
105pub struct DiagnosticsConfig {
106 pub disable_experimental: bool,
107 pub disabled: FxHashSet<String>,
108}
109
110struct DiagnosticsContext<'a> {
111 config: &'a DiagnosticsConfig,
112 sema: Semantics<'a, RootDatabase>,
113 resolve: &'a AssistResolveStrategy,
114}
115
116pub(crate) fn diagnostics(
117 db: &RootDatabase,
118 config: &DiagnosticsConfig,
119 resolve: &AssistResolveStrategy,
120 file_id: FileId,
121) -> Vec<Diagnostic> {
122 let _p = profile::span("diagnostics");
123 let sema = Semantics::new(db);
124 let parse = db.parse(file_id);
125 let mut res = Vec::new();
126
127 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
128 res.extend(
129 parse.errors().iter().take(128).map(|err| {
130 Diagnostic::new("syntax-error", format!("Syntax Error: {}", err), err.range())
131 }),
132 );
133
134 for node in parse.tree().syntax().descendants() {
135 check_unnecessary_braces_in_use_statement(&mut res, file_id, &node);
136 field_shorthand::check(&mut res, file_id, &node);
137 }
138
139 let mut diags = Vec::new();
140 let module = sema.to_module_def(file_id);
141 if let Some(m) = module {
142 m.diagnostics(db, &mut diags)
143 }
144
145 let ctx = DiagnosticsContext { config, sema, resolve };
146 if module.is_none() {
147 let d = UnlinkedFile { file: file_id };
148 let d = unlinked_file::unlinked_file(&ctx, &d);
149 res.push(d)
150 }
151
152 for diag in diags {
153 #[rustfmt::skip]
154 let d = match diag {
155 AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d),
156 AnyDiagnostic::IncorrectCase(d) => incorrect_case::incorrect_case(&ctx, &d),
157 AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d),
158 AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d),
159 AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
160 AnyDiagnostic::MissingMatchArms(d) => missing_match_arms::missing_match_arms(&ctx, &d),
161 AnyDiagnostic::MissingOkOrSomeInTailExpr(d) => missing_ok_or_some_in_tail_expr::missing_ok_or_some_in_tail_expr(&ctx, &d),
162 AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d),
163 AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d),
164 AnyDiagnostic::RemoveThisSemicolon(d) => remove_this_semicolon::remove_this_semicolon(&ctx, &d),
165 AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d),
166 AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),
167 AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
168 AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d),
169 AnyDiagnostic::UnresolvedMacroCall(d) => unresolved_macro_call::unresolved_macro_call(&ctx, &d),
170 AnyDiagnostic::UnresolvedModule(d) => unresolved_module::unresolved_module(&ctx, &d),
171 AnyDiagnostic::UnresolvedProcMacro(d) => unresolved_proc_macro::unresolved_proc_macro(&ctx, &d),
172
173 AnyDiagnostic::InactiveCode(d) => match inactive_code::inactive_code(&ctx, &d) {
174 Some(it) => it,
175 None => continue,
176 }
177 };
178 res.push(d)
179 }
180
181 res.retain(|d| {
182 !ctx.config.disabled.contains(d.code.as_str())
183 && !(ctx.config.disable_experimental && d.experimental)
184 });
185
186 res
187}
188
189fn check_unnecessary_braces_in_use_statement(
190 acc: &mut Vec<Diagnostic>,
191 file_id: FileId,
192 node: &SyntaxNode,
193) -> Option<()> {
194 let use_tree_list = ast::UseTreeList::cast(node.clone())?;
195 if let Some((single_use_tree,)) = use_tree_list.use_trees().collect_tuple() {
196 // If there is a comment inside the bracketed `use`,
197 // assume it is a commented out module path and don't show diagnostic.
198 if use_tree_list.has_inner_comment() {
199 return Some(());
200 }
201
202 let use_range = use_tree_list.syntax().text_range();
203 let edit =
204 text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(&single_use_tree)
205 .unwrap_or_else(|| {
206 let to_replace = single_use_tree.syntax().text().to_string();
207 let mut edit_builder = TextEdit::builder();
208 edit_builder.delete(use_range);
209 edit_builder.insert(use_range.start(), to_replace);
210 edit_builder.finish()
211 });
212
213 acc.push(
214 Diagnostic::new(
215 "unnecessary-braces",
216 "Unnecessary braces in use statement".to_string(),
217 use_range,
218 )
219 .severity(Severity::WeakWarning)
220 .with_fixes(Some(vec![fix(
221 "remove_braces",
222 "Remove unnecessary braces",
223 SourceChange::from_text_edit(file_id, edit),
224 use_range,
225 )])),
226 );
227 }
228
229 Some(())
230}
231
232fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
233 single_use_tree: &ast::UseTree,
234) -> Option<TextEdit> {
235 let use_tree_list_node = single_use_tree.syntax().parent()?;
236 if single_use_tree.path()?.segment()?.self_token().is_some() {
237 let start = use_tree_list_node.prev_sibling_or_token()?.text_range().start();
238 let end = use_tree_list_node.text_range().end();
239 return Some(TextEdit::delete(TextRange::new(start, end)));
240 }
241 None
242}
243
244fn fix(id: &'static str, label: &str, source_change: SourceChange, target: TextRange) -> Assist {
245 let mut res = unresolved_fix(id, label, target);
246 res.source_change = Some(source_change);
247 res
248}
249
250fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
251 assert!(!id.contains(' '));
252 Assist {
253 id: AssistId(id, AssistKind::QuickFix),
254 label: Label::new(label),
255 group: None,
256 target,
257 source_change: None,
258 }
259}
260
261#[cfg(test)]
262mod tests {
263 use expect_test::Expect;
264 use ide_assists::AssistResolveStrategy;
265 use stdx::trim_indent;
266 use test_utils::{assert_eq_text, extract_annotations};
267
268 use crate::{fixture, DiagnosticsConfig};
269
270 /// Takes a multi-file input fixture with annotated cursor positions,
271 /// and checks that:
272 /// * a diagnostic is produced
273 /// * the first diagnostic fix trigger range touches the input cursor position
274 /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
275 #[track_caller]
276 pub(crate) fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) {
277 check_nth_fix(0, ra_fixture_before, ra_fixture_after);
278 }
279 /// Takes a multi-file input fixture with annotated cursor positions,
280 /// and checks that:
281 /// * a diagnostic is produced
282 /// * every diagnostic fixes trigger range touches the input cursor position
283 /// * that the contents of the file containing the cursor match `after` after each diagnostic fix is applied
284 pub(crate) fn check_fixes(ra_fixture_before: &str, ra_fixtures_after: Vec<&str>) {
285 for (i, ra_fixture_after) in ra_fixtures_after.iter().enumerate() {
286 check_nth_fix(i, ra_fixture_before, ra_fixture_after)
287 }
288 }
289
290 #[track_caller]
291 fn check_nth_fix(nth: usize, ra_fixture_before: &str, ra_fixture_after: &str) {
292 let after = trim_indent(ra_fixture_after);
293
294 let (analysis, file_position) = fixture::position(ra_fixture_before);
295 let diagnostic = analysis
296 .diagnostics(
297 &DiagnosticsConfig::default(),
298 AssistResolveStrategy::All,
299 file_position.file_id,
300 )
301 .unwrap()
302 .pop()
303 .expect("no diagnostics");
304 let fix = &diagnostic.fixes.expect("diagnostic misses fixes")[nth];
305 let actual = {
306 let source_change = fix.source_change.as_ref().unwrap();
307 let file_id = *source_change.source_file_edits.keys().next().unwrap();
308 let mut actual = analysis.file_text(file_id).unwrap().to_string();
309
310 for edit in source_change.source_file_edits.values() {
311 edit.apply(&mut actual);
312 }
313 actual
314 };
315
316 assert_eq_text!(&after, &actual);
317 assert!(
318 fix.target.contains_inclusive(file_position.offset),
319 "diagnostic fix range {:?} does not touch cursor position {:?}",
320 fix.target,
321 file_position.offset
322 );
323 }
324
325 /// Checks that there's a diagnostic *without* fix at `$0`.
326 pub(crate) fn check_no_fix(ra_fixture: &str) {
327 let (analysis, file_position) = fixture::position(ra_fixture);
328 let diagnostic = analysis
329 .diagnostics(
330 &DiagnosticsConfig::default(),
331 AssistResolveStrategy::All,
332 file_position.file_id,
333 )
334 .unwrap()
335 .pop()
336 .unwrap();
337 assert!(diagnostic.fixes.is_none(), "got a fix when none was expected: {:?}", diagnostic);
338 }
339
340 pub(crate) fn check_expect(ra_fixture: &str, expect: Expect) {
341 let (analysis, file_id) = fixture::file(ra_fixture);
342 let diagnostics = analysis
343 .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id)
344 .unwrap();
345 expect.assert_debug_eq(&diagnostics)
346 }
347
348 #[track_caller]
349 pub(crate) fn check_diagnostics(ra_fixture: &str) {
350 let mut config = DiagnosticsConfig::default();
351 config.disabled.insert("inactive-code".to_string());
352 check_diagnostics_with_config(config, ra_fixture)
353 }
354
355 #[track_caller]
356 pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixture: &str) {
357 let (analysis, files) = fixture::files(ra_fixture);
358 for file_id in files {
359 let diagnostics =
360 analysis.diagnostics(&config, AssistResolveStrategy::All, file_id).unwrap();
361
362 let expected = extract_annotations(&*analysis.file_text(file_id).unwrap());
363 let mut actual =
364 diagnostics.into_iter().map(|d| (d.range, d.message)).collect::<Vec<_>>();
365 actual.sort_by_key(|(range, _)| range.start());
366 assert_eq!(expected, actual);
367 }
368 }
369
370 #[test]
371 fn test_check_unnecessary_braces_in_use_statement() {
372 check_diagnostics(
373 r#"
374use a;
375use a::{c, d::e};
376
377mod a {
378 mod c {}
379 mod d {
380 mod e {}
381 }
382}
383"#,
384 );
385 check_diagnostics(
386 r#"
387use a;
388use a::{
389 c,
390 // d::e
391};
392
393mod a {
394 mod c {}
395 mod d {
396 mod e {}
397 }
398}
399"#,
400 );
401 check_fix(
402 r"
403 mod b {}
404 use {$0b};
405 ",
406 r"
407 mod b {}
408 use b;
409 ",
410 );
411 check_fix(
412 r"
413 mod b {}
414 use {b$0};
415 ",
416 r"
417 mod b {}
418 use b;
419 ",
420 );
421 check_fix(
422 r"
423 mod a { mod c {} }
424 use a::{c$0};
425 ",
426 r"
427 mod a { mod c {} }
428 use a::c;
429 ",
430 );
431 check_fix(
432 r"
433 mod a {}
434 use a::{self$0};
435 ",
436 r"
437 mod a {}
438 use a;
439 ",
440 );
441 check_fix(
442 r"
443 mod a { mod c {} mod d { mod e {} } }
444 use a::{c, d::{e$0}};
445 ",
446 r"
447 mod a { mod c {} mod d { mod e {} } }
448 use a::{c, d::e};
449 ",
450 );
451 }
452
453 #[test]
454 fn test_disabled_diagnostics() {
455 let mut config = DiagnosticsConfig::default();
456 config.disabled.insert("unresolved-module".into());
457
458 let (analysis, file_id) = fixture::file(r#"mod foo;"#);
459
460 let diagnostics =
461 analysis.diagnostics(&config, AssistResolveStrategy::All, file_id).unwrap();
462 assert!(diagnostics.is_empty());
463
464 let diagnostics = analysis
465 .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id)
466 .unwrap();
467 assert!(!diagnostics.is_empty());
468 }
469
470 #[test]
471 fn import_extern_crate_clash_with_inner_item() {
472 // This is more of a resolver test, but doesn't really work with the hir_def testsuite.
473
474 check_diagnostics(
475 r#"
476//- /lib.rs crate:lib deps:jwt
477mod permissions;
478
479use permissions::jwt;
480
481fn f() {
482 fn inner() {}
483 jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic
484}
485
486//- /permissions.rs
487pub mod jwt {
488 pub struct Claims {}
489}
490
491//- /jwt/lib.rs crate:jwt
492pub struct Claims {
493 field: u8,
494}
495 "#,
496 );
497 }
498}
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs
index b75ec411c..455b32456 100644
--- a/crates/ide/src/display/navigation_target.rs
+++ b/crates/ide/src/display/navigation_target.rs
@@ -442,10 +442,10 @@ impl TryToNav for hir::TypeParam {
442 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { 442 fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
443 let src = self.source(db)?; 443 let src = self.source(db)?;
444 let full_range = match &src.value { 444 let full_range = match &src.value {
445 Either::Left(it) => it 445 Either::Left(type_param) => type_param.syntax().text_range(),
446 Either::Right(trait_) => trait_
446 .name() 447 .name()
447 .map_or_else(|| it.syntax().text_range(), |name| name.syntax().text_range()), 448 .map_or_else(|| trait_.syntax().text_range(), |name| name.syntax().text_range()),
448 Either::Right(it) => it.syntax().text_range(),
449 }; 449 };
450 let focus_range = match &src.value { 450 let focus_range = match &src.value {
451 Either::Left(it) => it.name(), 451 Either::Left(it) => it.name(),
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index 57ae9455b..7ac0118fe 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -241,6 +241,10 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
241 Definition::ModuleDef(ModuleDef::Module(module)) => module.krate(), 241 Definition::ModuleDef(ModuleDef::Module(module)) => module.krate(),
242 _ => definition.module(db)?.krate(), 242 _ => definition.module(db)?.krate(),
243 }; 243 };
244 // FIXME: using import map doesn't make sense here. What we want here is
245 // canonical path. What import map returns is the shortest path suitable for
246 // import. See this test:
247 cov_mark::hit!(test_reexport_order);
244 let import_map = db.import_map(krate.into()); 248 let import_map = db.import_map(krate.into());
245 249
246 let mut base = krate.display_name(db)?.to_string(); 250 let mut base = krate.display_name(db)?.to_string();
@@ -642,13 +646,15 @@ pub mod foo {
642 ) 646 )
643 } 647 }
644 648
645 // FIXME: ImportMap will return re-export paths instead of public module
646 // paths. The correct path to documentation will never be a re-export.
647 // This problem stops us from resolving stdlib items included in the prelude
648 // such as `Option::Some` correctly.
649 #[ignore = "ImportMap may return re-exports"]
650 #[test] 649 #[test]
651 fn test_reexport_order() { 650 fn test_reexport_order() {
651 cov_mark::check!(test_reexport_order);
652 // FIXME: This should return
653 //
654 // https://docs.rs/test/*/test/wrapper/modulestruct.Item.html
655 //
656 // That is, we should point inside the module, rather than at the
657 // re-export.
652 check( 658 check(
653 r#" 659 r#"
654pub mod wrapper { 660pub mod wrapper {
@@ -663,7 +669,7 @@ fn foo() {
663 let bar: wrapper::It$0em; 669 let bar: wrapper::It$0em;
664} 670}
665 "#, 671 "#,
666 expect![[r#"https://docs.rs/test/*/test/wrapper/module/struct.Item.html"#]], 672 expect![[r#"https://docs.rs/test/*/test/wrapper/struct.Item.html"#]],
667 ) 673 )
668 } 674 }
669} 675}
diff --git a/crates/ide/src/fixture.rs b/crates/ide/src/fixture.rs
index 38e2e866b..cf679edd3 100644
--- a/crates/ide/src/fixture.rs
+++ b/crates/ide/src/fixture.rs
@@ -12,14 +12,6 @@ pub(crate) fn file(ra_fixture: &str) -> (Analysis, FileId) {
12 (host.analysis(), change_fixture.files[0]) 12 (host.analysis(), change_fixture.files[0])
13} 13}
14 14
15/// Creates analysis for many files.
16pub(crate) fn files(ra_fixture: &str) -> (Analysis, Vec<FileId>) {
17 let mut host = AnalysisHost::default();
18 let change_fixture = ChangeFixture::parse(ra_fixture);
19 host.db.apply_change(change_fixture.change);
20 (host.analysis(), change_fixture.files)
21}
22
23/// Creates analysis from a multi-file fixture, returns positions marked with $0. 15/// Creates analysis from a multi-file fixture, returns positions marked with $0.
24pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) { 16pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) {
25 let mut host = AnalysisHost::default(); 17 let mut host = AnalysisHost::default();
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 8dd643a0f..d8e0dc4d5 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1130,15 +1130,15 @@ fn foo<'foobar>(_: &'foobar ()) {
1130 } 1130 }
1131 1131
1132 #[test] 1132 #[test]
1133 #[ignore] // requires the HIR to somehow track these hrtb lifetimes
1134 fn goto_lifetime_hrtb() { 1133 fn goto_lifetime_hrtb() {
1135 check( 1134 // FIXME: requires the HIR to somehow track these hrtb lifetimes
1135 check_unresolved(
1136 r#"trait Foo<T> {} 1136 r#"trait Foo<T> {}
1137fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {} 1137fn foo<T>() where for<'a> T: Foo<&'a$0 (u8, u16)>, {}
1138 //^^ 1138 //^^
1139"#, 1139"#,
1140 ); 1140 );
1141 check( 1141 check_unresolved(
1142 r#"trait Foo<T> {} 1142 r#"trait Foo<T> {}
1143fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {} 1143fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {}
1144 //^^ 1144 //^^
@@ -1147,9 +1147,9 @@ fn foo<T>() where for<'a$0> T: Foo<&'a (u8, u16)>, {}
1147 } 1147 }
1148 1148
1149 #[test] 1149 #[test]
1150 #[ignore] // requires ForTypes to be implemented
1151 fn goto_lifetime_hrtb_for_type() { 1150 fn goto_lifetime_hrtb_for_type() {
1152 check( 1151 // FIXME: requires ForTypes to be implemented
1152 check_unresolved(
1153 r#"trait Foo<T> {} 1153 r#"trait Foo<T> {}
1154fn foo<T>() where T: for<'a> Foo<&'a$0 (u8, u16)>, {} 1154fn foo<T>() where T: for<'a> Foo<&'a$0 (u8, u16)>, {}
1155 //^^ 1155 //^^
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index 004d9cb68..ca3c02bf6 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -25,7 +25,7 @@ pub(crate) fn goto_type_definition(
25 let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?; 25 let token: SyntaxToken = pick_best(file.syntax().token_at_offset(position.offset))?;
26 let token: SyntaxToken = sema.descend_into_macros(token); 26 let token: SyntaxToken = sema.descend_into_macros(token);
27 27
28 let (ty, node) = sema.token_ancestors_with_macros(token).find_map(|node| { 28 let (ty, node) = sema.token_ancestors_with_macros(token.clone()).find_map(|node| {
29 let ty = match_ast! { 29 let ty = match_ast! {
30 match node { 30 match node {
31 ast::Expr(it) => sema.type_of_expr(&it)?, 31 ast::Expr(it) => sema.type_of_expr(&it)?,
@@ -33,13 +33,23 @@ pub(crate) fn goto_type_definition(
33 ast::SelfParam(it) => sema.type_of_self(&it)?, 33 ast::SelfParam(it) => sema.type_of_self(&it)?,
34 ast::Type(it) => sema.resolve_type(&it)?, 34 ast::Type(it) => sema.resolve_type(&it)?,
35 ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?, 35 ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?,
36 ast::RecordField(it) => sema.to_def(&it).map(|d| d.ty(db.upcast()))?,
37 // can't match on RecordExprField directly as `ast::Expr` will match an iteration too early otherwise
38 ast::NameRef(it) => {
39 if let Some(record_field) = ast::RecordExprField::for_name_ref(&it) {
40 let (_, _, ty) = sema.resolve_record_field(&record_field)?;
41 ty
42 } else {
43 let record_field = ast::RecordPatField::for_field_name_ref(&it)?;
44 sema.resolve_record_pat_field(&record_field)?.ty(db)
45 }
46 },
36 _ => return None, 47 _ => return None,
37 } 48 }
38 }; 49 };
39 50
40 Some((ty, node)) 51 Some((ty, node))
41 })?; 52 })?;
42
43 let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; 53 let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?;
44 54
45 let nav = adt_def.try_to_nav(db)?; 55 let nav = adt_def.try_to_nav(db)?;
@@ -88,6 +98,54 @@ fn foo() {
88 } 98 }
89 99
90 #[test] 100 #[test]
101 fn goto_type_definition_record_expr_field() {
102 check(
103 r#"
104struct Bar;
105 // ^^^
106struct Foo { foo: Bar }
107fn foo() {
108 Foo { foo$0 }
109}
110"#,
111 );
112 check(
113 r#"
114struct Bar;
115 // ^^^
116struct Foo { foo: Bar }
117fn foo() {
118 Foo { foo$0: Bar }
119}
120"#,
121 );
122 }
123
124 #[test]
125 fn goto_type_definition_record_pat_field() {
126 check(
127 r#"
128struct Bar;
129 // ^^^
130struct Foo { foo: Bar }
131fn foo() {
132 let Foo { foo$0 };
133}
134"#,
135 );
136 check(
137 r#"
138struct Bar;
139 // ^^^
140struct Foo { foo: Bar }
141fn foo() {
142 let Foo { foo$0: bar };
143}
144"#,
145 );
146 }
147
148 #[test]
91 fn goto_type_definition_works_simple_ref() { 149 fn goto_type_definition_works_simple_ref() {
92 check( 150 check(
93 r#" 151 r#"
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index c08516805..14cf94d60 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -1821,9 +1821,10 @@ pub struct B$0ar
1821 ); 1821 );
1822 } 1822 }
1823 1823
1824 #[ignore = "path based links currently only support documentation on ModuleDef items"]
1825 #[test] 1824 #[test]
1826 fn test_hover_path_link_field() { 1825 fn test_hover_path_link_field() {
1826 // FIXME: Should be
1827 // [Foo](https://docs.rs/test/*/test/struct.Foo.html)
1827 check( 1828 check(
1828 r#" 1829 r#"
1829pub struct Foo; 1830pub struct Foo;
@@ -1845,7 +1846,7 @@ pub struct Bar {
1845 1846
1846 --- 1847 ---
1847 1848
1848 [Foo](https://docs.rs/test/*/test/struct.Foo.html) 1849 [Foo](struct.Foo.html)
1849 "#]], 1850 "#]],
1850 ); 1851 );
1851 } 1852 }
@@ -2999,29 +3000,24 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
2999 fn test_hover_async_block_impl_trait_has_goto_type_action() { 3000 fn test_hover_async_block_impl_trait_has_goto_type_action() {
3000 check_actions( 3001 check_actions(
3001 r#" 3002 r#"
3003//- minicore: future
3002struct S; 3004struct S;
3003fn foo() { 3005fn foo() {
3004 let fo$0o = async { S }; 3006 let fo$0o = async { S };
3005} 3007}
3006
3007#[prelude_import] use future::*;
3008mod future {
3009 #[lang = "future_trait"]
3010 pub trait Future { type Output; }
3011}
3012"#, 3008"#,
3013 expect![[r#" 3009 expect![[r#"
3014 [ 3010 [
3015 GoToType( 3011 GoToType(
3016 [ 3012 [
3017 HoverGotoTypeData { 3013 HoverGotoTypeData {
3018 mod_path: "test::future::Future", 3014 mod_path: "core::future::Future",
3019 nav: NavigationTarget { 3015 nav: NavigationTarget {
3020 file_id: FileId( 3016 file_id: FileId(
3021 0, 3017 1,
3022 ), 3018 ),
3023 full_range: 101..163, 3019 full_range: 244..426,
3024 focus_range: 140..146, 3020 focus_range: 283..289,
3025 name: "Future", 3021 name: "Future",
3026 kind: Trait, 3022 kind: Trait,
3027 description: "pub trait Future", 3023 description: "pub trait Future",
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 0511efae3..4bd073cc3 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -24,7 +24,6 @@ mod display;
24 24
25mod annotations; 25mod annotations;
26mod call_hierarchy; 26mod call_hierarchy;
27mod diagnostics;
28mod expand_macro; 27mod expand_macro;
29mod extend_selection; 28mod extend_selection;
30mod file_structure; 29mod file_structure;
@@ -40,6 +39,7 @@ mod matching_brace;
40mod move_item; 39mod move_item;
41mod parent_module; 40mod parent_module;
42mod references; 41mod references;
42mod rename;
43mod fn_references; 43mod fn_references;
44mod runnables; 44mod runnables;
45mod ssr; 45mod ssr;
@@ -71,7 +71,6 @@ use crate::display::ToNav;
71pub use crate::{ 71pub use crate::{
72 annotations::{Annotation, AnnotationConfig, AnnotationKind}, 72 annotations::{Annotation, AnnotationConfig, AnnotationKind},
73 call_hierarchy::CallItem, 73 call_hierarchy::CallItem,
74 diagnostics::{Diagnostic, DiagnosticsConfig, Severity},
75 display::navigation_target::NavigationTarget, 74 display::navigation_target::NavigationTarget,
76 expand_macro::ExpandedMacro, 75 expand_macro::ExpandedMacro,
77 file_structure::{StructureNode, StructureNodeKind}, 76 file_structure::{StructureNode, StructureNodeKind},
@@ -81,7 +80,8 @@ pub use crate::{
81 markup::Markup, 80 markup::Markup,
82 move_item::Direction, 81 move_item::Direction,
83 prime_caches::PrimeCachesProgress, 82 prime_caches::PrimeCachesProgress,
84 references::{rename::RenameError, ReferenceSearchResult}, 83 references::ReferenceSearchResult,
84 rename::RenameError,
85 runnables::{Runnable, RunnableKind, TestId}, 85 runnables::{Runnable, RunnableKind, TestId},
86 syntax_highlighting::{ 86 syntax_highlighting::{
87 tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag}, 87 tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag},
@@ -109,6 +109,7 @@ pub use ide_db::{
109 symbol_index::Query, 109 symbol_index::Query,
110 RootDatabase, SymbolKind, 110 RootDatabase, SymbolKind,
111}; 111};
112pub use ide_diagnostics::{Diagnostic, DiagnosticsConfig, Severity};
112pub use ide_ssr::SsrError; 113pub use ide_ssr::SsrError;
113pub use syntax::{TextRange, TextSize}; 114pub use syntax::{TextRange, TextSize};
114pub use text_edit::{Indel, TextEdit}; 115pub use text_edit::{Indel, TextEdit};
@@ -536,7 +537,7 @@ impl Analysis {
536 ) -> Cancellable<Vec<Assist>> { 537 ) -> Cancellable<Vec<Assist>> {
537 self.with_db(|db| { 538 self.with_db(|db| {
538 let ssr_assists = ssr::ssr_assists(db, &resolve, frange); 539 let ssr_assists = ssr::ssr_assists(db, &resolve, frange);
539 let mut acc = Assist::get(db, config, resolve, frange); 540 let mut acc = ide_assists::assists(db, config, resolve, frange);
540 acc.extend(ssr_assists.into_iter()); 541 acc.extend(ssr_assists.into_iter());
541 acc 542 acc
542 }) 543 })
@@ -549,7 +550,7 @@ impl Analysis {
549 resolve: AssistResolveStrategy, 550 resolve: AssistResolveStrategy,
550 file_id: FileId, 551 file_id: FileId,
551 ) -> Cancellable<Vec<Diagnostic>> { 552 ) -> Cancellable<Vec<Diagnostic>> {
552 self.with_db(|db| diagnostics::diagnostics(db, config, &resolve, file_id)) 553 self.with_db(|db| ide_diagnostics::diagnost