Skip to content

Commit fa36691

Browse files
committed
added Dependent<'owner, O> type alias
1 parent 7c53ba3 commit fa36691

30 files changed

+143
-228
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
Implemented the core functionality of this crate:
88
- Defined `Pair` struct
99
- Defined `Owner` and `HasDependent` traits
10+
- Defined `Dependent` type alias
1011

1112
## v0.1.0
1213

README.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ in time.
2323

2424
A typical use case might look something like this:
2525
```rust
26-
use pair::{HasDependent, Owner, Pair};
26+
use pair::{Dependent, HasDependent, Owner, Pair};
2727

2828
// Let's say you have some buffer type that contains a string
2929
#[derive(Debug)]
@@ -57,10 +57,7 @@ impl Owner for MyBuffer {
5757
type Context<'a> = (); // We don't need any extra args to `make_dependent`
5858
type Error = std::convert::Infallible; // Our example parsing can't fail
5959

60-
fn make_dependent(
61-
&self,
62-
(): Self::Context<'_>,
63-
) -> Result<<Self as pair::HasDependent<'_>>::Dependent, Self::Error> {
60+
fn make_dependent(&self, _: ()) -> Result<Dependent<'_, Self>, Self::Error> {
6461
Ok(parse(self))
6562
}
6663
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ mod drop_guard;
1313
mod owner;
1414
mod pair;
1515

16-
pub use owner::{HasDependent, Owner};
16+
pub use owner::{Dependent, HasDependent, Owner};
1717
pub use pair::Pair;

src/owner.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ pub trait HasDependent<'owner, ForImpliedBound: Sealed = Bounds<&'owner Self>> {
1919
type Dependent;
2020
}
2121

22+
/// A type alias for the [`Dependent`](HasDependent::Dependent) of some
23+
/// [`Owner`] with a specific lifetime `'owner`.
24+
pub type Dependent<'owner, O> = <O as HasDependent<'owner>>::Dependent;
25+
2226
#[expect(
2327
clippy::missing_errors_doc,
2428
reason = "failure modes are specific to the trait's implementation"
@@ -58,7 +62,7 @@ pub trait Owner: for<'any> HasDependent<'any> {
5862
fn make_dependent<'owner>(
5963
&'owner self,
6064
context: Self::Context<'_>,
61-
) -> Result<<Self as HasDependent<'owner>>::Dependent, Self::Error>;
65+
) -> Result<Dependent<'owner, Self>, Self::Error>;
6266
}
6367

6468
/// Used to prevent implementors of [`HasDependent`] from overriding the

src/pair.rs

Lines changed: 68 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ use core::{convert::Infallible, fmt::Debug, marker::PhantomData, mem::ManuallyDr
44

55
use alloc::boxed::Box;
66

7-
use crate::{HasDependent, Owner, drop_guard::DropGuard};
7+
use crate::{Dependent, Owner, drop_guard::DropGuard};
88

9-
/// A self-referential pair containing both some [`Owner`] and its
10-
/// [`Dependent`](HasDependent::Dependent).
9+
/// A self-referential pair containing both some [`Owner`] and its [`Dependent`].
1110
///
1211
/// The owner must be provided to construct a [`Pair`], and the dependent is
1312
/// immediately created (borrowing from the owner). Both are stored together in
@@ -46,12 +45,14 @@ use crate::{HasDependent, Owner, drop_guard::DropGuard};
4645
/// Every combination of these is supported, up to the most powerful (and least
4746
/// ergonomic) [`Pair::try_new_from_box_with_context`]. You should use the
4847
/// simplest constructor you can for your implementation of `Owner`.
48+
///
49+
/// [`Dependent`]: crate::HasDependent::Dependent
4950
pub struct Pair<O: Owner + ?Sized> {
5051
// Derived from a Box<O>
5152
// Immutably borrowed by `self.dependent` from construction until drop
5253
owner: NonNull<O>,
5354

54-
// Type-erased Box<<O as HasDependent<'self.owner>>::Dependent>
55+
// Type-erased Box<Dependent<'owner, O>>
5556
dependent: NonNull<()>,
5657

5758
// Need invariance over O - if we were covariant or contravariant, two
@@ -209,7 +210,7 @@ impl<O: Owner + ?Sized> Pair<O> {
209210
// Type-erase dependent so its inexpressible self-referential lifetime
210211
// goes away (we know that it's borrowing self.owner immutably from
211212
// construction (now) until drop)
212-
let dependent: NonNull<<O as HasDependent<'_>>::Dependent> = non_null_from_box(dependent);
213+
let dependent: NonNull<Dependent<'_, O>> = non_null_from_box(dependent);
213214
let dependent: NonNull<()> = dependent.cast();
214215

215216
Ok(Self {
@@ -234,66 +235,64 @@ impl<O: Owner + ?Sized> Pair<O> {
234235
/// Calls the given closure, providing shared access to the dependent, and
235236
/// returns the value computed by the closure.
236237
///
237-
/// The closure must be able to work with a
238-
/// [`Dependent`](HasDependent::Dependent) with any arbitrary lifetime that
239-
/// lives at least as long as the borrow of `self`. This is important
240-
/// because the dependent may be invariant over its lifetime, and the
241-
/// correct lifetime (lasting from the construction of `self` until drop) is
242-
/// inexpressible. For dependent types covariant over their lifetime, the
243-
/// closure may simply return the reference to the dependent, which may then
244-
/// be used as if this function directly returned a reference.
238+
/// The closure must be able to work with a [`Dependent`] with any arbitrary
239+
/// lifetime that lives at least as long as the borrow of `self`. This is
240+
/// important because the dependent may be invariant over its lifetime, and
241+
/// the correct lifetime (lasting from the construction of `self` until
242+
/// drop) is inexpressible. For dependent types covariant over their
243+
/// lifetime, the closure may simply return the reference to the dependent,
244+
/// which may then be used as if this function directly returned a
245+
/// reference.
246+
///
247+
/// [`Dependent`]: crate::HasDependent::Dependent
245248
pub fn with_dependent<'self_borrow, F, T>(&'self_borrow self, f: F) -> T
246249
where
247-
F: for<'any> FnOnce(&'self_borrow <O as HasDependent<'any>>::Dependent) -> T,
250+
F: for<'any> FnOnce(&'self_borrow Dependent<'_, O>) -> T,
248251
{
249252
// SAFETY: `self.dependent` was originally converted from a valid
250-
// Box<<O as HasDependent<'_>>::Dependent>, and type-erased to a
251-
// NonNull<()>. As such, it inherited the alignment and validity
252-
// guarantees of Box (for an <O as HasDependent<'_>>::Dependent) - and
253-
// neither our code nor any of our exposed APIs could have invalidated
254-
// those since construction. Additionally, because we have a shared
255-
// reference to self, we know that the value behind the pointer is
256-
// currently either not borrowed at all, or in a shared borrow state
257-
// (no exclusive borrows, no other code assuming unique ownership).
258-
// Here, we only either create the first shared borrow, or add another.
259-
let dependent: &<O as HasDependent<'_>>::Dependent = unsafe {
260-
self.dependent
261-
.cast::<<O as HasDependent<'_>>::Dependent>()
262-
.as_ref()
263-
};
253+
// Box<Dependent<'_, O>>, and type-erased to a NonNull<()>. As such, it
254+
// inherited the alignment and validity guarantees of Box (for a
255+
// Dependent<'_, O>) - and neither our code nor any of our exposed APIs
256+
// could have invalidated those since construction. Additionally,
257+
// because we have a shared reference to self, we know that the value
258+
// behind the pointer is currently either not borrowed at all, or in a
259+
// shared borrow state (no exclusive borrows, no other code assuming
260+
// unique ownership). Here, we only either create the first shared
261+
// borrow, or add another.
262+
let dependent = unsafe { self.dependent.cast::<Dependent<'_, O>>().as_ref() };
264263

265264
f(dependent)
266265
}
267266

268267
/// Calls the given closure, providing exclusive access to the dependent,
269268
/// and returns the value computed by the closure.
270269
///
271-
/// The closure must be able to work with a
272-
/// [`Dependent`](HasDependent::Dependent) with any arbitrary lifetime that
273-
/// lives at least as long as the borrow of `self`. This is important
274-
/// because mutable references are invariant over their type `T`, and the
275-
/// exact T here (a `Dependent` with a very specific lifetime lasting from
276-
/// the construction of `self` until drop) is inexpressible.
270+
/// The closure must be able to work with a [`Dependent`] with any arbitrary
271+
/// lifetime that lives at least as long as the borrow of `self`. This is
272+
/// important because mutable references are invariant over their type `T`,
273+
/// and the exact T here (a `Dependent` with a very specific lifetime
274+
/// lasting from the construction of `self` until drop) is inexpressible.
275+
///
276+
/// [`Dependent`]: crate::HasDependent::Dependent
277277
pub fn with_dependent_mut<'self_borrow, F, T>(&'self_borrow mut self, f: F) -> T
278278
where
279-
F: for<'any> FnOnce(&'self_borrow mut <O as HasDependent<'any>>::Dependent) -> T,
279+
F: for<'any> FnOnce(&'self_borrow mut Dependent<'_, O>) -> T,
280280
{
281281
self.with_both_mut(|_, dependent| f(dependent))
282282
}
283283

284284
/// Calls the given closure, providing shared access to both the owner and
285285
/// the dependent, and returns the value computed by the closure.
286286
///
287-
/// The closure must be able to work with a
288-
/// [`Dependent`](HasDependent::Dependent) with any arbitrary lifetime that
289-
/// lives at least as long as the borrow of `self`. See the documentation of
290-
/// [`with_dependent`](Pair::with_dependent) for more information on this.
287+
/// The closure must be able to work with a [`Dependent`] with any arbitrary
288+
/// lifetime that lives at least as long as the borrow of `self`. See the
289+
/// documentation of [`with_dependent`](Pair::with_dependent) for more
290+
/// information on this.
291+
///
292+
/// [`Dependent`]: crate::HasDependent::Dependent
291293
pub fn with_both<'self_borrow, F, T>(&'self_borrow self, f: F) -> T
292294
where
293-
F: for<'any> FnOnce(
294-
&'self_borrow O,
295-
&'self_borrow <O as HasDependent<'any>>::Dependent,
296-
) -> T,
295+
F: for<'any> FnOnce(&'self_borrow O, &'self_borrow Dependent<'_, O>) -> T,
297296
{
298297
self.with_dependent(|dependent| f(self.owner(), dependent))
299298
}
@@ -302,34 +301,28 @@ impl<O: Owner + ?Sized> Pair<O> {
302301
/// exclusive access to the dependent, and returns the value computed by the
303302
/// closure.
304303
///
305-
/// The closure must be able to work with a
306-
/// [`Dependent`](HasDependent::Dependent) with any arbitrary lifetime that
307-
/// lives at least as long as the borrow of `self`. See the documentation of
308-
/// [`with_dependent_mut`](Pair::with_dependent_mut) for more information on
309-
/// this.
304+
/// The closure must be able to work with a [`Dependent`] with any arbitrary
305+
/// lifetime that lives at least as long as the borrow of `self`. See the
306+
/// documentation of [`with_dependent_mut`](Pair::with_dependent_mut) for
307+
/// more information on this.
308+
///
309+
/// [`Dependent`]: crate::HasDependent::Dependent
310310
pub fn with_both_mut<'self_borrow, F, T>(&'self_borrow mut self, f: F) -> T
311311
where
312-
F: for<'any> FnOnce(
313-
&'self_borrow O,
314-
&'self_borrow mut <O as HasDependent<'any>>::Dependent,
315-
) -> T,
312+
F: for<'any> FnOnce(&'self_borrow O, &'self_borrow mut Dependent<'_, O>) -> T,
316313
{
317314
let owner: &O = self.owner();
318315

319316
// SAFETY: `self.dependent` was originally converted from a valid
320-
// Box<<O as HasDependent<'_>>::Dependent>, and type-erased to a
321-
// NonNull<()>. As such, it inherited the alignment and validity
322-
// guarantees of Box (for an <O as HasDependent<'_>>::Dependent) - and
323-
// neither our code nor any of our exposed APIs could have invalidated
324-
// those since construction. Additionally, because we have an exclusive
325-
// reference to self (and Pair::owner(..) doesn't borrow the dependent),
326-
// we know that the value behind the pointer is currently not borrowed
327-
// at all, and can't be until our exclusive borrow of `self` expires.
328-
let dependent: &mut <O as HasDependent<'_>>::Dependent = unsafe {
329-
self.dependent
330-
.cast::<<O as HasDependent<'_>>::Dependent>()
331-
.as_mut()
332-
};
317+
// Box<Dependent<'_, O>>, and type-erased to a NonNull<()>. As such, it
318+
// inherited the alignment and validity guarantees of Box (for a
319+
// Dependent<'_, O>) - and neither our code nor any of our exposed APIs
320+
// could have invalidated those since construction. Additionally,
321+
// because we have an exclusive reference to self (and Pair::owner(..)
322+
// doesn't borrow the dependent), we know that the value behind the
323+
// pointer is currently not borrowed at all, and can't be until our
324+
// exclusive borrow of `self` expires.
325+
let dependent = unsafe { self.dependent.cast::<Dependent<'_, O>>().as_mut() };
333326

334327
f(owner, dependent)
335328
}
@@ -352,15 +345,9 @@ impl<O: Owner + ?Sized> Pair<O> {
352345
// SAFETY: `this.dependent` was originally created from a Box, and never
353346
// invalidated since then. Because we took ownership of `self`, we know
354347
// there are no outstanding borrows to the dependent. Therefore,
355-
// reconstructing the original Box<<O as HasDependent<'_>>::Dependent>
356-
// is okay.
357-
let dependent: Box<<O as HasDependent<'_>>::Dependent> = unsafe {
358-
Box::from_raw(
359-
this.dependent
360-
.cast::<<O as HasDependent<'_>>::Dependent>()
361-
.as_ptr(),
362-
)
363-
};
348+
// reconstructing the original Box<Dependent<'_, O>> is okay.
349+
let dependent: Box<Dependent<'_, O>> =
350+
unsafe { Box::from_raw(this.dependent.cast::<Dependent<'_, O>>().as_ptr()) };
364351

365352
// We're about to drop the dependent - if it panics, we want to be able
366353
// to drop the boxed owner before unwinding the rest of the stack to
@@ -512,19 +499,14 @@ impl<O: Owner<Error = Infallible> + ?Sized> Pair<O> {
512499
// for the reasons described above.
513500
impl<O: Owner + ?Sized> Drop for Pair<O> {
514501
fn drop(&mut self) {
515-
// Drop the dependent `Box<<O as HasDependent<'_>>::Dependent>`
502+
// Drop the dependent `Box<Dependent<'_, O>>`
516503

517504
// SAFETY: `self.dependent` was originally created from a Box, and never
518505
// invalidated since then. Because we are in drop, we know there are no
519506
// outstanding borrows to the dependent. Therefore, reconstructing the
520-
// original Box<<O as HasDependent<'_>>::Dependent> is okay.
521-
let dependent = unsafe {
522-
Box::from_raw(
523-
self.dependent
524-
.cast::<<O as HasDependent<'_>>::Dependent>()
525-
.as_ptr(),
526-
)
527-
};
507+
// original Box<Dependent<'_, O>> is okay.
508+
let dependent =
509+
unsafe { Box::from_raw(self.dependent.cast::<Dependent<'_, O>>().as_ptr()) };
528510

529511
// We're about to drop the dependent - if it panics, we want to be able
530512
// to drop the boxed owner before unwinding the rest of the stack to
@@ -576,7 +558,7 @@ impl<O: Owner + ?Sized> Drop for Pair<O> {
576558
unsafe impl<O: Owner + ?Sized> Send for Pair<O>
577559
where
578560
O: Send,
579-
for<'any> <O as HasDependent<'any>>::Dependent: Send,
561+
for<'any> Dependent<'any, O>: Send,
580562
{
581563
}
582564

@@ -588,13 +570,13 @@ where
588570
unsafe impl<O: Owner + ?Sized> Sync for Pair<O>
589571
where
590572
O: Sync,
591-
for<'any> <O as HasDependent<'any>>::Dependent: Sync,
573+
for<'any> Dependent<'any, O>: Sync,
592574
{
593575
}
594576

595577
impl<O: Owner + Debug + ?Sized> Debug for Pair<O>
596578
where
597-
for<'any> <O as HasDependent<'any>>::Dependent: Debug,
579+
for<'any> Dependent<'any, O>: Debug,
598580
{
599581
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
600582
self.with_dependent(|dependent| {

tests/alternative_ctors.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use std::convert::Infallible;
44

5-
use pair::{HasDependent, Owner, Pair};
5+
use pair::{Dependent, HasDependent, Owner, Pair};
66

77
#[derive(Debug)]
88
struct BuffFallible(String);
@@ -15,10 +15,7 @@ impl Owner for BuffFallible {
1515
type Context<'a> = ();
1616
type Error = String;
1717

18-
fn make_dependent(
19-
&self,
20-
(): Self::Context<'_>,
21-
) -> Result<<Self as HasDependent<'_>>::Dependent, Self::Error> {
18+
fn make_dependent(&self, (): Self::Context<'_>) -> Result<Dependent<'_, Self>, Self::Error> {
2219
let parts: Vec<_> = self.0.split_whitespace().collect();
2320

2421
if parts.is_empty() {
@@ -64,7 +61,7 @@ impl Owner for BuffWithContext {
6461
fn make_dependent(
6562
&self,
6663
context: Self::Context<'_>,
67-
) -> Result<<Self as HasDependent<'_>>::Dependent, Self::Error> {
64+
) -> Result<Dependent<'_, Self>, Self::Error> {
6865
Ok(self.0.split(context).collect())
6966
}
7067
}
@@ -95,7 +92,7 @@ impl Owner for BuffFallibleWithContext {
9592
fn make_dependent(
9693
&self,
9794
context: Self::Context<'_>,
98-
) -> Result<<Self as HasDependent<'_>>::Dependent, Self::Error> {
95+
) -> Result<Dependent<'_, Self>, Self::Error> {
9996
let parts: Vec<_> = self.0.split(context).collect();
10097

10198
if parts.len() > 1 {

tests/basic_usage.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use std::convert::Infallible;
44

5-
use pair::{HasDependent, Owner, Pair};
5+
use pair::{Dependent, HasDependent, Owner, Pair};
66

77
#[derive(Debug, PartialEq)]
88
struct Buff(String);
@@ -15,10 +15,7 @@ impl Owner for Buff {
1515
type Context<'a> = ();
1616
type Error = Infallible;
1717

18-
fn make_dependent(
19-
&self,
20-
(): Self::Context<'_>,
21-
) -> Result<<Self as HasDependent<'_>>::Dependent, Self::Error> {
18+
fn make_dependent(&self, (): Self::Context<'_>) -> Result<Dependent<'_, Self>, Self::Error> {
2219
Ok(self.0.split_whitespace().collect())
2320
}
2421
}

tests/compile_fails/extract_with_dep_mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl Owner for Buff {
1818
fn make_dependent(
1919
&self,
2020
(): Self::Context<'_>,
21-
) -> Result<<Self as HasDependent<'_>>::Dependent, Self::Error> {
21+
) -> Result<Dependent<'_, Self>, Self::Error> {
2222
Ok(self.0.split_whitespace().collect())
2323
}
2424
}

tests/compile_fails/invariant_dep_extraction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl Owner for InvarOwner {
1717
fn make_dependent(
1818
&self,
1919
(): Self::Context<'_>,
20-
) -> Result<<Self as HasDependent<'_>>::Dependent, Self::Error> {
20+
) -> Result<Dependent<'_, Self>, Self::Error> {
2121
Ok(PhantomData)
2222
}
2323
}

0 commit comments

Comments
 (0)