Skip to content

Commit e34e52b

Browse files
committed
Add implementation
1 parent 7d10d32 commit e34e52b

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,18 @@
44
[![crates.io]](https://crates.io/crates/existential)
55
[![github]](https://github.com/steffahn/existential)
66
[![MIT / Apache 2.0 licensed]](#License)
7-
[![unsafe forbidden]](https://github.com/rust-secure-code/safety-dance/)
87

98
[github]: https://img.shields.io/badge/github-steffahn/existential-yellowgreen.svg
109
[crates.io]: https://img.shields.io/crates/v/existential.svg?maxAge=86400
1110
[MIT / Apache 2.0 licensed]: https://img.shields.io/crates/l/existential.svg?maxAge=2592000
1211
[docs.rs]: https://docs.rs/existential/badge.svg
13-
[unsafe forbidden]: https://img.shields.io/badge/unsafe-forbidden-success.svg
1412

1513

1614
[Existential types](https://wiki.haskell.org/Existential_type) in Rust, offering existential
1715
quantification over lifetimes, but as a library. This works because Rust has
1816
[parametricity](https://en.wikipedia.org/wiki/Parametricity) for generic lifetime arguments.
1917

20-
_Work in progress; this crate is still undocumented._
18+
_TODO: this crate is still undocumented._
2119

2220
## License
2321
Licensed under either of

src/lib.rs

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![no_std]
2-
#![forbid(unsafe_code)]
32
// reasonable clippy categories
43
#![warn(clippy::pedantic, clippy::nursery, clippy::cargo)]
54
// reasonable clippy::restriction lints
@@ -88,16 +87,69 @@
8887
//! [![crates.io]](https://crates.io/crates/existential)
8988
//! [![github]](https://github.com/steffahn/existential)
9089
//! [![MIT / Apache 2.0 licensed]](https://github.com/steffahn/existential#License)
91-
//! [![unsafe forbidden]](https://github.com/rust-secure-code/safety-dance/)
9290
//!
9391
//! [Existential types](https://wiki.haskell.org/Existential_type) in Rust, offering existential
9492
//! quantification over lifetimes, but as a library. This works because Rust has
9593
//! [parametricity](https://en.wikipedia.org/wiki/Parametricity) for generic lifetime arguments.
9694
//!
97-
//! _Work in progress; this crate is still undocumented._
95+
//! _TODO: this crate is still undocumented._
9896
//!
9997
//! [github]: https://img.shields.io/badge/github-steffahn/existential-yellowgreen.svg
10098
//! [crates.io]: https://img.shields.io/crates/v/existential.svg
10199
//! [MIT / Apache 2.0 licensed]: https://img.shields.io/crates/l/existential.svg
102100
//! [docs.rs]: https://docs.rs/existential/badge.svg
103-
//! [unsafe forbidden]: https://img.shields.io/badge/unsafe-forbidden-success.svg
101+
102+
use core::{
103+
marker::PhantomData,
104+
mem::{self, ManuallyDrop},
105+
};
106+
107+
pub trait TyConFor<'a> {
108+
type Applied;
109+
}
110+
111+
pub type Apply<'a, C> = <C as TyConFor<'a>>::Applied;
112+
113+
pub trait TyCon: for<'a> TyConFor<'a> {}
114+
impl<C: ?Sized> TyCon for C where C: for<'a> TyConFor<'a> {}
115+
116+
pub struct Existential<'lower_bound, C>
117+
where
118+
C: TyCon,
119+
{
120+
marker: PhantomData<&'lower_bound ()>,
121+
inner: Apply<'static, C>,
122+
}
123+
124+
impl<'lower_bound, C> Existential<'lower_bound, C>
125+
where
126+
C: TyCon,
127+
{
128+
pub fn new<'a: 'lower_bound>(inner: Apply<'a, C>) -> Existential<'lower_bound, C> {
129+
let inner = ManuallyDrop::new(inner);
130+
unsafe {
131+
Self {
132+
marker: PhantomData,
133+
inner: mem::transmute_copy::<Apply<'a, C>, Apply<'static, C>>(&inner),
134+
}
135+
}
136+
}
137+
pub fn with<'s, F, O>(&'s self, f: F) -> O
138+
where
139+
F: for<'a> FnOnce(&'s Apply<'a, C>, PhantomData<&'lower_bound &'a ()>) -> O,
140+
{
141+
f(&self.inner, PhantomData)
142+
}
143+
pub fn with_mut<'s, F, O>(&'s mut self, f: F) -> O
144+
where
145+
F: for<'a> FnOnce(&'s mut Apply<'a, C>, PhantomData<&'lower_bound &'a ()>) -> O,
146+
{
147+
f(&mut self.inner, PhantomData)
148+
}
149+
pub fn with_owned<F, O>(self, f: F) -> O
150+
where
151+
F: for<'a> FnOnce(Apply<'a, C>, PhantomData<&'lower_bound &'a ()>) -> O,
152+
{
153+
f(self.inner, PhantomData)
154+
}
155+
}

0 commit comments

Comments
 (0)