Implement function type matching

This commit is contained in:
Jessie Chatham Spencer 2023-11-04 12:31:42 +00:00 committed by Lukas Wirth
parent 14a7a614c1
commit 6abba17a5b
3 changed files with 95 additions and 101 deletions

View file

@ -1,6 +1,6 @@
//! Renderer for function calls.
use hir::{db::HirDatabase, AsAssocItem, Callable, HirDisplay, Type};
use hir::{db::HirDatabase, AsAssocItem, HirDisplay};
use ide_db::{SnippetCap, SymbolKind};
use itertools::Itertools;
use stdx::{format_to, to_lower_snake_case};
@ -8,13 +8,9 @@ use syntax::{AstNode, SmolStr};
use crate::{
context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind},
item::{
Builder, CompletionItem, CompletionItemKind, CompletionRelevance,
CompletionRelevanceTypeMatch,
},
item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance},
render::{
compute_exact_name_match, compute_ref_match, compute_type_match, compute_type_match2,
RenderContext,
compute_exact_name_match, compute_function_type_match, compute_ref_match, RenderContext,
},
CallableSnippets,
};
@ -85,47 +81,8 @@ fn render(
.and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db()))
.map_or(false, |trait_| completion.is_ops_trait(trait_));
// TODO next step figure out how to unify function typesk, we need to convert fndef to actual callable type
let type_match = if let Some(ref t) = completion.expected_type {
if let Some(t) = t.as_callable(db) {
let (mut param_types_exp, ret_type_exp) = (
t.params(db).into_iter().map(|(_, ty)| ty).collect::<Vec<Type>>(),
t.return_type(),
);
param_types_exp.push(ret_type_exp);
let mut param_types = func
.ty(db)
.as_callable(db)
.unwrap()
.params(db)
.into_iter()
.map(|(_, ty)| ty)
.collect::<Vec<Type>>();
param_types.push(ret_type.clone());
if param_types.len() != param_types_exp.len() {
None
} else {
if param_types_exp.iter().zip(param_types).all(|(expected_type, item_type)| {
compute_type_match2(completion, &expected_type, &item_type).is_some()
}) {
Some(CompletionRelevanceTypeMatch::CouldUnify)
} else {
None
}
}
} else {
None
}
} else {
None
};
item.set_relevance(CompletionRelevance {
type_match,
type_match: compute_function_type_match(completion, &func),
exact_name_match: compute_exact_name_match(completion, &call),
is_op_method,
..ctx.completion_relevance()