mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-01 20:31:59 +00:00
Improve error recovery when method-calling an assoc function
This commit is contained in:
parent
fb8bc313ff
commit
e6ea353d94
6 changed files with 111 additions and 70 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use hir::{db::ExpandDatabase, AssocItem, FileRange, HirDisplay, InFile};
|
||||
use hir::{db::ExpandDatabase, FileRange, HirDisplay, InFile};
|
||||
use ide_db::text_edit::TextEdit;
|
||||
use ide_db::{
|
||||
assists::{Assist, AssistId, AssistKind},
|
||||
|
|
@ -112,7 +112,7 @@ fn field_fix(
|
|||
}
|
||||
|
||||
fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option<Assist> {
|
||||
if let Some(assoc_item_id) = d.assoc_func_with_same_name {
|
||||
if let Some(f) = d.assoc_func_with_same_name {
|
||||
let db = ctx.sema.db;
|
||||
|
||||
let expr_ptr = &d.expr;
|
||||
|
|
@ -127,30 +127,25 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
|
|||
let receiver = call.receiver()?;
|
||||
let receiver_type = &ctx.sema.type_of_expr(&receiver)?.original;
|
||||
|
||||
let need_to_take_receiver_as_first_arg = match hir::AssocItem::from(assoc_item_id) {
|
||||
AssocItem::Function(f) => {
|
||||
let assoc_fn_params = f.assoc_fn_params(db);
|
||||
if assoc_fn_params.is_empty() {
|
||||
false
|
||||
} else {
|
||||
assoc_fn_params
|
||||
.first()
|
||||
.map(|first_arg| {
|
||||
// For generic type, say `Box`, take `Box::into_raw(b: Self)` as example,
|
||||
// type of `b` is `Self`, which is `Box<T, A>`, containing unspecified generics.
|
||||
// However, type of `receiver` is specified, it could be `Box<i32, Global>` or something like that,
|
||||
// so `first_arg.ty() == receiver_type` evaluate to `false` here.
|
||||
// Here add `first_arg.ty().as_adt() == receiver_type.as_adt()` as guard,
|
||||
// apply `.as_adt()` over `Box<T, A>` or `Box<i32, Global>` gets `Box`, so we get `true` here.
|
||||
let assoc_fn_params = f.assoc_fn_params(db);
|
||||
let need_to_take_receiver_as_first_arg = if assoc_fn_params.is_empty() {
|
||||
false
|
||||
} else {
|
||||
assoc_fn_params
|
||||
.first()
|
||||
.map(|first_arg| {
|
||||
// For generic type, say `Box`, take `Box::into_raw(b: Self)` as example,
|
||||
// type of `b` is `Self`, which is `Box<T, A>`, containing unspecified generics.
|
||||
// However, type of `receiver` is specified, it could be `Box<i32, Global>` or something like that,
|
||||
// so `first_arg.ty() == receiver_type` evaluate to `false` here.
|
||||
// Here add `first_arg.ty().as_adt() == receiver_type.as_adt()` as guard,
|
||||
// apply `.as_adt()` over `Box<T, A>` or `Box<i32, Global>` gets `Box`, so we get `true` here.
|
||||
|
||||
// FIXME: it fails when type of `b` is `Box` with other generic param different from `receiver`
|
||||
first_arg.ty() == receiver_type
|
||||
|| first_arg.ty().as_adt() == receiver_type.as_adt()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
// FIXME: it fails when type of `b` is `Box` with other generic param different from `receiver`
|
||||
first_arg.ty() == receiver_type
|
||||
|| first_arg.ty().as_adt() == receiver_type.as_adt()
|
||||
})
|
||||
.unwrap_or(false)
|
||||
};
|
||||
|
||||
let mut receiver_type_adt_name =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue