forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#135911 - Zalathar:arena-cache-option, r=<try>
Allow `arena_cache` queries to return `Option<&'tcx T>` Currently, `arena_cache` queries always have to return `&'tcx T`[^deref]. This means that if an arena-cached query wants to return an optional value, it has to return `&'tcx Option<T>`, which has a few negative consequences: - It goes against normal Rust style, where `Option<&T>` is preferred over `&Option<T>`. - Callers that actually want an `Option<&T>` have to manually call `.as_ref()` on the query result. - When the query result is `None`, a full-sized `Option<T>` still needs to be stored in the arena. This PR solves that problem by introducing a helper trait `ArenaCached` that is implemented for both `&T` and `Option<&T>`, and takes care of bridging between the provided type, the arena-allocated type, and the declared query return type. --- To demonstrate that this works, I have converted the two existing arena-cached queries that currently return `&Option<T>`: `mir_coroutine_witnesses` and `diagnostic_hir_wf_check`. Only the query declarations need to be modified; existing providers and callers continue to work with the new query return type. (My real goal is to apply this to `coverage_ids_info`, which will return Option as of rust-lang#135873, but that PR hasn't landed yet.) [^deref]: Technically they could return other types that implement `Deref`, but it's hard to imagine this working well with anything other than `&T`.
- Loading branch information
Showing
3 changed files
with
64 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/// Helper trait that allows `arena_cache` queries to return `Option<&T>` | ||
/// instead of `&Option<T>`, and avoid allocating `None` in the arena. | ||
/// | ||
/// An arena-cached query must be declared to return a type that implements | ||
/// this trait, i.e. either `&'tcx T` or `Option<&'tcx T>`. This trait then | ||
/// determines the types returned by the provider and stored in the arena, | ||
/// and provides a function to bridge between the three types. | ||
pub trait ArenaCached<'tcx>: Sized { | ||
/// Type that is returned by the query provider. | ||
type Provided; | ||
/// Type that is stored in the arena. | ||
type Allocated: 'tcx; | ||
|
||
/// Takes a provided value, and allocates it in the arena (if appropriate) | ||
/// with the help of the given `arena_alloc` closure. | ||
fn alloc_in_arena( | ||
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, | ||
value: Self::Provided, | ||
) -> Self; | ||
} | ||
|
||
impl<'tcx, T> ArenaCached<'tcx> for &'tcx T { | ||
type Provided = T; | ||
type Allocated = T; | ||
|
||
fn alloc_in_arena( | ||
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, | ||
value: Self::Provided, | ||
) -> Self { | ||
// Just allocate in the arena normally. | ||
arena_alloc(value) | ||
} | ||
} | ||
|
||
impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> { | ||
type Provided = Option<T>; | ||
/// The provide value is `Option<T>`, but we only store `T` in the arena. | ||
type Allocated = T; | ||
|
||
fn alloc_in_arena( | ||
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, | ||
value: Self::Provided, | ||
) -> Self { | ||
// Don't store None in the arena, and wrap the allocated reference in Some. | ||
value.map(arena_alloc) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters