Welcome, Guest | Browse

Software Factory Archive

← Previous Work All Works Next Work →

Semport

Rating:
General Audiences
Fandom:
StrongDM Software Factory
Characters:
Jay Taylor Justin McCarthy
Tags:
Semport Cross-Language Porting Semantic Translation Go Rust
Words:
478
Published:
2025-10-11

The word appeared in Jay's notes before it appeared anywhere else. Semport. Semantic port. Not syntactic translation—not running Go source through some mechanical process and producing Rust source that compiled. That was a transliteration, and transliterations produced code that no native speaker would ever write.

A semport was different. You took the meaning of the Go implementation—what it did, why it did it, the invariants it maintained, the failure modes it handled—and you expressed that meaning natively in Rust. The result wasn't Go-flavored Rust. It was Rust that happened to solve the same problem.

Jay had been thinking about this since the CXDB server. The server was 16,000 lines of Rust. The gateway was 9,500 lines of Go. They talked to each other over a binary protocol on port 9009. Both sides needed to serialize and deserialize the same message formats. Both sides needed to handle the same error conditions. Both sides needed to implement the same connection lifecycle.

But the Go gateway used goroutines and channels. The Rust server used async tasks and mpsc channels. The Go gateway used interfaces. The Rust server used traits. The Go gateway handled errors with early returns and wrapped errors. The Rust server used Result types and the question-mark operator.

Same semantics. Completely different idioms.

The first attempt at porting the Go connection handler to Rust had been a syntactic translation. An agent had dutifully converted goroutines to tokio tasks, channels to mpsc senders, interfaces to trait objects. The code compiled. It even passed basic scenarios. But it leaked memory under load because the Go garbage collector had been silently cleaning up abandoned goroutines, and the Rust translation had abandoned tasks that held Arc references in cycles.

"You can't translate the syntax," Jay told the agent in his next prompt. "Translate the semantics. Here's what the Go code means. Here are the invariants. Here are the lifecycle guarantees. Now write it the way a Rust programmer would write it from scratch, knowing these things."

The agent produced something that used structured concurrency with JoinSets. Tasks were owned by the connection handler and cancelled when the connection dropped. No leaked references. No cycles. The error handling used custom error types with thiserror instead of wrapping strings. The connection lifecycle used Drop implementations for deterministic cleanup instead of relying on garbage collection that didn't exist.

It was a Rust implementation that felt native. Jay showed it to Justin.

"If I didn't know this came from a Go original, I wouldn't guess," Justin said.

"That's the test," Jay replied. "If a native speaker can tell it was ported, it's a transliteration. If they can't, it's a semport."

Justin wrote the word down. He wrote it carefully, like he was adding it to a vocabulary he intended to use for a long time. Semport. The practice of carrying meaning across the border between languages, leaving the syntax behind at customs.

Kudos: 112

polyglot_coder 2025-10-13

The customs metaphor at the end is brilliant. Meaning crosses the border. Syntax gets confiscated. I've seen so many Go-to-Rust ports that are obviously Go wearing a Rust costume. A semport is the real thing.

trait_object 2025-10-14

The memory leak from translated goroutines is painfully real. Every Go-to-Rust port I've seen hits this exact wall. The GC was doing invisible work that you need to make explicit in Rust. Semantic porting forces you to confront that.

← Previous Work All Works Next Work →