use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use crate::middle::stability;
use crate::mir::{self, Mir, interpret, ProjectionKind};
-use crate::mir::interpret::Allocation;
-use crate::ty::subst::{Kind, InternalSubsts, Subst, SubstsRef};
+use crate::mir::interpret::{ConstValue, Allocation};
+use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst};
use crate::ty::ReprOptions;
use crate::traits;
use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
use crate::ty::RegionKind;
-use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
+use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid};
use crate::ty::TyKind::*;
+use crate::ty::{InferConst, ParamConst};
use crate::ty::GenericParamDefKind;
use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx};
use crate::ty::query;
use crate::ty::subst::{UserSubsts, UnpackedKind};
use crate::ty::{BoundVar, BindingMode};
use crate::ty::CanonicalPolyFnSig;
- use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap};
+ use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet};
use crate::util::nodemap::{FxHashMap, FxHashSet};
use errors::DiagnosticBuilder;
use rustc_data_structures::interner::HashInterner;
StableVec};
use arena::{TypedArena, SyncDroplessArena};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::sync::{self, Lrc, Lock, WorkerLocal};
+use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
use std::any::Any;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt;
use std::mem;
use std::ops::{Deref, Bound};
-use std::ptr;
use std::iter;
use std::sync::mpsc;
use std::sync::Arc;
use std::marker::PhantomData;
use rustc_target::spec::abi;
-use syntax::ast::{self, NodeId};
+use syntax::ast;
use syntax::attr;
use syntax::source_map::MultiSpan;
use syntax::edition::Edition;
// Make sure we don't end up with inference
// types/regions in the global interner
- if ptr::eq(local, global) {
+ if ptr_eq(local, global) {
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
&ty_struct);
/// MIR construction and hence is not serialized to metadata.
fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
- /// Maps a cast expression to its kind. This is keyed on the
- /// *from* expression of the cast, not the cast itself.
- cast_kinds: ItemLocalMap<ty::cast::CastKind>,
+ /// For every coercion cast we add the HIR node ID of the cast
+ /// expression to this set.
+ coercion_casts: ItemLocalSet,
/// Set of trait imports actually used in the method resolution.
/// This is used for warning unused imports. During type
closure_kind_origins: Default::default(),
liberated_fn_sigs: Default::default(),
fru_field_types: Default::default(),
- cast_kinds: Default::default(),
+ coercion_casts: Default::default(),
used_trait_imports: Lrc::new(Default::default()),
tainted_by_errors: false,
free_region_map: Default::default(),
}
}
- pub fn cast_kinds(&self) -> LocalTableInContext<'_, ty::cast::CastKind> {
- LocalTableInContext {
- local_id_root: self.local_id_root,
- data: &self.cast_kinds
- }
+ pub fn is_coercion_cast(&self, hir_id: hir::HirId) -> bool {
+ validate_hir_id_for_typeck_tables(self.local_id_root, hir_id, true);
+ self.coercion_casts.contains(&hir_id.local_id)
}
- pub fn cast_kinds_mut(&mut self) -> LocalTableInContextMut<'_, ty::cast::CastKind> {
- LocalTableInContextMut {
- local_id_root: self.local_id_root,
- data: &mut self.cast_kinds
- }
+ pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
+ self.coercion_casts.insert(id);
+ }
+
+ pub fn coercion_casts(&self) -> &ItemLocalSet {
+ &self.coercion_casts
}
+
}
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
ref liberated_fn_sigs,
ref fru_field_types,
- ref cast_kinds,
+ ref coercion_casts,
ref used_trait_imports,
tainted_by_errors,
closure_kind_origins.hash_stable(hcx, hasher);
liberated_fn_sigs.hash_stable(hcx, hasher);
fru_field_types.hash_stable(hcx, hasher);
- cast_kinds.hash_stable(hcx, hasher);
+ coercion_casts.hash_stable(hcx, hasher);
used_trait_imports.hash_stable(hcx, hasher);
tainted_by_errors.hash_stable(hcx, hasher);
free_region_map.hash_stable(hcx, hasher);
}
_ => false,
},
+
+ UnpackedKind::Const(ct) => match ct {
+ ty::LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Infer(InferConst::Canonical(debruijn, b)),
+ ..
+ }) => {
+ // We only allow a `ty::INNERMOST` index in substitutions.
+ assert_eq!(*debruijn, ty::INNERMOST);
+ cvar == *b
+ }
+ _ => false,
+ },
}
})
},
/// Returns `true` if self is the same as self.global_tcx().
fn is_global(self) -> bool {
- ptr::eq(self.interners, &self.global_interners)
+ ptr_eq(self.interners, &self.global_interners)
}
/// Creates a type context and call the closure with a `TyCtxt` reference
let gcx = arenas.global_ctxt.as_ref().unwrap();
- sync::assert_send_val(&gcx);
-
let r = tls::enter_global(gcx, f);
gcx.queries.record_computed_queries(s);
_ => return None, // not a free region
};
- let node_id = self.hir()
- .as_local_node_id(suitable_region_binding_scope)
+ let hir_id = self.hir()
+ .as_local_hir_id(suitable_region_binding_scope)
.unwrap();
- let is_impl_item = match self.hir().find(node_id) {
+ let is_impl_item = match self.hir().find_by_hir_id(hir_id) {
Some(Node::Item(..)) | Some(Node::TraitItem(..)) => false,
Some(Node::ImplItem(..)) => {
self.is_bound_region_in_impl_item(suitable_region_binding_scope)
scope_def_id: DefId,
) -> Option<Ty<'tcx>> {
// HACK: `type_of_def_id()` will fail on these (#55796), so return None
- let node_id = self.hir().as_local_node_id(scope_def_id).unwrap();
- match self.hir().get(node_id) {
+ let hir_id = self.hir().as_local_hir_id(scope_def_id).unwrap();
+ match self.hir().get_by_hir_id(hir_id) {
Node::Item(item) => {
match item.node {
ItemKind::Fn(..) => { /* type_of_def_id() will work */ }
}
pub mod tls {
- use super::{GlobalCtxt, TyCtxt};
+ use super::{GlobalCtxt, TyCtxt, ptr_eq};
use std::fmt;
use std::mem;
use std::marker::PhantomData;
- use std::ptr;
use syntax_pos;
use crate::ty::query;
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
rayon_core::tlv::get()
}
- /// A thread local variable which stores a pointer to the current ImplicitCtxt
#[cfg(not(parallel_compiler))]
- thread_local!(static TLV: Cell<usize> = Cell::new(0));
+ thread_local! {
+ /// A thread local variable which stores a pointer to the current ImplicitCtxt.
+ static TLV: Cell<usize> = Cell::new(0);
+ }
/// Sets TLV to `value` during the call to `f`.
/// It is restored to its previous value after.
})
}
- /// Stores a pointer to the GlobalCtxt if one is available.
- /// This is used to access the GlobalCtxt in the deadlock handler
- /// given to Rayon.
- scoped_thread_local!(pub static GCX_PTR: Lock<usize>);
+ scoped_thread_local! {
+ /// Stores a pointer to the GlobalCtxt if one is available.
+ /// This is used to access the GlobalCtxt in the deadlock handler given to Rayon.
+ pub static GCX_PTR: Lock<usize>
+ }
/// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local.
/// This is used in the deadlock handler.
{
with_context(|context| {
unsafe {
- assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
+ assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
f(context)
}
{
with_context(|context| {
unsafe {
- assert!(ptr::eq(context.tcx.gcx, tcx.gcx));
- assert!(ptr::eq(context.tcx.interners, tcx.interners));
+ assert!(ptr_eq(context.tcx.gcx, tcx.gcx));
+ assert!(ptr_eq(context.tcx.interners, tcx.interners));
let context: &ImplicitCtxt<'_, '_, '_> = mem::transmute(context);
f(context)
}
#[derive(Copy, Clone)]
struct DebugStat {
total: usize,
- region_infer: usize,
+ lt_infer: usize,
ty_infer: usize,
- both_infer: usize,
+ ct_infer: usize,
+ all_infer: usize,
}
pub fn go(tcx: TyCtxt<'_, '_, '_>) {
let mut total = DebugStat {
total: 0,
- region_infer: 0, ty_infer: 0, both_infer: 0,
+ lt_infer: 0,
+ ty_infer: 0,
+ ct_infer: 0,
+ all_infer: 0,
};
$(let mut $variant = total;)*
ty::Error => /* unimportant */ continue,
$(ty::$variant(..) => &mut $variant,)*
};
- let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
+ let lt = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
+ let ct = t.flags.intersects(ty::TypeFlags::HAS_CT_INFER);
variant.total += 1;
total.total += 1;
- if region { total.region_infer += 1; variant.region_infer += 1 }
+ if lt { total.lt_infer += 1; variant.lt_infer += 1 }
if ty { total.ty_infer += 1; variant.ty_infer += 1 }
- if region && ty { total.both_infer += 1; variant.both_infer += 1 }
+ if ct { total.ct_infer += 1; variant.ct_infer += 1 }
+ if lt && ty && ct { total.all_infer += 1; variant.all_infer += 1 }
}
- println!("Ty interner total ty region both");
+ println!("Ty interner total ty lt ct all");
$(println!(" {:18}: {uses:6} {usespc:4.1}%, \
- {ty:4.1}% {region:5.1}% {both:4.1}%",
- stringify!($variant),
- uses = $variant.total,
- usespc = $variant.total as f64 * 100.0 / total.total as f64,
- ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
- region = $variant.region_infer as f64 * 100.0 / total.total as f64,
- both = $variant.both_infer as f64 * 100.0 / total.total as f64);
- )*
+ {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
+ stringify!($variant),
+ uses = $variant.total,
+ usespc = $variant.total as f64 * 100.0 / total.total as f64,
+ ty = $variant.ty_infer as f64 * 100.0 / total.total as f64,
+ lt = $variant.lt_infer as f64 * 100.0 / total.total as f64,
+ ct = $variant.ct_infer as f64 * 100.0 / total.total as f64,
+ all = $variant.all_infer as f64 * 100.0 / total.total as f64);
+ )*
println!(" total {uses:6} \
- {ty:4.1}% {region:5.1}% {both:4.1}%",
- uses = total.total,
- ty = total.ty_infer as f64 * 100.0 / total.total as f64,
- region = total.region_infer as f64 * 100.0 / total.total as f64,
- both = total.both_infer as f64 * 100.0 / total.total as f64)
+ {ty:4.1}% {lt:5.1}% {ct:4.1}% {all:4.1}%",
+ uses = total.total,
+ ty = total.ty_infer as f64 * 100.0 / total.total as f64,
+ lt = total.lt_infer as f64 * 100.0 / total.total as f64,
+ ct = total.ct_infer as f64 * 100.0 / total.total as f64,
+ all = total.all_infer as f64 * 100.0 / total.total as f64)
}
}
self.mk_fn_sig(
params_iter,
s.output(),
- s.variadic,
+ s.c_variadic,
hir::Unsafety::Normal,
abi::Abi::Rust,
)
let adt_def = self.adt_def(def_id);
let substs = InternalSubsts::for_item(self, def_id, |param, substs| {
match param.kind {
- GenericParamDefKind::Lifetime => bug!(),
+ GenericParamDefKind::Lifetime |
+ GenericParamDefKind::Const => {
+ bug!()
+ }
GenericParamDefKind::Type { has_default, .. } => {
if param.index == 0 {
ty.into()
}
#[inline]
- pub fn mk_var(self, v: TyVid) -> Ty<'tcx> {
+ pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
self.mk_infer(TyVar(v))
}
+ #[inline]
+ pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
+ self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Infer(InferConst::Var(v)),
+ ty,
+ }))
+ }
+
#[inline]
pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
self.mk_infer(IntVar(v))
self.mk_ty(Param(ParamTy { idx: index, name: name }))
}
+ #[inline]
+ pub fn mk_const_param(
+ self,
+ index: u32,
+ name: InternedString,
+ ty: Ty<'tcx>
+ ) -> &'tcx LazyConst<'tcx> {
+ self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+ val: ConstValue::Param(ParamConst { index, name }),
+ ty,
+ }))
+ }
+
#[inline]
pub fn mk_self_type(self) -> Ty<'tcx> {
self.mk_ty_param(0, keywords::SelfUpper.name().as_interned_str())
GenericParamDefKind::Lifetime => {
self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
}
- GenericParamDefKind::Type {..} => self.mk_ty_param(param.index, param.name).into(),
+ GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
+ GenericParamDefKind::Const => {
+ self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into()
+ }
}
}
pub fn mk_fn_sig<I>(self,
inputs: I,
output: I::Item,
- variadic: bool,
+ c_variadic: bool,
unsafety: hir::Unsafety,
abi: abi::Abi)
-> <I::Item as InternIteratorElement<Ty<'tcx>, ty::FnSig<'tcx>>>::Output
{
inputs.chain(iter::once(output)).intern_with(|xs| ty::FnSig {
inputs_and_output: self.intern_type_list(xs),
- variadic, unsafety, abi
+ c_variadic, unsafety, abi
})
}
self.struct_span_lint_hir(lint, hir_id, span.into(), msg).emit()
}
- pub fn lint_node<S: Into<MultiSpan>>(self,
- lint: &'static Lint,
- id: NodeId,
- span: S,
- msg: &str) {
- self.struct_span_lint_node(lint, id, span.into(), msg).emit()
- }
-
pub fn lint_hir_note<S: Into<MultiSpan>>(self,
lint: &'static Lint,
hir_id: HirId,
err.emit()
}
- pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId)
+ pub fn lint_level_at_node(self, lint: &'static Lint, mut id: hir::HirId)
-> (lint::Level, lint::LintSource)
{
// Right now we insert a `with_ignore` node in the dep graph here to
self.dep_graph.with_ignore(|| {
let sets = self.lint_levels(LOCAL_CRATE);
loop {
- let hir_id = self.hir().definitions().node_to_hir_id(id);
- if let Some(pair) = sets.level_and_source(lint, hir_id, self.sess) {
+ if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
return pair
}
- let next = self.hir().get_parent_node(id);
+ let next = self.hir().get_parent_node_by_hir_id(id);
if next == id {
bug!("lint traversal reached the root of the crate");
}
msg: &str)
-> DiagnosticBuilder<'tcx>
{
- let node_id = self.hir().hir_to_node_id(hir_id);
- let (level, src) = self.lint_level_at_node(lint, node_id);
+ let (level, src) = self.lint_level_at_node(lint, hir_id);
lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
}
- pub fn struct_span_lint_node<S: Into<MultiSpan>>(self,
- lint: &'static Lint,
- id: NodeId,
- span: S,
- msg: &str)
- -> DiagnosticBuilder<'tcx>
- {
- let (level, src) = self.lint_level_at_node(lint, id);
- lint::struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg)
- }
-
- pub fn struct_lint_node(self, lint: &'static Lint, id: NodeId, msg: &str)
+ pub fn struct_lint_node(self, lint: &'static Lint, id: HirId, msg: &str)
-> DiagnosticBuilder<'tcx>
{
let (level, src) = self.lint_level_at_node(lint, id);
}
}
+// We are comparing types with different invariant lifetimes, so `ptr::eq`
+// won't work for us.
+fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
+ t as *const () == u as *const ()
+}
+
pub fn provide(providers: &mut ty::query::Providers<'_>) {
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();
use crate::hair::util::UserAnnotatedTyHelpers;
use rustc_data_structures::indexed_vec::Idx;
use rustc::hir::def::{Def, CtorKind};
-use rustc::mir::interpret::{GlobalId, ErrorHandled};
+use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
- use rustc::ty::cast::CastKind as TyCastKind;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::hir;
use rustc::hir::def_id::LocalDefId;
ExprKind::NeverToAny { source: expr.to_ref() }
}
Adjust::MutToConstPointer => {
- ExprKind::Cast { source: expr.to_ref() }
+ ExprKind::MutToConstPointer { source: expr.to_ref() }
}
Adjust::Deref(None) => {
// Adjust the span from the block, to the last expression of the
span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty);
}
};
- let expr_node_id = cx.tcx.hir().hir_to_node_id(expr.hir_id);
- let upvars = cx.tcx.with_freevars(expr_node_id, |freevars| {
+ let upvars = cx.tcx.with_freevars(expr.hir_id, |freevars| {
freevars.iter()
.zip(substs.upvar_tys(def_id, cx.tcx))
.map(|(fv, ty)| capture_freevar(cx, expr, fv, ty))
// Now comes the rote stuff:
hir::ExprKind::Repeat(ref v, ref count) => {
- let def_id = cx.tcx.hir().local_def_id(count.id);
+ let def_id = cx.tcx.hir().local_def_id_from_hir_id(count.hir_id);
let substs = InternalSubsts::identity_for_item(cx.tcx.global_tcx(), def_id);
let instance = ty::Instance::resolve(
cx.tcx.global_tcx(),
match dest.target_id {
Ok(target_id) => ExprKind::Break {
label: region::Scope {
- id: cx.tcx.hir().node_to_hir_id(target_id).local_id,
+ id: target_id.local_id,
data: region::ScopeData::Node
},
value: value.to_ref(),
match dest.target_id {
Ok(loop_id) => ExprKind::Continue {
label: region::Scope {
- id: cx.tcx.hir().node_to_hir_id(loop_id).local_id,
+ id: loop_id.local_id,
data: region::ScopeData::Node
},
},
// Check to see if this cast is a "coercion cast", where the cast is actually done
// using a coercion (or is a no-op).
- let cast = if let Some(&TyCastKind::CoercionCast) =
- cx.tables()
- .cast_kinds()
- .get(source.hir_id)
- {
+ let cast = if cx.tables().is_coercion_cast(source.hir_id) {
// Convert the lexpr to a vexpr.
ExprKind::Use { source: source.to_ref() }
} else {
};
let source = if let Some((did, offset, var_ty)) = var {
- let mk_const = |literal| Expr {
+ let mk_lazy_const = |literal| Expr {
temp_lifetime,
ty: var_ty,
span: expr.span,
user_ty: None
},
}.to_ref();
- let offset = mk_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
+ let offset = mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
cx.tcx,
offset as u128,
cx.param_env.and(var_ty),
// in case we are offsetting from a computed discriminant
// and not the beginning of discriminants (which is always `0`)
let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
- let lhs = mk_const(ty::LazyConst::Unevaluated(did, substs));
+ let lhs = mk_lazy_const(ty::LazyConst::Unevaluated(did, substs));
let bin = ExprKind::Binary {
op: BinOp::Add,
lhs,
))),
user_ty,
}
- },
+ }
+
+ Def::ConstParam(def_id) => {
+ let node_id = cx.tcx.hir().as_local_node_id(def_id).unwrap();
+ let item_id = cx.tcx.hir().get_parent_node(node_id);
+ let item_def_id = cx.tcx.hir().local_def_id(item_id);
+ let generics = cx.tcx.generics_of(item_def_id);
+ let index = generics.param_def_id_to_index[&cx.tcx.hir().local_def_id(node_id)];
+ let name = cx.tcx.hir().name(node_id).as_interned_str();
+ let val = ConstValue::Param(ty::ParamConst::new(index, name));
+ ExprKind::Literal {
+ literal: cx.tcx.mk_lazy_const(
+ ty::LazyConst::Evaluated(ty::Const {
+ val,
+ ty: cx.tables().node_type(expr.hir_id),
+ })
+ ),
+ user_ty: None,
+ }
+ }
Def::Const(def_id) |
Def::AssociatedConst(def_id) => {
let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
match def {
- Def::Local(id) => ExprKind::VarRef { id },
+ Def::Local(id) => ExprKind::VarRef { id: cx.tcx.hir().node_to_hir_id(id) },
Def::Upvar(var_id, index, closure_expr_id) => {
debug!("convert_var(upvar({:?}, {:?}, {:?}))",