mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
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:
commit
5033213fc9
5 changed files with 105 additions and 70 deletions
|
@ -334,6 +334,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
let (param_tys, ret_ty) = match res {
|
let (param_tys, ret_ty) = match res {
|
||||||
Some(res) => {
|
Some(res) => {
|
||||||
let adjustments = auto_deref_adjust_steps(&derefs);
|
let adjustments = auto_deref_adjust_steps(&derefs);
|
||||||
|
// FIXME: Handle call adjustments for Fn/FnMut
|
||||||
self.write_expr_adj(*callee, adjustments);
|
self.write_expr_adj(*callee, adjustments);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// Don't enable the assist if there is a type ascription without any placeholders
|
||||||
if let Some(ty) = &ascribed_ty {
|
if let Some(ty) = &ascribed_ty {
|
||||||
let mut contains_infer_ty = false;
|
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 {
|
if !contains_infer_ty {
|
||||||
cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified);
|
cov_mark::hit!(add_explicit_type_not_applicable_if_ty_already_specified);
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -108,76 +108,80 @@ fn collect_used_generics<'gp>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut generics = Vec::new();
|
let mut generics = Vec::new();
|
||||||
walk_ty(ty, &mut |ty| match ty {
|
walk_ty(ty, &mut |ty| {
|
||||||
ast::Type::PathType(ty) => {
|
match ty {
|
||||||
if let Some(path) = ty.path() {
|
ast::Type::PathType(ty) => {
|
||||||
if let Some(name_ref) = path.as_single_name_ref() {
|
if let Some(path) = ty.path() {
|
||||||
if let Some(param) = known_generics.iter().find(|gp| {
|
if let Some(name_ref) = path.as_single_name_ref() {
|
||||||
match gp {
|
if let Some(param) = known_generics.iter().find(|gp| {
|
||||||
ast::GenericParam::ConstParam(cp) => cp.name(),
|
match gp {
|
||||||
ast::GenericParam::TypeParam(tp) => tp.name(),
|
ast::GenericParam::ConstParam(cp) => cp.name(),
|
||||||
_ => None,
|
ast::GenericParam::TypeParam(tp) => tp.name(),
|
||||||
}
|
_ => None,
|
||||||
.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(<.text()))
|
|
||||||
}
|
}
|
||||||
_ => None,
|
.map_or(false, |n| n.text() == name_ref.text())
|
||||||
}),
|
}) {
|
||||||
);
|
generics.push(param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Type::ImplTraitType(impl_ty) => {
|
generics.extend(
|
||||||
if let Some(it) = impl_ty.type_bound_list() {
|
path.segments()
|
||||||
generics.extend(
|
.filter_map(|seg| seg.generic_arg_list())
|
||||||
it.bounds()
|
.flat_map(|it| it.generic_args())
|
||||||
.filter_map(|it| it.lifetime())
|
.filter_map(|it| match it {
|
||||||
.filter_map(|lt| known_generics.iter().find(find_lifetime(<.text()))),
|
ast::GenericArg::LifetimeArg(lt) => {
|
||||||
);
|
let lt = lt.lifetime()?;
|
||||||
}
|
known_generics.iter().find(find_lifetime(<.text()))
|
||||||
}
|
}
|
||||||
ast::Type::DynTraitType(dyn_ty) => {
|
_ => None,
|
||||||
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(<.text()))),
|
ast::Type::ImplTraitType(impl_ty) => {
|
||||||
);
|
if let Some(it) = impl_ty.type_bound_list() {
|
||||||
}
|
generics.extend(
|
||||||
}
|
it.bounds()
|
||||||
ast::Type::RefType(ref_) => generics.extend(
|
.filter_map(|it| it.lifetime())
|
||||||
ref_.lifetime().and_then(|lt| known_generics.iter().find(find_lifetime(<.text()))),
|
.filter_map(|lt| known_generics.iter().find(find_lifetime(<.text()))),
|
||||||
),
|
);
|
||||||
ast::Type::ArrayType(ar) => {
|
}
|
||||||
if let Some(expr) = ar.expr() {
|
}
|
||||||
if let ast::Expr::PathExpr(p) = expr {
|
ast::Type::DynTraitType(dyn_ty) => {
|
||||||
if let Some(path) = p.path() {
|
if let Some(it) = dyn_ty.type_bound_list() {
|
||||||
if let Some(name_ref) = path.as_single_name_ref() {
|
generics.extend(
|
||||||
if let Some(param) = known_generics.iter().find(|gp| {
|
it.bounds()
|
||||||
if let ast::GenericParam::ConstParam(cp) = gp {
|
.filter_map(|it| it.lifetime())
|
||||||
cp.name().map_or(false, |n| n.text() == name_ref.text())
|
.filter_map(|lt| known_generics.iter().find(find_lifetime(<.text()))),
|
||||||
} else {
|
);
|
||||||
false
|
}
|
||||||
|
}
|
||||||
|
ast::Type::RefType(ref_) => generics.extend(
|
||||||
|
ref_.lifetime()
|
||||||
|
.and_then(|lt| known_generics.iter().find(find_lifetime(<.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
|
// stable resort to lifetime, type, const
|
||||||
generics.sort_by_key(|gp| match gp {
|
generics.sort_by_key(|gp| match gp {
|
||||||
|
|
|
@ -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.
|
/// 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();
|
let mut preorder = ty.syntax().preorder();
|
||||||
while let Some(event) = preorder.next() {
|
while let Some(event) = preorder.next() {
|
||||||
let node = match event {
|
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) {
|
match ast::Type::cast(node) {
|
||||||
Some(ty @ ast::Type::MacroType(_)) => {
|
Some(ty @ ast::Type::MacroType(_)) => {
|
||||||
preorder.skip_subtree();
|
preorder.skip_subtree();
|
||||||
cb(ty)
|
cb(ty);
|
||||||
}
|
}
|
||||||
Some(ty) => {
|
Some(ty) => {
|
||||||
cb(ty);
|
if cb(ty) {
|
||||||
|
preorder.skip_subtree();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// skip const args
|
// skip const args
|
||||||
None if ast::ConstArg::can_cast(kind) => {
|
None if ast::ConstArg::can_cast(kind) => {
|
||||||
|
|
|
@ -59,9 +59,14 @@ pub(super) fn hints(
|
||||||
r.amp_token(),
|
r.amp_token(),
|
||||||
lifetime,
|
lifetime,
|
||||||
is_elided,
|
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
|
acc
|
||||||
|
@ -146,8 +151,13 @@ pub(super) fn hints(
|
||||||
is_trivial = false;
|
is_trivial = false;
|
||||||
acc.push(mk_lt_hint(amp, output_lt.to_string()));
|
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 ^'1 ^'0
|
// ^'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(&()) -> &()) {}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue