Skip to content

Commit 2e859d7

Browse files
Rollup merge of rust-lang#152417 - Zalathar:arena-alloc, r=nnethercote
Move the needs-drop check for `arena_cache` queries out of macro code This is slightly simpler than before, because now the macro only needs to call a single function, and can just unconditionally supply `tcx` and a typed arena. There should be no actual change to compiler behaviour.
2 parents b2568a7 + 4dc82e9 commit 2e859d7

3 files changed

Lines changed: 40 additions & 38 deletions

File tree

compiler/rustc_middle/src/queries.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@
6363
#![allow(unused_parens)]
6464

6565
use std::ffi::OsStr;
66-
use std::mem;
6766
use std::path::PathBuf;
6867
use std::sync::Arc;
6968

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
use std::mem;
2+
3+
use rustc_arena::TypedArena;
4+
5+
use crate::ty::TyCtxt;
6+
17
/// Helper trait that allows `arena_cache` queries to return `Option<&T>`
28
/// instead of `&Option<T>`, and avoid allocating `None` in the arena.
39
///
@@ -11,10 +17,11 @@ pub trait ArenaCached<'tcx>: Sized {
1117
/// Type that is stored in the arena.
1218
type Allocated: 'tcx;
1319

14-
/// Takes a provided value, and allocates it in the arena (if appropriate)
15-
/// with the help of the given `arena_alloc` closure.
20+
/// Takes a provided value, and allocates it in an appropriate arena,
21+
/// unless the particular value doesn't need allocation (e.g. `None`).
1622
fn alloc_in_arena(
17-
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
23+
tcx: TyCtxt<'tcx>,
24+
typed_arena: &'tcx TypedArena<Self::Allocated>,
1825
value: Self::Provided,
1926
) -> Self;
2027
}
@@ -23,12 +30,9 @@ impl<'tcx, T> ArenaCached<'tcx> for &'tcx T {
2330
type Provided = T;
2431
type Allocated = T;
2532

26-
fn alloc_in_arena(
27-
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
28-
value: Self::Provided,
29-
) -> Self {
33+
fn alloc_in_arena(tcx: TyCtxt<'tcx>, typed_arena: &'tcx TypedArena<T>, value: T) -> Self {
3034
// Just allocate in the arena normally.
31-
arena_alloc(value)
35+
do_alloc(tcx, typed_arena, value)
3236
}
3337
}
3438

@@ -38,10 +42,17 @@ impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> {
3842
type Allocated = T;
3943

4044
fn alloc_in_arena(
41-
arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated,
42-
value: Self::Provided,
45+
tcx: TyCtxt<'tcx>,
46+
typed_arena: &'tcx TypedArena<T>,
47+
value: Option<T>,
4348
) -> Self {
4449
// Don't store None in the arena, and wrap the allocated reference in Some.
45-
value.map(arena_alloc)
50+
try { do_alloc(tcx, typed_arena, value?) }
4651
}
4752
}
53+
54+
/// Allocates a value in either its dedicated arena, or in the common dropless
55+
/// arena, depending on whether it needs to be dropped.
56+
fn do_alloc<'tcx, T>(tcx: TyCtxt<'tcx>, typed_arena: &'tcx TypedArena<T>, value: T) -> &'tcx T {
57+
if mem::needs_drop::<T>() { typed_arena.alloc(value) } else { tcx.arena.dropless.alloc(value) }
58+
}

compiler/rustc_middle/src/query/plumbing.rs

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -295,36 +295,28 @@ macro_rules! define_callbacks {
295295
($V)
296296
);
297297

298-
/// This function takes `ProvidedValue` and converts it to an erased `Value` by
299-
/// allocating it on an arena if the query has the `arena_cache` modifier. The
300-
/// value is then erased and returned. This will happen when computing the query
301-
/// using a provider or decoding a stored result.
298+
/// This helper function takes a value returned by the query provider
299+
/// (or loaded from disk, or supplied by query feeding), allocates
300+
/// it in an arena if requested by the `arena_cache` modifier, and
301+
/// then returns an erased copy of it.
302302
#[inline(always)]
303303
pub fn provided_to_erased<'tcx>(
304-
_tcx: TyCtxt<'tcx>,
304+
tcx: TyCtxt<'tcx>,
305305
provided_value: ProvidedValue<'tcx>,
306306
) -> Erased<Value<'tcx>> {
307-
// Store the provided value in an arena and get a reference
308-
// to it, for queries with `arena_cache`.
309-
let value: Value<'tcx> = query_if_arena!([$($modifiers)*]
310-
{
311-
use $crate::query::arena_cached::ArenaCached;
312-
313-
if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() {
314-
<$V as ArenaCached>::alloc_in_arena(
315-
|v| _tcx.query_system.arenas.$name.alloc(v),
316-
provided_value,
317-
)
318-
} else {
319-
<$V as ArenaCached>::alloc_in_arena(
320-
|v| _tcx.arena.dropless.alloc(v),
321-
provided_value,
322-
)
323-
}
324-
}
325-
// Otherwise, the provided value is the value.
326-
(provided_value)
327-
);
307+
// For queries with the `arena_cache` modifier, store the
308+
// provided value in an arena and get a reference to it.
309+
let value: Value<'tcx> = query_if_arena!([$($modifiers)*] {
310+
<$V as $crate::query::arena_cached::ArenaCached>::alloc_in_arena(
311+
tcx,
312+
&tcx.query_system.arenas.$name,
313+
provided_value,
314+
)
315+
} {
316+
// Otherwise, the provided value is the value (and `tcx` is unused).
317+
let _ = tcx;
318+
provided_value
319+
});
328320
erase::erase_val(value)
329321
}
330322

0 commit comments

Comments
 (0)