@@ -35,53 +35,20 @@ pub(super) fn type_info_of(
35
35
_config : & HoverConfig ,
36
36
expr_or_pat : & Either < ast:: Expr , ast:: Pat > ,
37
37
) -> Option < HoverResult > {
38
- let TypeInfo { original , adjusted } = match expr_or_pat {
38
+ let ty_info = match expr_or_pat {
39
39
Either :: Left ( expr) => sema. type_of_expr ( expr) ?,
40
40
Either :: Right ( pat) => sema. type_of_pat ( pat) ?,
41
41
} ;
42
- type_info ( sema, _config, original , adjusted )
42
+ type_info ( sema, _config, ty_info )
43
43
}
44
44
45
45
pub ( super ) fn closure_expr (
46
46
sema : & Semantics < ' _ , RootDatabase > ,
47
47
config : & HoverConfig ,
48
48
c : ast:: ClosureExpr ,
49
49
) -> Option < HoverResult > {
50
- let ty = & sema. type_of_expr ( & c. into ( ) ) ?. original ;
51
- let layout = if config. memory_layout {
52
- ty. layout ( sema. db )
53
- . map ( |x| format ! ( " // size = {}, align = {}" , x. size. bytes( ) , x. align. abi. bytes( ) ) )
54
- . unwrap_or_default ( )
55
- } else {
56
- String :: default ( )
57
- } ;
58
- let c = ty. as_closure ( ) ?;
59
- let mut captures = c
60
- . captured_items ( sema. db )
61
- . into_iter ( )
62
- . map ( |it| {
63
- let borrow_kind= match it. kind ( ) {
64
- CaptureKind :: SharedRef => "immutable borrow" ,
65
- CaptureKind :: UniqueSharedRef => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))" ,
66
- CaptureKind :: MutableRef => "mutable borrow" ,
67
- CaptureKind :: Move => "move" ,
68
- } ;
69
- format ! ( "* `{}` by {}" , it. display_place( sema. db) , borrow_kind)
70
- } )
71
- . join ( "\n " ) ;
72
- if captures. trim ( ) . is_empty ( ) {
73
- captures = "This closure captures nothing" . to_string ( ) ;
74
- }
75
- let mut res = HoverResult :: default ( ) ;
76
- res. markup = format ! (
77
- "```rust\n {}{}\n {}\n ```\n \n ## Captures\n {}" ,
78
- c. display_with_id( sema. db) ,
79
- layout,
80
- c. display_with_impl( sema. db) ,
81
- captures,
82
- )
83
- . into ( ) ;
84
- Some ( res)
50
+ let TypeInfo { original, .. } = sema. type_of_expr ( & c. into ( ) ) ?;
51
+ closure_ty ( sema, config, & TypeInfo { original, adjusted : None } )
85
52
}
86
53
87
54
pub ( super ) fn try_expr (
@@ -522,10 +489,13 @@ pub(super) fn definition(
522
489
523
490
fn type_info (
524
491
sema : & Semantics < ' _ , RootDatabase > ,
525
- _config : & HoverConfig ,
526
- original : hir:: Type ,
527
- adjusted : Option < hir:: Type > ,
492
+ config : & HoverConfig ,
493
+ ty : TypeInfo ,
528
494
) -> Option < HoverResult > {
495
+ if let Some ( res) = closure_ty ( sema, config, & ty) {
496
+ return Some ( res) ;
497
+ } ;
498
+ let TypeInfo { original, adjusted } = ty;
529
499
let mut res = HoverResult :: default ( ) ;
530
500
let mut targets: Vec < hir:: ModuleDef > = Vec :: new ( ) ;
531
501
let mut push_new_def = |item : hir:: ModuleDef | {
@@ -555,6 +525,69 @@ fn type_info(
555
525
Some ( res)
556
526
}
557
527
528
+ fn closure_ty (
529
+ sema : & Semantics < ' _ , RootDatabase > ,
530
+ config : & HoverConfig ,
531
+ TypeInfo { original, adjusted } : & TypeInfo ,
532
+ ) -> Option < HoverResult > {
533
+ let c = original. as_closure ( ) ?;
534
+ let layout = if config. memory_layout {
535
+ original
536
+ . layout ( sema. db )
537
+ . map ( |x| format ! ( " // size = {}, align = {}" , x. size. bytes( ) , x. align. abi. bytes( ) ) )
538
+ . unwrap_or_default ( )
539
+ } else {
540
+ String :: default ( )
541
+ } ;
542
+ let mut captures_rendered = c. captured_items ( sema. db )
543
+ . into_iter ( )
544
+ . map ( |it| {
545
+ let borrow_kind = match it. kind ( ) {
546
+ CaptureKind :: SharedRef => "immutable borrow" ,
547
+ CaptureKind :: UniqueSharedRef => "unique immutable borrow ([read more](https://doc.rust-lang.org/stable/reference/types/closure.html#unique-immutable-borrows-in-captures))" ,
548
+ CaptureKind :: MutableRef => "mutable borrow" ,
549
+ CaptureKind :: Move => "move" ,
550
+ } ;
551
+ format ! ( "* `{}` by {}" , it. display_place( sema. db) , borrow_kind)
552
+ } )
553
+ . join ( "\n " ) ;
554
+ if captures_rendered. trim ( ) . is_empty ( ) {
555
+ captures_rendered = "This closure captures nothing" . to_string ( ) ;
556
+ }
557
+ let mut targets: Vec < hir:: ModuleDef > = Vec :: new ( ) ;
558
+ let mut push_new_def = |item : hir:: ModuleDef | {
559
+ if !targets. contains ( & item) {
560
+ targets. push ( item) ;
561
+ }
562
+ } ;
563
+ walk_and_push_ty ( sema. db , original, & mut push_new_def) ;
564
+ c. capture_types ( sema. db ) . into_iter ( ) . for_each ( |ty| {
565
+ walk_and_push_ty ( sema. db , & ty, & mut push_new_def) ;
566
+ } ) ;
567
+
568
+ let adjusted = if let Some ( adjusted_ty) = adjusted {
569
+ walk_and_push_ty ( sema. db , & adjusted_ty, & mut push_new_def) ;
570
+ format ! (
571
+ "\n Coerced to: {}" ,
572
+ adjusted_ty. display( sema. db) . with_closure_style( hir:: ClosureStyle :: ImplFn )
573
+ )
574
+ } else {
575
+ String :: new ( )
576
+ } ;
577
+
578
+ let mut res = HoverResult :: default ( ) ;
579
+ res. actions . push ( HoverAction :: goto_type_from_targets ( sema. db , targets) ) ;
580
+ res. markup = format ! (
581
+ "```rust\n {}{}\n {}\n ```{adjusted}\n \n ## Captures\n {}" ,
582
+ c. display_with_id( sema. db) ,
583
+ layout,
584
+ c. display_with_impl( sema. db) ,
585
+ captures_rendered,
586
+ )
587
+ . into ( ) ;
588
+ Some ( res)
589
+ }
590
+
558
591
fn render_builtin_attr ( db : & RootDatabase , attr : hir:: BuiltinAttr ) -> Option < Markup > {
559
592
let name = attr. name ( db) ;
560
593
let desc = format ! ( "#[{name}]" ) ;
0 commit comments