-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Background
When the semantic analyser cannot statically verify that argument types match a function's signature, it emits Binding::Dynamic(Vec<ResolvedVar>) — an overload set resolved at runtime. However, if the candidates list contains exactly one entry, there is no actual dispatch decision to make: that function will always be called regardless. The runtime type check is redundant because the native function already validates its arguments and returns a meaningful error if types don't match.
Current behaviour
For a call like n - 1 where n: Any, the analyser emits Binding::Dynamic([sub_fn]) with a single candidate. At runtime this causes:
Constant(OverloadSet([sub_fn]))— clones aBox<Object::OverloadSet(Vec<ResolvedVar>)>from the constant pool (heap allocation)resolve_callee()hits theOverloadSetbranch and callsfind_overload()find_overload()allocates aVec<StaticType>for the argument types, iterates candidates, looks up the global, checks the type signature
All of this for a call whose target was never ambiguous.
Proposed fix
In the analyser, when building a Binding::Dynamic, check if the resulting candidates list has exactly one entry. If so, return Binding::Resolved(candidates[0]) instead.
The compiler then emits a direct GetGlobal / GetLocal for the callee, and resolve_callee() hits the fast Object::Function(f) => Ok(Some(f.clone())) path.
Precondition: The candidates list must already be filtered by arity (so a single candidate with wrong arity isn't silently accepted). Verify this before applying.
Impact on fib.ndc
In fib(n) (no type annotations → n: Any), every arithmetic operator has exactly one binary registration:
+,-(binary),*,/— registered as(Number, Number) → Number<,>,<=,>=— registered as(Any, Any) → Bool
This means the optimisation fires for all three operators in fib (-, -, +, <), eliminating the overload resolution overhead on every call.
Trade-off
A type mismatch will produce an error from inside the native function rather than a "no matching overload" error at the call site. The error message is slightly less precise, but still meaningful.