From e29c49a7fa1438a7bd7a25cbc3fe9ca6409c29ce Mon Sep 17 00:00:00 2001 From: Chris Emery Date: Thu, 25 Nov 2021 15:45:42 -0800 Subject: [PATCH 1/2] Worked issue #10446 hide "obvious" inlays The suggested method in the issue didn't work because that code path appears not to be hit during the generation of these types. Instead I introduced a new concept of unambigious types as part of let statements and filtered out cases that the issue seemed to be pointing at. There were two tests that seemed to depend on the old behavior that I cleaned up in order to bring into alignment with the new behavior, this --- crates/ide/src/inlay_hints.rs | 66 ++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 985d3a4eccac..45d36fd4477f 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -1,5 +1,5 @@ use either::Either; -use hir::{known, Callable, HasVisibility, HirDisplay, Semantics, TypeInfo}; +use hir::{known, Callable, CallableKind, HasVisibility, HirDisplay, Semantics, TypeInfo}; use ide_db::RootDatabase; use ide_db::{base_db::FileRange, helpers::FamousDefs}; use itertools::Itertools; @@ -374,7 +374,7 @@ fn should_not_display_type_hint( for node in bind_pat.syntax().ancestors() { match_ast! { match node { - ast::LetStmt(it) => return it.ty().is_some(), + ast::LetStmt(it) => return is_unambigious_type(sema, it), ast::Param(it) => return it.ty().is_some(), ast::MatchArm(_it) => return pat_is_enum_variant(db, bind_pat, pat_ty), ast::IfExpr(it) => { @@ -401,6 +401,43 @@ fn should_not_display_type_hint( false } +fn is_unambigious_type(sema: &Semantics, let_stmt: ast::LetStmt) -> bool { + let default = let_stmt.ty().is_some(); + let initializer = let_stmt.initializer(); + let initializer = + if let Some(initializer) = initializer { initializer } else { return default }; + let (callable, _arg_list) = if let Some(callable) = get_callable(sema, &initializer) { + callable + } else { + return default; + }; + match callable.kind() { + CallableKind::TupleEnumVariant(_) => true, + CallableKind::TupleStruct(_) => { + if let ast::Expr::CallExpr(call) = initializer { + if let Some(ast::Expr::PathExpr(path_expr)) = call.expr() { + if let Some(path) = path_expr.path() { + if let Some(args) = path.segments().find_map(|s| s.generic_arg_list()) { + return args + .generic_args() + .filter_map(|a| match a { + ast::GenericArg::TypeArg(type_arg) => type_arg.ty(), + ast::GenericArg::AssocTypeArg(assoc_type_arg) => { + assoc_type_arg.ty() + } + _ => None, + }) + .all(|ty| !matches!(ty, ast::Type::InferType(_))); + } + } + } + } + default + } + _ => default, + } +} + fn should_hide_param_name_hint( sema: &Semantics, callable: &hir::Callable, @@ -921,6 +958,29 @@ fn main() { ); } + #[test] + fn hide_type_hints_tuple_generics() { + check_types( + r#" +struct Struct(T, U); + +enum Enum { + Variant(u32) +} + +fn main() { + let foo = Struct::(0, 0); + let foo = Enum::Variant(0); + let foo = Struct(1, 2); + //^^^ Struct + bar(foo); +} + +fn bar(foo: Struct) {} +"#, + ) + } + #[test] fn type_hints_bindings_after_at() { check_types( @@ -1154,7 +1214,6 @@ struct Test { a: Option, b: u8 } fn main() { let test = Some(Test { a: Some(3), b: 1 }); - //^^^^ Option if let None = &test {}; if let test = &test {}; //^^^^ &Option @@ -1184,7 +1243,6 @@ struct Test { a: Option, b: u8 } fn main() { let test = Some(Test { a: Some(3), b: 1 }); - //^^^^ Option while let Some(Test { a: Some(x), b: y }) = &test {}; //^ &u32 ^ &u8 }"#, From 3c6ae3669b1a6c59f92af9560a4ecc71b93260c9 Mon Sep 17 00:00:00 2001 From: Chris Emery Date: Thu, 25 Nov 2021 16:16:51 -0800 Subject: [PATCH 2/2] Switched function type to allow usage of ? This cleans up several if liet statements but... --- crates/ide/src/inlay_hints.rs | 50 +++++++++++++++-------------------- 1 file changed, 21 insertions(+), 29 deletions(-) diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 45d36fd4477f..44a7eeaddeac 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -374,7 +374,7 @@ fn should_not_display_type_hint( for node in bind_pat.syntax().ancestors() { match_ast! { match node { - ast::LetStmt(it) => return is_unambigious_type(sema, it), + ast::LetStmt(it) => return is_unambigious_type(sema, it).is_some(), ast::Param(it) => return it.ty().is_some(), ast::MatchArm(_it) => return pat_is_enum_variant(db, bind_pat, pat_ty), ast::IfExpr(it) => { @@ -401,40 +401,32 @@ fn should_not_display_type_hint( false } -fn is_unambigious_type(sema: &Semantics, let_stmt: ast::LetStmt) -> bool { - let default = let_stmt.ty().is_some(); - let initializer = let_stmt.initializer(); - let initializer = - if let Some(initializer) = initializer { initializer } else { return default }; - let (callable, _arg_list) = if let Some(callable) = get_callable(sema, &initializer) { - callable - } else { - return default; - }; +fn is_unambigious_type(sema: &Semantics, let_stmt: ast::LetStmt) -> Option<()> { + if let_stmt.ty().is_some() { + return Some(()); + } + let initializer = let_stmt.initializer()?; + let (callable, _arg_list) = get_callable(sema, &initializer)?; match callable.kind() { - CallableKind::TupleEnumVariant(_) => true, + CallableKind::TupleEnumVariant(_) => Some(()), CallableKind::TupleStruct(_) => { if let ast::Expr::CallExpr(call) = initializer { - if let Some(ast::Expr::PathExpr(path_expr)) = call.expr() { - if let Some(path) = path_expr.path() { - if let Some(args) = path.segments().find_map(|s| s.generic_arg_list()) { - return args - .generic_args() - .filter_map(|a| match a { - ast::GenericArg::TypeArg(type_arg) => type_arg.ty(), - ast::GenericArg::AssocTypeArg(assoc_type_arg) => { - assoc_type_arg.ty() - } - _ => None, - }) - .all(|ty| !matches!(ty, ast::Type::InferType(_))); - } - } + if let ast::Expr::PathExpr(path_expr) = call.expr()? { + let args = path_expr.path()?.segments().find_map(|s| s.generic_arg_list())?; + let unambigious = args + .generic_args() + .filter_map(|a| match a { + ast::GenericArg::TypeArg(type_arg) => type_arg.ty(), + ast::GenericArg::AssocTypeArg(assoc_type_arg) => assoc_type_arg.ty(), + _ => None, + }) + .all(|ty| !matches!(ty, ast::Type::InferType(_))); + return if unambigious { Some(()) } else { None }; } } - default + None } - _ => default, + _ => None, } }