Skip to content
Open
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_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,7 @@ fn check_type_defn<'tcx>(
item: &hir::Item<'tcx>,
all_sized: bool,
) -> Result<(), ErrorGuaranteed> {
// Check for a cycle
let _ = tcx.representability(item.owner_id.def_id);
let adt_def = tcx.adt_def(item.owner_id);

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
solve::provide(&mut providers.queries);
rustc_passes::provide(&mut providers.queries);
rustc_traits::provide(&mut providers.queries);
rustc_ty_utils::provide(&mut providers.queries);
rustc_ty_utils::provide(providers);
rustc_metadata::provide(providers);
rustc_lint::provide(&mut providers.queries);
rustc_symbol_mangling::provide(&mut providers.queries);
Expand Down Expand Up @@ -981,6 +981,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
rustc_query_impl::query_system(
providers.queries,
providers.extern_queries,
providers.query_cycle_handlers,
query_result_on_disk_cache,
incremental,
),
Expand Down
13 changes: 6 additions & 7 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,27 +592,26 @@ rustc_queries! {
separate_provide_extern
}

/// Checks whether a type is representable or infinitely sized
query representability(key: LocalDefId) -> rustc_middle::ty::Representability {
/// Checks whether a type is representable or infinitely sized, emits a cycle error if it's not.
query representability(key: LocalDefId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably be check_representable or sth now

desc { "checking if `{}` is representable", tcx.def_path_str(key) }
// infinitely sized types will cause a cycle
cycle_delay_bug
// we don't want recursive representability calls to be forced with
// incremental compilation because, if a cycle occurs, we need the
// entire cycle to be in memory for diagnostics
anon
}

/// An implementation detail for the `representability` query
query representability_adt_ty(key: Ty<'tcx>) -> rustc_middle::ty::Representability {
query representability_adt_ty(key: Ty<'tcx>) {
desc { "checking if `{}` is representable", key }
cycle_delay_bug
anon
}

/// Set of param indexes for type params that are in the type's representation
///
/// An implementation detail for the `representability` query
query params_in_repr(key: DefId) -> &'tcx rustc_index::bit_set::DenseBitSet<u32> {
desc { "finding type parameters in the representation" }
desc { "finding type parameters in the representation of `{}`", tcx.def_path_str(key) }
arena_cache
no_hash
separate_provide_extern
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,6 @@ impl_erasable_for_simple_types! {
rustc_middle::ty::Destructor,
rustc_middle::ty::fast_reject::SimplifiedType,
rustc_middle::ty::ImplPolarity,
rustc_middle::ty::Representability,
rustc_middle::ty::UnusedGenericParams,
rustc_middle::ty::util::AlwaysRequiresDrop,
rustc_middle::ty::Visibility<rustc_span::def_id::DefId>,
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_middle/src/query/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use crate::dep_graph;
use crate::dep_graph::{DepKind, DepNodeIndex, SerializedDepNodeIndex};
use crate::ich::StableHashingContext;
use crate::queries::{
ExternProviders, PerQueryVTables, Providers, QueryArenas, QueryCaches, QueryEngine, QueryStates,
CycleHandlers, ExternProviders, PerQueryVTables, Providers, QueryArenas, QueryCaches,
QueryEngine, QueryStates,
};
use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
use crate::query::stack::{QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra};
Expand Down Expand Up @@ -146,6 +147,7 @@ pub struct QuerySystemFns {
pub engine: QueryEngine,
pub local_providers: Providers,
pub extern_providers: ExternProviders,
pub cycle_handlers: CycleHandlers,
pub encode_query_results: for<'tcx> fn(
tcx: TyCtxt<'tcx>,
encoder: &mut CacheEncoder<'_, 'tcx>,
Expand Down Expand Up @@ -565,6 +567,18 @@ macro_rules! define_callbacks {
fn clone(&self) -> Self { *self }
}

#[derive(Default)]
pub struct CycleHandlers {
$(
pub $name: Option<fn(TyCtxt<'_>, &$crate::query::CycleError) -> Option<ErrorGuaranteed>>,
)*
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be put into QueryVTables, like in #152835?


impl Copy for CycleHandlers {}
impl Clone for CycleHandlers {
fn clone(&self) -> Self { *self }
}

pub struct QueryEngine {
$(
pub $name: for<'tcx> fn(
Expand Down
17 changes: 5 additions & 12 deletions compiler/rustc_middle/src/query/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use std::sync::Arc;

use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_hir::def::DefKind;
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_span::{ErrorGuaranteed, Span};

use crate::dep_graph::DepKind;
use crate::query::CycleError;
use crate::ty::TyCtxt;

/// Description of a frame in the query stack.
///
Expand All @@ -20,27 +22,18 @@ pub struct QueryStackFrame<I> {
/// by calling `lift`. This is done so that collecting query does not need to invoke
/// queries, instead `lift` will call queries in a more appropriate location.
pub info: I,

pub cycle_handler: Option<fn(TyCtxt<'_>, &CycleError) -> Option<ErrorGuaranteed>>,
pub dep_kind: DepKind,
pub def_id: Option<DefId>,
/// A def-id that is extracted from a `Ty` in a query key
pub def_id_for_ty_in_cycle: Option<DefId>,
}

impl<'tcx> QueryStackFrame<QueryStackDeferred<'tcx>> {
#[inline]
pub fn new(
info: QueryStackDeferred<'tcx>,
dep_kind: DepKind,
def_id: Option<DefId>,
def_id_for_ty_in_cycle: Option<DefId>,
) -> Self {
Self { info, def_id, dep_kind, def_id_for_ty_in_cycle }
}

pub fn lift(&self) -> QueryStackFrame<QueryStackFrameExtra> {
QueryStackFrame {
info: self.info.extract(),
cycle_handler: self.cycle_handler,
dep_kind: self.dep_kind,
def_id: self.def_id,
def_id_for_ty_in_cycle: self.def_id_for_ty_in_cycle,
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_middle/src/ty/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,9 +672,3 @@ impl<'tcx> AdtDef<'tcx> {
if self.is_struct() { tcx.adt_sizedness_constraint((self.did(), sizedness)) } else { None }
}
}

#[derive(Clone, Copy, Debug, HashStable)]
pub enum Representability {
Representable,
Infinite(ErrorGuaranteed),
}
5 changes: 2 additions & 3 deletions compiler/rustc_middle/src/ty/inhabitedness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ pub(crate) fn provide(providers: &mut Providers) {
/// requires calling [`InhabitedPredicate::instantiate`]
fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
if let Some(def_id) = def_id.as_local() {
if matches!(tcx.representability(def_id), ty::Representability::Infinite(_)) {
return InhabitedPredicate::True;
}
// Check for a cycle
let _ = tcx.representability(def_id);
}
let adt = tcx.adt_def(def_id);
InhabitedPredicate::any(
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ pub mod bug;
pub struct Providers {
pub queries: crate::queries::Providers,
pub extern_queries: crate::queries::ExternProviders,
pub query_cycle_handlers: crate::queries::CycleHandlers,
pub hooks: crate::hooks::Providers,
}
9 changes: 9 additions & 0 deletions compiler/rustc_query_impl/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ fn mk_cycle<'tcx, C: QueryCache, const FLAGS: QueryFlags>(
tcx: TyCtxt<'tcx>,
cycle_error: CycleError,
) -> C::Value {
// Check if any queries in the cycle can handle this cycle error
for query in &cycle_error.cycle {
if let Some(cycle_handler) = query.frame.cycle_handler
&& let Some(guard) = cycle_handler(tcx, &cycle_error)
{
guard.raise_fatal();
}
}

let error = report_cycle(tcx.sess, &cycle_error);
handle_cycle_error(query, tcx, &cycle_error, error)
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_query_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use std::marker::ConstParamTy;
use rustc_data_structures::sync::AtomicU64;
use rustc_middle::dep_graph::{self, DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
use rustc_middle::queries::{
self, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
self, CycleHandlers, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
};
use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
use rustc_middle::query::plumbing::{
Expand Down Expand Up @@ -239,6 +239,7 @@ trait QueryDispatcherUnerased<'tcx, C: QueryCache, const FLAGS: QueryFlags> {
pub fn query_system<'tcx>(
local_providers: Providers,
extern_providers: ExternProviders,
cycle_decor_providers: CycleHandlers,
on_disk_cache: Option<OnDiskCache>,
incremental: bool,
) -> QuerySystem<'tcx> {
Expand All @@ -252,6 +253,7 @@ pub fn query_system<'tcx>(
engine: engine(incremental),
local_providers,
extern_providers,
cycle_handlers: cycle_decor_providers,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type is called CycleHandlers, the field is named cycle_handlers. Why is the parameter called cycle_decor_providers?

encode_query_results: encode_all_query_results,
try_mark_green,
},
Expand Down
18 changes: 13 additions & 5 deletions compiler/rustc_query_impl/src/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ use rustc_middle::query::on_disk_cache::{
};
use rustc_middle::query::plumbing::QueryVTable;
use rustc_middle::query::{
Key, QueryCache, QueryJobId, QueryStackDeferred, QueryStackFrame, QueryStackFrameExtra,
CycleError, Key, QueryCache, QueryJobId, QueryStackDeferred, QueryStackFrame,
QueryStackFrameExtra,
};
use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::print::with_reduced_queries;
use rustc_middle::ty::tls::{self, ImplicitCtxt};
use rustc_middle::ty::{self, TyCtxt};
use rustc_serialize::{Decodable, Encodable};
use rustc_span::ErrorGuaranteed;
use rustc_span::def_id::LOCAL_CRATE;

use crate::error::{QueryOverflow, QueryOverflowNote};
Expand Down Expand Up @@ -309,19 +311,24 @@ where
pub(crate) fn create_deferred_query_stack_frame<'tcx, Cache>(
tcx: TyCtxt<'tcx>,
vtable: &'tcx QueryVTable<'tcx, Cache>,
cycle_handler: Option<fn(TyCtxt<'_>, &CycleError) -> Option<ErrorGuaranteed>>,
key: Cache::Key,
) -> QueryStackFrame<QueryStackDeferred<'tcx>>
where
Cache: QueryCache,
Cache::Key: Key + DynSend + DynSync,
{
let kind = vtable.dep_kind;

let def_id: Option<DefId> = key.key_as_def_id();
let def_id_for_ty_in_cycle: Option<DefId> = key.def_id_for_ty_in_cycle();

let info = QueryStackDeferred::new((tcx, vtable, key), mk_query_stack_frame_extra);
QueryStackFrame::new(info, kind, def_id, def_id_for_ty_in_cycle)
QueryStackFrame {
info,
cycle_handler,
dep_kind: vtable.dep_kind,
def_id,
def_id_for_ty_in_cycle,
}
}

pub(crate) fn encode_query_results<'a, 'tcx, Q, C: QueryCache, const FLAGS: QueryFlags>(
Expand Down Expand Up @@ -647,7 +654,8 @@ macro_rules! define_queries {
) -> Option<()> {
let make_frame = |tcx: TyCtxt<'tcx>, key| {
let vtable = &tcx.query_system.query_vtables.$name;
$crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, key)
let cycle_decorator = tcx.query_system.fns.cycle_handlers.$name;
$crate::plumbing::create_deferred_query_stack_frame(tcx, vtable, cycle_decorator, key)
};

// Call `gather_active_jobs_inner` to do the actual work.
Expand Down
Loading
Loading