Skip to content

Commit

Permalink
Implemented basic automatic passing of trait implementations for func…
Browse files Browse the repository at this point in the history
…tion calls when which trait implementation should be used is unambiguous
  • Loading branch information
IsaacShelton committed Jan 20, 2025
1 parent 2266e52 commit 5842ac0
Showing 1 changed file with 57 additions and 10 deletions.
67 changes: 57 additions & 10 deletions src/resolve/expr/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
resolve::{
conform::{conform_expr, to_default::conform_expr_to_default, ConformMode, Perform},
error::{ResolveError, ResolveErrorKind},
Initialized,
Initialized, PolyValue,
},
source_files::Source,
};
Expand Down Expand Up @@ -81,18 +81,65 @@ pub fn call_callee(
let num_required = function.params.required.len();

for (expected_name, expected_trait) in function.impl_params.params.iter() {
if !used_names.contains(expected_name) {
return Err(ResolveError::other(
format!(
"Missing '${} {}' trait implementation required by function call",
expected_name,
expected_trait.display(&ctx.asg),
),
source,
));
if used_names.contains(expected_name) {
continue;
}

// NOTE: PERFORMANCE: TODO: This could probably be optimized
if let Some(caller) = ctx
.func_ref
.map(|caller_func_ref| ctx.asg.funcs.get(caller_func_ref).unwrap())
{
let from_env = caller.impl_params.params.iter().filter(|(_, param_trait)| {
callee
.recipe
.resolve_trait(expected_trait)
.map_or(false, |expected_trait| **param_trait == expected_trait)
});

match from_env.exactly_one() {
Ok((param_name, _)) => {
if callee
.recipe
.polymorphs
.insert(expected_name.into(), PolyValue::PolyImpl(param_name.into()))
.is_some()
{
return Err(ResolveError::other(
format!(
"Could not automatically supply trait implementation for '${} {}' required by function call, since the polymorph is already in use",
expected_name,
expected_trait.display(&ctx.asg),
),
source,
));
}
}
Err(mut non_unique) => {
return Err(ResolveError::other(
if non_unique.next().is_some() {
format!(
"Ambiguous trait implementation for '${} {}' required by function call, please specify manually",
expected_name,
expected_trait.display(&ctx.asg),
)
} else {
format!(
"Missing '${} {}' trait implementation required by function call",
expected_name,
expected_trait.display(&ctx.asg),
)
},
source,
));
}
}
}
}

// We shouldn't use used_names after this, since we know all names were satisfied
drop(used_names);

for (i, arg) in args.iter_mut().enumerate() {
let function = ctx.asg.funcs.get(callee.func_ref).unwrap();

Expand Down

0 comments on commit 5842ac0

Please sign in to comment.