feat(provider-fn): enforce declarative signatures on provider functions#57
Open
raphaelvigee wants to merge 1 commit into
Open
feat(provider-fn): enforce declarative signatures on provider functions#57raphaelvigee wants to merge 1 commit into
raphaelvigee wants to merge 1 commit into
Conversation
Provider-exposed functions (heph.<provider>.<fn>) advertised only a name + handler; args and return were untyped htvalue::Value, the Starlark bridge installed them with for_arguments()/Ty::any(), and each handler hand-rolled its own validation. Add a declarative signature (typed positional + named params with required/optional/default, typed return) to ProviderFunctionDef and enforce it: - htvalue/signature.rs: ParamType (reuses htvalue::Value kinds), Param, FnSignature with validate_args/validate_return (hard-fail, naming the function + offending param) and render(). - Registry carries the signature (RegisteredFn). The bridge validates args and the return value around every call — the canonical guard, and the only one that checks the return at runtime. - build_globals drives Starlark's native param_spec/return_type from the signature, so BUILD-time also gets arity/type errors and typing/docs. - pluginfs glob/join/dir/base declare signatures; join now takes one list[string] (was variadic); redundant hand-rolled checks dropped. - inspect functions prints the rendered signature (e.g. heph.fs.glob(pattern: string) -> list[string]). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
raphaelvigee
commented
Jun 6, 2026
| for (provider, func) in engine.provider_functions() { | ||
| println!("heph.{provider}.{func}"); | ||
| for (provider, _func, rendered) in engine.provider_functions() { | ||
| println!("heph.{provider}.{rendered}"); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Provider-exposed functions (
heph.<provider>.<fn>, added in #656d9ab) advertised only a name + handler. Args and the return were untypedhtvalue::Value, the Starlark bridge installed every function withparam_spec: for_arguments()/return_type: Ty::any(), and each handler hand-rolled its own validation. A typo, wrong type, or bad arity slipped past the engine.Change
Add a declarative signature to
ProviderFunctionDef— typed positional + named params (required/optional + default) and a typed return — and enforce it (hard-fail).src/htvalue/signature.rs(new):ParamType(reuseshtvalue::Valuekinds — String/Bool/Int/Uint/Float/Null/List/Map),Param,FnSignaturewithvalidate_args/validate_return(errors name the function + offending param) andrender().RegisteredFn). The bridge validates args and the return value around every call — the canonical guard, and the only one that checks the return at runtime.build_globalsdrives Starlark's nativeparam_spec/return_typefrom the signature, so BUILD-time also gets arity/type errors + typing/docs. Both layers enforce.pluginfsglob/join/dir/basedeclare signatures;joinnow takes onelist[string](was variadic); redundant hand-rolled checks dropped.inspect functionsprints the rendered signature, e.g.heph.fs.glob(pattern: string) -> list[string].Scope
Provider functions only — not
target, not driver config.Test plan
cargo build+cargo clippy --all-targets -- -D warningsclean;cargo fmtapplied.htvalue/signature.rs) + 6 e2e BUILD-eval tests (missing required, wrong type, too-many-positional, unknown kwarg,joinrequires-list,joinaccepts-list).🤖 Generated with Claude Code