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

Always emit an error for a query cycle #57880

Merged
merged 2 commits into from
Feb 16, 2019
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
4 changes: 4 additions & 0 deletions src/librustc/ich/impls_ty.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading