Traits, Protocols, Interfaces
Different languages have different names for a similar idea:
Rust trait
Swift protocol
TypeScript interface
Java interface
Go interface
Haskell typeclass
C++ concept
Scala typeclass or traitThey all describe a contract, but they are not the same contract.
That difference matters for semantic merge and cross-language translation.
If the system sees only method names, it will overclaim. A method set is not enough to prove a trait, protocol, interface, typeclass, or concept survived a merge.
Names Are Not Contracts
Imagine a source trait:
trait Cache {
type Item;
fn get(&self, key: &str) -> Option<Self::Item>;
}It can be lowered into something that looks like a TypeScript interface:
interface Cache<Item> {
get(key: string): Item | undefined;
}The shape is close.
But the proof is not finished.
What happened to Self::Item? Is undefined the same absence convention as Option? Are implementations structural or nominal? Can any object satisfy the interface, or must an implementation be declared? Does dispatch happen statically, dynamically, or structurally?
Those are not philosophical questions. They decide whether a merge can be admitted.
1trait Cache {2 type Item;3 fn get(&self, key: &str) -> Option<Self::Item>;4}Obligations Travel Separately
A protocol-like contract is not one fact.
It is a set of obligations:
identity of the contract
required members
associated types or type members
generic parameters
where clauses and bounds
default methods
extension methods
implementation declarations
dynamic or static dispatch
coherence and orphan rules
object-safety or existential behaviorSome obligations translate cleanly.
Some need an adapter.
Some cannot be represented in the target language without runtime checks or conventions.
That is why a universal merge system should not store “interface preserved: true.”
It should store the obligations.
Dispatch Is Meaning
Dispatch is one of the easiest places to overclaim.
static dispatch
dynamic dispatch
structural dispatch
virtual dispatch
extension method lookup
blanket implementation
conditional implementationTwo outputs can have the same method call text and different dispatch meaning.
A target might call a structurally compatible object where the source required an explicit implementation. Or a source trait object may allow dynamic dispatch where the target generic erases it.
That is not automatically bad.
It is a lowering decision that needs to be named.
Structural Is Not Weaker By Default
TypeScript interfaces are structural. Rust traits are explicit. Go interfaces are structural but method-set based. Swift protocols have conformance rules. Haskell typeclasses have instance resolution.
No one model is universally “more semantic.”
They express different commitments.
Semantic merge should respect the source commitment and the target commitment. If a target weakens a nominal requirement into structural compatibility, the system should say so. If a target strengthens a structural shape into an explicit implementation, the system should say so.
The evidence is useful precisely because it refuses to flatten these differences into one field called interface.
The Mental Model
Traits, protocols, interfaces, typeclasses, and concepts are contract surfaces.
They are made of obligations.
Semantic merge should preserve or route each obligation:
member set
type members
bounds
dispatch
implementation authority
coherence
runtime behaviorIf those obligations are represented, the candidate can move forward.
If they are missing, the system should not guess from matching names.