Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make HandleCycleError an enum instead of a macro-generated closure #101303

Merged
merged 1 commit into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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");
}
}