aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/base_db/src/fixture.rs6
-rw-r--r--crates/hir_ty/src/tests/regression.rs64
-rw-r--r--crates/hir_ty/src/tests/simple.rs8
-rw-r--r--crates/hir_ty/src/tests/traits.rs309
-rw-r--r--crates/ide/src/goto_implementation.rs7
-rw-r--r--crates/ide/src/hover.rs6
-rw-r--r--crates/ide/src/inlay_hints.rs21
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs3
-rw-r--r--crates/ide_assists/src/handlers/convert_into_to_from.rs6
-rw-r--r--crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs14
-rw-r--r--crates/ide_assists/src/handlers/extract_function.rs12
-rw-r--r--crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs2
-rw-r--r--crates/ide_assists/src/handlers/fill_match_arms.rs11
-rw-r--r--crates/ide_assists/src/handlers/replace_if_let_with_match.rs66
-rw-r--r--crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs13
-rw-r--r--crates/ide_assists/src/handlers/replace_unwrap_with_match.rs60
-rw-r--r--crates/ide_assists/src/tests.rs1
-rw-r--r--crates/ide_assists/src/tests/generated.rs27
-rw-r--r--crates/ide_completion/src/completions/dot.rs5
-rw-r--r--crates/ide_completion/src/completions/postfix.rs27
-rw-r--r--crates/ide_completion/src/context.rs3
-rw-r--r--crates/ide_completion/src/item.rs2
-rw-r--r--crates/ide_completion/src/render.rs20
-rw-r--r--crates/ide_completion/src/tests.rs1
-rw-r--r--crates/ide_db/src/helpers/insert_use.rs78
-rw-r--r--crates/ide_db/src/helpers/insert_use/tests.rs165
-rw-r--r--crates/ide_diagnostics/src/handlers/missing_ok_or_some_in_tail_expr.rs76
-rw-r--r--crates/ide_diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs86
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/integrated_benchmarks.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs1
-rw-r--r--crates/syntax/src/ast/node_ext.rs17
-rw-r--r--crates/test_utils/src/minicore.rs69
33 files changed, 550 insertions, 642 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs
index d56b20b83..6ce377710 100644
--- a/crates/base_db/src/fixture.rs
+++ b/crates/base_db/src/fixture.rs
@@ -106,7 +106,7 @@ impl ChangeFixture {
106 let (range_or_offset, text) = extract_range_or_offset(&entry.text); 106 let (range_or_offset, text) = extract_range_or_offset(&entry.text);
107 assert!(file_position.is_none()); 107 assert!(file_position.is_none());
108 file_position = Some((file_id, range_or_offset)); 108 file_position = Some((file_id, range_or_offset));
109 text.to_string() 109 text
110 } 110 }
111 } else { 111 } else {
112 entry.text.clone() 112 entry.text.clone()
@@ -114,6 +114,9 @@ impl ChangeFixture {
114 114
115 let meta = FileMeta::from(entry); 115 let meta = FileMeta::from(entry);
116 assert!(meta.path.starts_with(&source_root_prefix)); 116 assert!(meta.path.starts_with(&source_root_prefix));
117 if !meta.deps.is_empty() {
118 assert!(meta.krate.is_some(), "can't specify deps without naming the crate")
119 }
117 120
118 if meta.introduce_new_source_root { 121 if meta.introduce_new_source_root {
119 roots.push(SourceRoot::new_local(mem::take(&mut file_set))); 122 roots.push(SourceRoot::new_local(mem::take(&mut file_set)));
@@ -199,6 +202,7 @@ impl ChangeFixture {
199 } 202 }
200} 203}
201 204
205#[derive(Debug)]
202struct FileMeta { 206struct FileMeta {
203 path: String, 207 path: String,
204 krate: Option<String>, 208 krate: Option<String>,
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index e0ad41fb9..0f418ea49 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -705,12 +705,8 @@ fn issue_4931() {
705fn issue_4885() { 705fn issue_4885() {
706 check_infer( 706 check_infer(
707 r#" 707 r#"
708 #[lang = "coerce_unsized"] 708 //- minicore: coerce_unsized, future
709 pub trait CoerceUnsized<T> {} 709 use core::future::Future;
710
711 trait Future {
712 type Output;
713 }
714 trait Foo<R> { 710 trait Foo<R> {
715 type Bar; 711 type Bar;
716 } 712 }
@@ -727,13 +723,13 @@ fn issue_4885() {
727 } 723 }
728 "#, 724 "#,
729 expect![[r#" 725 expect![[r#"
730 136..139 'key': &K 726 70..73 'key': &K
731 198..214 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar> 727 132..148 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
732 204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar> 728 138..141 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
733 204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> 729 138..146 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
734 208..211 'key': &K 730 142..145 'key': &K
735 228..231 'key': &K 731 162..165 'key': &K
736 290..293 '{ }': () 732 224..227 '{ }': ()
737 "#]], 733 "#]],
738 ); 734 );
739} 735}
@@ -796,6 +792,7 @@ fn issue_4800() {
796fn issue_4966() { 792fn issue_4966() {
797 check_infer( 793 check_infer(
798 r#" 794 r#"
795 //- minicore: deref
799 pub trait IntoIterator { 796 pub trait IntoIterator {
800 type Item; 797 type Item;
801 } 798 }
@@ -806,12 +803,7 @@ fn issue_4966() {
806 803
807 struct Vec<T> {} 804 struct Vec<T> {}
808 805
809 #[lang = "deref"] 806 impl<T> core::ops::Deref for Vec<T> {
810 pub trait Deref {
811 type Target;
812 }
813
814 impl<T> Deref for Vec<T> {
815 type Target = [T]; 807 type Target = [T];
816 } 808 }
817 809
@@ -828,23 +820,23 @@ fn issue_4966() {
828 } 820 }
829 "#, 821 "#,
830 expect![[r#" 822 expect![[r#"
831 270..274 'iter': T 823 225..229 'iter': T
832 289..291 '{}': () 824 244..246 '{}': ()
833 303..447 '{ ...r(); }': () 825 258..402 '{ ...r(); }': ()
834 313..318 'inner': Map<|&f64| -> f64> 826 268..273 'inner': Map<|&f64| -> f64>
835 321..345 'Map { ... 0.0 }': Map<|&f64| -> f64> 827 276..300 'Map { ... 0.0 }': Map<|&f64| -> f64>
836 330..343 '|_: &f64| 0.0': |&f64| -> f64 828 285..298 '|_: &f64| 0.0': |&f64| -> f64
837 331..332 '_': &f64 829 286..287 '_': &f64
838 340..343 '0.0': f64 830 295..298 '0.0': f64
839 356..362 'repeat': Repeat<Map<|&f64| -> f64>> 831 311..317 'repeat': Repeat<Map<|&f64| -> f64>>
840 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> 832 320..345 'Repeat...nner }': Repeat<Map<|&f64| -> f64>>
841 383..388 'inner': Map<|&f64| -> f64> 833 338..343 'inner': Map<|&f64| -> f64>
842 401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> 834 356..359 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
843 407..416 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> 835 362..371 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
844 407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> 836 362..379 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
845 417..423 'repeat': Repeat<Map<|&f64| -> f64>> 837 372..378 'repeat': Repeat<Map<|&f64| -> f64>>
846 431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>> 838 386..389 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
847 431..444 'vec.foo_bar()': {unknown} 839 386..399 'vec.foo_bar()': {unknown}
848 "#]], 840 "#]],
849 ); 841 );
850} 842}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 68776f3c0..108ff3179 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -1917,6 +1917,7 @@ fn fn_pointer_return() {
1917fn effects_smoke_test() { 1917fn effects_smoke_test() {
1918 check_infer( 1918 check_infer(
1919 r#" 1919 r#"
1920 //- minicore: future
1920 async fn main() { 1921 async fn main() {
1921 let x = unsafe { 92 }; 1922 let x = unsafe { 92 };
1922 let y = async { async { () }.await }; 1923 let y = async { async { () }.await };
@@ -1924,13 +1925,6 @@ fn effects_smoke_test() {
1924 let w = const { 92 }; 1925 let w = const { 92 };
1925 let t = 'a: { 92 }; 1926 let t = 'a: { 92 };
1926 } 1927 }
1927
1928 #[prelude_import] use future::*;
1929
1930 mod future {
1931 #[lang = "future_trait"]
1932 pub trait Future { type Output; }
1933 }
1934 "#, 1928 "#,
1935 expect![[r#" 1929 expect![[r#"
1936 16..162 '{ ...2 }; }': () 1930 16..162 '{ ...2 }; }': ()
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 22e0bfc49..279a1354a 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -567,11 +567,11 @@ fn indexing_arrays() {
567fn infer_ops_index() { 567fn infer_ops_index() {
568 check_types( 568 check_types(
569 r#" 569 r#"
570//- /main.rs crate:main deps:std 570//- minicore: index
571struct Bar; 571struct Bar;
572struct Foo; 572struct Foo;
573 573
574impl std::ops::Index<u32> for Bar { 574impl core::ops::Index<u32> for Bar {
575 type Output = Foo; 575 type Output = Foo;
576} 576}
577 577
@@ -580,15 +580,6 @@ fn test() {
580 let b = a[1u32]; 580 let b = a[1u32];
581 b; 581 b;
582} //^ Foo 582} //^ Foo
583
584//- /std.rs crate:std
585#[prelude_import] use ops::*;
586mod ops {
587 #[lang = "index"]
588 pub trait Index<Idx> {
589 type Output;
590 }
591}
592"#, 583"#,
593 ); 584 );
594} 585}
@@ -597,16 +588,16 @@ mod ops {
597fn infer_ops_index_int() { 588fn infer_ops_index_int() {
598 check_types( 589 check_types(
599 r#" 590 r#"
600//- /main.rs crate:main deps:std 591//- minicore: index
601struct Bar; 592struct Bar;
602struct Foo; 593struct Foo;
603 594
604impl std::ops::Index<u32> for Bar { 595impl core::ops::Index<u32> for Bar {
605 type Output = Foo; 596 type Output = Foo;
606} 597}
607 598
608struct Range; 599struct Range;
609impl std::ops::Index<Range> for Bar { 600impl core::ops::Index<Range> for Bar {
610 type Output = Bar; 601 type Output = Bar;
611} 602}
612 603
@@ -616,15 +607,6 @@ fn test() {
616 b; 607 b;
617 //^ Foo 608 //^ Foo
618} 609}
619
620//- /std.rs crate:std
621#[prelude_import] use ops::*;
622mod ops {
623 #[lang = "index"]
624 pub trait Index<Idx> {
625 type Output;
626 }
627}
628"#, 610"#,
629 ); 611 );
630} 612}
@@ -633,25 +615,12 @@ mod ops {
633fn infer_ops_index_autoderef() { 615fn infer_ops_index_autoderef() {
634 check_types( 616 check_types(
635 r#" 617 r#"
636//- /main.rs crate:main deps:std 618//- minicore: index, slice
637fn test() { 619fn test() {
638 let a = &[1u32, 2, 3]; 620 let a = &[1u32, 2, 3];
639 let b = a[1u32]; 621 let b = a[1];
640 b; 622 b;
641} //^ u32 623} //^ u32
642
643//- /std.rs crate:std
644impl<T> ops::Index<u32> for [T] {
645 type Output = T;
646}
647
648#[prelude_import] use ops::*;
649mod ops {
650 #[lang = "index"]
651 pub trait Index<Idx> {
652 type Output;
653 }
654}
655"#, 624"#,
656 ); 625 );
657} 626}
@@ -884,12 +853,9 @@ fn test<T>(t: T) { t.foo(); }
884fn generic_param_env_deref() { 853fn generic_param_env_deref() {
885 check_types( 854 check_types(
886 r#" 855 r#"
887#[lang = "deref"] 856//- minicore: deref
888trait Deref {
889 type Target;
890}
891trait Trait {} 857trait Trait {}
892impl<T> Deref for T where T: Trait { 858impl<T> core::ops::Deref for T where T: Trait {
893 type Target = i128; 859 type Target = i128;
894} 860}
895fn test<T: Trait>(t: T) { (*t); } 861fn test<T: Trait>(t: T) { (*t); }
@@ -1758,20 +1724,7 @@ fn test() {
1758fn fn_trait_deref_with_ty_default() { 1724fn fn_trait_deref_with_ty_default() {
1759 check_infer( 1725 check_infer(
1760 r#" 1726 r#"
1761#[lang = "deref"] 1727//- minicore: deref, fn
1762trait Deref {
1763 type Target;
1764
1765 fn deref(&self) -> &Self::Target;
1766}
1767
1768#[lang="fn_once"]
1769trait FnOnce<Args> {
1770 type Output;
1771
1772 fn call_once(self, args: Args) -> Self::Output;
1773}
1774
1775struct Foo; 1728struct Foo;
1776 1729
1777impl Foo { 1730impl Foo {
@@ -1784,7 +1737,7 @@ impl<T, F> Lazy<T, F> {
1784 pub fn new(f: F) -> Lazy<T, F> {} 1737 pub fn new(f: F) -> Lazy<T, F> {}
1785} 1738}
1786 1739
1787impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { 1740impl<T, F: FnOnce() -> T> core::ops::Deref for Lazy<T, F> {
1788 type Target = T; 1741 type Target = T;
1789} 1742}
1790 1743
@@ -1798,32 +1751,29 @@ fn test() {
1798 let r2 = lazy2.foo(); 1751 let r2 = lazy2.foo();
1799}"#, 1752}"#,
1800 expect![[r#" 1753 expect![[r#"
1801 64..68 'self': &Self 1754 36..40 'self': &Foo
1802 165..169 'self': Self 1755 51..53 '{}': ()
1803 171..175 'args': Args 1756 131..132 'f': F
1804 239..243 'self': &Foo 1757 151..153 '{}': ()
1805 254..256 '{}': () 1758 251..497 '{ ...o(); }': ()
1806 334..335 'f': F 1759 261..266 'lazy1': Lazy<Foo, || -> Foo>
1807 354..356 '{}': () 1760 283..292 'Lazy::new': fn new<Foo, || -> Foo>(|| -> Foo) -> Lazy<Foo, || -> Foo>
1808 443..689 '{ ...o(); }': () 1761 283..300 'Lazy::...| Foo)': Lazy<Foo, || -> Foo>
1809 453..458 'lazy1': Lazy<Foo, || -> Foo> 1762 293..299 '|| Foo': || -> Foo
1810 475..484 'Lazy::new': fn new<Foo, || -> Foo>(|| -> Foo) -> Lazy<Foo, || -> Foo> 1763 296..299 'Foo': Foo
1811 475..492 'Lazy::...| Foo)': Lazy<Foo, || -> Foo> 1764 310..312 'r1': usize
1812 485..491 '|| Foo': || -> Foo 1765 315..320 'lazy1': Lazy<Foo, || -> Foo>
1813 488..491 'Foo': Foo 1766 315..326 'lazy1.foo()': usize
1814 502..504 'r1': usize 1767 368..383 'make_foo_fn_ptr': fn() -> Foo
1815 507..512 'lazy1': Lazy<Foo, || -> Foo> 1768 399..410 'make_foo_fn': fn make_foo_fn() -> Foo
1816 507..518 'lazy1.foo()': usize 1769 420..425 'lazy2': Lazy<Foo, fn() -> Foo>
1817 560..575 'make_foo_fn_ptr': fn() -> Foo 1770 442..451 'Lazy::new': fn new<Foo, fn() -> Foo>(fn() -> Foo) -> Lazy<Foo, fn() -> Foo>
1818 591..602 'make_foo_fn': fn make_foo_fn() -> Foo 1771 442..468 'Lazy::...n_ptr)': Lazy<Foo, fn() -> Foo>
1819 612..617 'lazy2': Lazy<Foo, fn() -> Foo> 1772 452..467 'make_foo_fn_ptr': fn() -> Foo
1820 634..643 'Lazy::new': fn new<Foo, fn() -> Foo>(fn() -> Foo) -> Lazy<Foo, fn() -> Foo> 1773 478..480 'r2': usize
1821 634..660 'Lazy::...n_ptr)': Lazy<Foo, fn() -> Foo> 1774 483..488 'lazy2': Lazy<Foo, fn() -> Foo>
1822 644..659 'make_foo_fn_ptr': fn() -> Foo 1775 483..494 'lazy2.foo()': usize
1823 670..672 'r2': usize 1776 357..359 '{}': ()
1824 675..680 'lazy2': Lazy<Foo, fn() -> Foo>
1825 675..686 'lazy2.foo()': usize
1826 549..551 '{}': ()
1827 "#]], 1777 "#]],
1828 ); 1778 );
1829} 1779}
@@ -2731,9 +2681,7 @@ fn test(x: &dyn Foo) {
2731fn builtin_copy() { 2681fn builtin_copy() {
2732 check_infer_with_mismatches( 2682 check_infer_with_mismatches(
2733 r#" 2683 r#"
2734#[lang = "copy"] 2684//- minicore: copy
2735trait Copy {}
2736
2737struct IsCopy; 2685struct IsCopy;
2738impl Copy for IsCopy {} 2686impl Copy for IsCopy {}
2739struct NotCopy; 2687struct NotCopy;
@@ -2748,20 +2696,20 @@ fn test() {
2748 (IsCopy, NotCopy).test(); 2696 (IsCopy, NotCopy).test();
2749}"#, 2697}"#,
2750 expect![[r#" 2698 expect![[r#"
2751 110..114 'self': &Self 2699 78..82 'self': &Self
2752 166..267 '{ ...t(); }': () 2700 134..235 '{ ...t(); }': ()
2753 172..178 'IsCopy': IsCopy 2701 140..146 'IsCopy': IsCopy
2754 172..185 'IsCopy.test()': bool 2702 140..153 'IsCopy.test()': bool
2755 191..198 'NotCopy': NotCopy 2703 159..166 'NotCopy': NotCopy
2756 191..205 'NotCopy.test()': {unknown} 2704 159..173 'NotCopy.test()': {unknown}
2757 211..227 '(IsCop...sCopy)': (IsCopy, IsCopy) 2705 179..195 '(IsCop...sCopy)': (IsCopy, IsCopy)
2758 211..234 '(IsCop...test()': bool 2706 179..202 '(IsCop...test()': bool
2759 212..218 'IsCopy': IsCopy 2707 180..186 'IsCopy': IsCopy
2760 220..226 'IsCopy': IsCopy 2708 188..194 'IsCopy': IsCopy
2761 240..257 '(IsCop...tCopy)': (IsCopy, NotCopy) 2709 208..225 '(IsCop...tCopy)': (IsCopy, NotCopy)
2762 240..264 '(IsCop...test()': {unknown} 2710 208..232 '(IsCop...test()': {unknown}
2763 241..247 'IsCopy': IsCopy 2711 209..215 'IsCopy': IsCopy
2764 249..256 'NotCopy': NotCopy 2712 217..224 'NotCopy': NotCopy
2765 "#]], 2713 "#]],
2766 ); 2714 );
2767} 2715}
@@ -2770,9 +2718,7 @@ fn test() {
2770fn builtin_fn_def_copy() { 2718fn builtin_fn_def_copy() {
2771 check_infer_with_mismatches( 2719 check_infer_with_mismatches(
2772 r#" 2720 r#"
2773#[lang = "copy"] 2721//- minicore: copy
2774trait Copy {}
2775
2776fn foo() {} 2722fn foo() {}
2777fn bar<T: Copy>(T) -> T {} 2723fn bar<T: Copy>(T) -> T {}
2778struct Struct(usize); 2724struct Struct(usize);
@@ -2788,20 +2734,20 @@ fn test() {
2788 Enum::Variant.test(); 2734 Enum::Variant.test();
2789}"#, 2735}"#,
2790 expect![[r#" 2736 expect![[r#"
2791 41..43 '{}': () 2737 9..11 '{}': ()
2792 60..61 'T': {unknown} 2738 28..29 'T': {unknown}
2793 68..70 '{}': () 2739 36..38 '{}': ()
2794 68..70: expected T, got () 2740 36..38: expected T, got ()
2795 145..149 'self': &Self 2741 113..117 'self': &Self
2796 201..281 '{ ...t(); }': () 2742 169..249 '{ ...t(); }': ()
2797 207..210 'foo': fn foo() 2743 175..178 'foo': fn foo()
2798 207..217 'foo.test()': bool 2744 175..185 'foo.test()': bool
2799 223..226 'bar': fn bar<{unknown}>({unknown}) -> {unknown} 2745 191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown}
2800 223..233 'bar.test()': bool 2746 191..201 'bar.test()': bool
2801 239..245 'Struct': Struct(usize) -> Struct 2747 207..213 'Struct': Struct(usize) -> Struct
2802 239..252 'Struct.test()': bool 2748 207..220 'Struct.test()': bool
2803 258..271 'Enum::Variant': Variant(usize) -> Enum 2749 226..239 'Enum::Variant': Variant(usize) -> Enum
2804 258..278 'Enum::...test()': bool 2750 226..246 'Enum::...test()': bool
2805 "#]], 2751 "#]],
2806 ); 2752 );
2807} 2753}
@@ -2810,9 +2756,7 @@ fn test() {
2810fn builtin_fn_ptr_copy() { 2756fn builtin_fn_ptr_copy() {
2811 check_infer_with_mismatches( 2757 check_infer_with_mismatches(
2812 r#" 2758 r#"
2813#[lang = "copy"] 2759//- minicore: copy
2814trait Copy {}
2815
2816trait Test { fn test(&self) -> bool; } 2760trait Test { fn test(&self) -> bool; }
2817impl<T: Copy> Test for T {} 2761impl<T: Copy> Test for T {}
2818 2762
@@ -2822,17 +2766,17 @@ fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
2822 f3.test(); 2766 f3.test();
2823}"#, 2767}"#,
2824 expect![[r#" 2768 expect![[r#"
2825 54..58 'self': &Self 2769 22..26 'self': &Self
2826 108..110 'f1': fn() 2770 76..78 'f1': fn()
2827 118..120 'f2': fn(usize) -> u8 2771 86..88 'f2': fn(usize) -> u8
2828 139..141 'f3': fn(u8, u8) -> &u8 2772 107..109 'f3': fn(u8, u8) -> &u8
2829 162..210 '{ ...t(); }': () 2773 130..178 '{ ...t(); }': ()
2830 168..170 'f1': fn() 2774 136..138 'f1': fn()
2831 168..177 'f1.test()': bool 2775 136..145 'f1.test()': bool
2832 183..185 'f2': fn(usize) -> u8 2776 151..153 'f2': fn(usize) -> u8
2833 183..192 'f2.test()': bool 2777 151..160 'f2.test()': bool
2834 198..200 'f3': fn(u8, u8) -> &u8 2778 166..168 'f3': fn(u8, u8) -> &u8
2835 198..207 'f3.test()': bool 2779 166..175 'f3.test()': bool
2836 "#]], 2780 "#]],
2837 ); 2781 );
2838} 2782}
@@ -2841,9 +2785,7 @@ fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
2841fn builtin_sized() { 2785fn builtin_sized() {
2842 check_infer_with_mismatches( 2786 check_infer_with_mismatches(
2843 r#" 2787 r#"
2844#[lang = "sized"] 2788//- minicore: sized
2845trait Sized {}
2846
2847trait Test { fn test(&self) -> bool; } 2789trait Test { fn test(&self) -> bool; }
2848impl<T: Sized> Test for T {} 2790impl<T: Sized> Test for T {}
2849 2791
@@ -2854,22 +2796,22 @@ fn test() {
2854 (1u8, *"foo").test(); // not Sized 2796 (1u8, *"foo").test(); // not Sized
2855}"#, 2797}"#,
2856 expect![[r#" 2798 expect![[r#"
2857 56..60 'self': &Self 2799 22..26 'self': &Self
2858 113..228 '{ ...ized }': () 2800 79..194 '{ ...ized }': ()
2859 119..122 '1u8': u8 2801 85..88 '1u8': u8
2860 119..129 '1u8.test()': bool 2802 85..95 '1u8.test()': bool
2861 135..150 '(*"foo").test()': {unknown} 2803 101..116 '(*"foo").test()': {unknown}
2862 136..142 '*"foo"': str 2804 102..108 '*"foo"': str
2863 137..142 '"foo"': &str 2805 103..108 '"foo"': &str
2864 169..179 '(1u8, 1u8)': (u8, u8) 2806 135..145 '(1u8, 1u8)': (u8, u8)
2865 169..186 '(1u8, ...test()': bool 2807 135..152 '(1u8, ...test()': bool
2866 170..173 '1u8': u8 2808 136..139 '1u8': u8
2867 175..178 '1u8': u8 2809 141..144 '1u8': u8
2868 192..205 '(1u8, *"foo")': (u8, str) 2810 158..171 '(1u8, *"foo")': (u8, str)
2869 192..212 '(1u8, ...test()': {unknown} 2811 158..178 '(1u8, ...test()': {unknown}
2870 193..196 '1u8': u8 2812 159..162 '1u8': u8
2871 198..204 '*"foo"': str 2813 164..170 '*"foo"': str
2872 199..204 '"foo"': &str 2814 165..170 '"foo"': &str
2873 "#]], 2815 "#]],
2874 ); 2816 );
2875} 2817}
@@ -2980,28 +2922,13 @@ fn infer_box_fn_arg() {
2980 // The type mismatch is because we don't define Unsize and CoerceUnsized 2922 // The type mismatch is because we don't define Unsize and CoerceUnsized
2981 check_infer_with_mismatches( 2923 check_infer_with_mismatches(
2982 r#" 2924 r#"
2983//- /lib.rs deps:std 2925//- minicore: fn, deref, option
2984
2985#[lang = "fn_once"]
2986pub trait FnOnce<Args> {
2987 type Output;
2988
2989 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
2990}
2991
2992#[lang = "deref"]
2993pub trait Deref {
2994 type Target: ?Sized;
2995
2996 fn deref(&self) -> &Self::Target;
2997}
2998
2999#[lang = "owned_box"] 2926#[lang = "owned_box"]
3000pub struct Box<T: ?Sized> { 2927pub struct Box<T: ?Sized> {
3001 inner: *mut T, 2928 inner: *mut T,
3002} 2929}
3003 2930
3004impl<T: ?Sized> Deref for Box<T> { 2931impl<T: ?Sized> core::ops::Deref for Box<T> {
3005 type Target = T; 2932 type Target = T;
3006 2933
3007 fn deref(&self) -> &T { 2934 fn deref(&self) -> &T {
@@ -3009,38 +2936,30 @@ impl<T: ?Sized> Deref for Box<T> {
3009 } 2936 }
3010} 2937}
3011 2938
3012enum Option<T> {
3013 None,
3014 Some(T)
3015}
3016
3017fn foo() { 2939fn foo() {
3018 let s = Option::None; 2940 let s = None;
3019 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {}); 2941 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
3020 f(&s); 2942 f(&s);
3021}"#, 2943}"#,
3022 expect![[r#" 2944 expect![[r#"
3023 100..104 'self': Self 2945 154..158 'self': &Box<T>
3024 106..110 'args': Args 2946 166..193 '{ ... }': &T
3025 214..218 'self': &Self 2947 176..187 '&self.inner': &*mut T
3026 384..388 'self': &Box<T> 2948 177..181 'self': &Box<T>
3027 396..423 '{ ... }': &T 2949 177..187 'self.inner': *mut T
3028 406..417 '&self.inner': &*mut T 2950 206..296 '{ ...&s); }': ()
3029 407..411 'self': &Box<T> 2951 216..217 's': Option<i32>
3030 407..417 'self.inner': *mut T 2952 220..224 'None': Option<i32>
3031 478..576 '{ ...&s); }': () 2953 234..235 'f': Box<dyn FnOnce(&Option<i32>)>
3032 488..489 's': Option<i32> 2954 269..282 'box (|ps| {})': Box<|{unknown}| -> ()>
3033 492..504 'Option::None': Option<i32> 2955 274..281 '|ps| {}': |{unknown}| -> ()
3034 514..515 'f': Box<dyn FnOnce(&Option<i32>)> 2956 275..277 'ps': {unknown}
3035 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> 2957 279..281 '{}': ()
3036 554..561 '|ps| {}': |{unknown}| -> () 2958 288..289 'f': Box<dyn FnOnce(&Option<i32>)>
3037 555..557 'ps': {unknown} 2959 288..293 'f(&s)': ()
3038 559..561 '{}': () 2960 290..292 '&s': &Option<i32>
3039 568..569 'f': Box<dyn FnOnce(&Option<i32>)> 2961 291..292 's': Option<i32>
3040 568..573 'f(&s)': () 2962 269..282: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
3041 570..572 '&s': &Option<i32>
3042 571..572 's': Option<i32>
3043 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
3044 "#]], 2963 "#]],
3045 ); 2964 );
3046} 2965}
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 0013820b4..07686017d 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -236,15 +236,10 @@ impl T for &Foo {}
236 fn goto_implementation_to_builtin_derive() { 236 fn goto_implementation_to_builtin_derive() {
237 check( 237 check(
238 r#" 238 r#"
239//- minicore: copy, derive
239 #[derive(Copy)] 240 #[derive(Copy)]
240//^^^^^^^^^^^^^^^ 241//^^^^^^^^^^^^^^^
241struct Foo$0; 242struct Foo$0;
242
243mod marker {
244 trait Copy {}
245}
246#[rustc_builtin_macro]
247macro Copy {}
248"#, 243"#,
249 ); 244 );
250 } 245 }
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 4705fae08..2e1359eef 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -2258,7 +2258,7 @@ pub fn fo$0o() {}
2258 case 13. collapsed link: foo 2258 case 13. collapsed link: foo
2259 case 14. shortcut link: foo 2259 case 14. shortcut link: foo
2260 case 15. inline without URL: foo 2260 case 15. inline without URL: foo
2261 case 16. just escaped text: \[foo] 2261 case 16. just escaped text: \[foo\]
2262 case 17. inline link: Foo 2262 case 17. inline link: Foo
2263 2263
2264 [^example]: https://www.example.com/ 2264 [^example]: https://www.example.com/
@@ -3014,8 +3014,8 @@ fn foo() {
3014 file_id: FileId( 3014 file_id: FileId(
3015 1, 3015 1,
3016 ), 3016 ),
3017 full_range: 250..432, 3017 full_range: 251..433,
3018 focus_range: 289..295, 3018 focus_range: 290..296,
3019 name: "Future", 3019 name: "Future",
3020 kind: Trait, 3020 kind: Trait,
3021 description: "pub trait Future", 3021 description: "pub trait Future",
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 335d57a0d..95f9edce4 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -661,9 +661,7 @@ fn main() {
661 fn function_call_parameter_hint() { 661 fn function_call_parameter_hint() {
662 check_params( 662 check_params(
663 r#" 663 r#"
664enum Option<T> { None, Some(T) } 664//- minicore: option
665use Option::*;
666
667struct FileId {} 665struct FileId {}
668struct SmolStr {} 666struct SmolStr {}
669 667
@@ -872,7 +870,6 @@ fn main() {
872 check_types( 870 check_types(
873 r#" 871 r#"
874//- minicore: fn, sized 872//- minicore: fn, sized
875
876fn foo() -> impl Fn() { loop {} } 873fn foo() -> impl Fn() { loop {} }
877fn foo1() -> impl Fn(f64) { loop {} } 874fn foo1() -> impl Fn(f64) { loop {} }
878fn foo2() -> impl Fn(f64, f64) { loop {} } 875fn foo2() -> impl Fn(f64, f64) { loop {} }
@@ -908,9 +905,7 @@ fn main() {
908 fn unit_structs_have_no_type_hints() { 905 fn unit_structs_have_no_type_hints() {
909 check_types( 906 check_types(
910 r#" 907 r#"
911enum Result<T, E> { Ok(T), Err(E) } 908//- minicore: result
912use Result::*;
913
914struct SyntheticSyntax; 909struct SyntheticSyntax;
915 910
916fn main() { 911fn main() {
@@ -962,9 +957,7 @@ fn main() {
962 fn if_expr() { 957 fn if_expr() {
963 check_types( 958 check_types(
964 r#" 959 r#"
965enum Option<T> { None, Some(T) } 960//- minicore: option
966use Option::*;
967
968struct Test { a: Option<u32>, b: u8 } 961struct Test { a: Option<u32>, b: u8 }
969 962
970fn main() { 963fn main() {
@@ -994,9 +987,7 @@ fn main() {
994 fn while_expr() { 987 fn while_expr() {
995 check_types( 988 check_types(
996 r#" 989 r#"
997enum Option<T> { None, Some(T) } 990//- minicore: option
998use Option::*;
999
1000struct Test { a: Option<u32>, b: u8 } 991struct Test { a: Option<u32>, b: u8 }
1001 992
1002fn main() { 993fn main() {
@@ -1012,9 +1003,7 @@ fn main() {
1012 fn match_arm_list() { 1003 fn match_arm_list() {
1013 check_types( 1004 check_types(
1014 r#" 1005 r#"
1015enum Option<T> { None, Some(T) } 1006//- minicore: option
1016use Option::*;
1017
1018struct Test { a: Option<u32>, b: u8 } 1007struct Test { a: Option<u32>, b: u8 }
1019 1008
1020fn main() { 1009fn main() {
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index d4748ef3a..accc345fc 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -103,8 +103,9 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
103 let scope = match scope.clone() { 103 let scope = match scope.clone() {
104 ImportScope::File(it) => ImportScope::File(builder.make_mut(it)), 104 ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
105 ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)), 105 ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
106 ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
106 }; 107 };
107 insert_use(&scope, mod_path_to_ast(&import.import_path), ctx.config.insert_use); 108 insert_use(&scope, mod_path_to_ast(&import.import_path), &ctx.config.insert_use);
108 }, 109 },
109 ); 110 );
110 } 111 }
diff --git a/crates/ide_assists/src/handlers/convert_into_to_from.rs b/crates/ide_assists/src/handlers/convert_into_to_from.rs
index 79a0c4879..2d8b936cd 100644
--- a/crates/ide_assists/src/handlers/convert_into_to_from.rs
+++ b/crates/ide_assists/src/handlers/convert_into_to_from.rs
@@ -13,10 +13,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
13// Converts an Into impl to an equivalent From impl. 13// Converts an Into impl to an equivalent From impl.
14// 14//
15// ``` 15// ```
16// # //- /lib.rs crate:core 16// # //- minicore: from
17// # pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } }
18// # //- /lib.rs crate:main deps:core
19// # use core::convert::Into;
20// impl $0Into<Thing> for usize { 17// impl $0Into<Thing> for usize {
21// fn into(self) -> Thing { 18// fn into(self) -> Thing {
22// Thing { 19// Thing {
@@ -28,7 +25,6 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
28// ``` 25// ```
29// -> 26// ->
30// ``` 27// ```
31// # use core::convert::Into;
32// impl From<usize> for Thing { 28// impl From<usize> for Thing {
33// fn from(val: usize) -> Self { 29// fn from(val: usize) -> Self {
34// Thing { 30// Thing {
diff --git a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
index 7fd73d4c7..70754adf9 100644
--- a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
+++ b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs
@@ -11,14 +11,10 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
11// Converts an Iterator::for_each function into a for loop. 11// Converts an Iterator::for_each function into a for loop.
12// 12//
13// ``` 13// ```
14// # //- /lib.rs crate:core 14// # //- minicore: iterators
15// # pub mod iter { pub mod traits { pub mod iterator { pub trait Iterator {} } } } 15// # use core::iter;
16// # pub struct SomeIter;
17// # impl self::iter::traits::iterator::Iterator for SomeIter {}
18// # //- /lib.rs crate:main deps:core
19// # use core::SomeIter;
20// fn main() { 16// fn main() {
21// let iter = SomeIter; 17// let iter = iter::repeat((9, 2));
22// iter.for_each$0(|(x, y)| { 18// iter.for_each$0(|(x, y)| {
23// println!("x: {}, y: {}", x, y); 19// println!("x: {}, y: {}", x, y);
24// }); 20// });
@@ -26,9 +22,9 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
26// ``` 22// ```
27// -> 23// ->
28// ``` 24// ```
29// # use core::SomeIter; 25// # use core::iter;
30// fn main() { 26// fn main() {
31// let iter = SomeIter; 27// let iter = iter::repeat((9, 2));
32// for (x, y) in iter { 28// for (x, y) in iter {
33// println!("x: {}, y: {}", x, y); 29// println!("x: {}, y: {}", x, y);
34// } 30// }
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index 43e83d683..ac7f0959b 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -831,7 +831,6 @@ fn path_element_of_reference(
831 })?; 831 })?;
832 stdx::always!( 832 stdx::always!(
833 matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroCall(_)), 833 matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroCall(_)),
834
835 "unexpected expression type for variable usage: {:?}", 834 "unexpected expression type for variable usage: {:?}",
836 path 835 path
837 ); 836 );
@@ -2991,11 +2990,7 @@ mod bar {
2991 check_assist( 2990 check_assist(
2992 extract_function, 2991 extract_function,
2993 r#" 2992 r#"
2994enum Option<T> { 2993//- minicore: option
2995 #[lang = "None"] None,
2996 #[lang = "Some"] Some(T),
2997}
2998use Option::*;
2999fn foo() { 2994fn foo() {
3000 loop { 2995 loop {
3001 let n = 1; 2996 let n = 1;
@@ -3007,11 +3002,6 @@ fn foo() {
3007} 3002}
3008"#, 3003"#,
3009 r#" 3004 r#"
3010enum Option<T> {
3011 #[lang = "None"] None,
3012 #[lang = "Some"] Some(T),
3013}
3014use Option::*;
3015fn foo() { 3005fn foo() {
3016 loop { 3006 loop {
3017 let n = 1; 3007 let n = 1;
diff --git a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
index 6c6ff16c2..430710448 100644
--- a/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide_assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -236,7 +236,7 @@ fn apply_references(
236 import: Option<(ImportScope, hir::ModPath)>, 236 import: Option<(ImportScope, hir::ModPath)>,
237) { 237) {
238 if let Some((scope, path)) = import { 238 if let Some((scope, path)) = import {
239 insert_use(&scope, mod_path_to_ast(&path), insert_use_cfg); 239 insert_use(&scope, mod_path_to_ast(&path), &insert_use_cfg);
240 } 240 }
241 // deep clone to prevent cycle 241 // deep clone to prevent cycle
242 let path = make::path_from_segments(iter::once(segment.clone_subtree()), false); 242 let path = make::path_from_segments(iter::once(segment.clone_subtree()), false);
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs
index cd0f6dba9..318faa0fc 100644
--- a/crates/ide_assists/src/handlers/fill_match_arms.rs
+++ b/crates/ide_assists/src/handlers/fill_match_arms.rs
@@ -481,26 +481,21 @@ fn main() {
481 check_assist( 481 check_assist(
482 fill_match_arms, 482 fill_match_arms,
483 r#" 483 r#"
484enum Option<T> { Some(T), None } 484//- minicore: option
485use Option::*;
486
487fn main() { 485fn main() {
488 match None$0 { 486 match None$0 {
489 None => {} 487 None => {}
490 } 488 }
491} 489}
492 "#, 490"#,
493 r#" 491 r#"
494enum Option<T> { Some(T), None }
495use Option::*;
496
497fn main() { 492fn main() {
498 match None { 493 match None {
499 None => {} 494 None => {}
500 Some(${0:_}) => todo!(), 495 Some(${0:_}) => todo!(),
501 } 496 }
502} 497}
503 "#, 498"#,
504 ); 499 );
505 } 500 }
506 501
diff --git a/crates/ide_assists/src/handlers/replace_if_let_with_match.rs b/crates/ide_assists/src/handlers/replace_if_let_with_match.rs
index 9404aa26d..f37aa0d53 100644
--- a/crates/ide_assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ide_assists/src/handlers/replace_if_let_with_match.rs
@@ -262,9 +262,7 @@ impl VariantData {
262 check_assist( 262 check_assist(
263 replace_if_let_with_match, 263 replace_if_let_with_match,
264 r#" 264 r#"
265enum Option<T> { Some(T), None } 265//- minicore: option
266use Option::*;
267
268fn foo(x: Option<i32>) { 266fn foo(x: Option<i32>) {
269 $0if let Some(x) = x { 267 $0if let Some(x) = x {
270 println!("{}", x) 268 println!("{}", x)
@@ -272,18 +270,15 @@ fn foo(x: Option<i32>) {
272 println!("none") 270 println!("none")
273 } 271 }
274} 272}
275 "#, 273"#,
276 r#" 274 r#"
277enum Option<T> { Some(T), None }
278use Option::*;
279
280fn foo(x: Option<i32>) { 275fn foo(x: Option<i32>) {
281 match x { 276 match x {
282 Some(x) => println!("{}", x), 277 Some(x) => println!("{}", x),
283 None => println!("none"), 278 None => println!("none"),
284 } 279 }
285} 280}
286 "#, 281"#,
287 ); 282 );
288 } 283 }
289 284
@@ -292,9 +287,7 @@ fn foo(x: Option<i32>) {
292 check_assist( 287 check_assist(
293 replace_if_let_with_match, 288 replace_if_let_with_match,
294 r#" 289 r#"
295enum Option<T> { Some(T), None } 290//- minicore: option
296use Option::*;
297
298fn foo(x: Option<i32>) { 291fn foo(x: Option<i32>) {
299 $0if let None = x { 292 $0if let None = x {
300 println!("none") 293 println!("none")
@@ -302,18 +295,15 @@ fn foo(x: Option<i32>) {
302 println!("some") 295 println!("some")
303 } 296 }
304} 297}
305 "#, 298"#,
306 r#" 299 r#"
307enum Option<T> { Some(T), None }
308use Option::*;
309
310fn foo(x: Option<i32>) { 300fn foo(x: Option<i32>) {
311 match x { 301 match x {
312 None => println!("none"), 302 None => println!("none"),
313 Some(_) => println!("some"), 303 Some(_) => println!("some"),
314 } 304 }
315} 305}
316 "#, 306"#,
317 ); 307 );
318 } 308 }
319 309
@@ -322,9 +312,7 @@ fn foo(x: Option<i32>) {
322 check_assist( 312 check_assist(
323 replace_if_let_with_match, 313 replace_if_let_with_match,
324 r#" 314 r#"
325enum Result<T, E> { Ok(T), Err(E) } 315//- minicore: result
326use Result::*;
327
328fn foo(x: Result<i32, ()>) { 316fn foo(x: Result<i32, ()>) {
329 $0if let Ok(x) = x { 317 $0if let Ok(x) = x {
330 println!("{}", x) 318 println!("{}", x)
@@ -332,18 +320,15 @@ fn foo(x: Result<i32, ()>) {
332 println!("none") 320 println!("none")
333 } 321 }
334} 322}
335 "#, 323"#,
336 r#" 324 r#"
337enum Result<T, E> { Ok(T), Err(E) }
338use Result::*;
339
340fn foo(x: Result<i32, ()>) { 325fn foo(x: Result<i32, ()>) {
341 match x { 326 match x {
342 Ok(x) => println!("{}", x), 327 Ok(x) => println!("{}", x),
343 Err(_) => println!("none"), 328 Err(_) => println!("none"),
344 } 329 }
345} 330}
346 "#, 331"#,
347 ); 332 );
348 } 333 }
349 334
@@ -352,9 +337,7 @@ fn foo(x: Result<i32, ()>) {
352 check_assist( 337 check_assist(
353 replace_if_let_with_match, 338 replace_if_let_with_match,
354 r#" 339 r#"
355enum Result<T, E> { Ok(T), Err(E) } 340//- minicore: result
356use Result::*;
357
358fn foo(x: Result<i32, ()>) { 341fn foo(x: Result<i32, ()>) {
359 $0if let Err(x) = x { 342 $0if let Err(x) = x {
360 println!("{}", x) 343 println!("{}", x)
@@ -362,18 +345,15 @@ fn foo(x: Result<i32, ()>) {
362 println!("ok") 345 println!("ok")
363 } 346 }
364} 347}
365 "#, 348"#,
366 r#" 349 r#"
367enum Result<T, E> { Ok(T), Err(E) }
368use Result::*;
369
370fn foo(x: Result<i32, ()>) { 350fn foo(x: Result<i32, ()>) {
371 match x { 351 match x {
372 Err(x) => println!("{}", x), 352 Err(x) => println!("{}", x),
373 Ok(_) => println!("ok"), 353 Ok(_) => println!("ok"),
374 } 354 }
375} 355}
376 "#, 356"#,
377 ); 357 );
378 } 358 }
379 359
@@ -488,20 +468,15 @@ impl VariantData {
488 check_assist( 468 check_assist(
489 replace_match_with_if_let, 469 replace_match_with_if_let,
490 r#" 470 r#"
491enum Option<T> { Some(T), None } 471//- minicore: option
492use Option::*;
493
494fn foo(x: Option<i32>) { 472fn foo(x: Option<i32>) {
495 $0match x { 473 $0match x {
496 Some(x) => println!("{}", x), 474 Some(x) => println!("{}", x),
497 None => println!("none"), 475 None => println!("none"),
498 } 476 }
499} 477}
500 "#, 478"#,
501 r#" 479 r#"
502enum Option<T> { Some(T), None }
503use Option::*;
504
505fn foo(x: Option<i32>) { 480fn foo(x: Option<i32>) {
506 if let Some(x) = x { 481 if let Some(x) = x {
507 println!("{}", x) 482 println!("{}", x)
@@ -509,7 +484,7 @@ fn foo(x: Option<i32>) {
509 println!("none") 484 println!("none")
510 } 485 }
511} 486}
512 "#, 487"#,
513 ); 488 );
514 } 489 }
515 490
@@ -518,20 +493,15 @@ fn foo(x: Option<i32>) {
518 check_assist( 493 check_assist(
519 replace_match_with_if_let, 494 replace_match_with_if_let,
520 r#" 495 r#"
521enum Result<T, E> { Ok(T), Err(E) } 496//- minicore: result
522use Result::*;
523
524fn foo(x: Result<i32, ()>) { 497fn foo(x: Result<i32, ()>) {
525 $0match x { 498 $0match x {
526 Ok(x) => println!("{}", x), 499 Ok(x) => println!("{}", x),
527 Err(_) => println!("none"), 500 Err(_) => println!("none"),
528 } 501 }
529} 502}
530 "#, 503"#,
531 r#" 504 r#"
532enum Result<T, E> { Ok(T), Err(E) }
533use Result::*;
534
535fn foo(x: Result<i32, ()>) { 505fn foo(x: Result<i32, ()>) {
536 if let Ok(x) = x { 506 if let Ok(x) = x {
537 println!("{}", x) 507 println!("{}", x)
@@ -539,7 +509,7 @@ fn foo(x: Result<i32, ()>) {
539 println!("none") 509 println!("none")
540 } 510 }
541} 511}
542 "#, 512"#,
543 ); 513 );
544 } 514 }
545 515
diff --git a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
index 39f5eb4ff..26778ee74 100644
--- a/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ide_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -32,7 +32,6 @@ pub(crate) fn replace_qualified_name_with_use(
32 32
33 let target = path.syntax().text_range(); 33 let target = path.syntax().text_range();
34 let scope = ImportScope::find_insert_use_container_with_macros(path.syntax(), &ctx.sema)?; 34 let scope = ImportScope::find_insert_use_container_with_macros(path.syntax(), &ctx.sema)?;
35 let syntax = scope.as_syntax_node();
36 acc.add( 35 acc.add(
37 AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite), 36 AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite),
38 "Replace qualified path with use", 37 "Replace qualified path with use",
@@ -40,11 +39,13 @@ pub(crate) fn replace_qualified_name_with_use(
40 |builder| { 39 |builder| {
41 // Now that we've brought the name into scope, re-qualify all paths that could be 40 // Now that we've brought the name into scope, re-qualify all paths that could be
42 // affected (that is, all paths inside the node we added the `use` to). 41 // affected (that is, all paths inside the node we added the `use` to).
43 let syntax = builder.make_syntax_mut(syntax.clone()); 42 let scope = match scope {
44 if let Some(ref import_scope) = ImportScope::from(syntax.clone()) { 43 ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
45 shorten_paths(&syntax, &path.clone_for_update()); 44 ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
46 insert_use(import_scope, path, ctx.config.insert_use); 45 ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
47 } 46 };
47 shorten_paths(scope.as_syntax_node(), &path.clone_for_update());
48 insert_use(&scope, path, &ctx.config.insert_use);
48 }, 49 },
49 ) 50 )
50} 51}
diff --git a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
index a3bfa221c..f39c48d8f 100644
--- a/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ide_assists/src/handlers/replace_unwrap_with_match.rs
@@ -20,17 +20,16 @@ use ide_db::ty_filter::TryEnum;
20// Replaces `unwrap` with a `match` expression. Works for Result and Option. 20// Replaces `unwrap` with a `match` expression. Works for Result and Option.
21// 21//
22// ``` 22// ```
23// enum Result<T, E> { Ok(T), Err(E) } 23// # //- minicore: result
24// fn main() { 24// fn main() {
25// let x: Result<i32, i32> = Result::Ok(92); 25// let x: Result<i32, i32> = Ok(92);
26// let y = x.$0unwrap(); 26// let y = x.$0unwrap();
27// } 27// }
28// ``` 28// ```
29// -> 29// ->
30// ``` 30// ```
31// enum Result<T, E> { Ok(T), Err(E) }
32// fn main() { 31// fn main() {
33// let x: Result<i32, i32> = Result::Ok(92); 32// let x: Result<i32, i32> = Ok(92);
34// let y = match x { 33// let y = match x {
35// Ok(it) => it, 34// Ok(it) => it,
36// $0_ => unreachable!(), 35// $0_ => unreachable!(),
@@ -97,25 +96,24 @@ mod tests {
97 fn test_replace_result_unwrap_with_match() { 96 fn test_replace_result_unwrap_with_match() {
98 check_assist( 97 check_assist(
99 replace_unwrap_with_match, 98 replace_unwrap_with_match,
100 r" 99 r#"
101enum Result<T, E> { Ok(T), Err(E) } 100//- minicore: result
102fn i<T>(a: T) -> T { a } 101fn i<T>(a: T) -> T { a }
103fn main() { 102fn main() {
104 let x: Result<i32, i32> = Result::Ok(92); 103 let x: Result<i32, i32> = Ok(92);
105 let y = i(x).$0unwrap(); 104 let y = i(x).$0unwrap();
106} 105}
107 ", 106"#,
108 r" 107 r#"
109enum Result<T, E> { Ok(T), Err(E) }
110fn i<T>(a: T) -> T { a } 108fn i<T>(a: T) -> T { a }
111fn main() { 109fn main() {
112 let x: Result<i32, i32> = Result::Ok(92); 110 let x: Result<i32, i32> = Ok(92);
113 let y = match i(x) { 111 let y = match i(x) {
114 Ok(it) => it, 112 Ok(it) => it,
115 $0_ => unreachable!(), 113 $0_ => unreachable!(),
116 }; 114 };
117} 115}
118 ", 116"#,
119 ) 117 )
120 } 118 }
121 119
@@ -123,25 +121,24 @@ fn main() {
123 fn test_replace_option_unwrap_with_match() { 121 fn test_replace_option_unwrap_with_match() {
124 check_assist( 122 check_assist(
125 replace_unwrap_with_match, 123 replace_unwrap_with_match,
126 r" 124 r#"
127enum Option<T> { Some(T), None } 125//- minicore: option
128fn i<T>(a: T) -> T { a } 126fn i<T>(a: T) -> T { a }
129fn main() { 127fn main() {
130 let x = Option::Some(92); 128 let x = Some(92);
131 let y = i(x).$0unwrap(); 129 let y = i(x).$0unwrap();
132} 130}
133 ", 131"#,
134 r" 132 r#"
135enum Option<T> { Some(T), None }
136fn i<T>(a: T) -> T { a } 133fn i<T>(a: T) -> T { a }
137fn main() { 134fn main() {
138 let x = Option::Some(92); 135 let x = Some(92);
139 let y = match i(x) { 136 let y = match i(x) {
140 Some(it) => it, 137 Some(it) => it,
141 $0_ => unreachable!(), 138 $0_ => unreachable!(),
142 }; 139 };
143} 140}
144 ", 141"#,
145 ); 142 );
146 } 143 }
147 144
@@ -149,25 +146,24 @@ fn main() {
149 fn test_replace_result_unwrap_with_match_chaining() { 146 fn test_replace_result_unwrap_with_match_chaining() {
150 check_assist( 147 check_assist(
151 replace_unwrap_with_match, 148 replace_unwrap_with_match,
152 r" 149 r#"
153enum Result<T, E> { Ok(T), Err(E) } 150//- minicore: result
154fn i<T>(a: T) -> T { a } 151fn i<T>(a: T) -> T { a }
155fn main() { 152fn main() {
156 let x: Result<i32, i32> = Result::Ok(92); 153 let x: Result<i32, i32> = Ok(92);
157 let y = i(x).$0unwrap().count_zeroes(); 154 let y = i(x).$0unwrap().count_zeroes();
158} 155}
159 ", 156"#,
160 r" 157 r#"
161enum Result<T, E> { Ok(T), Err(E) }
162fn i<T>(a: T) -> T { a } 158fn i<T>(a: T) -> T { a }
163fn main() { 159fn main() {
164 let x: Result<i32, i32> = Result::Ok(92); 160 let x: Result<i32, i32> = Ok(92);
165 let y = match i(x) { 161 let y = match i(x) {
166 Ok(it) => it, 162 Ok(it) => it,
167 $0_ => unreachable!(), 163 $0_ => unreachable!(),
168 }.count_zeroes(); 164 }.count_zeroes();
169} 165}
170 ", 166"#,
171 ) 167 )
172 } 168 }
173 169
@@ -175,14 +171,14 @@ fn main() {
175 fn replace_unwrap_with_match_target() { 171 fn replace_unwrap_with_match_target() {
176 check_assist_target( 172 check_assist_target(
177 replace_unwrap_with_match, 173 replace_unwrap_with_match,
178 r" 174 r#"
179enum Option<T> { Some(T), None } 175//- minicore: option
180fn i<T>(a: T) -> T { a } 176fn i<T>(a: T) -> T { a }
181fn main() { 177fn main() {
182 let x = Option::Some(92); 178 let x = Some(92);
183 let y = i(x).$0unwrap(); 179 let y = i(x).$0unwrap();
184} 180}
185 ", 181"#,
186 r"i(x).unwrap()", 182 r"i(x).unwrap()",
187 ); 183 );
188 } 184 }
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index 4e96ff1ec..841537c77 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -28,6 +28,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
28 prefix_kind: hir::PrefixKind::Plain, 28 prefix_kind: hir::PrefixKind::Plain,
29 enforce_granularity: true, 29 enforce_granularity: true,
30 group: true, 30 group: true,
31 skip_glob_imports: true,
31 }, 32 },
32}; 33};
33 34
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index de5d9e55a..1509c3c63 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -209,10 +209,7 @@ fn doctest_convert_into_to_from() {
209 check_doc_test( 209 check_doc_test(
210 "convert_into_to_from", 210 "convert_into_to_from",
211 r#####" 211 r#####"
212//- /lib.rs crate:core 212//- minicore: from
213pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } }
214//- /lib.rs crate:main deps:core
215use core::convert::Into;
216impl $0Into<Thing> for usize { 213impl $0Into<Thing> for usize {
217 fn into(self) -> Thing { 214 fn into(self) -> Thing {
218 Thing { 215 Thing {
@@ -223,7 +220,6 @@ impl $0Into<Thing> for usize {
223} 220}
224"#####, 221"#####,
225 r#####" 222 r#####"
226use core::convert::Into;
227impl From<usize> for Thing { 223impl From<usize> for Thing {
228 fn from(val: usize) -> Self { 224 fn from(val: usize) -> Self {
229 Thing { 225 Thing {
@@ -241,23 +237,19 @@ fn doctest_convert_iter_for_each_to_for() {
241 check_doc_test( 237 check_doc_test(
242 "convert_iter_for_each_to_for", 238 "convert_iter_for_each_to_for",
243 r#####" 239 r#####"
244//- /lib.rs crate:core 240//- minicore: iterators
245pub mod iter { pub mod traits { pub mod iterator { pub trait Iterator {} } } } 241use core::iter;
246pub struct SomeIter;
247impl self::iter::traits::iterator::Iterator for SomeIter {}
248//- /lib.rs crate:main deps:core
249use core::SomeIter;
250fn main() { 242fn main() {
251 let iter = SomeIter; 243 let iter = iter::repeat((9, 2));
252 iter.for_each$0(|(x, y)| { 244 iter.for_each$0(|(x, y)| {
253 println!("x: {}, y: {}", x, y); 245 println!("x: {}, y: {}", x, y);
254 }); 246 });
255} 247}
256"#####, 248"#####,
257 r#####" 249 r#####"
258use core::SomeIter; 250use core::iter;
259fn main() { 251fn main() {
260 let iter = SomeIter; 252 let iter = iter::repeat((9, 2));
261 for (x, y) in iter { 253 for (x, y) in iter {
262 println!("x: {}, y: {}", x, y); 254 println!("x: {}, y: {}", x, y);
263 } 255 }
@@ -1519,16 +1511,15 @@ fn doctest_replace_unwrap_with_match() {
1519 check_doc_test( 1511 check_doc_test(
1520 "replace_unwrap_with_match", 1512 "replace_unwrap_with_match",
1521 r#####" 1513 r#####"
1522enum Result<T, E> { Ok(T), Err(E) } 1514//- minicore: result
1523fn main() { 1515fn main() {
1524 let x: Result<i32, i32> = Result::Ok(92); 1516 let x: Result<i32, i32> = Ok(92);
1525 let y = x.$0unwrap(); 1517 let y = x.$0unwrap();
1526} 1518}
1527"#####, 1519"#####,
1528 r#####" 1520 r#####"
1529enum Result<T, E> { Ok(T), Err(E) }
1530fn main() { 1521fn main() {
1531 let x: Result<i32, i32> = Result::Ok(92); 1522 let x: Result<i32, i32> = Ok(92);
1532 let y = match x { 1523 let y = match x {
1533 Ok(it) => it, 1524 Ok(it) => it,
1534 $0_ => unreachable!(), 1525 $0_ => unreachable!(),
diff --git a/crates/ide_completion/src/completions/dot.rs b/crates/ide_completion/src/completions/dot.rs
index 7f75d4298..286d7cb67 100644
--- a/crates/ide_completion/src/completions/dot.rs
+++ b/crates/ide_completion/src/completions/dot.rs
@@ -498,10 +498,7 @@ mod foo {
498 fn issue_8931() { 498 fn issue_8931() {
499 check( 499 check(
500 r#" 500 r#"
501#[lang = "fn_once"] 501//- minicore: fn
502trait FnOnce<Args> {
503 type Output;
504}
505struct S; 502struct S;
506 503
507struct Foo; 504struct Foo;
diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs
index c3c7e4589..4e20ec003 100644
--- a/crates/ide_completion/src/completions/postfix.rs
+++ b/crates/ide_completion/src/completions/postfix.rs
@@ -436,18 +436,15 @@ fn main() {
436 check_edit( 436 check_edit(
437 "ifl", 437 "ifl",
438 r#" 438 r#"
439enum Option<T> { Some(T), None } 439//- minicore: option
440
441fn main() { 440fn main() {
442 let bar = Option::Some(true); 441 let bar = Some(true);
443 bar.$0 442 bar.$0
444} 443}
445"#, 444"#,
446 r#" 445 r#"
447enum Option<T> { Some(T), None }
448
449fn main() { 446fn main() {
450 let bar = Option::Some(true); 447 let bar = Some(true);
451 if let Some($1) = bar { 448 if let Some($1) = bar {
452 $0 449 $0
453} 450}
@@ -461,18 +458,15 @@ fn main() {
461 check_edit( 458 check_edit(
462 "match", 459 "match",
463 r#" 460 r#"
464enum Result<T, E> { Ok(T), Err(E) } 461//- minicore: result
465
466fn main() { 462fn main() {
467 let bar = Result::Ok(true); 463 let bar = Ok(true);
468 bar.$0 464 bar.$0
469} 465}
470"#, 466"#,
471 r#" 467 r#"
472enum Result<T, E> { Ok(T), Err(E) }
473
474fn main() { 468fn main() {
475 let bar = Result::Ok(true); 469 let bar = Ok(true);
476 match bar { 470 match bar {
477 Ok(${1:_}) => {$2}, 471 Ok(${1:_}) => {$2},
478 Err(${3:_}) => {$0}, 472 Err(${3:_}) => {$0},
@@ -515,18 +509,15 @@ fn main() {
515 check_edit( 509 check_edit(
516 "ifl", 510 "ifl",
517 r#" 511 r#"
518enum Option<T> { Some(T), None } 512//- minicore: option
519
520fn main() { 513fn main() {
521 let bar = &Option::Some(true); 514 let bar = &Some(true);
522 bar.$0 515 bar.$0
523} 516}
524"#, 517"#,
525 r#" 518 r#"
526enum Option<T> { Some(T), None }
527
528fn main() { 519fn main() {
529 let bar = &Option::Some(true); 520 let bar = &Some(true);
530 if let Some($1) = bar { 521 if let Some($1) = bar {
531 $0 522 $0
532} 523}
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 98fb36042..e49e434fa 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -942,13 +942,12 @@ fn foo() -> u32 {
942 // FIXME: make this work with `|| $0` 942 // FIXME: make this work with `|| $0`
943 check_expected_type_and_name( 943 check_expected_type_and_name(
944 r#" 944 r#"
945//- minicore: fn
945fn foo() { 946fn foo() {
946 bar(|| a$0); 947 bar(|| a$0);
947} 948}
948 949
949fn bar(f: impl FnOnce() -> u32) {} 950fn bar(f: impl FnOnce() -> u32) {}
950#[lang = "fn_once"]
951trait FnOnce { type Output; }
952"#, 951"#,
953 expect![[r#"ty: u32, name: ?"#]], 952 expect![[r#"ty: u32, name: ?"#]],
954 ); 953 );
diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs
index 99edb9499..ae63d132e 100644
--- a/crates/ide_completion/src/item.rs
+++ b/crates/ide_completion/src/item.rs
@@ -378,7 +378,7 @@ impl ImportEdit {
378 let _p = profile::span("ImportEdit::to_text_edit"); 378 let _p = profile::span("ImportEdit::to_text_edit");
379 379
380 let new_ast = self.scope.clone_for_update(); 380 let new_ast = self.scope.clone_for_update();
381 insert_use::insert_use(&new_ast, mod_path_to_ast(&self.import.import_path), cfg); 381 insert_use::insert_use(&new_ast, mod_path_to_ast(&self.import.import_path), &cfg);
382 let mut import_insert = TextEdit::builder(); 382 let mut import_insert = TextEdit::builder();
383 algo::diff(self.scope.as_syntax_node(), new_ast.as_syntax_node()) 383 algo::diff(self.scope.as_syntax_node(), new_ast.as_syntax_node())
384 .into_text_edit(&mut import_insert); 384 .into_text_edit(&mut import_insert);
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 4b55f7504..9bec03e17 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -1269,16 +1269,11 @@ fn bar(t: &Foo) {}
1269 fn suggest_deref_fn_ret() { 1269 fn suggest_deref_fn_ret() {
1270 check_relevance( 1270 check_relevance(
1271 r#" 1271 r#"
1272#[lang = "deref"] 1272//- minicore: deref
1273trait Deref {
1274 type Target;
1275 fn deref(&self) -> &Self::Target;
1276}
1277
1278struct S; 1273struct S;
1279struct T(S); 1274struct T(S);
1280 1275
1281impl Deref for T { 1276impl core::ops::Deref for T {
1282 type Target = S; 1277 type Target = S;
1283 1278
1284 fn deref(&self) -> &Self::Target { 1279 fn deref(&self) -> &Self::Target {
@@ -1292,15 +1287,16 @@ fn bar() -> T {}
1292fn main() { 1287fn main() {
1293 foo($0); 1288 foo($0);
1294} 1289}
1295 "#, 1290"#,
1296 expect![[r#" 1291 expect![[r#"
1297 tt Deref []
1298 fn bar() []
1299 fn &bar() [type]
1300 fn foo(…) []
1301 st T [] 1292 st T []
1302 st S [] 1293 st S []
1303 fn main() [] 1294 fn main() []
1295 fn bar() []
1296 fn &bar() [type]
1297 fn foo(…) []
1298 md core []
1299 tt Sized []
1304 "#]], 1300 "#]],
1305 ) 1301 )
1306 } 1302 }
diff --git a/crates/ide_completion/src/tests.rs b/crates/ide_completion/src/tests.rs
index 1ea6017ce..211c89c40 100644
--- a/crates/ide_completion/src/tests.rs
+++ b/crates/ide_completion/src/tests.rs
@@ -36,6 +36,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
36 prefix_kind: PrefixKind::Plain, 36 prefix_kind: PrefixKind::Plain,
37 enforce_granularity: true, 37 enforce_granularity: true,
38 group: true, 38 group: true,
39 skip_glob_imports: true,
39 }, 40 },
40}; 41};
41 42
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index 10bbafe77..e6b4832e7 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -5,7 +5,7 @@ use hir::Semantics;
5use syntax::{ 5use syntax::{
6 algo, 6 algo,
7 ast::{self, make, AstNode, AttrsOwner, ModuleItemOwner, PathSegmentKind, VisibilityOwner}, 7 ast::{self, make, AstNode, AttrsOwner, ModuleItemOwner, PathSegmentKind, VisibilityOwner},
8 ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken, 8 match_ast, ted, AstToken, Direction, NodeOrToken, SyntaxNode, SyntaxToken,
9}; 9};
10 10
11use crate::{ 11use crate::{
@@ -36,22 +36,39 @@ pub struct InsertUseConfig {
36 pub enforce_granularity: bool, 36 pub enforce_granularity: bool,
37 pub prefix_kind: PrefixKind, 37 pub prefix_kind: PrefixKind,
38 pub group: bool, 38 pub group: bool,
39 pub skip_glob_imports: bool,
39} 40}
40 41
41#[derive(Debug, Clone)] 42#[derive(Debug, Clone)]
42pub enum ImportScope { 43pub enum ImportScope {
43 File(ast::SourceFile), 44 File(ast::SourceFile),
44 Module(ast::ItemList), 45 Module(ast::ItemList),
46 Block(ast::BlockExpr),
45} 47}
46 48
47impl ImportScope { 49impl ImportScope {
48 pub fn from(syntax: SyntaxNode) -> Option<Self> { 50 fn from(syntax: SyntaxNode) -> Option<Self> {
49 if let Some(module) = ast::Module::cast(syntax.clone()) { 51 fn contains_cfg_attr(attrs: &dyn AttrsOwner) -> bool {
50 module.item_list().map(ImportScope::Module) 52 attrs
51 } else if let this @ Some(_) = ast::SourceFile::cast(syntax.clone()) { 53 .attrs()
52 this.map(ImportScope::File) 54 .any(|attr| attr.as_simple_call().map_or(false, |(ident, _)| ident == "cfg"))
53 } else { 55 }
54 ast::ItemList::cast(syntax).map(ImportScope::Module) 56 match_ast! {
57 match syntax {
58 ast::Module(module) => module.item_list().map(ImportScope::Module),
59 ast::SourceFile(file) => Some(ImportScope::File(file)),
60 ast::Fn(func) => contains_cfg_attr(&func).then(|| func.body().map(ImportScope::Block)).flatten(),
61 ast::Const(konst) => contains_cfg_attr(&konst).then(|| match konst.body()? {
62 ast::Expr::BlockExpr(block) => Some(block),
63 _ => None,
64 }).flatten().map(ImportScope::Block),
65 ast::Static(statik) => contains_cfg_attr(&statik).then(|| match statik.body()? {
66 ast::Expr::BlockExpr(block) => Some(block),
67 _ => None,
68 }).flatten().map(ImportScope::Block),
69 _ => None,
70
71 }
55 } 72 }
56 } 73 }
57 74
@@ -72,6 +89,7 @@ impl ImportScope {
72 match self { 89 match self {
73 ImportScope::File(file) => file.syntax(), 90 ImportScope::File(file) => file.syntax(),
74 ImportScope::Module(item_list) => item_list.syntax(), 91 ImportScope::Module(item_list) => item_list.syntax(),
92 ImportScope::Block(block) => block.syntax(),
75 } 93 }
76 } 94 }
77 95
@@ -79,6 +97,7 @@ impl ImportScope {
79 match self { 97 match self {
80 ImportScope::File(file) => ImportScope::File(file.clone_for_update()), 98 ImportScope::File(file) => ImportScope::File(file.clone_for_update()),
81 ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()), 99 ImportScope::Module(item_list) => ImportScope::Module(item_list.clone_for_update()),
100 ImportScope::Block(block) => ImportScope::Block(block.clone_for_update()),
82 } 101 }
83 } 102 }
84 103
@@ -95,6 +114,7 @@ impl ImportScope {
95 let mut use_stmts = match self { 114 let mut use_stmts = match self {
96 ImportScope::File(f) => f.items(), 115 ImportScope::File(f) => f.items(),
97 ImportScope::Module(m) => m.items(), 116 ImportScope::Module(m) => m.items(),
117 ImportScope::Block(b) => b.items(),
98 } 118 }
99 .filter_map(use_stmt); 119 .filter_map(use_stmt);
100 let mut res = ImportGranularityGuess::Unknown; 120 let mut res = ImportGranularityGuess::Unknown;
@@ -153,7 +173,7 @@ enum ImportGranularityGuess {
153} 173}
154 174
155/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur. 175/// Insert an import path into the given file/node. A `merge` value of none indicates that no import merging is allowed to occur.
156pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig) { 176pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: &InsertUseConfig) {
157 let _p = profile::span("insert_use"); 177 let _p = profile::span("insert_use");
158 let mut mb = match cfg.granularity { 178 let mut mb = match cfg.granularity {
159 ImportGranularity::Crate => Some(MergeBehavior::Crate), 179 ImportGranularity::Crate => Some(MergeBehavior::Crate),
@@ -175,7 +195,10 @@ pub fn insert_use<'a>(scope: &ImportScope, path: ast::Path, cfg: InsertUseConfig
175 make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update(); 195 make::use_(None, make::use_tree(path.clone(), None, None, false)).clone_for_update();
176 // merge into existing imports if possible 196 // merge into existing imports if possible
177 if let Some(mb) = mb { 197 if let Some(mb) = mb {
178 for existing_use in scope.as_syntax_node().children().filter_map(ast::Use::cast) { 198 let filter = |it: &_| !(cfg.skip_glob_imports && ast::Use::is_simple_glob(it));
199 for existing_use in
200 scope.as_syntax_node().children().filter_map(ast::Use::cast).filter(filter)
201 {
179 if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) { 202 if let Some(merged) = try_merge_imports(&existing_use, &use_item, mb) {
180 ted::replace(existing_use.syntax(), merged.syntax()); 203 ted::replace(existing_use.syntax(), merged.syntax());
181 return; 204 return;
@@ -315,28 +338,29 @@ fn insert_use_(
315 ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline()); 338 ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline());
316 return; 339 return;
317 } 340 }
318 match scope { 341 let l_curly = match scope {
319 ImportScope::File(_) => { 342 ImportScope::File(_) => {
320 cov_mark::hit!(insert_group_empty_file); 343 cov_mark::hit!(insert_group_empty_file);
321 ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line()); 344 ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
322 ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()) 345 ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
346 return;
323 } 347 }
348 // don't insert the imports before the item list/block expr's opening curly brace
349 ImportScope::Module(item_list) => item_list.l_curly_token(),
324 // don't insert the imports before the item list's opening curly brace 350 // don't insert the imports before the item list's opening curly brace
325 ImportScope::Module(item_list) => match item_list.l_curly_token() { 351 ImportScope::Block(block) => block.l_curly_token(),
326 Some(b) => { 352 };
327 cov_mark::hit!(insert_group_empty_module); 353 match l_curly {
328 ted::insert(ted::Position::after(&b), make::tokens::single_newline()); 354 Some(b) => {
329 ted::insert(ted::Position::after(&b), use_item.syntax()); 355 cov_mark::hit!(insert_group_empty_module);
330 } 356 ted::insert(ted::Position::after(&b), make::tokens::single_newline());
331 None => { 357 ted::insert(ted::Position::after(&b), use_item.syntax());
332 // This should never happens, broken module syntax node 358 }
333 ted::insert( 359 None => {
334 ted::Position::first_child_of(scope_syntax), 360 // This should never happens, broken module syntax node
335 make::tokens::blank_line(), 361 ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
336 ); 362 ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
337 ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax()); 363 }
338 }
339 },
340 } 364 }
341} 365}
342 366
diff --git a/crates/ide_db/src/helpers/insert_use/tests.rs b/crates/ide_db/src/helpers/insert_use/tests.rs
index 5a88ec742..01894630a 100644
--- a/crates/ide_db/src/helpers/insert_use/tests.rs
+++ b/crates/ide_db/src/helpers/insert_use/tests.rs
@@ -1,12 +1,63 @@
1use super::*; 1use super::*;
2 2
3use hir::PrefixKind; 3use hir::PrefixKind;
4use test_utils::assert_eq_text; 4use test_utils::{assert_eq_text, extract_range_or_offset, CURSOR_MARKER};
5
6#[test]
7fn respects_cfg_attr_fn() {
8 check(
9 r"bar::Bar",
10 r#"
11#[cfg(test)]
12fn foo() {$0}
13"#,
14 r#"
15#[cfg(test)]
16fn foo() {
17use bar::Bar;
18}
19"#,
20 ImportGranularity::Crate,
21 );
22}
23
24#[test]
25fn respects_cfg_attr_const() {
26 check(
27 r"bar::Bar",
28 r#"
29#[cfg(test)]
30const FOO: Bar = {$0};
31"#,
32 r#"
33#[cfg(test)]
34const FOO: Bar = {
35use bar::Bar;
36};
37"#,
38 ImportGranularity::Crate,
39 );
40}
41
42#[test]
43fn insert_skips_lone_glob_imports() {
44 check(
45 "use foo::baz::A",
46 r"
47use foo::bar::*;
48",
49 r"
50use foo::bar::*;
51use foo::baz::A;
52",
53 ImportGranularity::Crate,
54 );
55}
5 56
6#[test] 57#[test]
7fn insert_not_group() { 58fn insert_not_group() {
8 cov_mark::check!(insert_no_grouping_last); 59 cov_mark::check!(insert_no_grouping_last);
9 check( 60 check_with_config(
10 "use external_crate2::bar::A", 61 "use external_crate2::bar::A",
11 r" 62 r"
12use std::bar::B; 63use std::bar::B;
@@ -21,24 +72,32 @@ use crate::bar::A;
21use self::bar::A; 72use self::bar::A;
22use super::bar::A; 73use super::bar::A;
23use external_crate2::bar::A;", 74use external_crate2::bar::A;",
24 ImportGranularity::Item, 75 &InsertUseConfig {
25 false, 76 granularity: ImportGranularity::Item,
26 false, 77 enforce_granularity: true,
78 prefix_kind: PrefixKind::Plain,
79 group: false,
80 skip_glob_imports: true,
81 },
27 ); 82 );
28} 83}
29 84
30#[test] 85#[test]
31fn insert_not_group_empty() { 86fn insert_not_group_empty() {
32 cov_mark::check!(insert_no_grouping_last2); 87 cov_mark::check!(insert_no_grouping_last2);
33 check( 88 check_with_config(
34 "use external_crate2::bar::A", 89 "use external_crate2::bar::A",
35 r"", 90 r"",
36 r"use external_crate2::bar::A; 91 r"use external_crate2::bar::A;
37 92
38", 93",
39 ImportGranularity::Item, 94 &InsertUseConfig {
40 false, 95 granularity: ImportGranularity::Item,
41 false, 96 enforce_granularity: true,
97 prefix_kind: PrefixKind::Plain,
98 group: false,
99 skip_glob_imports: true,
100 },
42 ); 101 );
43} 102}
44 103
@@ -277,13 +336,15 @@ fn insert_empty_module() {
277 cov_mark::check!(insert_group_empty_module); 336 cov_mark::check!(insert_group_empty_module);
278 check( 337 check(
279 "foo::bar", 338 "foo::bar",
280 "mod x {}", 339 r"
281 r"{ 340mod x {$0}
341",
342 r"
343mod x {
282 use foo::bar; 344 use foo::bar;
283}", 345}
346",
284 ImportGranularity::Item, 347 ImportGranularity::Item,
285 true,
286 true,
287 ) 348 )
288} 349}
289 350
@@ -534,17 +595,35 @@ fn merge_groups_self() {
534 595
535#[test] 596#[test]
536fn merge_mod_into_glob() { 597fn merge_mod_into_glob() {
537 check_crate( 598 check_with_config(
538 "token::TokenKind", 599 "token::TokenKind",
539 r"use token::TokenKind::*;", 600 r"use token::TokenKind::*;",
540 r"use token::TokenKind::{*, self};", 601 r"use token::TokenKind::{*, self};",
602 &InsertUseConfig {
603 granularity: ImportGranularity::Crate,
604 enforce_granularity: true,
605 prefix_kind: PrefixKind::Plain,
606 group: false,
607 skip_glob_imports: false,
608 },
541 ) 609 )
542 // FIXME: have it emit `use token::TokenKind::{self, *}`? 610 // FIXME: have it emit `use token::TokenKind::{self, *}`?
543} 611}
544 612
545#[test] 613#[test]
546fn merge_self_glob() { 614fn merge_self_glob() {
547 check_crate("self", r"use self::*;", r"use self::{*, self};") 615 check_with_config(
616 "self",
617 r"use self::*;",
618 r"use self::{*, self};",
619 &InsertUseConfig {
620 granularity: ImportGranularity::Crate,
621 enforce_granularity: true,
622 prefix_kind: PrefixKind::Plain,
623 group: false,
624 skip_glob_imports: false,
625 },
626 )
548 // FIXME: have it emit `use {self, *}`? 627 // FIXME: have it emit `use {self, *}`?
549} 628}
550 629
@@ -757,19 +836,24 @@ use foo::bar::qux;
757 ); 836 );
758} 837}
759 838
760fn check( 839fn check_with_config(
761 path: &str, 840 path: &str,
762 ra_fixture_before: &str, 841 ra_fixture_before: &str,
763 ra_fixture_after: &str, 842 ra_fixture_after: &str,
764 granularity: ImportGranularity, 843 config: &InsertUseConfig,
765 module: bool,
766 group: bool,
767) { 844) {
768 let mut syntax = ast::SourceFile::parse(ra_fixture_before).tree().syntax().clone(); 845 let (text, pos) = if ra_fixture_before.contains(CURSOR_MARKER) {
769 if module { 846 let (range_or_offset, text) = extract_range_or_offset(ra_fixture_before);
770 syntax = syntax.descendants().find_map(ast::Module::cast).unwrap().syntax().clone(); 847 (text, Some(range_or_offset))
771 } 848 } else {
772 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();
773 let path = ast::SourceFile::parse(&format!("use {};", path)) 857 let path = ast::SourceFile::parse(&format!("use {};", path))
774 .tree() 858 .tree()
775 .syntax() 859 .syntax()
@@ -777,30 +861,41 @@ fn check(
777 .find_map(ast::Path::cast) 861 .find_map(ast::Path::cast)
778 .unwrap(); 862 .unwrap();
779 863
780 insert_use( 864 insert_use(&file, path, config);
781 &file, 865 let result = file.as_syntax_node().ancestors().last().unwrap().to_string();
866 assert_eq_text!(ra_fixture_after, &result);
867}
868
869fn check(
870 path: &str,
871 ra_fixture_before: &str,
872 ra_fixture_after: &str,
873 granularity: ImportGranularity,
874) {
875 check_with_config(
782 path, 876 path,
783 InsertUseConfig { 877 ra_fixture_before,
878 ra_fixture_after,
879 &InsertUseConfig {
784 granularity, 880 granularity,
785 enforce_granularity: true, 881 enforce_granularity: true,
786 prefix_kind: PrefixKind::Plain, 882 prefix_kind: PrefixKind::Plain,
787 group, 883 group: true,
884 skip_glob_imports: true,
788 }, 885 },
789 ); 886 )
790 let result = file.as_syntax_node().to_string();
791 assert_eq_text!(ra_fixture_after, &result);
792} 887}
793 888
794fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 889fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
795 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate, false, true) 890 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate)
796} 891}
797 892
798fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 893fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
799 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module, false, true) 894 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module)
800} 895}
801 896
802fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 897fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
803 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item, false, true) 898 check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item)
804} 899}
805 900
806fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) { 901fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior) {
diff --git a/crates/ide_diagnostics/src/handlers/missing_ok_or_some_in_tail_expr.rs b/crates/ide_diagnostics/src/handlers/missing_ok_or_some_in_tail_expr.rs
index 63de54570..c0edcd7d3 100644
--- a/crates/ide_diagnostics/src/handlers/missing_ok_or_some_in_tail_expr.rs
+++ b/crates/ide_diagnostics/src/handlers/missing_ok_or_some_in_tail_expr.rs
@@ -49,26 +49,15 @@ mod tests {
49 fn test_wrap_return_type_option() { 49 fn test_wrap_return_type_option() {
50 check_fix( 50 check_fix(
51 r#" 51 r#"
52//- /main.rs crate:main deps:core 52//- minicore: option, result
53use core::option::Option::{self, Some, None};
54
55fn div(x: i32, y: i32) -> Option<i32> { 53fn div(x: i32, y: i32) -> Option<i32> {
56 if y == 0 { 54 if y == 0 {
57 return None; 55 return None;
58 } 56 }
59 x / y$0 57 x / y$0
60} 58}
61//- /core/lib.rs crate:core
62pub mod result {
63 pub enum Result<T, E> { Ok(T), Err(E) }
64}
65pub mod option {
66 pub enum Option<T> { Some(T), None }
67}
68"#, 59"#,
69 r#" 60 r#"
70use core::option::Option::{self, Some, None};
71
72fn div(x: i32, y: i32) -> Option<i32> { 61fn div(x: i32, y: i32) -> Option<i32> {
73 if y == 0 { 62 if y == 0 {
74 return None; 63 return None;
@@ -83,26 +72,15 @@ fn div(x: i32, y: i32) -> Option<i32> {
83 fn test_wrap_return_type() { 72 fn test_wrap_return_type() {
84 check_fix( 73 check_fix(
85 r#" 74 r#"
86//- /main.rs crate:main deps:core 75//- minicore: option, result
87use core::result::Result::{self, Ok, Err};
88
89fn div(x: i32, y: i32) -> Result<i32, ()> { 76fn div(x: i32, y: i32) -> Result<i32, ()> {
90 if y == 0 { 77 if y == 0 {
91 return Err(()); 78 return Err(());
92 } 79 }
93 x / y$0 80 x / y$0
94} 81}
95//- /core/lib.rs crate:core
96pub mod result {
97 pub enum Result<T, E> { Ok(T), Err(E) }
98}
99pub mod option {
100 pub enum Option<T> { Some(T), None }
101}
102"#, 82"#,
103 r#" 83 r#"
104use core::result::Result::{self, Ok, Err};
105
106fn div(x: i32, y: i32) -> Result<i32, ()> { 84fn div(x: i32, y: i32) -> Result<i32, ()> {
107 if y == 0 { 85 if y == 0 {
108 return Err(()); 86 return Err(());
@@ -117,26 +95,15 @@ fn div(x: i32, y: i32) -> Result<i32, ()> {
117 fn test_wrap_return_type_handles_generic_functions() { 95 fn test_wrap_return_type_handles_generic_functions() {
118 check_fix( 96 check_fix(
119 r#" 97 r#"
120//- /main.rs crate:main deps:core 98//- minicore: option, result
121use core::result::Result::{self, Ok, Err};
122
123fn div<T>(x: T) -> Result<T, i32> { 99fn div<T>(x: T) -> Result<T, i32> {
124 if x == 0 { 100 if x == 0 {
125 return Err(7); 101 return Err(7);
126 } 102 }
127 $0x 103 $0x
128} 104}
129//- /core/lib.rs crate:core
130pub mod result {
131 pub enum Result<T, E> { Ok(T), Err(E) }
132}
133pub mod option {
134 pub enum Option<T> { Some(T), None }
135}
136"#, 105"#,
137 r#" 106 r#"
138use core::result::Result::{self, Ok, Err};
139
140fn div<T>(x: T) -> Result<T, i32> { 107fn div<T>(x: T) -> Result<T, i32> {
141 if x == 0 { 108 if x == 0 {
142 return Err(7); 109 return Err(7);
@@ -151,9 +118,7 @@ fn div<T>(x: T) -> Result<T, i32> {
151 fn test_wrap_return_type_handles_type_aliases() { 118 fn test_wrap_return_type_handles_type_aliases() {
152 check_fix( 119 check_fix(
153 r#" 120 r#"
154//- /main.rs crate:main deps:core 121//- minicore: option, result
155use core::result::Result::{self, Ok, Err};
156
157type MyResult<T> = Result<T, ()>; 122type MyResult<T> = Result<T, ()>;
158 123
159fn div(x: i32, y: i32) -> MyResult<i32> { 124fn div(x: i32, y: i32) -> MyResult<i32> {
@@ -162,17 +127,8 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
162 } 127 }
163 x $0/ y 128 x $0/ y
164} 129}
165//- /core/lib.rs crate:core
166pub mod result {
167 pub enum Result<T, E> { Ok(T), Err(E) }
168}
169pub mod option {
170 pub enum Option<T> { Some(T), None }
171}
172"#, 130"#,
173 r#" 131 r#"
174use core::result::Result::{self, Ok, Err};
175
176type MyResult<T> = Result<T, ()>; 132type MyResult<T> = Result<T, ()>;
177 133
178fn div(x: i32, y: i32) -> MyResult<i32> { 134fn div(x: i32, y: i32) -> MyResult<i32> {
@@ -189,18 +145,8 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
189 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() { 145 fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
190 check_diagnostics( 146 check_diagnostics(
191 r#" 147 r#"
192//- /main.rs crate:main deps:core 148//- minicore: option, result
193use core::result::Result::{self, Ok, Err};
194
195fn foo() -> Result<(), i32> { 0 } 149fn foo() -> Result<(), i32> { 0 }
196
197//- /core/lib.rs crate:core
198pub mod result {
199 pub enum Result<T, E> { Ok(T), Err(E) }
200}
201pub mod option {
202 pub enum Option<T> { Some(T), None }
203}
204"#, 150"#,
205 ); 151 );
206 } 152 }
@@ -209,20 +155,10 @@ pub mod option {
209 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() { 155 fn test_wrap_return_type_not_applicable_when_return_type_is_not_result_or_option() {
210 check_diagnostics( 156 check_diagnostics(
211 r#" 157 r#"
212//- /main.rs crate:main deps:core 158//- minicore: option, result
213use core::result::Result::{self, Ok, Err};
214
215enum SomeOtherEnum { Ok(i32), Err(String) } 159enum SomeOtherEnum { Ok(i32), Err(String) }
216 160
217fn foo() -> SomeOtherEnum { 0 } 161fn foo() -> SomeOtherEnum { 0 }
218
219//- /core/lib.rs crate:core
220pub mod result {
221 pub enum Result<T, E> { Ok(T), Err(E) }
222}
223pub mod option {
224 pub enum Option<T> { Some(T), None }
225}
226"#, 162"#,
227 ); 163 );
228 } 164 }
diff --git a/crates/ide_diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/crates/ide_diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
index cd87a10bb..839ceac03 100644
--- a/crates/ide_diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
+++ b/crates/ide_diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
@@ -55,44 +55,16 @@ fn fixes(
55 55
56#[cfg(test)] 56#[cfg(test)]
57mod tests { 57mod tests {
58 use crate::tests::check_fix; 58 use crate::tests::{check_diagnostics, check_fix};
59
60 // Register the required standard library types to make the tests work
61 #[track_caller]
62 fn check_diagnostics(ra_fixture: &str) {
63 let prefix = r#"
64//- /main.rs crate:main deps:core
65use core::iter::Iterator;
66use core::option::Option::{self, Some, None};
67"#;
68 let suffix = r#"
69//- /core/lib.rs crate:core
70pub mod option {
71 pub enum Option<T> { Some(T), None }
72}
73pub mod iter {
74 pub trait Iterator {
75 type Item;
76 fn filter_map<B, F>(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option<B> { FilterMap }
77 fn next(&mut self) -> Option<Self::Item>;
78 }
79 pub struct FilterMap {}
80 impl Iterator for FilterMap {
81 type Item = i32;
82 fn next(&mut self) -> i32 { 7 }
83 }
84}
85"#;
86 crate::tests::check_diagnostics(&format!("{}{}{}", prefix, ra_fixture, suffix))
87 }
88 59
89 #[test] 60 #[test]
90 fn replace_filter_map_next_with_find_map2() { 61 fn replace_filter_map_next_with_find_map2() {
91 check_diagnostics( 62 check_diagnostics(
92 r#" 63 r#"
93 fn foo() { 64//- minicore: iterators
94 let m = [1, 2, 3].iter().filter_map(|x| Some(92)).next(); 65fn foo() {
95 } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..) 66 let m = core::iter::repeat(()).filter_map(|()| Some(92)).next();
67} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 💡 weak: replace filter_map(..).next() with find_map(..)
96"#, 68"#,
97 ); 69 );
98 } 70 }
@@ -101,11 +73,11 @@ pub mod iter {
101 fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() { 73 fn replace_filter_map_next_with_find_map_no_diagnostic_without_next() {
102 check_diagnostics( 74 check_diagnostics(
103 r#" 75 r#"
76//- minicore: iterators
104fn foo() { 77fn foo() {
105 let m = [1, 2, 3] 78 let m = core::iter::repeat(())
106 .iter() 79 .filter_map(|()| Some(92))
107 .filter_map(|x| Some(92)) 80 .count();
108 .len();
109} 81}
110"#, 82"#,
111 ); 83 );
@@ -115,12 +87,12 @@ fn foo() {
115 fn replace_filter_map_next_with_find_map_no_diagnostic_with_intervening_methods() { 87 fn replace_filter_map_next_with_find_map_no_diagnostic_with_intervening_methods() {
116 check_diagnostics( 88 check_diagnostics(
117 r#" 89 r#"
90//- minicore: iterators
118fn foo() { 91fn foo() {
119 let m = [1, 2, 3] 92 let m = core::iter::repeat(())
120 .iter() 93 .filter_map(|()| Some(92))
121 .filter_map(|x| Some(92))
122 .map(|x| x + 2) 94 .map(|x| x + 2)
123 .len(); 95 .next();
124} 96}
125"#, 97"#,
126 ); 98 );
@@ -130,10 +102,10 @@ fn foo() {
130 fn replace_filter_map_next_with_find_map_no_diagnostic_if_not_in_chain() { 102 fn replace_filter_map_next_with_find_map_no_diagnostic_if_not_in_chain() {
131 check_diagnostics( 103 check_diagnostics(
132 r#" 104 r#"
105//- minicore: iterators
133fn foo() { 106fn foo() {
134 let m = [1, 2, 3] 107 let m = core::iter::repeat(())
135 .iter() 108 .filter_map(|()| Some(92));
136 .filter_map(|x| Some(92));
137 let n = m.next(); 109 let n = m.next();
138} 110}
139"#, 111"#,
@@ -144,34 +116,14 @@ fn foo() {
144 fn replace_with_wind_map() { 116 fn replace_with_wind_map() {
145 check_fix( 117 check_fix(
146 r#" 118 r#"
147//- /main.rs crate:main deps:core 119//- minicore: iterators
148use core::iter::Iterator;
149use core::option::Option::{self, Some, None};
150fn foo() { 120fn foo() {
151 let m = [1, 2, 3].iter().$0filter_map(|x| Some(92)).next(); 121 let m = core::iter::repeat(()).$0filter_map(|()| Some(92)).next();
152}
153//- /core/lib.rs crate:core
154pub mod option {
155 pub enum Option<T> { Some(T), None }
156}
157pub mod iter {
158 pub trait Iterator {
159 type Item;
160 fn filter_map<B, F>(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option<B> { FilterMap }
161 fn next(&mut self) -> Option<Self::Item>;
162 }
163 pub struct FilterMap {}
164 impl Iterator for FilterMap {
165 type Item = i32;
166 fn next(&mut self) -> i32 { 7 }
167 }
168} 122}
169"#, 123"#,
170 r#" 124 r#"
171use core::iter::Iterator;
172use core::option::Option::{self, Some, None};
173fn foo() { 125fn foo() {
174 let m = [1, 2, 3].iter().find_map(|x| Some(92)); 126 let m = core::iter::repeat(()).find_map(|()| Some(92));
175} 127}
176"#, 128"#,
177 ) 129 )
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index c4757a1cb..16c295639 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -44,6 +44,9 @@ config_data! {
44 assist_importPrefix: ImportPrefixDef = "\"plain\"", 44 assist_importPrefix: ImportPrefixDef = "\"plain\"",
45 /// Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines. 45 /// Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.
46 assist_importGroup: bool = "true", 46 assist_importGroup: bool = "true",
47 /// Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`.
48 assist_allowMergingIntoGlobImports: bool = "true",
49
47 /// Show function name and docs in parameter hints. 50 /// Show function name and docs in parameter hints.
48 callInfo_full: bool = "true", 51 callInfo_full: bool = "true",
49 52
@@ -672,6 +675,7 @@ impl Config {
672 ImportPrefixDef::BySelf => PrefixKind::BySelf, 675 ImportPrefixDef::BySelf => PrefixKind::BySelf,
673 }, 676 },
674 group: self.data.assist_importGroup, 677 group: self.data.assist_importGroup,
678 skip_glob_imports: !self.data.assist_allowMergingIntoGlobImports,
675 } 679 }
676 } 680 }
677 pub fn completion(&self) -> CompletionConfig { 681 pub fn completion(&self) -> CompletionConfig {
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 8ddeb59f7..f8afc930a 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -143,6 +143,7 @@ fn integrated_completion_benchmark() {
143 prefix_kind: hir::PrefixKind::ByCrate, 143 prefix_kind: hir::PrefixKind::ByCrate,
144 enforce_granularity: true, 144 enforce_granularity: true,
145 group: true, 145 group: true,
146 skip_glob_imports: true,
146 }, 147 },
147 }; 148 };
148 let position = 149 let position =
@@ -178,6 +179,7 @@ fn integrated_completion_benchmark() {
178 prefix_kind: hir::PrefixKind::ByCrate, 179 prefix_kind: hir::PrefixKind::ByCrate,
179 enforce_granularity: true, 180 enforce_granularity: true,
180 group: true, 181 group: true,
182 skip_glob_imports: true,
181 }, 183 },
182 }; 184 };
183 let position = 185 let position =
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index e53cd3c7b..310d8c6d2 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -1187,6 +1187,7 @@ mod tests {
1187 prefix_kind: PrefixKind::Plain, 1187 prefix_kind: PrefixKind::Plain,
1188 enforce_granularity: true, 1188 enforce_granularity: true,
1189 group: true, 1189 group: true,
1190 skip_glob_imports: true,
1190 }, 1191 },
1191 }, 1192 },
1192 ide_db::base_db::FilePosition { file_id, offset }, 1193 ide_db::base_db::FilePosition { file_id, offset },
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index b057e6624..e33e5bb03 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -8,7 +8,7 @@ use parser::SyntaxKind;
8use rowan::{GreenNodeData, GreenTokenData}; 8use rowan::{GreenNodeData, GreenTokenData};
9 9
10use crate::{ 10use crate::{
11 ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode}, 11 ast::{self, support, AstChildren, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode},
12 NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T, 12 NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T,
13}; 13};
14 14
@@ -45,6 +45,12 @@ fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
45 } 45 }
46} 46}
47 47
48impl ast::BlockExpr {
49 pub fn items(&self) -> AstChildren<ast::Item> {
50 support::children(self.syntax())
51 }
52}
53
48#[derive(Debug, PartialEq, Eq, Clone)] 54#[derive(Debug, PartialEq, Eq, Clone)]
49pub enum Macro { 55pub enum Macro {
50 MacroRules(ast::MacroRules), 56 MacroRules(ast::MacroRules),
@@ -281,6 +287,15 @@ impl ast::Path {
281 successors(self.qualifier(), |p| p.qualifier()) 287 successors(self.qualifier(), |p| p.qualifier())
282 } 288 }
283} 289}
290
291impl ast::Use {
292 pub fn is_simple_glob(&self) -> bool {
293 self.use_tree()
294 .map(|use_tree| use_tree.use_tree_list().is_none() && use_tree.star_token().is_some())
295 .unwrap_or(false)
296 }
297}
298
284impl ast::UseTree { 299impl ast::UseTree {
285 pub fn is_simple_path(&self) -> bool { 300 pub fn is_simple_path(&self) -> bool {
286 self.use_tree_list().is_none() && self.star_token().is_none() 301 self.use_tree_list().is_none() && self.star_token().is_none()
diff --git a/crates/test_utils/src/minicore.rs b/crates/test_utils/src/minicore.rs
index 769028580..ce6ad8541 100644
--- a/crates/test_utils/src/minicore.rs
+++ b/crates/test_utils/src/minicore.rs
@@ -15,13 +15,14 @@
15//! range: 15//! range:
16//! deref: sized 16//! deref: sized
17//! deref_mut: deref 17//! deref_mut: deref
18//! index: sized
18//! fn: 19//! fn:
19//! pin: 20//! pin:
20//! future: pin 21//! future: pin
21//! option: 22//! option:
22//! result: 23//! result:
23//! iterator: option 24//! iterator: option
24//! iterators: iterator 25//! iterators: iterator, fn
25//! default: sized 26//! default: sized
26//! clone: sized 27//! clone: sized
27//! copy: clone 28//! copy: clone
@@ -167,6 +168,48 @@ pub mod ops {
167 }; 168 };
168 // endregion:deref 169 // endregion:deref
169 170
171 // region:index
172 mod index {
173 #[lang = "index"]
174 pub trait Index<Idx: ?Sized> {
175 type Output: ?Sized;
176 fn index(&self, index: Idx) -> &Self::Output;
177 }
178 #[lang = "index_mut"]
179 pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
180 fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
181 }
182
183 // region:slice
184 impl<T, I> Index<I> for [T]
185 where
186 I: SliceIndex<[T]>,
187 {
188 type Output = I::Output;
189 fn index(&self, index: I) -> &I::Output {
190 loop {}
191 }
192 }
193 impl<T, I> IndexMut<I> for [T]
194 where
195 I: SliceIndex<[T]>,
196 {
197 fn index_mut(&mut self, index: I) -> &mut I::Output {
198 loop {}
199 }
200 }
201
202 pub unsafe trait SliceIndex<T: ?Sized> {
203 type Output: ?Sized;
204 }
205 unsafe impl<T> SliceIndex<[T]> for usize {
206 type Output = T;
207 }
208 // endregion:slice
209 }
210 pub use self::index::{Index, IndexMut};
211 // endregion:index
212
170 // region:range 213 // region:range
171 mod range { 214 mod range {
172 #[lang = "RangeFull"] 215 #[lang = "RangeFull"]
@@ -347,7 +390,6 @@ pub mod iter {
347 iter: I, 390 iter: I,
348 n: usize, 391 n: usize,
349 } 392 }
350
351 impl<I> Iterator for Take<I> 393 impl<I> Iterator for Take<I>
352 where 394 where
353 I: Iterator, 395 I: Iterator,
@@ -358,6 +400,22 @@ pub mod iter {
358 loop {} 400 loop {}
359 } 401 }
360 } 402 }
403
404 pub struct FilterMap<I, F> {
405 iter: I,
406 f: F,
407 }
408 impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
409 where
410 F: FnMut(I::Item) -> Option<B>,
411 {
412 type Item = B;
413
414 #[inline]
415 fn next(&mut self) -> Option<B> {
416 loop {}
417 }
418 }
361 } 419 }
362 pub use self::adapters::Take; 420 pub use self::adapters::Take;
363 421
@@ -405,6 +463,13 @@ pub mod iter {
405 fn take(self, n: usize) -> crate::iter::Take<Self> { 463 fn take(self, n: usize) -> crate::iter::Take<Self> {
406 loop {} 464 loop {}
407 } 465 }
466 fn filter_map<B, F>(self, f: F) -> crate::iter::FilterMap<Self, F>
467 where
468 Self: Sized,
469 F: FnMut(Self::Item) -> Option<B>,
470 {
471 loop {}
472 }
408 // endregion:iterators 473 // endregion:iterators
409 } 474 }
410 impl<I: Iterator + ?Sized> Iterator for &mut I { 475 impl<I: Iterator + ?Sized> Iterator for &mut I {