Skip to content

reflect: implement MakeChan - #5588

Open
0pcom wants to merge 2 commits into
tinygo-org:devfrom
0magnet:reflect-makechan
Open

reflect: implement MakeChan#5588
0pcom wants to merge 2 commits into
tinygo-org:devfrom
0magnet:reflect-makechan

Conversation

@0pcom

@0pcom 0pcom commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

reflect.MakeChan currently panics with "unimplemented". This implements it.

It completes a small gap: MakeSlice, MakeMap and New are all supported, so code that builds a channel reflectively is the odd one out — and it is reached by generic container and codec libraries that construct channel types from a reflect.Type.

Verified by building TinyGo and running the compiler test suite.

@dgryski

dgryski commented Aug 14, 2026

Copy link
Copy Markdown
Member

Please add a test for this new function. For reflect, this can either be in testdata/reflect.go or reflect/value_test.go.

@0pcom

0pcom commented Aug 16, 2026

Copy link
Copy Markdown
Contributor Author

Added TestTinyMakeChan in src/reflect/value_test.go, and rebased on dev.

It covers buffered and unbuffered creation (kind, Cap, Len, and a real send/receive through Interface(), since Value.Send/Value.Recv are still unimplemented), plus the three panic paths: non-channel type, negative buffer size, and a unidirectional channel type.

On verification: CI has not run on this PR, so I checked the test's expectations against the host reflect package, where it passes — that pins the behaviour to upstream semantics. I could not run it against these sources under a released TinyGo binary (the musl build gets in the way), so the implementation itself is still only verified by reading.

@0pcom
0pcom force-pushed the reflect-makechan branch from 13e03e0 to 31537f7 Compare August 16, 2026 19:06

@dgryski dgryski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. The tests are currently failing on wasi because #5550 is not yet merged (which ideally should be "soon"). We can either hold off on merging this until that one is in, or update the tests that panic to not run on wasi yet.

@0pcom
0pcom force-pushed the reflect-makechan branch from 31537f7 to 18a08f0 Compare August 18, 2026 18:45
@0pcom

0pcom commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author

Took the second option, since #5550 is still open with review discussion on it and I would rather not have this wait on an unknown.

The three panic cases now skip on wasip1, with a TODO pointing at #5550 so the skip goes when that lands. The buffered and unbuffered cases — which are the substance, covering Cap, Len, and a real send and receive through Interface() — still run everywhere.

If you would rather hold this until #5550 is in, that last commit is the only thing to drop; the rest is unchanged from your LGTM.

@dgryski

dgryski commented Aug 18, 2026

Copy link
Copy Markdown
Member

t.Skip() doesn't work on wasi because it requires the same underlying features as panic/recover. We need to t.Log(); return or wait for the panic/recover PR to land.

TinyGo had MakeMap/MakeSlice but not MakeChan. Implement it via the runtime
chanMake primitive (mirroring MakeMap), so packages that call reflect.MakeChan
(e.g. github.com/ugorji/go/codec used by gin) compile and work.
@0pcom
0pcom force-pushed the reflect-makechan branch from 18a08f0 to f43bc68 Compare August 19, 2026 16:25
@0pcom

0pcom commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Swapped for t.Log(); return — thanks, I had not realised t.Skip needs the same machinery it was standing in for.

The two substantive cases, buffered and unbuffered, still run everywhere; only the three panic cases return early on wasip1, with the TODO still pointing at #5550 so they come back when it lands.

@deadprogram

Copy link
Copy Markdown
Member

Looks like the tests are still failing on this...

@dgryski

dgryski commented Aug 19, 2026

Copy link
Copy Markdown
Member

Yes, the runtime.GOOS == "wasip1" check needs to also check for GOOS == "wasip2"

… wasip1

The guard was on runtime.GOOS == "wasip1", so under wasip2 the three cases that
rely on recover ran anyway. recover does not work on wasm yet, so the panic
escaped and trapped the test binary — which is the tinygo-test-wasip2-fast
failure on this PR.

Checked on runtime.GOARCH instead, since the limitation is wasm's rather than
any one platform's. wasip1, wasip2 and js/wasm all set the tinygo.wasm build
tag, and arch_tinygowasm.go defines GOARCH as wasm for it, so one condition
covers all three of the wasm test targets.

Worth noting for anyone reading targets/wasip2.json: the goarch there is arm,
but that is what is handed to the Go toolchain for package selection —
runtime.GOARCH is the one above.
@0pcom

0pcom commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Fixed, and it turned out to be the CI failure rather than a cosmetic gap — thanks for spotting it.

tinygo-test-wasip2-fast was failing with panic: reflect: call of MakeChan on int Value and a wasm trap at value_test.go:1056. That is the first of the three panic cases: under wasip2 the GOOS == "wasip1" guard did not fire, the case ran, recover does not work on wasm yet, so the panic escaped and took the test binary with it.

I checked on runtime.GOARCH == "wasm" rather than adding wasip2 to a GOOS list, because the limitation is wasm's rather than any one platform's: wasip1, wasip2 and wasm all set the tinygo.wasm build tag, and arch_tinygowasm.go defines GOARCH as wasm for it, so one condition covers all three of the wasm test targets — including tinygo-test-wasm, which the explicit GOOS pair would still have missed.

One thing worth flagging for anyone reading along, because it briefly convinced me I had it wrong: targets/wasip2.json says "goarch": "arm". That is what is handed to the Go toolchain for package selection; runtime.GOARCH is the constant above and reports wasm.

Happy to switch to the explicit wasip1 || wasip2 || js list instead if you would rather it read the same way as the other checks in the tree.

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.

3 participants