Skip to content

feat(types): carry the (echo, epi) grade in function types (ADR-0009 D1/D3)#50

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/dazzling-albattani-ubS9r
Jun 19, 2026
Merged

feat(types): carry the (echo, epi) grade in function types (ADR-0009 D1/D3)#50
hyperpolymath merged 1 commit into
mainfrom
claude/dazzling-albattani-ubS9r

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

The second half of "type annotate and @epi" — carries the (echo, epi) effect row in a function type, with the prefix-marker syntax you chose. With this, the ADR-0009 D1+D2+D3 declaration + type effect surface is complete.

fn apply(f: @echo(Neutral) @epi(Partial) Fn(Int) -> Int): Int { ... }

What changed

  • ast.rs: EffectGrade { echo: Option<Echo>, epi: Option<Epistemic> }; TypeAnnotation::Function gains a trailing EffectGrade; Type::Function likewise.
  • grammar/parser: function_type accepts leading @echo/@epi markers (same tokens as on declarations); the parser splits them from the param/return types.
  • annotation_to_type carries the grade into Type::Function; Display + pretty + formatter emit the prefix markers (round-trip).
  • coercible_to: a function type is covariant in the grade (grade_leq) — a function that loses/reveals less is usable where more is allowed; a None target is unconstrained; a None source can't satisfy a Some ceiling; params/return invariant for now.

Honest scope (as discussed)

This is representational / forward infrastructure: JtV has no first-class function values yet (no lambdas / indirect calls), so the value-against-type coercion is correct but latent until function values land. It completes ADR-0009's stated surface and is the right shape for when they do.

Tests / quality

4 new tests (parse graded + ungraded; round-trip; covariance accept/reject/unconstrained). 142 lib tests, cargo fmt + clippy clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BJmfoz1ZS1Pejy9LLMY742


Generated by Claude Code

…D1/D3)

Completes the ADR-0009 effect surface: a function TYPE can now carry the
effect row, with the same prefix-marker syntax as declarations (user choice).

    @echo(Neutral) @epi(Partial) Fn(Int) -> Int

- ast.rs: `EffectGrade { echo: Option<Echo>, epi: Option<Epistemic> }`;
  `TypeAnnotation::Function` gains a trailing `EffectGrade`; `Type::Function`
  likewise.
- grammar/parser: `function_type` accepts leading `@echo`/`@epi` markers; the
  parser splits them from the param/return types into the `EffectGrade`.
- annotation_to_type carries the grade; Display + pretty + formatter emit it
  (round-trip).
- coercible_to: a function type is COVARIANT in the grade (`grade_leq`) -- a
  function that loses/reveals LESS is usable where MORE is allowed; a `None`
  target is unconstrained; a `None` source can't satisfy a `Some` ceiling;
  params/return invariant for now.

4 tests (parse graded + ungraded; round-trip; covariance accept/reject/
unconstrained). 142 lib tests, cargo fmt + clippy clean.

Honest scope: representational / forward infrastructure -- JtV has no first-class
function VALUES (no lambdas / indirect calls) yet, so the value-against-type
coercion is correct but latent until function values land. The ADR-0009 D1+D2+D3
declaration + type effect surface is now complete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BJmfoz1ZS1Pejy9LLMY742
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 55 issues detected

Severity Count
🔴 Critical 0
🟠 High 23
🟡 Medium 32
View findings
[
  {
    "reason": "No test directory or test files found",
    "type": "no_tests",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper",
    "action": "flag",
    "rule_module": "honest_completion",
    "severity": "high",
    "deduction": 20
  },
  {
    "reason": "Issue in secret-scanner.yml",
    "type": "missing_workflow",
    "file": "secret-scanner.yml",
    "action": "create",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "Issue in scorecard.yml",
    "type": "scorecard_wrapper_missing_job_permissions",
    "file": "scorecard.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "high"
  },
  {
    "reason": "unwrap() without prior check -- DoS via panic (10 occurrences, CWE-754)",
    "type": "unwrap_without_check",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper/crates/jtv-core/benches/interpreter_bench.rs",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  },
  {
    "reason": "unwrap() without prior check -- DoS via panic (6 occurrences, CWE-754)",
    "type": "unwrap_without_check",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper/crates/jtv-core/benches/parser_bench.rs",
    "action": "flag",
    "rule_module": "code_safety",
    "severity": "high"
  },
  {
    "reason": "Js.Array2 deprecated -- use Array (3 occurrences)",
    "type": "deprecated_api",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper/vscode-extension/src/Extension.res",
    "action": "search_replace",
    "rule_module": "migration_rules",
    "severity": "high"
  },
  {
    "reason": "Js.Promise deprecated -- use Promise (2 occurrences)",
    "type": "deprecated_api",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper/vscode-extension/src/Extension.res",
    "action": "module_replace",
    "rule_module": "migration_rules",
    "severity": "medium"
  },
  {
    "reason": "Belt.Array deprecated -- use Array (30 occurrences)",
    "type": "deprecated_api",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper/packages/jtv-analyzer/src/Main.res",
    "action": "module_replace",
    "rule_module": "migration_rules",
    "severity": "high"
  },
  {
    "reason": "Belt.Option deprecated -- use Option (2 occurrences)",
    "type": "deprecated_api",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper/packages/jtv-analyzer/src/Main.res",
    "action": "module_replace",
    "rule_module": "migration_rules",
    "severity": "medium"
  },
  {
    "reason": "Js.Array2 deprecated -- use Array (7 occurrences)",
    "type": "deprecated_api",
    "file": "/home/runner/work/julia-the-viper/julia-the-viper/packages/jtv-analyzer/src/Main.res",
    "action": "search_replace",
    "rule_module": "migration_rules",
    "severity": "high"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath
hyperpolymath marked this pull request as ready for review June 19, 2026 13:35
@hyperpolymath
hyperpolymath merged commit fff9689 into main Jun 19, 2026
32 checks passed
@hyperpolymath
hyperpolymath deleted the claude/dazzling-albattani-ubS9r branch June 19, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants