Skip to content

analysis: check return-type compatibility (OWN035) An external review of the very first main flagged two analyzer/codegen divergences that survived into the current tree: lower_return silently dropped a non-owned or empty return symbol to None, so the analyzer treated the function as a valid terminal while codegen printed the raw AST return x; -- emitting uncompilable C# the checker had accepted: * fn f(n: int) -> Buffer { return n; } -> Buffer f(int n){ return n; } * fn f() -> Buffer { return; } -> Buffer f(){ return; } Diagnose the mismatch instead of dropping it (new OWN035): a ). #5

Merged
PhysShell merged 3 commits into
mainfrom
claude/codegen-bugs-tests-670240
Jun 14, 2026

Conversation

@PhysShell

@PhysShell PhysShell commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • Bug Fixes & Improvements
    • Strengthened validation for return statements to match each function’s declared return type and expected resource kind.
    • The compiler now emits OWN035 (“return type mismatch”) for invalid return usage, including bare return; where a value is required, returning a value from void-style contexts, and returning incompatible owned resources.
  • Tests
    • Expanded regression coverage for OWN035, including additional soundness guard scenarios (including cases expecting OWN001).

An external review of the very first main flagged two analyzer/codegen
divergences that survived into the current tree: `lower_return` silently
dropped a non-owned or empty return symbol to None, so the analyzer treated
the function as a valid terminal while codegen printed the raw AST `return x;`
-- emitting uncompilable C# the checker had accepted:

  * `fn f(n: int) -> Buffer { return n; }`  -> `Buffer f(int n){ return n; }`
  * `fn f() -> Buffer { return; }`          -> `Buffer f(){ return; }`

Diagnose the mismatch instead of dropping it (new OWN035): a value-less
`return;` in a function with a return type, a value returned from a function
with none, and a non-owned value returned where an owned resource is required.
`emit` then refuses (its existing contract), so no bad C# is produced. Returning
an owned resource into a `-> Resource` stays clean (still escapes), and a
returned borrow stays OWN004.

Tests: 3 OWN035 cases + a clean bare-`return;`-in-void case (analysis 104/104).

(The deeper fix the review recommends -- generate from the checked CFG/effects
rather than the raw AST so the two cannot diverge -- remains roadmap; catching
it in the checker + refusing to emit is the sound MVP behaviour.)
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4bbd6400-c6be-494e-9491-83663b92db8d

📥 Commits

Reviewing files that changed from the base of the PR and between 5179aa5 and 728e868.

📒 Files selected for processing (2)
  • ownlang/cfg.py
  • tests/run_tests.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/run_tests.py
  • ownlang/cfg.py

📝 Walkthrough

Walkthrough

Adds OWN035 ("return type mismatch") diagnostic and extends _Builder.lower_return to validate return statements against declared return types. Type names are now tracked when acquiring and moving owned resources to enable type-based validation. Regression tests cover return type mismatches, valid returns, and ownership/borrow interaction boundaries.

Changes

OWN035 Return Type Mismatch Validation

Layer / File(s) Summary
Type name tracking for owned resources
ownlang/cfg.py
When lowering let = acquire <resource>, the symbol now records type_name from the resource identifier. When lowering let = move <src>, the destination symbol propagates type_name from the source, enabling later type checks to distinguish owned resource types.
OWN035 return type validation
ownlang/diagnostics.py, ownlang/cfg.py
OWN035 is registered as "return type mismatch" in TITLES. lower_return gains validation for: bare return; when a return type is declared, returning a value when no return type is declared, returning a non-owned value when an owned resource type is expected, and continues rejecting borrows with OWN004. In all invalid cases the return symbol is forced to None.
Return validation test coverage
tests/run_tests.py
Regression tests added for OWN035: three vectors expecting OWN035 for type mismatches (int instead of Buffer, empty return from Buffer-typed function, value return from void-typed function), clean baseline for return; in non-returning function, and expanded adversarial ownership/borrow soundness guards including void-return-in-borrow-leaks rejection case.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit tracks the types with care,
Each resource knows its name to bear.
When return mismatches what was planned,
OWN035 makes the error grand.
Now borrowed paths and owned ones too
Are validated through and through! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'analysis: check return-type compatibility (OWN035)' accurately summarizes the main change: adding return-type mismatch diagnostics via a new OWN035 error code.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/codegen-bugs-tests-670240

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab291b7449

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ownlang/cfg.py Outdated
claude added 2 commits June 14, 2026 14:25
Bringing the ownership checker -- the core of the PoC -- to a trustworthy
state. An adversarial pass over the loans/permissions rules (~30 hand-built
edge cases) found zero false negatives and zero false positives: every
ownership/borrow violation is flagged, every safe program is accepted. The
holes we had been finding all lived in codegen and the return-type edge, not
in the ownership lattice itself.

Capture the genuinely-new corners as permanent regression cases (16): borrow
of a moved-from name, a void return that leaks inside a borrow, double consume,
consuming/moving a borrow binding, a mutating call under a live shared borrow
(OWN006), an inner acquire that leaks inside a borrow, shadowed binding names,
return-of-moved + leak, and five clean programs guarding against the checker
becoming over-strict (sequential exclusive borrows, consume on both arms,
move chains, nested shared borrows). Analysis suite: 120/120.
Follow-up to the OWN035 return-type check: it only verified that a value
returned from a resource-typed function was *owned*, so a different owned
resource still slipped through -- `fn f() -> Buffer { let c = acquire Conn(1);
return c; }` produced no diagnostic and codegen emitted a `Buffer`-returning
method handing back a Conn, recreating the analyzer/codegen mismatch this
check exists to close.

Thread the resource type onto owned symbols (set on `acquire`, propagated
through `move`; params already carried it) and compare it to the declared
return type. Buffers keep their own escape rules (OWN015/016/017), so they are
left to the analyzer rather than reported here. A wrong-typed owned resource is
kept as escaped (not nulled) so it is not also spuriously reported as a leak --
the type mismatch is the single error.

Tests: wrong-resource return (acquired + param), plus a clean `-> Conn` return.
Analysis suite 123/123.
@PhysShell
PhysShell merged commit ad6a92c into main Jun 14, 2026
9 checks passed
@mrpunyetaz-cloud mrpunyetaz-cloud mentioned this pull request Jun 18, 2026
PhysShell pushed a commit that referenced this pull request Jul 3, 2026
Both reviewers converged; all corrections are factual/design refinements
(no forks):

- Crate DAG: own-codegen is a SIBLING of own-diagnostics (both consume
  own-cfg/own-analysis), not chained through it. Codegen is
  verdict-independent (AST/CFG-driven, matching Python codegen.generate),
  so the old own-diagnostics -> own-codegen edge would have forced
  diagnostics to re-export solver internals. Added a fitness function
  locking codegen !-> diagnostics (and !-> analysis for now). (Codex P2,
  CodeRabbit #1)
- Oracle: do NOT reuse scripts/oracle_compare.py as the parity oracle —
  it is cross-tool fuzzy (leak-only, +-N line tolerance, coarse severity)
  and would mask off-by-one/label/subject/exit-status divergences. Spec a
  new exact harness over status+stdout+stderr+SARIF/JSON, with an
  exit/crash gate first, exact set-equality incl. evidence label text,
  and intra-tie ordering. (Codex P1, CodeRabbit #4)
- CFG seam does not exist yet: python cfg prints human text, not JSON.
  Add+freeze a canonical cfg --format json before the ratchet uses that
  seam; added as migration step 0. (Codex P2)
- State: arena+CoW likely wins this procedural workload; bench largest
  real function, wall-clock + RSS. Prior art: clippy lint-pass registry,
  prusti-viper encoding boundary. Repo-layout revisit trigger. (CodeRabbit
  #2/#3/#5/#6)
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