Skip to content

Commit

Permalink
Always emit an error for a query cycle
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Feb 15, 2019
1 parent f47ec2a commit 82ec723
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 178 deletions.
4 changes: 4 additions & 0 deletions src/librustc/ich/impls_ty.rs
Expand Up @@ -206,6 +206,10 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::adjustment::AutoBorrow
}
}

impl_stable_hash_for!(tuple_struct ty::util::NeedsDrop { value });

impl_stable_hash_for!(tuple_struct ty::AdtSizedConstraint<'tcx> { list });

impl_stable_hash_for!(struct ty::UpvarPath { hir_id });

impl_stable_hash_for!(struct ty::UpvarId { var_path, closure_expr_id });
Expand Down
24 changes: 7 additions & 17 deletions src/librustc/ty/mod.rs
Expand Up @@ -43,7 +43,7 @@ use syntax::ast::{self, Name, Ident, NodeId};
use syntax::attr;
use syntax::ext::hygiene::Mark;
use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString};
use syntax_pos::{DUMMY_SP, Span};
use syntax_pos::Span;

use smallvec;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
Expand Down Expand Up @@ -2379,20 +2379,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
match tcx.try_adt_sized_constraint(DUMMY_SP, self.did) {
Ok(tys) => tys,
Err(mut bug) => {
debug!("adt_sized_constraint: {:?} is recursive", self);
// This should be reported as an error by `check_representable`.
//
// Consider the type as Sized in the meanwhile to avoid
// further errors. Delay our `bug` diagnostic here to get
// emitted later as well in case we accidentally otherwise don't
// emit an error.
bug.delay_as_bug();
tcx.intern_type_list(&[tcx.types.err])
}
}
tcx.adt_sized_constraint(self.did).0
}

fn sized_constraint_for_ty(&self,
Expand Down Expand Up @@ -3083,6 +3070,9 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Asso
parent_item.node)
}

#[derive(Clone)]
pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);

/// Calculates the `Sized` constraint.
///
/// In fact, there are only a few options for the types in the constraint:
Expand All @@ -3094,7 +3084,7 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Asso
/// check should catch this case.
fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> &'tcx [Ty<'tcx>] {
-> AdtSizedConstraint<'tcx> {
let def = tcx.adt_def(def_id);

let result = tcx.mk_type_list(def.variants.iter().flat_map(|v| {
Expand All @@ -3105,7 +3095,7 @@ fn adt_sized_constraint<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

debug!("adt_sized_constraint: {:?} => {:?}", def, result);

result
AdtSizedConstraint(result)
}

fn associated_item_def_ids<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/ty/query/config.rs
Expand Up @@ -13,6 +13,7 @@ use crate::ty::subst::Substs;
use crate::ty::query::queries;
use crate::ty::query::Query;
use crate::ty::query::QueryCache;
use crate::ty::query::plumbing::CycleError;
use crate::util::profiling::ProfileCategory;

use std::borrow::Cow;
Expand Down Expand Up @@ -49,7 +50,7 @@ pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
result: &Self::Value
) -> Option<Fingerprint>;

fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value;
fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>, error: CycleError<'tcx>) -> Self::Value;
}

pub(super) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
Expand Down
24 changes: 3 additions & 21 deletions src/librustc/ty/query/job.rs
Expand Up @@ -73,30 +73,12 @@ impl<'tcx> QueryJob<'tcx> {
}

/// Awaits for the query job to complete.
///
/// For single threaded rustc there's no concurrent jobs running, so if we are waiting for any
/// query that means that there is a query cycle, thus this always running a cycle error.
#[cfg(not(parallel_compiler))]
#[inline(never)]
#[cold]
pub(super) fn cycle_error<'lcx, 'a, D: QueryDescription<'tcx>>(
&self,
tcx: TyCtxt<'_, 'tcx, 'lcx>,
span: Span,
) -> TryGetJob<'a, 'tcx, D> {
TryGetJob::JobCompleted(Err(Box::new(self.find_cycle_in_stack(tcx, span))))
}

/// Awaits for the query job to complete.
///
/// For single threaded rustc there's no concurrent jobs running, so if we are waiting for any
/// query that means that there is a query cycle, thus this always running a cycle error.
#[cfg(parallel_compiler)]
pub(super) fn r#await<'lcx>(
&self,
tcx: TyCtxt<'_, 'tcx, 'lcx>,
span: Span,
) -> Result<(), Box<CycleError<'tcx>>> {
) -> Result<(), CycleError<'tcx>> {
tls::with_related_context(tcx, move |icx| {
let mut waiter = Lrc::new(QueryWaiter {
query: icx.query.clone(),
Expand All @@ -111,13 +93,13 @@ impl<'tcx> QueryJob<'tcx> {
let mut cycle = waiter.cycle.lock();
match cycle.take() {
None => Ok(()),
Some(cycle) => Err(Box::new(cycle))
Some(cycle) => Err(cycle)
}
})
}

#[cfg(not(parallel_compiler))]
fn find_cycle_in_stack<'lcx>(
pub(super) fn find_cycle_in_stack<'lcx>(
&self,
tcx: TyCtxt<'_, 'tcx, 'lcx>,
span: Span,
Expand Down
52 changes: 22 additions & 30 deletions src/librustc/ty/query/mod.rs
Expand Up @@ -34,15 +34,15 @@ use crate::traits::query::normalize::NormalizationResult;
use crate::traits::query::outlives_bounds::OutlivesBound;
use crate::traits::specialization_graph;
use crate::traits::Clauses;
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, AdtSizedConstraint};
use crate::ty::steal::Steal;
use crate::ty::subst::Substs;
use crate::ty::util::NeedsDrop;
use crate::util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
use crate::util::common::{ErrorReported};
use crate::util::profiling::ProfileCategory::*;
use crate::session::Session;

use errors::DiagnosticBuilder;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::indexed_vec::IndexVec;
Expand Down Expand Up @@ -154,7 +154,16 @@ define_queries! { <'tcx>
[] fn trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef,
[] fn adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef,
[] fn adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
[] fn adt_sized_constraint: SizedConstraint(DefId) -> &'tcx [Ty<'tcx>],

// The cycle error here should be reported as an error by `check_representable`.
// We consider the type as Sized in the meanwhile to avoid
// further errors (done in impl Value for AdtSizedConstraint).
// Use `cycle_delay_bug` to delay the cycle error here to be emitted later
// in case we accidentally otherwise don't emit an error.
[cycle_delay_bug] fn adt_sized_constraint: SizedConstraint(
DefId
) -> AdtSizedConstraint<'tcx>,

[] fn adt_dtorck_constraint: DtorckConstraint(
DefId
) -> Result<DtorckConstraint<'tcx>, NoSolution>,
Expand Down Expand Up @@ -411,7 +420,16 @@ define_queries! { <'tcx>
[] fn is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
[] fn is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
[] fn is_freeze_raw: is_freeze_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
[] fn needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,

// The cycle error here should be reported as an error by `check_representable`.
// We consider the type as not needing drop in the meanwhile to avoid
// further errors (done in impl Value for NeedsDrop).
// Use `cycle_delay_bug` to delay the cycle error here to be emitted later
// in case we accidentally otherwise don't emit an error.
[cycle_delay_bug] fn needs_drop_raw: needs_drop_dep_node(
ty::ParamEnvAnd<'tcx, Ty<'tcx>>
) -> NeedsDrop,

[] fn layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
-> Result<&'tcx ty::layout::LayoutDetails,
ty::layout::LayoutError<'tcx>>,
Expand Down Expand Up @@ -731,32 +749,6 @@ define_queries! { <'tcx>
},
}

// `try_get_query` can't be public because it uses the private query
// implementation traits, so we provide access to it selectively.
impl<'a, 'tcx, 'lcx> TyCtxt<'a, 'tcx, 'lcx> {
pub fn try_adt_sized_constraint(
self,
span: Span,
key: DefId,
) -> Result<&'tcx [Ty<'tcx>], Box<DiagnosticBuilder<'a>>> {
self.try_get_query::<queries::adt_sized_constraint<'_>>(span, key)
}
pub fn try_needs_drop_raw(
self,
span: Span,
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Result<bool, Box<DiagnosticBuilder<'a>>> {
self.try_get_query::<queries::needs_drop_raw<'_>>(span, key)
}
pub fn try_optimized_mir(
self,
span: Span,
key: DefId,
) -> Result<&'tcx mir::Mir<'tcx>, Box<DiagnosticBuilder<'a>>> {
self.try_get_query::<queries::optimized_mir<'_>>(span, key)
}
}

//////////////////////////////////////////////////////////////////////
// These functions are little shims used to find the dep-node for a
// given query when there is not a *direct* mapping:
Expand Down

0 comments on commit 82ec723

Please sign in to comment.