about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-05-13 11:02:57 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-05-13 11:02:57 +0200
commitedd60f7b0d02e85a9c0ee60620cb3347b37e5fdf (patch)
tree4b39740ac2523b74e1b4fd9ed8c116ce6057b50b
parent730286b523c23170630142b6ebba0677a9aedae9 (diff)
downloadrust-edd60f7b0d02e85a9c0ee60620cb3347b37e5fdf.tar.gz
rust-edd60f7b0d02e85a9c0ee60620cb3347b37e5fdf.zip
Simplify bind pat filtering
-rw-r--r--crates/ide/src/inlay_hints/bind_pat.rs103
1 files changed, 32 insertions, 71 deletions
diff --git a/crates/ide/src/inlay_hints/bind_pat.rs b/crates/ide/src/inlay_hints/bind_pat.rs
index f98cc129a93..3d5122a7cf3 100644
--- a/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/crates/ide/src/inlay_hints/bind_pat.rs
@@ -3,7 +3,7 @@
 //! fn f(a: i32, b: i32) -> i32 { a + b }
 //! let _x /* i32 */= f(4, 4);
 //! ```
-use hir::{Semantics, TypeInfo};
+use hir::Semantics;
 use ide_db::{base_db::FileId, famous_defs::FamousDefs, RootDatabase};
 
 use itertools::Itertools;
@@ -28,11 +28,41 @@ pub(super) fn hints(
         return None;
     }
 
+    let parent = pat.syntax().parent()?;
+    let type_ascriptable = match_ast! {
+        match parent {
+            ast::Param(it) => {
+                if it.ty().is_some() {
+                    return None;
+                }
+                Some(it.colon_token())
+            },
+            ast::LetStmt(it) => {
+                if config.hide_closure_initialization_hints {
+                    if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
+                        if closure_has_block_body(&closure) {
+                            return None;
+                        }
+                    }
+                }
+                if it.ty().is_some() {
+                    return None;
+                }
+                Some(it.colon_token())
+            },
+            _ => None
+        }
+    };
+
     let descended = sema.descend_node_into_attributes(pat.clone()).pop();
     let desc_pat = descended.as_ref().unwrap_or(pat);
     let ty = sema.type_of_binding_in_pat(desc_pat)?;
 
-    if should_not_display_type_hint(sema, config, pat, &ty) {
+    if ty.is_unknown() {
+        return None;
+    }
+
+    if sema.resolve_bind_pat_to_const(pat).is_some() {
         return None;
     }
 
@@ -44,11 +74,6 @@ pub(super) fn hints(
         return None;
     }
 
-    let type_ascriptable = desc_pat.syntax().parent().and_then(|it| {
-        ast::LetStmt::cast(it.clone())
-            .map(|it| it.colon_token())
-            .or_else(|| ast::Param::cast(it).map(|it| it.colon_token()))
-    });
     let text_edit = if let Some(colon_token) = &type_ascriptable {
         ty_to_text_edit(
             sema,
@@ -89,57 +114,6 @@ pub(super) fn hints(
     Some(())
 }
 
-fn should_not_display_type_hint(
-    sema: &Semantics<'_, RootDatabase>,
-    config: &InlayHintsConfig,
-    bind_pat: &ast::IdentPat,
-    pat_ty: &hir::Type,
-) -> bool {
-    let db = sema.db;
-
-    if pat_ty.is_unknown() {
-        return true;
-    }
-
-    if sema.resolve_bind_pat_to_const(bind_pat).is_some() {
-        return true;
-    }
-
-    for node in bind_pat.syntax().ancestors() {
-        match_ast! {
-            match node {
-                ast::LetStmt(it) => {
-                    if config.hide_closure_initialization_hints {
-                        if let Some(ast::Expr::ClosureExpr(closure)) = it.initializer() {
-                            if closure_has_block_body(&closure) {
-                                return true;
-                            }
-                        }
-                    }
-                    return it.ty().is_some()
-                },
-                // FIXME: We might wanna show type hints in parameters for non-top level patterns as well
-                ast::Param(it) => return it.ty().is_some(),
-                ast::MatchArm(_) => return pat_is_enum_variant(db, bind_pat, pat_ty),
-                ast::LetExpr(_) => return pat_is_enum_variant(db, bind_pat, pat_ty),
-                ast::IfExpr(_) => return false,
-                ast::WhileExpr(_) => return false,
-                ast::ForExpr(it) => {
-                    // We *should* display hint only if user provided "in {expr}" and we know the type of expr (and it's not unit).
-                    // Type of expr should be iterable.
-                    return it.in_token().is_none() ||
-                        it.iterable()
-                            .and_then(|iterable_expr| sema.type_of_expr(&iterable_expr))
-                            .map(TypeInfo::original)
-                            .map_or(true, |iterable_ty| iterable_ty.is_unknown() || iterable_ty.is_unit())
-                },
-                _ => (),
-            }
-        }
-    }
-    false
-}
-
 fn is_named_constructor(
     sema: &Semantics<'_, RootDatabase>,
     pat: &ast::IdentPat,
@@ -193,19 +167,6 @@ fn is_named_constructor(
     (ctor_name == ty_name).then_some(())
 }
 
-fn pat_is_enum_variant(db: &RootDatabase, bind_pat: &ast::IdentPat, pat_ty: &hir::Type) -> bool {
-    if let Some(hir::Adt::Enum(enum_data)) = pat_ty.as_adt() {
-        let pat_text = bind_pat.to_string();
-        enum_data
-            .variants(db)
-            .into_iter()
-            .map(|variant| variant.name(db).to_smol_str())
-            .any(|enum_name| enum_name == pat_text)
-    } else {
-        false
-    }
-}
-
 #[cfg(test)]
 mod tests {
     // This module also contains tests for super::closure_ret