@@ -243,6 +243,11 @@ fn hover_ranged(
243243 } ) ?;
244244 let res = match & expr_or_pat {
245245 Either :: Left ( ast:: Expr :: TryExpr ( try_expr) ) => hover_try_expr ( sema, config, try_expr) ,
246+ Either :: Left ( ast:: Expr :: PrefixExpr ( prefix_expr) )
247+ if prefix_expr. op_kind ( ) == Some ( ast:: UnaryOp :: Deref ) =>
248+ {
249+ hover_deref_expr ( sema, config, prefix_expr)
250+ }
246251 _ => None ,
247252 } ;
248253 let res = res. or_else ( || hover_type_info ( sema, config, & expr_or_pat) ) ;
@@ -346,6 +351,70 @@ fn hover_try_expr(
346351 Some ( res)
347352}
348353
354+ fn hover_deref_expr (
355+ sema : & Semantics < RootDatabase > ,
356+ config : & HoverConfig ,
357+ deref_expr : & ast:: PrefixExpr ,
358+ ) -> Option < HoverResult > {
359+ let inner_ty = sema. type_of_expr ( & deref_expr. expr ( ) ?) ?. original ;
360+ let TypeInfo { original, adjusted } =
361+ sema. type_of_expr ( & ast:: Expr :: from ( deref_expr. clone ( ) ) ) ?;
362+
363+ let mut res = HoverResult :: default ( ) ;
364+ let mut targets: Vec < hir:: ModuleDef > = Vec :: new ( ) ;
365+ let mut push_new_def = |item : hir:: ModuleDef | {
366+ if !targets. contains ( & item) {
367+ targets. push ( item) ;
368+ }
369+ } ;
370+ walk_and_push_ty ( sema. db , & inner_ty, & mut push_new_def) ;
371+ walk_and_push_ty ( sema. db , & original, & mut push_new_def) ;
372+
373+ res. markup = if let Some ( adjusted_ty) = adjusted {
374+ walk_and_push_ty ( sema. db , & adjusted_ty, & mut push_new_def) ;
375+ let original = original. display ( sema. db ) . to_string ( ) ;
376+ let adjusted = adjusted_ty. display ( sema. db ) . to_string ( ) ;
377+ let inner = inner_ty. display ( sema. db ) . to_string ( ) ;
378+ let type_len = "To type: " . len ( ) ;
379+ let coerced_len = "Coerced to: " . len ( ) ;
380+ let deref_len = "Dereferenced from: " . len ( ) ;
381+ let max_len = ( original. len ( ) + type_len)
382+ . max ( adjusted. len ( ) + coerced_len)
383+ . max ( inner. len ( ) + deref_len) ;
384+ format ! (
385+ "{bt_start}Dereferenced from: {:>ipad$}\n To type: {:>apad$}\n Coerced to: {:>opad$}\n {bt_end}" ,
386+ inner,
387+ original,
388+ adjusted,
389+ ipad = max_len - deref_len,
390+ apad = max_len - type_len,
391+ opad = max_len - coerced_len,
392+ bt_start = if config. markdown( ) { "```text\n " } else { "" } ,
393+ bt_end = if config. markdown( ) { "```\n " } else { "" }
394+ )
395+ . into ( )
396+ } else {
397+ let original = original. display ( sema. db ) . to_string ( ) ;
398+ let inner = inner_ty. display ( sema. db ) . to_string ( ) ;
399+ let type_len = "To type: " . len ( ) ;
400+ let deref_len = "Dereferenced from: " . len ( ) ;
401+ let max_len = ( original. len ( ) + type_len) . max ( inner. len ( ) + deref_len) ;
402+ format ! (
403+ "{bt_start}Dereferenced from: {:>ipad$}\n To type: {:>apad$}\n {bt_end}" ,
404+ inner,
405+ original,
406+ ipad = max_len - deref_len,
407+ apad = max_len - type_len,
408+ bt_start = if config. markdown( ) { "```text\n " } else { "" } ,
409+ bt_end = if config. markdown( ) { "```\n " } else { "" }
410+ )
411+ . into ( )
412+ } ;
413+ res. actions . push ( HoverAction :: goto_type_from_targets ( sema. db , targets) ) ;
414+
415+ Some ( res)
416+ }
417+
349418fn hover_type_info (
350419 sema : & Semantics < RootDatabase > ,
351420 config : & HoverConfig ,
@@ -4647,4 +4716,71 @@ fn foo() -> Option<()> {
46474716 ```"# ] ] ,
46484717 ) ;
46494718 }
4719+
4720+ #[ test]
4721+ fn hover_deref_expr ( ) {
4722+ check_hover_range (
4723+ r#"
4724+ //- minicore: deref
4725+ use core::ops::Deref;
4726+
4727+ struct DerefExample<T> {
4728+ value: T
4729+ }
4730+
4731+ impl<T> Deref for DerefExample<T> {
4732+ type Target = T;
4733+
4734+ fn deref(&self) -> &Self::Target {
4735+ &self.value
4736+ }
4737+ }
4738+
4739+ fn foo() {
4740+ let x = DerefExample { value: 0 };
4741+ let y: i32 = $0*x$0;
4742+ }
4743+ "# ,
4744+ expect ! [ [ r#"
4745+ ```text
4746+ Dereferenced from: DerefExample<i32>
4747+ To type: i32
4748+ ```
4749+ "# ] ] ,
4750+ ) ;
4751+ }
4752+
4753+ #[ test]
4754+ fn hover_deref_expr_with_coercion ( ) {
4755+ check_hover_range (
4756+ r#"
4757+ //- minicore: deref
4758+ use core::ops::Deref;
4759+
4760+ struct DerefExample<T> {
4761+ value: T
4762+ }
4763+
4764+ impl<T> Deref for DerefExample<T> {
4765+ type Target = T;
4766+
4767+ fn deref(&self) -> &Self::Target {
4768+ &self.value
4769+ }
4770+ }
4771+
4772+ fn foo() {
4773+ let x = DerefExample { value: &&&&&0 };
4774+ let y: &i32 = $0*x$0;
4775+ }
4776+ "# ,
4777+ expect ! [ [ r#"
4778+ ```text
4779+ Dereferenced from: DerefExample<&&&&&i32>
4780+ To type: &&&&&i32
4781+ Coerced to: &i32
4782+ ```
4783+ "# ] ] ,
4784+ ) ;
4785+ }
46504786}
0 commit comments