https://github.com/fujiapple852/fromage
A cheesy Rust hack for converting between non-local types
https://github.com/fujiapple852/fromage
cheese coherence conversion hack orphan rust rust-lang trait
Last synced: about 2 months ago
JSON representation
A cheesy Rust hack for converting between non-local types
- Host: GitHub
- URL: https://github.com/fujiapple852/fromage
- Owner: fujiapple852
- License: apache-2.0
- Created: 2025-04-04T12:59:32.000Z (7 months ago)
- Default Branch: master
- Last Pushed: 2025-04-06T10:45:21.000Z (7 months ago)
- Last Synced: 2025-08-26T18:54:21.511Z (about 2 months ago)
- Topics: cheese, coherence, conversion, hack, orphan, rust, rust-lang, trait
- Language: Rust
- Homepage:
- Size: 12.7 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README

[](https://docs.rs/fromage/0.1.1)
[](https://crates.io/crates/fromage/0.1.1)
# Fromage 🧀
A cheesy Rust hack for converting between _non-local_ types.
TL;DR: Allows implementing `From` and `TryFrom` like traits for _non-local_ types without violating
the [orphan rules](https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules).
This crate has no dependencies or macros, is `no_std` and forbids `unsafe` code.
## Example
Convert between the two non-local types `String` and `usize`:
```rust
use fromage::{Fromage, TryFromage};
struct X;
impl Fromage for usize {
fn fromage(value: String) -> Self {
value.len()
}
}
impl TryFromage for usize {
type Error = ();
fn try_fromage(value: String) -> Result {
Ok(value.len())
}
}
#[test]
fn test() {
assert_eq!(5_usize, usize::fromage(String::from("hello")));
assert_eq!(5_usize, usize::try_fromage(String::from("world")).unwrap());
}
```
## Status
Experimental.
## How it works
The [orphan rules](https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules) state that:
```
> Given impl Trait for T0, an impl is valid only if at least one of the following is true:
>
> - `Trait` is a local trait
> - All of:
> - At least one of the types T0..=Tn must be a local type. Let Ti be the first such type.
> - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)
```
Fromage defines the `Fromage` and `TryFromage` traits that mirror the traits in the standard library, except that they
require an `impl` defined additional type parameter `X` and therefore fulfil the _"At least one of the types `T0..=Tn`
must be a local type"_ clause above.
The type parameter `X` is not used in the trait methods. It may be
any type provided it is both [local](https://doc.rust-lang.org/reference/glossary.html#local-type)
and [uncovered](https://doc.rust-lang.org/reference/glossary.html#uncovered-type), typically
a [unit struct](https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields). It
may be reused for all `Fromage` and `TryFromage` implementations within a crate.
The `Fromage` and `TryFromage` traits define methods named `fromage` and `try_fromage` respectively to avoid conflicting
with the standard library's `From` and `TryFrom` traits.
## Limitations
The `Fromage` and `TryFromage` traits defined in this crate are distinct from the standard library's `From` and
`TryFrom` traits and are not interchangeable. Therefore, if a crate uses the standard library's `From` and `TryFrom`
traits in its public API, you cannot use the `Fromage` and `TryFromage` traits to implement conversions for the
types required by that crate.
For example, if a crate exposes the following public API then you cannot use an `impl Fromage for Bar` to
implement the conversion.
```rust
pub fn foo(value: impl Into) { ... }
```
## Alternatives
### Newtype
Typically, a
local [newtype](https://doc.rust-lang.org/book/ch20-02-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-typesl)
is used to implement the standard library's `From` and `TryFrom` traits when both types are non-local.
Either:
```rust
struct FooWrapper(Foo);
impl From for Bar {
fn from(_value: FooWrapper) -> Self {
Bar
}
}
```
Or:
```rust
struct BarWrapper(Bar);
impl From for BarWrapper {
fn from(_value: Foo) -> Self {
BarWrapper(Bar)
}
}
```
### Conversion function
Simple conversions functions can be used instead of the `From` and `TryFrom` traits.
```rust
fn convert(_value: Foo) -> Bar {
Bar
}
fn try_convert(_value: Foo) -> Result {
Ok(Bar)
}
```
### Local traits
For completeness, the orphan rules allow implementing local `MyFrom` and `MyTryFrom` traits which may then be used with
non-local types.
This approach is not recommended as it requires a significant amount of boilerplate code whilst sharing the same
limitations as the Fromage approach.
## License
Fromage is distributed under the terms of the Apache License (Version 2.0).
See [LICENSE](LICENSE) for details.
Copyright 2025