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
This commit is contained in:
bors 2023-01-03 10:59:21 +00:00
commit 5033213fc9
5 changed files with 105 additions and 70 deletions

View file

@ -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
}

View file

@ -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;

View file

@ -108,7 +108,8 @@ fn collect_used_generics<'gp>(
}
let mut generics = Vec::new();
walk_ty(ty, &mut |ty| match ty {
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() {
@ -156,7 +157,8 @@ fn collect_used_generics<'gp>(
}
}
ast::Type::RefType(ref_) => generics.extend(
ref_.lifetime().and_then(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
ref_.lifetime()
.and_then(|lt| known_generics.iter().find(find_lifetime(&lt.text()))),
),
ast::Type::ArrayType(ar) => {
if let Some(expr) = ar.expr() {
@ -178,6 +180,8 @@ fn collect_used_generics<'gp>(
}
}
_ => (),
};
false
});
// stable resort to lifetime, type, const
generics.sort_by_key(|gp| match gp {

View file

@ -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) => {

View file

@ -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,
})
}
}
@ -295,6 +305,20 @@ impl () {
// ^^^<'0, '1>
// ^'0 ^'1 ^'0
}
"#,
);
}
#[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(&()) -> &()) {}
"#,
);
}