]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/auto_import.rs
Deduplicate imports for qualify_path
[rust.git] / crates / ide_assists / src / handlers / auto_import.rs
1 use ide_db::helpers::{
2     import_assets::{ImportAssets, ImportCandidate},
3     insert_use::{insert_use, ImportScope},
4     mod_path_to_ast,
5 };
6 use syntax::{ast, AstNode, SyntaxNode};
7
8 use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
9
10 // Feature: Auto Import
11 //
12 // Using the `auto-import` assist it is possible to insert missing imports for unresolved items.
13 // When inserting an import it will do so in a structured manner by keeping imports grouped,
14 // separated by a newline in the following order:
15 //
16 // - `std` and `core`
17 // - External Crates
18 // - Current Crate, paths prefixed by `crate`
19 // - Current Module, paths prefixed by `self`
20 // - Super Module, paths prefixed by `super`
21 //
22 // Example:
23 // ```rust
24 // use std::fs::File;
25 //
26 // use itertools::Itertools;
27 // use syntax::ast;
28 //
29 // use crate::utils::insert_use;
30 //
31 // use self::auto_import;
32 //
33 // use super::AssistContext;
34 // ```
35 //
36 // .Import Granularity
37 //
38 // It is possible to configure how use-trees are merged with the `importGranularity` setting.
39 // It has the following configurations:
40 //
41 // - `crate`: Merge imports from the same crate into a single use statement. This kind of
42 //  nesting is only supported in Rust versions later than 1.24.
43 // - `module`: Merge imports from the same module into a single use statement.
44 // - `item`: Don't merge imports at all, creating one import per item.
45 // - `preserve`: Do not change the granularity of any imports. For auto-import this has the same
46 //  effect as `item`.
47 //
48 // In `VS Code` the configuration for this is `rust-analyzer.assist.importGranularity`.
49 //
50 // .Import Prefix
51 //
52 // The style of imports in the same crate is configurable through the `importPrefix` setting.
53 // It has the following configurations:
54 //
55 // - `by_crate`: This setting will force paths to be always absolute, starting with the `crate`
56 //  prefix, unless the item is defined outside of the current crate.
57 // - `by_self`: This setting will force paths that are relative to the current module to always
58 //  start with `self`. This will result in paths that always start with either `crate`, `self`,
59 //  `super` or an extern crate identifier.
60 // - `plain`: This setting does not impose any restrictions in imports.
61 //
62 // In `VS Code` the configuration for this is `rust-analyzer.assist.importPrefix`.
63 //
64 // image::https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif[]
65
66 // Assist: auto_import
67 //
68 // If the name is unresolved, provides all possible imports for it.
69 //
70 // ```
71 // fn main() {
72 //     let map = HashMap$0::new();
73 // }
74 // # pub mod std { pub mod collections { pub struct HashMap { } } }
75 // ```
76 // ->
77 // ```
78 // use std::collections::HashMap;
79 //
80 // fn main() {
81 //     let map = HashMap::new();
82 // }
83 // # pub mod std { pub mod collections { pub struct HashMap { } } }
84 // ```
85 pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
86     let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
87     let mut proposed_imports =
88         import_assets.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind);
89     if proposed_imports.is_empty() {
90         return None;
91     }
92
93     let range = ctx.sema.original_range(&syntax_under_caret).range;
94     let group_label = group_label(import_assets.import_candidate());
95     let scope = ImportScope::find_insert_use_container_with_macros(&syntax_under_caret, &ctx.sema)?;
96
97     // we aren't interested in different namespaces
98     proposed_imports.dedup_by(|a, b| a.import_path == b.import_path);
99     for import in proposed_imports {
100         acc.add_group(
101             &group_label,
102             AssistId("auto_import", AssistKind::QuickFix),
103             format!("Import `{}`", import.import_path),
104             range,
105             |builder| {
106                 let scope = match scope.clone() {
107                     ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
108                     ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
109                     ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
110                 };
111                 insert_use(&scope, mod_path_to_ast(&import.import_path), &ctx.config.insert_use);
112             },
113         );
114     }
115     Some(())
116 }
117
118 pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets, SyntaxNode)> {
119     if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
120         ImportAssets::for_exact_path(&path_under_caret, &ctx.sema)
121             .zip(Some(path_under_caret.syntax().clone()))
122     } else if let Some(method_under_caret) =
123         ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>()
124     {
125         ImportAssets::for_method_call(&method_under_caret, &ctx.sema)
126             .zip(Some(method_under_caret.syntax().clone()))
127     } else if let Some(pat) = ctx
128         .find_node_at_offset_with_descend::<ast::IdentPat>()
129         .filter(ast::IdentPat::is_simple_ident)
130     {
131         ImportAssets::for_ident_pat(&pat, &ctx.sema).zip(Some(pat.syntax().clone()))
132     } else {
133         None
134     }
135 }
136
137 fn group_label(import_candidate: &ImportCandidate) -> GroupLabel {
138     let name = match import_candidate {
139         ImportCandidate::Path(candidate) => format!("Import {}", candidate.name.text()),
140         ImportCandidate::TraitAssocItem(candidate) => {
141             format!("Import a trait for item {}", candidate.assoc_item_name.text())
142         }
143         ImportCandidate::TraitMethod(candidate) => {
144             format!("Import a trait for method {}", candidate.assoc_item_name.text())
145         }
146     };
147     GroupLabel(name)
148 }
149
150 #[cfg(test)]
151 mod tests {
152     use super::*;
153
154     use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
155
156     #[test]
157     fn applicable_when_found_an_import_partial() {
158         check_assist(
159             auto_import,
160             r"
161             mod std {
162                 pub mod fmt {
163                     pub struct Formatter;
164                 }
165             }
166
167             use std::fmt;
168
169             $0Formatter
170             ",
171             r"
172             mod std {
173                 pub mod fmt {
174                     pub struct Formatter;
175                 }
176             }
177
178             use std::fmt::{self, Formatter};
179
180             Formatter
181             ",
182         );
183     }
184
185     #[test]
186     fn applicable_when_found_an_import() {
187         check_assist(
188             auto_import,
189             r"
190             $0PubStruct
191
192             pub mod PubMod {
193                 pub struct PubStruct;
194             }
195             ",
196             r"
197             use PubMod::PubStruct;
198
199             PubStruct
200
201             pub mod PubMod {
202                 pub struct PubStruct;
203             }
204             ",
205         );
206     }
207
208     #[test]
209     fn applicable_when_found_an_import_in_macros() {
210         check_assist(
211             auto_import,
212             r"
213             macro_rules! foo {
214                 ($i:ident) => { fn foo(a: $i) {} }
215             }
216             foo!(Pub$0Struct);
217
218             pub mod PubMod {
219                 pub struct PubStruct;
220             }
221             ",
222             r"
223             use PubMod::PubStruct;
224
225             macro_rules! foo {
226                 ($i:ident) => { fn foo(a: $i) {} }
227             }
228             foo!(PubStruct);
229
230             pub mod PubMod {
231                 pub struct PubStruct;
232             }
233             ",
234         );
235     }
236
237     #[test]
238     fn applicable_when_found_multiple_imports() {
239         check_assist(
240             auto_import,
241             r"
242             PubSt$0ruct
243
244             pub mod PubMod1 {
245                 pub struct PubStruct;
246             }
247             pub mod PubMod2 {
248                 pub struct PubStruct;
249             }
250             pub mod PubMod3 {
251                 pub struct PubStruct;
252             }
253             ",
254             r"
255             use PubMod3::PubStruct;
256
257             PubStruct
258
259             pub mod PubMod1 {
260                 pub struct PubStruct;
261             }
262             pub mod PubMod2 {
263                 pub struct PubStruct;
264             }
265             pub mod PubMod3 {
266                 pub struct PubStruct;
267             }
268             ",
269         );
270     }
271
272     #[test]
273     fn not_applicable_for_already_imported_types() {
274         check_assist_not_applicable(
275             auto_import,
276             r"
277             use PubMod::PubStruct;
278
279             PubStruct$0
280
281             pub mod PubMod {
282                 pub struct PubStruct;
283             }
284             ",
285         );
286     }
287
288     #[test]
289     fn not_applicable_for_types_with_private_paths() {
290         check_assist_not_applicable(
291             auto_import,
292             r"
293             PrivateStruct$0
294
295             pub mod PubMod {
296                 struct PrivateStruct;
297             }
298             ",
299         );
300     }
301
302     #[test]
303     fn not_applicable_when_no_imports_found() {
304         check_assist_not_applicable(
305             auto_import,
306             "
307             PubStruct$0",
308         );
309     }
310
311     #[test]
312     fn not_applicable_in_import_statements() {
313         check_assist_not_applicable(
314             auto_import,
315             r"
316             use PubStruct$0;
317
318             pub mod PubMod {
319                 pub struct PubStruct;
320             }",
321         );
322     }
323
324     #[test]
325     fn function_import() {
326         check_assist(
327             auto_import,
328             r"
329             test_function$0
330
331             pub mod PubMod {
332                 pub fn test_function() {};
333             }
334             ",
335             r"
336             use PubMod::test_function;
337
338             test_function
339
340             pub mod PubMod {
341                 pub fn test_function() {};
342             }
343             ",
344         );
345     }
346
347     #[test]
348     fn macro_import() {
349         check_assist(
350             auto_import,
351             r"
352 //- /lib.rs crate:crate_with_macro
353 #[macro_export]
354 macro_rules! foo {
355     () => ()
356 }
357
358 //- /main.rs crate:main deps:crate_with_macro
359 fn main() {
360     foo$0
361 }
362 ",
363             r"use crate_with_macro::foo;
364
365 fn main() {
366     foo
367 }
368 ",
369         );
370     }
371
372     #[test]
373     fn auto_import_target() {
374         check_assist_target(
375             auto_import,
376             r"
377             struct AssistInfo {
378                 group_label: Option<$0GroupLabel>,
379             }
380
381             mod m { pub struct GroupLabel; }
382             ",
383             "GroupLabel",
384         )
385     }
386
387     #[test]
388     fn not_applicable_when_path_start_is_imported() {
389         check_assist_not_applicable(
390             auto_import,
391             r"
392             pub mod mod1 {
393                 pub mod mod2 {
394                     pub mod mod3 {
395                         pub struct TestStruct;
396                     }
397                 }
398             }
399
400             use mod1::mod2;
401             fn main() {
402                 mod2::mod3::TestStruct$0
403             }
404             ",
405         );
406     }
407
408     #[test]
409     fn not_applicable_for_imported_function() {
410         check_assist_not_applicable(
411             auto_import,
412             r"
413             pub mod test_mod {
414                 pub fn test_function() {}
415             }
416
417             use test_mod::test_function;
418             fn main() {
419                 test_function$0
420             }
421             ",
422         );
423     }
424
425     #[test]
426     fn associated_struct_function() {
427         check_assist(
428             auto_import,
429             r"
430             mod test_mod {
431                 pub struct TestStruct {}
432                 impl TestStruct {
433                     pub fn test_function() {}
434                 }
435             }
436
437             fn main() {
438                 TestStruct::test_function$0
439             }
440             ",
441             r"
442             use test_mod::TestStruct;
443
444             mod test_mod {
445                 pub struct TestStruct {}
446                 impl TestStruct {
447                     pub fn test_function() {}
448                 }
449             }
450
451             fn main() {
452                 TestStruct::test_function
453             }
454             ",
455         );
456     }
457
458     #[test]
459     fn associated_struct_const() {
460         check_assist(
461             auto_import,
462             r"
463             mod test_mod {
464                 pub struct TestStruct {}
465                 impl TestStruct {
466                     const TEST_CONST: u8 = 42;
467                 }
468             }
469
470             fn main() {
471                 TestStruct::TEST_CONST$0
472             }
473             ",
474             r"
475             use test_mod::TestStruct;
476
477             mod test_mod {
478                 pub struct TestStruct {}
479                 impl TestStruct {
480                     const TEST_CONST: u8 = 42;
481                 }
482             }
483
484             fn main() {
485                 TestStruct::TEST_CONST
486             }
487             ",
488         );
489     }
490
491     #[test]
492     fn associated_trait_function() {
493         check_assist(
494             auto_import,
495             r"
496             mod test_mod {
497                 pub trait TestTrait {
498                     fn test_function();
499                 }
500                 pub struct TestStruct {}
501                 impl TestTrait for TestStruct {
502                     fn test_function() {}
503                 }
504             }
505
506             fn main() {
507                 test_mod::TestStruct::test_function$0
508             }
509             ",
510             r"
511             use test_mod::TestTrait;
512
513             mod test_mod {
514                 pub trait TestTrait {
515                     fn test_function();
516                 }
517                 pub struct TestStruct {}
518                 impl TestTrait for TestStruct {
519                     fn test_function() {}
520                 }
521             }
522
523             fn main() {
524                 test_mod::TestStruct::test_function
525             }
526             ",
527         );
528     }
529
530     #[test]
531     fn not_applicable_for_imported_trait_for_function() {
532         check_assist_not_applicable(
533             auto_import,
534             r"
535             mod test_mod {
536                 pub trait TestTrait {
537                     fn test_function();
538                 }
539                 pub trait TestTrait2 {
540                     fn test_function();
541                 }
542                 pub enum TestEnum {
543                     One,
544                     Two,
545                 }
546                 impl TestTrait2 for TestEnum {
547                     fn test_function() {}
548                 }
549                 impl TestTrait for TestEnum {
550                     fn test_function() {}
551                 }
552             }
553
554             use test_mod::TestTrait2;
555             fn main() {
556                 test_mod::TestEnum::test_function$0;
557             }
558             ",
559         )
560     }
561
562     #[test]
563     fn associated_trait_const() {
564         check_assist(
565             auto_import,
566             r"
567             mod test_mod {
568                 pub trait TestTrait {
569                     const TEST_CONST: u8;
570                 }
571                 pub struct TestStruct {}
572                 impl TestTrait for TestStruct {
573                     const TEST_CONST: u8 = 42;
574                 }
575             }
576
577             fn main() {
578                 test_mod::TestStruct::TEST_CONST$0
579             }
580             ",
581             r"
582             use test_mod::TestTrait;
583
584             mod test_mod {
585                 pub trait TestTrait {
586                     const TEST_CONST: u8;
587                 }
588                 pub struct TestStruct {}
589                 impl TestTrait for TestStruct {
590                     const TEST_CONST: u8 = 42;
591                 }
592             }
593
594             fn main() {
595                 test_mod::TestStruct::TEST_CONST
596             }
597             ",
598         );
599     }
600
601     #[test]
602     fn not_applicable_for_imported_trait_for_const() {
603         check_assist_not_applicable(
604             auto_import,
605             r"
606             mod test_mod {
607                 pub trait TestTrait {
608                     const TEST_CONST: u8;
609                 }
610                 pub trait TestTrait2 {
611                     const TEST_CONST: f64;
612                 }
613                 pub enum TestEnum {
614                     One,
615                     Two,
616                 }
617                 impl TestTrait2 for TestEnum {
618                     const TEST_CONST: f64 = 42.0;
619                 }
620                 impl TestTrait for TestEnum {
621                     const TEST_CONST: u8 = 42;
622                 }
623             }
624
625             use test_mod::TestTrait2;
626             fn main() {
627                 test_mod::TestEnum::TEST_CONST$0;
628             }
629             ",
630         )
631     }
632
633     #[test]
634     fn trait_method() {
635         check_assist(
636             auto_import,
637             r"
638             mod test_mod {
639                 pub trait TestTrait {
640                     fn test_method(&self);
641                 }
642                 pub struct TestStruct {}
643                 impl TestTrait for TestStruct {
644                     fn test_method(&self) {}
645                 }
646             }
647
648             fn main() {
649                 let test_struct = test_mod::TestStruct {};
650                 test_struct.test_meth$0od()
651             }
652             ",
653             r"
654             use test_mod::TestTrait;
655
656             mod test_mod {
657                 pub trait TestTrait {
658                     fn test_method(&self);
659                 }
660                 pub struct TestStruct {}
661                 impl TestTrait for TestStruct {
662                     fn test_method(&self) {}
663                 }
664             }
665
666             fn main() {
667                 let test_struct = test_mod::TestStruct {};
668                 test_struct.test_method()
669             }
670             ",
671         );
672     }
673
674     #[test]
675     fn trait_method_cross_crate() {
676         check_assist(
677             auto_import,
678             r"
679             //- /main.rs crate:main deps:dep
680             fn main() {
681                 let test_struct = dep::test_mod::TestStruct {};
682                 test_struct.test_meth$0od()
683             }
684             //- /dep.rs crate:dep
685             pub mod test_mod {
686                 pub trait TestTrait {
687                     fn test_method(&self);
688                 }
689                 pub struct TestStruct {}
690                 impl TestTrait for TestStruct {
691                     fn test_method(&self) {}
692                 }
693             }
694             ",
695             r"
696             use dep::test_mod::TestTrait;
697
698             fn main() {
699                 let test_struct = dep::test_mod::TestStruct {};
700                 test_struct.test_method()
701             }
702             ",
703         );
704     }
705
706     #[test]
707     fn assoc_fn_cross_crate() {
708         check_assist(
709             auto_import,
710             r"
711             //- /main.rs crate:main deps:dep
712             fn main() {
713                 dep::test_mod::TestStruct::test_func$0tion
714             }
715             //- /dep.rs crate:dep
716             pub mod test_mod {
717                 pub trait TestTrait {
718                     fn test_function();
719                 }
720                 pub struct TestStruct {}
721                 impl TestTrait for TestStruct {
722                     fn test_function() {}
723                 }
724             }
725             ",
726             r"
727             use dep::test_mod::TestTrait;
728
729             fn main() {
730                 dep::test_mod::TestStruct::test_function
731             }
732             ",
733         );
734     }
735
736     #[test]
737     fn assoc_const_cross_crate() {
738         check_assist(
739             auto_import,
740             r"
741             //- /main.rs crate:main deps:dep
742             fn main() {
743                 dep::test_mod::TestStruct::CONST$0
744             }
745             //- /dep.rs crate:dep
746             pub mod test_mod {
747                 pub trait TestTrait {
748                     const CONST: bool;
749                 }
750                 pub struct TestStruct {}
751                 impl TestTrait for TestStruct {
752                     const CONST: bool = true;
753                 }
754             }
755             ",
756             r"
757             use dep::test_mod::TestTrait;
758
759             fn main() {
760                 dep::test_mod::TestStruct::CONST
761             }
762             ",
763         );
764     }
765
766     #[test]
767     fn assoc_fn_as_method_cross_crate() {
768         check_assist_not_applicable(
769             auto_import,
770             r"
771             //- /main.rs crate:main deps:dep
772             fn main() {
773                 let test_struct = dep::test_mod::TestStruct {};
774                 test_struct.test_func$0tion()
775             }
776             //- /dep.rs crate:dep
777             pub mod test_mod {
778                 pub trait TestTrait {
779                     fn test_function();
780                 }
781                 pub struct TestStruct {}
782                 impl TestTrait for TestStruct {
783                     fn test_function() {}
784                 }
785             }
786             ",
787         );
788     }
789
790     #[test]
791     fn private_trait_cross_crate() {
792         check_assist_not_applicable(
793             auto_import,
794             r"
795             //- /main.rs crate:main deps:dep
796             fn main() {
797                 let test_struct = dep::test_mod::TestStruct {};
798                 test_struct.test_meth$0od()
799             }
800             //- /dep.rs crate:dep
801             pub mod test_mod {
802                 trait TestTrait {
803                     fn test_method(&self);
804                 }
805                 pub struct TestStruct {}
806                 impl TestTrait for TestStruct {
807                     fn test_method(&self) {}
808                 }
809             }
810             ",
811         );
812     }
813
814     #[test]
815     fn not_applicable_for_imported_trait_for_method() {
816         check_assist_not_applicable(
817             auto_import,
818             r"
819             mod test_mod {
820                 pub trait TestTrait {
821                     fn test_method(&self);
822                 }
823                 pub trait TestTrait2 {
824                     fn test_method(&self);
825                 }
826                 pub enum TestEnum {
827                     One,
828                     Two,
829                 }
830                 impl TestTrait2 for TestEnum {
831                     fn test_method(&self) {}
832                 }
833                 impl TestTrait for TestEnum {
834                     fn test_method(&self) {}
835                 }
836             }
837
838             use test_mod::TestTrait2;
839             fn main() {
840                 let one = test_mod::TestEnum::One;
841                 one.test$0_method();
842             }
843             ",
844         )
845     }
846
847     #[test]
848     fn dep_import() {
849         check_assist(
850             auto_import,
851             r"
852 //- /lib.rs crate:dep
853 pub struct Struct;
854
855 //- /main.rs crate:main deps:dep
856 fn main() {
857     Struct$0
858 }
859 ",
860             r"use dep::Struct;
861
862 fn main() {
863     Struct
864 }
865 ",
866         );
867     }
868
869     #[test]
870     fn whole_segment() {
871         // Tests that only imports whose last segment matches the identifier get suggested.
872         check_assist(
873             auto_import,
874             r"
875 //- /lib.rs crate:dep
876 pub mod fmt {
877     pub trait Display {}
878 }
879
880 pub fn panic_fmt() {}
881
882 //- /main.rs crate:main deps:dep
883 struct S;
884
885 impl f$0mt::Display for S {}
886 ",
887             r"use dep::fmt;
888
889 struct S;
890
891 impl fmt::Display for S {}
892 ",
893         );
894     }
895
896     #[test]
897     fn macro_generated() {
898         // Tests that macro-generated items are suggested from external crates.
899         check_assist(
900             auto_import,
901             r"
902 //- /lib.rs crate:dep
903 macro_rules! mac {
904     () => {
905         pub struct Cheese;
906     };
907 }
908
909 mac!();
910
911 //- /main.rs crate:main deps:dep
912 fn main() {
913     Cheese$0;
914 }
915 ",
916             r"use dep::Cheese;
917
918 fn main() {
919     Cheese;
920 }
921 ",
922         );
923     }
924
925     #[test]
926     fn casing() {
927         // Tests that differently cased names don't interfere and we only suggest the matching one.
928         check_assist(
929             auto_import,
930             r"
931 //- /lib.rs crate:dep
932 pub struct FMT;
933 pub struct fmt;
934
935 //- /main.rs crate:main deps:dep
936 fn main() {
937     FMT$0;
938 }
939 ",
940             r"use dep::FMT;
941
942 fn main() {
943     FMT;
944 }
945 ",
946         );
947     }
948
949     #[test]
950     fn inner_items() {
951         check_assist(
952             auto_import,
953             r#"
954 mod baz {
955     pub struct Foo {}
956 }
957
958 mod bar {
959     fn bar() {
960         Foo$0;
961         println!("Hallo");
962     }
963 }
964 "#,
965             r#"
966 mod baz {
967     pub struct Foo {}
968 }
969
970 mod bar {
971     use crate::baz::Foo;
972
973     fn bar() {
974         Foo;
975         println!("Hallo");
976     }
977 }
978 "#,
979         );
980     }
981
982     #[test]
983     fn uses_abs_path_with_extern_crate_clash() {
984         cov_mark::check!(ambiguous_crate_start);
985         check_assist(
986             auto_import,
987             r#"
988 //- /main.rs crate:main deps:foo
989 mod foo {}
990
991 const _: () = {
992     Foo$0
993 };
994 //- /foo.rs crate:foo
995 pub struct Foo
996 "#,
997             r#"
998 use ::foo::Foo;
999
1000 mod foo {}
1001
1002 const _: () = {
1003     Foo
1004 };
1005 "#,
1006         );
1007     }
1008
1009     #[test]
1010     fn works_on_ident_patterns() {
1011         check_assist(
1012             auto_import,
1013             r#"
1014 mod foo {
1015     pub struct Foo {}
1016 }
1017 fn foo() {
1018     let Foo$0;
1019 }
1020 "#,
1021             r#"
1022 use foo::Foo;
1023
1024 mod foo {
1025     pub struct Foo {}
1026 }
1027 fn foo() {
1028     let Foo;
1029 }
1030 "#,
1031         );
1032     }
1033 }