use traits::{Clause, Clauses, GoalKind, Goal, Goals};
use ty::{self, Ty, TypeAndMut};
use ty::{TyS, TyKind, List};
-use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
+use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
use ty::RegionKind;
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
region: InternedSet<'tcx, RegionKind>,
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
- const_: InternedSet<'tcx, Const<'tcx>>,
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
goal: InternedSet<'tcx, GoalKind<'tcx>>,
goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
predicates: Default::default(),
- const_: Default::default(),
clauses: Default::default(),
goal: Default::default(),
goal_list: Default::default(),
self.global_arenas.adt_def.alloc(def)
}
- pub fn alloc_byte_array(self, bytes: &[u8]) -> &'gcx [u8] {
- if bytes.is_empty() {
- &[]
- } else {
- self.global_interners.arena.alloc_slice(bytes)
- }
- }
-
- pub fn alloc_const_slice(self, values: &[&'tcx ty::Const<'tcx>])
- -> &'tcx [&'tcx ty::Const<'tcx>] {
- if values.is_empty() {
- &[]
- } else {
- self.interners.arena.alloc_slice(values)
- }
- }
-
- pub fn alloc_name_const_slice(self, values: &[(ast::Name, &'tcx ty::Const<'tcx>)])
- -> &'tcx [(ast::Name, &'tcx ty::Const<'tcx>)] {
- if values.is_empty() {
- &[]
- } else {
- self.interners.arena.alloc_slice(values)
- }
- }
-
pub fn intern_const_alloc(
self,
alloc: Allocation,
})
}
+ pub fn intern_lazy_const(self, c: ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+ self.global_interners.arena.alloc(c)
+ }
+
pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
self.layout_interner.borrow_mut().intern(layout, |layout| {
self.global_arenas.layout.alloc(layout)
sync::assert_send_val(&gcx);
- tls::enter_global(gcx, f)
+ let r = tls::enter_global(gcx, f);
+
+ gcx.queries.record_computed_queries(s);
+
+ r
}
pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
let new_icx = ty::tls::ImplicitCtxt {
tcx,
query: icx.query.clone(),
+ diagnostics: icx.diagnostics,
layout_depth: icx.layout_depth,
- task: icx.task,
+ task_deps: icx.task_deps,
};
ty::tls::enter_context(&new_icx, |_| {
f(tcx)
fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted>;
}
-impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
- type Lifted = Ty<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for Region<'a> {
- type Lifted = Region<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Region<'tcx>> {
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for Goal<'a> {
- type Lifted = Goal<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Goal<'tcx>> {
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for &'a List<Goal<'a>> {
- type Lifted = &'tcx List<Goal<'tcx>>;
- fn lift_to_tcx<'b, 'gcx>(
- &self,
- tcx: TyCtxt<'b, 'gcx, 'tcx>,
- ) -> Option<&'tcx List<Goal<'tcx>>> {
- if self.is_empty() {
- return Some(List::empty());
- }
-
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for &'a List<Clause<'a>> {
- type Lifted = &'tcx List<Clause<'tcx>>;
- fn lift_to_tcx<'b, 'gcx>(
- &self,
- tcx: TyCtxt<'b, 'gcx, 'tcx>,
- ) -> Option<&'tcx List<Clause<'tcx>>> {
- if self.is_empty() {
- return Some(List::empty());
- }
-
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for &'a Const<'a> {
- type Lifted = &'tcx Const<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Const<'tcx>> {
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
-impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
- type Lifted = &'tcx Substs<'tcx>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> {
- if self.len() == 0 {
- return Some(List::empty());
- }
- if tcx.interners.arena.in_arena(&self[..] as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
+macro_rules! nop_lift {
+ ($ty:ty => $lifted:ty) => {
+ impl<'a, 'tcx> Lift<'tcx> for $ty {
+ type Lifted = $lifted;
+ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ if tcx.interners.arena.in_arena(*self as *const _) {
+ return Some(unsafe { mem::transmute(*self) });
+ }
+ // Also try in the global tcx if we're not that.
+ if !tcx.is_global() {
+ self.lift_to_tcx(tcx.global_tcx())
+ } else {
+ None
+ }
+ }
}
- }
+ };
}
-impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
- type Lifted = &'tcx List<Ty<'tcx>>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
- -> Option<&'tcx List<Ty<'tcx>>> {
- if self.len() == 0 {
- return Some(List::empty());
- }
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
+macro_rules! nop_list_lift {
+ ($ty:ty => $lifted:ty) => {
+ impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
+ type Lifted = &'tcx List<$lifted>;
+ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+ if self.is_empty() {
+ return Some(List::empty());
+ }
+ if tcx.interners.arena.in_arena(*self as *const _) {
+ return Some(unsafe { mem::transmute(*self) });
+ }
+ // Also try in the global tcx if we're not that.
+ if !tcx.is_global() {
+ self.lift_to_tcx(tcx.global_tcx())
+ } else {
+ None
+ }
+ }
}
- }
+ };
}
-impl<'a, 'tcx> Lift<'tcx> for &'a List<ExistentialPredicate<'a>> {
- type Lifted = &'tcx List<ExistentialPredicate<'tcx>>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
- -> Option<&'tcx List<ExistentialPredicate<'tcx>>> {
- if self.is_empty() {
- return Some(List::empty());
- }
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
+nop_lift!{Ty<'a> => Ty<'tcx>}
+nop_lift!{Region<'a> => Region<'tcx>}
+nop_lift!{Goal<'a> => Goal<'tcx>}
+nop_lift!{&'a LazyConst<'a> => &'tcx LazyConst<'tcx>}
-impl<'a, 'tcx> Lift<'tcx> for &'a List<Predicate<'a>> {
- type Lifted = &'tcx List<Predicate<'tcx>>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
- -> Option<&'tcx List<Predicate<'tcx>>> {
- if self.is_empty() {
- return Some(List::empty());
- }
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
+nop_list_lift!{Goal<'a> => Goal<'tcx>}
+nop_list_lift!{Clause<'a> => Clause<'tcx>}
+nop_list_lift!{Ty<'a> => Ty<'tcx>}
+nop_list_lift!{ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
+nop_list_lift!{Predicate<'a> => Predicate<'tcx>}
+nop_list_lift!{CanonicalVarInfo => CanonicalVarInfo}
+nop_list_lift!{ProjectionKind<'a> => ProjectionKind<'tcx>}
-impl<'a, 'tcx> Lift<'tcx> for &'a List<CanonicalVarInfo> {
- type Lifted = &'tcx List<CanonicalVarInfo>;
- fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- if self.len() == 0 {
- return Some(List::empty());
- }
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
- }
-}
+// this is the impl for `&'a Substs<'a>`
+nop_list_lift!{Kind<'a> => Kind<'tcx>}
-impl<'a, 'tcx> Lift<'tcx> for &'a List<ProjectionKind<'a>> {
- type Lifted = &'tcx List<ProjectionKind<'tcx>>;
+impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation {
+ type Lifted = &'tcx mir::interpret::Allocation;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- if self.len() == 0 {
- return Some(List::empty());
- }
- if tcx.interners.arena.in_arena(*self as *const _) {
- return Some(unsafe { mem::transmute(*self) });
- }
- // Also try in the global tcx if we're not that.
- if !tcx.is_global() {
- self.lift_to_tcx(tcx.global_tcx())
- } else {
- None
- }
+ assert!(tcx.global_arenas.const_allocs.in_arena(*self as *const _));
+ Some(unsafe { mem::transmute(*self) })
}
}
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
use rustc_data_structures::OnDrop;
use rustc_data_structures::sync::{self, Lrc, Lock};
- use dep_graph::OpenTask;
+ use rustc_data_structures::thin_vec::ThinVec;
+ use dep_graph::TaskDeps;
#[cfg(not(parallel_queries))]
use std::cell::Cell;
/// by `enter_local` with a new local interner
pub tcx: TyCtxt<'tcx, 'gcx, 'tcx>,
- /// The current query job, if any. This is updated by start_job in
+ /// The current query job, if any. This is updated by JobOwner::start in
/// ty::query::plumbing when executing a query
pub query: Option<Lrc<query::QueryJob<'gcx>>>,
+ /// Where to store diagnostics for the current query job, if any.
+ /// This is updated by JobOwner::start in ty::query::plumbing when executing a query
+ pub diagnostics: Option<&'a Lock<ThinVec<Diagnostic>>>,
+
/// Used to prevent layout from recursing too deeply.
pub layout_depth: usize,
/// The current dep graph task. This is used to add dependencies to queries
/// when executing them
- pub task: &'a OpenTask,
+ pub task_deps: Option<&'a Lock<TaskDeps>>,
}
/// Sets Rayon's thread local variable which is preserved for Rayon jobs
fn track_diagnostic(diagnostic: &Diagnostic) {
with_context_opt(|icx| {
if let Some(icx) = icx {
- if let Some(ref query) = icx.query {
- query.diagnostics.lock().push(diagnostic.clone());
+ if let Some(ref diagnostics) = icx.diagnostics {
+ let mut diagnostics = diagnostics.lock();
+ diagnostics.extend(Some(diagnostic.clone()));
}
}
})
let icx = ImplicitCtxt {
tcx,
query: None,
+ diagnostics: None,
layout_depth: 0,
- task: &OpenTask::Ignore,
+ task_deps: None,
};
enter_context(&icx, |_| {
f(tcx)
};
let icx = ImplicitCtxt {
query: None,
+ diagnostics: None,
tcx,
layout_depth: 0,
- task: &OpenTask::Ignore,
+ task_deps: None,
};
enter_context(&icx, |_| f(tcx))
}
direct_interners!('tcx,
region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
- const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>,
goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>
);
#[inline]
pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
- self.mk_ty(Array(ty, ty::Const::from_usize(self, n)))
+ self.mk_ty(Array(ty, self.intern_lazy_const(
+ ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n))
+ )))
}
#[inline]
}
pub fn provide(providers: &mut ty::query::Providers<'_>) {
- // FIXME(#44234): almost all of these queries have no sub-queries and
- // therefore no actual inputs, they're just reading tables calculated in
- // resolve! Does this work? Unsure! That's what the issue is about.
providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned();
providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned();
providers.crate_name = |tcx, id| {