Skip to content

Commit 9a82458

Browse files
committed
Move eval_const_fn_call to the const_eval module
1 parent 2d67edd commit 9a82458

File tree

2 files changed

+44
-34
lines changed

2 files changed

+44
-34
lines changed

src/librustc_mir/const_eval/machine.rs

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
149149
// sensitive check here. But we can at least rule out functions that are not const
150150
// at all.
151151
if ecx.tcx.is_const_fn_raw(def_id) {
152-
// If this function is a `const fn` then as an optimization we can query this
153-
// evaluation immediately.
154-
//
155-
// For the moment we only do this for functions which take no arguments
156-
// (or all arguments are ZSTs) so that we don't memoize too much.
157-
//
158-
// Because `#[track_caller]` adds an implicit non-ZST argument, we also cannot
159-
// perform this optimization on items tagged with it.
160-
let no_implicit_args = !instance.def.requires_caller_location(ecx.tcx());
161-
if args.iter().all(|a| a.layout.is_zst()) && no_implicit_args {
162-
let gid = GlobalId { instance, promoted: None };
163-
ecx.eval_const_fn_call(gid, ret)?;
152+
// If this function is a `const fn` then under certain circumstances we
153+
// can evaluate call via the query system, thus memoizing all future calls.
154+
if ecx.try_eval_const_fn_call(instance, ret, args)? {
164155
return Ok(None);
165156
}
166157
} else {
@@ -326,3 +317,43 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
326317
}
327318
}
328319
}
320+
321+
impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
322+
/// Evaluate a const function where all arguments (if any) are zero-sized types.
323+
/// The evaluation is memoized thanks to the query system.
324+
///
325+
/// Returns `true` if the call has been evaluated.
326+
fn try_eval_const_fn_call(
327+
&mut self,
328+
instance: ty::Instance<'tcx>,
329+
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
330+
args: &[OpTy<'tcx>],
331+
) -> InterpResult<'tcx, bool> {
332+
trace!("try_eval_const_fn_call: {:?}", instance);
333+
// Because `#[track_caller]` adds an implicit non-ZST argument, we also cannot
334+
// perform this optimization on items tagged with it.
335+
if instance.def.requires_caller_location(self.tcx()) {
336+
return Ok(false);
337+
}
338+
// For the moment we only do this for functions which take no arguments
339+
// (or all arguments are ZSTs) so that we don't memoize too much.
340+
if args.iter().any(|a| !a.layout.is_zst()) {
341+
return Ok(false);
342+
}
343+
344+
let gid = GlobalId { instance, promoted: None };
345+
346+
let place = self.const_eval_raw(gid)?;
347+
let dest = match ret {
348+
Some((dest, _)) => dest,
349+
// Don't memoize diverging function calls.
350+
None => return Ok(false),
351+
};
352+
353+
self.copy_op(place.into(), dest)?;
354+
355+
self.return_to_block(ret.map(|r| r.1))?;
356+
self.dump_place(*dest);
357+
return Ok(true);
358+
}
359+
}

src/librustc_mir/interpret/terminator.rs

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use rustc_target::spec::abi::Abi;
77
use syntax::source_map::Span;
88

99
use super::{
10-
FnVal, GlobalId, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy,
11-
StackPopCleanup,
10+
FnVal, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, PlaceTy, StackPopCleanup,
1211
};
1312

1413
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@@ -402,26 +401,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
402401
}
403402
}
404403

405-
/// Evaluate a const function where all arguments (if any) are zero-sized types.
406-
/// The evaluation is memoized thanks to the query system.
407-
// FIXME: Consider moving this to `const_eval.rs`.
408-
pub(crate) fn eval_const_fn_call(
409-
&mut self,
410-
gid: GlobalId<'tcx>,
411-
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
412-
) -> InterpResult<'tcx> {
413-
trace!("eval_const_fn_call: {:?}", gid);
414-
415-
let place = self.const_eval_raw(gid)?;
416-
let dest = ret.ok_or_else(|| err_ub!(Unreachable))?.0;
417-
418-
self.copy_op(place.into(), dest)?;
419-
420-
self.return_to_block(ret.map(|r| r.1))?;
421-
self.dump_place(*dest);
422-
return Ok(());
423-
}
424-
425404
fn drop_in_place(
426405
&mut self,
427406
place: PlaceTy<'tcx, M::PointerTag>,

0 commit comments

Comments
 (0)