Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13885 - Veykril:bin-op-adjust, r=Veykril
Skip lifetime elision on fn pointers and fn trait types These currently don't work correctly, so it's better to not render them at all there
bors 2023-01-03
parent 50801b7 · parent b996a54 · commit 5033213
-rw-r--r--crates/hir-ty/src/infer/expr.rs1
-rw-r--r--crates/ide-assists/src/handlers/add_explicit_type.rs5
-rw-r--r--crates/ide-assists/src/handlers/extract_type_alias.rs120
-rw-r--r--crates/ide-db/src/syntax_helpers/node_ext.rs9
-rw-r--r--crates/ide/src/inlay_hints/fn_lifetime_fn.rs30
5 files changed, 100 insertions, 65 deletions
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 2e5c424410..a015f67024 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -334,6 +334,7 @@ impl<'a> InferenceContext<'a> {
let (param_tys, ret_ty) = match res {
Some(res) => {
let adjustments = auto_deref_adjust_steps(&derefs);
+ // FIXME: Handle call adjustments for Fn/FnMut
self.write_expr_adj(*callee, adjustments);
res
}
diff --git a/crates/ide-assists/src/handlers/add_explicit_type.rs b/crates/ide-assists/src/handlers/add_explicit_type.rs
index b5f99726fe..0057f439f1 100644
--- a/crates/ide-assists/src/handlers/add_explicit_type.rs
+++ b/crates/ide-assists/src/handlers/add_explicit_type.rs
@@ -47,7 +47,10 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
// Don't enable the assist if there is a type ascription without any placeholders
if let Some(ty) = &ascribed_ty {
let mut contains_infer_ty = false;
- walk_ty(ty, &mut |ty| contains_infer_ty |= matches!(ty, ast::Type::InferType(_)));
+ walk_ty(ty, &mut |ty| {
+ contains_infer_ty |= matches!(ty, ast::Type::InferType(_));
+ false
+ });
if !contains_infer_ty {
cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified);
return None;
diff --git a/crates/ide-assists/src/handlers/extract_type_alias.rs b/crates/ide-assists/src/handlers/extract_type_alias.rs
index 3116935fc5..0505f5784f 100644
--- a/crates/ide-assists/src/handlers/extract_type_alias.rs
+++ b/crates/ide-assists/src/handlers/extract_type_alias.rs
@@ -108,76 +108,80 @@ fn collect_used_generics<'gp>(
}
let mut generics = Vec::new();
- walk_ty(ty, &mut |ty| match ty {
- ast::Type::PathType(ty) => {
- if let Some(path) = ty.path() {
- if let Some(name_ref) = path.as_single_name_ref() {
- if let Some(param) = known_generics.iter().find(|gp| {
- match gp {
- ast::GenericParam::ConstParam(cp) => cp.name(),
- ast::GenericParam::TypeParam(tp) => tp.name(),
- _ => None,
+ walk_ty(ty, &mut |ty| {
+ match ty {
+ ast::Type::PathType(ty) => {
+ if let Some(path) = ty.path() {
+ if let Some(name_ref) = path.as_single_name_ref() {
+ if let Some(param) = known_generics.iter().find(|gp| {
+ match gp {
+ ast::GenericParam::ConstParam(cp) => cp.name(),
+ ast::GenericParam::TypeParam(tp) => tp.name(),
+ _ => None,
+ }
+ .map_or(false, |n| n.text() == name_ref.text())
+ }) {
+ generics.push(param);
}
- .map_or(false, |n| n.text() == name_ref.text())
- }) {
- generics.push(param);
}
+ generics.extend(
+ path.segments()
+ .filter_map(|seg| seg.generic_arg_list())
+ .flat_map(|it| it.generic_args())
+ .filter_map(|it| match it {
+ ast::GenericArg::LifetimeArg(lt) => {
+ let lt = lt.lifetime()?;
+ known_generics.iter().find(find_lifetime(&lt.text()))
+ }
+ _ => None,
+ }),
+ );
}
- generics.extend(
- path.segments()
- .filter_map(|seg| seg.generic_arg_list())
- .flat_map(|it| it.generic_args())
- .filter_map(|it| match it {
- ast::GenericArg::LifetimeArg(lt) => {
- let lt = lt.lifetime()?;
- known_generics.iter().find(find_lifetime(&lt.text()))
- }
- _ => None,
- }),
- );
}
- }
- ast::Type::ImplTraitType(impl_ty) => {
- if let Some(it) = impl_ty.type_bound_list() {
- generics.extend(
- it.bounds()
- .filter_map(|it| it.lifetime())
- .filter_map(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
- );
+ ast::Type::ImplTraitType(impl_ty) => {
+ if let Some(it) = impl_ty.type_bound_list() {
+ generics.extend(
+ it.bounds()
+ .filter_map(|it| it.lifetime())
+ .filter_map(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
+ );
+ }
}
- }
- ast::Type::DynTraitType(dyn_ty) => {
- if let Some(it) = dyn_ty.type_bound_list() {
- generics.extend(
- it.bounds()
- .filter_map(|it| it.lifetime())
- .filter_map(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
- );
+ ast::Type::DynTraitType(dyn_ty) => {
+ if let Some(it) = dyn_ty.type_bound_list() {
+ generics.extend(
+ it.bounds()
+ .filter_map(|it| it.lifetime())
+ .filter_map(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
+ );
+ }
}
- }
- ast::Type::RefType(ref_) => generics.extend(
- ref_.lifetime().and_then(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
- ),
- ast::Type::ArrayType(ar) => {
- if let Some(expr) = ar.expr() {
- if let ast::Expr::PathExpr(p) = expr {
- if let Some(path) = p.path() {
- if let Some(name_ref) = path.as_single_name_ref() {
- if let Some(param) = known_generics.iter().find(|gp| {
- if let ast::GenericParam::ConstParam(cp) = gp {
- cp.name().map_or(false, |n| n.text() == name_ref.text())
- } else {
- false
+ ast::Type::RefType(ref_) => generics.extend(
+ ref_.lifetime()
+ .and_then(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
+ ),
+ ast::Type::ArrayType(ar) => {
+ if let Some(expr) = ar.expr() {
+ if let ast::Expr::PathExpr(p) = expr {
+ if let Some(path) = p.path() {
+ if let Some(name_ref) = path.as_single_name_ref() {
+ if let Some(param) = known_generics.iter().find(|gp| {
+ if let ast::GenericParam::ConstParam(cp) = gp {
+ cp.name().map_or(false, |n| n.text() == name_ref.text())
+ } else {
+ false
+ }
+ }) {
+ generics.push(param);
}
- }) {
- generics.push(param);
}
}
}
}
}
- }
- _ => (),
+ _ => (),
+ };
+ false
});
// stable resort to lifetime, type, const
generics.sort_by_key(|gp| match gp {
diff --git a/crates/ide-db/src/syntax_helpers/node_ext.rs b/crates/ide-db/src/syntax_helpers/node_ext.rs
index b72003ff36..aa03478599 100644
--- a/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -173,7 +173,8 @@ pub fn walk_pat(pat: &ast::Pat, cb: &mut dyn FnMut(ast::Pat)) {
}
/// Preorder walk all the type's sub types.
-pub fn walk_ty(ty: &ast::Type, cb: &mut dyn FnMut(ast::Type)) {
+// FIXME: Make the control flow more proper
+pub fn walk_ty(ty: &ast::Type, cb: &mut dyn FnMut(ast::Type) -> bool) {
let mut preorder = ty.syntax().preorder();
while let Some(event) = preorder.next() {
let node = match event {
@@ -184,10 +185,12 @@ pub fn walk_ty(ty: &ast::Type, cb: &mut dyn FnMut(ast::Type)) {
match ast::Type::cast(node) {
Some(ty @ ast::Type::MacroType(_)) => {
preorder.skip_subtree();
- cb(ty)
+ cb(ty);
}
Some(ty) => {
- cb(ty);
+ if cb(ty) {
+ preorder.skip_subtree();
+ }
}
// skip const args
None if ast::ConstArg::can_cast(kind) => {
diff --git a/crates/ide/src/inlay_hints/fn_lifetime_fn.rs b/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
index 1f5bcea63a..2aa5e3dc73 100644
--- a/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
+++ b/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
@@ -59,9 +59,14 @@ pub(super) fn hints(
r.amp_token(),
lifetime,
is_elided,
- ))
+ ));
+ false
}
- _ => (),
+ ast::Type::FnPtrType(_) => true,
+ ast::Type::PathType(t) => {
+ t.path().and_then(|it| it.segment()).and_then(|it| it.param_list()).is_some()
+ }
+ _ => false,
})
});
acc
@@ -146,8 +151,13 @@ pub(super) fn hints(
is_trivial = false;
acc.push(mk_lt_hint(amp, output_lt.to_string()));
}
+ false
+ }
+ ast::Type::FnPtrType(_) => true,
+ ast::Type::PathType(t) => {
+ t.path().and_then(|it| it.segment()).and_then(|it| it.param_list()).is_some()
}
- _ => (),
+ _ => false,
})
}
}
@@ -298,4 +308,18 @@ impl () {
"#,
);
}
+
+ #[test]
+ fn hints_lifetimes_skip_fn_likes() {
+ check_with_config(
+ InlayHintsConfig {
+ lifetime_elision_hints: LifetimeElisionHints::Always,
+ ..TEST_CONFIG
+ },
+ r#"
+fn fn_ptr(a: fn(&()) -> &()) {}
+fn fn_trait<>(a: impl Fn(&()) -> &()) {}
+"#,
+ );
+ }
}