Skip to content

Commit fe74309

Browse files
committed
D5.3: normalize a global:: qualifier on the BCL factory match (CodeRabbit #127)
CodeRabbit marked the Tier-B precision concern addressed by 52a562e; this folds in its remaining suggestion — strip an optional `global::` qualifier before the match, so `global::System.IO.File.OpenRead` resolves as the BCL identity while a `global::`-qualified non-System.IO look-alike is still rejected. Tests for both. ownir 177/177; ruff + mypy clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkpSWNx7ARLpQeAs13kkyA
1 parent 52a562e commit fe74309

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

ownlang/ownir.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,9 +1122,13 @@ def _infer_return_skeleton(nodes: Any, param_names: set[str]) -> ReturnSkeleton:
11221122
def _is_bcl_fresh_factory(callee: str) -> bool:
11231123
"""True if `callee` names a curated BCL factory whose return the caller owns. Accepts
11241124
ONLY the bare `Type.Method` (`File.OpenRead`) or the fully-qualified `System.IO.File.*`
1125-
identity — a same-named type in another namespace (`MyCompany.File.OpenRead`) is NOT a
1126-
match. Precision-first: we never fabricate ownership for a non-BCL look-alike (Codex)."""
1127-
return bool(callee) and (callee in _BCL_FRESH_FACTORIES or callee in _BCL_FRESH_FQNS)
1125+
identity (with an optional `global::` qualifier) — a same-named type in another namespace
1126+
(`MyCompany.File.OpenRead`) is NOT a match. Precision-first: we never fabricate ownership
1127+
for a non-BCL look-alike (Codex / CodeRabbit)."""
1128+
if not callee:
1129+
return False
1130+
name = callee.removeprefix("global::")
1131+
return name in _BCL_FRESH_FACTORIES or name in _BCL_FRESH_FQNS
11281132

11291133

11301134
def _callee_returns_fresh(callee: str, mos: dict[str, Any] | None) -> bool:

tests/test_ownir.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,17 @@ def _bcl(body: list) -> list:
15591559
"result": "s", "line": 5}]):
15601560
fails.append("Tier B precision: a non-System.IO `*.File.OpenRead` must NOT match")
15611561
checks += 1
1562+
# a `global::`-qualified System.IO.File factory IS the BCL identity (the qualifier is
1563+
# stripped); a `global::`-qualified non-System.IO look-alike still must NOT match.
1564+
gq = [(x.code, x.line) for x in _bcl([{"op": "call",
1565+
"callee": "global::System.IO.File.OpenRead", "args": ["p"],
1566+
"result": "s", "line": 4}])]
1567+
if gq != [("OWN001", 4)]:
1568+
fails.append(f"Tier B: a `global::System.IO.File.*` factory must match, got {gq}")
1569+
if _bcl([{"op": "call", "callee": "global::MyCompany.File.OpenRead", "args": ["p"],
1570+
"result": "s", "line": 4}]):
1571+
fails.append("Tier B precision: `global::`-qualified non-System.IO must NOT match")
1572+
checks += 1
15621573
# OVERRIDE (Codex): a first-party summary is authoritative — a first-party `File.OpenRead`
15631574
# that returns its parameter is NOT fresh, so a caller dropping its result is clean; the
15641575
# table must not fabricate ownership for a callee whose body we can see.

0 commit comments

Comments
 (0)