diff options
69 files changed, 2067 insertions, 2243 deletions
diff --git a/Cargo.lock b/Cargo.lock index 5066d5f0f..238c21f52 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -37,9 +37,9 @@ dependencies = [ | |||
37 | 37 | ||
38 | [[package]] | 38 | [[package]] |
39 | name = "anyhow" | 39 | name = "anyhow" |
40 | version = "1.0.40" | 40 | version = "1.0.41" |
41 | source = "registry+https://github.com/rust-lang/crates.io-index" | 41 | source = "registry+https://github.com/rust-lang/crates.io-index" |
42 | checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" | 42 | checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61" |
43 | 43 | ||
44 | [[package]] | 44 | [[package]] |
45 | name = "anymap" | 45 | name = "anymap" |
@@ -49,9 +49,9 @@ checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" | |||
49 | 49 | ||
50 | [[package]] | 50 | [[package]] |
51 | name = "arrayvec" | 51 | name = "arrayvec" |
52 | version = "0.7.0" | 52 | version = "0.7.1" |
53 | source = "registry+https://github.com/rust-lang/crates.io-index" | 53 | source = "registry+https://github.com/rust-lang/crates.io-index" |
54 | checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7" | 54 | checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" |
55 | 55 | ||
56 | [[package]] | 56 | [[package]] |
57 | name = "atty" | 57 | name = "atty" |
@@ -333,9 +333,9 @@ dependencies = [ | |||
333 | 333 | ||
334 | [[package]] | 334 | [[package]] |
335 | name = "env_logger" | 335 | name = "env_logger" |
336 | version = "0.8.3" | 336 | version = "0.8.4" |
337 | source = "registry+https://github.com/rust-lang/crates.io-index" | 337 | source = "registry+https://github.com/rust-lang/crates.io-index" |
338 | checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" | 338 | checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" |
339 | dependencies = [ | 339 | dependencies = [ |
340 | "log", | 340 | "log", |
341 | ] | 341 | ] |
@@ -421,9 +421,9 @@ dependencies = [ | |||
421 | 421 | ||
422 | [[package]] | 422 | [[package]] |
423 | name = "fst" | 423 | name = "fst" |
424 | version = "0.4.6" | 424 | version = "0.4.7" |
425 | source = "registry+https://github.com/rust-lang/crates.io-index" | 425 | source = "registry+https://github.com/rust-lang/crates.io-index" |
426 | checksum = "e398fae362f4124bbe630d99519fb2d68a03e2e3a23b441028cdcdc4f4895687" | 426 | checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" |
427 | 427 | ||
428 | [[package]] | 428 | [[package]] |
429 | name = "gimli" | 429 | name = "gimli" |
@@ -741,9 +741,9 @@ dependencies = [ | |||
741 | 741 | ||
742 | [[package]] | 742 | [[package]] |
743 | name = "itertools" | 743 | name = "itertools" |
744 | version = "0.10.0" | 744 | version = "0.10.1" |
745 | source = "registry+https://github.com/rust-lang/crates.io-index" | 745 | source = "registry+https://github.com/rust-lang/crates.io-index" |
746 | checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" | 746 | checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" |
747 | dependencies = [ | 747 | dependencies = [ |
748 | "either", | 748 | "either", |
749 | ] | 749 | ] |
@@ -788,9 +788,9 @@ dependencies = [ | |||
788 | 788 | ||
789 | [[package]] | 789 | [[package]] |
790 | name = "libmimalloc-sys" | 790 | name = "libmimalloc-sys" |
791 | version = "0.1.21" | 791 | version = "0.1.22" |
792 | source = "registry+https://github.com/rust-lang/crates.io-index" | 792 | source = "registry+https://github.com/rust-lang/crates.io-index" |
793 | checksum = "2396cf99d2f58611cd69f0efeee4af3d2e2c7b61bed433515029163aa567e65c" | 793 | checksum = "1d1b8479c593dba88c2741fc50b92e13dbabbbe0bd504d979f244ccc1a5b1c01" |
794 | dependencies = [ | 794 | dependencies = [ |
795 | "cc", | 795 | "cc", |
796 | ] | 796 | ] |
@@ -827,9 +827,9 @@ dependencies = [ | |||
827 | 827 | ||
828 | [[package]] | 828 | [[package]] |
829 | name = "lsp-types" | 829 | name = "lsp-types" |
830 | version = "0.89.1" | 830 | version = "0.89.2" |
831 | source = "registry+https://github.com/rust-lang/crates.io-index" | 831 | source = "registry+https://github.com/rust-lang/crates.io-index" |
832 | checksum = "48b8a871b0a450bcec0e26d74a59583c8173cb9fb7d7f98889e18abb84838e0f" | 832 | checksum = "852e0dedfd52cc32325598b2631e0eba31b7b708959676a9f837042f276b09a2" |
833 | dependencies = [ | 833 | dependencies = [ |
834 | "bitflags", | 834 | "bitflags", |
835 | "serde", | 835 | "serde", |
@@ -895,9 +895,9 @@ dependencies = [ | |||
895 | 895 | ||
896 | [[package]] | 896 | [[package]] |
897 | name = "mimalloc" | 897 | name = "mimalloc" |
898 | version = "0.1.25" | 898 | version = "0.1.26" |
899 | source = "registry+https://github.com/rust-lang/crates.io-index" | 899 | source = "registry+https://github.com/rust-lang/crates.io-index" |
900 | checksum = "1e7c6b11afd1e5e689ac96b6d18b1fc763398fe3d7eed99e8773426bc2033dfb" | 900 | checksum = "fb74897ce508e6c49156fd1476fc5922cbc6e75183c65e399c765a09122e5130" |
901 | dependencies = [ | 901 | dependencies = [ |
902 | "libmimalloc-sys", | 902 | "libmimalloc-sys", |
903 | ] | 903 | ] |
@@ -978,9 +978,9 @@ checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" | |||
978 | 978 | ||
979 | [[package]] | 979 | [[package]] |
980 | name = "once_cell" | 980 | name = "once_cell" |
981 | version = "1.7.2" | 981 | version = "1.8.0" |
982 | source = "registry+https://github.com/rust-lang/crates.io-index" | 982 | source = "registry+https://github.com/rust-lang/crates.io-index" |
983 | checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" | 983 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" |
984 | 984 | ||
985 | [[package]] | 985 | [[package]] |
986 | name = "oorandom" | 986 | name = "oorandom" |
@@ -1204,9 +1204,9 @@ dependencies = [ | |||
1204 | 1204 | ||
1205 | [[package]] | 1205 | [[package]] |
1206 | name = "pulldown-cmark-to-cmark" | 1206 | name = "pulldown-cmark-to-cmark" |
1207 | version = "6.0.0" | 1207 | version = "6.0.1" |
1208 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1209 | checksum = "e8f2b9878102358ec65434fdd1a9a161f8648bb2f531acc9260e4d094c96de23" | 1209 | checksum = "6a95f396125c68d833fc40cca35532c49ab7394382f7b0e46144a4761896ce80" |
1210 | dependencies = [ | 1210 | dependencies = [ |
1211 | "pulldown-cmark", | 1211 | "pulldown-cmark", |
1212 | ] | 1212 | ] |
@@ -1909,18 +1909,18 @@ checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" | |||
1909 | 1909 | ||
1910 | [[package]] | 1910 | [[package]] |
1911 | name = "xflags" | 1911 | name = "xflags" |
1912 | version = "0.2.1" | 1912 | version = "0.2.2" |
1913 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1913 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1914 | checksum = "59ad6ce6a0b7224130015b4ebac796478ac04e0079f5d222a690efea06a9208a" | 1914 | checksum = "a25b85ca0fcf2d003f2b0cfdce73897c54ec3d793dfe008a64de5040209363c9" |
1915 | dependencies = [ | 1915 | dependencies = [ |
1916 | "xflags-macros", | 1916 | "xflags-macros", |
1917 | ] | 1917 | ] |
1918 | 1918 | ||
1919 | [[package]] | 1919 | [[package]] |
1920 | name = "xflags-macros" | 1920 | name = "xflags-macros" |
1921 | version = "0.2.1" | 1921 | version = "0.2.2" |
1922 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1922 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1923 | checksum = "c8037d3ca14996158b03c0fa905d0834906ef0fc7044df72c1f5ff690e5e62c9" | 1923 | checksum = "00055208d8839f11689012fecb42bbc024e25bf3af91b3b9879739d3cda65bf0" |
1924 | dependencies = [ | 1924 | dependencies = [ |
1925 | "proc-macro2", | 1925 | "proc-macro2", |
1926 | ] | 1926 | ] |
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index d0c946d83..7d5d12e63 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs | |||
@@ -106,7 +106,7 @@ impl ChangeFixture { | |||
106 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); | 106 | let (range_or_offset, text) = extract_range_or_offset(&entry.text); |
107 | assert!(file_position.is_none()); | 107 | assert!(file_position.is_none()); |
108 | file_position = Some((file_id, range_or_offset)); | 108 | file_position = Some((file_id, range_or_offset)); |
109 | text.to_string() | 109 | text |
110 | } | 110 | } |
111 | } else { | 111 | } else { |
112 | entry.text.clone() | 112 | entry.text.clone() |
@@ -128,6 +128,7 @@ impl ChangeFixture { | |||
128 | file_id, | 128 | file_id, |
129 | meta.edition, | 129 | meta.edition, |
130 | Some(crate_name.clone().into()), | 130 | Some(crate_name.clone().into()), |
131 | meta.cfg.clone(), | ||
131 | meta.cfg, | 132 | meta.cfg, |
132 | meta.env, | 133 | meta.env, |
133 | Default::default(), | 134 | Default::default(), |
@@ -157,6 +158,7 @@ impl ChangeFixture { | |||
157 | crate_root, | 158 | crate_root, |
158 | Edition::Edition2018, | 159 | Edition::Edition2018, |
159 | Some(CrateName::new("test").unwrap().into()), | 160 | Some(CrateName::new("test").unwrap().into()), |
161 | default_cfg.clone(), | ||
160 | default_cfg, | 162 | default_cfg, |
161 | Env::default(), | 163 | Env::default(), |
162 | Default::default(), | 164 | Default::default(), |
@@ -186,6 +188,7 @@ impl ChangeFixture { | |||
186 | Edition::Edition2021, | 188 | Edition::Edition2021, |
187 | Some(CrateDisplayName::from_canonical_name("core".to_string())), | 189 | Some(CrateDisplayName::from_canonical_name("core".to_string())), |
188 | CfgOptions::default(), | 190 | CfgOptions::default(), |
191 | CfgOptions::default(), | ||
189 | Env::default(), | 192 | Env::default(), |
190 | Vec::new(), | 193 | Vec::new(), |
191 | ); | 194 | ); |
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs index 23cb0c839..0c51a59a0 100644 --- a/crates/base_db/src/input.rs +++ b/crates/base_db/src/input.rs | |||
@@ -189,6 +189,7 @@ pub struct CrateData { | |||
189 | /// `Dependency` matters), this name should only be used for UI. | 189 | /// `Dependency` matters), this name should only be used for UI. |
190 | pub display_name: Option<CrateDisplayName>, | 190 | pub display_name: Option<CrateDisplayName>, |
191 | pub cfg_options: CfgOptions, | 191 | pub cfg_options: CfgOptions, |
192 | pub potential_cfg_options: CfgOptions, | ||
192 | pub env: Env, | 193 | pub env: Env, |
193 | pub dependencies: Vec<Dependency>, | 194 | pub dependencies: Vec<Dependency>, |
194 | pub proc_macro: Vec<ProcMacro>, | 195 | pub proc_macro: Vec<ProcMacro>, |
@@ -219,6 +220,7 @@ impl CrateGraph { | |||
219 | edition: Edition, | 220 | edition: Edition, |
220 | display_name: Option<CrateDisplayName>, | 221 | display_name: Option<CrateDisplayName>, |
221 | cfg_options: CfgOptions, | 222 | cfg_options: CfgOptions, |
223 | potential_cfg_options: CfgOptions, | ||
222 | env: Env, | 224 | env: Env, |
223 | proc_macro: Vec<ProcMacro>, | 225 | proc_macro: Vec<ProcMacro>, |
224 | ) -> CrateId { | 226 | ) -> CrateId { |
@@ -227,6 +229,7 @@ impl CrateGraph { | |||
227 | edition, | 229 | edition, |
228 | display_name, | 230 | display_name, |
229 | cfg_options, | 231 | cfg_options, |
232 | potential_cfg_options, | ||
230 | env, | 233 | env, |
231 | proc_macro, | 234 | proc_macro, |
232 | dependencies: Vec::new(), | 235 | dependencies: Vec::new(), |
@@ -504,6 +507,7 @@ mod tests { | |||
504 | Edition2018, | 507 | Edition2018, |
505 | None, | 508 | None, |
506 | CfgOptions::default(), | 509 | CfgOptions::default(), |
510 | CfgOptions::default(), | ||
507 | Env::default(), | 511 | Env::default(), |
508 | Default::default(), | 512 | Default::default(), |
509 | ); | 513 | ); |
@@ -512,6 +516,7 @@ mod tests { | |||
512 | Edition2018, | 516 | Edition2018, |
513 | None, | 517 | None, |
514 | CfgOptions::default(), | 518 | CfgOptions::default(), |
519 | CfgOptions::default(), | ||
515 | Env::default(), | 520 | Env::default(), |
516 | Default::default(), | 521 | Default::default(), |
517 | ); | 522 | ); |
@@ -520,6 +525,7 @@ mod tests { | |||
520 | Edition2018, | 525 | Edition2018, |
521 | None, | 526 | None, |
522 | CfgOptions::default(), | 527 | CfgOptions::default(), |
528 | CfgOptions::default(), | ||
523 | Env::default(), | 529 | Env::default(), |
524 | Default::default(), | 530 | Default::default(), |
525 | ); | 531 | ); |
@@ -536,6 +542,7 @@ mod tests { | |||
536 | Edition2018, | 542 | Edition2018, |
537 | None, | 543 | None, |
538 | CfgOptions::default(), | 544 | CfgOptions::default(), |
545 | CfgOptions::default(), | ||
539 | Env::default(), | 546 | Env::default(), |
540 | Default::default(), | 547 | Default::default(), |
541 | ); | 548 | ); |
@@ -544,6 +551,7 @@ mod tests { | |||
544 | Edition2018, | 551 | Edition2018, |
545 | None, | 552 | None, |
546 | CfgOptions::default(), | 553 | CfgOptions::default(), |
554 | CfgOptions::default(), | ||
547 | Env::default(), | 555 | Env::default(), |
548 | Default::default(), | 556 | Default::default(), |
549 | ); | 557 | ); |
@@ -559,6 +567,7 @@ mod tests { | |||
559 | Edition2018, | 567 | Edition2018, |
560 | None, | 568 | None, |
561 | CfgOptions::default(), | 569 | CfgOptions::default(), |
570 | CfgOptions::default(), | ||
562 | Env::default(), | 571 | Env::default(), |
563 | Default::default(), | 572 | Default::default(), |
564 | ); | 573 | ); |
@@ -567,6 +576,7 @@ mod tests { | |||
567 | Edition2018, | 576 | Edition2018, |
568 | None, | 577 | None, |
569 | CfgOptions::default(), | 578 | CfgOptions::default(), |
579 | CfgOptions::default(), | ||
570 | Env::default(), | 580 | Env::default(), |
571 | Default::default(), | 581 | Default::default(), |
572 | ); | 582 | ); |
@@ -575,6 +585,7 @@ mod tests { | |||
575 | Edition2018, | 585 | Edition2018, |
576 | None, | 586 | None, |
577 | CfgOptions::default(), | 587 | CfgOptions::default(), |
588 | CfgOptions::default(), | ||
578 | Env::default(), | 589 | Env::default(), |
579 | Default::default(), | 590 | Default::default(), |
580 | ); | 591 | ); |
@@ -590,6 +601,7 @@ mod tests { | |||
590 | Edition2018, | 601 | Edition2018, |
591 | None, | 602 | None, |
592 | CfgOptions::default(), | 603 | CfgOptions::default(), |
604 | CfgOptions::default(), | ||
593 | Env::default(), | 605 | Env::default(), |
594 | Default::default(), | 606 | Default::default(), |
595 | ); | 607 | ); |
@@ -598,6 +610,7 @@ mod tests { | |||
598 | Edition2018, | 610 | Edition2018, |
599 | None, | 611 | None, |
600 | CfgOptions::default(), | 612 | CfgOptions::default(), |
613 | CfgOptions::default(), | ||
601 | Env::default(), | 614 | Env::default(), |
602 | Default::default(), | 615 | Default::default(), |
603 | ); | 616 | ); |
diff --git a/crates/cfg/src/lib.rs b/crates/cfg/src/lib.rs index 03b8dd767..9a4baa636 100644 --- a/crates/cfg/src/lib.rs +++ b/crates/cfg/src/lib.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! cfg defines conditional compiling options, `cfg` attibute parser and evaluator | 1 | //! cfg defines conditional compiling options, `cfg` attribute parser and evaluator |
2 | 2 | ||
3 | mod cfg_expr; | 3 | mod cfg_expr; |
4 | mod dnf; | 4 | mod dnf; |
@@ -50,8 +50,29 @@ impl CfgOptions { | |||
50 | self.enabled.remove(&atom); | 50 | self.enabled.remove(&atom); |
51 | } | 51 | } |
52 | } | 52 | } |
53 | |||
54 | pub fn get_cfg_keys(&self) -> Vec<&SmolStr> { | ||
55 | self.enabled | ||
56 | .iter() | ||
57 | .map(|x| match x { | ||
58 | CfgAtom::Flag(key) => key, | ||
59 | CfgAtom::KeyValue { key, .. } => key, | ||
60 | }) | ||
61 | .collect() | ||
62 | } | ||
63 | |||
64 | pub fn get_cfg_values(&self, cfg_key: &str) -> Vec<&SmolStr> { | ||
65 | self.enabled | ||
66 | .iter() | ||
67 | .filter_map(|x| match x { | ||
68 | CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value), | ||
69 | _ => None, | ||
70 | }) | ||
71 | .collect() | ||
72 | } | ||
53 | } | 73 | } |
54 | 74 | ||
75 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
55 | pub struct CfgDiff { | 76 | pub struct CfgDiff { |
56 | // Invariants: No duplicates, no atom that's both in `enable` and `disable`. | 77 | // Invariants: No duplicates, no atom that's both in `enable` and `disable`. |
57 | enable: Vec<CfgAtom>, | 78 | enable: Vec<CfgAtom>, |
@@ -59,6 +80,20 @@ pub struct CfgDiff { | |||
59 | } | 80 | } |
60 | 81 | ||
61 | impl CfgDiff { | 82 | impl CfgDiff { |
83 | /// Create a new CfgDiff. Will return None if the same item appears more than once in the set | ||
84 | /// of both. | ||
85 | pub fn new(enable: Vec<CfgAtom>, disable: Vec<CfgAtom>) -> Option<CfgDiff> { | ||
86 | let mut occupied = FxHashSet::default(); | ||
87 | for item in enable.iter().chain(disable.iter()) { | ||
88 | if !occupied.insert(item) { | ||
89 | // was present | ||
90 | return None; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | Some(CfgDiff { enable, disable }) | ||
95 | } | ||
96 | |||
62 | /// Returns the total number of atoms changed by this diff. | 97 | /// Returns the total number of atoms changed by this diff. |
63 | pub fn len(&self) -> usize { | 98 | pub fn len(&self) -> usize { |
64 | self.enable.len() + self.disable.len() | 99 | self.enable.len() + self.disable.len() |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b7eabaabb..30cc34403 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -219,8 +219,7 @@ impl Crate { | |||
219 | let doc_url = doc_attr_q.tt_values().map(|tt| { | 219 | let doc_url = doc_attr_q.tt_values().map(|tt| { |
220 | let name = tt.token_trees.iter() | 220 | let name = tt.token_trees.iter() |
221 | .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url")) | 221 | .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url")) |
222 | .skip(2) | 222 | .nth(2); |
223 | .next(); | ||
224 | 223 | ||
225 | match name { | 224 | match name { |
226 | Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text), | 225 | Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text), |
@@ -234,6 +233,10 @@ impl Crate { | |||
234 | pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions { | 233 | pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions { |
235 | db.crate_graph()[self.id].cfg_options.clone() | 234 | db.crate_graph()[self.id].cfg_options.clone() |
236 | } | 235 | } |
236 | |||
237 | pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions { | ||
238 | db.crate_graph()[self.id].potential_cfg_options.clone() | ||
239 | } | ||
237 | } | 240 | } |
238 | 241 | ||
239 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 242 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -1846,7 +1849,7 @@ impl TypeParam { | |||
1846 | 1849 | ||
1847 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { | 1850 | pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> { |
1848 | db.generic_predicates_for_param(self.id) | 1851 | db.generic_predicates_for_param(self.id) |
1849 | .into_iter() | 1852 | .iter() |
1850 | .filter_map(|pred| match &pred.skip_binders().skip_binders() { | 1853 | .filter_map(|pred| match &pred.skip_binders().skip_binders() { |
1851 | hir_ty::WhereClause::Implemented(trait_ref) => { | 1854 | hir_ty::WhereClause::Implemented(trait_ref) => { |
1852 | Some(Trait::from(trait_ref.hir_trait_id())) | 1855 | Some(Trait::from(trait_ref.hir_trait_id())) |
@@ -1951,7 +1954,7 @@ impl Impl { | |||
1951 | all.extend( | 1954 | all.extend( |
1952 | db.inherent_impls_in_crate(id) | 1955 | db.inherent_impls_in_crate(id) |
1953 | .for_self_ty(&ty) | 1956 | .for_self_ty(&ty) |
1954 | .into_iter() | 1957 | .iter() |
1955 | .cloned() | 1958 | .cloned() |
1956 | .map(Self::from) | 1959 | .map(Self::from) |
1957 | .filter(filter), | 1960 | .filter(filter), |
@@ -2232,8 +2235,8 @@ impl Type { | |||
2232 | } | 2235 | } |
2233 | 2236 | ||
2234 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 2237 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
2235 | let adt_id = match self.ty.kind(&Interner) { | 2238 | let adt_id = match *self.ty.kind(&Interner) { |
2236 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, | 2239 | TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, |
2237 | _ => return false, | 2240 | _ => return false, |
2238 | }; | 2241 | }; |
2239 | 2242 | ||
@@ -2287,9 +2290,9 @@ impl Type { | |||
2287 | } | 2290 | } |
2288 | 2291 | ||
2289 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 2292 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
2290 | let (variant_id, substs) = match self.ty.kind(&Interner) { | 2293 | let (variant_id, substs) = match *self.ty.kind(&Interner) { |
2291 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), | 2294 | TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), |
2292 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), | 2295 | TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), |
2293 | _ => return Vec::new(), | 2296 | _ => return Vec::new(), |
2294 | }; | 2297 | }; |
2295 | 2298 | ||
@@ -2488,20 +2491,17 @@ impl Type { | |||
2488 | cb: &mut impl FnMut(Type), | 2491 | cb: &mut impl FnMut(Type), |
2489 | ) { | 2492 | ) { |
2490 | for pred in bounds { | 2493 | for pred in bounds { |
2491 | match pred.skip_binders() { | 2494 | if let WhereClause::Implemented(trait_ref) = pred.skip_binders() { |
2492 | WhereClause::Implemented(trait_ref) => { | 2495 | cb(type_.clone()); |
2493 | cb(type_.clone()); | 2496 | // skip the self type. it's likely the type we just got the bounds from |
2494 | // skip the self type. it's likely the type we just got the bounds from | 2497 | for ty in trait_ref |
2495 | for ty in trait_ref | 2498 | .substitution |
2496 | .substitution | 2499 | .iter(&Interner) |
2497 | .iter(&Interner) | 2500 | .skip(1) |
2498 | .skip(1) | 2501 | .filter_map(|a| a.ty(&Interner)) |
2499 | .filter_map(|a| a.ty(&Interner)) | 2502 | { |
2500 | { | 2503 | walk_type(db, &type_.derived(ty.clone()), cb); |
2501 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
2502 | } | ||
2503 | } | 2504 | } |
2504 | _ => (), | ||
2505 | } | 2505 | } |
2506 | } | 2506 | } |
2507 | } | 2507 | } |
@@ -2514,7 +2514,7 @@ impl Type { | |||
2514 | walk_substs(db, type_, substs, cb); | 2514 | walk_substs(db, type_, substs, cb); |
2515 | } | 2515 | } |
2516 | TyKind::AssociatedType(_, substs) => { | 2516 | TyKind::AssociatedType(_, substs) => { |
2517 | if let Some(_) = ty.associated_type_parent_trait(db) { | 2517 | if ty.associated_type_parent_trait(db).is_some() { |
2518 | cb(type_.derived(ty.clone())); | 2518 | cb(type_.derived(ty.clone())); |
2519 | } | 2519 | } |
2520 | walk_substs(db, type_, substs, cb); | 2520 | walk_substs(db, type_, substs, cb); |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index bed4c4994..f6e6cdbe2 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -690,9 +690,7 @@ impl ExprCollector<'_> { | |||
690 | } | 690 | } |
691 | } | 691 | } |
692 | ast::Stmt::Item(item) => { | 692 | ast::Stmt::Item(item) => { |
693 | if self.check_cfg(&item).is_none() { | 693 | self.check_cfg(&item); |
694 | return; | ||
695 | } | ||
696 | } | 694 | } |
697 | } | 695 | } |
698 | } | 696 | } |
@@ -717,7 +715,8 @@ impl ExprCollector<'_> { | |||
717 | block.statements().for_each(|s| self.collect_stmt(s)); | 715 | block.statements().for_each(|s| self.collect_stmt(s)); |
718 | block.tail_expr().and_then(|e| { | 716 | block.tail_expr().and_then(|e| { |
719 | let expr = self.maybe_collect_expr(e)?; | 717 | let expr = self.maybe_collect_expr(e)?; |
720 | Some(self.statements_in_scope.push(Statement::Expr { expr, has_semi: false })) | 718 | self.statements_in_scope.push(Statement::Expr { expr, has_semi: false }); |
719 | Some(()) | ||
721 | }); | 720 | }); |
722 | 721 | ||
723 | let mut tail = None; | 722 | let mut tail = None; |
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index 27d837d47..673a75386 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -15,12 +15,9 @@ fn lower(ra_fixture: &str) -> Arc<Body> { | |||
15 | let mut fn_def = None; | 15 | let mut fn_def = None; |
16 | 'outer: for (_, module) in def_map.modules() { | 16 | 'outer: for (_, module) in def_map.modules() { |
17 | for decl in module.scope.declarations() { | 17 | for decl in module.scope.declarations() { |
18 | match decl { | 18 | if let ModuleDefId::FunctionId(it) = decl { |
19 | ModuleDefId::FunctionId(it) => { | 19 | fn_def = Some(it); |
20 | fn_def = Some(it); | 20 | break 'outer; |
21 | break 'outer; | ||
22 | } | ||
23 | _ => {} | ||
24 | } | 21 | } |
25 | } | 22 | } |
26 | } | 23 | } |
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 0f04b2bae..096ac7968 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -104,7 +104,7 @@ impl GenericParams { | |||
104 | ) -> Interned<GenericParams> { | 104 | ) -> Interned<GenericParams> { |
105 | let _p = profile::span("generic_params_query"); | 105 | let _p = profile::span("generic_params_query"); |
106 | 106 | ||
107 | let generics = match def { | 107 | match def { |
108 | GenericDefId::FunctionId(id) => { | 108 | GenericDefId::FunctionId(id) => { |
109 | let id = id.lookup(db).id; | 109 | let id = id.lookup(db).id; |
110 | let tree = id.item_tree(db); | 110 | let tree = id.item_tree(db); |
@@ -150,8 +150,7 @@ impl GenericParams { | |||
150 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { | 150 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { |
151 | Interned::new(GenericParams::default()) | 151 | Interned::new(GenericParams::default()) |
152 | } | 152 | } |
153 | }; | 153 | } |
154 | generics | ||
155 | } | 154 | } |
156 | 155 | ||
157 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { | 156 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 08407ebfa..567ae5660 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -241,10 +241,8 @@ impl ItemScope { | |||
241 | check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type); | 241 | check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type); |
242 | check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type); | 242 | check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type); |
243 | 243 | ||
244 | if def.is_none() { | 244 | if def.is_none() && self.unresolved.insert(lookup.1) { |
245 | if self.unresolved.insert(lookup.1) { | 245 | changed = true; |
246 | changed = true; | ||
247 | } | ||
248 | } | 246 | } |
249 | 247 | ||
250 | changed | 248 | changed |
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index e63bc8232..8b12e5a67 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs | |||
@@ -30,16 +30,16 @@ pub(super) fn print_item_tree(tree: &ItemTree) -> String { | |||
30 | 30 | ||
31 | macro_rules! w { | 31 | macro_rules! w { |
32 | ($dst:expr, $($arg:tt)*) => { | 32 | ($dst:expr, $($arg:tt)*) => { |
33 | drop(write!($dst, $($arg)*)) | 33 | { let _ = write!($dst, $($arg)*); } |
34 | }; | 34 | }; |
35 | } | 35 | } |
36 | 36 | ||
37 | macro_rules! wln { | 37 | macro_rules! wln { |
38 | ($dst:expr) => { | 38 | ($dst:expr) => { |
39 | drop(writeln!($dst)) | 39 | { let _ = writeln!($dst); } |
40 | }; | 40 | }; |
41 | ($dst:expr, $($arg:tt)*) => { | 41 | ($dst:expr, $($arg:tt)*) => { |
42 | drop(writeln!($dst, $($arg)*)) | 42 | { let _ = writeln!($dst, $($arg)*); } |
43 | }; | 43 | }; |
44 | } | 44 | } |
45 | 45 | ||
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index ebfcc26c4..9e6aa9607 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -367,10 +367,7 @@ impl DefMap { | |||
367 | pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> { | 367 | pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> { |
368 | match &self[local_mod].parent { | 368 | match &self[local_mod].parent { |
369 | Some(parent) => Some(self.module_id(*parent)), | 369 | Some(parent) => Some(self.module_id(*parent)), |
370 | None => match &self.block { | 370 | None => self.block.as_ref().map(|block| block.parent), |
371 | Some(block) => Some(block.parent), | ||
372 | None => None, | ||
373 | }, | ||
374 | } | 371 | } |
375 | } | 372 | } |
376 | 373 | ||
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index 629bc7952..229f57d77 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -55,7 +55,7 @@ impl ResolvePathResult { | |||
55 | segment_index: Option<usize>, | 55 | segment_index: Option<usize>, |
56 | krate: Option<CrateId>, | 56 | krate: Option<CrateId>, |
57 | ) -> ResolvePathResult { | 57 | ) -> ResolvePathResult { |
58 | ResolvePathResult { resolved_def, reached_fixedpoint, segment_index, krate } | 58 | ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, krate } |
59 | } | 59 | } |
60 | } | 60 | } |
61 | 61 | ||
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 4cdb5913d..667092cd2 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -209,7 +209,7 @@ impl Path { | |||
209 | 209 | ||
210 | pub fn is_self_type(&self) -> bool { | 210 | pub fn is_self_type(&self) -> bool { |
211 | self.type_anchor.is_none() | 211 | self.type_anchor.is_none() |
212 | && self.generic_args == &[None] | 212 | && self.generic_args == [None] |
213 | && self.mod_path.as_ident() == Some(&name!(Self)) | 213 | && self.mod_path.as_ident() == Some(&name!(Self)) |
214 | } | 214 | } |
215 | } | 215 | } |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index 49c573087..a11439c3b 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -388,9 +388,9 @@ impl Resolver { | |||
388 | self.module_scope().map(|t| t.0.krate()) | 388 | self.module_scope().map(|t| t.0.krate()) |
389 | } | 389 | } |
390 | 390 | ||
391 | pub fn where_predicates_in_scope<'a>( | 391 | pub fn where_predicates_in_scope( |
392 | &'a self, | 392 | &self, |
393 | ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { | 393 | ) -> impl Iterator<Item = &crate::generics::WherePredicate> { |
394 | self.scopes | 394 | self.scopes |
395 | .iter() | 395 | .iter() |
396 | .rev() | 396 | .rev() |
@@ -464,16 +464,16 @@ impl Scope { | |||
464 | &Scope::GenericParams { ref params, def: parent } => { | 464 | &Scope::GenericParams { ref params, def: parent } => { |
465 | for (local_id, param) in params.types.iter() { | 465 | for (local_id, param) in params.types.iter() { |
466 | if let Some(ref name) = param.name { | 466 | if let Some(ref name) = param.name { |
467 | let id = TypeParamId { local_id, parent }; | 467 | let id = TypeParamId { parent, local_id }; |
468 | f(name.clone(), ScopeDef::GenericParam(id.into())) | 468 | f(name.clone(), ScopeDef::GenericParam(id.into())) |
469 | } | 469 | } |
470 | } | 470 | } |
471 | for (local_id, param) in params.consts.iter() { | 471 | for (local_id, param) in params.consts.iter() { |
472 | let id = ConstParamId { local_id, parent }; | 472 | let id = ConstParamId { parent, local_id }; |
473 | f(param.name.clone(), ScopeDef::GenericParam(id.into())) | 473 | f(param.name.clone(), ScopeDef::GenericParam(id.into())) |
474 | } | 474 | } |
475 | for (local_id, param) in params.lifetimes.iter() { | 475 | for (local_id, param) in params.lifetimes.iter() { |
476 | let id = LifetimeParamId { local_id, parent }; | 476 | let id = LifetimeParamId { parent, local_id }; |
477 | f(param.name.clone(), ScopeDef::GenericParam(id.into())) | 477 | f(param.name.clone(), ScopeDef::GenericParam(id.into())) |
478 | } | 478 | } |
479 | } | 479 | } |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 4c83a2efe..f556bc751 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -420,7 +420,7 @@ fn parse_string(tt: &tt::Subtree) -> Result<String, mbe::ExpandError> { | |||
420 | tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(it), | 420 | tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(it), |
421 | _ => None, | 421 | _ => None, |
422 | }) | 422 | }) |
423 | .ok_or_else(|| mbe::ExpandError::ConversionError) | 423 | .ok_or(mbe::ExpandError::ConversionError) |
424 | } | 424 | } |
425 | 425 | ||
426 | fn include_expand( | 426 | fn include_expand( |
@@ -432,9 +432,8 @@ fn include_expand( | |||
432 | let path = parse_string(tt)?; | 432 | let path = parse_string(tt)?; |
433 | let file_id = relative_file(db, arg_id, &path, false)?; | 433 | let file_id = relative_file(db, arg_id, &path, false)?; |
434 | 434 | ||
435 | let subtree = parse_to_token_tree(&db.file_text(file_id)) | 435 | let subtree = |
436 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 436 | parse_to_token_tree(&db.file_text(file_id)).ok_or(mbe::ExpandError::ConversionError)?.0; |
437 | .0; | ||
438 | Ok((subtree, file_id)) | 437 | Ok((subtree, file_id)) |
439 | })(); | 438 | })(); |
440 | 439 | ||
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 584ddcf9f..66601f4df 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -128,7 +128,7 @@ pub fn expand_eager_macro( | |||
128 | }), | 128 | }), |
129 | kind: MacroCallKind::FnLike { ast_id: call_id, fragment: FragmentKind::Expr }, | 129 | kind: MacroCallKind::FnLike { ast_id: call_id, fragment: FragmentKind::Expr }, |
130 | }); | 130 | }); |
131 | let arg_file_id: MacroCallId = arg_id; | 131 | let arg_file_id = arg_id; |
132 | 132 | ||
133 | let parsed_args = | 133 | let parsed_args = |
134 | diagnostic_sink.result(mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr))?.0; | 134 | diagnostic_sink.result(mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr))?.0; |
@@ -177,7 +177,7 @@ fn lazy_expand( | |||
177 | let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value); | 177 | let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value); |
178 | 178 | ||
179 | let fragment = crate::to_fragment_kind(¯o_call.value); | 179 | let fragment = crate::to_fragment_kind(¯o_call.value); |
180 | let id: MacroCallId = def.as_lazy_macro( | 180 | let id = def.as_lazy_macro( |
181 | db, | 181 | db, |
182 | krate, | 182 | krate, |
183 | MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), fragment }, | 183 | MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), fragment }, |
@@ -207,7 +207,7 @@ fn eager_macro_recur( | |||
207 | .option_with(|| macro_resolver(child.path()?), || err("failed to resolve macro"))?; | 207 | .option_with(|| macro_resolver(child.path()?), || err("failed to resolve macro"))?; |
208 | let insert = match def.kind { | 208 | let insert = match def.kind { |
209 | MacroDefKind::BuiltInEager(..) => { | 209 | MacroDefKind::BuiltInEager(..) => { |
210 | let id: MacroCallId = expand_eager_macro( | 210 | let id = expand_eager_macro( |
211 | db, | 211 | db, |
212 | krate, | 212 | krate, |
213 | curr.with_value(child.clone()), | 213 | curr.with_value(child.clone()), |
diff --git a/crates/hir_ty/src/chalk_db.rs b/crates/hir_ty/src/chalk_db.rs index a4c09c742..a55b99de0 100644 --- a/crates/hir_ty/src/chalk_db.rs +++ b/crates/hir_ty/src/chalk_db.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | //! about the code that Chalk needs. | 2 | //! about the code that Chalk needs. |
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use cov_mark::hit; | ||
5 | use log::debug; | 6 | use log::debug; |
6 | 7 | ||
7 | use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds}; | 8 | use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds}; |
@@ -106,7 +107,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
106 | }; | 107 | }; |
107 | 108 | ||
108 | fn local_impls(db: &dyn HirDatabase, module: ModuleId) -> Option<Arc<TraitImpls>> { | 109 | fn local_impls(db: &dyn HirDatabase, module: ModuleId) -> Option<Arc<TraitImpls>> { |
109 | db.trait_impls_in_block(module.containing_block()?) | 110 | let block = module.containing_block()?; |
111 | hit!(block_local_impls); | ||
112 | db.trait_impls_in_block(block) | ||
110 | } | 113 | } |
111 | 114 | ||
112 | // Note: Since we're using impls_for_trait, only impls where the trait | 115 | // Note: Since we're using impls_for_trait, only impls where the trait |
diff --git a/crates/hir_ty/src/test_db.rs b/crates/hir_ty/src/test_db.rs index 4640ea821..b99a03492 100644 --- a/crates/hir_ty/src/test_db.rs +++ b/crates/hir_ty/src/test_db.rs | |||
@@ -86,16 +86,20 @@ impl FileLoader for TestDB { | |||
86 | } | 86 | } |
87 | 87 | ||
88 | impl TestDB { | 88 | impl TestDB { |
89 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { | 89 | pub(crate) fn module_for_file_opt(&self, file_id: FileId) -> Option<ModuleId> { |
90 | for &krate in self.relevant_crates(file_id).iter() { | 90 | for &krate in self.relevant_crates(file_id).iter() { |
91 | let crate_def_map = self.crate_def_map(krate); | 91 | let crate_def_map = self.crate_def_map(krate); |
92 | for (local_id, data) in crate_def_map.modules() { | 92 | for (local_id, data) in crate_def_map.modules() { |
93 | if data.origin.file_id() == Some(file_id) { | 93 | if data.origin.file_id() == Some(file_id) { |
94 | return crate_def_map.module_id(local_id); | 94 | return Some(crate_def_map.module_id(local_id)); |
95 | } | 95 | } |
96 | } | 96 | } |
97 | } | 97 | } |
98 | panic!("Can't find module for file") | 98 | None |
99 | } | ||
100 | |||
101 | pub(crate) fn module_for_file(&self, file_id: FileId) -> ModuleId { | ||
102 | self.module_for_file_opt(file_id).unwrap() | ||
99 | } | 103 | } |
100 | 104 | ||
101 | pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { | 105 | pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> { |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index b873585c4..0651f34ae 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -11,23 +11,21 @@ mod incremental; | |||
11 | 11 | ||
12 | use std::{collections::HashMap, env, sync::Arc}; | 12 | use std::{collections::HashMap, env, sync::Arc}; |
13 | 13 | ||
14 | use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt}; | 14 | use base_db::{fixture::WithFixture, FileRange, SourceDatabaseExt}; |
15 | use expect_test::Expect; | 15 | use expect_test::Expect; |
16 | use hir_def::{ | 16 | use hir_def::{ |
17 | body::{Body, BodySourceMap, SyntheticSyntax}, | 17 | body::{Body, BodySourceMap, SyntheticSyntax}, |
18 | child_by_source::ChildBySource, | ||
19 | db::DefDatabase, | 18 | db::DefDatabase, |
19 | expr::{ExprId, PatId}, | ||
20 | item_scope::ItemScope, | 20 | item_scope::ItemScope, |
21 | keys, | ||
22 | nameres::DefMap, | 21 | nameres::DefMap, |
23 | src::HasSource, | 22 | src::HasSource, |
24 | AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, | 23 | AssocItemId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleDefId, |
25 | }; | 24 | }; |
26 | use hir_expand::{db::AstDatabase, InFile}; | 25 | use hir_expand::{db::AstDatabase, InFile}; |
27 | use once_cell::race::OnceBool; | 26 | use once_cell::race::OnceBool; |
28 | use stdx::format_to; | 27 | use stdx::format_to; |
29 | use syntax::{ | 28 | use syntax::{ |
30 | algo, | ||
31 | ast::{self, AstNode, NameOwner}, | 29 | ast::{self, AstNode, NameOwner}, |
32 | SyntaxNode, | 30 | SyntaxNode, |
33 | }; | 31 | }; |
@@ -59,51 +57,55 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> { | |||
59 | } | 57 | } |
60 | 58 | ||
61 | fn check_types(ra_fixture: &str) { | 59 | fn check_types(ra_fixture: &str) { |
62 | check_types_impl(ra_fixture, false) | 60 | check_impl(ra_fixture, false, true, false) |
63 | } | 61 | } |
64 | 62 | ||
65 | fn check_types_source_code(ra_fixture: &str) { | 63 | fn check_types_source_code(ra_fixture: &str) { |
66 | check_types_impl(ra_fixture, true) | 64 | check_impl(ra_fixture, false, true, true) |
67 | } | ||
68 | |||
69 | fn check_types_impl(ra_fixture: &str, display_source: bool) { | ||
70 | let _tracing = setup_tracing(); | ||
71 | let db = TestDB::with_files(ra_fixture); | ||
72 | let mut checked_one = false; | ||
73 | for (file_id, annotations) in db.extract_annotations() { | ||
74 | for (range, expected) in annotations { | ||
75 | let ty = type_at_range(&db, FileRange { file_id, range }); | ||
76 | let actual = if display_source { | ||
77 | let module = db.module_for_file(file_id); | ||
78 | ty.display_source_code(&db, module).unwrap() | ||
79 | } else { | ||
80 | ty.display_test(&db).to_string() | ||
81 | }; | ||
82 | assert_eq!(expected, actual); | ||
83 | checked_one = true; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | assert!(checked_one, "no `//^` annotations found"); | ||
88 | } | 65 | } |
89 | 66 | ||
90 | fn check_no_mismatches(ra_fixture: &str) { | 67 | fn check_no_mismatches(ra_fixture: &str) { |
91 | check_mismatches_impl(ra_fixture, true) | 68 | check_impl(ra_fixture, true, false, false) |
92 | } | 69 | } |
93 | 70 | ||
94 | #[allow(unused)] | 71 | fn check(ra_fixture: &str) { |
95 | fn check_mismatches(ra_fixture: &str) { | 72 | check_impl(ra_fixture, false, false, false) |
96 | check_mismatches_impl(ra_fixture, false) | ||
97 | } | 73 | } |
98 | 74 | ||
99 | fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | 75 | fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) { |
100 | let _tracing = setup_tracing(); | 76 | let _tracing = setup_tracing(); |
101 | let (db, file_id) = TestDB::with_single_file(ra_fixture); | 77 | let (db, files) = TestDB::with_many_files(ra_fixture); |
102 | let module = db.module_for_file(file_id); | 78 | |
103 | let def_map = module.def_map(&db); | 79 | let mut had_annotations = false; |
80 | let mut mismatches = HashMap::new(); | ||
81 | let mut types = HashMap::new(); | ||
82 | for (file_id, annotations) in db.extract_annotations() { | ||
83 | for (range, expected) in annotations { | ||
84 | let file_range = FileRange { file_id, range }; | ||
85 | if only_types { | ||
86 | types.insert(file_range, expected); | ||
87 | } else if expected.starts_with("type: ") { | ||
88 | types.insert(file_range, expected.trim_start_matches("type: ").to_string()); | ||
89 | } else if expected.starts_with("expected") { | ||
90 | mismatches.insert(file_range, expected); | ||
91 | } else { | ||
92 | panic!("unexpected annotation: {}", expected); | ||
93 | } | ||
94 | had_annotations = true; | ||
95 | } | ||
96 | } | ||
97 | assert!(had_annotations || allow_none, "no `//^` annotations found"); | ||
104 | 98 | ||
105 | let mut defs: Vec<DefWithBodyId> = Vec::new(); | 99 | let mut defs: Vec<DefWithBodyId> = Vec::new(); |
106 | visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it)); | 100 | for file_id in files { |
101 | let module = db.module_for_file_opt(file_id); | ||
102 | let module = match module { | ||
103 | Some(m) => m, | ||
104 | None => continue, | ||
105 | }; | ||
106 | let def_map = module.def_map(&db); | ||
107 | visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it)); | ||
108 | } | ||
107 | defs.sort_by_key(|def| match def { | 109 | defs.sort_by_key(|def| match def { |
108 | DefWithBodyId::FunctionId(it) => { | 110 | DefWithBodyId::FunctionId(it) => { |
109 | let loc = it.lookup(&db); | 111 | let loc = it.lookup(&db); |
@@ -118,37 +120,59 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | |||
118 | loc.source(&db).value.syntax().text_range().start() | 120 | loc.source(&db).value.syntax().text_range().start() |
119 | } | 121 | } |
120 | }); | 122 | }); |
121 | let mut mismatches = HashMap::new(); | 123 | let mut unexpected_type_mismatches = String::new(); |
122 | let mut push_mismatch = |src_ptr: InFile<SyntaxNode>, mismatch: TypeMismatch| { | ||
123 | let range = src_ptr.value.text_range(); | ||
124 | if src_ptr.file_id.call_node(&db).is_some() { | ||
125 | panic!("type mismatch in macro expansion"); | ||
126 | } | ||
127 | let file_range = FileRange { file_id: src_ptr.file_id.original_file(&db), range }; | ||
128 | let actual = format!( | ||
129 | "expected {}, got {}", | ||
130 | mismatch.expected.display_test(&db), | ||
131 | mismatch.actual.display_test(&db) | ||
132 | ); | ||
133 | mismatches.insert(file_range, actual); | ||
134 | }; | ||
135 | for def in defs { | 124 | for def in defs { |
136 | let (_body, body_source_map) = db.body_with_source_map(def); | 125 | let (_body, body_source_map) = db.body_with_source_map(def); |
137 | let inference_result = db.infer(def); | 126 | let inference_result = db.infer(def); |
127 | |||
128 | for (pat, ty) in inference_result.type_of_pat.iter() { | ||
129 | let node = match pat_node(&body_source_map, pat, &db) { | ||
130 | Some(value) => value, | ||
131 | None => continue, | ||
132 | }; | ||
133 | let range = node.as_ref().original_file_range(&db); | ||
134 | if let Some(expected) = types.remove(&range) { | ||
135 | let actual = if display_source { | ||
136 | ty.display_source_code(&db, def.module(&db)).unwrap() | ||
137 | } else { | ||
138 | ty.display_test(&db).to_string() | ||
139 | }; | ||
140 | assert_eq!(actual, expected); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | for (expr, ty) in inference_result.type_of_expr.iter() { | ||
145 | let node = match expr_node(&body_source_map, expr, &db) { | ||
146 | Some(value) => value, | ||
147 | None => continue, | ||
148 | }; | ||
149 | let range = node.as_ref().original_file_range(&db); | ||
150 | if let Some(expected) = types.remove(&range) { | ||
151 | let actual = if display_source { | ||
152 | ty.display_source_code(&db, def.module(&db)).unwrap() | ||
153 | } else { | ||
154 | ty.display_test(&db).to_string() | ||
155 | }; | ||
156 | assert_eq!(actual, expected); | ||
157 | } | ||
158 | } | ||
159 | |||
138 | for (pat, mismatch) in inference_result.pat_type_mismatches() { | 160 | for (pat, mismatch) in inference_result.pat_type_mismatches() { |
139 | let syntax_ptr = match body_source_map.pat_syntax(pat) { | 161 | let node = match pat_node(&body_source_map, pat, &db) { |
140 | Ok(sp) => { | 162 | Some(value) => value, |
141 | let root = db.parse_or_expand(sp.file_id).unwrap(); | 163 | None => continue, |
142 | sp.map(|ptr| { | ||
143 | ptr.either( | ||
144 | |it| it.to_node(&root).syntax().clone(), | ||
145 | |it| it.to_node(&root).syntax().clone(), | ||
146 | ) | ||
147 | }) | ||
148 | } | ||
149 | Err(SyntheticSyntax) => continue, | ||
150 | }; | 164 | }; |
151 | push_mismatch(syntax_ptr, mismatch.clone()); | 165 | let range = node.as_ref().original_file_range(&db); |
166 | let actual = format!( | ||
167 | "expected {}, got {}", | ||
168 | mismatch.expected.display_test(&db), | ||
169 | mismatch.actual.display_test(&db) | ||
170 | ); | ||
171 | if let Some(annotation) = mismatches.remove(&range) { | ||
172 | assert_eq!(actual, annotation); | ||
173 | } else { | ||
174 | format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual); | ||
175 | } | ||
152 | } | 176 | } |
153 | for (expr, mismatch) in inference_result.expr_type_mismatches() { | 177 | for (expr, mismatch) in inference_result.expr_type_mismatches() { |
154 | let node = match body_source_map.expr_syntax(expr) { | 178 | let node = match body_source_map.expr_syntax(expr) { |
@@ -158,45 +182,70 @@ fn check_mismatches_impl(ra_fixture: &str, allow_none: bool) { | |||
158 | } | 182 | } |
159 | Err(SyntheticSyntax) => continue, | 183 | Err(SyntheticSyntax) => continue, |
160 | }; | 184 | }; |
161 | push_mismatch(node, mismatch.clone()); | 185 | let range = node.as_ref().original_file_range(&db); |
162 | } | 186 | let actual = format!( |
163 | } | 187 | "expected {}, got {}", |
164 | let mut checked_one = false; | 188 | mismatch.expected.display_test(&db), |
165 | for (file_id, annotations) in db.extract_annotations() { | 189 | mismatch.actual.display_test(&db) |
166 | for (range, expected) in annotations { | 190 | ); |
167 | let file_range = FileRange { file_id, range }; | 191 | if let Some(annotation) = mismatches.remove(&range) { |
168 | if let Some(mismatch) = mismatches.remove(&file_range) { | 192 | assert_eq!(actual, annotation); |
169 | assert_eq!(mismatch, expected); | ||
170 | } else { | 193 | } else { |
171 | assert!(false, "Expected mismatch not encountered: {}\n", expected); | 194 | format_to!(unexpected_type_mismatches, "{:?}: {}\n", range.range, actual); |
172 | } | 195 | } |
173 | checked_one = true; | ||
174 | } | 196 | } |
175 | } | 197 | } |
198 | |||
176 | let mut buf = String::new(); | 199 | let mut buf = String::new(); |
177 | for (range, mismatch) in mismatches { | 200 | if !unexpected_type_mismatches.is_empty() { |
178 | format_to!(buf, "{:?}: {}\n", range.range, mismatch,); | 201 | format_to!(buf, "Unexpected type mismatches:\n{}", unexpected_type_mismatches); |
202 | } | ||
203 | if !mismatches.is_empty() { | ||
204 | format_to!(buf, "Unchecked mismatch annotations:\n"); | ||
205 | for m in mismatches { | ||
206 | format_to!(buf, "{:?}: {}\n", m.0.range, m.1); | ||
207 | } | ||
179 | } | 208 | } |
180 | assert!(buf.is_empty(), "Unexpected type mismatches:\n{}", buf); | 209 | if !types.is_empty() { |
210 | format_to!(buf, "Unchecked type annotations:\n"); | ||
211 | for t in types { | ||
212 | format_to!(buf, "{:?}: type {}\n", t.0.range, t.1); | ||
213 | } | ||
214 | } | ||
215 | assert!(buf.is_empty(), "{}", buf); | ||
216 | } | ||
181 | 217 | ||
182 | assert!(checked_one || allow_none, "no `//^` annotations found"); | 218 | fn expr_node( |
219 | body_source_map: &BodySourceMap, | ||
220 | expr: ExprId, | ||
221 | db: &TestDB, | ||
222 | ) -> Option<InFile<SyntaxNode>> { | ||
223 | Some(match body_source_map.expr_syntax(expr) { | ||
224 | Ok(sp) => { | ||
225 | let root = db.parse_or_expand(sp.file_id).unwrap(); | ||
226 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | ||
227 | } | ||
228 | Err(SyntheticSyntax) => return None, | ||
229 | }) | ||
183 | } | 230 | } |
184 | 231 | ||
185 | fn type_at_range(db: &TestDB, pos: FileRange) -> Ty { | 232 | fn pat_node( |
186 | let file = db.parse(pos.file_id).ok().unwrap(); | 233 | body_source_map: &BodySourceMap, |
187 | let expr = algo::find_node_at_range::<ast::Expr>(file.syntax(), pos.range).unwrap(); | 234 | pat: PatId, |
188 | let fn_def = expr.syntax().ancestors().find_map(ast::Fn::cast).unwrap(); | 235 | db: &TestDB, |
189 | let module = db.module_for_file(pos.file_id); | 236 | ) -> Option<InFile<SyntaxNode>> { |
190 | let func = *module.child_by_source(db)[keys::FUNCTION] | 237 | Some(match body_source_map.pat_syntax(pat) { |
191 | .get(&InFile::new(pos.file_id.into(), fn_def)) | 238 | Ok(sp) => { |
192 | .unwrap(); | 239 | let root = db.parse_or_expand(sp.file_id).unwrap(); |
193 | 240 | sp.map(|ptr| { | |
194 | let (_body, source_map) = db.body_with_source_map(func.into()); | 241 | ptr.either( |
195 | if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { | 242 | |it| it.to_node(&root).syntax().clone(), |
196 | let infer = db.infer(func.into()); | 243 | |it| it.to_node(&root).syntax().clone(), |
197 | return infer[expr_id].clone(); | 244 | ) |
198 | } | 245 | }) |
199 | panic!("Can't find expression") | 246 | } |
247 | Err(SyntheticSyntax) => return None, | ||
248 | }) | ||
200 | } | 249 | } |
201 | 250 | ||
202 | fn infer(ra_fixture: &str) -> String { | 251 | fn infer(ra_fixture: &str) -> String { |
diff --git a/crates/hir_ty/src/tests/coercion.rs b/crates/hir_ty/src/tests/coercion.rs index 713b74165..87089f09d 100644 --- a/crates/hir_ty/src/tests/coercion.rs +++ b/crates/hir_ty/src/tests/coercion.rs | |||
@@ -1,27 +1,22 @@ | |||
1 | use expect_test::expect; | 1 | use super::{check, check_no_mismatches, check_types}; |
2 | |||
3 | use super::{check_infer, check_infer_with_mismatches, check_no_mismatches, check_types}; | ||
4 | 2 | ||
5 | #[test] | 3 | #[test] |
6 | fn infer_block_expr_type_mismatch() { | 4 | fn block_expr_type_mismatch() { |
7 | check_infer( | 5 | // FIXME fix double type mismatch |
6 | check( | ||
8 | r" | 7 | r" |
9 | fn test() { | 8 | fn test() { |
10 | let a: i32 = { 1i64 }; | 9 | let a: i32 = { 1i64 }; |
11 | } | 10 | // ^^^^^^^^ expected i32, got i64 |
11 | // ^^^^ expected i32, got i64 | ||
12 | } | ||
12 | ", | 13 | ", |
13 | expect![[r" | ||
14 | 10..40 '{ ...4 }; }': () | ||
15 | 20..21 'a': i32 | ||
16 | 29..37 '{ 1i64 }': i64 | ||
17 | 31..35 '1i64': i64 | ||
18 | "]], | ||
19 | ); | 14 | ); |
20 | } | 15 | } |
21 | 16 | ||
22 | #[test] | 17 | #[test] |
23 | fn coerce_places() { | 18 | fn coerce_places() { |
24 | check_infer( | 19 | check_no_mismatches( |
25 | r#" | 20 | r#" |
26 | //- minicore: coerce_unsized | 21 | //- minicore: coerce_unsized |
27 | struct S<T> { a: T } | 22 | struct S<T> { a: T } |
@@ -46,81 +41,25 @@ fn test2() { | |||
46 | let g: (&[_], &[_]) = (arr, arr); | 41 | let g: (&[_], &[_]) = (arr, arr); |
47 | } | 42 | } |
48 | "#, | 43 | "#, |
49 | expect![[r#" | ||
50 | 30..31 '_': &[T] | ||
51 | 44..55 '{ loop {} }': T | ||
52 | 46..53 'loop {}': ! | ||
53 | 51..53 '{}': () | ||
54 | 64..65 '_': S<&[T]> | ||
55 | 81..92 '{ loop {} }': T | ||
56 | 83..90 'loop {}': ! | ||
57 | 88..90 '{}': () | ||
58 | 121..132 '{ loop {} }': *mut [T; 2] | ||
59 | 123..130 'loop {}': ! | ||
60 | 128..130 '{}': () | ||
61 | 159..172 '{ gen() }': *mut [U] | ||
62 | 165..168 'gen': fn gen<U>() -> *mut [U; 2] | ||
63 | 165..170 'gen()': *mut [U; 2] | ||
64 | 185..419 '{ ...rr); }': () | ||
65 | 195..198 'arr': &[u8; 1] | ||
66 | 211..215 '&[1]': &[u8; 1] | ||
67 | 212..215 '[1]': [u8; 1] | ||
68 | 213..214 '1': u8 | ||
69 | 226..227 'a': &[u8] | ||
70 | 236..239 'arr': &[u8; 1] | ||
71 | 249..250 'b': u8 | ||
72 | 253..254 'f': fn f<u8>(&[u8]) -> u8 | ||
73 | 253..259 'f(arr)': u8 | ||
74 | 255..258 'arr': &[u8; 1] | ||
75 | 269..270 'c': &[u8] | ||
76 | 279..286 '{ arr }': &[u8] | ||
77 | 281..284 'arr': &[u8; 1] | ||
78 | 296..297 'd': u8 | ||
79 | 300..301 'g': fn g<u8>(S<&[u8]>) -> u8 | ||
80 | 300..315 'g(S { a: arr })': u8 | ||
81 | 302..314 'S { a: arr }': S<&[u8]> | ||
82 | 309..312 'arr': &[u8; 1] | ||
83 | 325..326 'e': [&[u8]; 1] | ||
84 | 340..345 '[arr]': [&[u8]; 1] | ||
85 | 341..344 'arr': &[u8; 1] | ||
86 | 355..356 'f': [&[u8]; 2] | ||
87 | 370..378 '[arr; 2]': [&[u8]; 2] | ||
88 | 371..374 'arr': &[u8; 1] | ||
89 | 376..377 '2': usize | ||
90 | 388..389 'g': (&[u8], &[u8]) | ||
91 | 406..416 '(arr, arr)': (&[u8], &[u8]) | ||
92 | 407..410 'arr': &[u8; 1] | ||
93 | 412..415 'arr': &[u8; 1] | ||
94 | "#]], | ||
95 | ); | 44 | ); |
96 | } | 45 | } |
97 | 46 | ||
98 | #[test] | 47 | #[test] |
99 | fn infer_let_stmt_coerce() { | 48 | fn let_stmt_coerce() { |
100 | check_infer( | 49 | check_no_mismatches( |
101 | r" | 50 | r" |
102 | fn test() { | 51 | //- minicore: coerce_unsized |
103 | let x: &[isize] = &[1]; | 52 | fn test() { |
104 | let x: *const [isize] = &[1]; | 53 | let x: &[isize] = &[1]; |
105 | } | 54 | let x: *const [isize] = &[1]; |
106 | ", | 55 | } |
107 | expect![[r#" | 56 | ", |
108 | 10..75 '{ ...[1]; }': () | ||
109 | 20..21 'x': &[isize] | ||
110 | 34..38 '&[1]': &[isize; 1] | ||
111 | 35..38 '[1]': [isize; 1] | ||
112 | 36..37 '1': isize | ||
113 | 48..49 'x': *const [isize] | ||
114 | 68..72 '&[1]': &[isize; 1] | ||
115 | 69..72 '[1]': [isize; 1] | ||
116 | 70..71 '1': isize | ||
117 | "#]], | ||
118 | ); | 57 | ); |
119 | } | 58 | } |
120 | 59 | ||
121 | #[test] | 60 | #[test] |
122 | fn infer_custom_coerce_unsized() { | 61 | fn custom_coerce_unsized() { |
123 | check_infer( | 62 | check( |
124 | r#" | 63 | r#" |
125 | //- minicore: coerce_unsized | 64 | //- minicore: coerce_unsized |
126 | use core::{marker::Unsize, ops::CoerceUnsized}; | 65 | use core::{marker::Unsize, ops::CoerceUnsized}; |
@@ -138,46 +77,22 @@ fn foo3<T>(x: C<[T]>) -> C<[T]> { x } | |||
138 | 77 | ||
139 | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | 78 | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { |
140 | let d = foo1(a); | 79 | let d = foo1(a); |
80 | // ^ expected A<[{unknown}]>, got A<[u8; 2]> | ||
141 | let e = foo2(b); | 81 | let e = foo2(b); |
82 | // ^ type: B<[u8]> | ||
142 | let f = foo3(c); | 83 | let f = foo3(c); |
84 | // ^ type: C<[u8]> | ||
143 | } | 85 | } |
144 | "#, | 86 | "#, |
145 | expect![[r#" | ||
146 | 306..307 'x': A<[T]> | ||
147 | 327..332 '{ x }': A<[T]> | ||
148 | 329..330 'x': A<[T]> | ||
149 | 344..345 'x': B<[T]> | ||
150 | 365..370 '{ x }': B<[T]> | ||
151 | 367..368 'x': B<[T]> | ||
152 | 382..383 'x': C<[T]> | ||
153 | 403..408 '{ x }': C<[T]> | ||
154 | 405..406 'x': C<[T]> | ||
155 | 418..419 'a': A<[u8; 2]> | ||
156 | 433..434 'b': B<[u8; 2]> | ||
157 | 448..449 'c': C<[u8; 2]> | ||
158 | 463..529 '{ ...(c); }': () | ||
159 | 473..474 'd': A<[{unknown}]> | ||
160 | 477..481 'foo1': fn foo1<{unknown}>(A<[{unknown}]>) -> A<[{unknown}]> | ||
161 | 477..484 'foo1(a)': A<[{unknown}]> | ||
162 | 482..483 'a': A<[u8; 2]> | ||
163 | 494..495 'e': B<[u8]> | ||
164 | 498..502 'foo2': fn foo2<u8>(B<[u8]>) -> B<[u8]> | ||
165 | 498..505 'foo2(b)': B<[u8]> | ||
166 | 503..504 'b': B<[u8; 2]> | ||
167 | 515..516 'f': C<[u8]> | ||
168 | 519..523 'foo3': fn foo3<u8>(C<[u8]>) -> C<[u8]> | ||
169 | 519..526 'foo3(c)': C<[u8]> | ||
170 | 524..525 'c': C<[u8; 2]> | ||
171 | "#]], | ||
172 | ); | 87 | ); |
173 | } | 88 | } |
174 | 89 | ||
175 | #[test] | 90 | #[test] |
176 | fn infer_if_coerce() { | 91 | fn if_coerce() { |
177 | check_infer( | 92 | check_no_mismatches( |
178 | r#" | 93 | r#" |
179 | //- minicore: unsize | 94 | //- minicore: coerce_unsized |
180 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 95 | fn foo<T>(x: &[T]) -> &[T] { x } |
181 | fn test() { | 96 | fn test() { |
182 | let x = if true { | 97 | let x = if true { |
183 | foo(&[1]) | 98 | foo(&[1]) |
@@ -186,35 +101,15 @@ fn test() { | |||
186 | }; | 101 | }; |
187 | } | 102 | } |
188 | "#, | 103 | "#, |
189 | expect![[r#" | ||
190 | 10..11 'x': &[T] | ||
191 | 27..38 '{ loop {} }': &[T] | ||
192 | 29..36 'loop {}': ! | ||
193 | 34..36 '{}': () | ||
194 | 49..125 '{ ... }; }': () | ||
195 | 59..60 'x': &[i32] | ||
196 | 63..122 'if tru... }': &[i32] | ||
197 | 66..70 'true': bool | ||
198 | 71..96 '{ ... }': &[i32] | ||
199 | 81..84 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
200 | 81..90 'foo(&[1])': &[i32] | ||
201 | 85..89 '&[1]': &[i32; 1] | ||
202 | 86..89 '[1]': [i32; 1] | ||
203 | 87..88 '1': i32 | ||
204 | 102..122 '{ ... }': &[i32; 1] | ||
205 | 112..116 '&[1]': &[i32; 1] | ||
206 | 113..116 '[1]': [i32; 1] | ||
207 | 114..115 '1': i32 | ||
208 | "#]], | ||
209 | ); | 104 | ); |
210 | } | 105 | } |
211 | 106 | ||
212 | #[test] | 107 | #[test] |
213 | fn infer_if_else_coerce() { | 108 | fn if_else_coerce() { |
214 | check_infer( | 109 | check_no_mismatches( |
215 | r#" | 110 | r#" |
216 | //- minicore: coerce_unsized | 111 | //- minicore: coerce_unsized |
217 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 112 | fn foo<T>(x: &[T]) -> &[T] { x } |
218 | fn test() { | 113 | fn test() { |
219 | let x = if true { | 114 | let x = if true { |
220 | &[1] | 115 | &[1] |
@@ -223,35 +118,15 @@ fn test() { | |||
223 | }; | 118 | }; |
224 | } | 119 | } |
225 | "#, | 120 | "#, |
226 | expect![[r#" | ||
227 | 10..11 'x': &[T] | ||
228 | 27..38 '{ loop {} }': &[T] | ||
229 | 29..36 'loop {}': ! | ||
230 | 34..36 '{}': () | ||
231 | 49..125 '{ ... }; }': () | ||
232 | 59..60 'x': &[i32] | ||
233 | 63..122 'if tru... }': &[i32] | ||
234 | 66..70 'true': bool | ||
235 | 71..91 '{ ... }': &[i32; 1] | ||
236 | 81..85 '&[1]': &[i32; 1] | ||
237 | 82..85 '[1]': [i32; 1] | ||
238 | 83..84 '1': i32 | ||
239 | 97..122 '{ ... }': &[i32] | ||
240 | 107..110 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
241 | 107..116 'foo(&[1])': &[i32] | ||
242 | 111..115 '&[1]': &[i32; 1] | ||
243 | 112..115 '[1]': [i32; 1] | ||
244 | 113..114 '1': i32 | ||
245 | "#]], | ||
246 | ) | 121 | ) |
247 | } | 122 | } |
248 | 123 | ||
249 | #[test] | 124 | #[test] |
250 | fn infer_match_first_coerce() { | 125 | fn match_first_coerce() { |
251 | check_infer( | 126 | check_no_mismatches( |
252 | r#" | 127 | r#" |
253 | //- minicore: unsize | 128 | //- minicore: coerce_unsized |
254 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 129 | fn foo<T>(x: &[T]) -> &[T] { x } |
255 | fn test(i: i32) { | 130 | fn test(i: i32) { |
256 | let x = match i { | 131 | let x = match i { |
257 | 2 => foo(&[2]), | 132 | 2 => foo(&[2]), |
@@ -260,39 +135,12 @@ fn test(i: i32) { | |||
260 | }; | 135 | }; |
261 | } | 136 | } |
262 | "#, | 137 | "#, |
263 | expect![[r#" | ||
264 | 10..11 'x': &[T] | ||
265 | 27..38 '{ loop {} }': &[T] | ||
266 | 29..36 'loop {}': ! | ||
267 | 34..36 '{}': () | ||
268 | 47..48 'i': i32 | ||
269 | 55..149 '{ ... }; }': () | ||
270 | 65..66 'x': &[i32] | ||
271 | 69..146 'match ... }': &[i32] | ||
272 | 75..76 'i': i32 | ||
273 | 87..88 '2': i32 | ||
274 | 87..88 '2': i32 | ||
275 | 92..95 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
276 | 92..101 'foo(&[2])': &[i32] | ||
277 | 96..100 '&[2]': &[i32; 1] | ||
278 | 97..100 '[2]': [i32; 1] | ||
279 | 98..99 '2': i32 | ||
280 | 111..112 '1': i32 | ||
281 | 111..112 '1': i32 | ||
282 | 116..120 '&[1]': &[i32; 1] | ||
283 | 117..120 '[1]': [i32; 1] | ||
284 | 118..119 '1': i32 | ||
285 | 130..131 '_': i32 | ||
286 | 135..139 '&[3]': &[i32; 1] | ||
287 | 136..139 '[3]': [i32; 1] | ||
288 | 137..138 '3': i32 | ||
289 | "#]], | ||
290 | ); | 138 | ); |
291 | } | 139 | } |
292 | 140 | ||
293 | #[test] | 141 | #[test] |
294 | fn infer_match_second_coerce() { | 142 | fn match_second_coerce() { |
295 | check_infer( | 143 | check_no_mismatches( |
296 | r#" | 144 | r#" |
297 | //- minicore: coerce_unsized | 145 | //- minicore: coerce_unsized |
298 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 146 | fn foo<T>(x: &[T]) -> &[T] { loop {} } |
@@ -304,33 +152,6 @@ fn test(i: i32) { | |||
304 | }; | 152 | }; |
305 | } | 153 | } |
306 | "#, | 154 | "#, |
307 | expect![[r#" | ||
308 | 10..11 'x': &[T] | ||
309 | 27..38 '{ loop {} }': &[T] | ||
310 | 29..36 'loop {}': ! | ||
311 | 34..36 '{}': () | ||
312 | 47..48 'i': i32 | ||
313 | 55..149 '{ ... }; }': () | ||
314 | 65..66 'x': &[i32] | ||
315 | 69..146 'match ... }': &[i32] | ||
316 | 75..76 'i': i32 | ||
317 | 87..88 '1': i32 | ||
318 | 87..88 '1': i32 | ||
319 | 92..96 '&[1]': &[i32; 1] | ||
320 | 93..96 '[1]': [i32; 1] | ||
321 | 94..95 '1': i32 | ||
322 | 106..107 '2': i32 | ||
323 | 106..107 '2': i32 | ||
324 | 111..114 'foo': fn foo<i32>(&[i32]) -> &[i32] | ||
325 | 111..120 'foo(&[2])': &[i32] | ||
326 | 115..119 '&[2]': &[i32; 1] | ||
327 | 116..119 '[2]': [i32; 1] | ||
328 | 117..118 '2': i32 | ||
329 | 130..131 '_': i32 | ||
330 | 135..139 '&[3]': &[i32; 1] | ||
331 | 136..139 '[3]': [i32; 1] | ||
332 | 137..138 '3': i32 | ||
333 | "#]], | ||
334 | ); | 155 | ); |
335 | } | 156 | } |
336 | 157 | ||
@@ -338,94 +159,52 @@ fn test(i: i32) { | |||
338 | fn coerce_merge_one_by_one1() { | 159 | fn coerce_merge_one_by_one1() { |
339 | cov_mark::check!(coerce_merge_fail_fallback); | 160 | cov_mark::check!(coerce_merge_fail_fallback); |
340 | 161 | ||
341 | check_infer( | 162 | check( |
342 | r" | 163 | r" |
343 | fn test() { | 164 | fn test() { |
344 | let t = &mut 1; | 165 | let t = &mut 1; |
345 | let x = match 1 { | 166 | let x = match 1 { |
346 | 1 => t as *mut i32, | 167 | 1 => t as *mut i32, |
347 | 2 => t as &i32, | 168 | 2 => t as &i32, |
348 | _ => t as *const i32, | 169 | //^^^^^^^^^ expected *mut i32, got &i32 |
349 | }; | 170 | _ => t as *const i32, |
350 | } | 171 | }; |
172 | x; | ||
173 | //^ type: *const i32 | ||
174 | } | ||
351 | ", | 175 | ", |
352 | expect![[r" | ||
353 | 10..144 '{ ... }; }': () | ||
354 | 20..21 't': &mut i32 | ||
355 | 24..30 '&mut 1': &mut i32 | ||
356 | 29..30 '1': i32 | ||
357 | 40..41 'x': *const i32 | ||
358 | 44..141 'match ... }': *const i32 | ||
359 | 50..51 '1': i32 | ||
360 | 62..63 '1': i32 | ||
361 | 62..63 '1': i32 | ||
362 | 67..68 't': &mut i32 | ||
363 | 67..80 't as *mut i32': *mut i32 | ||
364 | 90..91 '2': i32 | ||
365 | 90..91 '2': i32 | ||
366 | 95..96 't': &mut i32 | ||
367 | 95..104 't as &i32': &i32 | ||
368 | 114..115 '_': i32 | ||
369 | 119..120 't': &mut i32 | ||
370 | 119..134 't as *const i32': *const i32 | ||
371 | "]], | ||
372 | ); | 176 | ); |
373 | } | 177 | } |
374 | 178 | ||
375 | #[test] | 179 | #[test] |
376 | fn return_coerce_unknown() { | 180 | fn return_coerce_unknown() { |
377 | check_infer_with_mismatches( | 181 | check_types( |
378 | r" | 182 | r" |
379 | fn foo() -> u32 { | 183 | fn foo() -> u32 { |
380 | return unknown; | 184 | return unknown; |
381 | } | 185 | //^^^^^^^ u32 |
186 | } | ||
382 | ", | 187 | ", |
383 | expect![[r" | ||
384 | 16..39 '{ ...own; }': u32 | ||
385 | 22..36 'return unknown': ! | ||
386 | 29..36 'unknown': u32 | ||
387 | "]], | ||
388 | ); | 188 | ); |
389 | } | 189 | } |
390 | 190 | ||
391 | #[test] | 191 | #[test] |
392 | fn coerce_autoderef() { | 192 | fn coerce_autoderef() { |
393 | check_infer_with_mismatches( | 193 | check_no_mismatches( |
394 | r" | 194 | r" |
395 | struct Foo; | 195 | struct Foo; |
396 | fn takes_ref_foo(x: &Foo) {} | 196 | fn takes_ref_foo(x: &Foo) {} |
397 | fn test() { | 197 | fn test() { |
398 | takes_ref_foo(&Foo); | 198 | takes_ref_foo(&Foo); |
399 | takes_ref_foo(&&Foo); | 199 | takes_ref_foo(&&Foo); |
400 | takes_ref_foo(&&&Foo); | 200 | takes_ref_foo(&&&Foo); |
401 | } | 201 | }", |
402 | ", | ||
403 | expect![[r" | ||
404 | 29..30 'x': &Foo | ||
405 | 38..40 '{}': () | ||
406 | 51..132 '{ ...oo); }': () | ||
407 | 57..70 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
408 | 57..76 'takes_...(&Foo)': () | ||
409 | 71..75 '&Foo': &Foo | ||
410 | 72..75 'Foo': Foo | ||
411 | 82..95 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
412 | 82..102 'takes_...&&Foo)': () | ||
413 | 96..101 '&&Foo': &&Foo | ||
414 | 97..101 '&Foo': &Foo | ||
415 | 98..101 'Foo': Foo | ||
416 | 108..121 'takes_ref_foo': fn takes_ref_foo(&Foo) | ||
417 | 108..129 'takes_...&&Foo)': () | ||
418 | 122..128 '&&&Foo': &&&Foo | ||
419 | 123..128 '&&Foo': &&Foo | ||
420 | 124..128 '&Foo': &Foo | ||
421 | 125..128 'Foo': Foo | ||
422 | "]], | ||
423 | ); | 202 | ); |
424 | } | 203 | } |
425 | 204 | ||
426 | #[test] | 205 | #[test] |
427 | fn coerce_autoderef_generic() { | 206 | fn coerce_autoderef_generic() { |
428 | check_infer_with_mismatches( | 207 | check_no_mismatches( |
429 | r#" | 208 | r#" |
430 | struct Foo; | 209 | struct Foo; |
431 | fn takes_ref<T>(x: &T) -> T { *x } | 210 | fn takes_ref<T>(x: &T) -> T { *x } |
@@ -435,34 +214,12 @@ fn test() { | |||
435 | takes_ref(&&&Foo); | 214 | takes_ref(&&&Foo); |
436 | } | 215 | } |
437 | "#, | 216 | "#, |
438 | expect![[r" | ||
439 | 28..29 'x': &T | ||
440 | 40..46 '{ *x }': T | ||
441 | 42..44 '*x': T | ||
442 | 43..44 'x': &T | ||
443 | 57..126 '{ ...oo); }': () | ||
444 | 63..72 'takes_ref': fn takes_ref<Foo>(&Foo) -> Foo | ||
445 | 63..78 'takes_ref(&Foo)': Foo | ||
446 | 73..77 '&Foo': &Foo | ||
447 | 74..77 'Foo': Foo | ||
448 | 84..93 'takes_ref': fn takes_ref<&Foo>(&&Foo) -> &Foo | ||
449 | 84..100 'takes_...&&Foo)': &Foo | ||
450 | 94..99 '&&Foo': &&Foo | ||
451 | 95..99 '&Foo': &Foo | ||
452 | 96..99 'Foo': Foo | ||
453 | 106..115 'takes_ref': fn takes_ref<&&Foo>(&&&Foo) -> &&Foo | ||
454 | 106..123 'takes_...&&Foo)': &&Foo | ||
455 | 116..122 '&&&Foo': &&&Foo | ||
456 | 117..122 '&&Foo': &&Foo | ||
457 | 118..122 '&Foo': &Foo | ||
458 | 119..122 'Foo': Foo | ||
459 | "]], | ||
460 | ); | 217 | ); |
461 | } | 218 | } |
462 | 219 | ||
463 | #[test] | 220 | #[test] |
464 | fn coerce_autoderef_block() { | 221 | fn coerce_autoderef_block() { |
465 | check_infer_with_mismatches( | 222 | check_no_mismatches( |
466 | r#" | 223 | r#" |
467 | //- minicore: deref | 224 | //- minicore: deref |
468 | struct String {} | 225 | struct String {} |
@@ -473,71 +230,32 @@ fn test() { | |||
473 | takes_ref_str(&{ returns_string() }); | 230 | takes_ref_str(&{ returns_string() }); |
474 | } | 231 | } |
475 | "#, | 232 | "#, |
476 | expect![[r#" | ||
477 | 90..91 'x': &str | ||
478 | 99..101 '{}': () | ||
479 | 132..143 '{ loop {} }': String | ||
480 | 134..141 'loop {}': ! | ||
481 | 139..141 '{}': () | ||
482 | 154..199 '{ ... }); }': () | ||
483 | 160..173 'takes_ref_str': fn takes_ref_str(&str) | ||
484 | 160..196 'takes_...g() })': () | ||
485 | 174..195 '&{ ret...ng() }': &String | ||
486 | 175..195 '{ retu...ng() }': String | ||
487 | 177..191 'returns_string': fn returns_string() -> String | ||
488 | 177..193 'return...ring()': String | ||
489 | "#]], | ||
490 | ); | 233 | ); |
491 | } | 234 | } |
492 | 235 | ||
493 | #[test] | 236 | #[test] |
494 | fn closure_return_coerce() { | 237 | fn closure_return_coerce() { |
495 | check_infer_with_mismatches( | 238 | check_no_mismatches( |
496 | r" | 239 | r" |
497 | fn foo() { | 240 | fn foo() { |
498 | let x = || { | 241 | let x = || { |
499 | if true { | 242 | if true { |
500 | return &1u32; | 243 | return &1u32; |
501 | } | ||
502 | &&1u32 | ||
503 | }; | ||
504 | } | 244 | } |
505 | ", | 245 | &&1u32 |
506 | expect![[r" | 246 | }; |
507 | 9..105 '{ ... }; }': () | 247 | }", |
508 | 19..20 'x': || -> &u32 | ||
509 | 23..102 '|| { ... }': || -> &u32 | ||
510 | 26..102 '{ ... }': &u32 | ||
511 | 36..81 'if tru... }': () | ||
512 | 39..43 'true': bool | ||
513 | 44..81 '{ ... }': () | ||
514 | 58..70 'return &1u32': ! | ||
515 | 65..70 '&1u32': &u32 | ||
516 | 66..70 '1u32': u32 | ||
517 | 90..96 '&&1u32': &&u32 | ||
518 | 91..96 '&1u32': &u32 | ||
519 | 92..96 '1u32': u32 | ||
520 | "]], | ||
521 | ); | 248 | ); |
522 | } | 249 | } |
523 | 250 | ||
524 | #[test] | 251 | #[test] |
525 | fn coerce_fn_item_to_fn_ptr() { | 252 | fn coerce_fn_item_to_fn_ptr() { |
526 | check_infer_with_mismatches( | 253 | check_no_mismatches( |
527 | r" | 254 | r" |
528 | fn foo(x: u32) -> isize { 1 } | 255 | fn foo(x: u32) -> isize { 1 } |
529 | fn test() { | 256 | fn test() { |
530 | let f: fn(u32) -> isize = foo; | 257 | let f: fn(u32) -> isize = foo; |
531 | } | 258 | }", |
532 | ", | ||
533 | expect![[r" | ||
534 | 7..8 'x': u32 | ||
535 | 24..29 '{ 1 }': isize | ||
536 | 26..27 '1': isize | ||
537 | 40..78 '{ ...foo; }': () | ||
538 | 50..51 'f': fn(u32) -> isize | ||
539 | 72..75 'foo': fn foo(u32) -> isize | ||
540 | "]], | ||
541 | ); | 259 | ); |
542 | } | 260 | } |
543 | 261 | ||
@@ -545,110 +263,62 @@ fn coerce_fn_item_to_fn_ptr() { | |||
545 | fn coerce_fn_items_in_match_arms() { | 263 | fn coerce_fn_items_in_match_arms() { |
546 | cov_mark::check!(coerce_fn_reification); | 264 | cov_mark::check!(coerce_fn_reification); |
547 | 265 | ||
548 | check_infer_with_mismatches( | 266 | check_types( |
549 | r" | 267 | r" |
550 | fn foo1(x: u32) -> isize { 1 } | 268 | fn foo1(x: u32) -> isize { 1 } |
551 | fn foo2(x: u32) -> isize { 2 } | 269 | fn foo2(x: u32) -> isize { 2 } |
552 | fn foo3(x: u32) -> isize { 3 } | 270 | fn foo3(x: u32) -> isize { 3 } |
553 | fn test() { | 271 | fn test() { |
554 | let x = match 1 { | 272 | let x = match 1 { |
555 | 1 => foo1, | 273 | 1 => foo1, |
556 | 2 => foo2, | 274 | 2 => foo2, |
557 | _ => foo3, | 275 | _ => foo3, |
558 | }; | 276 | }; |
559 | } | 277 | x; |
560 | ", | 278 | //^ fn(u32) -> isize |
561 | expect![[r" | 279 | }", |
562 | 8..9 'x': u32 | ||
563 | 25..30 '{ 1 }': isize | ||
564 | 27..28 '1': isize | ||
565 | 39..40 'x': u32 | ||
566 | 56..61 '{ 2 }': isize | ||
567 | 58..59 '2': isize | ||
568 | 70..71 'x': u32 | ||
569 | 87..92 '{ 3 }': isize | ||
570 | 89..90 '3': isize | ||
571 | 103..192 '{ ... }; }': () | ||
572 | 113..114 'x': fn(u32) -> isize | ||
573 | 117..189 'match ... }': fn(u32) -> isize | ||
574 | 123..124 '1': i32 | ||
575 | 135..136 '1': i32 | ||
576 | 135..136 '1': i32 | ||
577 | 140..144 'foo1': fn foo1(u32) -> isize | ||
578 | 154..155 '2': i32 | ||
579 | 154..155 '2': i32 | ||
580 | 159..163 'foo2': fn foo2(u32) -> isize | ||
581 | 173..174 '_': i32 | ||
582 | 178..182 'foo3': fn foo3(u32) -> isize | ||
583 | "]], | ||
584 | ); | 280 | ); |
585 | } | 281 | } |
586 | 282 | ||
587 | #[test] | 283 | #[test] |
588 | fn coerce_closure_to_fn_ptr() { | 284 | fn coerce_closure_to_fn_ptr() { |
589 | check_infer_with_mismatches( | 285 | check_no_mismatches( |
590 | r" | 286 | r" |
591 | fn test() { | 287 | fn test() { |
592 | let f: fn(u32) -> isize = |x| { 1 }; | 288 | let f: fn(u32) -> isize = |x| { 1 }; |
593 | } | 289 | }", |
594 | ", | ||
595 | expect![[r" | ||
596 | 10..54 '{ ...1 }; }': () | ||
597 | 20..21 'f': fn(u32) -> isize | ||
598 | 42..51 '|x| { 1 }': |u32| -> isize | ||
599 | 43..44 'x': u32 | ||
600 | 46..51 '{ 1 }': isize | ||
601 | 48..49 '1': isize | ||
602 | "]], | ||
603 | ); | 290 | ); |
604 | } | 291 | } |
605 | 292 | ||
606 | #[test] | 293 | #[test] |
607 | fn coerce_placeholder_ref() { | 294 | fn coerce_placeholder_ref() { |
608 | // placeholders should unify, even behind references | 295 | // placeholders should unify, even behind references |
609 | check_infer_with_mismatches( | 296 | check_no_mismatches( |
610 | r" | 297 | r" |
611 | struct S<T> { t: T } | 298 | struct S<T> { t: T } |
612 | impl<TT> S<TT> { | 299 | impl<TT> S<TT> { |
613 | fn get(&self) -> &TT { | 300 | fn get(&self) -> &TT { |
614 | &self.t | 301 | &self.t |
615 | } | 302 | } |
616 | } | 303 | }", |
617 | ", | ||
618 | expect![[r" | ||
619 | 50..54 'self': &S<TT> | ||
620 | 63..86 '{ ... }': &TT | ||
621 | 73..80 '&self.t': &TT | ||
622 | 74..78 'self': &S<TT> | ||
623 | 74..80 'self.t': TT | ||
624 | "]], | ||
625 | ); | 304 | ); |
626 | } | 305 | } |
627 | 306 | ||
628 | #[test] | 307 | #[test] |
629 | fn coerce_unsize_array() { | 308 | fn coerce_unsize_array() { |
630 | check_infer_with_mismatches( | 309 | check_types( |
631 | r#" | 310 | r#" |
632 | //- minicore: coerce_unsized | 311 | //- minicore: coerce_unsized |
633 | fn test() { | 312 | fn test() { |
634 | let f: &[usize] = &[1, 2, 3]; | 313 | let f: &[usize] = &[1, 2, 3]; |
635 | } | 314 | //^ usize |
636 | "#, | 315 | }"#, |
637 | expect![[r#" | ||
638 | 10..47 '{ ... 3]; }': () | ||
639 | 20..21 'f': &[usize] | ||
640 | 34..44 '&[1, 2, 3]': &[usize; 3] | ||
641 | 35..44 '[1, 2, 3]': [usize; 3] | ||
642 | 36..37 '1': usize | ||
643 | 39..40 '2': usize | ||
644 | 42..43 '3': usize | ||
645 | "#]], | ||
646 | ); | 316 | ); |
647 | } | 317 | } |
648 | 318 | ||
649 | #[test] | 319 | #[test] |
650 | fn coerce_unsize_trait_object_simple() { | 320 | fn coerce_unsize_trait_object_simple() { |
651 | check_infer_with_mismatches( | 321 | check_types( |
652 | r#" | 322 | r#" |
653 | //- minicore: coerce_unsized | 323 | //- minicore: coerce_unsized |
654 | trait Foo<T, U> {} | 324 | trait Foo<T, U> {} |
@@ -662,88 +332,18 @@ impl<T, X> Baz<T, X> for S<T, X> {} | |||
662 | 332 | ||
663 | fn test() { | 333 | fn test() { |
664 | let obj: &dyn Baz<i8, i16> = &S; | 334 | let obj: &dyn Baz<i8, i16> = &S; |
335 | //^ S<i8, i16> | ||
665 | let obj: &dyn Bar<_, i8, i16> = &S; | 336 | let obj: &dyn Bar<_, i8, i16> = &S; |
337 | //^ S<i8, i16> | ||
666 | let obj: &dyn Foo<i8, _> = &S; | 338 | let obj: &dyn Foo<i8, _> = &S; |
667 | } | 339 | //^ S<i8, {unknown}> |
668 | "#, | 340 | }"#, |
669 | expect![[r#" | ||
670 | 236..351 '{ ... &S; }': () | ||
671 | 246..249 'obj': &dyn Baz<i8, i16> | ||
672 | 271..273 '&S': &S<i8, i16> | ||
673 | 272..273 'S': S<i8, i16> | ||
674 | 283..286 'obj': &dyn Bar<usize, i8, i16> | ||
675 | 311..313 '&S': &S<i8, i16> | ||
676 | 312..313 'S': S<i8, i16> | ||
677 | 323..326 'obj': &dyn Foo<i8, usize> | ||
678 | 346..348 '&S': &S<i8, {unknown}> | ||
679 | 347..348 'S': S<i8, {unknown}> | ||
680 | "#]], | ||
681 | ); | ||
682 | } | ||
683 | |||
684 | #[test] | ||
685 | fn coerce_unsize_trait_object_to_trait_object() { | ||
686 | // FIXME: The rust reference says this should be possible, but rustc doesn't | ||
687 | // implement it. We used to support it, but Chalk doesn't. Here's the | ||
688 | // correct expect: | ||
689 | // | ||
690 | // 424..609 '{ ...bj2; }': () | ||
691 | // 434..437 'obj': &dyn Baz<i8, i16> | ||
692 | // 459..461 '&S': &S<i8, i16> | ||
693 | // 460..461 'S': S<i8, i16> | ||
694 | // 471..474 'obj': &dyn Bar<usize, i8, i16> | ||
695 | // 496..499 'obj': &dyn Baz<i8, i16> | ||
696 | // 509..512 'obj': &dyn Foo<i8, usize> | ||
697 | // 531..534 'obj': &dyn Bar<usize, i8, i16> | ||
698 | // 544..548 'obj2': &dyn Baz<i8, i16> | ||
699 | // 570..572 '&S': &S<i8, i16> | ||
700 | // 571..572 'S': S<i8, i16> | ||
701 | // 582..583 '_': &dyn Foo<i8, usize> | ||
702 | // 602..606 'obj2': &dyn Baz<i8, i16> | ||
703 | check_infer_with_mismatches( | ||
704 | r#" | ||
705 | //- minicore: coerce_unsized | ||
706 | trait Foo<T, U> {} | ||
707 | trait Bar<U, T, X>: Foo<T, U> {} | ||
708 | trait Baz<T, X>: Bar<usize, T, X> {} | ||
709 | |||
710 | struct S<T, X>; | ||
711 | impl<T, X> Foo<T, usize> for S<T, X> {} | ||
712 | impl<T, X> Bar<usize, T, X> for S<T, X> {} | ||
713 | impl<T, X> Baz<T, X> for S<T, X> {} | ||
714 | |||
715 | fn test() { | ||
716 | let obj: &dyn Baz<i8, i16> = &S; | ||
717 | let obj: &dyn Bar<_, _, _> = obj; | ||
718 | let obj: &dyn Foo<_, _> = obj; | ||
719 | let obj2: &dyn Baz<i8, i16> = &S; | ||
720 | let _: &dyn Foo<_, _> = obj2; | ||
721 | } | ||
722 | "#, | ||
723 | expect![[r#" | ||
724 | 236..421 '{ ...bj2; }': () | ||
725 | 246..249 'obj': &dyn Baz<i8, i16> | ||
726 | 271..273 '&S': &S<i8, i16> | ||
727 | 272..273 'S': S<i8, i16> | ||
728 | 283..286 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}> | ||
729 | 308..311 'obj': &dyn Baz<i8, i16> | ||
730 | 321..324 'obj': &dyn Foo<{unknown}, {unknown}> | ||
731 | 343..346 'obj': &dyn Bar<{unknown}, {unknown}, {unknown}> | ||
732 | 356..360 'obj2': &dyn Baz<i8, i16> | ||
733 | 382..384 '&S': &S<i8, i16> | ||
734 | 383..384 'S': S<i8, i16> | ||
735 | 394..395 '_': &dyn Foo<{unknown}, {unknown}> | ||
736 | 414..418 'obj2': &dyn Baz<i8, i16> | ||
737 | 308..311: expected &dyn Bar<{unknown}, {unknown}, {unknown}>, got &dyn Baz<i8, i16> | ||
738 | 343..346: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Bar<{unknown}, {unknown}, {unknown}> | ||
739 | 414..418: expected &dyn Foo<{unknown}, {unknown}>, got &dyn Baz<i8, i16> | ||
740 | "#]], | ||
741 | ); | 341 | ); |
742 | } | 342 | } |
743 | 343 | ||
744 | #[test] | 344 | #[test] |
745 | fn coerce_unsize_super_trait_cycle() { | 345 | fn coerce_unsize_super_trait_cycle() { |
746 | check_infer_with_mismatches( | 346 | check_no_mismatches( |
747 | r#" | 347 | r#" |
748 | //- minicore: coerce_unsized | 348 | //- minicore: coerce_unsized |
749 | trait A {} | 349 | trait A {} |
@@ -762,22 +362,13 @@ fn test() { | |||
762 | let obj: &dyn A = &S; | 362 | let obj: &dyn A = &S; |
763 | } | 363 | } |
764 | "#, | 364 | "#, |
765 | expect![[r#" | ||
766 | 140..195 '{ ... &S; }': () | ||
767 | 150..153 'obj': &dyn D | ||
768 | 164..166 '&S': &S | ||
769 | 165..166 'S': S | ||
770 | 176..179 'obj': &dyn A | ||
771 | 190..192 '&S': &S | ||
772 | 191..192 'S': S | ||
773 | "#]], | ||
774 | ); | 365 | ); |
775 | } | 366 | } |
776 | 367 | ||
777 | #[test] | 368 | #[test] |
778 | fn coerce_unsize_generic() { | 369 | fn coerce_unsize_generic() { |
779 | // FIXME: fix the type mismatches here | 370 | // FIXME: fix the type mismatches here |
780 | check_infer_with_mismatches( | 371 | check( |
781 | r#" | 372 | r#" |
782 | //- minicore: coerce_unsized | 373 | //- minicore: coerce_unsized |
783 | struct Foo<T> { t: T }; | 374 | struct Foo<T> { t: T }; |
@@ -785,73 +376,47 @@ struct Bar<T>(Foo<T>); | |||
785 | 376 | ||
786 | fn test() { | 377 | fn test() { |
787 | let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; | 378 | let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; |
379 | //^^^^^^^^^ expected [usize], got [usize; 3] | ||
788 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); | 380 | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); |
381 | //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]> | ||
789 | } | 382 | } |
790 | "#, | 383 | "#, |
791 | expect![[r#" | ||
792 | 58..166 '{ ... }); }': () | ||
793 | 68..69 '_': &Foo<[usize]> | ||
794 | 87..108 '&Foo {..., 3] }': &Foo<[usize]> | ||
795 | 88..108 'Foo { ..., 3] }': Foo<[usize]> | ||
796 | 97..106 '[1, 2, 3]': [usize; 3] | ||
797 | 98..99 '1': usize | ||
798 | 101..102 '2': usize | ||
799 | 104..105 '3': usize | ||
800 | 118..119 '_': &Bar<[usize]> | ||
801 | 137..163 '&Bar(F... 3] })': &Bar<[i32; 3]> | ||
802 | 138..141 'Bar': Bar<[i32; 3]>(Foo<[i32; 3]>) -> Bar<[i32; 3]> | ||
803 | 138..163 'Bar(Fo... 3] })': Bar<[i32; 3]> | ||
804 | 142..162 'Foo { ..., 3] }': Foo<[i32; 3]> | ||
805 | 151..160 '[1, 2, 3]': [i32; 3] | ||
806 | 152..153 '1': i32 | ||
807 | 155..156 '2': i32 | ||
808 | 158..159 '3': i32 | ||
809 | 97..106: expected [usize], got [usize; 3] | ||
810 | 137..163: expected &Bar<[usize]>, got &Bar<[i32; 3]> | ||
811 | "#]], | ||
812 | ); | 384 | ); |
813 | } | 385 | } |
814 | 386 | ||
815 | #[test] | 387 | #[test] |
816 | fn coerce_unsize_apit() { | 388 | fn coerce_unsize_apit() { |
817 | // FIXME: #8984 | 389 | // FIXME: #8984 |
818 | check_infer_with_mismatches( | 390 | check( |
819 | r#" | 391 | r#" |
820 | //- minicore: coerce_unsized | 392 | //- minicore: coerce_unsized |
821 | trait Foo {} | 393 | trait Foo {} |
822 | 394 | ||
823 | fn test(f: impl Foo) { | 395 | fn test(f: impl Foo) { |
824 | let _: &dyn Foo = &f; | 396 | let _: &dyn Foo = &f; |
397 | //^^ expected &dyn Foo, got &impl Foo | ||
825 | } | 398 | } |
826 | "#, | 399 | "#, |
827 | expect![[r#" | ||
828 | 22..23 'f': impl Foo | ||
829 | 35..64 '{ ... &f; }': () | ||
830 | 45..46 '_': &dyn Foo | ||
831 | 59..61 '&f': &impl Foo | ||
832 | 60..61 'f': impl Foo | ||
833 | 59..61: expected &dyn Foo, got &impl Foo | ||
834 | "#]], | ||
835 | ); | 400 | ); |
836 | } | 401 | } |
837 | 402 | ||
838 | #[test] | 403 | #[test] |
839 | fn infer_two_closures_lub() { | 404 | fn two_closures_lub() { |
840 | check_types( | 405 | check_types( |
841 | r#" | 406 | r#" |
842 | fn foo(c: i32) { | 407 | fn foo(c: i32) { |
843 | let add = |a: i32, b: i32| a + b; | 408 | let add = |a: i32, b: i32| a + b; |
844 | let sub = |a, b| a - b; | 409 | let sub = |a, b| a - b; |
845 | //^ |i32, i32| -> i32 | 410 | //^^^^^^^^^^^^ |i32, i32| -> i32 |
846 | if c > 42 { add } else { sub }; | 411 | if c > 42 { add } else { sub }; |
847 | //^ fn(i32, i32) -> i32 | 412 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32 |
848 | } | 413 | } |
849 | "#, | 414 | "#, |
850 | ) | 415 | ) |
851 | } | 416 | } |
852 | 417 | ||
853 | #[test] | 418 | #[test] |
854 | fn infer_match_diverging_branch_1() { | 419 | fn match_diverging_branch_1() { |
855 | check_types( | 420 | check_types( |
856 | r#" | 421 | r#" |
857 | enum Result<T> { Ok(T), Err } | 422 | enum Result<T> { Ok(T), Err } |
@@ -870,7 +435,7 @@ fn test() -> i32 { | |||
870 | } | 435 | } |
871 | 436 | ||
872 | #[test] | 437 | #[test] |
873 | fn infer_match_diverging_branch_2() { | 438 | fn match_diverging_branch_2() { |
874 | // same as 1 except for order of branches | 439 | // same as 1 except for order of branches |
875 | check_types( | 440 | check_types( |
876 | r#" | 441 | r#" |
diff --git a/crates/hir_ty/src/tests/display_source_code.rs b/crates/hir_ty/src/tests/display_source_code.rs index 3d29021aa..058cd02d7 100644 --- a/crates/hir_ty/src/tests/display_source_code.rs +++ b/crates/hir_ty/src/tests/display_source_code.rs | |||
@@ -10,8 +10,8 @@ mod foo { | |||
10 | 10 | ||
11 | fn bar() { | 11 | fn bar() { |
12 | let foo: foo::Foo = foo::Foo; | 12 | let foo: foo::Foo = foo::Foo; |
13 | foo | 13 | foo; |
14 | } //^ foo::Foo | 14 | } //^^^ foo::Foo |
15 | 15 | ||
16 | "#, | 16 | "#, |
17 | ); | 17 | ); |
@@ -25,7 +25,7 @@ struct Foo<T = u8> { t: T } | |||
25 | fn main() { | 25 | fn main() { |
26 | let foo = Foo { t: 5u8 }; | 26 | let foo = Foo { t: 5u8 }; |
27 | foo; | 27 | foo; |
28 | } //^ Foo | 28 | } //^^^ Foo |
29 | "#, | 29 | "#, |
30 | ); | 30 | ); |
31 | 31 | ||
@@ -35,7 +35,7 @@ struct Foo<K, T = u8> { k: K, t: T } | |||
35 | fn main() { | 35 | fn main() { |
36 | let foo = Foo { k: 400, t: 5u8 }; | 36 | let foo = Foo { k: 400, t: 5u8 }; |
37 | foo; | 37 | foo; |
38 | } //^ Foo<i32> | 38 | } //^^^ Foo<i32> |
39 | "#, | 39 | "#, |
40 | ); | 40 | ); |
41 | } | 41 | } |
@@ -50,7 +50,7 @@ fn foo() -> *const (impl Unpin + Sized) { loop {} } | |||
50 | fn main() { | 50 | fn main() { |
51 | let foo = foo(); | 51 | let foo = foo(); |
52 | foo; | 52 | foo; |
53 | } //^ *const (impl Unpin + Sized) | 53 | } //^^^ *const (impl Unpin + Sized) |
54 | "#, | 54 | "#, |
55 | ); | 55 | ); |
56 | } | 56 | } |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index d14103aab..2cf41e49e 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -435,11 +435,11 @@ fn processes_impls_generated_by_macros() { | |||
435 | macro_rules! m { | 435 | macro_rules! m { |
436 | ($ident:ident) => (impl Trait for $ident {}) | 436 | ($ident:ident) => (impl Trait for $ident {}) |
437 | } | 437 | } |
438 | trait Trait { fn foo(self) -> u128 {} } | 438 | trait Trait { fn foo(self) -> u128 { 0 } } |
439 | struct S; | 439 | struct S; |
440 | m!(S); | 440 | m!(S); |
441 | fn test() { S.foo(); } | 441 | fn test() { S.foo(); } |
442 | //^ u128 | 442 | //^^^^^^^ u128 |
443 | "#, | 443 | "#, |
444 | ); | 444 | ); |
445 | } | 445 | } |
@@ -457,7 +457,7 @@ impl S { | |||
457 | } | 457 | } |
458 | 458 | ||
459 | fn test() { S.foo(); } | 459 | fn test() { S.foo(); } |
460 | //^ u128 | 460 | //^^^^^^^ u128 |
461 | "#, | 461 | "#, |
462 | ); | 462 | ); |
463 | } | 463 | } |
@@ -479,7 +479,7 @@ impl S { | |||
479 | } | 479 | } |
480 | 480 | ||
481 | fn test() { S.foo(); } | 481 | fn test() { S.foo(); } |
482 | //^ u128 | 482 | //^^^^^^^ u128 |
483 | "#, | 483 | "#, |
484 | ); | 484 | ); |
485 | } | 485 | } |
@@ -743,7 +743,7 @@ include!("foo.rs"); | |||
743 | 743 | ||
744 | fn main() { | 744 | fn main() { |
745 | bar(); | 745 | bar(); |
746 | } //^ u32 | 746 | } //^^^^^ u32 |
747 | 747 | ||
748 | //- /foo.rs | 748 | //- /foo.rs |
749 | fn bar() -> u32 {0} | 749 | fn bar() -> u32 {0} |
@@ -781,7 +781,7 @@ include!("f/foo.rs"); | |||
781 | 781 | ||
782 | fn main() { | 782 | fn main() { |
783 | bar::bar(); | 783 | bar::bar(); |
784 | } //^ u32 | 784 | } //^^^^^^^^^^ u32 |
785 | 785 | ||
786 | //- /f/foo.rs | 786 | //- /f/foo.rs |
787 | pub mod bar; | 787 | pub mod bar; |
@@ -853,7 +853,7 @@ include!("foo.rs"); | |||
853 | 853 | ||
854 | fn main() { | 854 | fn main() { |
855 | RegisterBlock { }; | 855 | RegisterBlock { }; |
856 | //^ RegisterBlock | 856 | //^^^^^^^^^^^^^^^^^ RegisterBlock |
857 | } | 857 | } |
858 | "#; | 858 | "#; |
859 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data); | 859 | let fixture = format!("{}\n//- /foo.rs\n{}", fixture, data); |
@@ -879,7 +879,7 @@ include!(concat!("f", "oo.rs")); | |||
879 | 879 | ||
880 | fn main() { | 880 | fn main() { |
881 | bar(); | 881 | bar(); |
882 | } //^ u32 | 882 | } //^^^^^ u32 |
883 | 883 | ||
884 | //- /foo.rs | 884 | //- /foo.rs |
885 | fn bar() -> u32 {0} | 885 | fn bar() -> u32 {0} |
@@ -905,7 +905,7 @@ include!(concat!(env!("OUT_DIR"), "/foo.rs")); | |||
905 | 905 | ||
906 | fn main() { | 906 | fn main() { |
907 | bar(); | 907 | bar(); |
908 | } //^ {unknown} | 908 | } //^^^^^ {unknown} |
909 | 909 | ||
910 | //- /foo.rs | 910 | //- /foo.rs |
911 | fn bar() -> u32 {0} | 911 | fn bar() -> u32 {0} |
@@ -923,7 +923,7 @@ macro_rules! include {() => {}} | |||
923 | include!("main.rs"); | 923 | include!("main.rs"); |
924 | 924 | ||
925 | fn main() { | 925 | fn main() { |
926 | 0 | 926 | 0; |
927 | } //^ i32 | 927 | } //^ i32 |
928 | "#, | 928 | "#, |
929 | ); | 929 | ); |
@@ -979,7 +979,7 @@ fn infer_derive_clone_simple() { | |||
979 | struct S; | 979 | struct S; |
980 | fn test() { | 980 | fn test() { |
981 | S.clone(); | 981 | S.clone(); |
982 | } //^ S | 982 | } //^^^^^^^^^ S |
983 | 983 | ||
984 | //- /lib.rs crate:core | 984 | //- /lib.rs crate:core |
985 | pub mod prelude { | 985 | pub mod prelude { |
@@ -1028,7 +1028,7 @@ pub struct S; | |||
1028 | use core::S; | 1028 | use core::S; |
1029 | fn test() { | 1029 | fn test() { |
1030 | S.clone(); | 1030 | S.clone(); |
1031 | } //^ S | 1031 | } //^^^^^^^^^ S |
1032 | "#, | 1032 | "#, |
1033 | ); | 1033 | ); |
1034 | } | 1034 | } |
@@ -1044,7 +1044,8 @@ struct S; | |||
1044 | struct Wrapper<T>(T); | 1044 | struct Wrapper<T>(T); |
1045 | struct NonClone; | 1045 | struct NonClone; |
1046 | fn test() { | 1046 | fn test() { |
1047 | (Wrapper(S).clone(), Wrapper(NonClone).clone()); | 1047 | let x = (Wrapper(S).clone(), Wrapper(NonClone).clone()); |
1048 | x; | ||
1048 | //^ (Wrapper<S>, {unknown}) | 1049 | //^ (Wrapper<S>, {unknown}) |
1049 | } | 1050 | } |
1050 | 1051 | ||
@@ -1079,7 +1080,7 @@ struct S{} | |||
1079 | 1080 | ||
1080 | fn test() { | 1081 | fn test() { |
1081 | S{}; | 1082 | S{}; |
1082 | } //^ S | 1083 | } //^^^ S |
1083 | "#, | 1084 | "#, |
1084 | ); | 1085 | ); |
1085 | } | 1086 | } |
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index d9b5ee9cf..3f7a37295 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -257,7 +257,7 @@ fn test() { | |||
257 | mod foo { | 257 | mod foo { |
258 | struct S; | 258 | struct S; |
259 | impl S { | 259 | impl S { |
260 | fn thing() -> i128 {} | 260 | fn thing() -> i128 { 0 } |
261 | } | 261 | } |
262 | } | 262 | } |
263 | "#, | 263 | "#, |
@@ -267,164 +267,128 @@ mod foo { | |||
267 | #[test] | 267 | #[test] |
268 | fn infer_trait_method_simple() { | 268 | fn infer_trait_method_simple() { |
269 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 269 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
270 | check_infer( | 270 | check_types( |
271 | r#" | 271 | r#" |
272 | trait Trait1 { | 272 | trait Trait1 { |
273 | fn method(&self) -> u32; | 273 | fn method(&self) -> u32; |
274 | } | 274 | } |
275 | struct S1; | 275 | struct S1; |
276 | impl Trait1 for S1 {} | 276 | impl Trait1 for S1 {} |
277 | trait Trait2 { | 277 | trait Trait2 { |
278 | fn method(&self) -> i128; | 278 | fn method(&self) -> i128; |
279 | } | 279 | } |
280 | struct S2; | 280 | struct S2; |
281 | impl Trait2 for S2 {} | 281 | impl Trait2 for S2 {} |
282 | fn test() { | 282 | fn test() { |
283 | S1.method(); // -> u32 | 283 | S1.method(); |
284 | S2.method(); // -> i128 | 284 | //^^^^^^^^^^^ u32 |
285 | } | 285 | S2.method(); // -> i128 |
286 | //^^^^^^^^^^^ i128 | ||
287 | } | ||
286 | "#, | 288 | "#, |
287 | expect![[r#" | ||
288 | 30..34 'self': &Self | ||
289 | 109..113 'self': &Self | ||
290 | 169..227 '{ ...i128 }': () | ||
291 | 175..177 'S1': S1 | ||
292 | 175..186 'S1.method()': u32 | ||
293 | 202..204 'S2': S2 | ||
294 | 202..213 'S2.method()': i128 | ||
295 | "#]], | ||
296 | ); | 289 | ); |
297 | } | 290 | } |
298 | 291 | ||
299 | #[test] | 292 | #[test] |
300 | fn infer_trait_method_scoped() { | 293 | fn infer_trait_method_scoped() { |
301 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 294 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
302 | check_infer( | 295 | check_types( |
303 | r#" | 296 | r#" |
304 | struct S; | 297 | struct S; |
305 | mod foo { | 298 | mod foo { |
306 | pub trait Trait1 { | 299 | pub trait Trait1 { |
307 | fn method(&self) -> u32; | 300 | fn method(&self) -> u32; |
308 | } | 301 | } |
309 | impl Trait1 for super::S {} | 302 | impl Trait1 for super::S {} |
310 | } | 303 | } |
311 | mod bar { | 304 | mod bar { |
312 | pub trait Trait2 { | 305 | pub trait Trait2 { |
313 | fn method(&self) -> i128; | 306 | fn method(&self) -> i128; |
314 | } | 307 | } |
315 | impl Trait2 for super::S {} | 308 | impl Trait2 for super::S {} |
316 | } | 309 | } |
317 | 310 | ||
318 | mod foo_test { | 311 | mod foo_test { |
319 | use super::S; | 312 | use super::S; |
320 | use super::foo::Trait1; | 313 | use super::foo::Trait1; |
321 | fn test() { | 314 | fn test() { |
322 | S.method(); // -> u32 | 315 | S.method(); |
323 | } | 316 | //^^^^^^^^^^ u32 |
324 | } | 317 | } |
318 | } | ||
325 | 319 | ||
326 | mod bar_test { | 320 | mod bar_test { |
327 | use super::S; | 321 | use super::S; |
328 | use super::bar::Trait2; | 322 | use super::bar::Trait2; |
329 | fn test() { | 323 | fn test() { |
330 | S.method(); // -> i128 | 324 | S.method(); |
331 | } | 325 | //^^^^^^^^^^ i128 |
332 | } | 326 | } |
327 | } | ||
333 | "#, | 328 | "#, |
334 | expect![[r#" | ||
335 | 62..66 'self': &Self | ||
336 | 168..172 'self': &Self | ||
337 | 299..336 '{ ... }': () | ||
338 | 309..310 'S': S | ||
339 | 309..319 'S.method()': u32 | ||
340 | 415..453 '{ ... }': () | ||
341 | 425..426 'S': S | ||
342 | 425..435 'S.method()': i128 | ||
343 | "#]], | ||
344 | ); | 329 | ); |
345 | } | 330 | } |
346 | 331 | ||
347 | #[test] | 332 | #[test] |
348 | fn infer_trait_method_generic_1() { | 333 | fn infer_trait_method_generic_1() { |
349 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 334 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
350 | check_infer( | 335 | check_types( |
351 | r#" | 336 | r#" |
352 | trait Trait<T> { | 337 | trait Trait<T> { |
353 | fn method(&self) -> T; | 338 | fn method(&self) -> T; |
354 | } | 339 | } |
355 | struct S; | 340 | struct S; |
356 | impl Trait<u32> for S {} | 341 | impl Trait<u32> for S {} |
357 | fn test() { | 342 | fn test() { |
358 | S.method(); | 343 | S.method(); |
359 | } | 344 | //^^^^^^^^^^ u32 |
345 | } | ||
360 | "#, | 346 | "#, |
361 | expect![[r#" | ||
362 | 32..36 'self': &Self | ||
363 | 91..110 '{ ...d(); }': () | ||
364 | 97..98 'S': S | ||
365 | 97..107 'S.method()': u32 | ||
366 | "#]], | ||
367 | ); | 347 | ); |
368 | } | 348 | } |
369 | 349 | ||
370 | #[test] | 350 | #[test] |
371 | fn infer_trait_method_generic_more_params() { | 351 | fn infer_trait_method_generic_more_params() { |
372 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 352 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
373 | check_infer( | 353 | check_types( |
374 | r#" | 354 | r#" |
375 | trait Trait<T1, T2, T3> { | 355 | trait Trait<T1, T2, T3> { |
376 | fn method1(&self) -> (T1, T2, T3); | 356 | fn method1(&self) -> (T1, T2, T3); |
377 | fn method2(&self) -> (T3, T2, T1); | 357 | fn method2(&self) -> (T3, T2, T1); |
378 | } | 358 | } |
379 | struct S1; | 359 | struct S1; |
380 | impl Trait<u8, u16, u32> for S1 {} | 360 | impl Trait<u8, u16, u32> for S1 {} |
381 | struct S2; | 361 | struct S2; |
382 | impl<T> Trait<i8, i16, T> for S2 {} | 362 | impl<T> Trait<i8, i16, T> for S2 {} |
383 | fn test() { | 363 | fn test() { |
384 | S1.method1(); // u8, u16, u32 | 364 | S1.method1(); |
385 | S1.method2(); // u32, u16, u8 | 365 | //^^^^^^^^^^^^ (u8, u16, u32) |
386 | S2.method1(); // i8, i16, {unknown} | 366 | S1.method2(); |
387 | S2.method2(); // {unknown}, i16, i8 | 367 | //^^^^^^^^^^^^ (u32, u16, u8) |
388 | } | 368 | S2.method1(); |
369 | //^^^^^^^^^^^^ (i8, i16, {unknown}) | ||
370 | S2.method2(); | ||
371 | //^^^^^^^^^^^^ ({unknown}, i16, i8) | ||
372 | } | ||
389 | "#, | 373 | "#, |
390 | expect![[r#" | ||
391 | 42..46 'self': &Self | ||
392 | 81..85 'self': &Self | ||
393 | 209..360 '{ ..., i8 }': () | ||
394 | 215..217 'S1': S1 | ||
395 | 215..227 'S1.method1()': (u8, u16, u32) | ||
396 | 249..251 'S1': S1 | ||
397 | 249..261 'S1.method2()': (u32, u16, u8) | ||
398 | 283..285 'S2': S2 | ||
399 | 283..295 'S2.method1()': (i8, i16, {unknown}) | ||
400 | 323..325 'S2': S2 | ||
401 | 323..335 'S2.method2()': ({unknown}, i16, i8) | ||
402 | "#]], | ||
403 | ); | 374 | ); |
404 | } | 375 | } |
405 | 376 | ||
406 | #[test] | 377 | #[test] |
407 | fn infer_trait_method_generic_2() { | 378 | fn infer_trait_method_generic_2() { |
408 | // the trait implementation is intentionally incomplete -- it shouldn't matter | 379 | // the trait implementation is intentionally incomplete -- it shouldn't matter |
409 | check_infer( | 380 | check_types( |
410 | r#" | 381 | r#" |
411 | trait Trait<T> { | 382 | trait Trait<T> { |
412 | fn method(&self) -> T; | 383 | fn method(&self) -> T; |
413 | } | 384 | } |
414 | struct S<T>(T); | 385 | struct S<T>(T); |
415 | impl<U> Trait<U> for S<U> {} | 386 | impl<U> Trait<U> for S<U> {} |
416 | fn test() { | 387 | fn test() { |
417 | S(1u32).method(); | 388 | S(1u32).method(); |
418 | } | 389 | //^^^^^^^^^^^^^^^^ u32 |
390 | } | ||
419 | "#, | 391 | "#, |
420 | expect![[r#" | ||
421 | 32..36 'self': &Self | ||
422 | 101..126 '{ ...d(); }': () | ||
423 | 107..108 'S': S<u32>(u32) -> S<u32> | ||
424 | 107..114 'S(1u32)': S<u32> | ||
425 | 107..123 'S(1u32...thod()': u32 | ||
426 | 109..113 '1u32': u32 | ||
427 | "#]], | ||
428 | ); | 392 | ); |
429 | } | 393 | } |
430 | 394 | ||
@@ -685,10 +649,10 @@ fn method_resolution_unify_impl_self_type() { | |||
685 | check_types( | 649 | check_types( |
686 | r#" | 650 | r#" |
687 | struct S<T>; | 651 | struct S<T>; |
688 | impl S<u32> { fn foo(&self) -> u8 {} } | 652 | impl S<u32> { fn foo(&self) -> u8 { 0 } } |
689 | impl S<i32> { fn foo(&self) -> i8 {} } | 653 | impl S<i32> { fn foo(&self) -> i8 { 0 } } |
690 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } | 654 | fn test() { (S::<u32>.foo(), S::<i32>.foo()); } |
691 | //^ (u8, i8) | 655 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (u8, i8) |
692 | "#, | 656 | "#, |
693 | ); | 657 | ); |
694 | } | 658 | } |
@@ -702,7 +666,7 @@ struct S; | |||
702 | impl S { fn foo(&self) -> i8 { 0 } } | 666 | impl S { fn foo(&self) -> i8 { 0 } } |
703 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 667 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
704 | fn test() { S.foo(); } | 668 | fn test() { S.foo(); } |
705 | //^ u128 | 669 | //^^^^^^^ u128 |
706 | "#, | 670 | "#, |
707 | ); | 671 | ); |
708 | } | 672 | } |
@@ -716,7 +680,7 @@ struct S; | |||
716 | impl Clone for S {} | 680 | impl Clone for S {} |
717 | impl Clone for &S {} | 681 | impl Clone for &S {} |
718 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } | 682 | fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } |
719 | //^ (S, S, &S) | 683 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (S, S, &S) |
720 | "#, | 684 | "#, |
721 | ); | 685 | ); |
722 | } | 686 | } |
@@ -730,7 +694,7 @@ struct S; | |||
730 | impl S { fn foo(self) -> i8 { 0 } } | 694 | impl S { fn foo(self) -> i8 { 0 } } |
731 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 695 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
732 | fn test() { (&S).foo(); } | 696 | fn test() { (&S).foo(); } |
733 | //^ u128 | 697 | //^^^^^^^^^^ u128 |
734 | "#, | 698 | "#, |
735 | ); | 699 | ); |
736 | } | 700 | } |
@@ -744,7 +708,7 @@ struct S; | |||
744 | impl S { fn foo(self) -> i8 { 0 } } | 708 | impl S { fn foo(self) -> i8 { 0 } } |
745 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 709 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
746 | fn test() { S.foo(); } | 710 | fn test() { S.foo(); } |
747 | //^ i8 | 711 | //^^^^^^^ i8 |
748 | "#, | 712 | "#, |
749 | ); | 713 | ); |
750 | } | 714 | } |
@@ -758,7 +722,7 @@ struct S; | |||
758 | impl S { fn foo(&self) -> i8 { 0 } } | 722 | impl S { fn foo(&self) -> i8 { 0 } } |
759 | impl Trait for &S { fn foo(self) -> u128 { 0 } } | 723 | impl Trait for &S { fn foo(self) -> u128 { 0 } } |
760 | fn test() { S.foo(); } | 724 | fn test() { S.foo(); } |
761 | //^ i8 | 725 | //^^^^^^^ i8 |
762 | "#, | 726 | "#, |
763 | ); | 727 | ); |
764 | } | 728 | } |
@@ -771,7 +735,7 @@ trait Trait { fn foo(self) -> u128; } | |||
771 | struct S; | 735 | struct S; |
772 | impl Trait for S { fn foo(self) -> u128 { 0 } } | 736 | impl Trait for S { fn foo(self) -> u128 { 0 } } |
773 | fn test() { (&S).foo(); } | 737 | fn test() { (&S).foo(); } |
774 | //^ u128 | 738 | //^^^^^^^^^^ u128 |
775 | "#, | 739 | "#, |
776 | ); | 740 | ); |
777 | } | 741 | } |
@@ -784,7 +748,7 @@ fn method_resolution_unsize_array() { | |||
784 | fn test() { | 748 | fn test() { |
785 | let a = [1, 2, 3]; | 749 | let a = [1, 2, 3]; |
786 | a.len(); | 750 | a.len(); |
787 | } //^ usize | 751 | } //^^^^^^^ usize |
788 | "#, | 752 | "#, |
789 | ); | 753 | ); |
790 | } | 754 | } |
@@ -799,7 +763,7 @@ impl Clone for S {} | |||
799 | 763 | ||
800 | fn test() { | 764 | fn test() { |
801 | S.clone(); | 765 | S.clone(); |
802 | //^ S | 766 | //^^^^^^^^^ S |
803 | } | 767 | } |
804 | 768 | ||
805 | //- /lib.rs crate:core | 769 | //- /lib.rs crate:core |
@@ -823,7 +787,7 @@ trait Trait { fn foo(self) -> u128; } | |||
823 | struct S; | 787 | struct S; |
824 | impl<T> Trait for T where T: UnknownTrait {} | 788 | impl<T> Trait for T where T: UnknownTrait {} |
825 | fn test() { (&S).foo(); } | 789 | fn test() { (&S).foo(); } |
826 | //^ u128 | 790 | //^^^^^^^^^^ u128 |
827 | "#, | 791 | "#, |
828 | ); | 792 | ); |
829 | } | 793 | } |
@@ -841,7 +805,7 @@ trait Trait { fn foo(self) -> u128; } | |||
841 | struct S; | 805 | struct S; |
842 | impl<T> Trait for T where T: Clone {} | 806 | impl<T> Trait for T where T: Clone {} |
843 | fn test() { (&S).foo(); } | 807 | fn test() { (&S).foo(); } |
844 | //^ {unknown} | 808 | //^^^^^^^^^^ {unknown} |
845 | "#, | 809 | "#, |
846 | ); | 810 | ); |
847 | } | 811 | } |
@@ -856,7 +820,7 @@ trait Trait { fn foo(self) -> u128; } | |||
856 | struct S; | 820 | struct S; |
857 | impl<T: Clone> Trait for T {} | 821 | impl<T: Clone> Trait for T {} |
858 | fn test() { (&S).foo(); } | 822 | fn test() { (&S).foo(); } |
859 | //^ {unknown} | 823 | //^^^^^^^^^^ {unknown} |
860 | "#, | 824 | "#, |
861 | ); | 825 | ); |
862 | } | 826 | } |
@@ -871,7 +835,7 @@ struct S; | |||
871 | impl Clone for S {} | 835 | impl Clone for S {} |
872 | impl<T> Trait for T where T: Clone {} | 836 | impl<T> Trait for T where T: Clone {} |
873 | fn test() { S.foo(); } | 837 | fn test() { S.foo(); } |
874 | //^ u128 | 838 | //^^^^^^^ u128 |
875 | "#, | 839 | "#, |
876 | ); | 840 | ); |
877 | } | 841 | } |
@@ -887,7 +851,7 @@ struct S2; | |||
887 | impl From<S2> for S1 {} | 851 | impl From<S2> for S1 {} |
888 | impl<T, U> Into<U> for T where U: From<T> {} | 852 | impl<T, U> Into<U> for T where U: From<T> {} |
889 | fn test() { S2.into(); } | 853 | fn test() { S2.into(); } |
890 | //^ {unknown} | 854 | //^^^^^^^^^ {unknown} |
891 | "#, | 855 | "#, |
892 | ); | 856 | ); |
893 | } | 857 | } |
@@ -903,7 +867,7 @@ struct S2; | |||
903 | impl From<S2> for S1 {} | 867 | impl From<S2> for S1 {} |
904 | impl<T, U: From<T>> Into<U> for T {} | 868 | impl<T, U: From<T>> Into<U> for T {} |
905 | fn test() { S2.into(); } | 869 | fn test() { S2.into(); } |
906 | //^ {unknown} | 870 | //^^^^^^^^^ {unknown} |
907 | "#, | 871 | "#, |
908 | ); | 872 | ); |
909 | } | 873 | } |
@@ -933,7 +897,7 @@ fn main() { | |||
933 | let a = Wrapper::<Foo<f32>>::new(1.0); | 897 | let a = Wrapper::<Foo<f32>>::new(1.0); |
934 | let b = Wrapper::<Bar<f32>>::new(1.0); | 898 | let b = Wrapper::<Bar<f32>>::new(1.0); |
935 | (a, b); | 899 | (a, b); |
936 | //^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) | 900 | //^^^^^^ (Wrapper<Foo<f32>>, Wrapper<Bar<f32>>) |
937 | } | 901 | } |
938 | "#, | 902 | "#, |
939 | ); | 903 | ); |
@@ -947,7 +911,7 @@ fn method_resolution_encountering_fn_type() { | |||
947 | fn foo() {} | 911 | fn foo() {} |
948 | trait FnOnce { fn call(self); } | 912 | trait FnOnce { fn call(self); } |
949 | fn test() { foo.call(); } | 913 | fn test() { foo.call(); } |
950 | //^ {unknown} | 914 | //^^^^^^^^^^ {unknown} |
951 | "#, | 915 | "#, |
952 | ); | 916 | ); |
953 | } | 917 | } |
@@ -1013,7 +977,7 @@ where | |||
1013 | Wrapper<T>: a::Foo, | 977 | Wrapper<T>: a::Foo, |
1014 | { | 978 | { |
1015 | t.foo(); | 979 | t.foo(); |
1016 | } //^ {unknown} | 980 | } //^^^^^^^ {unknown} |
1017 | "#, | 981 | "#, |
1018 | ); | 982 | ); |
1019 | } | 983 | } |
@@ -1030,7 +994,7 @@ impl A<i32> { | |||
1030 | 994 | ||
1031 | fn main() { | 995 | fn main() { |
1032 | A::from(3); | 996 | A::from(3); |
1033 | } //^ A<i32> | 997 | } //^^^^^^^^^^ A<i32> |
1034 | "#, | 998 | "#, |
1035 | ); | 999 | ); |
1036 | } | 1000 | } |
@@ -1058,7 +1022,7 @@ trait FnX {} | |||
1058 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} | 1022 | impl<B, C> Trait for S<B, C> where C: FnX, B: SendX {} |
1059 | 1023 | ||
1060 | fn test() { (S {}).method(); } | 1024 | fn test() { (S {}).method(); } |
1061 | //^ () | 1025 | //^^^^^^^^^^^^^^^ () |
1062 | "#, | 1026 | "#, |
1063 | ); | 1027 | ); |
1064 | } | 1028 | } |
@@ -1143,8 +1107,8 @@ impl<T> Slice<T> { | |||
1143 | 1107 | ||
1144 | fn main() { | 1108 | fn main() { |
1145 | let foo: Slice<u32>; | 1109 | let foo: Slice<u32>; |
1146 | (foo.into_vec()); // we don't actually support arbitrary self types, but we shouldn't crash at least | 1110 | foo.into_vec(); // we shouldn't crash on this at least |
1147 | } //^ {unknown} | 1111 | } //^^^^^^^^^^^^^^ {unknown} |
1148 | "#, | 1112 | "#, |
1149 | ); | 1113 | ); |
1150 | } | 1114 | } |
@@ -1165,7 +1129,7 @@ impl dyn Foo + '_ { | |||
1165 | fn main() { | 1129 | fn main() { |
1166 | let f = &42u32 as &dyn Foo; | 1130 | let f = &42u32 as &dyn Foo; |
1167 | f.dyn_foo(); | 1131 | f.dyn_foo(); |
1168 | // ^u32 | 1132 | // ^^^^^^^^^^^ u32 |
1169 | } | 1133 | } |
1170 | "#, | 1134 | "#, |
1171 | ); | 1135 | ); |
@@ -1376,11 +1340,11 @@ pub trait IntoIterator { | |||
1376 | 1340 | ||
1377 | impl<T> IntoIterator for [T; 1] { | 1341 | impl<T> IntoIterator for [T; 1] { |
1378 | type Out = T; | 1342 | type Out = T; |
1379 | fn into_iter(self) -> Self::Out {} | 1343 | fn into_iter(self) -> Self::Out { loop {} } |
1380 | } | 1344 | } |
1381 | impl<'a, T> IntoIterator for &'a [T] { | 1345 | impl<'a, T> IntoIterator for &'a [T] { |
1382 | type Out = &'a T; | 1346 | type Out = &'a T; |
1383 | fn into_iter(self) -> Self::Out {} | 1347 | fn into_iter(self) -> Self::Out { loop {} } |
1384 | } | 1348 | } |
1385 | "#, | 1349 | "#, |
1386 | ); | 1350 | ); |
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index 5adbe9c45..47aa30d2e 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use expect_test::expect; | 1 | use expect_test::expect; |
2 | 2 | ||
3 | use super::{check_infer, check_infer_with_mismatches, check_mismatches, check_types}; | 3 | use super::{check, check_infer, check_infer_with_mismatches, check_types}; |
4 | 4 | ||
5 | #[test] | 5 | #[test] |
6 | fn infer_pattern() { | 6 | fn infer_pattern() { |
@@ -518,7 +518,7 @@ fn infer_generics_in_patterns() { | |||
518 | 518 | ||
519 | #[test] | 519 | #[test] |
520 | fn infer_const_pattern() { | 520 | fn infer_const_pattern() { |
521 | check_mismatches( | 521 | check( |
522 | r#" | 522 | r#" |
523 | enum Option<T> { None } | 523 | enum Option<T> { None } |
524 | use Option::None; | 524 | use Option::None; |
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 0f418ea49..8c5e8954c 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use expect_test::expect; | 1 | use expect_test::expect; |
2 | 2 | ||
3 | use super::{check_infer, check_types}; | 3 | use super::{check_infer, check_no_mismatches, check_types}; |
4 | 4 | ||
5 | #[test] | 5 | #[test] |
6 | fn bug_484() { | 6 | fn bug_484() { |
@@ -422,20 +422,20 @@ fn issue_2683_chars_impl() { | |||
422 | pub struct Chars<'a> {} | 422 | pub struct Chars<'a> {} |
423 | impl<'a> Iterator for Chars<'a> { | 423 | impl<'a> Iterator for Chars<'a> { |
424 | type Item = char; | 424 | type Item = char; |
425 | fn next(&mut self) -> Option<char> {} | 425 | fn next(&mut self) -> Option<char> { loop {} } |
426 | } | 426 | } |
427 | 427 | ||
428 | fn test() { | 428 | fn test() { |
429 | let chars: Chars<'_>; | 429 | let chars: Chars<'_>; |
430 | (chars.next(), chars.nth(1)); | 430 | (chars.next(), chars.nth(1)); |
431 | } //^ (Option<char>, Option<char>) | 431 | } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (Option<char>, Option<char>) |
432 | "#, | 432 | "#, |
433 | ); | 433 | ); |
434 | } | 434 | } |
435 | 435 | ||
436 | #[test] | 436 | #[test] |
437 | fn issue_3642_bad_macro_stackover() { | 437 | fn issue_3642_bad_macro_stackover() { |
438 | check_types( | 438 | check_no_mismatches( |
439 | r#" | 439 | r#" |
440 | #[macro_export] | 440 | #[macro_export] |
441 | macro_rules! match_ast { | 441 | macro_rules! match_ast { |
@@ -452,7 +452,6 @@ macro_rules! match_ast { | |||
452 | 452 | ||
453 | fn main() { | 453 | fn main() { |
454 | let anchor = match_ast! { | 454 | let anchor = match_ast! { |
455 | //^ () | ||
456 | match parent { | 455 | match parent { |
457 | as => {}, | 456 | as => {}, |
458 | _ => return None | 457 | _ => return None |
@@ -956,7 +955,7 @@ trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> { | |||
956 | 955 | ||
957 | fn clone_iter<T>(s: Iter<T>) { | 956 | fn clone_iter<T>(s: Iter<T>) { |
958 | s.inner.clone_box(); | 957 | s.inner.clone_box(); |
959 | //^^^^^^^^^^^^^^^^^^^ () | 958 | //^^^^^^^^^^^^^^^^^^^ () |
960 | } | 959 | } |
961 | "#, | 960 | "#, |
962 | ) | 961 | ) |
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 108ff3179..b4bcc6d95 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -60,7 +60,7 @@ enum Nat { Succ(Self), Demo(Nat), Zero } | |||
60 | fn test() { | 60 | fn test() { |
61 | let foo: Nat = Nat::Zero; | 61 | let foo: Nat = Nat::Zero; |
62 | if let Nat::Succ(x) = foo { | 62 | if let Nat::Succ(x) = foo { |
63 | x | 63 | x; |
64 | } //^ Nat | 64 | } //^ Nat |
65 | } | 65 | } |
66 | "#, | 66 | "#, |
@@ -138,7 +138,7 @@ enum Option<T> { Some(T), None } | |||
138 | fn test() { | 138 | fn test() { |
139 | let foo: Option<f32> = None; | 139 | let foo: Option<f32> = None; |
140 | while let Option::Some(x) = foo { | 140 | while let Option::Some(x) = foo { |
141 | x | 141 | x; |
142 | } //^ f32 | 142 | } //^ f32 |
143 | } | 143 | } |
144 | "#, | 144 | "#, |
@@ -1745,7 +1745,7 @@ impl i32 { fn foo(&self) -> Foo { Foo } } | |||
1745 | fn main() { | 1745 | fn main() { |
1746 | let x: i32 = i32; | 1746 | let x: i32 = i32; |
1747 | x.foo(); | 1747 | x.foo(); |
1748 | //^ Foo | 1748 | //^^^^^^^ Foo |
1749 | }"#, | 1749 | }"#, |
1750 | ); | 1750 | ); |
1751 | } | 1751 | } |
@@ -1763,7 +1763,7 @@ fn main() { | |||
1763 | fn inner() {} | 1763 | fn inner() {} |
1764 | let x: i32 = i32; | 1764 | let x: i32 = i32; |
1765 | x.foo(); | 1765 | x.foo(); |
1766 | //^ Foo | 1766 | //^^^^^^^ Foo |
1767 | }"#, | 1767 | }"#, |
1768 | ); | 1768 | ); |
1769 | } | 1769 | } |
@@ -1781,7 +1781,7 @@ fn foo() -> &'static str { "" } | |||
1781 | 1781 | ||
1782 | fn main() { | 1782 | fn main() { |
1783 | foo(); | 1783 | foo(); |
1784 | //^ &str | 1784 | //^^^^^ &str |
1785 | }"#, | 1785 | }"#, |
1786 | ); | 1786 | ); |
1787 | } | 1787 | } |
@@ -1799,7 +1799,7 @@ fn foo() -> &'static str { "" } | |||
1799 | 1799 | ||
1800 | fn main() { | 1800 | fn main() { |
1801 | str::foo(); | 1801 | str::foo(); |
1802 | //^ u32 | 1802 | //^^^^^^^^^^ u32 |
1803 | }"#, | 1803 | }"#, |
1804 | ); | 1804 | ); |
1805 | } | 1805 | } |
@@ -1825,9 +1825,9 @@ mod d { | |||
1825 | 1825 | ||
1826 | fn main() { | 1826 | fn main() { |
1827 | d::foo(); | 1827 | d::foo(); |
1828 | //^ u8 | 1828 | //^^^^^^^^ u8 |
1829 | d::foo{a:0}; | 1829 | d::foo{a:0}; |
1830 | //^ u8 | 1830 | //^^^^^^^^^^^ foo |
1831 | }"#, | 1831 | }"#, |
1832 | ); | 1832 | ); |
1833 | } | 1833 | } |
@@ -2677,7 +2677,7 @@ fn prelude_2015() { | |||
2677 | //- /main.rs edition:2015 crate:main deps:core | 2677 | //- /main.rs edition:2015 crate:main deps:core |
2678 | fn f() { | 2678 | fn f() { |
2679 | Rust; | 2679 | Rust; |
2680 | //^ Rust | 2680 | //^^^^ Rust |
2681 | } | 2681 | } |
2682 | 2682 | ||
2683 | //- /core.rs crate:core | 2683 | //- /core.rs crate:core |
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 279a1354a..a0ddad570 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -1,6 +1,7 @@ | |||
1 | use cov_mark::check; | ||
1 | use expect_test::expect; | 2 | use expect_test::expect; |
2 | 3 | ||
3 | use super::{check_infer, check_infer_with_mismatches, check_types}; | 4 | use super::{check, check_infer, check_infer_with_mismatches, check_types}; |
4 | 5 | ||
5 | #[test] | 6 | #[test] |
6 | fn infer_await() { | 7 | fn infer_await() { |
@@ -285,7 +286,7 @@ mod ops { | |||
285 | 286 | ||
286 | #[test] | 287 | #[test] |
287 | fn infer_from_bound_1() { | 288 | fn infer_from_bound_1() { |
288 | check_infer( | 289 | check_types( |
289 | r#" | 290 | r#" |
290 | trait Trait<T> {} | 291 | trait Trait<T> {} |
291 | struct S<T>(T); | 292 | struct S<T>(T); |
@@ -293,99 +294,62 @@ impl<U> Trait<U> for S<U> {} | |||
293 | fn foo<T: Trait<u32>>(t: T) {} | 294 | fn foo<T: Trait<u32>>(t: T) {} |
294 | fn test() { | 295 | fn test() { |
295 | let s = S(unknown); | 296 | let s = S(unknown); |
297 | // ^^^^^^^ u32 | ||
296 | foo(s); | 298 | foo(s); |
297 | }"#, | 299 | }"#, |
298 | expect![[r#" | ||
299 | 85..86 't': T | ||
300 | 91..93 '{}': () | ||
301 | 104..143 '{ ...(s); }': () | ||
302 | 114..115 's': S<u32> | ||
303 | 118..119 'S': S<u32>(u32) -> S<u32> | ||
304 | 118..128 'S(unknown)': S<u32> | ||
305 | 120..127 'unknown': u32 | ||
306 | 134..137 'foo': fn foo<S<u32>>(S<u32>) | ||
307 | 134..140 'foo(s)': () | ||
308 | 138..139 's': S<u32> | ||
309 | "#]], | ||
310 | ); | 300 | ); |
311 | } | 301 | } |
312 | 302 | ||
313 | #[test] | 303 | #[test] |
314 | fn infer_from_bound_2() { | 304 | fn infer_from_bound_2() { |
315 | check_infer( | 305 | check_types( |
316 | r#" | 306 | r#" |
317 | trait Trait<T> {} | 307 | trait Trait<T> {} |
318 | struct S<T>(T); | 308 | struct S<T>(T); |
319 | impl<U> Trait<U> for S<U> {} | 309 | impl<U> Trait<U> for S<U> {} |
320 | fn foo<U, T: Trait<U>>(t: T) -> U {} | 310 | fn foo<U, T: Trait<U>>(t: T) -> U { loop {} } |
321 | fn test() { | 311 | fn test() { |
322 | let s = S(unknown); | 312 | let s = S(unknown); |
313 | // ^^^^^^^ u32 | ||
323 | let x: u32 = foo(s); | 314 | let x: u32 = foo(s); |
324 | }"#, | 315 | }"#, |
325 | expect![[r#" | ||
326 | 86..87 't': T | ||
327 | 97..99 '{}': () | ||
328 | 110..162 '{ ...(s); }': () | ||
329 | 120..121 's': S<u32> | ||
330 | 124..125 'S': S<u32>(u32) -> S<u32> | ||
331 | 124..134 'S(unknown)': S<u32> | ||
332 | 126..133 'unknown': u32 | ||
333 | 144..145 'x': u32 | ||
334 | 153..156 'foo': fn foo<u32, S<u32>>(S<u32>) -> u32 | ||
335 | 153..159 'foo(s)': u32 | ||
336 | 157..158 's': S<u32> | ||
337 | "#]], | ||
338 | ); | 316 | ); |
339 | } | 317 | } |
340 | 318 | ||
341 | #[test] | 319 | #[test] |
342 | fn trait_default_method_self_bound_implements_trait() { | 320 | fn trait_default_method_self_bound_implements_trait() { |
343 | cov_mark::check!(trait_self_implements_self); | 321 | cov_mark::check!(trait_self_implements_self); |
344 | check_infer( | 322 | check( |
345 | r#" | 323 | r#" |
346 | trait Trait { | 324 | trait Trait { |
347 | fn foo(&self) -> i64; | 325 | fn foo(&self) -> i64; |
348 | fn bar(&self) -> { | 326 | fn bar(&self) -> () { |
349 | let x = self.foo(); | 327 | self.foo(); |
328 | // ^^^^^^^^^^ type: i64 | ||
350 | } | 329 | } |
351 | }"#, | 330 | }"#, |
352 | expect![[r#" | ||
353 | 26..30 'self': &Self | ||
354 | 52..56 'self': &Self | ||
355 | 61..96 '{ ... }': () | ||
356 | 75..76 'x': i64 | ||
357 | 79..83 'self': &Self | ||
358 | 79..89 'self.foo()': i64 | ||
359 | "#]], | ||
360 | ); | 331 | ); |
361 | } | 332 | } |
362 | 333 | ||
363 | #[test] | 334 | #[test] |
364 | fn trait_default_method_self_bound_implements_super_trait() { | 335 | fn trait_default_method_self_bound_implements_super_trait() { |
365 | check_infer( | 336 | check( |
366 | r#" | 337 | r#" |
367 | trait SuperTrait { | 338 | trait SuperTrait { |
368 | fn foo(&self) -> i64; | 339 | fn foo(&self) -> i64; |
369 | } | 340 | } |
370 | trait Trait: SuperTrait { | 341 | trait Trait: SuperTrait { |
371 | fn bar(&self) -> { | 342 | fn bar(&self) -> () { |
372 | let x = self.foo(); | 343 | self.foo(); |
344 | // ^^^^^^^^^^ type: i64 | ||
373 | } | 345 | } |
374 | }"#, | 346 | }"#, |
375 | expect![[r#" | ||
376 | 31..35 'self': &Self | ||
377 | 85..89 'self': &Self | ||
378 | 94..129 '{ ... }': () | ||
379 | 108..109 'x': i64 | ||
380 | 112..116 'self': &Self | ||
381 | 112..122 'self.foo()': i64 | ||
382 | "#]], | ||
383 | ); | 347 | ); |
384 | } | 348 | } |
385 | 349 | ||
386 | #[test] | 350 | #[test] |
387 | fn infer_project_associated_type() { | 351 | fn infer_project_associated_type() { |
388 | check_infer( | 352 | check_types( |
389 | r#" | 353 | r#" |
390 | trait Iterable { | 354 | trait Iterable { |
391 | type Item; | 355 | type Item; |
@@ -394,89 +358,62 @@ struct S; | |||
394 | impl Iterable for S { type Item = u32; } | 358 | impl Iterable for S { type Item = u32; } |
395 | fn test<T: Iterable>() { | 359 | fn test<T: Iterable>() { |
396 | let x: <S as Iterable>::Item = 1; | 360 | let x: <S as Iterable>::Item = 1; |
397 | let y: <T as Iterable>::Item = no_matter; | 361 | // ^ u32 |
398 | let z: T::Item = no_matter; | 362 | let y: <T as Iterable>::Item = u; |
399 | let a: <T>::Item = no_matter; | 363 | // ^ Iterable::Item<T> |
364 | let z: T::Item = u; | ||
365 | // ^ Iterable::Item<T> | ||
366 | let a: <T>::Item = u; | ||
367 | // ^ Iterable::Item<T> | ||
400 | }"#, | 368 | }"#, |
401 | expect![[r#" | ||
402 | 108..261 '{ ...ter; }': () | ||
403 | 118..119 'x': u32 | ||
404 | 145..146 '1': u32 | ||
405 | 156..157 'y': Iterable::Item<T> | ||
406 | 183..192 'no_matter': Iterable::Item<T> | ||
407 | 202..203 'z': Iterable::Item<T> | ||
408 | 215..224 'no_matter': Iterable::Item<T> | ||
409 | 234..235 'a': Iterable::Item<T> | ||
410 | 249..258 'no_matter': Iterable::Item<T> | ||
411 | "#]], | ||
412 | ); | 369 | ); |
413 | } | 370 | } |
414 | 371 | ||
415 | #[test] | 372 | #[test] |
416 | fn infer_return_associated_type() { | 373 | fn infer_return_associated_type() { |
417 | check_infer( | 374 | check_types( |
418 | r#" | 375 | r#" |
419 | trait Iterable { | 376 | trait Iterable { |
420 | type Item; | 377 | type Item; |
421 | } | 378 | } |
422 | struct S; | 379 | struct S; |
423 | impl Iterable for S { type Item = u32; } | 380 | impl Iterable for S { type Item = u32; } |
424 | fn foo1<T: Iterable>(t: T) -> T::Item {} | 381 | fn foo1<T: Iterable>(t: T) -> T::Item { loop {} } |
425 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} | 382 | fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item { loop {} } |
426 | fn foo3<T: Iterable>(t: T) -> <T>::Item {} | 383 | fn foo3<T: Iterable>(t: T) -> <T>::Item { loop {} } |
427 | fn test() { | 384 | fn test() { |
428 | let x = foo1(S); | 385 | foo1(S); |
429 | let y = foo2(S); | 386 | // ^^^^^^^ u32 |
430 | let z = foo3(S); | 387 | foo2(S); |
388 | // ^^^^^^^ u32 | ||
389 | foo3(S); | ||
390 | // ^^^^^^^ u32 | ||
431 | }"#, | 391 | }"#, |
432 | expect![[r#" | ||
433 | 106..107 't': T | ||
434 | 123..125 '{}': () | ||
435 | 147..148 't': T | ||
436 | 178..180 '{}': () | ||
437 | 202..203 't': T | ||
438 | 221..223 '{}': () | ||
439 | 234..300 '{ ...(S); }': () | ||
440 | 244..245 'x': u32 | ||
441 | 248..252 'foo1': fn foo1<S>(S) -> <S as Iterable>::Item | ||
442 | 248..255 'foo1(S)': u32 | ||
443 | 253..254 'S': S | ||
444 | 265..266 'y': u32 | ||
445 | 269..273 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item | ||
446 | 269..276 'foo2(S)': u32 | ||
447 | 274..275 'S': S | ||
448 | 286..287 'z': u32 | ||
449 | 290..294 'foo3': fn foo3<S>(S) -> <S as Iterable>::Item | ||
450 | 290..297 'foo3(S)': u32 | ||
451 | 295..296 'S': S | ||
452 | "#]], | ||
453 | ); | 392 | ); |
454 | } | 393 | } |
455 | 394 | ||
456 | #[test] | 395 | #[test] |
457 | fn infer_associated_type_bound() { | 396 | fn infer_associated_type_bound() { |
458 | check_infer( | 397 | check_types( |
459 | r#" | 398 | r#" |
460 | trait Iterable { | 399 | trait Iterable { |
461 | type Item; | 400 | type Item; |
462 | } | 401 | } |
463 | fn test<T: Iterable<Item=u32>>() { | 402 | fn test<T: Iterable<Item=u32>>() { |
464 | let y: T::Item = unknown; | 403 | let y: T::Item = unknown; |
404 | // ^^^^^^^ u32 | ||
465 | }"#, | 405 | }"#, |
466 | expect![[r#" | ||
467 | 67..100 '{ ...own; }': () | ||
468 | 77..78 'y': u32 | ||
469 | 90..97 'unknown': u32 | ||
470 | "#]], | ||
471 | ); | 406 | ); |
472 | } | 407 | } |
473 | 408 | ||
474 | #[test] | 409 | #[test] |
475 | fn infer_const_body() { | 410 | fn infer_const_body() { |
411 | // FIXME make check_types work with other bodies | ||
476 | check_infer( | 412 | check_infer( |
477 | r#" | 413 | r#" |
478 | const A: u32 = 1 + 1; | 414 | const A: u32 = 1 + 1; |
479 | static B: u64 = { let x = 1; x };"#, | 415 | static B: u64 = { let x = 1; x }; |
416 | "#, | ||
480 | expect![[r#" | 417 | expect![[r#" |
481 | 15..16 '1': u32 | 418 | 15..16 '1': u32 |
482 | 15..20 '1 + 1': u32 | 419 | 15..20 '1 + 1': u32 |
@@ -637,12 +574,12 @@ impl<T> core::ops::Deref for Arc<T> { | |||
637 | 574 | ||
638 | struct S; | 575 | struct S; |
639 | impl S { | 576 | impl S { |
640 | fn foo(&self) -> u128 {} | 577 | fn foo(&self) -> u128 { 0 } |
641 | } | 578 | } |
642 | 579 | ||
643 | fn test(s: Arc<S>) { | 580 | fn test(s: Arc<S>) { |
644 | (*s, s.foo()); | 581 | (*s, s.foo()); |
645 | } //^ (S, u128) | 582 | } //^^^^^^^^^^^^^ (S, u128) |
646 | "#, | 583 | "#, |
647 | ); | 584 | ); |
648 | } | 585 | } |
@@ -653,7 +590,7 @@ fn deref_trait_with_inference_var() { | |||
653 | r#" | 590 | r#" |
654 | //- minicore: deref | 591 | //- minicore: deref |
655 | struct Arc<T>; | 592 | struct Arc<T>; |
656 | fn new_arc<T>() -> Arc<T> {} | 593 | fn new_arc<T>() -> Arc<T> { Arc } |
657 | impl<T> core::ops::Deref for Arc<T> { | 594 | impl<T> core::ops::Deref for Arc<T> { |
658 | type Target = T; | 595 | type Target = T; |
659 | } | 596 | } |
@@ -663,8 +600,8 @@ fn foo(a: Arc<S>) {} | |||
663 | 600 | ||
664 | fn test() { | 601 | fn test() { |
665 | let a = new_arc(); | 602 | let a = new_arc(); |
666 | let b = (*a); | 603 | let b = *a; |
667 | //^ S | 604 | //^^ S |
668 | foo(a); | 605 | foo(a); |
669 | } | 606 | } |
670 | "#, | 607 | "#, |
@@ -684,7 +621,7 @@ impl core::ops::Deref for S { | |||
684 | 621 | ||
685 | fn test(s: S) { | 622 | fn test(s: S) { |
686 | s.foo(); | 623 | s.foo(); |
687 | } //^ {unknown} | 624 | } //^^^^^^^ {unknown} |
688 | "#, | 625 | "#, |
689 | ); | 626 | ); |
690 | } | 627 | } |
@@ -701,12 +638,12 @@ impl<T: ?Sized> core::ops::Deref for Arc<T> { | |||
701 | 638 | ||
702 | struct S; | 639 | struct S; |
703 | impl S { | 640 | impl S { |
704 | fn foo(&self) -> u128 {} | 641 | fn foo(&self) -> u128 { 0 } |
705 | } | 642 | } |
706 | 643 | ||
707 | fn test(s: Arc<S>) { | 644 | fn test(s: Arc<S>) { |
708 | (*s, s.foo()); | 645 | (*s, s.foo()); |
709 | } //^ (S, u128) | 646 | } //^^^^^^^^^^^^^ (S, u128) |
710 | "#, | 647 | "#, |
711 | ); | 648 | ); |
712 | } | 649 | } |
@@ -720,11 +657,11 @@ struct S; | |||
720 | trait Trait<T> {} | 657 | trait Trait<T> {} |
721 | impl Trait<u32> for S {} | 658 | impl Trait<u32> for S {} |
722 | 659 | ||
723 | fn foo<T: Trait<U>, U>(t: T) -> U {} | 660 | fn foo<T: Trait<U>, U>(t: T) -> U { loop {} } |
724 | 661 | ||
725 | fn test(s: S) { | 662 | fn test(s: S) { |
726 | (foo(s)); | 663 | foo(s); |
727 | } //^ u32 | 664 | } //^^^^^^ u32 |
728 | "#, | 665 | "#, |
729 | ); | 666 | ); |
730 | } | 667 | } |
@@ -741,12 +678,12 @@ impl Trait<isize> for S {} | |||
741 | 678 | ||
742 | struct O; | 679 | struct O; |
743 | impl O { | 680 | impl O { |
744 | fn foo<T: Trait<U>, U>(&self, t: T) -> U {} | 681 | fn foo<T: Trait<U>, U>(&self, t: T) -> U { loop {} } |
745 | } | 682 | } |
746 | 683 | ||
747 | fn test() { | 684 | fn test() { |
748 | O.foo(S); | 685 | O.foo(S); |
749 | } //^ isize | 686 | } //^^^^^^^^ isize |
750 | "#, | 687 | "#, |
751 | ); | 688 | ); |
752 | } | 689 | } |
@@ -761,12 +698,12 @@ trait Trait<T> {} | |||
761 | impl Trait<i64> for S {} | 698 | impl Trait<i64> for S {} |
762 | 699 | ||
763 | impl S { | 700 | impl S { |
764 | fn foo<U>(&self) -> U where Self: Trait<U> {} | 701 | fn foo<U>(&self) -> U where Self: Trait<U> { loop {} } |
765 | } | 702 | } |
766 | 703 | ||
767 | fn test() { | 704 | fn test() { |
768 | S.foo(); | 705 | S.foo(); |
769 | } //^ i64 | 706 | } //^^^^^^^ i64 |
770 | "#, | 707 | "#, |
771 | ); | 708 | ); |
772 | } | 709 | } |
@@ -782,12 +719,12 @@ impl Trait<&str> for S {} | |||
782 | 719 | ||
783 | struct O<T>; | 720 | struct O<T>; |
784 | impl<U, T: Trait<U>> O<T> { | 721 | impl<U, T: Trait<U>> O<T> { |
785 | fn foo(&self) -> U {} | 722 | fn foo(&self) -> U { loop {} } |
786 | } | 723 | } |
787 | 724 | ||
788 | fn test(o: O<S>) { | 725 | fn test(o: O<S>) { |
789 | o.foo(); | 726 | o.foo(); |
790 | } //^ &str | 727 | } //^^^^^^^ &str |
791 | "#, | 728 | "#, |
792 | ); | 729 | ); |
793 | } | 730 | } |
@@ -802,7 +739,7 @@ struct S; | |||
802 | impl Clone for S {} | 739 | impl Clone for S {} |
803 | impl<T> Trait for T where T: Clone {} | 740 | impl<T> Trait for T where T: Clone {} |
804 | fn test<T: Clone>(t: T) { t.foo(); } | 741 | fn test<T: Clone>(t: T) { t.foo(); } |
805 | //^ u128 | 742 | //^^^^^^^ u128 |
806 | "#, | 743 | "#, |
807 | ); | 744 | ); |
808 | } | 745 | } |
@@ -818,7 +755,7 @@ struct S; | |||
818 | impl Clone for S {} | 755 | impl Clone for S {} |
819 | impl<T> Trait for T where T: Clone {} | 756 | impl<T> Trait for T where T: Clone {} |
820 | fn test<T>(t: T) { t.foo(); } | 757 | fn test<T>(t: T) { t.foo(); } |
821 | //^ {unknown} | 758 | //^^^^^^^ {unknown} |
822 | "#, | 759 | "#, |
823 | ); | 760 | ); |
824 | } | 761 | } |
@@ -831,7 +768,7 @@ trait Trait { fn foo(self) -> u128; } | |||
831 | struct S; | 768 | struct S; |
832 | impl Trait for S {} | 769 | impl Trait for S {} |
833 | fn test<T: Trait>(t: T) { t.foo(); } | 770 | fn test<T: Trait>(t: T) { t.foo(); } |
834 | //^ u128 | 771 | //^^^^^^^ u128 |
835 | "#, | 772 | "#, |
836 | ); | 773 | ); |
837 | } | 774 | } |
@@ -844,7 +781,7 @@ trait Trait { fn foo(self) -> u128; } | |||
844 | struct S; | 781 | struct S; |
845 | impl Trait for S {} | 782 | impl Trait for S {} |
846 | fn test<T>(t: T) { t.foo(); } | 783 | fn test<T>(t: T) { t.foo(); } |
847 | //^ {unknown} | 784 | //^^^^^^^ {unknown} |
848 | "#, | 785 | "#, |
849 | ); | 786 | ); |
850 | } | 787 | } |
@@ -858,8 +795,8 @@ trait Trait {} | |||
858 | impl<T> core::ops::Deref for T where T: Trait { | 795 | impl<T> core::ops::Deref for T where T: Trait { |
859 | type Target = i128; | 796 | type Target = i128; |
860 | } | 797 | } |
861 | fn test<T: Trait>(t: T) { (*t); } | 798 | fn test<T: Trait>(t: T) { *t; } |
862 | //^ i128 | 799 | //^^ i128 |
863 | "#, | 800 | "#, |
864 | ); | 801 | ); |
865 | } | 802 | } |
@@ -1380,12 +1317,12 @@ fn error_bound_chalk() { | |||
1380 | check_types( | 1317 | check_types( |
1381 | r#" | 1318 | r#" |
1382 | trait Trait { | 1319 | trait Trait { |
1383 | fn foo(&self) -> u32 {} | 1320 | fn foo(&self) -> u32 { 0 } |
1384 | } | 1321 | } |
1385 | 1322 | ||
1386 | fn test(x: (impl Trait + UnknownTrait)) { | 1323 | fn test(x: (impl Trait + UnknownTrait)) { |
1387 | x.foo(); | 1324 | x.foo(); |
1388 | } //^ u32 | 1325 | } //^^^^^^^ u32 |
1389 | "#, | 1326 | "#, |
1390 | ); | 1327 | ); |
1391 | } | 1328 | } |
@@ -1476,7 +1413,7 @@ trait Clone { | |||
1476 | fn api_walkthrough() { | 1413 | fn api_walkthrough() { |
1477 | for node in foo() { | 1414 | for node in foo() { |
1478 | node.clone(); | 1415 | node.clone(); |
1479 | } //^ {unknown} | 1416 | } //^^^^^^^^^^^^ {unknown} |
1480 | } | 1417 | } |
1481 | "#, | 1418 | "#, |
1482 | ); | 1419 | ); |
@@ -1513,13 +1450,13 @@ fn where_clause_trait_in_scope_for_method_resolution() { | |||
1513 | r#" | 1450 | r#" |
1514 | mod foo { | 1451 | mod foo { |
1515 | trait Trait { | 1452 | trait Trait { |
1516 | fn foo(&self) -> u32 {} | 1453 | fn foo(&self) -> u32 { 0 } |
1517 | } | 1454 | } |
1518 | } | 1455 | } |
1519 | 1456 | ||
1520 | fn test<T: foo::Trait>(x: T) { | 1457 | fn test<T: foo::Trait>(x: T) { |
1521 | x.foo(); | 1458 | x.foo(); |
1522 | } //^ u32 | 1459 | } //^^^^^^^ u32 |
1523 | "#, | 1460 | "#, |
1524 | ); | 1461 | ); |
1525 | } | 1462 | } |
@@ -1982,7 +1919,7 @@ fn fn_item_fn_trait() { | |||
1982 | //- minicore: fn | 1919 | //- minicore: fn |
1983 | struct S; | 1920 | struct S; |
1984 | 1921 | ||
1985 | fn foo() -> S {} | 1922 | fn foo() -> S { S } |
1986 | 1923 | ||
1987 | fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } | 1924 | fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() } |
1988 | 1925 | ||
@@ -2009,7 +1946,7 @@ trait Trait2 { | |||
2009 | fn test<T: Trait>() where T::Item: Trait2 { | 1946 | fn test<T: Trait>() where T::Item: Trait2 { |
2010 | let x: T::Item = no_matter; | 1947 | let x: T::Item = no_matter; |
2011 | x.foo(); | 1948 | x.foo(); |
2012 | } //^ u32 | 1949 | } //^^^^^^^ u32 |
2013 | "#, | 1950 | "#, |
2014 | ); | 1951 | ); |
2015 | } | 1952 | } |
@@ -2029,7 +1966,7 @@ trait Trait2 { | |||
2029 | fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { | 1966 | fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> { |
2030 | let x: T::Item = no_matter; | 1967 | let x: T::Item = no_matter; |
2031 | x.foo(); | 1968 | x.foo(); |
2032 | } //^ u32 | 1969 | } //^^^^^^^ u32 |
2033 | "#, | 1970 | "#, |
2034 | ); | 1971 | ); |
2035 | } | 1972 | } |
@@ -2092,7 +2029,7 @@ impl Trait for S { | |||
2092 | 2029 | ||
2093 | fn test() { | 2030 | fn test() { |
2094 | S.f(); | 2031 | S.f(); |
2095 | } //^ u32 | 2032 | } //^^^^^ u32 |
2096 | "#, | 2033 | "#, |
2097 | ); | 2034 | ); |
2098 | } | 2035 | } |
@@ -2120,7 +2057,7 @@ where | |||
2120 | 2057 | ||
2121 | fn foo<I: Interner>(interner: &I, t: Ty<I>) { | 2058 | fn foo<I: Interner>(interner: &I, t: Ty<I>) { |
2122 | fold(interner, t); | 2059 | fold(interner, t); |
2123 | } //^ Ty<I> | 2060 | } //^^^^^^^^^^^^^^^^^ Ty<I> |
2124 | "#, | 2061 | "#, |
2125 | ); | 2062 | ); |
2126 | } | 2063 | } |
@@ -2139,7 +2076,7 @@ impl Trait<Self> for S {} | |||
2139 | 2076 | ||
2140 | fn test() { | 2077 | fn test() { |
2141 | S.foo(); | 2078 | S.foo(); |
2142 | } //^ () | 2079 | } //^^^^^^^ () |
2143 | "#, | 2080 | "#, |
2144 | ); | 2081 | ); |
2145 | } | 2082 | } |
@@ -2158,7 +2095,7 @@ impl Trait for S<Self> {} | |||
2158 | 2095 | ||
2159 | fn test() { | 2096 | fn test() { |
2160 | S.foo(); | 2097 | S.foo(); |
2161 | } //^ {unknown} | 2098 | } //^^^^^^^ {unknown} |
2162 | "#, | 2099 | "#, |
2163 | ); | 2100 | ); |
2164 | } | 2101 | } |
@@ -2176,7 +2113,7 @@ trait Trait2<T> {} | |||
2176 | 2113 | ||
2177 | fn test<T: Trait>() where T: Trait2<T::Item> { | 2114 | fn test<T: Trait>() where T: Trait2<T::Item> { |
2178 | let x: T::Item = no_matter; | 2115 | let x: T::Item = no_matter; |
2179 | } //^ {unknown} | 2116 | } //^^^^^^^^^ {unknown} |
2180 | "#, | 2117 | "#, |
2181 | ); | 2118 | ); |
2182 | } | 2119 | } |
@@ -2193,7 +2130,7 @@ trait Trait<T> { | |||
2193 | 2130 | ||
2194 | fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | 2131 | fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { |
2195 | let x: T::Item = no_matter; | 2132 | let x: T::Item = no_matter; |
2196 | } //^ {unknown} | 2133 | } //^^^^^^^^^ {unknown} |
2197 | "#, | 2134 | "#, |
2198 | ); | 2135 | ); |
2199 | } | 2136 | } |
@@ -2211,7 +2148,7 @@ trait Trait { | |||
2211 | 2148 | ||
2212 | fn test<T>() where T: Trait<OtherItem = T::Item> { | 2149 | fn test<T>() where T: Trait<OtherItem = T::Item> { |
2213 | let x: T::Item = no_matter; | 2150 | let x: T::Item = no_matter; |
2214 | } //^ Trait::Item<T> | 2151 | } //^^^^^^^^^ Trait::Item<T> |
2215 | "#, | 2152 | "#, |
2216 | ); | 2153 | ); |
2217 | } | 2154 | } |
@@ -2243,7 +2180,7 @@ fn test<T>(t: T) where T: UnificationStoreMut { | |||
2243 | t.push(x); | 2180 | t.push(x); |
2244 | let y: Key<T>; | 2181 | let y: Key<T>; |
2245 | (x, y); | 2182 | (x, y); |
2246 | } //^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) | 2183 | } //^^^^^^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) |
2247 | "#, | 2184 | "#, |
2248 | ); | 2185 | ); |
2249 | } | 2186 | } |
@@ -2268,7 +2205,7 @@ impl<T: Iterator> Iterator for S<T> { | |||
2268 | fn test<I: Iterator<Item: OtherTrait<u32>>>() { | 2205 | fn test<I: Iterator<Item: OtherTrait<u32>>>() { |
2269 | let x: <S<I> as Iterator>::Item; | 2206 | let x: <S<I> as Iterator>::Item; |
2270 | x.foo(); | 2207 | x.foo(); |
2271 | } //^ u32 | 2208 | } //^^^^^^^ u32 |
2272 | "#, | 2209 | "#, |
2273 | ); | 2210 | ); |
2274 | } | 2211 | } |
@@ -2470,7 +2407,7 @@ impl<T: Trait> Trait for S<T> { | |||
2470 | fn test<T: Trait>() { | 2407 | fn test<T: Trait>() { |
2471 | let y: <S<T> as Trait>::Item = no_matter; | 2408 | let y: <S<T> as Trait>::Item = no_matter; |
2472 | y.foo(); | 2409 | y.foo(); |
2473 | } //^ u32 | 2410 | } //^^^^^^^ u32 |
2474 | "#, | 2411 | "#, |
2475 | ); | 2412 | ); |
2476 | } | 2413 | } |
@@ -2490,7 +2427,7 @@ trait Trait { | |||
2490 | 2427 | ||
2491 | fn test(x: Box<dyn Trait>) { | 2428 | fn test(x: Box<dyn Trait>) { |
2492 | x.foo(); | 2429 | x.foo(); |
2493 | } //^ () | 2430 | } //^^^^^^^ () |
2494 | "#, | 2431 | "#, |
2495 | ); | 2432 | ); |
2496 | } | 2433 | } |
@@ -2509,7 +2446,7 @@ impl ToOwned for str { | |||
2509 | } | 2446 | } |
2510 | fn test() { | 2447 | fn test() { |
2511 | "foo".to_owned(); | 2448 | "foo".to_owned(); |
2512 | } //^ String | 2449 | } //^^^^^^^^^^^^^^^^ String |
2513 | "#, | 2450 | "#, |
2514 | ); | 2451 | ); |
2515 | } | 2452 | } |
@@ -2649,7 +2586,7 @@ impl<T:A> B for T { | |||
2649 | 2586 | ||
2650 | fn main() { | 2587 | fn main() { |
2651 | Bar::foo(); | 2588 | Bar::foo(); |
2652 | } //^ Foo | 2589 | } //^^^^^^^^^^ Foo |
2653 | "#, | 2590 | "#, |
2654 | ); | 2591 | ); |
2655 | } | 2592 | } |
@@ -3002,7 +2939,7 @@ fn test() { | |||
3002 | S.get(1); | 2939 | S.get(1); |
3003 | //^^^^^^^^ u128 | 2940 | //^^^^^^^^ u128 |
3004 | S.get(1.); | 2941 | S.get(1.); |
3005 | //^^^^^^^^ f32 | 2942 | //^^^^^^^^^ f32 |
3006 | } | 2943 | } |
3007 | "#, | 2944 | "#, |
3008 | ); | 2945 | ); |
@@ -3477,14 +3414,12 @@ trait Convert { | |||
3477 | fn new() -> Self; | 3414 | fn new() -> Self; |
3478 | } | 3415 | } |
3479 | impl Convert for u32 { | 3416 | impl Convert for u32 { |
3480 | fn new() -> Self { | 3417 | fn new() -> Self { 0 } |
3481 | 0 | ||
3482 | } | ||
3483 | } | 3418 | } |
3484 | 3419 | ||
3485 | async fn get_accounts() -> Result<u32, ()> { | 3420 | async fn get_accounts() -> Result<u32, ()> { |
3486 | let ret = Fooey.collect(); | 3421 | let ret = Fooey.collect(); |
3487 | // ^ u32 | 3422 | // ^^^^^^^^^^^^^^^ u32 |
3488 | Ok(ret) | 3423 | Ok(ret) |
3489 | } | 3424 | } |
3490 | "#, | 3425 | "#, |
@@ -3493,6 +3428,7 @@ async fn get_accounts() -> Result<u32, ()> { | |||
3493 | 3428 | ||
3494 | #[test] | 3429 | #[test] |
3495 | fn local_impl_1() { | 3430 | fn local_impl_1() { |
3431 | check!(block_local_impls); | ||
3496 | check_types( | 3432 | check_types( |
3497 | r#" | 3433 | r#" |
3498 | trait Trait<T> { | 3434 | trait Trait<T> { |
@@ -3502,7 +3438,7 @@ trait Trait<T> { | |||
3502 | fn test() { | 3438 | fn test() { |
3503 | struct S; | 3439 | struct S; |
3504 | impl Trait<u32> for S { | 3440 | impl Trait<u32> for S { |
3505 | fn foo(&self) { 0 } | 3441 | fn foo(&self) -> u32 { 0 } |
3506 | } | 3442 | } |
3507 | 3443 | ||
3508 | S.foo(); | 3444 | S.foo(); |
@@ -3514,6 +3450,7 @@ fn test() { | |||
3514 | 3450 | ||
3515 | #[test] | 3451 | #[test] |
3516 | fn local_impl_2() { | 3452 | fn local_impl_2() { |
3453 | check!(block_local_impls); | ||
3517 | check_types( | 3454 | check_types( |
3518 | r#" | 3455 | r#" |
3519 | struct S; | 3456 | struct S; |
@@ -3523,7 +3460,7 @@ fn test() { | |||
3523 | fn foo(&self) -> T; | 3460 | fn foo(&self) -> T; |
3524 | } | 3461 | } |
3525 | impl Trait<u32> for S { | 3462 | impl Trait<u32> for S { |
3526 | fn foo(&self) { 0 } | 3463 | fn foo(&self) -> u32 { 0 } |
3527 | } | 3464 | } |
3528 | 3465 | ||
3529 | S.foo(); | 3466 | S.foo(); |
@@ -3535,6 +3472,7 @@ fn test() { | |||
3535 | 3472 | ||
3536 | #[test] | 3473 | #[test] |
3537 | fn local_impl_3() { | 3474 | fn local_impl_3() { |
3475 | check!(block_local_impls); | ||
3538 | check_types( | 3476 | check_types( |
3539 | r#" | 3477 | r#" |
3540 | trait Trait<T> { | 3478 | trait Trait<T> { |
@@ -3547,7 +3485,7 @@ fn test() { | |||
3547 | struct S2; | 3485 | struct S2; |
3548 | 3486 | ||
3549 | impl Trait<S1> for S2 { | 3487 | impl Trait<S1> for S2 { |
3550 | fn foo(&self) { S1 } | 3488 | fn foo(&self) -> S1 { S1 } |
3551 | } | 3489 | } |
3552 | 3490 | ||
3553 | S2.foo(); | 3491 | S2.foo(); |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 05a2b1293..c6d6bb74a 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -1,8 +1,5 @@ | |||
1 | use either::Either; | 1 | use either::Either; |
2 | use hir::{ | 2 | use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics}; |
3 | AsAssocItem, AssocItemContainer, GenericParam, HasAttrs, HasSource, HirDisplay, InFile, Module, | ||
4 | ModuleDef, Semantics, | ||
5 | }; | ||
6 | use ide_db::{ | 3 | use ide_db::{ |
7 | base_db::SourceDatabase, | 4 | base_db::SourceDatabase, |
8 | defs::{Definition, NameClass, NameRefClass}, | 5 | defs::{Definition, NameClass, NameRefClass}, |
@@ -33,37 +30,20 @@ use crate::{ | |||
33 | 30 | ||
34 | #[derive(Clone, Debug, PartialEq, Eq)] | 31 | #[derive(Clone, Debug, PartialEq, Eq)] |
35 | pub struct HoverConfig { | 32 | pub struct HoverConfig { |
36 | pub implementations: bool, | ||
37 | pub references: bool, | ||
38 | pub run: bool, | ||
39 | pub debug: bool, | ||
40 | pub goto_type_def: bool, | ||
41 | pub links_in_hover: bool, | 33 | pub links_in_hover: bool, |
42 | pub markdown: bool, | 34 | pub documentation: Option<HoverDocFormat>, |
43 | } | 35 | } |
44 | 36 | ||
45 | impl HoverConfig { | 37 | impl HoverConfig { |
46 | pub const NO_ACTIONS: Self = Self { | 38 | fn markdown(&self) -> bool { |
47 | implementations: false, | 39 | matches!(self.documentation, Some(HoverDocFormat::Markdown)) |
48 | references: false, | ||
49 | run: false, | ||
50 | debug: false, | ||
51 | goto_type_def: false, | ||
52 | links_in_hover: true, | ||
53 | markdown: true, | ||
54 | }; | ||
55 | |||
56 | pub fn any(&self) -> bool { | ||
57 | self.implementations || self.references || self.runnable() || self.goto_type_def | ||
58 | } | ||
59 | |||
60 | pub fn none(&self) -> bool { | ||
61 | !self.any() | ||
62 | } | 40 | } |
41 | } | ||
63 | 42 | ||
64 | pub fn runnable(&self) -> bool { | 43 | #[derive(Clone, Debug, PartialEq, Eq)] |
65 | self.run || self.debug | 44 | pub enum HoverDocFormat { |
66 | } | 45 | Markdown, |
46 | PlainText, | ||
67 | } | 47 | } |
68 | 48 | ||
69 | #[derive(Debug, Clone)] | 49 | #[derive(Debug, Clone)] |
@@ -96,10 +76,9 @@ pub struct HoverResult { | |||
96 | pub(crate) fn hover( | 76 | pub(crate) fn hover( |
97 | db: &RootDatabase, | 77 | db: &RootDatabase, |
98 | position: FilePosition, | 78 | position: FilePosition, |
99 | links_in_hover: bool, | 79 | config: &HoverConfig, |
100 | markdown: bool, | ||
101 | ) -> Option<RangeInfo<HoverResult>> { | 80 | ) -> Option<RangeInfo<HoverResult>> { |
102 | let sema = Semantics::new(db); | 81 | let sema = hir::Semantics::new(db); |
103 | let file = sema.parse(position.file_id).syntax().clone(); | 82 | let file = sema.parse(position.file_id).syntax().clone(); |
104 | let token = pick_best(file.token_at_offset(position.offset))?; | 83 | let token = pick_best(file.token_at_offset(position.offset))?; |
105 | let token = sema.descend_into_macros(token); | 84 | let token = sema.descend_into_macros(token); |
@@ -131,7 +110,7 @@ pub(crate) fn hover( | |||
131 | let (docs, doc_mapping) = attributes.docs_with_rangemap(db)?; | 110 | let (docs, doc_mapping) = attributes.docs_with_rangemap(db)?; |
132 | let (idl_range, link, ns) = | 111 | let (idl_range, link, ns) = |
133 | extract_definitions_from_markdown(docs.as_str()).into_iter().find_map(|(range, link, ns)| { | 112 | extract_definitions_from_markdown(docs.as_str()).into_iter().find_map(|(range, link, ns)| { |
134 | let InFile { file_id, value: range } = doc_mapping.map(range)?; | 113 | let hir::InFile { file_id, value: range } = doc_mapping.map(range)?; |
135 | if file_id == position.file_id.into() && range.contains(position.offset) { | 114 | if file_id == position.file_id.into() && range.contains(position.offset) { |
136 | Some((range, link, ns)) | 115 | Some((range, link, ns)) |
137 | } else { | 116 | } else { |
@@ -151,13 +130,13 @@ pub(crate) fn hover( | |||
151 | 130 | ||
152 | if let Some(definition) = definition { | 131 | if let Some(definition) = definition { |
153 | let famous_defs = match &definition { | 132 | let famous_defs = match &definition { |
154 | Definition::ModuleDef(ModuleDef::BuiltinType(_)) => { | 133 | Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) => { |
155 | Some(FamousDefs(&sema, sema.scope(&node).krate())) | 134 | Some(FamousDefs(&sema, sema.scope(&node).krate())) |
156 | } | 135 | } |
157 | _ => None, | 136 | _ => None, |
158 | }; | 137 | }; |
159 | if let Some(markup) = hover_for_definition(db, definition, famous_defs.as_ref()) { | 138 | if let Some(markup) = hover_for_definition(db, definition, famous_defs.as_ref(), config) { |
160 | res.markup = process_markup(sema.db, definition, &markup, links_in_hover, markdown); | 139 | res.markup = process_markup(sema.db, definition, &markup, config); |
161 | if let Some(action) = show_implementations_action(db, definition) { | 140 | if let Some(action) = show_implementations_action(db, definition) { |
162 | res.actions.push(action); | 141 | res.actions.push(action); |
163 | } | 142 | } |
@@ -179,7 +158,7 @@ pub(crate) fn hover( | |||
179 | } | 158 | } |
180 | } | 159 | } |
181 | 160 | ||
182 | if let res @ Some(_) = hover_for_keyword(&sema, links_in_hover, markdown, &token) { | 161 | if let res @ Some(_) = hover_for_keyword(&sema, config, &token) { |
183 | return res; | 162 | return res; |
184 | } | 163 | } |
185 | 164 | ||
@@ -198,7 +177,7 @@ pub(crate) fn hover( | |||
198 | } | 177 | } |
199 | }; | 178 | }; |
200 | 179 | ||
201 | res.markup = if markdown { | 180 | res.markup = if config.markdown() { |
202 | Markup::fenced_block(&ty.display(db)) | 181 | Markup::fenced_block(&ty.display(db)) |
203 | } else { | 182 | } else { |
204 | ty.display(db).to_string().into() | 183 | ty.display(db).to_string().into() |
@@ -261,8 +240,10 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov | |||
261 | } | 240 | } |
262 | 241 | ||
263 | let adt = match def { | 242 | let adt = match def { |
264 | Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action), | 243 | Definition::ModuleDef(hir::ModuleDef::Trait(it)) => { |
265 | Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it), | 244 | return it.try_to_nav(db).map(to_action) |
245 | } | ||
246 | Definition::ModuleDef(hir::ModuleDef::Adt(it)) => Some(it), | ||
266 | Definition::SelfType(it) => it.self_ty(db).as_adt(), | 247 | Definition::SelfType(it) => it.self_ty(db).as_adt(), |
267 | _ => None, | 248 | _ => None, |
268 | }?; | 249 | }?; |
@@ -271,25 +252,27 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov | |||
271 | 252 | ||
272 | fn show_fn_references_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | 253 | fn show_fn_references_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { |
273 | match def { | 254 | match def { |
274 | Definition::ModuleDef(ModuleDef::Function(it)) => it.try_to_nav(db).map(|nav_target| { | 255 | Definition::ModuleDef(hir::ModuleDef::Function(it)) => { |
275 | HoverAction::Reference(FilePosition { | 256 | it.try_to_nav(db).map(|nav_target| { |
276 | file_id: nav_target.file_id, | 257 | HoverAction::Reference(FilePosition { |
277 | offset: nav_target.focus_or_full_range().start(), | 258 | file_id: nav_target.file_id, |
259 | offset: nav_target.focus_or_full_range().start(), | ||
260 | }) | ||
278 | }) | 261 | }) |
279 | }), | 262 | } |
280 | _ => None, | 263 | _ => None, |
281 | } | 264 | } |
282 | } | 265 | } |
283 | 266 | ||
284 | fn runnable_action( | 267 | fn runnable_action( |
285 | sema: &Semantics<RootDatabase>, | 268 | sema: &hir::Semantics<RootDatabase>, |
286 | def: Definition, | 269 | def: Definition, |
287 | file_id: FileId, | 270 | file_id: FileId, |
288 | ) -> Option<HoverAction> { | 271 | ) -> Option<HoverAction> { |
289 | match def { | 272 | match def { |
290 | Definition::ModuleDef(it) => match it { | 273 | Definition::ModuleDef(it) => match it { |
291 | ModuleDef::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable), | 274 | hir::ModuleDef::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable), |
292 | ModuleDef::Function(func) => { | 275 | hir::ModuleDef::Function(func) => { |
293 | let src = func.source(sema.db)?; | 276 | let src = func.source(sema.db)?; |
294 | if src.file_id != file_id.into() { | 277 | if src.file_id != file_id.into() { |
295 | cov_mark::hit!(hover_macro_generated_struct_fn_doc_comment); | 278 | cov_mark::hit!(hover_macro_generated_struct_fn_doc_comment); |
@@ -306,19 +289,19 @@ fn runnable_action( | |||
306 | } | 289 | } |
307 | 290 | ||
308 | fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | 291 | fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { |
309 | let mut targets: Vec<ModuleDef> = Vec::new(); | 292 | let mut targets: Vec<hir::ModuleDef> = Vec::new(); |
310 | let mut push_new_def = |item: ModuleDef| { | 293 | let mut push_new_def = |item: hir::ModuleDef| { |
311 | if !targets.contains(&item) { | 294 | if !targets.contains(&item) { |
312 | targets.push(item); | 295 | targets.push(item); |
313 | } | 296 | } |
314 | }; | 297 | }; |
315 | 298 | ||
316 | if let Definition::GenericParam(GenericParam::TypeParam(it)) = def { | 299 | if let Definition::GenericParam(hir::GenericParam::TypeParam(it)) = def { |
317 | it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into())); | 300 | it.trait_bounds(db).into_iter().for_each(|it| push_new_def(it.into())); |
318 | } else { | 301 | } else { |
319 | let ty = match def { | 302 | let ty = match def { |
320 | Definition::Local(it) => it.ty(db), | 303 | Definition::Local(it) => it.ty(db), |
321 | Definition::GenericParam(GenericParam::ConstParam(it)) => it.ty(db), | 304 | Definition::GenericParam(hir::GenericParam::ConstParam(it)) => it.ty(db), |
322 | _ => return None, | 305 | _ => return None, |
323 | }; | 306 | }; |
324 | 307 | ||
@@ -348,42 +331,32 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> { | |||
348 | Some(HoverAction::GoToType(targets)) | 331 | Some(HoverAction::GoToType(targets)) |
349 | } | 332 | } |
350 | 333 | ||
351 | fn hover_markup( | 334 | fn hover_markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Option<Markup> { |
352 | docs: Option<String>, | 335 | let mut buf = String::new(); |
353 | desc: Option<String>, | ||
354 | mod_path: Option<String>, | ||
355 | ) -> Option<Markup> { | ||
356 | match desc { | ||
357 | Some(desc) => { | ||
358 | let mut buf = String::new(); | ||
359 | |||
360 | if let Some(mod_path) = mod_path { | ||
361 | if !mod_path.is_empty() { | ||
362 | format_to!(buf, "```rust\n{}\n```\n\n", mod_path); | ||
363 | } | ||
364 | } | ||
365 | format_to!(buf, "```rust\n{}\n```", desc); | ||
366 | 336 | ||
367 | if let Some(doc) = docs { | 337 | if let Some(mod_path) = mod_path { |
368 | format_to!(buf, "\n___\n\n{}", doc); | 338 | if !mod_path.is_empty() { |
369 | } | 339 | format_to!(buf, "```rust\n{}\n```\n\n", mod_path); |
370 | Some(buf.into()) | ||
371 | } | 340 | } |
372 | None => docs.map(Markup::from), | ||
373 | } | 341 | } |
342 | format_to!(buf, "```rust\n{}\n```", desc); | ||
343 | |||
344 | if let Some(doc) = docs { | ||
345 | format_to!(buf, "\n___\n\n{}", doc); | ||
346 | } | ||
347 | Some(buf.into()) | ||
374 | } | 348 | } |
375 | 349 | ||
376 | fn process_markup( | 350 | fn process_markup( |
377 | db: &RootDatabase, | 351 | db: &RootDatabase, |
378 | def: Definition, | 352 | def: Definition, |
379 | markup: &Markup, | 353 | markup: &Markup, |
380 | links_in_hover: bool, | 354 | config: &HoverConfig, |
381 | markdown: bool, | ||
382 | ) -> Markup { | 355 | ) -> Markup { |
383 | let markup = markup.as_str(); | 356 | let markup = markup.as_str(); |
384 | let markup = if !markdown { | 357 | let markup = if !config.markdown() { |
385 | remove_markdown(markup) | 358 | remove_markdown(markup) |
386 | } else if links_in_hover { | 359 | } else if config.links_in_hover { |
387 | rewrite_links(db, markup, &def) | 360 | rewrite_links(db, markup, &def) |
388 | } else { | 361 | } else { |
389 | remove_links(markup) | 362 | remove_links(markup) |
@@ -396,11 +369,11 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> | |||
396 | Definition::Field(f) => Some(f.parent_def(db).name(db)), | 369 | Definition::Field(f) => Some(f.parent_def(db).name(db)), |
397 | Definition::Local(l) => l.parent(db).name(db), | 370 | Definition::Local(l) => l.parent(db).name(db), |
398 | Definition::ModuleDef(md) => match md { | 371 | Definition::ModuleDef(md) => match md { |
399 | ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) { | 372 | hir::ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) { |
400 | AssocItemContainer::Trait(t) => Some(t.name(db)), | 373 | hir::AssocItemContainer::Trait(t) => Some(t.name(db)), |
401 | AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)), | 374 | hir::AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)), |
402 | }, | 375 | }, |
403 | ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)), | 376 | hir::ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)), |
404 | _ => None, | 377 | _ => None, |
405 | }, | 378 | }, |
406 | _ => None, | 379 | _ => None, |
@@ -408,7 +381,7 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> | |||
408 | .map(|name| name.to_string()) | 381 | .map(|name| name.to_string()) |
409 | } | 382 | } |
410 | 383 | ||
411 | fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String { | 384 | fn render_path(db: &RootDatabase, module: hir::Module, item_name: Option<String>) -> String { |
412 | let crate_name = | 385 | let crate_name = |
413 | db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string()); | 386 | db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string()); |
414 | let module_path = module | 387 | let module_path = module |
@@ -420,6 +393,9 @@ fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> | |||
420 | } | 393 | } |
421 | 394 | ||
422 | fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { | 395 | fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { |
396 | if let Definition::GenericParam(_) = def { | ||
397 | return None; | ||
398 | } | ||
423 | def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def))) | 399 | def.module(db).map(|module| render_path(db, module, definition_owner_name(db, def))) |
424 | } | 400 | } |
425 | 401 | ||
@@ -427,60 +403,57 @@ fn hover_for_definition( | |||
427 | db: &RootDatabase, | 403 | db: &RootDatabase, |
428 | def: Definition, | 404 | def: Definition, |
429 | famous_defs: Option<&FamousDefs>, | 405 | famous_defs: Option<&FamousDefs>, |
406 | config: &HoverConfig, | ||
430 | ) -> Option<Markup> { | 407 | ) -> Option<Markup> { |
431 | let mod_path = definition_mod_path(db, &def); | 408 | let mod_path = definition_mod_path(db, &def); |
432 | return match def { | 409 | let (label, docs) = match def { |
433 | Definition::Macro(it) => match &it.source(db)?.value { | 410 | Definition::Macro(it) => match &it.source(db)?.value { |
434 | Either::Left(mac) => { | 411 | Either::Left(mac) => { |
435 | let label = macro_label(mac); | 412 | let label = macro_label(mac); |
436 | from_def_source_labeled(db, it, Some(label), mod_path) | 413 | (label, it.attrs(db).docs()) |
437 | } | 414 | } |
438 | Either::Right(_) => { | 415 | Either::Right(_) => { |
439 | // FIXME | 416 | // FIXME |
440 | None | 417 | return None; |
441 | } | 418 | } |
442 | }, | 419 | }, |
443 | Definition::Field(def) => from_hir_fmt(db, def, mod_path), | 420 | Definition::Field(def) => label_and_docs(db, def), |
444 | Definition::ModuleDef(it) => match it { | 421 | Definition::ModuleDef(it) => match it { |
445 | ModuleDef::Module(it) => from_hir_fmt(db, it, mod_path), | 422 | hir::ModuleDef::Module(it) => label_and_docs(db, it), |
446 | ModuleDef::Function(it) => from_hir_fmt(db, it, mod_path), | 423 | hir::ModuleDef::Function(it) => label_and_docs(db, it), |
447 | ModuleDef::Adt(it) => from_hir_fmt(db, it, mod_path), | 424 | hir::ModuleDef::Adt(it) => label_and_docs(db, it), |
448 | ModuleDef::Variant(it) => from_hir_fmt(db, it, mod_path), | 425 | hir::ModuleDef::Variant(it) => label_and_docs(db, it), |
449 | ModuleDef::Const(it) => from_hir_fmt(db, it, mod_path), | 426 | hir::ModuleDef::Const(it) => label_and_docs(db, it), |
450 | ModuleDef::Static(it) => from_hir_fmt(db, it, mod_path), | 427 | hir::ModuleDef::Static(it) => label_and_docs(db, it), |
451 | ModuleDef::Trait(it) => from_hir_fmt(db, it, mod_path), | 428 | hir::ModuleDef::Trait(it) => label_and_docs(db, it), |
452 | ModuleDef::TypeAlias(it) => from_hir_fmt(db, it, mod_path), | 429 | hir::ModuleDef::TypeAlias(it) => label_and_docs(db, it), |
453 | ModuleDef::BuiltinType(it) => famous_defs | 430 | hir::ModuleDef::BuiltinType(it) => { |
454 | .and_then(|fd| hover_for_builtin(fd, it)) | 431 | return famous_defs |
455 | .or_else(|| Some(Markup::fenced_block(&it.name()))), | 432 | .and_then(|fd| hover_for_builtin(fd, it)) |
433 | .or_else(|| Some(Markup::fenced_block(&it.name()))) | ||
434 | } | ||
456 | }, | 435 | }, |
457 | Definition::Local(it) => hover_for_local(it, db), | 436 | Definition::Local(it) => return hover_for_local(it, db), |
458 | Definition::SelfType(impl_def) => { | 437 | Definition::SelfType(impl_def) => { |
459 | impl_def.self_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path)) | 438 | impl_def.self_ty(db).as_adt().map(|adt| label_and_docs(db, adt))? |
460 | } | 439 | } |
461 | Definition::GenericParam(it) => from_hir_fmt(db, it, None), | 440 | Definition::GenericParam(it) => label_and_docs(db, it), |
462 | Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), | 441 | Definition::Label(it) => return Some(Markup::fenced_block(&it.name(db))), |
463 | }; | 442 | }; |
464 | 443 | ||
465 | fn from_hir_fmt<D>(db: &RootDatabase, def: D, mod_path: Option<String>) -> Option<Markup> | 444 | return hover_markup( |
445 | docs.filter(|_| config.documentation.is_some()).map(Into::into), | ||
446 | label, | ||
447 | mod_path, | ||
448 | ); | ||
449 | |||
450 | fn label_and_docs<D>(db: &RootDatabase, def: D) -> (String, Option<hir::Documentation>) | ||
466 | where | 451 | where |
467 | D: HasAttrs + HirDisplay, | 452 | D: HasAttrs + HirDisplay, |
468 | { | 453 | { |
469 | let label = def.display(db).to_string(); | 454 | let label = def.display(db).to_string(); |
470 | from_def_source_labeled(db, def, Some(label), mod_path) | 455 | let docs = def.attrs(db).docs(); |
471 | } | 456 | (label, docs) |
472 | |||
473 | fn from_def_source_labeled<D>( | ||
474 | db: &RootDatabase, | ||
475 | def: D, | ||
476 | short_label: Option<String>, | ||
477 | mod_path: Option<String>, | ||
478 | ) -> Option<Markup> | ||
479 | where | ||
480 | D: HasAttrs, | ||
481 | { | ||
482 | let docs = def.attrs(db).docs().map(Into::into); | ||
483 | hover_markup(docs, short_label, mod_path) | ||
484 | } | 457 | } |
485 | } | 458 | } |
486 | 459 | ||
@@ -504,16 +477,15 @@ fn hover_for_local(it: hir::Local, db: &RootDatabase) -> Option<Markup> { | |||
504 | } | 477 | } |
505 | Either::Right(_) => format!("{}self: {}", is_mut, ty), | 478 | Either::Right(_) => format!("{}self: {}", is_mut, ty), |
506 | }; | 479 | }; |
507 | hover_markup(None, Some(desc), None) | 480 | hover_markup(None, desc, None) |
508 | } | 481 | } |
509 | 482 | ||
510 | fn hover_for_keyword( | 483 | fn hover_for_keyword( |
511 | sema: &Semantics<RootDatabase>, | 484 | sema: &Semantics<RootDatabase>, |
512 | links_in_hover: bool, | 485 | config: &HoverConfig, |
513 | markdown: bool, | ||
514 | token: &SyntaxToken, | 486 | token: &SyntaxToken, |
515 | ) -> Option<RangeInfo<HoverResult>> { | 487 | ) -> Option<RangeInfo<HoverResult>> { |
516 | if !token.kind().is_keyword() { | 488 | if !token.kind().is_keyword() || !config.documentation.is_some() { |
517 | return None; | 489 | return None; |
518 | } | 490 | } |
519 | let famous_defs = FamousDefs(sema, sema.scope(&token.parent()?).krate()); | 491 | let famous_defs = FamousDefs(sema, sema.scope(&token.parent()?).krate()); |
@@ -524,9 +496,8 @@ fn hover_for_keyword( | |||
524 | let markup = process_markup( | 496 | let markup = process_markup( |
525 | sema.db, | 497 | sema.db, |
526 | Definition::ModuleDef(doc_owner.into()), | 498 | Definition::ModuleDef(doc_owner.into()), |
527 | &hover_markup(Some(docs.into()), Some(token.text().into()), None)?, | 499 | &hover_markup(Some(docs.into()), token.text().into(), None)?, |
528 | links_in_hover, | 500 | config, |
529 | markdown, | ||
530 | ); | 501 | ); |
531 | Some(RangeInfo::new(token.text_range(), HoverResult { markup, actions: Default::default() })) | 502 | Some(RangeInfo::new(token.text_range(), HoverResult { markup, actions: Default::default() })) |
532 | } | 503 | } |
@@ -536,7 +507,7 @@ fn hover_for_builtin(famous_defs: &FamousDefs, builtin: hir::BuiltinType) -> Opt | |||
536 | let primitive_mod = format!("prim_{}", builtin.name()); | 507 | let primitive_mod = format!("prim_{}", builtin.name()); |
537 | let doc_owner = find_std_module(famous_defs, &primitive_mod)?; | 508 | let doc_owner = find_std_module(famous_defs, &primitive_mod)?; |
538 | let docs = doc_owner.attrs(famous_defs.0.db).docs()?; | 509 | let docs = doc_owner.attrs(famous_defs.0.db).docs()?; |
539 | hover_markup(Some(docs.into()), Some(builtin.name().to_string()), None) | 510 | hover_markup(Some(docs.into()), builtin.name().to_string(), None) |
540 | } | 511 | } |
541 | 512 | ||
542 | fn find_std_module(famous_defs: &FamousDefs, name: &str) -> Option<hir::Module> { | 513 | fn find_std_module(famous_defs: &FamousDefs, name: &str) -> Option<hir::Module> { |
@@ -566,16 +537,34 @@ mod tests { | |||
566 | use expect_test::{expect, Expect}; | 537 | use expect_test::{expect, Expect}; |
567 | use ide_db::base_db::FileLoader; | 538 | use ide_db::base_db::FileLoader; |
568 | 539 | ||
569 | use crate::fixture; | 540 | use crate::{fixture, hover::HoverDocFormat, HoverConfig}; |
570 | 541 | ||
571 | fn check_hover_no_result(ra_fixture: &str) { | 542 | fn check_hover_no_result(ra_fixture: &str) { |
572 | let (analysis, position) = fixture::position(ra_fixture); | 543 | let (analysis, position) = fixture::position(ra_fixture); |
573 | assert!(analysis.hover(position, true, true).unwrap().is_none()); | 544 | assert!(analysis |
545 | .hover( | ||
546 | position, | ||
547 | &HoverConfig { | ||
548 | links_in_hover: true, | ||
549 | documentation: Some(HoverDocFormat::Markdown) | ||
550 | } | ||
551 | ) | ||
552 | .unwrap() | ||
553 | .is_none()); | ||
574 | } | 554 | } |
575 | 555 | ||
576 | fn check(ra_fixture: &str, expect: Expect) { | 556 | fn check(ra_fixture: &str, expect: Expect) { |
577 | let (analysis, position) = fixture::position(ra_fixture); | 557 | let (analysis, position) = fixture::position(ra_fixture); |
578 | let hover = analysis.hover(position, true, true).unwrap().unwrap(); | 558 | let hover = analysis |
559 | .hover( | ||
560 | position, | ||
561 | &HoverConfig { | ||
562 | links_in_hover: true, | ||
563 | documentation: Some(HoverDocFormat::Markdown), | ||
564 | }, | ||
565 | ) | ||
566 | .unwrap() | ||
567 | .unwrap(); | ||
579 | 568 | ||
580 | let content = analysis.db.file_text(position.file_id); | 569 | let content = analysis.db.file_text(position.file_id); |
581 | let hovered_element = &content[hover.range]; | 570 | let hovered_element = &content[hover.range]; |
@@ -586,7 +575,16 @@ mod tests { | |||
586 | 575 | ||
587 | fn check_hover_no_links(ra_fixture: &str, expect: Expect) { | 576 | fn check_hover_no_links(ra_fixture: &str, expect: Expect) { |
588 | let (analysis, position) = fixture::position(ra_fixture); | 577 | let (analysis, position) = fixture::position(ra_fixture); |
589 | let hover = analysis.hover(position, false, true).unwrap().unwrap(); | 578 | let hover = analysis |
579 | .hover( | ||
580 | position, | ||
581 | &HoverConfig { | ||
582 | links_in_hover: false, | ||
583 | documentation: Some(HoverDocFormat::Markdown), | ||
584 | }, | ||
585 | ) | ||
586 | .unwrap() | ||
587 | .unwrap(); | ||
590 | 588 | ||
591 | let content = analysis.db.file_text(position.file_id); | 589 | let content = analysis.db.file_text(position.file_id); |
592 | let hovered_element = &content[hover.range]; | 590 | let hovered_element = &content[hover.range]; |
@@ -597,7 +595,16 @@ mod tests { | |||
597 | 595 | ||
598 | fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) { | 596 | fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) { |
599 | let (analysis, position) = fixture::position(ra_fixture); | 597 | let (analysis, position) = fixture::position(ra_fixture); |
600 | let hover = analysis.hover(position, true, false).unwrap().unwrap(); | 598 | let hover = analysis |
599 | .hover( | ||
600 | position, | ||
601 | &HoverConfig { | ||
602 | links_in_hover: true, | ||
603 | documentation: Some(HoverDocFormat::PlainText), | ||
604 | }, | ||
605 | ) | ||
606 | .unwrap() | ||
607 | .unwrap(); | ||
601 | 608 | ||
602 | let content = analysis.db.file_text(position.file_id); | 609 | let content = analysis.db.file_text(position.file_id); |
603 | let hovered_element = &content[hover.range]; | 610 | let hovered_element = &content[hover.range]; |
@@ -608,7 +615,16 @@ mod tests { | |||
608 | 615 | ||
609 | fn check_actions(ra_fixture: &str, expect: Expect) { | 616 | fn check_actions(ra_fixture: &str, expect: Expect) { |
610 | let (analysis, position) = fixture::position(ra_fixture); | 617 | let (analysis, position) = fixture::position(ra_fixture); |
611 | let hover = analysis.hover(position, true, true).unwrap().unwrap(); | 618 | let hover = analysis |
619 | .hover( | ||
620 | position, | ||
621 | &HoverConfig { | ||
622 | links_in_hover: true, | ||
623 | documentation: Some(HoverDocFormat::Markdown), | ||
624 | }, | ||
625 | ) | ||
626 | .unwrap() | ||
627 | .unwrap(); | ||
612 | expect.assert_debug_eq(&hover.info.actions) | 628 | expect.assert_debug_eq(&hover.info.actions) |
613 | } | 629 | } |
614 | 630 | ||
@@ -2258,7 +2274,7 @@ pub fn fo$0o() {} | |||
2258 | case 13. collapsed link: foo | 2274 | case 13. collapsed link: foo |
2259 | case 14. shortcut link: foo | 2275 | case 14. shortcut link: foo |
2260 | case 15. inline without URL: foo | 2276 | case 15. inline without URL: foo |
2261 | case 16. just escaped text: \[foo] | 2277 | case 16. just escaped text: \[foo\] |
2262 | case 17. inline link: Foo | 2278 | case 17. inline link: Foo |
2263 | 2279 | ||
2264 | [^example]: https://www.example.com/ | 2280 | [^example]: https://www.example.com/ |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 4bd073cc3..b978e36af 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -75,7 +75,7 @@ pub use crate::{ | |||
75 | expand_macro::ExpandedMacro, | 75 | expand_macro::ExpandedMacro, |
76 | file_structure::{StructureNode, StructureNodeKind}, | 76 | file_structure::{StructureNode, StructureNodeKind}, |
77 | folding_ranges::{Fold, FoldKind}, | 77 | folding_ranges::{Fold, FoldKind}, |
78 | hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, | 78 | hover::{HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult}, |
79 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, | 79 | inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, |
80 | markup::Markup, | 80 | markup::Markup, |
81 | move_item::Direction, | 81 | move_item::Direction, |
@@ -217,6 +217,7 @@ impl Analysis { | |||
217 | file_id, | 217 | file_id, |
218 | Edition::Edition2018, | 218 | Edition::Edition2018, |
219 | None, | 219 | None, |
220 | cfg_options.clone(), | ||
220 | cfg_options, | 221 | cfg_options, |
221 | Env::default(), | 222 | Env::default(), |
222 | Default::default(), | 223 | Default::default(), |
@@ -407,10 +408,9 @@ impl Analysis { | |||
407 | pub fn hover( | 408 | pub fn hover( |
408 | &self, | 409 | &self, |
409 | position: FilePosition, | 410 | position: FilePosition, |
410 | links_in_hover: bool, | 411 | config: &HoverConfig, |
411 | markdown: bool, | ||
412 | ) -> Cancellable<Option<RangeInfo<HoverResult>>> { | 412 | ) -> Cancellable<Option<RangeInfo<HoverResult>>> { |
413 | self.with_db(|db| hover::hover(db, position, links_in_hover, markdown)) | 413 | self.with_db(|db| hover::hover(db, position, config)) |
414 | } | 414 | } |
415 | 415 | ||
416 | /// Return URL(s) for the documentation of the symbol under the cursor. | 416 | /// Return URL(s) for the documentation of the symbol under the cursor. |
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs index 8096dfa0e..96bd07708 100644 --- a/crates/ide/src/rename.rs +++ b/crates/ide/src/rename.rs | |||
@@ -10,7 +10,7 @@ use ide_db::{ | |||
10 | rename::{bail, format_err, source_edit_from_references, IdentifierKind}, | 10 | rename::{bail, format_err, source_edit_from_references, IdentifierKind}, |
11 | RootDatabase, | 11 | RootDatabase, |
12 | }; | 12 | }; |
13 | use stdx::never; | 13 | use stdx::{always, never}; |
14 | use syntax::{ast, AstNode, SyntaxNode}; | 14 | use syntax::{ast, AstNode, SyntaxNode}; |
15 | 15 | ||
16 | use text_edit::TextEdit; | 16 | use text_edit::TextEdit; |
@@ -31,10 +31,13 @@ pub(crate) fn prepare_rename( | |||
31 | let source_file = sema.parse(position.file_id); | 31 | let source_file = sema.parse(position.file_id); |
32 | let syntax = source_file.syntax(); | 32 | let syntax = source_file.syntax(); |
33 | 33 | ||
34 | let def = find_definition(&sema, syntax, position)?; | 34 | let (name_like, def) = find_definition(&sema, syntax, position)?; |
35 | let frange = def | 35 | if def.range_for_rename(&sema).is_none() { |
36 | .range_for_rename(&sema) | 36 | bail!("No references found at position") |
37 | .ok_or_else(|| format_err!("No references found at position"))?; | 37 | } |
38 | |||
39 | let frange = sema.original_range(name_like.syntax()); | ||
40 | always!(frange.range.contains_inclusive(position.offset) && frange.file_id == position.file_id); | ||
38 | Ok(RangeInfo::new(frange.range, ())) | 41 | Ok(RangeInfo::new(frange.range, ())) |
39 | } | 42 | } |
40 | 43 | ||
@@ -55,31 +58,23 @@ pub(crate) fn rename( | |||
55 | new_name: &str, | 58 | new_name: &str, |
56 | ) -> RenameResult<SourceChange> { | 59 | ) -> RenameResult<SourceChange> { |
57 | let sema = Semantics::new(db); | 60 | let sema = Semantics::new(db); |
58 | rename_with_semantics(&sema, position, new_name) | ||
59 | } | ||
60 | |||
61 | pub(crate) fn rename_with_semantics( | ||
62 | sema: &Semantics<RootDatabase>, | ||
63 | position: FilePosition, | ||
64 | new_name: &str, | ||
65 | ) -> RenameResult<SourceChange> { | ||
66 | let source_file = sema.parse(position.file_id); | 61 | let source_file = sema.parse(position.file_id); |
67 | let syntax = source_file.syntax(); | 62 | let syntax = source_file.syntax(); |
68 | 63 | ||
69 | let def = find_definition(sema, syntax, position)?; | 64 | let (_name_like, def) = find_definition(&sema, syntax, position)?; |
70 | 65 | ||
71 | if let Definition::Local(local) = def { | 66 | if let Definition::Local(local) = def { |
72 | if let Some(self_param) = local.as_self_param(sema.db) { | 67 | if let Some(self_param) = local.as_self_param(sema.db) { |
73 | cov_mark::hit!(rename_self_to_param); | 68 | cov_mark::hit!(rename_self_to_param); |
74 | return rename_self_to_param(sema, local, self_param, new_name); | 69 | return rename_self_to_param(&sema, local, self_param, new_name); |
75 | } | 70 | } |
76 | if new_name == "self" { | 71 | if new_name == "self" { |
77 | cov_mark::hit!(rename_to_self); | 72 | cov_mark::hit!(rename_to_self); |
78 | return rename_to_self(sema, local); | 73 | return rename_to_self(&sema, local); |
79 | } | 74 | } |
80 | } | 75 | } |
81 | 76 | ||
82 | def.rename(sema, new_name) | 77 | def.rename(&sema, new_name) |
83 | } | 78 | } |
84 | 79 | ||
85 | /// Called by the client when it is about to rename a file. | 80 | /// Called by the client when it is about to rename a file. |
@@ -100,11 +95,12 @@ fn find_definition( | |||
100 | sema: &Semantics<RootDatabase>, | 95 | sema: &Semantics<RootDatabase>, |
101 | syntax: &SyntaxNode, | 96 | syntax: &SyntaxNode, |
102 | position: FilePosition, | 97 | position: FilePosition, |
103 | ) -> RenameResult<Definition> { | 98 | ) -> RenameResult<(ast::NameLike, Definition)> { |
104 | match sema | 99 | let name_like = sema |
105 | .find_node_at_offset_with_descend(syntax, position.offset) | 100 | .find_node_at_offset_with_descend::<ast::NameLike>(syntax, position.offset) |
106 | .ok_or_else(|| format_err!("No references found at position"))? | 101 | .ok_or_else(|| format_err!("No references found at position"))?; |
107 | { | 102 | |
103 | let def = match &name_like { | ||
108 | // renaming aliases would rename the item being aliased as the HIR doesn't track aliases yet | 104 | // renaming aliases would rename the item being aliased as the HIR doesn't track aliases yet |
109 | ast::NameLike::Name(name) | 105 | ast::NameLike::Name(name) |
110 | if name.syntax().parent().map_or(false, |it| ast::Rename::can_cast(it.kind())) => | 106 | if name.syntax().parent().map_or(false, |it| ast::Rename::can_cast(it.kind())) => |
@@ -134,7 +130,9 @@ fn find_definition( | |||
134 | .map(|it| it.referenced_or_defined(sema.db)) | 130 | .map(|it| it.referenced_or_defined(sema.db)) |
135 | }), | 131 | }), |
136 | } | 132 | } |
137 | .ok_or_else(|| format_err!("No references found at position")) | 133 | .ok_or_else(|| format_err!("No references found at position"))?; |
134 | |||
135 | Ok((name_like, def)) | ||
138 | } | 136 | } |
139 | 137 | ||
140 | fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> { | 138 | fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> { |
@@ -328,7 +326,7 @@ mod tests { | |||
328 | fn test_prepare_rename_namelikes() { | 326 | fn test_prepare_rename_namelikes() { |
329 | check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]); | 327 | check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]); |
330 | check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]); | 328 | check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]); |
331 | check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"3..7: name"#]]); | 329 | check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]); |
332 | } | 330 | } |
333 | 331 | ||
334 | #[test] | 332 | #[test] |
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs index 4ad49eca0..37ae92350 100644 --- a/crates/ide/src/typing.rs +++ b/crates/ide/src/typing.rs | |||
@@ -23,7 +23,7 @@ use syntax::{ | |||
23 | algo::find_node_at_offset, | 23 | algo::find_node_at_offset, |
24 | ast::{self, edit::IndentLevel, AstToken}, | 24 | ast::{self, edit::IndentLevel, AstToken}, |
25 | AstNode, Parse, SourceFile, | 25 | AstNode, Parse, SourceFile, |
26 | SyntaxKind::{FIELD_EXPR, METHOD_CALL_EXPR}, | 26 | SyntaxKind::{self, FIELD_EXPR, METHOD_CALL_EXPR}, |
27 | TextRange, TextSize, | 27 | TextRange, TextSize, |
28 | }; | 28 | }; |
29 | 29 | ||
@@ -95,9 +95,16 @@ fn on_opening_brace_typed(file: &Parse<SourceFile>, offset: TextSize) -> Option< | |||
95 | } | 95 | } |
96 | 96 | ||
97 | let brace_token = file.tree().syntax().token_at_offset(offset).right_biased()?; | 97 | let brace_token = file.tree().syntax().token_at_offset(offset).right_biased()?; |
98 | if brace_token.kind() != SyntaxKind::L_CURLY { | ||
99 | return None; | ||
100 | } | ||
98 | 101 | ||
99 | // Remove the `{` to get a better parse tree, and reparse | 102 | // Remove the `{` to get a better parse tree, and reparse. |
100 | let file = file.reparse(&Indel::delete(brace_token.text_range())); | 103 | let range = brace_token.text_range(); |
104 | if !stdx::always!(range.len() == TextSize::of('{')) { | ||
105 | return None; | ||
106 | } | ||
107 | let file = file.reparse(&Indel::delete(range)); | ||
101 | 108 | ||
102 | if let Some(edit) = brace_expr(&file.tree(), offset) { | 109 | if let Some(edit) = brace_expr(&file.tree(), offset) { |
103 | return Some(edit); | 110 | return Some(edit); |
@@ -550,6 +557,29 @@ fn f() { | |||
550 | } | 557 | } |
551 | 558 | ||
552 | #[test] | 559 | #[test] |
560 | fn noop_in_string_literal() { | ||
561 | // Regression test for #9351 | ||
562 | type_char_noop( | ||
563 | '{', | ||
564 | r##" | ||
565 | fn check_with(ra_fixture: &str, expect: Expect) { | ||
566 | let base = r#" | ||
567 | enum E { T(), R$0, C } | ||
568 | use self::E::X; | ||
569 | const Z: E = E::C; | ||
570 | mod m {} | ||
571 | asdasdasdasdasdasda | ||
572 | sdasdasdasdasdasda | ||
573 | sdasdasdasdasd | ||
574 | "#; | ||
575 | let actual = completion_list(&format!("{}\n{}", base, ra_fixture)); | ||
576 | expect.assert_eq(&actual) | ||
577 | } | ||
578 | "##, | ||
579 | ); | ||
580 | } | ||
581 | |||
582 | #[test] | ||
553 | fn adds_closing_brace_for_use_tree() { | 583 | fn adds_closing_brace_for_use_tree() { |
554 | type_char( | 584 | type_char( |
555 | '{', | 585 | '{', |
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs index 8df8b060d..accc345fc 100644 --- a/crates/ide_assists/src/handlers/auto_import.rs +++ b/crates/ide_assists/src/handlers/auto_import.rs | |||
@@ -995,62 +995,4 @@ const _: () = { | |||
995 | "#, | 995 | "#, |
996 | ); | 996 | ); |
997 | } | 997 | } |
998 | |||
999 | #[test] | ||
1000 | fn respects_cfg_attr() { | ||
1001 | check_assist( | ||
1002 | auto_import, | ||
1003 | r#" | ||
1004 | mod bar { | ||
1005 | pub struct Bar; | ||
1006 | } | ||
1007 | |||
1008 | #[cfg(test)] | ||
1009 | fn foo() { | ||
1010 | Bar$0 | ||
1011 | } | ||
1012 | "#, | ||
1013 | r#" | ||
1014 | mod bar { | ||
1015 | pub struct Bar; | ||
1016 | } | ||
1017 | |||
1018 | #[cfg(test)] | ||
1019 | fn foo() { | ||
1020 | use bar::Bar; | ||
1021 | |||
1022 | Bar | ||
1023 | } | ||
1024 | "#, | ||
1025 | ); | ||
1026 | } | ||
1027 | |||
1028 | #[test] | ||
1029 | fn respects_cfg_attr2() { | ||
1030 | check_assist( | ||
1031 | auto_import, | ||
1032 | r#" | ||
1033 | mod bar { | ||
1034 | pub struct Bar; | ||
1035 | } | ||
1036 | |||
1037 | #[cfg(test)] | ||
1038 | const FOO: Bar = { | ||
1039 | Bar$0 | ||
1040 | } | ||
1041 | "#, | ||
1042 | r#" | ||
1043 | mod bar { | ||
1044 | pub struct Bar; | ||
1045 | } | ||
1046 | |||
1047 | #[cfg(test)] | ||
1048 | const FOO: Bar = { | ||
1049 | use bar::Bar; | ||
1050 | |||
1051 | Bar | ||
1052 | } | ||
1053 | "#, | ||
1054 | ); | ||
1055 | } | ||
1056 | } | 998 | } |
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index ac7f0959b..870d4f665 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs | |||
@@ -109,10 +109,15 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option | |||
109 | 109 | ||
110 | let new_indent = IndentLevel::from_node(&insert_after); | 110 | let new_indent = IndentLevel::from_node(&insert_after); |
111 | let old_indent = fun.body.indent_level(); | 111 | let old_indent = fun.body.indent_level(); |
112 | let body_contains_await = body_contains_await(&fun.body); | ||
112 | 113 | ||
113 | builder.replace(target_range, format_replacement(ctx, &fun, old_indent)); | 114 | builder.replace( |
115 | target_range, | ||
116 | format_replacement(ctx, &fun, old_indent, body_contains_await), | ||
117 | ); | ||
114 | 118 | ||
115 | let fn_def = format_function(ctx, module, &fun, old_indent, new_indent); | 119 | let fn_def = |
120 | format_function(ctx, module, &fun, old_indent, new_indent, body_contains_await); | ||
116 | let insert_offset = insert_after.text_range().end(); | 121 | let insert_offset = insert_after.text_range().end(); |
117 | match ctx.config.snippet_cap { | 122 | match ctx.config.snippet_cap { |
118 | Some(cap) => builder.insert_snippet(cap, insert_offset, fn_def), | 123 | Some(cap) => builder.insert_snippet(cap, insert_offset, fn_def), |
@@ -954,7 +959,12 @@ fn scope_for_fn_insertion_node(node: &SyntaxNode, anchor: Anchor) -> Option<Synt | |||
954 | last_ancestor | 959 | last_ancestor |
955 | } | 960 | } |
956 | 961 | ||
957 | fn format_replacement(ctx: &AssistContext, fun: &Function, indent: IndentLevel) -> String { | 962 | fn format_replacement( |
963 | ctx: &AssistContext, | ||
964 | fun: &Function, | ||
965 | indent: IndentLevel, | ||
966 | body_contains_await: bool, | ||
967 | ) -> String { | ||
958 | let ret_ty = fun.return_type(ctx); | 968 | let ret_ty = fun.return_type(ctx); |
959 | 969 | ||
960 | let args = fun.params.iter().map(|param| param.to_arg(ctx)); | 970 | let args = fun.params.iter().map(|param| param.to_arg(ctx)); |
@@ -994,6 +1004,9 @@ fn format_replacement(ctx: &AssistContext, fun: &Function, indent: IndentLevel) | |||
994 | } | 1004 | } |
995 | } | 1005 | } |
996 | format_to!(buf, "{}", expr); | 1006 | format_to!(buf, "{}", expr); |
1007 | if body_contains_await { | ||
1008 | buf.push_str(".await"); | ||
1009 | } | ||
997 | if fun.ret_ty.is_unit() | 1010 | if fun.ret_ty.is_unit() |
998 | && (!fun.vars_defined_in_body_and_outlive.is_empty() || !expr.is_block_like()) | 1011 | && (!fun.vars_defined_in_body_and_outlive.is_empty() || !expr.is_block_like()) |
999 | { | 1012 | { |
@@ -1122,12 +1135,13 @@ fn format_function( | |||
1122 | fun: &Function, | 1135 | fun: &Function, |
1123 | old_indent: IndentLevel, | 1136 | old_indent: IndentLevel, |
1124 | new_indent: IndentLevel, | 1137 | new_indent: IndentLevel, |
1138 | body_contains_await: bool, | ||
1125 | ) -> String { | 1139 | ) -> String { |
1126 | let mut fn_def = String::new(); | 1140 | let mut fn_def = String::new(); |
1127 | let params = make_param_list(ctx, module, fun); | 1141 | let params = make_param_list(ctx, module, fun); |
1128 | let ret_ty = make_ret_ty(ctx, module, fun); | 1142 | let ret_ty = make_ret_ty(ctx, module, fun); |
1129 | let body = make_body(ctx, old_indent, new_indent, fun); | 1143 | let body = make_body(ctx, old_indent, new_indent, fun); |
1130 | let async_kw = if body_contains_await(&fun.body) { "async " } else { "" }; | 1144 | let async_kw = if body_contains_await { "async " } else { "" }; |
1131 | match ctx.config.snippet_cap { | 1145 | match ctx.config.snippet_cap { |
1132 | Some(_) => format_to!(fn_def, "\n\n{}{}fn $0{}{}", new_indent, async_kw, fun.name, params), | 1146 | Some(_) => format_to!(fn_def, "\n\n{}{}fn $0{}{}", new_indent, async_kw, fun.name, params), |
1133 | None => format_to!(fn_def, "\n\n{}{}fn {}{}", new_indent, async_kw, fun.name, params), | 1147 | None => format_to!(fn_def, "\n\n{}{}fn {}{}", new_indent, async_kw, fun.name, params), |
@@ -3681,7 +3695,7 @@ async fn some_function() { | |||
3681 | "#, | 3695 | "#, |
3682 | r#" | 3696 | r#" |
3683 | fn main() { | 3697 | fn main() { |
3684 | fun_name(); | 3698 | fun_name().await; |
3685 | } | 3699 | } |
3686 | 3700 | ||
3687 | async fn $0fun_name() { | 3701 | async fn $0fun_name() { |
@@ -3710,7 +3724,7 @@ async fn some_function() { | |||
3710 | "#, | 3724 | "#, |
3711 | r#" | 3725 | r#" |
3712 | fn main() { | 3726 | fn main() { |
3713 | fun_name(); | 3727 | fun_name().await; |
3714 | } | 3728 | } |
3715 | 3729 | ||
3716 | async fn $0fun_name() { | 3730 | async fn $0fun_name() { |
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs index 78fc30e16..cc4f4b2af 100644 --- a/crates/ide_completion/src/completions/attribute.rs +++ b/crates/ide_completion/src/completions/attribute.rs | |||
@@ -15,6 +15,7 @@ use crate::{ | |||
15 | Completions, | 15 | Completions, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | mod cfg; | ||
18 | mod derive; | 19 | mod derive; |
19 | mod lint; | 20 | mod lint; |
20 | mod repr; | 21 | mod repr; |
@@ -30,6 +31,9 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) | |||
30 | lint::complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINTS); | 31 | lint::complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINTS); |
31 | lint::complete_lint(acc, ctx, token_tree, CLIPPY_LINTS); | 32 | lint::complete_lint(acc, ctx, token_tree, CLIPPY_LINTS); |
32 | } | 33 | } |
34 | "cfg" => { | ||
35 | cfg::complete_cfg(acc, ctx); | ||
36 | } | ||
33 | _ => (), | 37 | _ => (), |
34 | }, | 38 | }, |
35 | (None, Some(_)) => (), | 39 | (None, Some(_)) => (), |
@@ -852,4 +856,15 @@ mod tests { | |||
852 | "#]], | 856 | "#]], |
853 | ); | 857 | ); |
854 | } | 858 | } |
859 | |||
860 | #[test] | ||
861 | fn test_cfg() { | ||
862 | check( | ||
863 | r#"#[cfg(target_endian = $0"#, | ||
864 | expect![[r#" | ||
865 | at little | ||
866 | at big | ||
867 | "#]], | ||
868 | ); | ||
869 | } | ||
855 | } | 870 | } |
diff --git a/crates/ide_completion/src/completions/attribute/cfg.rs b/crates/ide_completion/src/completions/attribute/cfg.rs new file mode 100644 index 000000000..847e6529a --- /dev/null +++ b/crates/ide_completion/src/completions/attribute/cfg.rs | |||
@@ -0,0 +1,112 @@ | |||
1 | //! Completion for cfg | ||
2 | |||
3 | use std::iter; | ||
4 | |||
5 | use syntax::SyntaxKind; | ||
6 | |||
7 | use crate::{ | ||
8 | completions::Completions, context::CompletionContext, item::CompletionKind, CompletionItem, | ||
9 | CompletionItemKind, | ||
10 | }; | ||
11 | |||
12 | pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) { | ||
13 | let add_completion = |item: &&str| { | ||
14 | let mut completion = | ||
15 | CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), *item); | ||
16 | completion.insert_text(format!(r#""{}""#, item)); | ||
17 | completion.kind(CompletionItemKind::Attribute); | ||
18 | acc.add(completion.build()); | ||
19 | }; | ||
20 | |||
21 | let previous = iter::successors(ctx.original_token.prev_token(), |t| { | ||
22 | (matches!(t.kind(), SyntaxKind::EQ) || t.kind().is_trivia()) | ||
23 | .then(|| t.prev_token()) | ||
24 | .flatten() | ||
25 | }) | ||
26 | .find(|t| matches!(t.kind(), SyntaxKind::IDENT)); | ||
27 | |||
28 | match previous.as_ref().map(|p| p.text()) { | ||
29 | Some("target_arch") => KNOWN_ARCH.iter().for_each(add_completion), | ||
30 | Some("target_env") => KNOWN_ENV.iter().for_each(add_completion), | ||
31 | Some("target_os") => KNOWN_OS.iter().for_each(add_completion), | ||
32 | Some("target_vendor") => KNOWN_VENDOR.iter().for_each(add_completion), | ||
33 | Some("target_endian") => ["little", "big"].iter().for_each(add_completion), | ||
34 | Some(name) => { | ||
35 | ctx.krate.map(|krate| { | ||
36 | krate.potential_cfg(ctx.db).get_cfg_values(&name).iter().for_each(|s| { | ||
37 | let mut item = CompletionItem::new( | ||
38 | CompletionKind::Attribute, | ||
39 | ctx.source_range(), | ||
40 | s.as_str(), | ||
41 | ); | ||
42 | item.insert_text(format!(r#""{}""#, s)); | ||
43 | |||
44 | acc.add(item.build()); | ||
45 | }) | ||
46 | }); | ||
47 | } | ||
48 | None => { | ||
49 | ctx.krate.map(|krate| { | ||
50 | krate.potential_cfg(ctx.db).get_cfg_keys().iter().for_each(|s| { | ||
51 | let item = CompletionItem::new( | ||
52 | CompletionKind::Attribute, | ||
53 | ctx.source_range(), | ||
54 | s.as_str(), | ||
55 | ); | ||
56 | acc.add(item.build()); | ||
57 | }) | ||
58 | }); | ||
59 | } | ||
60 | }; | ||
61 | } | ||
62 | |||
63 | const KNOWN_ARCH: [&'static str; 19] = [ | ||
64 | "aarch64", | ||
65 | "arm", | ||
66 | "avr", | ||
67 | "hexagon", | ||
68 | "mips", | ||
69 | "mips64", | ||
70 | "msp430", | ||
71 | "nvptx64", | ||
72 | "powerpc", | ||
73 | "powerpc64", | ||
74 | "riscv32", | ||
75 | "riscv64", | ||
76 | "s390x", | ||
77 | "sparc", | ||
78 | "sparc64", | ||
79 | "wasm32", | ||
80 | "wasm64", | ||
81 | "x86", | ||
82 | "x86_64", | ||
83 | ]; | ||
84 | |||
85 | const KNOWN_ENV: [&'static str; 7] = | ||
86 | ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"]; | ||
87 | |||
88 | const KNOWN_OS: [&'static str; 20] = [ | ||
89 | "cuda", | ||
90 | "dragonfly", | ||
91 | "emscripten", | ||
92 | "freebsd", | ||
93 | "fuchsia", | ||
94 | "haiku", | ||
95 | "hermit", | ||
96 | "illumos", | ||
97 | "l4re", | ||
98 | "linux", | ||
99 | "netbsd", | ||
100 | "none", | ||
101 | "openbsd", | ||
102 | "psp", | ||
103 | "redox", | ||
104 | "solaris", | ||
105 | "uefi", | ||
106 | "unknown", | ||
107 | "vxworks", | ||
108 | "windows", | ||
109 | ]; | ||
110 | |||
111 | const KNOWN_VENDOR: [&'static str; 8] = | ||
112 | ["apple", "fortanix", "nvidia", "pc", "sony", "unknown", "wrs", "uwp"]; | ||
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs index 07541c79c..407f796ef 100644 --- a/crates/ide_completion/src/completions/keyword.rs +++ b/crates/ide_completion/src/completions/keyword.rs | |||
@@ -92,7 +92,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
92 | } | 92 | } |
93 | 93 | ||
94 | if !ctx.has_visibility_prev_sibling() | 94 | if !ctx.has_visibility_prev_sibling() |
95 | && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_record_field()) | 95 | && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field()) |
96 | { | 96 | { |
97 | add_keyword("pub(crate)", "pub(crate) "); | 97 | add_keyword("pub(crate)", "pub(crate) "); |
98 | add_keyword("pub", "pub "); | 98 | add_keyword("pub", "pub "); |
@@ -122,6 +122,10 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
122 | add_keyword("union", "union $1 {\n $0\n}"); | 122 | add_keyword("union", "union $1 {\n $0\n}"); |
123 | } | 123 | } |
124 | 124 | ||
125 | if ctx.expects_type() { | ||
126 | return; | ||
127 | } | ||
128 | |||
125 | if ctx.expects_expression() { | 129 | if ctx.expects_expression() { |
126 | if !has_block_expr_parent { | 130 | if !has_block_expr_parent { |
127 | add_keyword("unsafe", "unsafe {\n $0\n}"); | 131 | add_keyword("unsafe", "unsafe {\n $0\n}"); |
@@ -373,28 +377,6 @@ fn quux() -> i32 { | |||
373 | } | 377 | } |
374 | 378 | ||
375 | #[test] | 379 | #[test] |
376 | fn test_mut_in_ref_and_in_fn_parameters_list() { | ||
377 | check( | ||
378 | r"fn my_fn(&$0) {}", | ||
379 | expect![[r#" | ||
380 | kw mut | ||
381 | "#]], | ||
382 | ); | ||
383 | check( | ||
384 | r"fn my_fn($0) {}", | ||
385 | expect![[r#" | ||
386 | kw mut | ||
387 | "#]], | ||
388 | ); | ||
389 | check( | ||
390 | r"fn my_fn() { let &$0 }", | ||
391 | expect![[r#" | ||
392 | kw mut | ||
393 | "#]], | ||
394 | ); | ||
395 | } | ||
396 | |||
397 | #[test] | ||
398 | fn no_keyword_completion_in_comments() { | 380 | fn no_keyword_completion_in_comments() { |
399 | cov_mark::check!(no_keyword_completion_in_comments); | 381 | cov_mark::check!(no_keyword_completion_in_comments); |
400 | check( | 382 | check( |
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs index efe3c957a..bd13a62d7 100644 --- a/crates/ide_completion/src/completions/pattern.rs +++ b/crates/ide_completion/src/completions/pattern.rs | |||
@@ -55,398 +55,3 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
55 | } | 55 | } |
56 | }); | 56 | }); |
57 | } | 57 | } |
58 | |||
59 | #[cfg(test)] | ||
60 | mod tests { | ||
61 | use expect_test::{expect, Expect}; | ||
62 | |||
63 | use crate::{ | ||
64 | tests::{check_edit, filtered_completion_list}, | ||
65 | CompletionKind, | ||
66 | }; | ||
67 | |||
68 | fn check(ra_fixture: &str, expect: Expect) { | ||
69 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Reference); | ||
70 | expect.assert_eq(&actual) | ||
71 | } | ||
72 | |||
73 | fn check_snippet(ra_fixture: &str, expect: Expect) { | ||
74 | let actual = filtered_completion_list(ra_fixture, CompletionKind::Snippet); | ||
75 | expect.assert_eq(&actual) | ||
76 | } | ||
77 | |||
78 | #[test] | ||
79 | fn completes_enum_variants_and_modules() { | ||
80 | check( | ||
81 | r#" | ||
82 | enum E { X } | ||
83 | use self::E::X; | ||
84 | const Z: E = E::X; | ||
85 | mod m {} | ||
86 | |||
87 | static FOO: E = E::X; | ||
88 | struct Bar { f: u32 } | ||
89 | |||
90 | fn foo() { | ||
91 | match E::X { a$0 } | ||
92 | } | ||
93 | "#, | ||
94 | expect![[r#" | ||
95 | en E | ||
96 | ct Z | ||
97 | st Bar | ||
98 | ev X | ||
99 | md m | ||
100 | "#]], | ||
101 | ); | ||
102 | } | ||
103 | |||
104 | #[test] | ||
105 | fn does_not_complete_non_fn_macros() { | ||
106 | check( | ||
107 | r#" | ||
108 | macro_rules! m { ($e:expr) => { $e } } | ||
109 | enum E { X } | ||
110 | |||
111 | #[rustc_builtin_macro] | ||
112 | macro Clone {} | ||
113 | |||
114 | fn foo() { | ||
115 | match E::X { $0 } | ||
116 | } | ||
117 | "#, | ||
118 | expect![[r#" | ||
119 | ev E::X () | ||
120 | en E | ||
121 | ma m!(…) macro_rules! m | ||
122 | "#]], | ||
123 | ); | ||
124 | } | ||
125 | |||
126 | #[test] | ||
127 | fn completes_in_simple_macro_call() { | ||
128 | check( | ||
129 | r#" | ||
130 | macro_rules! m { ($e:expr) => { $e } } | ||
131 | enum E { X } | ||
132 | |||
133 | fn foo() { | ||
134 | m!(match E::X { a$0 }) | ||
135 | } | ||
136 | "#, | ||
137 | expect![[r#" | ||
138 | ev E::X () | ||
139 | en E | ||
140 | ma m!(…) macro_rules! m | ||
141 | "#]], | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | #[test] | ||
146 | fn completes_in_irrefutable_let() { | ||
147 | check( | ||
148 | r#" | ||
149 | enum E { X } | ||
150 | use self::E::X; | ||
151 | const Z: E = E::X; | ||
152 | mod m {} | ||
153 | |||
154 | static FOO: E = E::X; | ||
155 | struct Bar { f: u32 } | ||
156 | |||
157 | fn foo() { | ||
158 | let a$0 | ||
159 | } | ||
160 | "#, | ||
161 | expect![[r#" | ||
162 | st Bar | ||
163 | "#]], | ||
164 | ); | ||
165 | } | ||
166 | |||
167 | #[test] | ||
168 | fn completes_in_param() { | ||
169 | check( | ||
170 | r#" | ||
171 | enum E { X } | ||
172 | |||
173 | static FOO: E = E::X; | ||
174 | struct Bar { f: u32 } | ||
175 | |||
176 | fn foo(a$0) { | ||
177 | } | ||
178 | "#, | ||
179 | expect![[r#" | ||
180 | st Bar | ||
181 | "#]], | ||
182 | ); | ||
183 | } | ||
184 | |||
185 | #[test] | ||
186 | fn completes_pat_in_let() { | ||
187 | check_snippet( | ||
188 | r#" | ||
189 | struct Bar { f: u32 } | ||
190 | |||
191 | fn foo() { | ||
192 | let a$0 | ||
193 | } | ||
194 | "#, | ||
195 | expect![[r#" | ||
196 | bn Bar Bar { f$1 }$0 | ||
197 | "#]], | ||
198 | ); | ||
199 | } | ||
200 | |||
201 | #[test] | ||
202 | fn completes_param_pattern() { | ||
203 | check_snippet( | ||
204 | r#" | ||
205 | struct Foo { bar: String, baz: String } | ||
206 | struct Bar(String, String); | ||
207 | struct Baz; | ||
208 | fn outer(a$0) {} | ||
209 | "#, | ||
210 | expect![[r#" | ||
211 | bn Foo Foo { bar$1, baz$2 }: Foo$0 | ||
212 | bn Bar Bar($1, $2): Bar$0 | ||
213 | "#]], | ||
214 | ) | ||
215 | } | ||
216 | |||
217 | #[test] | ||
218 | fn completes_let_pattern() { | ||
219 | check_snippet( | ||
220 | r#" | ||
221 | struct Foo { bar: String, baz: String } | ||
222 | struct Bar(String, String); | ||
223 | struct Baz; | ||
224 | fn outer() { | ||
225 | let a$0 | ||
226 | } | ||
227 | "#, | ||
228 | expect![[r#" | ||
229 | bn Foo Foo { bar$1, baz$2 }$0 | ||
230 | bn Bar Bar($1, $2)$0 | ||
231 | "#]], | ||
232 | ) | ||
233 | } | ||
234 | |||
235 | #[test] | ||
236 | fn completes_refutable_pattern() { | ||
237 | check_snippet( | ||
238 | r#" | ||
239 | struct Foo { bar: i32, baz: i32 } | ||
240 | struct Bar(String, String); | ||
241 | struct Baz; | ||
242 | fn outer() { | ||
243 | match () { | ||
244 | a$0 | ||
245 | } | ||
246 | } | ||
247 | "#, | ||
248 | expect![[r#" | ||
249 | bn Foo Foo { bar$1, baz$2 }$0 | ||
250 | bn Bar Bar($1, $2)$0 | ||
251 | "#]], | ||
252 | ) | ||
253 | } | ||
254 | |||
255 | #[test] | ||
256 | fn omits_private_fields_pat() { | ||
257 | check_snippet( | ||
258 | r#" | ||
259 | mod foo { | ||
260 | pub struct Foo { pub bar: i32, baz: i32 } | ||
261 | pub struct Bar(pub String, String); | ||
262 | pub struct Invisible(String, String); | ||
263 | } | ||
264 | use foo::*; | ||
265 | |||
266 | fn outer() { | ||
267 | match () { | ||
268 | a$0 | ||
269 | } | ||
270 | } | ||
271 | "#, | ||
272 | expect![[r#" | ||
273 | bn Foo Foo { bar$1, .. }$0 | ||
274 | bn Bar Bar($1, ..)$0 | ||
275 | "#]], | ||
276 | ) | ||
277 | } | ||
278 | |||
279 | #[test] | ||
280 | fn only_shows_ident_completion() { | ||
281 | check_edit( | ||
282 | "Foo", | ||
283 | r#" | ||
284 | struct Foo(i32); | ||
285 | fn main() { | ||
286 | match Foo(92) { | ||
287 | a$0(92) => (), | ||
288 | } | ||
289 | } | ||
290 | "#, | ||
291 | r#" | ||
292 | struct Foo(i32); | ||
293 | fn main() { | ||
294 | match Foo(92) { | ||
295 | Foo(92) => (), | ||
296 | } | ||
297 | } | ||
298 | "#, | ||
299 | ); | ||
300 | } | ||
301 | |||
302 | #[test] | ||
303 | fn completes_self_pats() { | ||
304 | check_snippet( | ||
305 | r#" | ||
306 | struct Foo(i32); | ||
307 | impl Foo { | ||
308 | fn foo() { | ||
309 | match () { | ||
310 | a$0 | ||
311 | } | ||
312 | } | ||
313 | } | ||
314 | "#, | ||
315 | expect![[r#" | ||
316 | bn Self Self($1)$0 | ||
317 | bn Foo Foo($1)$0 | ||
318 | "#]], | ||
319 | ) | ||
320 | } | ||
321 | |||
322 | #[test] | ||
323 | fn completes_qualified_variant() { | ||
324 | check_snippet( | ||
325 | r#" | ||
326 | enum Foo { | ||
327 | Bar { baz: i32 } | ||
328 | } | ||
329 | impl Foo { | ||
330 | fn foo() { | ||
331 | match {Foo::Bar { baz: 0 }} { | ||
332 | B$0 | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | "#, | ||
337 | expect![[r#" | ||
338 | bn Self::Bar Self::Bar { baz$1 }$0 | ||
339 | bn Foo::Bar Foo::Bar { baz$1 }$0 | ||
340 | "#]], | ||
341 | ) | ||
342 | } | ||
343 | |||
344 | #[test] | ||
345 | fn completes_enum_variant_matcharm() { | ||
346 | check( | ||
347 | r#" | ||
348 | enum Foo { Bar, Baz, Quux } | ||
349 | |||
350 | fn main() { | ||
351 | let foo = Foo::Quux; | ||
352 | match foo { Qu$0 } | ||
353 | } | ||
354 | "#, | ||
355 | expect![[r#" | ||
356 | ev Foo::Bar () | ||
357 | ev Foo::Baz () | ||
358 | ev Foo::Quux () | ||
359 | en Foo | ||
360 | "#]], | ||
361 | ) | ||
362 | } | ||
363 | |||
364 | #[test] | ||
365 | fn completes_enum_variant_matcharm_ref() { | ||
366 | check( | ||
367 | r#" | ||
368 | enum Foo { Bar, Baz, Quux } | ||
369 | |||
370 | fn main() { | ||
371 | let foo = Foo::Quux; | ||
372 | match &foo { Qu$0 } | ||
373 | } | ||
374 | "#, | ||
375 | expect![[r#" | ||
376 | ev Foo::Bar () | ||
377 | ev Foo::Baz () | ||
378 | ev Foo::Quux () | ||
379 | en Foo | ||
380 | "#]], | ||
381 | ) | ||
382 | } | ||
383 | |||
384 | #[test] | ||
385 | fn completes_enum_variant_iflet() { | ||
386 | check( | ||
387 | r#" | ||
388 | enum Foo { Bar, Baz, Quux } | ||
389 | |||
390 | fn main() { | ||
391 | let foo = Foo::Quux; | ||
392 | if let Qu$0 = foo { } | ||
393 | } | ||
394 | "#, | ||
395 | expect![[r#" | ||
396 | ev Foo::Bar () | ||
397 | ev Foo::Baz () | ||
398 | ev Foo::Quux () | ||
399 | en Foo | ||
400 | "#]], | ||
401 | ) | ||
402 | } | ||
403 | |||
404 | #[test] | ||
405 | fn completes_enum_variant_impl() { | ||
406 | check( | ||
407 | r#" | ||
408 | enum Foo { Bar, Baz, Quux } | ||
409 | impl Foo { | ||
410 | fn foo() { match Foo::Bar { Q$0 } } | ||
411 | } | ||
412 | "#, | ||
413 | expect![[r#" | ||
414 | ev Self::Bar () | ||
415 | ev Self::Baz () | ||
416 | ev Self::Quux () | ||
417 | ev Foo::Bar () | ||
418 | ev Foo::Baz () | ||
419 | ev Foo::Quux () | ||
420 | sp Self | ||
421 | en Foo | ||
422 | "#]], | ||
423 | ) | ||
424 | } | ||
425 | |||
426 | #[test] | ||
427 | fn completes_in_record_field_pat() { | ||
428 | check_snippet( | ||
429 | r#" | ||
430 | struct Foo { bar: Bar } | ||
431 | struct Bar(u32); | ||
432 | fn outer(Foo { bar: $0 }: Foo) {} | ||
433 | "#, | ||
434 | expect![[r#" | ||
435 | bn Foo Foo { bar$1 }$0 | ||
436 | bn Bar Bar($1)$0 | ||
437 | "#]], | ||
438 | ) | ||
439 | } | ||
440 | |||
441 | #[test] | ||
442 | fn skips_in_record_field_pat_name() { | ||
443 | check_snippet( | ||
444 | r#" | ||
445 | struct Foo { bar: Bar } | ||
446 | struct Bar(u32); | ||
447 | fn outer(Foo { bar$0 }: Foo) {} | ||
448 | "#, | ||
449 | expect![[r#""#]], | ||
450 | ) | ||
451 | } | ||
452 | } | ||
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index f5dbd203b..1b8997ecf 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs | |||
@@ -219,36 +219,6 @@ mod tests { | |||
219 | } | 219 | } |
220 | 220 | ||
221 | #[test] | 221 | #[test] |
222 | fn dont_complete_values_in_type_pos() { | ||
223 | check( | ||
224 | r#" | ||
225 | const FOO: () = (); | ||
226 | static BAR: () = (); | ||
227 | struct Baz; | ||
228 | fn foo() { | ||
229 | let _: self::$0; | ||
230 | } | ||
231 | "#, | ||
232 | expect![[r#" | ||
233 | st Baz | ||
234 | "#]], | ||
235 | ); | ||
236 | } | ||
237 | |||
238 | #[test] | ||
239 | fn dont_complete_enum_variants_in_type_pos() { | ||
240 | check( | ||
241 | r#" | ||
242 | enum Foo { Bar } | ||
243 | fn foo() { | ||
244 | let _: Foo::$0; | ||
245 | } | ||
246 | "#, | ||
247 | expect![[r#""#]], | ||
248 | ); | ||
249 | } | ||
250 | |||
251 | #[test] | ||
252 | fn dont_complete_primitive_in_use() { | 222 | fn dont_complete_primitive_in_use() { |
253 | check_builtin(r#"use self::$0;"#, expect![[""]]); | 223 | check_builtin(r#"use self::$0;"#, expect![[""]]); |
254 | } | 224 | } |
@@ -259,32 +229,6 @@ fn foo() { | |||
259 | } | 229 | } |
260 | 230 | ||
261 | #[test] | 231 | #[test] |
262 | fn completes_primitives() { | ||
263 | check_builtin( | ||
264 | r#"fn main() { let _: $0 = 92; }"#, | ||
265 | expect![[r#" | ||
266 | bt u32 | ||
267 | bt bool | ||
268 | bt u8 | ||
269 | bt isize | ||
270 | bt u16 | ||
271 | bt u64 | ||
272 | bt u128 | ||
273 | bt f32 | ||
274 | bt i128 | ||
275 | bt i16 | ||
276 | bt str | ||
277 | bt i64 | ||
278 | bt char | ||
279 | bt f64 | ||
280 | bt i32 | ||
281 | bt i8 | ||
282 | bt usize | ||
283 | "#]], | ||
284 | ); | ||
285 | } | ||
286 | |||
287 | #[test] | ||
288 | fn completes_enum_variant() { | 232 | fn completes_enum_variant() { |
289 | check( | 233 | check( |
290 | r#" | 234 | r#" |
@@ -749,24 +693,4 @@ fn main() { | |||
749 | "#]], | 693 | "#]], |
750 | ); | 694 | ); |
751 | } | 695 | } |
752 | |||
753 | #[test] | ||
754 | fn completes_types_and_const_in_arg_list() { | ||
755 | check( | ||
756 | r#" | ||
757 | mod foo { | ||
758 | pub const CONST: () = (); | ||
759 | pub type Type = (); | ||
760 | } | ||
761 | |||
762 | struct Foo<T>(t); | ||
763 | |||
764 | fn foo(_: Foo<foo::$0>) {} | ||
765 | "#, | ||
766 | expect![[r#" | ||
767 | ta Type | ||
768 | ct CONST | ||
769 | "#]], | ||
770 | ); | ||
771 | } | ||
772 | } | 696 | } |
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs index 81c4fb305..380c1e079 100644 --- a/crates/ide_completion/src/completions/unqualified_path.rs +++ b/crates/ide_completion/src/completions/unqualified_path.rs | |||
@@ -113,78 +113,6 @@ mod tests { | |||
113 | } | 113 | } |
114 | 114 | ||
115 | #[test] | 115 | #[test] |
116 | fn dont_complete_values_in_type_pos() { | ||
117 | check( | ||
118 | r#" | ||
119 | const FOO: () = (); | ||
120 | static BAR: () = (); | ||
121 | enum Foo { | ||
122 | Bar | ||
123 | } | ||
124 | struct Baz; | ||
125 | fn foo() { | ||
126 | let local = (); | ||
127 | let _: $0; | ||
128 | } | ||
129 | "#, | ||
130 | expect![[r#" | ||
131 | en Foo | ||
132 | st Baz | ||
133 | "#]], | ||
134 | ); | ||
135 | } | ||
136 | |||
137 | #[test] | ||
138 | fn bind_pat_and_path_ignore_at() { | ||
139 | check( | ||
140 | r#" | ||
141 | enum Enum { A, B } | ||
142 | fn quux(x: Option<Enum>) { | ||
143 | match x { | ||
144 | None => (), | ||
145 | Some(en$0 @ Enum::A) => (), | ||
146 | } | ||
147 | } | ||
148 | "#, | ||
149 | expect![[r#""#]], | ||
150 | ); | ||
151 | } | ||
152 | |||
153 | #[test] | ||
154 | fn bind_pat_and_path_ignore_ref() { | ||
155 | check( | ||
156 | r#" | ||
157 | enum Enum { A, B } | ||
158 | fn quux(x: Option<Enum>) { | ||
159 | match x { | ||
160 | None => (), | ||
161 | Some(ref en$0) => (), | ||
162 | } | ||
163 | } | ||
164 | "#, | ||
165 | expect![[r#""#]], | ||
166 | ); | ||
167 | } | ||
168 | |||
169 | #[test] | ||
170 | fn bind_pat_and_path() { | ||
171 | check( | ||
172 | r#" | ||
173 | enum Enum { A, B } | ||
174 | fn quux(x: Option<Enum>) { | ||
175 | match x { | ||
176 | None => (), | ||
177 | Some(En$0) => (), | ||
178 | } | ||
179 | } | ||
180 | "#, | ||
181 | expect![[r#" | ||
182 | en Enum | ||
183 | "#]], | ||
184 | ); | ||
185 | } | ||
186 | |||
187 | #[test] | ||
188 | fn completes_bindings_from_let() { | 116 | fn completes_bindings_from_let() { |
189 | check( | 117 | check( |
190 | r#" | 118 | r#" |
@@ -289,29 +217,6 @@ fn main() { | |||
289 | } | 217 | } |
290 | 218 | ||
291 | #[test] | 219 | #[test] |
292 | fn completes_generic_params_in_struct() { | ||
293 | check( | ||
294 | r#"struct S<T> { x: $0}"#, | ||
295 | expect![[r#" | ||
296 | sp Self | ||
297 | tp T | ||
298 | st S<…> | ||
299 | "#]], | ||
300 | ); | ||
301 | } | ||
302 | |||
303 | #[test] | ||
304 | fn completes_self_in_enum() { | ||
305 | check( | ||
306 | r#"enum X { Y($0) }"#, | ||
307 | expect![[r#" | ||
308 | sp Self | ||
309 | en X | ||
310 | "#]], | ||
311 | ); | ||
312 | } | ||
313 | |||
314 | #[test] | ||
315 | fn completes_module_items() { | 220 | fn completes_module_items() { |
316 | check( | 221 | check( |
317 | r#" | 222 | r#" |
@@ -365,19 +270,6 @@ mod m { | |||
365 | } | 270 | } |
366 | 271 | ||
367 | #[test] | 272 | #[test] |
368 | fn completes_return_type() { | ||
369 | check( | ||
370 | r#" | ||
371 | struct Foo; | ||
372 | fn x() -> $0 | ||
373 | "#, | ||
374 | expect![[r#" | ||
375 | st Foo | ||
376 | "#]], | ||
377 | ); | ||
378 | } | ||
379 | |||
380 | #[test] | ||
381 | fn dont_show_both_completions_for_shadowing() { | 273 | fn dont_show_both_completions_for_shadowing() { |
382 | check( | 274 | check( |
383 | r#" | 275 | r#" |
@@ -559,19 +451,6 @@ fn foo() { $0 } | |||
559 | } | 451 | } |
560 | 452 | ||
561 | #[test] | 453 | #[test] |
562 | fn completes_macros_as_type() { | ||
563 | check( | ||
564 | r#" | ||
565 | macro_rules! foo { () => {} } | ||
566 | fn main() { let x: $0 } | ||
567 | "#, | ||
568 | expect![[r#" | ||
569 | ma foo!(…) macro_rules! foo | ||
570 | "#]], | ||
571 | ); | ||
572 | } | ||
573 | |||
574 | #[test] | ||
575 | fn completes_macros_as_stmt() { | 454 | fn completes_macros_as_stmt() { |
576 | check( | 455 | check( |
577 | r#" | 456 | r#" |
@@ -716,30 +595,4 @@ fn f() {} | |||
716 | expect![[""]], | 595 | expect![[""]], |
717 | ) | 596 | ) |
718 | } | 597 | } |
719 | |||
720 | #[test] | ||
721 | fn completes_types_and_const_in_arg_list() { | ||
722 | check( | ||
723 | r#" | ||
724 | enum Bar { | ||
725 | Baz | ||
726 | } | ||
727 | trait Foo { | ||
728 | type Bar; | ||
729 | } | ||
730 | |||
731 | const CONST: () = (); | ||
732 | |||
733 | fn foo<T: Foo<$0>, const CONST_PARAM: usize>(_: T) {} | ||
734 | "#, | ||
735 | expect![[r#" | ||
736 | ta Bar = type Bar; | ||
737 | tp T | ||
738 | cp CONST_PARAM | ||
739 | tt Foo | ||
740 | en Bar | ||
741 | ct CONST | ||
742 | "#]], | ||
743 | ); | ||
744 | } | ||
745 | } | 598 | } |
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs index e49e434fa..f0da98739 100644 --- a/crates/ide_completion/src/context.rs +++ b/crates/ide_completion/src/context.rs | |||
@@ -286,8 +286,11 @@ impl<'a> CompletionContext<'a> { | |||
286 | ) | 286 | ) |
287 | } | 287 | } |
288 | 288 | ||
289 | pub(crate) fn expect_record_field(&self) -> bool { | 289 | pub(crate) fn expect_field(&self) -> bool { |
290 | matches!(self.completion_location, Some(ImmediateLocation::RecordField)) | 290 | matches!( |
291 | self.completion_location, | ||
292 | Some(ImmediateLocation::RecordField | ImmediateLocation::TupleField) | ||
293 | ) | ||
291 | } | 294 | } |
292 | 295 | ||
293 | pub(crate) fn in_use_tree(&self) -> bool { | 296 | pub(crate) fn in_use_tree(&self) -> bool { |
@@ -385,14 +388,19 @@ impl<'a> CompletionContext<'a> { | |||
385 | (ty, name) | 388 | (ty, name) |
386 | }, | 389 | }, |
387 | ast::ArgList(_it) => { | 390 | ast::ArgList(_it) => { |
388 | cov_mark::hit!(expected_type_fn_param_with_leading_char); | 391 | cov_mark::hit!(expected_type_fn_param); |
389 | cov_mark::hit!(expected_type_fn_param_without_leading_char); | ||
390 | ActiveParameter::at_token( | 392 | ActiveParameter::at_token( |
391 | &self.sema, | 393 | &self.sema, |
392 | self.token.clone(), | 394 | self.token.clone(), |
393 | ).map(|ap| { | 395 | ).map(|ap| { |
394 | let name = ap.ident().map(NameOrNameRef::Name); | 396 | let name = ap.ident().map(NameOrNameRef::Name); |
395 | (Some(ap.ty), name) | 397 | let ty = if has_ref(&self.token) { |
398 | cov_mark::hit!(expected_type_fn_param_ref); | ||
399 | ap.ty.remove_ref() | ||
400 | } else { | ||
401 | Some(ap.ty) | ||
402 | }; | ||
403 | (ty, name) | ||
396 | }) | 404 | }) |
397 | .unwrap_or((None, None)) | 405 | .unwrap_or((None, None)) |
398 | }, | 406 | }, |
@@ -697,6 +705,19 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> { | |||
697 | use_tree.path().zip(Some(true)) | 705 | use_tree.path().zip(Some(true)) |
698 | } | 706 | } |
699 | 707 | ||
708 | fn has_ref(token: &SyntaxToken) -> bool { | ||
709 | let mut token = token.clone(); | ||
710 | for skip in [WHITESPACE, IDENT, T![mut]] { | ||
711 | if token.kind() == skip { | ||
712 | token = match token.prev_token() { | ||
713 | Some(it) => it, | ||
714 | None => return false, | ||
715 | } | ||
716 | } | ||
717 | } | ||
718 | token.kind() == T![&] | ||
719 | } | ||
720 | |||
700 | #[cfg(test)] | 721 | #[cfg(test)] |
701 | mod tests { | 722 | mod tests { |
702 | use expect_test::{expect, Expect}; | 723 | use expect_test::{expect, Expect}; |
@@ -769,14 +790,18 @@ fn foo() { | |||
769 | } | 790 | } |
770 | 791 | ||
771 | #[test] | 792 | #[test] |
772 | fn expected_type_fn_param_without_leading_char() { | 793 | fn expected_type_fn_param() { |
773 | cov_mark::check!(expected_type_fn_param_without_leading_char); | 794 | cov_mark::check!(expected_type_fn_param); |
774 | check_expected_type_and_name( | 795 | check_expected_type_and_name( |
775 | r#" | 796 | r#" |
776 | fn foo() { | 797 | fn foo() { bar($0); } |
777 | bar($0); | 798 | fn bar(x: u32) {} |
778 | } | 799 | "#, |
779 | 800 | expect![[r#"ty: u32, name: x"#]], | |
801 | ); | ||
802 | check_expected_type_and_name( | ||
803 | r#" | ||
804 | fn foo() { bar(c$0); } | ||
780 | fn bar(x: u32) {} | 805 | fn bar(x: u32) {} |
781 | "#, | 806 | "#, |
782 | expect![[r#"ty: u32, name: x"#]], | 807 | expect![[r#"ty: u32, name: x"#]], |
@@ -784,18 +809,29 @@ fn bar(x: u32) {} | |||
784 | } | 809 | } |
785 | 810 | ||
786 | #[test] | 811 | #[test] |
787 | fn expected_type_fn_param_with_leading_char() { | 812 | fn expected_type_fn_param_ref() { |
788 | cov_mark::check!(expected_type_fn_param_with_leading_char); | 813 | cov_mark::check!(expected_type_fn_param_ref); |
789 | check_expected_type_and_name( | 814 | check_expected_type_and_name( |
790 | r#" | 815 | r#" |
791 | fn foo() { | 816 | fn foo() { bar(&$0); } |
792 | bar(c$0); | 817 | fn bar(x: &u32) {} |
793 | } | ||
794 | |||
795 | fn bar(x: u32) {} | ||
796 | "#, | 818 | "#, |
797 | expect![[r#"ty: u32, name: x"#]], | 819 | expect![[r#"ty: u32, name: x"#]], |
798 | ); | 820 | ); |
821 | check_expected_type_and_name( | ||
822 | r#" | ||
823 | fn foo() { bar(&mut $0); } | ||
824 | fn bar(x: &mut u32) {} | ||
825 | "#, | ||
826 | expect![[r#"ty: u32, name: x"#]], | ||
827 | ); | ||
828 | check_expected_type_and_name( | ||
829 | r#" | ||
830 | fn foo() { bar(&c$0); } | ||
831 | fn bar(x: &u32) {} | ||
832 | "#, | ||
833 | expect![[r#"ty: u32, name: x"#]], | ||
834 | ); | ||
799 | } | 835 | } |
800 | 836 | ||
801 | #[test] | 837 | #[test] |
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs index 271409c38..757c9a3da 100644 --- a/crates/ide_completion/src/patterns.rs +++ b/crates/ide_completion/src/patterns.rs | |||
@@ -31,6 +31,7 @@ pub(crate) enum ImmediateLocation { | |||
31 | Impl, | 31 | Impl, |
32 | Trait, | 32 | Trait, |
33 | RecordField, | 33 | RecordField, |
34 | TupleField, | ||
34 | RefExpr, | 35 | RefExpr, |
35 | IdentPat, | 36 | IdentPat, |
36 | BlockExpr, | 37 | BlockExpr, |
@@ -187,7 +188,13 @@ pub(crate) fn determine_location( | |||
187 | ast::SourceFile(_it) => ImmediateLocation::ItemList, | 188 | ast::SourceFile(_it) => ImmediateLocation::ItemList, |
188 | ast::ItemList(_it) => ImmediateLocation::ItemList, | 189 | ast::ItemList(_it) => ImmediateLocation::ItemList, |
189 | ast::RefExpr(_it) => ImmediateLocation::RefExpr, | 190 | ast::RefExpr(_it) => ImmediateLocation::RefExpr, |
190 | ast::RecordField(_it) => ImmediateLocation::RecordField, | 191 | ast::RecordField(it) => if it.ty().map_or(false, |it| it.syntax().text_range().contains(offset)) { |
192 | return None; | ||
193 | } else { | ||
194 | ImmediateLocation::RecordField | ||
195 | }, | ||
196 | ast::TupleField(_it) => ImmediateLocation::TupleField, | ||
197 | ast::TupleFieldList(_it) => ImmediateLocation::TupleField, | ||
191 | ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) { | 198 | ast::AssocItemList(it) => match it.syntax().parent().map(|it| it.kind()) { |
192 | Some(IMPL) => ImmediateLocation::Impl, | 199 | Some(IMPL) => ImmediateLocation::Impl, |
193 | Some(TRAIT) => ImmediateLocation::Trait, | 200 | Some(TRAIT) => ImmediateLocation::Trait, |
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 9bec03e17..1a9b6212a 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -1057,7 +1057,7 @@ fn f() { | |||
1057 | #[test] | 1057 | #[test] |
1058 | fn suggest_ref_mut() { | 1058 | fn suggest_ref_mut() { |
1059 | cov_mark::check!(suggest_ref); | 1059 | cov_mark::check!(suggest_ref); |
1060 | check( | 1060 | check_relevance( |
1061 | r#" | 1061 | r#" |
1062 | struct S; | 1062 | struct S; |
1063 | fn foo(s: &mut S) {} | 1063 | fn foo(s: &mut S) {} |
@@ -1067,58 +1067,29 @@ fn main() { | |||
1067 | } | 1067 | } |
1068 | "#, | 1068 | "#, |
1069 | expect![[r#" | 1069 | expect![[r#" |
1070 | [ | 1070 | lc s [name+local] |
1071 | CompletionItem { | 1071 | lc &mut s [type+name+local] |
1072 | label: "S", | 1072 | st S [] |
1073 | source_range: 70..70, | 1073 | fn main() [] |
1074 | delete: 70..70, | 1074 | fn foo(…) [] |
1075 | insert: "S", | ||
1076 | kind: SymbolKind( | ||
1077 | Struct, | ||
1078 | ), | ||
1079 | }, | ||
1080 | CompletionItem { | ||
1081 | label: "foo(…)", | ||
1082 | source_range: 70..70, | ||
1083 | delete: 70..70, | ||
1084 | insert: "foo(${1:&mut s})$0", | ||
1085 | kind: SymbolKind( | ||
1086 | Function, | ||
1087 | ), | ||
1088 | lookup: "foo", | ||
1089 | detail: "fn(&mut S)", | ||
1090 | trigger_call_info: true, | ||
1091 | }, | ||
1092 | CompletionItem { | ||
1093 | label: "main()", | ||
1094 | source_range: 70..70, | ||
1095 | delete: 70..70, | ||
1096 | insert: "main()$0", | ||
1097 | kind: SymbolKind( | ||
1098 | Function, | ||
1099 | ), | ||
1100 | lookup: "main", | ||
1101 | detail: "fn()", | ||
1102 | }, | ||
1103 | CompletionItem { | ||
1104 | label: "s", | ||
1105 | source_range: 70..70, | ||
1106 | delete: 70..70, | ||
1107 | insert: "s", | ||
1108 | kind: SymbolKind( | ||
1109 | Local, | ||
1110 | ), | ||
1111 | detail: "S", | ||
1112 | relevance: CompletionRelevance { | ||
1113 | exact_name_match: true, | ||
1114 | type_match: None, | ||
1115 | is_local: true, | ||
1116 | }, | ||
1117 | ref_match: "&mut ", | ||
1118 | }, | ||
1119 | ] | ||
1120 | "#]], | 1075 | "#]], |
1121 | ) | 1076 | ); |
1077 | check_relevance( | ||
1078 | r#" | ||
1079 | struct S; | ||
1080 | fn foo(s: &mut S) {} | ||
1081 | fn main() { | ||
1082 | let mut s = S; | ||
1083 | foo(&mut $0); | ||
1084 | } | ||
1085 | "#, | ||
1086 | expect![[r#" | ||
1087 | lc s [type+name+local] | ||
1088 | st S [] | ||
1089 | fn main() [] | ||
1090 | fn foo(…) [] | ||
1091 | "#]], | ||
1092 | ); | ||
1122 | } | 1093 | } |
1123 | 1094 | ||
1124 | #[test] | 1095 | #[test] |
diff --git a/crates/ide_completion/src/tests.rs b/crates/ide_completion/src/tests.rs index 211c89c40..97298ff27 100644 --- a/crates/ide_completion/src/tests.rs +++ b/crates/ide_completion/src/tests.rs | |||
@@ -7,6 +7,10 @@ | |||
7 | mod item_list; | 7 | mod item_list; |
8 | mod use_tree; | 8 | mod use_tree; |
9 | mod items; | 9 | mod items; |
10 | mod pattern; | ||
11 | mod type_pos; | ||
12 | |||
13 | use std::mem; | ||
10 | 14 | ||
11 | use hir::{PrefixKind, Semantics}; | 15 | use hir::{PrefixKind, Semantics}; |
12 | use ide_db::{ | 16 | use ide_db::{ |
@@ -45,7 +49,16 @@ pub(crate) fn completion_list(code: &str) -> String { | |||
45 | } | 49 | } |
46 | 50 | ||
47 | fn completion_list_with_config(config: CompletionConfig, code: &str) -> String { | 51 | fn completion_list_with_config(config: CompletionConfig, code: &str) -> String { |
48 | render_completion_list(get_all_items(config, code)) | 52 | // filter out all but one builtintype completion for smaller test outputs |
53 | let items = get_all_items(config, code); | ||
54 | let mut bt_seen = false; | ||
55 | let items = items | ||
56 | .into_iter() | ||
57 | .filter(|it| { | ||
58 | it.completion_kind != CompletionKind::BuiltinType || !mem::replace(&mut bt_seen, true) | ||
59 | }) | ||
60 | .collect(); | ||
61 | render_completion_list(items) | ||
49 | } | 62 | } |
50 | 63 | ||
51 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. | 64 | /// Creates analysis from a multi-file fixture, returns positions marked with $0. |
diff --git a/crates/ide_completion/src/tests/items.rs b/crates/ide_completion/src/tests/items.rs index 8dfb8221b..b98baffd6 100644 --- a/crates/ide_completion/src/tests/items.rs +++ b/crates/ide_completion/src/tests/items.rs | |||
@@ -35,22 +35,6 @@ impl Tra$0 | |||
35 | ma foo!(…) #[macro_export] macro_rules! foo | 35 | ma foo!(…) #[macro_export] macro_rules! foo |
36 | ma foo!(…) #[macro_export] macro_rules! foo | 36 | ma foo!(…) #[macro_export] macro_rules! foo |
37 | bt u32 | 37 | bt u32 |
38 | bt bool | ||
39 | bt u8 | ||
40 | bt isize | ||
41 | bt u16 | ||
42 | bt u64 | ||
43 | bt u128 | ||
44 | bt f32 | ||
45 | bt i128 | ||
46 | bt i16 | ||
47 | bt str | ||
48 | bt i64 | ||
49 | bt char | ||
50 | bt f64 | ||
51 | bt i32 | ||
52 | bt i8 | ||
53 | bt usize | ||
54 | "##]], | 38 | "##]], |
55 | ) | 39 | ) |
56 | } | 40 | } |
@@ -69,22 +53,6 @@ impl Trait for Str$0 | |||
69 | ma foo!(…) #[macro_export] macro_rules! foo | 53 | ma foo!(…) #[macro_export] macro_rules! foo |
70 | ma foo!(…) #[macro_export] macro_rules! foo | 54 | ma foo!(…) #[macro_export] macro_rules! foo |
71 | bt u32 | 55 | bt u32 |
72 | bt bool | ||
73 | bt u8 | ||
74 | bt isize | ||
75 | bt u16 | ||
76 | bt u64 | ||
77 | bt u128 | ||
78 | bt f32 | ||
79 | bt i128 | ||
80 | bt i16 | ||
81 | bt str | ||
82 | bt i64 | ||
83 | bt char | ||
84 | bt f64 | ||
85 | bt i32 | ||
86 | bt i8 | ||
87 | bt usize | ||
88 | "##]], | 56 | "##]], |
89 | ) | 57 | ) |
90 | } | 58 | } |
diff --git a/crates/ide_completion/src/tests/pattern.rs b/crates/ide_completion/src/tests/pattern.rs new file mode 100644 index 000000000..1ad5ccd97 --- /dev/null +++ b/crates/ide_completion/src/tests/pattern.rs | |||
@@ -0,0 +1,348 @@ | |||
1 | //! Completions tests for pattern position. | ||
2 | use expect_test::{expect, Expect}; | ||
3 | |||
4 | use crate::tests::completion_list; | ||
5 | |||
6 | fn check(ra_fixture: &str, expect: Expect) { | ||
7 | let actual = completion_list(ra_fixture); | ||
8 | expect.assert_eq(&actual) | ||
9 | } | ||
10 | |||
11 | fn check_with(ra_fixture: &str, expect: Expect) { | ||
12 | let base = r#" | ||
13 | enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV } | ||
14 | use self::Enum::TupleV; | ||
15 | mod module {} | ||
16 | |||
17 | static STATIC: Unit = Unit; | ||
18 | const CONST: Unit = Unit; | ||
19 | struct Record { field: u32 } | ||
20 | struct Tuple(u32); | ||
21 | struct Unit | ||
22 | macro_rules! makro {} | ||
23 | "#; | ||
24 | let actual = completion_list(&format!("{}\n{}", base, ra_fixture)); | ||
25 | expect.assert_eq(&actual) | ||
26 | } | ||
27 | |||
28 | #[test] | ||
29 | fn ident_rebind_pat() { | ||
30 | check( | ||
31 | r#" | ||
32 | fn quux() { | ||
33 | let en$0 @ x | ||
34 | } | ||
35 | "#, | ||
36 | expect![[r#" | ||
37 | kw mut | ||
38 | "#]], | ||
39 | ); | ||
40 | } | ||
41 | |||
42 | #[test] | ||
43 | fn ident_ref_pat() { | ||
44 | check( | ||
45 | r#" | ||
46 | fn quux() { | ||
47 | let ref en$0 | ||
48 | } | ||
49 | "#, | ||
50 | expect![[r#" | ||
51 | kw mut | ||
52 | "#]], | ||
53 | ); | ||
54 | check( | ||
55 | r#" | ||
56 | fn quux() { | ||
57 | let ref en$0 @ x | ||
58 | } | ||
59 | "#, | ||
60 | expect![[r#" | ||
61 | kw mut | ||
62 | "#]], | ||
63 | ); | ||
64 | } | ||
65 | |||
66 | #[test] | ||
67 | fn ident_ref_mut_pat() { | ||
68 | // FIXME mut is already here, don't complete it again | ||
69 | check( | ||
70 | r#" | ||
71 | fn quux() { | ||
72 | let ref mut en$0 | ||
73 | } | ||
74 | "#, | ||
75 | expect![[r#" | ||
76 | kw mut | ||
77 | "#]], | ||
78 | ); | ||
79 | check( | ||
80 | r#" | ||
81 | fn quux() { | ||
82 | let ref mut en$0 @ x | ||
83 | } | ||
84 | "#, | ||
85 | expect![[r#" | ||
86 | kw mut | ||
87 | "#]], | ||
88 | ); | ||
89 | } | ||
90 | |||
91 | #[test] | ||
92 | fn ref_pat() { | ||
93 | check( | ||
94 | r#" | ||
95 | fn quux() { | ||
96 | let &en$0 | ||
97 | } | ||
98 | "#, | ||
99 | expect![[r#" | ||
100 | kw mut | ||
101 | "#]], | ||
102 | ); | ||
103 | // FIXME mut is already here, don't complete it again | ||
104 | check( | ||
105 | r#" | ||
106 | fn quux() { | ||
107 | let &mut en$0 | ||
108 | } | ||
109 | "#, | ||
110 | expect![[r#" | ||
111 | kw mut | ||
112 | "#]], | ||
113 | ); | ||
114 | } | ||
115 | |||
116 | #[test] | ||
117 | fn refutable() { | ||
118 | check_with( | ||
119 | r#" | ||
120 | fn foo() { | ||
121 | if let a$0 | ||
122 | } | ||
123 | "#, | ||
124 | expect![[r#" | ||
125 | kw mut | ||
126 | bn Record Record { field$1 }$0 | ||
127 | st Record | ||
128 | en Enum | ||
129 | bn Tuple Tuple($1)$0 | ||
130 | st Tuple | ||
131 | md module | ||
132 | bn TupleV TupleV($1)$0 | ||
133 | ev TupleV | ||
134 | st Unit | ||
135 | ct CONST | ||
136 | ma makro!(…) macro_rules! makro | ||
137 | "#]], | ||
138 | ); | ||
139 | } | ||
140 | |||
141 | #[test] | ||
142 | fn irrefutable() { | ||
143 | check_with( | ||
144 | r#" | ||
145 | fn foo() { | ||
146 | let a$0 | ||
147 | } | ||
148 | "#, | ||
149 | expect![[r#" | ||
150 | kw mut | ||
151 | bn Record Record { field$1 }$0 | ||
152 | st Record | ||
153 | bn Tuple Tuple($1)$0 | ||
154 | st Tuple | ||
155 | st Unit | ||
156 | ma makro!(…) macro_rules! makro | ||
157 | "#]], | ||
158 | ); | ||
159 | } | ||
160 | |||
161 | #[test] | ||
162 | fn in_param() { | ||
163 | check_with( | ||
164 | r#" | ||
165 | fn foo(a$0) { | ||
166 | } | ||
167 | "#, | ||
168 | expect![[r#" | ||
169 | kw mut | ||
170 | bn Record Record { field$1 }: Record$0 | ||
171 | st Record | ||
172 | bn Tuple Tuple($1): Tuple$0 | ||
173 | st Tuple | ||
174 | st Unit | ||
175 | ma makro!(…) macro_rules! makro | ||
176 | "#]], | ||
177 | ); | ||
178 | } | ||
179 | |||
180 | #[test] | ||
181 | fn only_fn_like_macros() { | ||
182 | check( | ||
183 | r#" | ||
184 | macro_rules! m { ($e:expr) => { $e } } | ||
185 | |||
186 | #[rustc_builtin_macro] | ||
187 | macro Clone {} | ||
188 | |||
189 | fn foo() { | ||
190 | let x$0 | ||
191 | } | ||
192 | "#, | ||
193 | expect![[r#" | ||
194 | kw mut | ||
195 | ma m!(…) macro_rules! m | ||
196 | "#]], | ||
197 | ); | ||
198 | } | ||
199 | |||
200 | #[test] | ||
201 | fn in_simple_macro_call() { | ||
202 | check( | ||
203 | r#" | ||
204 | macro_rules! m { ($e:expr) => { $e } } | ||
205 | enum E { X } | ||
206 | |||
207 | fn foo() { | ||
208 | m!(match E::X { a$0 }) | ||
209 | } | ||
210 | "#, | ||
211 | expect![[r#" | ||
212 | kw mut | ||
213 | ev E::X () | ||
214 | en E | ||
215 | ma m!(…) macro_rules! m | ||
216 | "#]], | ||
217 | ); | ||
218 | } | ||
219 | |||
220 | #[test] | ||
221 | fn omits_private_fields_pat() { | ||
222 | check( | ||
223 | r#" | ||
224 | mod foo { | ||
225 | pub struct Record { pub field: i32, _field: i32 } | ||
226 | pub struct Tuple(pub u32, u32); | ||
227 | pub struct Invisible(u32, u32); | ||
228 | } | ||
229 | use foo::*; | ||
230 | |||
231 | fn outer() { | ||
232 | if let a$0 | ||
233 | } | ||
234 | "#, | ||
235 | expect![[r#" | ||
236 | kw mut | ||
237 | bn Record Record { field$1, .. }$0 | ||
238 | st Record | ||
239 | bn Tuple Tuple($1, ..)$0 | ||
240 | st Tuple | ||
241 | st Invisible | ||
242 | md foo | ||
243 | "#]], | ||
244 | ) | ||
245 | } | ||
246 | |||
247 | // #[test] | ||
248 | // fn only_shows_ident_completion() { | ||
249 | // check_edit( | ||
250 | // "Foo", | ||
251 | // r#" | ||
252 | // struct Foo(i32); | ||
253 | // fn main() { | ||
254 | // match Foo(92) { | ||
255 | // a$0(92) => (), | ||
256 | // } | ||
257 | // } | ||
258 | // "#, | ||
259 | // r#" | ||
260 | // struct Foo(i32); | ||
261 | // fn main() { | ||
262 | // match Foo(92) { | ||
263 | // Foo(92) => (), | ||
264 | // } | ||
265 | // } | ||
266 | // "#, | ||
267 | // ); | ||
268 | // } | ||
269 | |||
270 | #[test] | ||
271 | fn completes_self_pats() { | ||
272 | check( | ||
273 | r#" | ||
274 | struct Foo(i32); | ||
275 | impl Foo { | ||
276 | fn foo() { | ||
277 | match Foo(0) { | ||
278 | a$0 | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | "#, | ||
283 | expect![[r#" | ||
284 | kw mut | ||
285 | bn Self Self($1)$0 | ||
286 | sp Self | ||
287 | bn Foo Foo($1)$0 | ||
288 | st Foo | ||
289 | "#]], | ||
290 | ) | ||
291 | } | ||
292 | |||
293 | #[test] | ||
294 | fn completes_qualified_variant() { | ||
295 | check( | ||
296 | r#" | ||
297 | enum Foo { | ||
298 | Bar { baz: i32 } | ||
299 | } | ||
300 | impl Foo { | ||
301 | fn foo() { | ||
302 | match {Foo::Bar { baz: 0 }} { | ||
303 | B$0 | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | "#, | ||
308 | expect![[r#" | ||
309 | kw mut | ||
310 | bn Self::Bar Self::Bar { baz$1 }$0 | ||
311 | ev Self::Bar { baz: i32 } | ||
312 | bn Foo::Bar Foo::Bar { baz$1 }$0 | ||
313 | ev Foo::Bar { baz: i32 } | ||
314 | sp Self | ||
315 | en Foo | ||
316 | "#]], | ||
317 | ) | ||
318 | } | ||
319 | |||
320 | #[test] | ||
321 | fn completes_in_record_field_pat() { | ||
322 | check( | ||
323 | r#" | ||
324 | struct Foo { bar: Bar } | ||
325 | struct Bar(u32); | ||
326 | fn outer(Foo { bar: $0 }: Foo) {} | ||
327 | "#, | ||
328 | expect![[r#" | ||
329 | kw mut | ||
330 | bn Foo Foo { bar$1 }$0 | ||
331 | st Foo | ||
332 | bn Bar Bar($1)$0 | ||
333 | st Bar | ||
334 | "#]], | ||
335 | ) | ||
336 | } | ||
337 | |||
338 | #[test] | ||
339 | fn skips_in_record_field_pat_name() { | ||
340 | check( | ||
341 | r#" | ||
342 | struct Foo { bar: Bar } | ||
343 | struct Bar(u32); | ||
344 | fn outer(Foo { bar$0 }: Foo) {} | ||
345 | "#, | ||
346 | expect![[r#""#]], | ||
347 | ) | ||
348 | } | ||
diff --git a/crates/ide_completion/src/tests/type_pos.rs b/crates/ide_completion/src/tests/type_pos.rs new file mode 100644 index 000000000..1ab47b27e --- /dev/null +++ b/crates/ide_completion/src/tests/type_pos.rs | |||
@@ -0,0 +1,177 @@ | |||
1 | //! Completions tests for type position. | ||
2 | use expect_test::{expect, Expect}; | ||
3 | |||
4 | use crate::tests::completion_list; | ||
5 | |||
6 | fn check_with(ra_fixture: &str, expect: Expect) { | ||
7 | let base = r#" | ||
8 | enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV } | ||
9 | use self::Enum::TupleV; | ||
10 | mod module {} | ||
11 | |||
12 | trait Trait {} | ||
13 | static STATIC: Unit = Unit; | ||
14 | const CONST: Unit = Unit; | ||
15 | struct Record { field: u32 } | ||
16 | struct Tuple(u32); | ||
17 | struct Unit | ||
18 | macro_rules! makro {} | ||
19 | "#; | ||
20 | let actual = completion_list(&format!("{}\n{}", base, ra_fixture)); | ||
21 | expect.assert_eq(&actual) | ||
22 | } | ||
23 | |||
24 | #[test] | ||
25 | fn record_field_ty() { | ||
26 | check_with( | ||
27 | r#" | ||
28 | struct Foo<'lt, T, const C: usize> { | ||
29 | f: $0 | ||
30 | } | ||
31 | "#, | ||
32 | expect![[r#" | ||
33 | sp Self | ||
34 | tp T | ||
35 | tt Trait | ||
36 | en Enum | ||
37 | st Record | ||
38 | st Tuple | ||
39 | md module | ||
40 | st Foo<…> | ||
41 | st Unit | ||
42 | ma makro!(…) macro_rules! makro | ||
43 | bt u32 | ||
44 | "#]], | ||
45 | ) | ||
46 | } | ||
47 | |||
48 | #[test] | ||
49 | fn tuple_struct_field() { | ||
50 | check_with( | ||
51 | r#" | ||
52 | struct Foo<'lt, T, const C: usize>(f$0); | ||
53 | "#, | ||
54 | expect![[r#" | ||
55 | kw pub(crate) | ||
56 | kw pub | ||
57 | sp Self | ||
58 | tp T | ||
59 | tt Trait | ||
60 | en Enum | ||
61 | st Record | ||
62 | st Tuple | ||
63 | md module | ||
64 | st Foo<…> | ||
65 | st Unit | ||
66 | ma makro!(…) macro_rules! makro | ||
67 | bt u32 | ||
68 | "#]], | ||
69 | ) | ||
70 | } | ||
71 | |||
72 | #[test] | ||
73 | fn fn_return_type() { | ||
74 | check_with( | ||
75 | r#" | ||
76 | fn x<'lt, T, const C: usize>() -> $0 | ||
77 | "#, | ||
78 | expect![[r#" | ||
79 | tp T | ||
80 | tt Trait | ||
81 | en Enum | ||
82 | st Record | ||
83 | st Tuple | ||
84 | md module | ||
85 | st Unit | ||
86 | ma makro!(…) macro_rules! makro | ||
87 | bt u32 | ||
88 | "#]], | ||
89 | ); | ||
90 | } | ||
91 | |||
92 | #[test] | ||
93 | fn body_type_pos() { | ||
94 | check_with( | ||
95 | r#" | ||
96 | fn foo<'lt, T, const C: usize>() { | ||
97 | let local = (); | ||
98 | let _: $0; | ||
99 | } | ||
100 | "#, | ||
101 | expect![[r#" | ||
102 | tp T | ||
103 | tt Trait | ||
104 | en Enum | ||
105 | st Record | ||
106 | st Tuple | ||
107 | md module | ||
108 | st Unit | ||
109 | ma makro!(…) macro_rules! makro | ||
110 | bt u32 | ||
111 | "#]], | ||
112 | ); | ||
113 | check_with( | ||
114 | r#" | ||
115 | fn foo<'lt, T, const C: usize>() { | ||
116 | let local = (); | ||
117 | let _: self::$0; | ||
118 | } | ||
119 | "#, | ||
120 | expect![[r#" | ||
121 | tt Trait | ||
122 | en Enum | ||
123 | st Record | ||
124 | st Tuple | ||
125 | md module | ||
126 | st Unit | ||
127 | "#]], | ||
128 | ); | ||
129 | } | ||
130 | |||
131 | #[test] | ||
132 | fn completes_types_and_const_in_arg_list() { | ||
133 | // FIXME: we should complete the lifetime here for now | ||
134 | check_with( | ||
135 | r#" | ||
136 | trait Trait2 { | ||
137 | type Foo; | ||
138 | } | ||
139 | |||
140 | fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} | ||
141 | "#, | ||
142 | expect![[r#" | ||
143 | ta Foo = type Foo; | ||
144 | tp T | ||
145 | cp CONST_PARAM | ||
146 | tt Trait | ||
147 | en Enum | ||
148 | st Record | ||
149 | st Tuple | ||
150 | tt Trait2 | ||
151 | md module | ||
152 | st Unit | ||
153 | ct CONST | ||
154 | ma makro!(…) macro_rules! makro | ||
155 | bt u32 | ||
156 | "#]], | ||
157 | ); | ||
158 | check_with( | ||
159 | r#" | ||
160 | trait Trait2 { | ||
161 | type Foo; | ||
162 | } | ||
163 | |||
164 | fn foo<'lt, T: Trait2<self::$0>, const CONST_PARAM: usize>(_: T) {} | ||
165 | "#, | ||
166 | expect![[r#" | ||
167 | tt Trait | ||
168 | en Enum | ||
169 | st Record | ||
170 | st Tuple | ||
171 | tt Trait2 | ||
172 | md module | ||
173 | st Unit | ||
174 | ct CONST | ||
175 | "#]], | ||
176 | ); | ||
177 | } | ||
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs index 263edcdc9..01894630a 100644 --- a/crates/ide_db/src/helpers/insert_use/tests.rs +++ b/crates/ide_db/src/helpers/insert_use/tests.rs | |||
@@ -1,7 +1,43 @@ | |||
1 | use super::*; | 1 | use super::*; |
2 | 2 | ||
3 | use hir::PrefixKind; | 3 | use hir::PrefixKind; |
4 | use test_utils::assert_eq_text; | 4 | use test_utils::{assert_eq_text, extract_range_or_offset, CURSOR_MARKER}; |
5 | |||
6 | #[test] | ||
7 | fn respects_cfg_attr_fn() { | ||
8 | check( | ||
9 | r"bar::Bar", | ||
10 | r#" | ||
11 | #[cfg(test)] | ||
12 | fn foo() {$0} | ||
13 | "#, | ||
14 | r#" | ||
15 | #[cfg(test)] | ||
16 | fn foo() { | ||
17 | use bar::Bar; | ||
18 | } | ||
19 | "#, | ||
20 | ImportGranularity::Crate, | ||
21 | ); | ||
22 | } | ||
23 | |||
24 | #[test] | ||
25 | fn respects_cfg_attr_const() { | ||
26 | check( | ||
27 | r"bar::Bar", | ||
28 | r#" | ||
29 | #[cfg(test)] | ||
30 | const FOO: Bar = {$0}; | ||
31 | "#, | ||
32 | r#" | ||
33 | #[cfg(test)] | ||
34 | const FOO: Bar = { | ||
35 | use bar::Bar; | ||
36 | }; | ||
37 | "#, | ||
38 | ImportGranularity::Crate, | ||
39 | ); | ||
40 | } | ||
5 | 41 | ||
6 | #[test] | 42 | #[test] |
7 | fn insert_skips_lone_glob_imports() { | 43 | fn insert_skips_lone_glob_imports() { |
@@ -15,15 +51,13 @@ use foo::bar::*; | |||
15 | use foo::baz::A; | 51 | use foo::baz::A; |
16 | ", | 52 | ", |
17 | ImportGranularity::Crate, | 53 | ImportGranularity::Crate, |
18 | false, | ||
19 | false, | ||
20 | ); | 54 | ); |
21 | } | 55 | } |
22 | 56 | ||
23 | #[test] | 57 | #[test] |
24 | fn insert_not_group() { | 58 | fn insert_not_group() { |
25 | cov_mark::check!(insert_no_grouping_last); | 59 | cov_mark::check!(insert_no_grouping_last); |
26 | check( | 60 | check_with_config( |
27 | "use external_crate2::bar::A", | 61 | "use external_crate2::bar::A", |
28 | r" | 62 | r" |
29 | use std::bar::B; | 63 | use std::bar::B; |
@@ -38,24 +72,32 @@ use crate::bar::A; | |||
38 | use self::bar::A; | 72 | use self::bar::A; |
39 | use super::bar::A; | 73 | use super::bar::A; |
40 | use external_crate2::bar::A;", | 74 | use external_crate2::bar::A;", |
41 | ImportGranularity::Item, | 75 | &InsertUseConfig { |
42 | false, | 76 | granularity: ImportGranularity::Item, |
43 | false, | 77 | enforce_granularity: true, |
78 | prefix_kind: PrefixKind::Plain, | ||
79 | group: false, | ||
80 | skip_glob_imports: true, | ||
81 | }, | ||
44 | ); | 82 | ); |
45 | } | 83 | } |
46 | 84 | ||
47 | #[test] | 85 | #[test] |
48 | fn insert_not_group_empty() { | 86 | fn insert_not_group_empty() { |
49 | cov_mark::check!(insert_no_grouping_last2); | 87 | cov_mark::check!(insert_no_grouping_last2); |
50 | check( | 88 | check_with_config( |
51 | "use external_crate2::bar::A", | 89 | "use external_crate2::bar::A", |
52 | r"", | 90 | r"", |
53 | r"use external_crate2::bar::A; | 91 | r"use external_crate2::bar::A; |
54 | 92 | ||
55 | ", | 93 | ", |
56 | ImportGranularity::Item, | 94 | &InsertUseConfig { |
57 | false, | 95 | granularity: ImportGranularity::Item, |
58 | false, | 96 | enforce_granularity: true, |
97 | prefix_kind: PrefixKind::Plain, | ||
98 | group: false, | ||
99 | skip_glob_imports: true, | ||
100 | }, | ||
59 | ); | 101 | ); |
60 | } | 102 | } |
61 | 103 | ||
@@ -294,13 +336,15 @@ fn insert_empty_module() { | |||
294 | cov_mark::check!(insert_group_empty_module); | 336 | cov_mark::check!(insert_group_empty_module); |
295 | check( | 337 | check( |
296 | "foo::bar", | 338 | "foo::bar", |
297 | "mod x {}", | 339 | r" |
298 | r"{ | 340 | mod x {$0} |
341 | ", | ||
342 | r" | ||
343 | mod x { | ||
299 | use foo::bar; | 344 | use foo::bar; |
300 | }", | 345 | } |
346 | ", | ||
301 | ImportGranularity::Item, | 347 | ImportGranularity::Item, |
302 | true, | ||
303 | true, | ||
304 | ) | 348 | ) |
305 | } | 349 | } |
306 | 350 | ||
@@ -555,7 +599,6 @@ fn merge_mod_into_glob() { | |||
555 | "token::TokenKind", | 599 | "token::TokenKind", |
556 | r"use token::TokenKind::*;", | 600 | r"use token::TokenKind::*;", |
557 | r"use token::TokenKind::{*, self};", | 601 | r"use token::TokenKind::{*, self};", |
558 | false, | ||
559 | &InsertUseConfig { | 602 | &InsertUseConfig { |
560 | granularity: ImportGranularity::Crate, | 603 | granularity: ImportGranularity::Crate, |
561 | enforce_granularity: true, | 604 | enforce_granularity: true, |
@@ -573,7 +616,6 @@ fn merge_self_glob() { | |||
573 | "self", | 616 | "self", |
574 | r"use self::*;", | 617 | r"use self::*;", |
575 | r"use self::{*, self};", | 618 | r"use self::{*, self};", |
576 | false, | ||
577 | &InsertUseConfig { | 619 | &InsertUseConfig { |
578 | granularity: ImportGranularity::Crate, | 620 | granularity: ImportGranularity::Crate, |
579 | enforce_granularity: true, | 621 | enforce_granularity: true, |
@@ -798,14 +840,20 @@ fn check_with_config( | |||
798 | path: &str, | 840 | path: &str, |
799 | ra_fixture_before: &str, | 841 | ra_fixture_before: &str, |
800 | ra_fixture_after: &str, | 842 | ra_fixture_after: &str, |
801 | module: bool, | ||
802 | config: &InsertUseConfig, | 843 | config: &InsertUseConfig, |
803 | ) { | 844 | ) { |
804 | let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone(); | 845 | let (text, pos) = if ra_fixture_before.contains(CURSOR_MARKER) { |
805 | if module { | 846 | let (range_or_offset, text) = extract_range_or_offset(ra_fixture_before); |
806 | syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone(); | 847 | (text, Some(range_or_offset)) |
807 | } | 848 | } else { |
808 | let file = super::ImportScope::from(syntax.clone_for_update()).unwrap(); | 849 | (ra_fixture_before.to_owned(), None) |
850 | }; | ||
851 | let syntax = ast::SourceFile::parse(&text).tree().syntax().clone_for_update(); | ||
852 | let file = pos | ||
853 | .and_then(|pos| syntax.token_at_offset(pos.expect_offset()).next()?.parent()) | ||
854 | .and_then(|it| super::ImportScope::find_insert_use_container(&it)) | ||
855 | .or_else(|| super::ImportScope::from(syntax)) | ||
856 | .unwrap(); | ||
809 | let path = ast::SourceFile::parse(&format!("use {};", path)) | 857 | let path = ast::SourceFile::parse(&format!("use {};", path)) |
810 | .tree() | 858 | .tree() |
811 | .syntax() | 859 | .syntax() |
@@ -814,7 +862,7 @@ fn check_with_config( | |||
814 | .unwrap(); | 862 | .unwrap(); |
815 | 863 | ||
816 | insert_use(&file, path, config); | 864 | insert_use(&file, path, config); |
817 | let result = file.as_syntax_node().to_string(); | 865 | let result = file.as_syntax_node().ancestors().last().unwrap().to_string(); |
818 | assert_eq_text!(ra_fixture_after, &result); | 866 | assert_eq_text!(ra_fixture_after, &result); |
819 | } | 867 | } |
820 | 868 | ||
@@ -823,34 +871,31 @@ fn check( | |||
823 | ra_fixture_before: &str, | 871 | ra_fixture_before: &str, |
824 | ra_fixture_after: &str, | 872 | ra_fixture_after: &str, |
825 | granularity: ImportGranularity, | 873 | granularity: ImportGranularity, |
826 | module: bool, | ||
827 | group: bool, | ||
828 | ) { | 874 | ) { |
829 | check_with_config( | 875 | check_with_config( |
830 | path, | 876 | path, |
831 | ra_fixture_before, | 877 | ra_fixture_before, |
832 | ra_fixture_after, | 878 | ra_fixture_after, |
833 | module, | ||
834 | &InsertUseConfig { | 879 | &InsertUseConfig { |
835 | granularity, | 880 | granularity, |
836 | enforce_granularity: true, | 881 | enforce_granularity: true, |
837 | prefix_kind: PrefixKind::Plain, | 882 | prefix_kind: PrefixKind::Plain, |
838 | group, | 883 | group: true, |
839 | skip_glob_imports: true, | 884 | skip_glob_imports: true, |
840 | }, | 885 | }, |
841 | ) | 886 | ) |
842 | } | 887 | } |
843 | 888 | ||
844 | fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 889 | fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
845 | check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate, false, true) | 890 | check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate) |
846 | } | 891 | } |
847 | 892 | ||
848 | fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 893 | fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
849 | check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module, false, true) | 894 | check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module) |
850 | } | 895 | } |
851 | 896 | ||
852 | fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { | 897 | fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { |
853 | check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item, false, true) | 898 | check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item) |
854 | } | 899 | } |
855 | 900 | ||
856 | fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) { | 901 | fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) { |
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index b4f2fe9a4..0d694b1a7 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs | |||
@@ -645,7 +645,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
645 | None if match_res.err.is_none() => { | 645 | None if match_res.err.is_none() => { |
646 | bindings_builder.push_optional(&mut item.bindings, name); | 646 | bindings_builder.push_optional(&mut item.bindings, name); |
647 | } | 647 | } |
648 | _ => {} | 648 | None => {} |
649 | } | 649 | } |
650 | if let Some(err) = match_res.err { | 650 | if let Some(err) = match_res.err { |
651 | res.add_err(err); | 651 | res.add_err(err); |
@@ -756,7 +756,7 @@ impl<'a> TtIter<'a> { | |||
756 | let ok = match separator { | 756 | let ok = match separator { |
757 | Separator::Ident(lhs) if idx == 0 => match fork.expect_ident_or_underscore() { | 757 | Separator::Ident(lhs) if idx == 0 => match fork.expect_ident_or_underscore() { |
758 | Ok(rhs) => rhs.text == lhs.text, | 758 | Ok(rhs) => rhs.text == lhs.text, |
759 | _ => false, | 759 | Err(_) => false, |
760 | }, | 760 | }, |
761 | Separator::Literal(lhs) if idx == 0 => match fork.expect_literal() { | 761 | Separator::Literal(lhs) if idx == 0 => match fork.expect_literal() { |
762 | Ok(rhs) => match rhs { | 762 | Ok(rhs) => match rhs { |
@@ -764,11 +764,11 @@ impl<'a> TtIter<'a> { | |||
764 | tt::Leaf::Ident(rhs) => rhs.text == lhs.text, | 764 | tt::Leaf::Ident(rhs) => rhs.text == lhs.text, |
765 | tt::Leaf::Punct(_) => false, | 765 | tt::Leaf::Punct(_) => false, |
766 | }, | 766 | }, |
767 | _ => false, | 767 | Err(_) => false, |
768 | }, | 768 | }, |
769 | Separator::Puncts(lhss) if idx < lhss.len() => match fork.expect_punct() { | 769 | Separator::Puncts(lhss) if idx < lhss.len() => match fork.expect_punct() { |
770 | Ok(rhs) => rhs.char == lhss[idx].char, | 770 | Ok(rhs) => rhs.char == lhss[idx].char, |
771 | _ => false, | 771 | Err(_) => false, |
772 | }, | 772 | }, |
773 | _ => false, | 773 | _ => false, |
774 | }; | 774 | }; |
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index 49a137577..4894e2a0c 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs | |||
@@ -241,6 +241,6 @@ fn push_fragment(buf: &mut Vec<tt::TokenTree>, fragment: Fragment) { | |||
241 | fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) { | 241 | fn push_subtree(buf: &mut Vec<tt::TokenTree>, tt: tt::Subtree) { |
242 | match tt.delimiter { | 242 | match tt.delimiter { |
243 | None => buf.extend(tt.token_trees), | 243 | None => buf.extend(tt.token_trees), |
244 | _ => buf.push(tt.into()), | 244 | Some(_) => buf.push(tt.into()), |
245 | } | 245 | } |
246 | } | 246 | } |
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 8c8528aaf..fcc596756 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs | |||
@@ -135,7 +135,7 @@ impl Shift { | |||
135 | 135 | ||
136 | /// Shift given TokenTree token id | 136 | /// Shift given TokenTree token id |
137 | fn shift_all(self, tt: &mut tt::Subtree) { | 137 | fn shift_all(self, tt: &mut tt::Subtree) { |
138 | for t in tt.token_trees.iter_mut() { | 138 | for t in &mut tt.token_trees { |
139 | match t { | 139 | match t { |
140 | tt::TokenTree::Leaf(leaf) => match leaf { | 140 | tt::TokenTree::Leaf(leaf) => match leaf { |
141 | tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id), | 141 | tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id), |
@@ -188,7 +188,7 @@ impl MacroRules { | |||
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | for rule in rules.iter() { | 191 | for rule in &rules { |
192 | validate(&rule.lhs)?; | 192 | validate(&rule.lhs)?; |
193 | } | 193 | } |
194 | 194 | ||
@@ -241,7 +241,7 @@ impl MacroDef { | |||
241 | } | 241 | } |
242 | rules.push(rule); | 242 | rules.push(rule); |
243 | } | 243 | } |
244 | for rule in rules.iter() { | 244 | for rule in &rules { |
245 | validate(&rule.lhs)?; | 245 | validate(&rule.lhs)?; |
246 | } | 246 | } |
247 | 247 | ||
@@ -268,7 +268,7 @@ impl MacroDef { | |||
268 | } | 268 | } |
269 | 269 | ||
270 | impl Rule { | 270 | impl Rule { |
271 | fn parse(src: &mut TtIter, expect_arrow: bool) -> Result<Rule, ParseError> { | 271 | fn parse(src: &mut TtIter, expect_arrow: bool) -> Result<Self, ParseError> { |
272 | let lhs = src | 272 | let lhs = src |
273 | .expect_subtree() | 273 | .expect_subtree() |
274 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; | 274 | .map_err(|()| ParseError::Expected("expected subtree".to_string()))?; |
@@ -356,7 +356,7 @@ impl<T> ExpandResult<T> { | |||
356 | } | 356 | } |
357 | 357 | ||
358 | pub fn result(self) -> Result<T, ExpandError> { | 358 | pub fn result(self) -> Result<T, ExpandError> { |
359 | self.err.map(Err).unwrap_or(Ok(self.value)) | 359 | self.err.map_or(Ok(self.value), Err) |
360 | } | 360 | } |
361 | } | 361 | } |
362 | 362 | ||
diff --git a/crates/mbe/src/subtree_source.rs b/crates/mbe/src/subtree_source.rs index ee80807ad..ffc2a6017 100644 --- a/crates/mbe/src/subtree_source.rs +++ b/crates/mbe/src/subtree_source.rs | |||
@@ -115,7 +115,7 @@ impl<'a> TokenSource for SubtreeTokenSource { | |||
115 | fn is_keyword(&self, kw: &str) -> bool { | 115 | fn is_keyword(&self, kw: &str) -> bool { |
116 | match self.cached.get(self.curr.1) { | 116 | match self.cached.get(self.curr.1) { |
117 | Some(t) => t.text == *kw, | 117 | Some(t) => t.text == *kw, |
118 | _ => false, | 118 | None => false, |
119 | } | 119 | } |
120 | } | 120 | } |
121 | } | 121 | } |
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index cdc22425d..7526bd8e6 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs | |||
@@ -283,7 +283,7 @@ trait TokenConvertor { | |||
283 | let (id, idx) = self.id_alloc().open_delim(range); | 283 | let (id, idx) = self.id_alloc().open_delim(range); |
284 | subtree.delimiter = Some(tt::Delimiter { id, kind }); | 284 | subtree.delimiter = Some(tt::Delimiter { id, kind }); |
285 | 285 | ||
286 | while self.peek().map(|it| it.kind() != closed).unwrap_or(false) { | 286 | while self.peek().map_or(false, |it| it.kind() != closed) { |
287 | self.collect_leaf(&mut subtree.token_trees); | 287 | self.collect_leaf(&mut subtree.token_trees); |
288 | } | 288 | } |
289 | let last_range = match self.bump() { | 289 | let last_range = match self.bump() { |
diff --git a/crates/mbe/src/tt_iter.rs b/crates/mbe/src/tt_iter.rs index 5a4eca7bf..65da83476 100644 --- a/crates/mbe/src/tt_iter.rs +++ b/crates/mbe/src/tt_iter.rs | |||
@@ -121,10 +121,11 @@ impl<'a> TtIter<'a> { | |||
121 | 121 | ||
122 | parser::parse_fragment(&mut src, &mut sink, fragment_kind); | 122 | parser::parse_fragment(&mut src, &mut sink, fragment_kind); |
123 | 123 | ||
124 | let mut err = None; | 124 | let mut err = if !sink.cursor.is_root() || sink.error { |
125 | if !sink.cursor.is_root() || sink.error { | 125 | Some(err!("expected {:?}", fragment_kind)) |
126 | err = Some(err!("expected {:?}", fragment_kind)); | 126 | } else { |
127 | } | 127 | None |
128 | }; | ||
128 | 129 | ||
129 | let mut curr = buffer.begin(); | 130 | let mut curr = buffer.begin(); |
130 | let mut res = vec![]; | 131 | let mut res = vec![]; |
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs index 65ca3eb6c..e252e89a5 100644 --- a/crates/proc_macro_srv/src/rustc_server.rs +++ b/crates/proc_macro_srv/src/rustc_server.rs | |||
@@ -248,7 +248,7 @@ pub mod token_stream { | |||
248 | token_trees: subtree | 248 | token_trees: subtree |
249 | .token_trees | 249 | .token_trees |
250 | .into_iter() | 250 | .into_iter() |
251 | .map(|t| token_tree_replace_token_ids_with_unspecified(t)) | 251 | .map(token_tree_replace_token_ids_with_unspecified) |
252 | .collect(), | 252 | .collect(), |
253 | } | 253 | } |
254 | } | 254 | } |
@@ -457,7 +457,7 @@ impl server::Group for Rustc { | |||
457 | } | 457 | } |
458 | 458 | ||
459 | fn span(&mut self, group: &Self::Group) -> Self::Span { | 459 | fn span(&mut self, group: &Self::Group) -> Self::Span { |
460 | group.delimiter.map(|it| it.id).unwrap_or_else(|| tt::TokenId::unspecified()) | 460 | group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified) |
461 | } | 461 | } |
462 | 462 | ||
463 | fn set_span(&mut self, _group: &mut Self::Group, _span: Self::Span) { | 463 | fn set_span(&mut self, _group: &mut Self::Group, _span: Self::Span) { |
diff --git a/crates/proc_macro_test/build.rs b/crates/proc_macro_test/build.rs index 4653a93dd..1e7aa026f 100644 --- a/crates/proc_macro_test/build.rs +++ b/crates/proc_macro_test/build.rs | |||
@@ -17,9 +17,16 @@ fn main() { | |||
17 | 17 | ||
18 | let name = "proc_macro_test_impl"; | 18 | let name = "proc_macro_test_impl"; |
19 | let version = "0.0.0"; | 19 | let version = "0.0.0"; |
20 | let target_dir = out_dir.join("target"); | ||
20 | let output = Command::new(toolchain::cargo()) | 21 | let output = Command::new(toolchain::cargo()) |
21 | .current_dir("imp") | 22 | .current_dir("imp") |
22 | .args(&["build", "-p", "proc_macro_test_impl", "--message-format", "json"]) | 23 | .args(&["build", "-p", "proc_macro_test_impl", "--message-format", "json"]) |
24 | // Explicit override the target directory to avoid using the same one which the parent | ||
25 | // cargo is using, or we'll deadlock. | ||
26 | // This can happen when `CARGO_TARGET_DIR` is set or global config forces all cargo | ||
27 | // instance to use the same target directory. | ||
28 | .arg("--target-dir") | ||
29 | .arg(&target_dir) | ||
23 | .output() | 30 | .output() |
24 | .unwrap(); | 31 | .unwrap(); |
25 | assert!(output.status.success()); | 32 | assert!(output.status.success()); |
@@ -39,10 +46,9 @@ fn main() { | |||
39 | } | 46 | } |
40 | } | 47 | } |
41 | 48 | ||
42 | let src_path = artifact_path.expect("no dylib for proc_macro_test_impl found"); | 49 | // This file is under `target_dir` and is already under `OUT_DIR`. |
43 | let dest_path = out_dir.join(src_path.file_name().unwrap()); | 50 | let artifact_path = artifact_path.expect("no dylib for proc_macro_test_impl found"); |
44 | fs::copy(src_path, &dest_path).unwrap(); | ||
45 | 51 | ||
46 | let info_path = out_dir.join("proc_macro_test_location.txt"); | 52 | let info_path = out_dir.join("proc_macro_test_location.txt"); |
47 | fs::write(info_path, dest_path.to_str().unwrap()).unwrap(); | 53 | fs::write(info_path, artifact_path.to_str().unwrap()).unwrap(); |
48 | } | 54 | } |
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index ac079f83e..0935ea967 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | //! See [`CargoWorkspace`]. | 1 | //! See [`CargoWorkspace`]. |
2 | 2 | ||
3 | use std::iter; | ||
3 | use std::path::PathBuf; | 4 | use std::path::PathBuf; |
4 | use std::{convert::TryInto, ops, process::Command, sync::Arc}; | 5 | use std::{convert::TryInto, ops, process::Command, sync::Arc}; |
5 | 6 | ||
@@ -12,6 +13,7 @@ use rustc_hash::FxHashMap; | |||
12 | use serde::Deserialize; | 13 | use serde::Deserialize; |
13 | use serde_json::from_value; | 14 | use serde_json::from_value; |
14 | 15 | ||
16 | use crate::CfgOverrides; | ||
15 | use crate::{build_data::BuildDataConfig, utf8_stdout}; | 17 | use crate::{build_data::BuildDataConfig, utf8_stdout}; |
16 | 18 | ||
17 | /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo | 19 | /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo |
@@ -76,6 +78,21 @@ pub struct CargoConfig { | |||
76 | 78 | ||
77 | /// rustc private crate source | 79 | /// rustc private crate source |
78 | pub rustc_source: Option<RustcSource>, | 80 | pub rustc_source: Option<RustcSource>, |
81 | |||
82 | /// crates to disable `#[cfg(test)]` on | ||
83 | pub unset_test_crates: Vec<String>, | ||
84 | } | ||
85 | |||
86 | impl CargoConfig { | ||
87 | pub fn cfg_overrides(&self) -> CfgOverrides { | ||
88 | self.unset_test_crates | ||
89 | .iter() | ||
90 | .cloned() | ||
91 | .zip(iter::repeat_with(|| { | ||
92 | cfg::CfgDiff::new(Vec::new(), vec![cfg::CfgAtom::Flag("test".into())]).unwrap() | ||
93 | })) | ||
94 | .collect() | ||
95 | } | ||
79 | } | 96 | } |
80 | 97 | ||
81 | pub type Package = Idx<PackageData>; | 98 | pub type Package = Idx<PackageData>; |
diff --git a/crates/project_model/src/lib.rs b/crates/project_model/src/lib.rs index 8c6cf94c2..1d408dff2 100644 --- a/crates/project_model/src/lib.rs +++ b/crates/project_model/src/lib.rs | |||
@@ -41,7 +41,7 @@ pub use crate::{ | |||
41 | }, | 41 | }, |
42 | project_json::{ProjectJson, ProjectJsonData}, | 42 | project_json::{ProjectJson, ProjectJsonData}, |
43 | sysroot::Sysroot, | 43 | sysroot::Sysroot, |
44 | workspace::{PackageRoot, ProjectWorkspace}, | 44 | workspace::{CfgOverrides, PackageRoot, ProjectWorkspace}, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | pub use proc_macro_api::ProcMacroClient; | 47 | pub use proc_macro_api::ProcMacroClient; |
diff --git a/crates/project_model/src/sysroot.rs b/crates/project_model/src/sysroot.rs index a22f79c15..006263da8 100644 --- a/crates/project_model/src/sysroot.rs +++ b/crates/project_model/src/sysroot.rs | |||
@@ -68,8 +68,9 @@ impl Sysroot { | |||
68 | pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> { | 68 | pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> { |
69 | let mut sysroot = Sysroot { crates: Arena::default() }; | 69 | let mut sysroot = Sysroot { crates: Arena::default() }; |
70 | 70 | ||
71 | for name in SYSROOT_CRATES.trim().lines() { | 71 | for path in SYSROOT_CRATES.trim().lines() { |
72 | let root = [format!("{}/src/lib.rs", name), format!("lib{}/lib.rs", name)] | 72 | let name = path.split('/').last().unwrap(); |
73 | let root = [format!("{}/src/lib.rs", path), format!("lib{}/lib.rs", path)] | ||
73 | .iter() | 74 | .iter() |
74 | .map(|it| sysroot_src_dir.join(it)) | 75 | .map(|it| sysroot_src_dir.join(it)) |
75 | .find(|it| it.exists()); | 76 | .find(|it| it.exists()); |
@@ -191,9 +192,8 @@ panic_abort | |||
191 | panic_unwind | 192 | panic_unwind |
192 | proc_macro | 193 | proc_macro |
193 | profiler_builtins | 194 | profiler_builtins |
194 | rtstartup | ||
195 | std | 195 | std |
196 | stdarch | 196 | stdarch/crates/std_detect |
197 | term | 197 | term |
198 | test | 198 | test |
199 | unwind"; | 199 | unwind"; |
@@ -204,9 +204,8 @@ core | |||
204 | panic_abort | 204 | panic_abort |
205 | panic_unwind | 205 | panic_unwind |
206 | profiler_builtins | 206 | profiler_builtins |
207 | rtstartup | ||
208 | proc_macro | 207 | proc_macro |
209 | stdarch | 208 | std_detect |
210 | term | 209 | term |
211 | test | 210 | test |
212 | unwind"; | 211 | unwind"; |
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index ef0f3c9e4..e67ba2bd9 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
@@ -7,7 +7,7 @@ use std::{collections::VecDeque, fmt, fs, path::Path, process::Command}; | |||
7 | use anyhow::{format_err, Context, Result}; | 7 | use anyhow::{format_err, Context, Result}; |
8 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; | 8 | use base_db::{CrateDisplayName, CrateGraph, CrateId, CrateName, Edition, Env, FileId, ProcMacro}; |
9 | use cargo_workspace::DepKind; | 9 | use cargo_workspace::DepKind; |
10 | use cfg::CfgOptions; | 10 | use cfg::{CfgDiff, CfgOptions}; |
11 | use paths::{AbsPath, AbsPathBuf}; | 11 | use paths::{AbsPath, AbsPathBuf}; |
12 | use proc_macro_api::ProcMacroClient; | 12 | use proc_macro_api::ProcMacroClient; |
13 | use rustc_hash::{FxHashMap, FxHashSet}; | 13 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -22,6 +22,8 @@ use crate::{ | |||
22 | Sysroot, TargetKind, | 22 | Sysroot, TargetKind, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | pub type CfgOverrides = FxHashMap<String, CfgDiff>; | ||
26 | |||
25 | /// `PackageRoot` describes a package root folder. | 27 | /// `PackageRoot` describes a package root folder. |
26 | /// Which may be an external dependency, or a member of | 28 | /// Which may be an external dependency, or a member of |
27 | /// the current workspace. | 29 | /// the current workspace. |
@@ -46,6 +48,7 @@ pub enum ProjectWorkspace { | |||
46 | /// FIXME: make this a per-crate map, as, eg, build.rs might have a | 48 | /// FIXME: make this a per-crate map, as, eg, build.rs might have a |
47 | /// different target. | 49 | /// different target. |
48 | rustc_cfg: Vec<CfgFlag>, | 50 | rustc_cfg: Vec<CfgFlag>, |
51 | cfg_overrides: CfgOverrides, | ||
49 | }, | 52 | }, |
50 | /// Project workspace was manually specified using a `rust-project.json` file. | 53 | /// Project workspace was manually specified using a `rust-project.json` file. |
51 | Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, | 54 | Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, |
@@ -67,7 +70,7 @@ impl fmt::Debug for ProjectWorkspace { | |||
67 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 70 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
68 | // Make sure this isn't too verbose. | 71 | // Make sure this isn't too verbose. |
69 | match self { | 72 | match self { |
70 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => f | 73 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg, cfg_overrides } => f |
71 | .debug_struct("Cargo") | 74 | .debug_struct("Cargo") |
72 | .field("root", &cargo.workspace_root().file_name()) | 75 | .field("root", &cargo.workspace_root().file_name()) |
73 | .field("n_packages", &cargo.packages().len()) | 76 | .field("n_packages", &cargo.packages().len()) |
@@ -77,6 +80,7 @@ impl fmt::Debug for ProjectWorkspace { | |||
77 | &rustc.as_ref().map_or(0, |rc| rc.packages().len()), | 80 | &rustc.as_ref().map_or(0, |rc| rc.packages().len()), |
78 | ) | 81 | ) |
79 | .field("n_rustc_cfg", &rustc_cfg.len()) | 82 | .field("n_rustc_cfg", &rustc_cfg.len()) |
83 | .field("n_cfg_overrides", &cfg_overrides.len()) | ||
80 | .finish(), | 84 | .finish(), |
81 | ProjectWorkspace::Json { project, sysroot, rustc_cfg } => { | 85 | ProjectWorkspace::Json { project, sysroot, rustc_cfg } => { |
82 | let mut debug_struct = f.debug_struct("Json"); | 86 | let mut debug_struct = f.debug_struct("Json"); |
@@ -164,7 +168,9 @@ impl ProjectWorkspace { | |||
164 | }; | 168 | }; |
165 | 169 | ||
166 | let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); | 170 | let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); |
167 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } | 171 | |
172 | let cfg_overrides = config.cfg_overrides(); | ||
173 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg, cfg_overrides } | ||
168 | } | 174 | } |
169 | }; | 175 | }; |
170 | 176 | ||
@@ -213,43 +219,45 @@ impl ProjectWorkspace { | |||
213 | }) | 219 | }) |
214 | })) | 220 | })) |
215 | .collect::<Vec<_>>(), | 221 | .collect::<Vec<_>>(), |
216 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg: _ } => cargo | 222 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg: _, cfg_overrides: _ } => { |
217 | .packages() | 223 | cargo |
218 | .map(|pkg| { | 224 | .packages() |
219 | let is_member = cargo[pkg].is_member; | 225 | .map(|pkg| { |
220 | let pkg_root = cargo[pkg].root().to_path_buf(); | 226 | let is_member = cargo[pkg].is_member; |
221 | 227 | let pkg_root = cargo[pkg].root().to_path_buf(); | |
222 | let mut include = vec![pkg_root.clone()]; | 228 | |
223 | include.extend( | 229 | let mut include = vec![pkg_root.clone()]; |
224 | build_data | 230 | include.extend( |
225 | .and_then(|it| it.get(cargo.workspace_root())) | 231 | build_data |
226 | .and_then(|map| map.get(&cargo[pkg].id)) | 232 | .and_then(|it| it.get(cargo.workspace_root())) |
227 | .and_then(|it| it.out_dir.clone()), | 233 | .and_then(|map| map.get(&cargo[pkg].id)) |
228 | ); | 234 | .and_then(|it| it.out_dir.clone()), |
235 | ); | ||
229 | 236 | ||
230 | let mut exclude = vec![pkg_root.join(".git")]; | 237 | let mut exclude = vec![pkg_root.join(".git")]; |
231 | if is_member { | 238 | if is_member { |
232 | exclude.push(pkg_root.join("target")); | 239 | exclude.push(pkg_root.join("target")); |
233 | } else { | 240 | } else { |
234 | exclude.push(pkg_root.join("tests")); | 241 | exclude.push(pkg_root.join("tests")); |
235 | exclude.push(pkg_root.join("examples")); | 242 | exclude.push(pkg_root.join("examples")); |
236 | exclude.push(pkg_root.join("benches")); | 243 | exclude.push(pkg_root.join("benches")); |
237 | } | 244 | } |
238 | PackageRoot { is_member, include, exclude } | 245 | PackageRoot { is_member, include, exclude } |
239 | }) | 246 | }) |
240 | .chain(sysroot.crates().map(|krate| PackageRoot { | 247 | .chain(sysroot.crates().map(|krate| PackageRoot { |
241 | is_member: false, | ||
242 | include: vec![sysroot[krate].root_dir().to_path_buf()], | ||
243 | exclude: Vec::new(), | ||
244 | })) | ||
245 | .chain(rustc.into_iter().flat_map(|rustc| { | ||
246 | rustc.packages().map(move |krate| PackageRoot { | ||
247 | is_member: false, | 248 | is_member: false, |
248 | include: vec![rustc[krate].root().to_path_buf()], | 249 | include: vec![sysroot[krate].root_dir().to_path_buf()], |
249 | exclude: Vec::new(), | 250 | exclude: Vec::new(), |
250 | }) | 251 | })) |
251 | })) | 252 | .chain(rustc.into_iter().flat_map(|rustc| { |
252 | .collect(), | 253 | rustc.packages().map(move |krate| PackageRoot { |
254 | is_member: false, | ||
255 | include: vec![rustc[krate].root().to_path_buf()], | ||
256 | exclude: Vec::new(), | ||
257 | }) | ||
258 | })) | ||
259 | .collect() | ||
260 | } | ||
253 | ProjectWorkspace::DetachedFiles { files, sysroot, .. } => files | 261 | ProjectWorkspace::DetachedFiles { files, sysroot, .. } => files |
254 | .into_iter() | 262 | .into_iter() |
255 | .map(|detached_file| PackageRoot { | 263 | .map(|detached_file| PackageRoot { |
@@ -299,16 +307,22 @@ impl ProjectWorkspace { | |||
299 | project, | 307 | project, |
300 | sysroot, | 308 | sysroot, |
301 | ), | 309 | ), |
302 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } => cargo_to_crate_graph( | 310 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg, cfg_overrides } => { |
303 | rustc_cfg.clone(), | 311 | cargo_to_crate_graph( |
304 | &proc_macro_loader, | 312 | rustc_cfg.clone(), |
305 | load, | 313 | cfg_overrides, |
306 | cargo, | 314 | &proc_macro_loader, |
307 | build_data.and_then(|it| it.get(cargo.workspace_root())), | 315 | load, |
308 | sysroot, | 316 | cargo, |
309 | rustc, | 317 | build_data.and_then(|it| it.get(cargo.workspace_root())), |
310 | rustc.as_ref().zip(build_data).and_then(|(it, map)| map.get(it.workspace_root())), | 318 | sysroot, |
311 | ), | 319 | rustc, |
320 | rustc | ||
321 | .as_ref() | ||
322 | .zip(build_data) | ||
323 | .and_then(|(it, map)| map.get(it.workspace_root())), | ||
324 | ) | ||
325 | } | ||
312 | ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => { | 326 | ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => { |
313 | detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot) | 327 | detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot) |
314 | } | 328 | } |
@@ -370,6 +384,7 @@ fn project_json_to_crate_graph( | |||
370 | file_id, | 384 | file_id, |
371 | krate.edition, | 385 | krate.edition, |
372 | krate.display_name.clone(), | 386 | krate.display_name.clone(), |
387 | cfg_options.clone(), | ||
373 | cfg_options, | 388 | cfg_options, |
374 | env, | 389 | env, |
375 | proc_macro.unwrap_or_default(), | 390 | proc_macro.unwrap_or_default(), |
@@ -398,6 +413,7 @@ fn project_json_to_crate_graph( | |||
398 | 413 | ||
399 | fn cargo_to_crate_graph( | 414 | fn cargo_to_crate_graph( |
400 | rustc_cfg: Vec<CfgFlag>, | 415 | rustc_cfg: Vec<CfgFlag>, |
416 | override_cfg: &CfgOverrides, | ||
401 | proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, | 417 | proc_macro_loader: &dyn Fn(&Path) -> Vec<ProcMacro>, |
402 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, | 418 | load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, |
403 | cargo: &CargoWorkspace, | 419 | cargo: &CargoWorkspace, |
@@ -425,6 +441,21 @@ fn cargo_to_crate_graph( | |||
425 | let mut has_private = false; | 441 | let mut has_private = false; |
426 | // Next, create crates for each package, target pair | 442 | // Next, create crates for each package, target pair |
427 | for pkg in cargo.packages() { | 443 | for pkg in cargo.packages() { |
444 | let mut cfg_options = &cfg_options; | ||
445 | let mut replaced_cfg_options; | ||
446 | if let Some(overrides) = override_cfg.get(&cargo[pkg].name) { | ||
447 | // FIXME: this is sort of a hack to deal with #![cfg(not(test))] vanishing such as seen | ||
448 | // in ed25519_dalek (#7243), and libcore (#9203) (although you only hit that one while | ||
449 | // working on rust-lang/rust as that's the only time it appears outside sysroot). | ||
450 | // | ||
451 | // A more ideal solution might be to reanalyze crates based on where the cursor is and | ||
452 | // figure out the set of cfgs that would have to apply to make it active. | ||
453 | |||
454 | replaced_cfg_options = cfg_options.clone(); | ||
455 | replaced_cfg_options.apply_diff(overrides.clone()); | ||
456 | cfg_options = &replaced_cfg_options; | ||
457 | }; | ||
458 | |||
428 | has_private |= cargo[pkg].metadata.rustc_private; | 459 | has_private |= cargo[pkg].metadata.rustc_private; |
429 | let mut lib_tgt = None; | 460 | let mut lib_tgt = None; |
430 | for &tgt in cargo[pkg].targets.iter() { | 461 | for &tgt in cargo[pkg].targets.iter() { |
@@ -550,6 +581,7 @@ fn detached_files_to_crate_graph( | |||
550 | Edition::Edition2018, | 581 | Edition::Edition2018, |
551 | display_name, | 582 | display_name, |
552 | cfg_options.clone(), | 583 | cfg_options.clone(), |
584 | cfg_options.clone(), | ||
553 | Env::default(), | 585 | Env::default(), |
554 | Vec::new(), | 586 | Vec::new(), |
555 | ); | 587 | ); |
@@ -689,11 +721,19 @@ fn add_target_crate_root( | |||
689 | .unwrap_or_default(); | 721 | .unwrap_or_default(); |
690 | 722 | ||
691 | let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string()); | 723 | let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string()); |
724 | let mut potential_cfg_options = cfg_options.clone(); | ||
725 | potential_cfg_options.extend( | ||
726 | pkg.features | ||
727 | .iter() | ||
728 | .map(|feat| CfgFlag::KeyValue { key: "feature".into(), value: feat.0.into() }), | ||
729 | ); | ||
730 | |||
692 | let crate_id = crate_graph.add_crate_root( | 731 | let crate_id = crate_graph.add_crate_root( |
693 | file_id, | 732 | file_id, |
694 | edition, | 733 | edition, |
695 | Some(display_name), | 734 | Some(display_name), |
696 | cfg_options, | 735 | cfg_options, |
736 | potential_cfg_options, | ||
697 | env, | 737 | env, |
698 | proc_macro, | 738 | proc_macro, |
699 | ); | 739 | ); |
@@ -723,6 +763,7 @@ fn sysroot_to_crate_graph( | |||
723 | Edition::Edition2018, | 763 | Edition::Edition2018, |
724 | Some(display_name), | 764 | Some(display_name), |
725 | cfg_options.clone(), | 765 | cfg_options.clone(), |
766 | cfg_options.clone(), | ||
726 | env, | 767 | env, |
727 | proc_macro, | 768 | proc_macro, |
728 | ); | 769 | ); |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index afc96505f..97246cae6 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -60,7 +60,14 @@ fn try_main() -> Result<()> { | |||
60 | } | 60 | } |
61 | } | 61 | } |
62 | 62 | ||
63 | setup_logging(flags.log_file.as_deref(), flags.no_log_buffering)?; | 63 | let mut log_file = flags.log_file.as_deref(); |
64 | |||
65 | let env_log_file = env::var("RA_LOG_FILE").ok(); | ||
66 | if let Some(env_log_file) = env_log_file.as_deref() { | ||
67 | log_file = Some(Path::new(env_log_file)); | ||
68 | } | ||
69 | |||
70 | setup_logging(log_file, flags.no_log_buffering)?; | ||
64 | let verbosity = flags.verbosity(); | 71 | let verbosity = flags.verbosity(); |
65 | 72 | ||
66 | match flags.subcommand { | 73 | match flags.subcommand { |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 16c295639..b9aa6f0aa 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -10,7 +10,10 @@ | |||
10 | use std::{ffi::OsString, iter, path::PathBuf}; | 10 | use std::{ffi::OsString, iter, path::PathBuf}; |
11 | 11 | ||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; | 13 | use ide::{ |
14 | AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, HoverDocFormat, | ||
15 | InlayHintsConfig, | ||
16 | }; | ||
14 | use ide_db::helpers::{ | 17 | use ide_db::helpers::{ |
15 | insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, | 18 | insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, |
16 | SnippetCap, | 19 | SnippetCap, |
@@ -32,6 +35,9 @@ use crate::{ | |||
32 | // | 35 | // |
33 | // However, editor specific config, which the server doesn't know about, should | 36 | // However, editor specific config, which the server doesn't know about, should |
34 | // be specified directly in `package.json`. | 37 | // be specified directly in `package.json`. |
38 | // | ||
39 | // To deprecate an option by replacing it with another name use `new_name | `old_name` so that we keep | ||
40 | // parsing the old name. | ||
35 | config_data! { | 41 | config_data! { |
36 | struct ConfigData { | 42 | struct ConfigData { |
37 | /// How imports should be grouped into use statements. | 43 | /// How imports should be grouped into use statements. |
@@ -55,6 +61,8 @@ config_data! { | |||
55 | cargo_autoreload: bool = "true", | 61 | cargo_autoreload: bool = "true", |
56 | /// Activate all available features (`--all-features`). | 62 | /// Activate all available features (`--all-features`). |
57 | cargo_allFeatures: bool = "false", | 63 | cargo_allFeatures: bool = "false", |
64 | /// Unsets `#[cfg(test)]` for the specified crates. | ||
65 | cargo_unsetTest: Vec<String> = "[\"core\"]", | ||
58 | /// List of features to activate. | 66 | /// List of features to activate. |
59 | cargo_features: Vec<String> = "[]", | 67 | cargo_features: Vec<String> = "[]", |
60 | /// Run build scripts (`build.rs`) for more precise code analysis. | 68 | /// Run build scripts (`build.rs`) for more precise code analysis. |
@@ -144,6 +152,12 @@ config_data! { | |||
144 | /// their contents. | 152 | /// their contents. |
145 | highlighting_strings: bool = "true", | 153 | highlighting_strings: bool = "true", |
146 | 154 | ||
155 | /// Whether to show documentation on hover. | ||
156 | hover_documentation: bool = "true", | ||
157 | /// Use markdown syntax for links in hover. | ||
158 | hover_linksInHover | | ||
159 | hoverActions_linksInHover: bool = "true", | ||
160 | |||
147 | /// Whether to show `Debug` action. Only applies when | 161 | /// Whether to show `Debug` action. Only applies when |
148 | /// `#rust-analyzer.hoverActions.enable#` is set. | 162 | /// `#rust-analyzer.hoverActions.enable#` is set. |
149 | hoverActions_debug: bool = "true", | 163 | hoverActions_debug: bool = "true", |
@@ -161,8 +175,6 @@ config_data! { | |||
161 | /// Whether to show `Run` action. Only applies when | 175 | /// Whether to show `Run` action. Only applies when |
162 | /// `#rust-analyzer.hoverActions.enable#` is set. | 176 | /// `#rust-analyzer.hoverActions.enable#` is set. |
163 | hoverActions_run: bool = "true", | 177 | hoverActions_run: bool = "true", |
164 | /// Use markdown syntax for links in hover. | ||
165 | hoverActions_linksInHover: bool = "true", | ||
166 | 178 | ||
167 | /// Whether to show inlay type hints for method chains. | 179 | /// Whether to show inlay type hints for method chains. |
168 | inlayHints_chainingHints: bool = "true", | 180 | inlayHints_chainingHints: bool = "true", |
@@ -303,6 +315,37 @@ impl LensConfig { | |||
303 | } | 315 | } |
304 | } | 316 | } |
305 | 317 | ||
318 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
319 | pub struct HoverActionsConfig { | ||
320 | pub implementations: bool, | ||
321 | pub references: bool, | ||
322 | pub run: bool, | ||
323 | pub debug: bool, | ||
324 | pub goto_type_def: bool, | ||
325 | } | ||
326 | |||
327 | impl HoverActionsConfig { | ||
328 | pub const NO_ACTIONS: Self = Self { | ||
329 | implementations: false, | ||
330 | references: false, | ||
331 | run: false, | ||
332 | debug: false, | ||
333 | goto_type_def: false, | ||
334 | }; | ||
335 | |||
336 | pub fn any(&self) -> bool { | ||
337 | self.implementations || self.references || self.runnable() || self.goto_type_def | ||
338 | } | ||
339 | |||
340 | pub fn none(&self) -> bool { | ||
341 | !self.any() | ||
342 | } | ||
343 | |||
344 | pub fn runnable(&self) -> bool { | ||
345 | self.run || self.debug | ||
346 | } | ||
347 | } | ||
348 | |||
306 | #[derive(Debug, Clone)] | 349 | #[derive(Debug, Clone)] |
307 | pub struct FilesConfig { | 350 | pub struct FilesConfig { |
308 | pub watcher: FilesWatcher, | 351 | pub watcher: FilesWatcher, |
@@ -521,7 +564,7 @@ impl Config { | |||
521 | pub fn code_action_group(&self) -> bool { | 564 | pub fn code_action_group(&self) -> bool { |
522 | self.experimental("codeActionGroup") | 565 | self.experimental("codeActionGroup") |
523 | } | 566 | } |
524 | pub fn hover_actions(&self) -> bool { | 567 | pub fn experimental_hover_actions(&self) -> bool { |
525 | self.experimental("hoverActions") | 568 | self.experimental("hoverActions") |
526 | } | 569 | } |
527 | pub fn server_status_notification(&self) -> bool { | 570 | pub fn server_status_notification(&self) -> bool { |
@@ -595,8 +638,10 @@ impl Config { | |||
595 | target: self.data.cargo_target.clone(), | 638 | target: self.data.cargo_target.clone(), |
596 | rustc_source, | 639 | rustc_source, |
597 | no_sysroot: self.data.cargo_noSysroot, | 640 | no_sysroot: self.data.cargo_noSysroot, |
641 | unset_test_crates: self.data.cargo_unsetTest.clone(), | ||
598 | } | 642 | } |
599 | } | 643 | } |
644 | |||
600 | pub fn rustfmt(&self) -> RustfmtConfig { | 645 | pub fn rustfmt(&self) -> RustfmtConfig { |
601 | match &self.data.rustfmt_overrideCommand { | 646 | match &self.data.rustfmt_overrideCommand { |
602 | Some(args) if !args.is_empty() => { | 647 | Some(args) if !args.is_empty() => { |
@@ -719,30 +764,41 @@ impl Config { | |||
719 | refs: self.data.lens_enable && self.data.lens_references, | 764 | refs: self.data.lens_enable && self.data.lens_references, |
720 | } | 765 | } |
721 | } | 766 | } |
722 | pub fn highlighting_strings(&self) -> bool { | 767 | pub fn hover_actions(&self) -> HoverActionsConfig { |
723 | self.data.highlighting_strings | 768 | HoverActionsConfig { |
724 | } | ||
725 | pub fn hover(&self) -> HoverConfig { | ||
726 | HoverConfig { | ||
727 | implementations: self.data.hoverActions_enable | 769 | implementations: self.data.hoverActions_enable |
728 | && self.data.hoverActions_implementations, | 770 | && self.data.hoverActions_implementations, |
729 | references: self.data.hoverActions_enable && self.data.hoverActions_references, | 771 | references: self.data.hoverActions_enable && self.data.hoverActions_references, |
730 | run: self.data.hoverActions_enable && self.data.hoverActions_run, | 772 | run: self.data.hoverActions_enable && self.data.hoverActions_run, |
731 | debug: self.data.hoverActions_enable && self.data.hoverActions_debug, | 773 | debug: self.data.hoverActions_enable && self.data.hoverActions_debug, |
732 | goto_type_def: self.data.hoverActions_enable && self.data.hoverActions_gotoTypeDef, | 774 | goto_type_def: self.data.hoverActions_enable && self.data.hoverActions_gotoTypeDef, |
733 | links_in_hover: self.data.hoverActions_linksInHover, | 775 | } |
734 | markdown: try_or!( | 776 | } |
735 | self.caps | 777 | pub fn highlighting_strings(&self) -> bool { |
736 | .text_document | 778 | self.data.highlighting_strings |
737 | .as_ref()? | 779 | } |
738 | .hover | 780 | pub fn hover(&self) -> HoverConfig { |
739 | .as_ref()? | 781 | HoverConfig { |
740 | .content_format | 782 | links_in_hover: self.data.hover_linksInHover, |
741 | .as_ref()? | 783 | documentation: self.data.hover_documentation.then(|| { |
742 | .as_slice(), | 784 | let is_markdown = try_or!( |
743 | &[] | 785 | self.caps |
744 | ) | 786 | .text_document |
745 | .contains(&MarkupKind::Markdown), | 787 | .as_ref()? |
788 | .hover | ||
789 | .as_ref()? | ||
790 | .content_format | ||
791 | .as_ref()? | ||
792 | .as_slice(), | ||
793 | &[] | ||
794 | ) | ||
795 | .contains(&MarkupKind::Markdown); | ||
796 | if is_markdown { | ||
797 | HoverDocFormat::Markdown | ||
798 | } else { | ||
799 | HoverDocFormat::PlainText | ||
800 | } | ||
801 | }), | ||
746 | } | 802 | } |
747 | } | 803 | } |
748 | 804 | ||
@@ -852,6 +908,7 @@ macro_rules! _config_data { | |||
852 | $({ | 908 | $({ |
853 | let field = stringify!($field); | 909 | let field = stringify!($field); |
854 | let ty = stringify!($ty); | 910 | let ty = stringify!($ty); |
911 | |||
855 | (field, ty, &[$($doc),*], $default) | 912 | (field, ty, &[$($doc),*], $default) |
856 | },)* | 913 | },)* |
857 | ]) | 914 | ]) |
@@ -863,6 +920,7 @@ macro_rules! _config_data { | |||
863 | $({ | 920 | $({ |
864 | let field = stringify!($field); | 921 | let field = stringify!($field); |
865 | let ty = stringify!($ty); | 922 | let ty = stringify!($ty); |
923 | |||
866 | (field, ty, &[$($doc),*], $default) | 924 | (field, ty, &[$($doc),*], $default) |
867 | },)* | 925 | },)* |
868 | ]) | 926 | ]) |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index ccf66294f..dcead5f5c 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -861,12 +861,10 @@ pub(crate) fn handle_hover( | |||
861 | ) -> Result<Option<lsp_ext::Hover>> { | 861 | ) -> Result<Option<lsp_ext::Hover>> { |
862 | let _p = profile::span("handle_hover"); | 862 | let _p = profile::span("handle_hover"); |
863 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; | 863 | let position = from_proto::file_position(&snap, params.text_document_position_params)?; |
864 | let hover_config = snap.config.hover(); | 864 | let info = match snap.analysis.hover(position, &snap.config.hover())? { |
865 | let info = | 865 | None => return Ok(None), |
866 | match snap.analysis.hover(position, hover_config.links_in_hover, hover_config.markdown)? { | 866 | Some(info) => info, |
867 | None => return Ok(None), | 867 | }; |
868 | Some(info) => info, | ||
869 | }; | ||
870 | let line_index = snap.file_line_index(position.file_id)?; | 868 | let line_index = snap.file_line_index(position.file_id)?; |
871 | let range = to_proto::range(&line_index, info.range); | 869 | let range = to_proto::range(&line_index, info.range); |
872 | let hover = lsp_ext::Hover { | 870 | let hover = lsp_ext::Hover { |
@@ -1483,7 +1481,7 @@ fn show_impl_command_link( | |||
1483 | snap: &GlobalStateSnapshot, | 1481 | snap: &GlobalStateSnapshot, |
1484 | position: &FilePosition, | 1482 | position: &FilePosition, |
1485 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1483 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1486 | if snap.config.hover().implementations { | 1484 | if snap.config.hover_actions().implementations { |
1487 | if let Some(nav_data) = snap.analysis.goto_implementation(*position).unwrap_or(None) { | 1485 | if let Some(nav_data) = snap.analysis.goto_implementation(*position).unwrap_or(None) { |
1488 | let uri = to_proto::url(snap, position.file_id); | 1486 | let uri = to_proto::url(snap, position.file_id); |
1489 | let line_index = snap.file_line_index(position.file_id).ok()?; | 1487 | let line_index = snap.file_line_index(position.file_id).ok()?; |
@@ -1509,7 +1507,7 @@ fn show_ref_command_link( | |||
1509 | snap: &GlobalStateSnapshot, | 1507 | snap: &GlobalStateSnapshot, |
1510 | position: &FilePosition, | 1508 | position: &FilePosition, |
1511 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1509 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1512 | if snap.config.hover().references { | 1510 | if snap.config.hover_actions().references { |
1513 | if let Some(ref_search_res) = snap.analysis.find_all_refs(*position, None).unwrap_or(None) { | 1511 | if let Some(ref_search_res) = snap.analysis.find_all_refs(*position, None).unwrap_or(None) { |
1514 | let uri = to_proto::url(snap, position.file_id); | 1512 | let uri = to_proto::url(snap, position.file_id); |
1515 | let line_index = snap.file_line_index(position.file_id).ok()?; | 1513 | let line_index = snap.file_line_index(position.file_id).ok()?; |
@@ -1540,8 +1538,8 @@ fn runnable_action_links( | |||
1540 | runnable: Runnable, | 1538 | runnable: Runnable, |
1541 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1539 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1542 | let cargo_spec = CargoTargetSpec::for_file(snap, runnable.nav.file_id).ok()?; | 1540 | let cargo_spec = CargoTargetSpec::for_file(snap, runnable.nav.file_id).ok()?; |
1543 | let hover_config = snap.config.hover(); | 1541 | let hover_actions_config = snap.config.hover_actions(); |
1544 | if !hover_config.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) { | 1542 | if !hover_actions_config.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) { |
1545 | return None; | 1543 | return None; |
1546 | } | 1544 | } |
1547 | 1545 | ||
@@ -1549,12 +1547,12 @@ fn runnable_action_links( | |||
1549 | to_proto::runnable(snap, runnable).ok().map(|r| { | 1547 | to_proto::runnable(snap, runnable).ok().map(|r| { |
1550 | let mut group = lsp_ext::CommandLinkGroup::default(); | 1548 | let mut group = lsp_ext::CommandLinkGroup::default(); |
1551 | 1549 | ||
1552 | if hover_config.run { | 1550 | if hover_actions_config.run { |
1553 | let run_command = to_proto::command::run_single(&r, action.run_title); | 1551 | let run_command = to_proto::command::run_single(&r, action.run_title); |
1554 | group.commands.push(to_command_link(run_command, r.label.clone())); | 1552 | group.commands.push(to_command_link(run_command, r.label.clone())); |
1555 | } | 1553 | } |
1556 | 1554 | ||
1557 | if hover_config.debug { | 1555 | if hover_actions_config.debug { |
1558 | let dbg_command = to_proto::command::debug_single(&r); | 1556 | let dbg_command = to_proto::command::debug_single(&r); |
1559 | group.commands.push(to_command_link(dbg_command, r.label)); | 1557 | group.commands.push(to_command_link(dbg_command, r.label)); |
1560 | } | 1558 | } |
@@ -1567,7 +1565,7 @@ fn goto_type_action_links( | |||
1567 | snap: &GlobalStateSnapshot, | 1565 | snap: &GlobalStateSnapshot, |
1568 | nav_targets: &[HoverGotoTypeData], | 1566 | nav_targets: &[HoverGotoTypeData], |
1569 | ) -> Option<lsp_ext::CommandLinkGroup> { | 1567 | ) -> Option<lsp_ext::CommandLinkGroup> { |
1570 | if !snap.config.hover().goto_type_def || nav_targets.is_empty() { | 1568 | if !snap.config.hover_actions().goto_type_def || nav_targets.is_empty() { |
1571 | return None; | 1569 | return None; |
1572 | } | 1570 | } |
1573 | 1571 | ||
@@ -1587,7 +1585,7 @@ fn prepare_hover_actions( | |||
1587 | snap: &GlobalStateSnapshot, | 1585 | snap: &GlobalStateSnapshot, |
1588 | actions: &[HoverAction], | 1586 | actions: &[HoverAction], |
1589 | ) -> Vec<lsp_ext::CommandLinkGroup> { | 1587 | ) -> Vec<lsp_ext::CommandLinkGroup> { |
1590 | if snap.config.hover().none() || !snap.config.hover_actions() { | 1588 | if snap.config.hover_actions().none() || !snap.config.experimental_hover_actions() { |
1591 | return Vec::new(); | 1589 | return Vec::new(); |
1592 | } | 1590 | } |
1593 | 1591 | ||
diff --git a/crates/syntax/src/ptr.rs b/crates/syntax/src/ptr.rs index 195d2251b..282470bae 100644 --- a/crates/syntax/src/ptr.rs +++ b/crates/syntax/src/ptr.rs | |||
@@ -32,10 +32,19 @@ impl SyntaxNodePtr { | |||
32 | SyntaxNodePtr { range: node.text_range(), kind: node.kind() } | 32 | SyntaxNodePtr { range: node.text_range(), kind: node.kind() } |
33 | } | 33 | } |
34 | 34 | ||
35 | /// "Dereference" the pointer to get the node it points to. | ||
36 | /// | ||
37 | /// Panics if node is not found, so make sure that `root` syntax tree is | ||
38 | /// equivalent (is build from the same text) to the tree which was | ||
39 | /// originally used to get this [`SyntaxNodePtr`]. | ||
40 | /// | ||
41 | /// The complexity is linear in the depth of the tree and logarithmic in | ||
42 | /// tree width. As most trees are shallow, thinking about this as | ||
43 | /// `O(log(N))` in the size of the tree is not too wrong! | ||
35 | pub fn to_node(&self, root: &SyntaxNode) -> SyntaxNode { | 44 | pub fn to_node(&self, root: &SyntaxNode) -> SyntaxNode { |
36 | assert!(root.parent().is_none()); | 45 | assert!(root.parent().is_none()); |
37 | successors(Some(root.clone()), |node| { | 46 | successors(Some(root.clone()), |node| { |
38 | node.children().find(|it| it.text_range().contains_range(self.range)) | 47 | node.child_or_token_at_range(self.range).and_then(|it| it.into_node()) |
39 | }) | 48 | }) |
40 | .find(|it| it.text_range() == self.range && it.kind() == self.kind) | 49 | .find(|it| it.text_range() == self.range && it.kind() == self.kind) |
41 | .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) | 50 | .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index d55bae62a..d9c22c180 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -11,6 +11,7 @@ mod fixture; | |||
11 | mod assert_linear; | 11 | mod assert_linear; |
12 | 12 | ||
13 | use std::{ | 13 | use std::{ |
14 | collections::BTreeMap, | ||
14 | convert::{TryFrom, TryInto}, | 15 | convert::{TryFrom, TryInto}, |
15 | env, fs, | 16 | env, fs, |
16 | path::{Path, PathBuf}, | 17 | path::{Path, PathBuf}, |
@@ -205,14 +206,25 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String { | |||
205 | /// | 206 | /// |
206 | /// // ^^^ first line | 207 | /// // ^^^ first line |
207 | /// // | second line | 208 | /// // | second line |
209 | /// | ||
210 | /// Annotations point to the last line that actually was long enough for the | ||
211 | /// range, not counting annotations themselves. So overlapping annotations are | ||
212 | /// possible: | ||
213 | /// ```no_run | ||
214 | /// // stuff other stuff | ||
215 | /// // ^^ 'st' | ||
216 | /// // ^^^^^ 'stuff' | ||
217 | /// // ^^^^^^^^^^^ 'other stuff' | ||
218 | /// ``` | ||
208 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | 219 | pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { |
209 | let mut res = Vec::new(); | 220 | let mut res = Vec::new(); |
210 | let mut prev_line_start: Option<TextSize> = Some(0.into()); | 221 | // map from line length to beginning of last line that had that length |
222 | let mut line_start_map = BTreeMap::new(); | ||
211 | let mut line_start: TextSize = 0.into(); | 223 | let mut line_start: TextSize = 0.into(); |
212 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); | 224 | let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new(); |
213 | for line in text.split_inclusive('\n') { | 225 | for line in text.split_inclusive('\n') { |
214 | let mut this_line_annotations = Vec::new(); | 226 | let mut this_line_annotations = Vec::new(); |
215 | if let Some(idx) = line.find("//") { | 227 | let line_length = if let Some(idx) = line.find("//") { |
216 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); | 228 | let annotation_offset = TextSize::of(&line[..idx + "//".len()]); |
217 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { | 229 | for annotation in extract_line_annotations(&line[idx + "//".len()..]) { |
218 | match annotation { | 230 | match annotation { |
@@ -222,7 +234,9 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
222 | let range = if file { | 234 | let range = if file { |
223 | TextRange::up_to(TextSize::of(text)) | 235 | TextRange::up_to(TextSize::of(text)) |
224 | } else { | 236 | } else { |
225 | range + prev_line_start.unwrap() | 237 | let line_start = line_start_map.range(range.end()..).next().unwrap(); |
238 | |||
239 | range + line_start.1 | ||
226 | }; | 240 | }; |
227 | res.push((range, content)) | 241 | res.push((range, content)) |
228 | } | 242 | } |
@@ -238,9 +252,14 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> { | |||
238 | } | 252 | } |
239 | } | 253 | } |
240 | } | 254 | } |
241 | } | 255 | idx.try_into().unwrap() |
256 | } else { | ||
257 | TextSize::of(line) | ||
258 | }; | ||
259 | |||
260 | line_start_map = line_start_map.split_off(&line_length); | ||
261 | line_start_map.insert(line_length, line_start); | ||
242 | 262 | ||
243 | prev_line_start = Some(line_start); | ||
244 | line_start += TextSize::of(line); | 263 | line_start += TextSize::of(line); |
245 | 264 | ||
246 | prev_line_annotations = this_line_annotations; | 265 | prev_line_annotations = this_line_annotations; |
@@ -296,7 +315,7 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> { | |||
296 | } | 315 | } |
297 | 316 | ||
298 | #[test] | 317 | #[test] |
299 | fn test_extract_annotations() { | 318 | fn test_extract_annotations_1() { |
300 | let text = stdx::trim_indent( | 319 | let text = stdx::trim_indent( |
301 | r#" | 320 | r#" |
302 | fn main() { | 321 | fn main() { |
@@ -321,6 +340,25 @@ fn main() { | |||
321 | assert_eq!(res[3].0.len(), 115); | 340 | assert_eq!(res[3].0.len(), 115); |
322 | } | 341 | } |
323 | 342 | ||
343 | #[test] | ||
344 | fn test_extract_annotations_2() { | ||
345 | let text = stdx::trim_indent( | ||
346 | r#" | ||
347 | fn main() { | ||
348 | (x, y); | ||
349 | //^ a | ||
350 | // ^ b | ||
351 | //^^^^^^^^ c | ||
352 | }"#, | ||
353 | ); | ||
354 | let res = extract_annotations(&text) | ||
355 | .into_iter() | ||
356 | .map(|(range, ann)| (&text[range], ann)) | ||
357 | .collect::<Vec<_>>(); | ||
358 | |||
359 | assert_eq!(res, [("x", "a".into()), ("y", "b".into()), ("(x, y)", "c".into())]); | ||
360 | } | ||
361 | |||
324 | /// Returns `false` if slow tests should not run, otherwise returns `true` and | 362 | /// Returns `false` if slow tests should not run, otherwise returns `true` and |
325 | /// also creates a file at `./target/.slow_tests_cookie` which serves as a flag | 363 | /// also creates a file at `./target/.slow_tests_cookie` which serves as a flag |
326 | /// that slow tests did run. | 364 | /// that slow tests did run. |
diff --git a/docs/dev/README.md b/docs/dev/README.md index e81f1e74c..a394b8501 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -131,7 +131,8 @@ Logging is done by both rust-analyzer and VS Code, so it might be tricky to figu | |||
131 | 131 | ||
132 | Inside rust-analyzer, we use the standard `log` crate for logging, and `env_logger` for logging frontend. | 132 | Inside rust-analyzer, we use the standard `log` crate for logging, and `env_logger` for logging frontend. |
133 | By default, log goes to stderr, but the stderr itself is processed by VS Code. | 133 | By default, log goes to stderr, but the stderr itself is processed by VS Code. |
134 | `--log-file <PATH>` CLI argument allows logging to file. | 134 | `--log-file <PATH>` CLI argument allows logging to file. |
135 | Setting the `RA_LOG_FILE=<PATH>` environment variable will also log to file, it will also override `--log-file`. | ||
135 | 136 | ||
136 | To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `rust-analyzer`. | 137 | To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `rust-analyzer`. |
137 | This shows `eprintln!` as well. | 138 | This shows `eprintln!` as well. |
diff --git a/docs/dev/debugging.md b/docs/dev/debugging.md index 5876e71bc..48caec1d8 100644 --- a/docs/dev/debugging.md +++ b/docs/dev/debugging.md | |||
@@ -65,6 +65,11 @@ If you need to debug the server from the very beginning, including its initializ | |||
65 | } | 65 | } |
66 | ``` | 66 | ``` |
67 | 67 | ||
68 | However for this to work, you will need to enable debug_assertions in your build | ||
69 | ```rust | ||
70 | RUSTFLAGS='--cfg debug_assertions' cargo build --release | ||
71 | ``` | ||
72 | |||
68 | ## Demo | 73 | ## Demo |
69 | 74 | ||
70 | - [Debugging TypeScript VScode extension](https://www.youtube.com/watch?v=T-hvpK6s4wM). | 75 | - [Debugging TypeScript VScode extension](https://www.youtube.com/watch?v=T-hvpK6s4wM). |
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 18ea77266..cc7fdd38f 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc | |||
@@ -39,6 +39,11 @@ Automatically refresh project info via `cargo metadata` on | |||
39 | -- | 39 | -- |
40 | Activate all available features (`--all-features`). | 40 | Activate all available features (`--all-features`). |
41 | -- | 41 | -- |
42 | [[rust-analyzer.cargo.unsetTest]]rust-analyzer.cargo.unsetTest (default: `["core"]`):: | ||
43 | + | ||
44 | -- | ||
45 | Unsets `#[cfg(test)]` for the specified crates. | ||
46 | -- | ||
42 | [[rust-analyzer.cargo.features]]rust-analyzer.cargo.features (default: `[]`):: | 47 | [[rust-analyzer.cargo.features]]rust-analyzer.cargo.features (default: `[]`):: |
43 | + | 48 | + |
44 | -- | 49 | -- |
@@ -210,6 +215,16 @@ In some editors (e.g. vscode) semantic tokens override other highlighting gramma | |||
210 | By disabling semantic tokens for strings, other grammars can be used to highlight | 215 | By disabling semantic tokens for strings, other grammars can be used to highlight |
211 | their contents. | 216 | their contents. |
212 | -- | 217 | -- |
218 | [[rust-analyzer.hover.documentation]]rust-analyzer.hover.documentation (default: `true`):: | ||
219 | + | ||
220 | -- | ||
221 | Whether to show documentation on hover. | ||
222 | -- | ||
223 | [[rust-analyzer.hover.linksInHover]]rust-analyzer.hover.linksInHover (default: `true`):: | ||
224 | + | ||
225 | -- | ||
226 | Use markdown syntax for links in hover. | ||
227 | -- | ||
213 | [[rust-analyzer.hoverActions.debug]]rust-analyzer.hoverActions.debug (default: `true`):: | 228 | [[rust-analyzer.hoverActions.debug]]rust-analyzer.hoverActions.debug (default: `true`):: |
214 | + | 229 | + |
215 | -- | 230 | -- |
@@ -245,11 +260,6 @@ Whether to show `References` action. Only applies when | |||
245 | Whether to show `Run` action. Only applies when | 260 | Whether to show `Run` action. Only applies when |
246 | `#rust-analyzer.hoverActions.enable#` is set. | 261 | `#rust-analyzer.hoverActions.enable#` is set. |
247 | -- | 262 | -- |
248 | [[rust-analyzer.hoverActions.linksInHover]]rust-analyzer.hoverActions.linksInHover (default: `true`):: | ||
249 | + | ||
250 | -- | ||
251 | Use markdown syntax for links in hover. | ||
252 | -- | ||
253 | [[rust-analyzer.inlayHints.chainingHints]]rust-analyzer.inlayHints.chainingHints (default: `true`):: | 263 | [[rust-analyzer.inlayHints.chainingHints]]rust-analyzer.inlayHints.chainingHints (default: `true`):: |
254 | + | 264 | + |
255 | -- | 265 | -- |
diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index d22c80754..95c9571e9 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json | |||
@@ -11,7 +11,7 @@ | |||
11 | "dependencies": { | 11 | "dependencies": { |
12 | "https-proxy-agent": "^5.0.0", | 12 | "https-proxy-agent": "^5.0.0", |
13 | "node-fetch": "^2.6.1", | 13 | "node-fetch": "^2.6.1", |
14 | "vscode-languageclient": "^7.1.0-next.4" | 14 | "vscode-languageclient": "^7.1.0-next.5" |
15 | }, | 15 | }, |
16 | "devDependencies": { | 16 | "devDependencies": { |
17 | "@rollup/plugin-commonjs": "^17.0.0", | 17 | "@rollup/plugin-commonjs": "^17.0.0", |
@@ -3388,39 +3388,39 @@ | |||
3388 | } | 3388 | } |
3389 | }, | 3389 | }, |
3390 | "node_modules/vscode-jsonrpc": { | 3390 | "node_modules/vscode-jsonrpc": { |
3391 | "version": "6.1.0-next.2", | 3391 | "version": "7.0.0-next.1", |
3392 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.1.0-next.2.tgz", | 3392 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-7.0.0-next.1.tgz", |
3393 | "integrity": "sha512-nkiNDGI+Ytp7uj1lxHXddXCoEunhcry1D+KmVHBfUUgWT9jMF8ZJyH5KQObdF+OGAh7bXZxD/SV4uGwSCeHHWA==", | 3393 | "integrity": "sha512-dEmliPZGbSyIcEeKRGzosCy7y7zsc8FXg1l5BBOGgMUbemlo3vUnsa2GFqpILJwJvlbvkRcF2QASNwIlKe9J7g==", |
3394 | "engines": { | 3394 | "engines": { |
3395 | "node": ">=8.0.0 || >=10.0.0" | 3395 | "node": ">=8.0.0 || >=10.0.0" |
3396 | } | 3396 | } |
3397 | }, | 3397 | }, |
3398 | "node_modules/vscode-languageclient": { | 3398 | "node_modules/vscode-languageclient": { |
3399 | "version": "7.1.0-next.4", | 3399 | "version": "7.1.0-next.5", |
3400 | "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.1.0-next.4.tgz", | 3400 | "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.1.0-next.5.tgz", |
3401 | "integrity": "sha512-Gal+DvbI1KIwO1z90MvSnghMCVBCGlwdpOVIS0Hhmep7rjHUOwuC5Df7YlVkpzfPm+RCRyZQnUSJ19VNrnxxhA==", | 3401 | "integrity": "sha512-TpzpAhpdCNJHaLzptFRs54xsU6xTmaiVPCse0W0rRB5jJBPjOBKilrFPMMm/sJA0y8Yxa9sOvZaNu6WPg3dYAw==", |
3402 | "dependencies": { | 3402 | "dependencies": { |
3403 | "minimatch": "^3.0.4", | 3403 | "minimatch": "^3.0.4", |
3404 | "semver": "^7.3.4", | 3404 | "semver": "^7.3.4", |
3405 | "vscode-languageserver-protocol": "3.17.0-next.5" | 3405 | "vscode-languageserver-protocol": "3.17.0-next.6" |
3406 | }, | 3406 | }, |
3407 | "engines": { | 3407 | "engines": { |
3408 | "vscode": "^1.53.0" | 3408 | "vscode": "^1.53.0" |
3409 | } | 3409 | } |
3410 | }, | 3410 | }, |
3411 | "node_modules/vscode-languageserver-protocol": { | 3411 | "node_modules/vscode-languageserver-protocol": { |
3412 | "version": "3.17.0-next.5", | 3412 | "version": "3.17.0-next.6", |
3413 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.5.tgz", | 3413 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.6.tgz", |
3414 | "integrity": "sha512-LFZ6WMB3iPezQAU9OnGoERzcIVKhcs0OLfD/NHcqSj3g1wgxuLUL5kSlZbbjFySQCmhzm6b0yb3hjTSeBtq1+w==", | 3414 | "integrity": "sha512-f1kGsoOpISB5jSqQNeMDl2446enxVahyux2e5vZap6pu/TC+2UlvPT4DCR0gPph95KOQZweL9zq1SzLoPdqhuA==", |
3415 | "dependencies": { | 3415 | "dependencies": { |
3416 | "vscode-jsonrpc": "6.1.0-next.2", | 3416 | "vscode-jsonrpc": "7.0.0-next.1", |
3417 | "vscode-languageserver-types": "3.17.0-next.1" | 3417 | "vscode-languageserver-types": "3.17.0-next.2" |
3418 | } | 3418 | } |
3419 | }, | 3419 | }, |
3420 | "node_modules/vscode-languageserver-types": { | 3420 | "node_modules/vscode-languageserver-types": { |
3421 | "version": "3.17.0-next.1", | 3421 | "version": "3.17.0-next.2", |
3422 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.1.tgz", | 3422 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.2.tgz", |
3423 | "integrity": "sha512-VGzh06oynbYa6JbTKUbxOEZN7CYEtWhN7DK5wfzUpeCJl8X8xZX39g2PVfpqXrIEduu7dcJgK007KgnX9tHNKA==" | 3423 | "integrity": "sha512-L5S2kNLCgYJMVWgsZjBaorMM/6+itAfvOyl6Kv1bgFzDNaUKm9HsnUlehjpWPdV5DqnfJhJ5E03Z+/3Mw8ii+Q==" |
3424 | }, | 3424 | }, |
3425 | "node_modules/vscode-test": { | 3425 | "node_modules/vscode-test": { |
3426 | "version": "1.5.2", | 3426 | "version": "1.5.2", |
@@ -6167,33 +6167,33 @@ | |||
6167 | } | 6167 | } |
6168 | }, | 6168 | }, |
6169 | "vscode-jsonrpc": { | 6169 | "vscode-jsonrpc": { |
6170 | "version": "6.1.0-next.2", | 6170 | "version": "7.0.0-next.1", |
6171 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.1.0-next.2.tgz", | 6171 | "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-7.0.0-next.1.tgz", |
6172 | "integrity": "sha512-nkiNDGI+Ytp7uj1lxHXddXCoEunhcry1D+KmVHBfUUgWT9jMF8ZJyH5KQObdF+OGAh7bXZxD/SV4uGwSCeHHWA==" | 6172 | "integrity": "sha512-dEmliPZGbSyIcEeKRGzosCy7y7zsc8FXg1l5BBOGgMUbemlo3vUnsa2GFqpILJwJvlbvkRcF2QASNwIlKe9J7g==" |
6173 | }, | 6173 | }, |
6174 | "vscode-languageclient": { | 6174 | "vscode-languageclient": { |
6175 | "version": "7.1.0-next.4", | 6175 | "version": "7.1.0-next.5", |
6176 | "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.1.0-next.4.tgz", | 6176 | "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.1.0-next.5.tgz", |
6177 | "integrity": "sha512-Gal+DvbI1KIwO1z90MvSnghMCVBCGlwdpOVIS0Hhmep7rjHUOwuC5Df7YlVkpzfPm+RCRyZQnUSJ19VNrnxxhA==", | 6177 | "integrity": "sha512-TpzpAhpdCNJHaLzptFRs54xsU6xTmaiVPCse0W0rRB5jJBPjOBKilrFPMMm/sJA0y8Yxa9sOvZaNu6WPg3dYAw==", |
6178 | "requires": { | 6178 | "requires": { |
6179 | "minimatch": "^3.0.4", | 6179 | "minimatch": "^3.0.4", |
6180 | "semver": "^7.3.4", | 6180 | "semver": "^7.3.4", |
6181 | "vscode-languageserver-protocol": "3.17.0-next.5" | 6181 | "vscode-languageserver-protocol": "3.17.0-next.6" |
6182 | } | 6182 | } |
6183 | }, | 6183 | }, |
6184 | "vscode-languageserver-protocol": { | 6184 | "vscode-languageserver-protocol": { |
6185 | "version": "3.17.0-next.5", | 6185 | "version": "3.17.0-next.6", |
6186 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.5.tgz", | 6186 | "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.0-next.6.tgz", |
6187 | "integrity": "sha512-LFZ6WMB3iPezQAU9OnGoERzcIVKhcs0OLfD/NHcqSj3g1wgxuLUL5kSlZbbjFySQCmhzm6b0yb3hjTSeBtq1+w==", | 6187 | "integrity": "sha512-f1kGsoOpISB5jSqQNeMDl2446enxVahyux2e5vZap6pu/TC+2UlvPT4DCR0gPph95KOQZweL9zq1SzLoPdqhuA==", |
6188 | "requires": { | 6188 | "requires": { |
6189 | "vscode-jsonrpc": "6.1.0-next.2", | 6189 | "vscode-jsonrpc": "7.0.0-next.1", |
6190 | "vscode-languageserver-types": "3.17.0-next.1" | 6190 | "vscode-languageserver-types": "3.17.0-next.2" |
6191 | } | 6191 | } |
6192 | }, | 6192 | }, |
6193 | "vscode-languageserver-types": { | 6193 | "vscode-languageserver-types": { |
6194 | "version": "3.17.0-next.1", | 6194 | "version": "3.17.0-next.2", |
6195 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.1.tgz", | 6195 | "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.0-next.2.tgz", |
6196 | "integrity": "sha512-VGzh06oynbYa6JbTKUbxOEZN7CYEtWhN7DK5wfzUpeCJl8X8xZX39g2PVfpqXrIEduu7dcJgK007KgnX9tHNKA==" | 6196 | "integrity": "sha512-L5S2kNLCgYJMVWgsZjBaorMM/6+itAfvOyl6Kv1bgFzDNaUKm9HsnUlehjpWPdV5DqnfJhJ5E03Z+/3Mw8ii+Q==" |
6197 | }, | 6197 | }, |
6198 | "vscode-test": { | 6198 | "vscode-test": { |
6199 | "version": "1.5.2", | 6199 | "version": "1.5.2", |
diff --git a/editors/code/package.json b/editors/code/package.json index c077bd2c0..0b9b4e42f 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -37,7 +37,7 @@ | |||
37 | "dependencies": { | 37 | "dependencies": { |
38 | "https-proxy-agent": "^5.0.0", | 38 | "https-proxy-agent": "^5.0.0", |
39 | "node-fetch": "^2.6.1", | 39 | "node-fetch": "^2.6.1", |
40 | "vscode-languageclient": "^7.1.0-next.4" | 40 | "vscode-languageclient": "^7.1.0-next.5" |
41 | }, | 41 | }, |
42 | "devDependencies": { | 42 | "devDependencies": { |
43 | "@rollup/plugin-commonjs": "^17.0.0", | 43 | "@rollup/plugin-commonjs": "^17.0.0", |
@@ -452,6 +452,16 @@ | |||
452 | "default": false, | 452 | "default": false, |
453 | "type": "boolean" | 453 | "type": "boolean" |
454 | }, | 454 | }, |
455 | "rust-analyzer.cargo.unsetTest": { | ||
456 | "markdownDescription": "Unsets `#[cfg(test)]` for the specified crates.", | ||
457 | "default": [ | ||
458 | "core" | ||
459 | ], | ||
460 | "type": "array", | ||
461 | "items": { | ||
462 | "type": "string" | ||
463 | } | ||
464 | }, | ||
455 | "rust-analyzer.cargo.features": { | 465 | "rust-analyzer.cargo.features": { |
456 | "markdownDescription": "List of features to activate.", | 466 | "markdownDescription": "List of features to activate.", |
457 | "default": [], | 467 | "default": [], |
@@ -645,6 +655,16 @@ | |||
645 | "default": true, | 655 | "default": true, |
646 | "type": "boolean" | 656 | "type": "boolean" |
647 | }, | 657 | }, |
658 | "rust-analyzer.hover.documentation": { | ||
659 | "markdownDescription": "Whether to show documentation on hover.", | ||
660 | "default": true, | ||
661 | "type": "boolean" | ||
662 | }, | ||
663 | "rust-analyzer.hover.linksInHover": { | ||
664 | "markdownDescription": "Use markdown syntax for links in hover.", | ||
665 | "default": true, | ||
666 | "type": "boolean" | ||
667 | }, | ||
648 | "rust-analyzer.hoverActions.debug": { | 668 | "rust-analyzer.hoverActions.debug": { |
649 | "markdownDescription": "Whether to show `Debug` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.", | 669 | "markdownDescription": "Whether to show `Debug` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.", |
650 | "default": true, | 670 | "default": true, |
@@ -675,11 +695,6 @@ | |||
675 | "default": true, | 695 | "default": true, |
676 | "type": "boolean" | 696 | "type": "boolean" |
677 | }, | 697 | }, |
678 | "rust-analyzer.hoverActions.linksInHover": { | ||
679 | "markdownDescription": "Use markdown syntax for links in hover.", | ||
680 | "default": true, | ||
681 | "type": "boolean" | ||
682 | }, | ||
683 | "rust-analyzer.inlayHints.chainingHints": { | 698 | "rust-analyzer.inlayHints.chainingHints": { |
684 | "markdownDescription": "Whether to show inlay type hints for method chains.", | 699 | "markdownDescription": "Whether to show inlay type hints for method chains.", |
685 | "default": true, | 700 | "default": true, |