Skip to content

Commit

Permalink
Make HandleCycleError an enum instead of a macro-generated closure
Browse files Browse the repository at this point in the history
- Add a `HandleCycleError` enum to rustc_query_system, along with a `handle_cycle_error` function
- Move `Value` to rustc_query_system, so `handle_cycle_error` can use it
- Move the `Value` impls from rustc_query_impl to rustc_middle. This is necessary due to orphan rules.
  • Loading branch information
jyn514 committed Sep 7, 2022
1 parent 4e09a13 commit 4856aff
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 43 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub mod mir;
pub mod thir;
pub mod traits;
pub mod ty;
mod values;

pub mod util {
pub mod bug;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,28 @@
use super::QueryCtxt;
use rustc_middle::ty::{self, AdtSizedConstraint, Ty};
use rustc_middle::ty::{self, AdtSizedConstraint, Ty, TyCtxt};
use rustc_query_system::Value;

pub(super) trait Value<'tcx>: Sized {
fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self;
}

impl<'tcx, T> Value<'tcx> for T {
default fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> T {
tcx.sess.abort_if_errors();
bug!("Value::from_cycle_error called without errors");
}
}

impl<'tcx> Value<'tcx> for Ty<'_> {
fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self {
impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
// SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.ty_error()) }
}
}

impl<'tcx> Value<'tcx> for ty::SymbolName<'_> {
fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self {
impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
// SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe {
std::mem::transmute::<ty::SymbolName<'tcx>, ty::SymbolName<'_>>(ty::SymbolName::new(
*tcx, "<error>",
tcx, "<error>",
))
}
}
}

impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> {
fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self {
impl<'tcx> Value<TyCtxt<'tcx>> for AdtSizedConstraint<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
// SAFETY: This is never called when `Self` is not `AdtSizedConstraint<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe {
Expand All @@ -44,8 +33,8 @@ impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> {
}
}

impl<'tcx> Value<'tcx> for ty::Binder<'_, ty::FnSig<'_>> {
fn from_cycle_error(tcx: QueryCtxt<'tcx>) -> Self {
impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
let err = tcx.ty_error();
// FIXME(compiler-errors): It would be nice if we could get the
// query key, so we could at least generate a fn signature that
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_query_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ pub use rustc_query_system::query::{deadlock, QueryContext};
mod keys;
use keys::Key;

mod values;
use self::values::Value;

pub use rustc_query_system::query::QueryConfig;
pub(crate) use rustc_query_system::query::{QueryDescription, QueryVTable};

Expand Down
24 changes: 11 additions & 13 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use rustc_query_system::query::{
force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap,
QuerySideEffects, QueryStackFrame,
};
use rustc_query_system::Value;
use std::any::Any;
use std::num::NonZeroU64;
use thin_vec::ThinVec;
Expand Down Expand Up @@ -174,21 +175,17 @@ impl<'tcx> QueryCtxt<'tcx> {
}

macro_rules! handle_cycle_error {
([][$tcx: expr, $error:expr]) => {{
$error.emit();
Value::from_cycle_error($tcx)
([]) => {{
rustc_query_system::HandleCycleError::Error
}};
([(fatal_cycle) $($rest:tt)*][$tcx:expr, $error:expr]) => {{
$error.emit();
$tcx.sess.abort_if_errors();
unreachable!()
([(fatal_cycle) $($rest:tt)*]) => {{
rustc_query_system::HandleCycleError::Fatal
}};
([(cycle_delay_bug) $($rest:tt)*][$tcx:expr, $error:expr]) => {{
$error.delay_as_bug();
Value::from_cycle_error($tcx)
([(cycle_delay_bug) $($rest:tt)*]) => {{
rustc_query_system::HandleCycleError::DelayBug
}};
([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
handle_cycle_error!([$($modifiers)*][$($args)*])
([$other:tt $($modifiers:tt)*]) => {
handle_cycle_error!([$($modifiers)*])
};
}

Expand Down Expand Up @@ -320,6 +317,7 @@ fn force_from_dep_node<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool
where
Q: QueryDescription<QueryCtxt<'tcx>>,
Q::Key: DepNodeParams<TyCtxt<'tcx>>,
Q::Value: Value<TyCtxt<'tcx>>,
{
if let Some(key) = Q::Key::recover(tcx, &dep_node) {
#[cfg(debug_assertions)]
Expand Down Expand Up @@ -418,7 +416,7 @@ macro_rules! define_queries {
depth_limit: depth_limit!([$($modifiers)*]),
dep_kind: dep_graph::DepKind::$name,
hash_result: hash_result!([$($modifiers)*]),
handle_cycle_error: |tcx, mut error| handle_cycle_error!([$($modifiers)*][tcx, error]),
handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
compute,
cache_on_disk,
try_load_from_disk: Self::TRY_LOAD_FROM_DISK,
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_query_system/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ impl AddSubdiagnostic for CycleStack {
}
}

#[derive(Copy, Clone)]
pub enum HandleCycleError {
Error,
Fatal,
DelayBug,
}

#[derive(SessionSubdiagnostic)]
pub enum StackCount {
#[note(query_system::cycle_stack_single)]
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_query_system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ pub mod dep_graph;
mod error;
pub mod ich;
pub mod query;
mod values;

pub use error::HandleCycleError;
pub use values::Value;
5 changes: 3 additions & 2 deletions compiler/rustc_query_system/src/query/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
use crate::dep_graph::DepNode;
use crate::dep_graph::SerializedDepNodeIndex;
use crate::error::HandleCycleError;
use crate::ich::StableHashingContext;
use crate::query::caches::QueryCache;
use crate::query::{QueryContext, QueryState};

use rustc_data_structures::fingerprint::Fingerprint;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use std::fmt::Debug;
use std::hash::Hash;

Expand All @@ -19,6 +19,7 @@ pub trait QueryConfig {
type Stored: Clone;
}

#[derive(Copy, Clone)]
pub struct QueryVTable<CTX: QueryContext, K, V> {
pub anon: bool,
pub dep_kind: CTX::DepKind,
Expand All @@ -28,7 +29,7 @@ pub struct QueryVTable<CTX: QueryContext, K, V> {

pub compute: fn(CTX::DepContext, K) -> V,
pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>,
pub handle_cycle_error: fn(CTX, DiagnosticBuilder<'_, ErrorGuaranteed>) -> V,
pub handle_cycle_error: HandleCycleError,
pub try_load_from_disk: Option<fn(CTX, SerializedDepNodeIndex) -> Option<V>>,
}

Expand Down
38 changes: 35 additions & 3 deletions compiler/rustc_query_system/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crate::query::caches::QueryCache;
use crate::query::config::{QueryDescription, QueryVTable};
use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo};
use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame};
use crate::values::Value;
use crate::HandleCycleError;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
#[cfg(parallel_compiler)]
Expand Down Expand Up @@ -118,19 +120,46 @@ where
fn mk_cycle<CTX, V, R>(
tcx: CTX,
error: CycleError,
handle_cycle_error: fn(CTX, DiagnosticBuilder<'_, ErrorGuaranteed>) -> V,
handler: HandleCycleError,
cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
) -> R
where
CTX: QueryContext,
V: std::fmt::Debug,
V: std::fmt::Debug + Value<CTX::DepContext>,
R: Clone,
{
let error = report_cycle(tcx.dep_context().sess(), error);
let value = handle_cycle_error(tcx, error);
let value = handle_cycle_error(*tcx.dep_context(), error, handler);
cache.store_nocache(value)
}

fn handle_cycle_error<CTX, V>(
tcx: CTX,
mut error: DiagnosticBuilder<'_, ErrorGuaranteed>,
handler: HandleCycleError,
) -> V
where
CTX: DepContext,
V: Value<CTX>,
{
use HandleCycleError::*;
match handler {
Error => {
error.emit();
Value::from_cycle_error(tcx)
}
Fatal => {
error.emit();
tcx.sess().abort_if_errors();
unreachable!()
}
DelayBug => {
error.delay_as_bug();
Value::from_cycle_error(tcx)
}
}
}

impl<'tcx, K> JobOwner<'tcx, K>
where
K: Eq + Hash + Clone,
Expand Down Expand Up @@ -336,6 +365,7 @@ fn try_execute_query<CTX, C>(
where
C: QueryCache,
C::Key: Clone + DepNodeParams<CTX::DepContext>,
C::Value: Value<CTX::DepContext>,
CTX: QueryContext,
{
match JobOwner::<'_, C::Key>::try_start(&tcx, state, span, key.clone()) {
Expand Down Expand Up @@ -686,6 +716,7 @@ pub fn get_query<Q, CTX>(tcx: CTX, span: Span, key: Q::Key, mode: QueryMode) ->
where
Q: QueryDescription<CTX>,
Q::Key: DepNodeParams<CTX::DepContext>,
Q::Value: Value<CTX::DepContext>,
CTX: QueryContext,
{
let query = Q::make_vtable(tcx, &key);
Expand Down Expand Up @@ -718,6 +749,7 @@ pub fn force_query<Q, CTX>(tcx: CTX, key: Q::Key, dep_node: DepNode<CTX::DepKind
where
Q: QueryDescription<CTX>,
Q::Key: DepNodeParams<CTX::DepContext>,
Q::Value: Value<CTX::DepContext>,
CTX: QueryContext,
{
// We may be concurrently trying both execute and force a query.
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_query_system/src/values.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::dep_graph::DepContext;

pub trait Value<CTX: DepContext>: Sized {
fn from_cycle_error(tcx: CTX) -> Self;
}

impl<CTX: DepContext, T> Value<CTX> for T {
default fn from_cycle_error(tcx: CTX) -> T {
tcx.sess().abort_if_errors();
// Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's
// non-trivial to define it earlier.
panic!("Value::from_cycle_error called without errors");
}
}

0 comments on commit 4856aff

Please sign in to comment.