Skip to content

Commit 2a02e71

Browse files
olwangclaude
andcommitted
docs: feature requests from tinygrad-rsmc refactor
- module-value-access: qualified module.Variant/CONST value access or glob imports (cross-module enum/const usage; blocks module de-prefixing). - freshness-direct-call-return: propagate freshness through `return fresh_call()` (the lone remaining RS0602 in the port). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent e606c8e commit 2a02e71

2 files changed

Lines changed: 140 additions & 0 deletions

File tree

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Feature request: freshness propagation through a direct `return fresh_call()`
2+
3+
**Status:** requested · **Driver:** tinygrad-rsmc clean `rss check`
4+
**Repro built on:** current `rss` (post literal/enum/clean-local freshness fixes)
5+
6+
## Summary
7+
8+
Treat `return <call-to-fresh-fn>(...)` as fresh when the callee is a known
9+
fresh-returning function — the same way the just-landed "clean local" rule treats
10+
`let s = <fresh-call>(); return s`. This is the lone remaining freshness gap.
11+
12+
## Motivation / impact
13+
14+
After the literal-return, enum-variant, and clean-local-propagation fixes,
15+
`rss check tinygrad-rss` went from **483 → 1** `RS0602` warning. The single
16+
remaining one is a function that simply forwards another fresh function's result
17+
directly in a `return`, without binding it to a local first. Closing this gets the
18+
port to a **0-warning** check.
19+
20+
## Current behavior (verified)
21+
22+
The remaining warning in the port:
23+
24+
```
25+
warning[RS0602]: freshness of return value in `tensor_max_pool2d_resolved`
26+
--> tinygrad-rss/src/tensor.rss:4867
27+
return tensor_max_pool2d(cache: mut cache, x: x, kh: kh, ... )
28+
```
29+
30+
Minimal form:
31+
32+
```rss
33+
fn make() -> fresh String { return "x" }
34+
35+
fn via_local() -> fresh String {
36+
let s = make()
37+
return s // OK now (clean-local rule)
38+
}
39+
40+
fn direct() -> fresh String {
41+
return make() // warning[RS0602]: freshness unknown
42+
}
43+
```
44+
45+
The via-local spelling is already accepted; the equivalent direct spelling is not.
46+
47+
## Proposed behavior
48+
49+
In the freshness check, a `return E` where `E` is a call to a function whose
50+
return is known-fresh (declared/inferred `fresh`) is itself fresh — identical to
51+
binding `E` to a clean local and returning that local.
52+
53+
## Acceptance criteria
54+
55+
- `fn direct() -> fresh String { return make() }` checks clean.
56+
- `rss check tinygrad-rss` reports **0 warnings** (currently 1).
57+
58+
## Notes
59+
60+
- Low priority / small: it's a single warning, no behavioral effect, and a natural
61+
extension of the clean-local propagation rule already implemented.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Feature request: cross-module enum-variant / constant usage
2+
3+
**Status:** requested · **Driver:** tinygrad-rsmc module de-prefixing
4+
**Repro built on:** current `rss` (post module-isolation + use-aliasing)
5+
6+
## Summary
7+
8+
Make enum/sum **variants** and **constants** defined in one `module` usable from
9+
another without one `use` line per symbol. Today only per-symbol
10+
`use module.NAME` + bare reference works; **qualified value access fails** and
11+
**glob imports are unsupported**. This blocks de-prefixing enum/const-heavy files.
12+
13+
## Motivation / impact
14+
15+
The tinygrad-rsmc port has a single `Ops` sum type with ~100 variants
16+
(`ADD`, `MUL`, `GLOBAL`, `INDEX`, …) referenced across ~100 files, plus shared
17+
constants. To put `Ops` in `module ops`, every consumer must currently add a
18+
separate `use ops.ADD`, `use ops.MUL`, … — thousands of `use` lines — and two
19+
modules that both define a same-named variant can't be used in one file at all
20+
(no qualification, no aliasing for values). That makes module de-prefixing of
21+
these files impractical, which is the last refactor still gated.
22+
23+
## Current behavior (verified)
24+
25+
```rss
26+
// ops.rss
27+
module ops
28+
sum Ops { ADD, MUL, OTHER }
29+
const MAX_OPS: Int = 64
30+
```
31+
32+
```rss
33+
// user.rss
34+
module user
35+
use ops.Ops
36+
use ops.ADD
37+
use ops.MAX_OPS
38+
39+
fn a(o: read Ops) -> Int { return 1 } // OK (type via use)
40+
fn b() -> fresh Ops { return ADD } // OK (variant via use + bare)
41+
fn d() -> Int { return MAX_OPS } // OK (const via use + bare)
42+
43+
fn c() -> fresh Ops { return ops.MUL } // error[RS0026]: unknown value binding `ops`
44+
fn e() -> Int { return ops.MAX_OPS } // error[RS0026]: unknown value binding `ops`
45+
```
46+
47+
```rss
48+
use ops.* // error[RS0015]: unsupported RSScript syntax
49+
```
50+
51+
So: qualified *calls* (`ops.fn()`) resolve, but qualified *values*
52+
(`ops.MUL`, `ops.MAX_OPS`) do not, and there is no glob form.
53+
54+
## Proposed behavior — either option unblocks this
55+
56+
1. **Qualified value access:** resolve `module.Variant` and `module.CONST` in
57+
value position the same way `module.fn()` already resolves in call position.
58+
(Preferred — also gives per-use disambiguation for same-named variants across
59+
modules, which `use` alone cannot.)
60+
2. **Glob import:** support `use module.*` to bring every public symbol of a
61+
module into scope at once. (Simpler for the common "import the whole ops
62+
enum" case; does not solve cross-module name collisions.)
63+
64+
Ideally both; #1 is the more general fix.
65+
66+
## Acceptance criteria
67+
68+
- `fn c() -> fresh Ops { return ops.MUL }` and `fn e() -> Int { return ops.MAX_OPS }`
69+
check clean.
70+
- (If #2) `use ops.*` brings `Ops`, its variants, and `MAX_OPS` into scope.
71+
- A file can reference two same-named variants from different modules — at least
72+
one via qualification (#1).
73+
74+
## Notes
75+
76+
- Pairs with the portman rss-adapter `module` awareness already shipped, which
77+
reconstructs the flat owner-qualified identity for de-prefixed functions.
78+
- Scope is enum variants and constants specifically; types and functions already
79+
work via `use` / qualified calls.

0 commit comments

Comments
 (0)