Skip to content

Commit 5842ac0

Browse files
committed
Implemented basic automatic passing of trait implementations for function calls when which trait implementation should be used is unambiguous
1 parent 2266e52 commit 5842ac0

File tree

1 file changed

+57
-10
lines changed

1 file changed

+57
-10
lines changed

Diff for: src/resolve/expr/call/mod.rs

+57-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
resolve::{
99
conform::{conform_expr, to_default::conform_expr_to_default, ConformMode, Perform},
1010
error::{ResolveError, ResolveErrorKind},
11-
Initialized,
11+
Initialized, PolyValue,
1212
},
1313
source_files::Source,
1414
};
@@ -81,18 +81,65 @@ pub fn call_callee(
8181
let num_required = function.params.required.len();
8282

8383
for (expected_name, expected_trait) in function.impl_params.params.iter() {
84-
if !used_names.contains(expected_name) {
85-
return Err(ResolveError::other(
86-
format!(
87-
"Missing '${} {}' trait implementation required by function call",
88-
expected_name,
89-
expected_trait.display(&ctx.asg),
90-
),
91-
source,
92-
));
84+
if used_names.contains(expected_name) {
85+
continue;
86+
}
87+
88+
// NOTE: PERFORMANCE: TODO: This could probably be optimized
89+
if let Some(caller) = ctx
90+
.func_ref
91+
.map(|caller_func_ref| ctx.asg.funcs.get(caller_func_ref).unwrap())
92+
{
93+
let from_env = caller.impl_params.params.iter().filter(|(_, param_trait)| {
94+
callee
95+
.recipe
96+
.resolve_trait(expected_trait)
97+
.map_or(false, |expected_trait| **param_trait == expected_trait)
98+
});
99+
100+
match from_env.exactly_one() {
101+
Ok((param_name, _)) => {
102+
if callee
103+
.recipe
104+
.polymorphs
105+
.insert(expected_name.into(), PolyValue::PolyImpl(param_name.into()))
106+
.is_some()
107+
{
108+
return Err(ResolveError::other(
109+
format!(
110+
"Could not automatically supply trait implementation for '${} {}' required by function call, since the polymorph is already in use",
111+
expected_name,
112+
expected_trait.display(&ctx.asg),
113+
),
114+
source,
115+
));
116+
}
117+
}
118+
Err(mut non_unique) => {
119+
return Err(ResolveError::other(
120+
if non_unique.next().is_some() {
121+
format!(
122+
"Ambiguous trait implementation for '${} {}' required by function call, please specify manually",
123+
expected_name,
124+
expected_trait.display(&ctx.asg),
125+
)
126+
} else {
127+
format!(
128+
"Missing '${} {}' trait implementation required by function call",
129+
expected_name,
130+
expected_trait.display(&ctx.asg),
131+
)
132+
},
133+
source,
134+
));
135+
}
136+
}
93137
}
94138
}
95139

140+
// We shouldn't use used_names after this, since we know all names were satisfied
141+
drop(used_names);
142+
96143
for (i, arg) in args.iter_mut().enumerate() {
97144
let function = ctx.asg.funcs.get(callee.func_ref).unwrap();
98145

0 commit comments

Comments
 (0)