@@ -377,14 +377,34 @@ impl SourceAnalyzer {
377377 db : & dyn HirDatabase ,
378378 prefix_expr : & ast:: PrefixExpr ,
379379 ) -> Option < FunctionId > {
380- let ( lang_item, fn_name) = match prefix_expr. op_kind ( ) ? {
381- ast:: UnaryOp :: Deref => ( LangItem :: Deref , name ! [ deref] ) ,
382- ast:: UnaryOp :: Not => ( LangItem :: Not , name ! [ not] ) ,
383- ast:: UnaryOp :: Neg => ( LangItem :: Neg , name ! [ neg] ) ,
380+ let ( op_trait, op_fn) = match prefix_expr. op_kind ( ) ? {
381+ ast:: UnaryOp :: Deref => {
382+ // This can be either `Deref::deref` or `DerefMut::deref_mut`.
383+ // Since deref kind is inferenced and stored in `InferenceResult.method_resolution`,
384+ // use that result to find out which one it is.
385+ let ( deref_trait, deref) =
386+ self . lang_trait_fn ( db, LangItem :: Deref , & name ! [ deref] ) ?;
387+ self . infer
388+ . as_ref ( )
389+ . and_then ( |infer| {
390+ let expr = self . expr_id ( db, & prefix_expr. clone ( ) . into ( ) ) ?;
391+ let ( func, _) = infer. method_resolution ( expr) ?;
392+ let ( deref_mut_trait, deref_mut) =
393+ self . lang_trait_fn ( db, LangItem :: DerefMut , & name ! [ deref_mut] ) ?;
394+ if func == deref_mut {
395+ Some ( ( deref_mut_trait, deref_mut) )
396+ } else {
397+ None
398+ }
399+ } )
400+ . unwrap_or ( ( deref_trait, deref) )
401+ }
402+ ast:: UnaryOp :: Not => self . lang_trait_fn ( db, LangItem :: Not , & name ! [ not] ) ?,
403+ ast:: UnaryOp :: Neg => self . lang_trait_fn ( db, LangItem :: Neg , & name ! [ neg] ) ?,
384404 } ;
405+
385406 let ty = self . ty_of_expr ( db, & prefix_expr. expr ( ) ?) ?;
386407
387- let ( op_trait, op_fn) = self . lang_trait_fn ( db, lang_item, & fn_name) ?;
388408 // HACK: subst for all methods coincides with that for their trait because the methods
389409 // don't have any generic parameters, so we skip building another subst for the methods.
390410 let substs = hir_ty:: TyBuilder :: subst_for_def ( db, op_trait, None ) . push ( ty. clone ( ) ) . build ( ) ;
0 commit comments