summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/ty')
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs23
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs30
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs5
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs31
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs40
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs10
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs19
-rw-r--r--compiler/rustc_middle/src/ty/context.rs244
-rw-r--r--compiler/rustc_middle/src/ty/context/tls.rs10
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs4
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs7
-rw-r--r--compiler/rustc_middle/src/ty/error.rs6
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs2
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs20
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs3
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs4
-rw-r--r--compiler/rustc_middle/src/ty/impls_ty.rs28
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs12
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs121
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs26
-rw-r--r--compiler/rustc_middle/src/ty/list.rs36
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs328
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs10
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs14
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs9
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs121
-rw-r--r--compiler/rustc_middle/src/ty/query.rs606
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs52
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs87
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs150
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs139
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs62
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs26
-rw-r--r--compiler/rustc_middle/src/ty/util.rs142
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs25
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs2
38 files changed, 924 insertions, 1538 deletions
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 468c2c818..cbc68fde9 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -83,7 +83,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
- _ => relate::super_relate_tys(self, a, b),
+ _ => relate::structurally_relate_tys(self, a, b),
}
}
@@ -109,7 +109,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
_ => {}
}
- relate::super_relate_consts(self, a, b)
+ relate::structurally_relate_consts(self, a, b)
}
fn binders<T>(
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index f889ce827..a39631da9 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -1,10 +1,9 @@
-//! A subset of a mir body used for const evaluatability checking.
+//! A subset of a mir body used for const evaluability checking.
use crate::ty::{
self, Const, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt,
};
use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def_id::DefId;
#[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)]
#[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)]
@@ -35,19 +34,6 @@ TrivialTypeTraversalAndLiftImpls! {
pub type BoundAbstractConst<'tcx> = Result<Option<EarlyBinder<ty::Const<'tcx>>>, ErrorGuaranteed>;
impl<'tcx> TyCtxt<'tcx> {
- /// Returns a const without substs applied
- pub fn bound_abstract_const(
- self,
- uv: ty::WithOptConstParam<DefId>,
- ) -> BoundAbstractConst<'tcx> {
- let ac = if let Some((did, param_did)) = uv.as_const_arg() {
- self.thir_abstract_const_of_const_arg((did, param_did))
- } else {
- self.thir_abstract_const(uv.did)
- };
- Ok(ac?.map(|ac| EarlyBinder(ac)))
- }
-
pub fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, ac: T) -> T {
struct Expander<'tcx> {
tcx: TyCtxt<'tcx>,
@@ -66,11 +52,12 @@ impl<'tcx> TyCtxt<'tcx> {
}
fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> {
let ct = match c.kind() {
- ty::ConstKind::Unevaluated(uv) => match self.tcx.bound_abstract_const(uv.def) {
- Err(e) => self.tcx.const_error_with_guaranteed(c.ty(), e),
+ ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
+ Err(e) => self.tcx.const_error(c.ty(), e),
Ok(Some(bac)) => {
let substs = self.tcx.erase_regions(uv.substs);
- bac.subst(self.tcx, substs)
+ let bac = bac.subst(self.tcx, substs);
+ return bac.fold_with(self);
}
Ok(None) => c,
},
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 3a03c0901..7c5c030c2 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
-use rustc_index::vec::{IndexSlice, IndexVec};
+use rustc_index::{IndexSlice, IndexVec};
use rustc_query_system::ich::StableHashingContext;
use rustc_session::DataTypeKind;
use rustc_span::symbol::sym;
@@ -26,7 +26,7 @@ use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, Var
bitflags! {
#[derive(HashStable, TyEncodable, TyDecodable)]
- pub struct AdtFlags: u32 {
+ pub struct AdtFlags: u16 {
const NO_ADT_FLAGS = 0;
/// Indicates whether the ADT is an enum.
const IS_ENUM = 1 << 0;
@@ -111,12 +111,30 @@ impl Ord for AdtDefData {
}
}
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `PartialEq` only based on `did`.
impl PartialEq for AdtDefData {
#[inline]
fn eq(&self, other: &Self) -> bool {
- self.did == other.did
+ // There should be only one `AdtDefData` for each `def_id`, therefore
+ // it is fine to implement `PartialEq` only based on `def_id`.
+ //
+ // Below, we exhaustively destructure `self` and `other` so that if the
+ // definition of `AdtDefData` changes, a compile-error will be produced,
+ // reminding us to revisit this assumption.
+
+ let Self { did: self_def_id, variants: _, flags: _, repr: _ } = self;
+ let Self { did: other_def_id, variants: _, flags: _, repr: _ } = other;
+
+ let res = self_def_id == other_def_id;
+
+ // Double check that implicit assumption detailed above.
+ if cfg!(debug_assertions) && res {
+ let deep = self.flags == other.flags
+ && self.repr == other.repr
+ && self.variants == other.variants;
+ assert!(deep, "AdtDefData for the same def-id has differing data");
+ }
+
+ res
}
}
@@ -188,7 +206,7 @@ impl<'tcx> AdtDef<'tcx> {
}
}
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, HashStable, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
pub enum AdtKind {
Struct,
Union,
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index f29bf92b0..be7b2b7ec 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -5,6 +5,7 @@ use crate::{mir, ty};
use std::fmt::Write;
+use crate::query::Providers;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{self as hir, LangItem};
@@ -457,6 +458,6 @@ impl BorrowKind {
}
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { closure_typeinfo, ..*providers }
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { closure_typeinfo, ..*providers }
}
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 8ef4a46a7..7fc75674d 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -19,6 +19,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::TyCtxt;
use rustc_serialize::{Decodable, Encodable};
use rustc_span::Span;
+use rustc_target::abi::FieldIdx;
pub use rustc_type_ir::{TyDecoder, TyEncoder};
use std::hash::Hash;
use std::intrinsics;
@@ -401,6 +402,15 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<FieldIdx> {
+ fn decode(decoder: &mut D) -> &'tcx Self {
+ let len = decoder.read_usize();
+ decoder
+ .interner()
+ .mk_fields_from_iter((0..len).map::<FieldIdx, _>(|_| Decodable::decode(decoder)))
+ }
+}
+
impl_decodable_via_ref! {
&'tcx ty::TypeckResults<'tcx>,
&'tcx ty::List<Ty<'tcx>>,
@@ -412,6 +422,7 @@ impl_decodable_via_ref! {
&'tcx mir::coverage::CodeRegion,
&'tcx ty::List<ty::BoundVariableKind>,
&'tcx ty::List<ty::Predicate<'tcx>>,
+ &'tcx ty::List<FieldIdx>,
}
#[macro_export]
@@ -489,36 +500,40 @@ impl_arena_copy_decoder! {<'tcx>
macro_rules! implement_ty_decoder {
($DecoderName:ident <$($typaram:tt),*>) => {
mod __ty_decoder_impl {
- use std::borrow::Cow;
use rustc_serialize::Decoder;
use super::$DecoderName;
impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
$crate::__impl_decoder_methods! {
+ read_usize -> usize;
read_u128 -> u128;
read_u64 -> u64;
read_u32 -> u32;
read_u16 -> u16;
read_u8 -> u8;
- read_usize -> usize;
+ read_isize -> isize;
read_i128 -> i128;
read_i64 -> i64;
read_i32 -> i32;
read_i16 -> i16;
- read_i8 -> i8;
- read_isize -> isize;
-
- read_bool -> bool;
- read_char -> char;
- read_str -> &str;
}
#[inline]
fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
self.opaque.read_raw_bytes(len)
}
+
+ #[inline]
+ fn peek_byte(&self) -> u8 {
+ self.opaque.peek_byte()
+ }
+
+ #[inline]
+ fn position(&self) -> usize {
+ self.opaque.position()
+ }
}
}
}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index bcedae233..1a4bd1481 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -6,7 +6,6 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
use rustc_macros::HashStable;
-use std::fmt;
mod int;
mod kind;
@@ -21,15 +20,6 @@ pub use valtree::*;
#[rustc_pass_by_value]
pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
-impl<'tcx> fmt::Debug for Const<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // This reflects what `Const` looked liked before `Interned` was
- // introduced. We print it like this to avoid having to update expected
- // output in a lot of tests.
- write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
- }
-}
-
/// Typed constant value.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
pub struct ConstData<'tcx> {
@@ -53,19 +43,12 @@ impl<'tcx> Const<'tcx> {
/// Literals and const generic parameters are eagerly converted to a constant, everything else
/// becomes `Unevaluated`.
- pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
- Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id))
- }
-
#[instrument(skip(tcx), level = "debug")]
- pub fn from_opt_const_arg_anon_const(
- tcx: TyCtxt<'tcx>,
- def: ty::WithOptConstParam<LocalDefId>,
- ) -> Self {
- let body_id = match tcx.hir().get_by_def_id(def.did) {
+ pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
+ let body_id = match tcx.hir().get_by_def_id(def) {
hir::Node::AnonConst(ac) => ac.body,
_ => span_bug!(
- tcx.def_span(def.did.to_def_id()),
+ tcx.def_span(def.to_def_id()),
"from_anon_const can only process anonymous constants"
),
};
@@ -73,17 +56,14 @@ impl<'tcx> Const<'tcx> {
let expr = &tcx.hir().body(body_id).value;
debug!(?expr);
- let ty = tcx
- .type_of(def.def_id_for_type_of())
- .no_bound_vars()
- .expect("const parameter types cannot be generic");
+ let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
None => tcx.mk_const(
ty::UnevaluatedConst {
- def: def.to_global(),
- substs: InternalSubsts::identity_for_item(tcx, def.did),
+ def: def.to_def_id(),
+ substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()),
},
ty,
),
@@ -124,7 +104,7 @@ impl<'tcx> Const<'tcx> {
Err(e) => {
tcx.sess.delay_span_bug(
expr.span,
- &format!("Const::from_anon_const: couldn't lit_to_const {:?}", e),
+ format!("Const::from_anon_const: couldn't lit_to_const {:?}", e),
);
}
}
@@ -152,9 +132,7 @@ impl<'tcx> Const<'tcx> {
ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
param_ty,
)),
- Some(rbv::ResolvedArg::Error(guar)) => {
- Some(tcx.const_error_with_guaranteed(param_ty, guar))
- }
+ Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)),
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
}
}
@@ -238,7 +216,7 @@ impl<'tcx> Const<'tcx> {
if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
match val {
Ok(val) => tcx.mk_const(val, self.ty()),
- Err(guar) => tcx.const_error_with_guaranteed(self.ty(), guar),
+ Err(guar) => tcx.const_error(self.ty(), guar),
}
} else {
// Either the constant isn't evaluatable or ValTree creation failed.
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index c0e557d48..d1dbc531e 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -141,14 +141,18 @@ impl<CTX> crate::ty::HashStable<CTX> for ScalarInt {
impl<S: Encoder> Encodable<S> for ScalarInt {
fn encode(&self, s: &mut S) {
- s.emit_u128(self.data);
- s.emit_u8(self.size.get());
+ let size = self.size.get();
+ s.emit_u8(size);
+ s.emit_raw_bytes(&self.data.to_le_bytes()[..size as usize]);
}
}
impl<D: Decoder> Decodable<D> for ScalarInt {
fn decode(d: &mut D) -> ScalarInt {
- ScalarInt { data: d.read_u128(), size: NonZeroU8::new(d.read_u8()).unwrap() }
+ let mut data = [0u8; 16];
+ let size = d.read_u8();
+ data[..size as usize].copy_from_slice(d.read_raw_bytes(size as usize));
+ ScalarInt { data: u128::from_le_bytes(data), size: NonZeroU8::new(size).unwrap() }
}
}
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 560caa041..1dd4f8a24 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -17,7 +17,7 @@ use super::ScalarInt;
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
pub struct UnevaluatedConst<'tcx> {
- pub def: ty::WithOptConstParam<DefId>,
+ pub def: DefId,
pub substs: SubstsRef<'tcx>,
}
@@ -36,16 +36,13 @@ impl<'tcx> UnevaluatedConst<'tcx> {
impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
- pub fn new(
- def: ty::WithOptConstParam<DefId>,
- substs: SubstsRef<'tcx>,
- ) -> UnevaluatedConst<'tcx> {
+ pub fn new(def: DefId, substs: SubstsRef<'tcx>) -> UnevaluatedConst<'tcx> {
UnevaluatedConst { def, substs }
}
}
/// Represents a constant in Rust.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
#[derive(derive_more::From)]
pub enum ConstKind<'tcx> {
@@ -131,7 +128,7 @@ impl<'tcx> ConstKind<'tcx> {
}
/// An inference variable for a const, for use in const generics.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
pub enum InferConst<'tcx> {
/// Infer the value of the const.
Var(ty::ConstVid<'tcx>),
@@ -224,9 +221,9 @@ impl<'tcx> ConstKind<'tcx> {
// FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
// we can call `infcx.const_eval_resolve` which handles inference variables.
let param_env_and = if (param_env, unevaluated).has_non_region_infer() {
- tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
+ tcx.param_env(unevaluated.def).and(ty::UnevaluatedConst {
def: unevaluated.def,
- substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
+ substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
})
} else {
tcx.erase_regions(param_env)
@@ -248,7 +245,7 @@ impl<'tcx> ConstKind<'tcx> {
// can leak through `val` into the const we return.
Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
Err(ErrorHandled::TooGeneric) => None,
- Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+ Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
}
}
EvalMode::Mir => {
@@ -259,7 +256,7 @@ impl<'tcx> ConstKind<'tcx> {
// can leak through `val` into the const we return.
Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
Err(ErrorHandled::TooGeneric) => None,
- Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+ Err(ErrorHandled::Reported(e)) => Some(Err(e.into())),
}
}
}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 63f7cc2ee..2bde55bc4 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -13,25 +13,28 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_bound_vars;
use crate::middle::stability;
use crate::mir::interpret::{self, Allocation, ConstAllocation};
-use crate::mir::{Body, BorrowCheckResult, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::query::plumbing::QuerySystem;
use crate::query::LocalCrate;
+use crate::query::Providers;
+use crate::query::{IntoQueryParam, TyCtxtAt};
use crate::thir::Thir;
use crate::traits;
use crate::traits::solve;
-use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
-use crate::ty::query::{self, TyCtxtAt};
+use crate::traits::solve::{
+ ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
+};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
- TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, Visibility,
+ TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, UintTy, Visibility,
};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_ast::{self as ast, attr};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::intern::Interned;
-use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -50,7 +53,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::{
Constness, ExprKind, HirId, ImplItemKind, ItemKind, Node, TraitCandidate, TraitItemKind,
};
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::dep_graph::DepNodeIndex;
use rustc_query_system::ich::StableHashingContext;
@@ -61,7 +64,6 @@ use rustc_session::lint::Lint;
use rustc_session::Limit;
use rustc_session::Session;
use rustc_span::def_id::{DefPathHash, StableCrateId};
-use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
@@ -82,21 +84,6 @@ use std::ops::{Bound, Deref};
const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
-pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
- /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
- fn new(sess: &'tcx Session, data: Mmap, start_pos: usize) -> Self
- where
- Self: Sized;
-
- fn new_empty(source_map: &'tcx SourceMap) -> Self
- where
- Self: Sized;
-
- fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
-
- fn serialize(&self, tcx: TyCtxt<'tcx>, encoder: FileEncoder) -> FileEncodeResult;
-}
-
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Interner for TyCtxt<'tcx> {
type AdtDef = ty::AdtDef<'tcx>;
@@ -141,6 +128,7 @@ pub struct CtxtInterners<'tcx> {
type_: InternedSet<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>,
const_lists: InternedSet<'tcx, List<ty::Const<'tcx>>>,
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
+ type_lists: InternedSet<'tcx, List<Ty<'tcx>>>,
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
region: InternedSet<'tcx, RegionKind<'tcx>>,
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
@@ -154,6 +142,8 @@ pub struct CtxtInterners<'tcx> {
layout: InternedSet<'tcx, LayoutS>,
adt_def: InternedSet<'tcx, AdtDefData>,
external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>,
+ predefined_opaques_in_body: InternedSet<'tcx, PredefinedOpaquesData<'tcx>>,
+ fields: InternedSet<'tcx, List<FieldIdx>>,
}
impl<'tcx> CtxtInterners<'tcx> {
@@ -163,6 +153,7 @@ impl<'tcx> CtxtInterners<'tcx> {
type_: Default::default(),
const_lists: Default::default(),
substs: Default::default(),
+ type_lists: Default::default(),
region: Default::default(),
poly_existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
@@ -176,6 +167,8 @@ impl<'tcx> CtxtInterners<'tcx> {
layout: Default::default(),
adt_def: Default::default(),
external_constraints: Default::default(),
+ predefined_opaques_in_body: Default::default(),
+ fields: Default::default(),
}
}
@@ -209,7 +202,7 @@ impl<'tcx> CtxtInterners<'tcx> {
) -> Fingerprint {
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
- if flags.flags.intersects(TypeFlags::NEEDS_INFER) || sess.opts.incremental.is_none() {
+ if flags.flags.intersects(TypeFlags::HAS_INFER) || sess.opts.incremental.is_none() {
Fingerprint::ZERO
} else {
let mut hasher = StableHasher::new();
@@ -447,6 +440,14 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> {
TyCtxtFeed { tcx: self, key: LOCAL_CRATE }
}
+
+ /// In order to break cycles involving `AnonConst`, we need to set the expected type by side
+ /// effect. However, we do not want this as a general capability, so this interface restricts
+ /// to the only allowed case.
+ pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<Ty<'tcx>>) {
+ debug_assert_eq!(self.def_kind(key), DefKind::AnonConst);
+ TyCtxtFeed { tcx: self, key }.type_of(value)
+ }
}
impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> {
@@ -496,7 +497,7 @@ pub struct GlobalCtxt<'tcx> {
///
/// FIXME(Centril): consider `dyn LintStoreMarker` once
/// we can upcast to `Any` for some additional type safety.
- pub lint_store: Lrc<dyn Any + sync::Sync + sync::Send>,
+ pub lint_store: Lrc<dyn Any + sync::DynSync + sync::DynSend>,
pub dep_graph: DepGraph,
@@ -513,14 +514,7 @@ pub struct GlobalCtxt<'tcx> {
untracked: Untracked,
- /// This provides access to the incremental compilation on-disk cache for query results.
- /// Do not access this directly. It is only meant to be used by
- /// `DepGraph::try_mark_green()` and the query infrastructure.
- /// This is `None` if we are not incremental compilation mode
- pub on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
-
- pub queries: &'tcx dyn query::QueryEngine<'tcx>,
- pub query_system: query::QuerySystem<'tcx>,
+ pub query_system: QuerySystem<'tcx>,
pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
// Internal caches for metadata decoding. No need to track deps on this.
@@ -581,28 +575,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn typeck_opt_const_arg(
- self,
- def: ty::WithOptConstParam<LocalDefId>,
- ) -> &'tcx TypeckResults<'tcx> {
- if let Some(param_did) = def.const_param_did {
- self.typeck_const_arg((def.did, param_did))
- } else {
- self.typeck(def.did)
- }
- }
-
- pub fn mir_borrowck_opt_const_arg(
- self,
- def: ty::WithOptConstParam<LocalDefId>,
- ) -> &'tcx BorrowCheckResult<'tcx> {
- if let Some(param_did) = def.const_param_did {
- self.mir_borrowck_const_arg((def.did, param_did))
- } else {
- self.mir_borrowck(def.did)
- }
- }
-
pub fn alloc_steal_thir(self, thir: Thir<'tcx>) -> &'tcx Steal<Thir<'tcx>> {
self.arena.alloc(Steal::new(thir))
}
@@ -677,14 +649,13 @@ impl<'tcx> TyCtxt<'tcx> {
/// reference to the context, to allow formatting values that need it.
pub fn create_global_ctxt(
s: &'tcx Session,
- lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
+ lint_store: Lrc<dyn Any + sync::DynSend + sync::DynSync>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
untracked: Untracked,
dep_graph: DepGraph,
- on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
- queries: &'tcx dyn query::QueryEngine<'tcx>,
query_kinds: &'tcx [DepKindStruct<'tcx>],
+ query_system: QuerySystem<'tcx>,
) -> GlobalCtxt<'tcx> {
let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
s.emit_fatal(err);
@@ -706,9 +677,7 @@ impl<'tcx> TyCtxt<'tcx> {
lifetimes: common_lifetimes,
consts: common_consts,
untracked,
- on_disk_cache,
- queries,
- query_system: Default::default(),
+ query_system,
query_kinds,
ty_rcache: Default::default(),
pred_rcache: Default::default(),
@@ -735,7 +704,11 @@ impl<'tcx> TyCtxt<'tcx> {
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
/// ensure it gets used.
#[track_caller]
- pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
+ pub fn ty_error_with_message<S: Into<MultiSpan>>(
+ self,
+ span: S,
+ msg: impl Into<DiagnosticMessage>,
+ ) -> Ty<'tcx> {
let reported = self.sess.delay_span_bug(span, msg);
self.mk_ty_from_kind(Error(reported))
}
@@ -766,17 +739,13 @@ impl<'tcx> TyCtxt<'tcx> {
/// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
#[track_caller]
- pub fn const_error_with_guaranteed(
- self,
- ty: Ty<'tcx>,
- reported: ErrorGuaranteed,
- ) -> Const<'tcx> {
+ pub fn const_error(self, ty: Ty<'tcx>, reported: ErrorGuaranteed) -> Const<'tcx> {
self.mk_const(ty::ConstKind::Error(reported), ty)
}
/// Like [TyCtxt::ty_error] but for constants.
#[track_caller]
- pub fn const_error(self, ty: Ty<'tcx>) -> Const<'tcx> {
+ pub fn const_error_misc(self, ty: Ty<'tcx>) -> Const<'tcx> {
self.const_error_with_message(
ty,
DUMMY_SP,
@@ -834,7 +803,8 @@ impl<'tcx> TyCtxt<'tcx> {
self.features_query(())
}
- pub fn def_key(self, id: DefId) -> rustc_hir::definitions::DefKey {
+ pub fn def_key(self, id: impl IntoQueryParam<DefId>) -> rustc_hir::definitions::DefKey {
+ let id = id.into_query_param();
// Accessing the DefKey is ok, since it is part of DefPathHash.
if let Some(id) = id.as_local() {
self.definitions_untracked().def_key(id)
@@ -925,7 +895,7 @@ impl<'tcx> TyCtxt<'tcx> {
crate_name,
// Don't print the whole stable crate id. That's just
// annoying in debug output.
- stable_crate_id.to_u64() >> (8 * 6),
+ stable_crate_id.as_u64() >> (8 * 6),
self.def_path(def_id).to_string_no_crate_verbose()
)
}
@@ -1046,7 +1016,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
- self.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder))
+ self.query_system.on_disk_cache.as_ref().map_or(Ok(0), |c| c.serialize(self, encoder))
}
/// If `true`, we should use lazy normalization for constants, otherwise
@@ -1123,11 +1093,13 @@ impl<'tcx> TyCtxt<'tcx> {
v.0
}
- /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type and associated alias span when type alias is used
+ /// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in
+ /// its return type, and the associated alias span when type alias is used,
+ /// along with a span for lifetime suggestion (if there are existing generics).
pub fn return_type_impl_or_dyn_traits_with_type_alias(
self,
scope_def_id: LocalDefId,
- ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span)> {
+ ) -> Option<(Vec<&'tcx hir::Ty<'tcx>>, Span, Option<Span>)> {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let mut v = TraitObjectVisitor(vec![], self.hir());
// when the return type is a type alias
@@ -1141,7 +1113,7 @@ impl<'tcx> TyCtxt<'tcx> {
{
v.visit_ty(alias_ty);
if !v.0.is_empty() {
- return Some((v.0, alias_generics.span));
+ return Some((v.0, alias_generics.span, alias_generics.span_for_lifetime_suggestion()));
}
}
return None;
@@ -1231,7 +1203,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
iter::once(LOCAL_CRATE)
.chain(self.crates(()).iter().copied())
- .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied())
+ .flat_map(move |cnum| self.traits(cnum).iter().copied())
}
#[inline]
@@ -1278,25 +1250,6 @@ macro_rules! nop_lift {
};
}
-// Can't use the macros as we have reuse the `substs` here.
-//
-// See `mk_type_list` for more info.
-impl<'a, 'tcx> Lift<'tcx> for &'a List<Ty<'a>> {
- type Lifted = &'tcx List<Ty<'tcx>>;
- fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
- if self.is_empty() {
- return Some(List::empty());
- }
-
- tcx.interners
- .substs
- .contains_pointer_to(&InternedInSet(self.as_substs()))
- // SAFETY: `self` is interned and therefore valid
- // for the entire lifetime of the `TyCtxt`.
- .then(|| unsafe { mem::transmute::<&'a List<Ty<'a>>, &'tcx List<Ty<'tcx>>>(self) })
- }
-}
-
macro_rules! nop_list_lift {
($set:ident; $ty:ty => $lifted:ty) => {
impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
@@ -1320,6 +1273,7 @@ nop_lift! {const_; Const<'a> => Const<'tcx>}
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
+nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>}
nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
@@ -1329,9 +1283,12 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
// This is the impl for `&'a InternalSubsts<'a>`.
nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
-CloneLiftImpls! { for<'tcx> {
- Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint,
-} }
+CloneLiftImpls! {
+ Constness,
+ traits::WellFormedLoc,
+ ImplPolarity,
+ crate::mir::ReturnConstraint,
+}
macro_rules! sty_debug_print {
($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{
@@ -1567,6 +1524,8 @@ direct_interners! {
adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>,
external_constraints: pub mk_external_constraints(ExternalConstraintsData<'tcx>):
ExternalConstraints -> ExternalConstraints<'tcx>,
+ predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData<'tcx>):
+ PredefinedOpaques -> PredefinedOpaques<'tcx>,
}
macro_rules! slice_interners {
@@ -1591,12 +1550,14 @@ macro_rules! slice_interners {
slice_interners!(
const_lists: pub mk_const_list(Const<'tcx>),
substs: pub mk_substs(GenericArg<'tcx>),
+ type_lists: pub mk_type_list(Ty<'tcx>),
canonical_var_infos: pub mk_canonical_var_infos(CanonicalVarInfo<'tcx>),
poly_existential_predicates: intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>),
predicates: intern_predicates(Predicate<'tcx>),
projs: pub mk_projs(ProjectionKind),
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
+ fields: pub mk_fields(FieldIdx),
);
impl<'tcx> TyCtxt<'tcx> {
@@ -1610,11 +1571,11 @@ impl<'tcx> TyCtxt<'tcx> {
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
/// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
- pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+ pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
self.super_traits_of(trait_def_id).any(|trait_did| {
self.associated_items(trait_did)
- .find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
- .is_some()
+ .filter_by_name_unhygienic(assoc_name.name)
+ .any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did))
})
}
@@ -1623,7 +1584,7 @@ impl<'tcx> TyCtxt<'tcx> {
let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false };
let future_trait = self.require_lang_item(LangItem::Future, None);
- self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| {
+ self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| {
let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else {
return false;
};
@@ -1881,7 +1842,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
#[inline(always)]
- fn check_and_mk_substs(
+ pub(crate) fn check_and_mk_substs(
self,
_def_id: DefId,
substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
@@ -1889,7 +1850,17 @@ impl<'tcx> TyCtxt<'tcx> {
let substs = substs.into_iter().map(Into::into);
#[cfg(debug_assertions)]
{
- let n = self.generics_of(_def_id).count();
+ let generics = self.generics_of(_def_id);
+
+ let n = if let DefKind::AssocTy = self.def_kind(_def_id)
+ && let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(_def_id))
+ {
+ // If this is an inherent projection.
+
+ generics.params.len() + 1
+ } else {
+ generics.count()
+ };
assert_eq!(
(n, Some(n)),
substs.size_hint(),
@@ -2050,7 +2021,7 @@ impl<'tcx> TyCtxt<'tcx> {
debug_assert_matches!(
(kind, self.def_kind(alias_ty.def_id)),
(ty::Opaque, DefKind::OpaqueTy)
- | (ty::Projection, DefKind::AssocTy)
+ | (ty::Projection | ty::Inherent, DefKind::AssocTy)
| (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
);
self.mk_ty_from_kind(Alias(kind, alias_ty))
@@ -2190,18 +2161,6 @@ impl<'tcx> TyCtxt<'tcx> {
T::collect_and_apply(iter, |xs| self.mk_const_list(xs))
}
- pub fn mk_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
- // Actually intern type lists as lists of `GenericArg`s.
- //
- // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
- // as explained in `ty_slice_as_generic_arg`. With this,
- // we guarantee that even when transmuting between `List<Ty<'tcx>>`
- // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
- // lists is upheld.
- let substs = self.mk_substs(ty::subst::ty_slice_as_generic_args(ts));
- substs.try_as_type_list().unwrap()
- }
-
// Unlike various other `mk_*_from_iter` functions, this one uses `I:
// IntoIterator` instead of `I: Iterator`, and it doesn't have a slice
// variant, because of the need to combine `inputs` and `output`. This
@@ -2277,6 +2236,14 @@ impl<'tcx> TyCtxt<'tcx> {
T::collect_and_apply(iter, |xs| self.mk_place_elems(xs))
}
+ pub fn mk_fields_from_iter<I, T>(self, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<FieldIdx, &'tcx List<FieldIdx>>,
+ {
+ T::collect_and_apply(iter, |xs| self.mk_fields(xs))
+ }
+
pub fn mk_substs_trait(
self,
self_ty: Ty<'tcx>,
@@ -2285,15 +2252,6 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_substs_from_iter(iter::once(self_ty.into()).chain(rest))
}
- pub fn mk_trait_ref(
- self,
- trait_def_id: DefId,
- substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
- ) -> ty::TraitRef<'tcx> {
- let substs = self.check_and_mk_substs(trait_def_id, substs);
- ty::TraitRef { def_id: trait_def_id, substs, _use_mk_trait_ref_instead: () }
- }
-
pub fn mk_alias_ty(
self,
def_id: DefId,
@@ -2389,7 +2347,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn is_late_bound(self, id: HirId) -> bool {
- self.is_late_bound_map(id.owner).map_or(false, |set| set.contains(&id.local_id))
+ self.is_late_bound_map(id.owner).is_some_and(|set| set.contains(&id.local_id))
}
pub fn late_bound_vars(self, id: HirId) -> &'tcx List<ty::BoundVariableKind> {
@@ -2461,26 +2419,17 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- /// Named module children from all items except `use` and `extern crate` imports.
- ///
- /// In addition to regular items this list also includes struct or variant constructors, and
+ /// Named module children from all kinds of items, including imports.
+ /// In addition to regular items this list also includes struct and variant constructors, and
/// items inside `extern {}` blocks because all of them introduce names into parent module.
- /// For non-reexported children every such name is associated with a separate `DefId`.
///
/// Module here is understood in name resolution sense - it can be a `mod` item,
/// or a crate root, or an enum, or a trait.
- pub fn module_children_non_reexports(self, def_id: LocalDefId) -> &'tcx [LocalDefId] {
- self.resolutions(()).module_children_non_reexports.get(&def_id).map_or(&[], |v| &v[..])
- }
-
- /// Named module children from `use` and `extern crate` imports.
///
- /// Reexported names are not associated with individual `DefId`s,
- /// e.g. a glob import can introduce a lot of names, all with the same `DefId`.
- /// That's why the list needs to contain `ModChild` structures describing all the names
- /// individually instead of `DefId`s.
- pub fn module_children_reexports(self, def_id: LocalDefId) -> &'tcx [ModChild] {
- self.resolutions(()).module_children_reexports.get(&def_id).map_or(&[], |v| &v[..])
+ /// This is not a query, making it a query causes perf regressions
+ /// (probably due to hashing spans in `ModChild`ren).
+ pub fn module_children_local(self, def_id: LocalDefId) -> &'tcx [ModChild] {
+ self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..])
}
}
@@ -2494,18 +2443,9 @@ impl<'tcx> TyCtxtAt<'tcx> {
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
/// ensure it gets used.
#[track_caller]
- pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
+ pub fn ty_error_with_message(self, msg: impl Into<DiagnosticMessage>) -> Ty<'tcx> {
self.tcx.ty_error_with_message(self.span, msg)
}
-
- pub fn mk_trait_ref(
- self,
- trait_lang_item: LangItem,
- substs: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
- ) -> ty::TraitRef<'tcx> {
- let trait_def_id = self.require_lang_item(trait_lang_item, Some(self.span));
- self.tcx.mk_trait_ref(trait_def_id, substs)
- }
}
/// Parameter attributes that can only be determined by examining the body of a function instead
@@ -2523,7 +2463,7 @@ pub struct DeducedParamAttrs {
pub read_only: bool,
}
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
providers.names_imported_by_glob_use = |tcx, id| {
@@ -2540,7 +2480,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
|tcx, LocalCrate| attr::contains_name(tcx.hir().krate_attrs(), sym::compiler_builtins);
providers.has_panic_handler = |tcx, LocalCrate| {
// We want to check if the panic handler was defined in this crate
- tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
+ tcx.lang_items().panic_impl().is_some_and(|did| did.is_local())
};
providers.source_span = |tcx, def_id| tcx.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP);
}
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
index fb0d90930..9de77b9fd 100644
--- a/compiler/rustc_middle/src/ty/context/tls.rs
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -1,7 +1,7 @@
use super::{GlobalCtxt, TyCtxt};
use crate::dep_graph::TaskDepsRef;
-use crate::ty::query;
+use crate::query::plumbing::QueryJobId;
use rustc_data_structures::sync::{self, Lock};
use rustc_errors::Diagnostic;
#[cfg(not(parallel_compiler))]
@@ -22,7 +22,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
/// The current query job, if any. This is updated by `JobOwner::start` in
/// `ty::query::plumbing` when executing a query.
- pub query: Option<query::QueryJobId>,
+ pub query: Option<QueryJobId>,
/// 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.
@@ -78,7 +78,7 @@ where
{
TLV.with(|tlv| {
let old = tlv.replace(erase(context));
- let _reset = rustc_data_structures::OnDrop(move || tlv.set(old));
+ let _reset = rustc_data_structures::defer(move || tlv.set(old));
f()
})
}
@@ -94,8 +94,8 @@ where
f(None)
} else {
// We could get an `ImplicitCtxt` pointer from another thread.
- // Ensure that `ImplicitCtxt` is `Sync`.
- sync::assert_sync::<ImplicitCtxt<'_, '_>>();
+ // Ensure that `ImplicitCtxt` is `DynSync`.
+ sync::assert_dyn_sync::<ImplicitCtxt<'_, '_>>();
unsafe { f(Some(downcast(context))) }
}
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index ae0bb4949..6a29063b8 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -139,7 +139,7 @@ pub fn suggest_arbitrary_trait_bound<'tcx>(
// Suggest a where clause bound for a non-type parameter.
err.span_suggestion_verbose(
generics.tail_span_for_predicate_suggestion(),
- &format!(
+ format!(
"consider {} `where` clause, but there might be an alternative better way to express \
this requirement",
if generics.where_clause_span.is_empty() { "introducing a" } else { "extending the" },
@@ -242,7 +242,7 @@ pub fn suggest_constraining_type_params<'a>(
err.span_label(
param.span,
- &format!("this type parameter needs to be `{}`", constraint),
+ format!("this type parameter needs to be `{}`", constraint),
);
suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id);
}
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index 383773248..7895993cc 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,8 +1,9 @@
+use crate::query::Providers;
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
-pub(super) fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { erase_regions_ty, ..*providers };
+pub(super) fn provide(providers: &mut Providers) {
+ *providers = Providers { erase_regions_ty, ..*providers };
}
fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -40,7 +41,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if ty.needs_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) }
+ if ty.has_infer() { ty.super_fold_with(self) } else { self.tcx.erase_regions_ty(ty) }
}
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index aff6c77e0..49ab9b79e 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -28,7 +28,7 @@ impl<T> ExpectedFound<T> {
}
// Data structures used in type unification
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, TypeVisitable, Lift, PartialEq, Eq)]
#[rustc_pass_by_value]
pub enum TypeError<'tcx> {
Mismatch,
@@ -265,7 +265,7 @@ impl<'tcx> Ty<'tcx> {
ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
- ty::Alias(ty::Projection, _) => "associated type".into(),
+ ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(),
ty::Param(p) => format!("type parameter `{p}`").into(),
ty::Alias(ty::Opaque, ..) => if tcx.ty_is_opaque_future(self) { "future".into() } else { "opaque type".into() },
ty::Error(_) => "type error".into(),
@@ -312,7 +312,7 @@ impl<'tcx> Ty<'tcx> {
ty::Tuple(..) => "tuple".into(),
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
- ty::Alias(ty::Projection, _) => "associated type".into(),
+ ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(),
ty::Param(_) => "type parameter".into(),
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
}
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 31d00b65e..76f61d9ac 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -68,7 +68,7 @@ pub enum TreatParams {
}
/// During fast-rejection, we have the choice of treating projection types
-/// as either simplifyable or not, depending on whether we expect the projection
+/// as either simplifiable or not, depending on whether we expect the projection
/// to be normalized/rigid.
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
pub enum TreatProjections {
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 5a6ee1238..d64875a9f 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -176,14 +176,14 @@ impl FlagComputation {
self.add_substs(substs);
}
- &ty::Alias(ty::Projection, data) => {
- self.add_flags(TypeFlags::HAS_TY_PROJECTION);
- self.add_projection_ty(data);
- }
+ &ty::Alias(kind, data) => {
+ self.add_flags(match kind {
+ ty::Projection => TypeFlags::HAS_TY_PROJECTION,
+ ty::Inherent => TypeFlags::HAS_TY_INHERENT,
+ ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
+ });
- &ty::Alias(ty::Opaque, ty::AliasTy { substs, .. }) => {
- self.add_flags(TypeFlags::HAS_TY_OPAQUE);
- self.add_substs(substs);
+ self.add_alias_ty(data);
}
&ty::Dynamic(obj, r, _) => {
@@ -267,7 +267,7 @@ impl FlagComputation {
projection_ty,
term,
})) => {
- self.add_projection_ty(projection_ty);
+ self.add_alias_ty(projection_ty);
self.add_term(term);
}
ty::PredicateKind::WellFormed(arg) => {
@@ -372,8 +372,8 @@ impl FlagComputation {
}
}
- fn add_projection_ty(&mut self, projection_ty: ty::AliasTy<'_>) {
- self.add_substs(projection_ty.substs);
+ fn add_alias_ty(&mut self, alias_ty: ty::AliasTy<'_>) {
+ self.add_substs(alias_ty.substs);
}
fn add_substs(&mut self, substs: &[GenericArg<'_>]) {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 203e16bea..25890eb15 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -37,7 +37,8 @@ where
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- let r = r.super_fold_with(self);
+ // This one is a little different, because `super_fold_with` is not
+ // implemented on non-recursive `Region`.
(self.lt_op)(r)
}
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index baef4ffed..b0ffe7829 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -103,7 +103,7 @@ impl GenericParamDef {
ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
ty::GenericParamDefKind::Const { .. } => {
- tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
+ tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
}
}
}
@@ -298,7 +298,7 @@ impl<'tcx> Generics {
.iter()
.rev()
.take_while(|param| {
- param.default_value(tcx).map_or(false, |default| {
+ param.default_value(tcx).is_some_and(|default| {
default.subst(tcx, substs) == substs[param.index as usize]
})
})
diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs
index 4c7822acd..02baa395c 100644
--- a/compiler/rustc_middle/src/ty/impls_ty.rs
+++ b/compiler/rustc_middle/src/ty/impls_ty.rs
@@ -73,34 +73,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArg<'t
}
}
-impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::subst::GenericArgKind<'tcx> {
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- match self {
- // WARNING: We dedup cache the `HashStable` results for `List`
- // while ignoring types and freely transmute
- // between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
- // See `fn mk_type_list` for more details.
- //
- // We therefore hash types without adding a hash for their discriminant.
- //
- // In order to make it very unlikely for the sequence of bytes being hashed for
- // a `GenericArgKind::Type` to be the same as the sequence of bytes being
- // hashed for one of the other variants, we hash some very high number instead
- // of their actual discriminant since `TyKind` should never start with anything
- // that high.
- ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher),
- ty::subst::GenericArgKind::Const(ct) => {
- 0xF3u8.hash_stable(hcx, hasher);
- ct.hash_stable(hcx, hasher);
- }
- ty::subst::GenericArgKind::Lifetime(lt) => {
- 0xF5u8.hash_stable(hcx, hasher);
- lt.hash_stable(hcx, hasher);
- }
- }
- }
-}
-
// AllocIds get resolved to whatever they point to (to be stable)
impl<'a> HashStable<StableHashingContext<'a>> for mir::interpret::AllocId {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 92a040068..422350284 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -43,6 +43,7 @@
//! This code should only compile in modules where the uninhabitedness of `Foo`
//! is visible.
+use crate::query::Providers;
use crate::ty::context::TyCtxt;
use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
@@ -52,9 +53,8 @@ pub mod inhabited_predicate;
pub use inhabited_predicate::InhabitedPredicate;
-pub(crate) fn provide(providers: &mut ty::query::Providers) {
- *providers =
- ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
+pub(crate) fn provide(providers: &mut Providers) {
+ *providers = Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
}
/// Returns an `InhabitedPredicate` that is generic over type parameters and
@@ -113,6 +113,12 @@ impl<'tcx> Ty<'tcx> {
}
Never => InhabitedPredicate::False,
Param(_) | Alias(ty::Projection, _) => InhabitedPredicate::GenericType(self),
+ // FIXME(inherent_associated_types): Most likely we can just map to `GenericType` like above.
+ // However it's unclear if the substs passed to `InhabitedPredicate::subst` are of the correct
+ // format, i.e. don't contain parent substs. If you hit this case, please verify this beforehand.
+ Alias(ty::Inherent, _) => {
+ bug!("unimplemented: inhabitedness checking for inherent projections")
+ }
Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
// use a query for more complex cases
Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index e73225f70..e641d1ef1 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -34,7 +34,7 @@ pub enum InstanceDef<'tcx> {
/// - `fn` items
/// - closures
/// - generators
- Item(ty::WithOptConstParam<DefId>),
+ Item(DefId),
/// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
///
@@ -115,7 +115,7 @@ impl<'tcx> Instance<'tcx> {
/// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization.
pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> {
let ty = tcx.type_of(self.def.def_id());
- tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty.skip_binder())
+ tcx.subst_and_normalize_erasing_regions(self.substs, param_env, ty)
}
/// Finds a crate that contains a monomorphization of this instance that
@@ -143,7 +143,7 @@ impl<'tcx> Instance<'tcx> {
match self.def {
InstanceDef::Item(def) => tcx
- .upstream_monomorphizations_for(def.did)
+ .upstream_monomorphizations_for(def)
.and_then(|monos| monos.get(&self.substs).cloned()),
InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.substs),
_ => None,
@@ -155,8 +155,8 @@ impl<'tcx> InstanceDef<'tcx> {
#[inline]
pub fn def_id(self) -> DefId {
match self {
- InstanceDef::Item(def) => def.did,
- InstanceDef::VTableShim(def_id)
+ InstanceDef::Item(def_id)
+ | InstanceDef::VTableShim(def_id)
| InstanceDef::ReifyShim(def_id)
| InstanceDef::FnPtrShim(def_id, _)
| InstanceDef::Virtual(def_id, _)
@@ -172,7 +172,7 @@ impl<'tcx> InstanceDef<'tcx> {
/// Returns the `DefId` of instances which might not require codegen locally.
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
match self {
- ty::InstanceDef::Item(def) => Some(def.did),
+ ty::InstanceDef::Item(def) => Some(def),
ty::InstanceDef::DropGlue(def_id, Some(_)) | InstanceDef::ThreadLocalShim(def_id) => {
Some(def_id)
}
@@ -189,23 +189,6 @@ impl<'tcx> InstanceDef<'tcx> {
}
#[inline]
- pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
- match self {
- InstanceDef::Item(def) => def,
- InstanceDef::VTableShim(def_id)
- | InstanceDef::ReifyShim(def_id)
- | InstanceDef::FnPtrShim(def_id, _)
- | InstanceDef::Virtual(def_id, _)
- | InstanceDef::Intrinsic(def_id)
- | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
- | InstanceDef::DropGlue(def_id, _)
- | InstanceDef::CloneShim(def_id, _)
- | InstanceDef::ThreadLocalShim(def_id)
- | InstanceDef::FnPtrAddrShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
- }
- }
-
- #[inline]
pub fn get_attrs(
&self,
tcx: TyCtxt<'tcx>,
@@ -222,7 +205,7 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn requires_inline(&self, tcx: TyCtxt<'tcx>) -> bool {
use rustc_hir::definitions::DefPathData;
let def_id = match *self {
- ty::InstanceDef::Item(def) => def.did,
+ ty::InstanceDef::Item(def) => def,
ty::InstanceDef::DropGlue(_, Some(_)) => return false,
ty::InstanceDef::ThreadLocalShim(_) => return false,
_ => return true,
@@ -273,8 +256,7 @@ impl<'tcx> InstanceDef<'tcx> {
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
match *self {
- InstanceDef::Item(ty::WithOptConstParam { did: def_id, .. })
- | InstanceDef::Virtual(def_id, _) => {
+ InstanceDef::Item(def_id) | InstanceDef::Virtual(def_id, _) => {
tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
}
InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
@@ -358,7 +340,7 @@ impl<'tcx> Instance<'tcx> {
def_id,
substs
);
- Instance { def: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), substs }
+ Instance { def: InstanceDef::Item(def_id), substs }
}
pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> {
@@ -403,18 +385,21 @@ impl<'tcx> Instance<'tcx> {
/// couldn't complete due to errors elsewhere - this is distinct
/// from `Ok(None)` to avoid misleading diagnostics when an error
/// has already been/will be emitted, for the original cause
+ #[instrument(level = "debug", skip(tcx), ret)]
pub fn resolve(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
substs: SubstsRef<'tcx>,
) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- Instance::resolve_opt_const_arg(
- tcx,
- param_env,
- ty::WithOptConstParam::unknown(def_id),
- substs,
- )
+ // All regions in the result of this query are erased, so it's
+ // fine to erase all of the input regions.
+
+ // HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
+ // below is more likely to ignore the bounds in scope (e.g. if the only
+ // generic parameters mentioned by `substs` were lifetime ones).
+ let substs = tcx.erase_regions(substs);
+ tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, substs))))
}
pub fn expect_resolve(
@@ -432,31 +417,6 @@ impl<'tcx> Instance<'tcx> {
}
}
- // This should be kept up to date with `resolve`.
- pub fn resolve_opt_const_arg(
- tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- def: ty::WithOptConstParam<DefId>,
- substs: SubstsRef<'tcx>,
- ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> {
- // All regions in the result of this query are erased, so it's
- // fine to erase all of the input regions.
-
- // HACK(eddyb) erase regions in `substs` first, so that `param_env.and(...)`
- // below is more likely to ignore the bounds in scope (e.g. if the only
- // generic parameters mentioned by `substs` were lifetime ones).
- let substs = tcx.erase_regions(substs);
-
- // FIXME(eddyb) should this always use `param_env.with_reveal_all()`?
- if let Some((did, param_did)) = def.as_const_arg() {
- tcx.resolve_instance_of_const_arg(
- tcx.erase_regions(param_env.and((did, param_did, substs))),
- )
- } else {
- tcx.resolve_instance(tcx.erase_regions(param_env.and((def.did, substs))))
- }
- }
-
pub fn resolve_for_fn_ptr(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -470,7 +430,7 @@ impl<'tcx> Instance<'tcx> {
match resolved.def {
InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
debug!(" => fn pointer created for function with #[track_caller]");
- resolved.def = InstanceDef::ReifyShim(def.did);
+ resolved.def = InstanceDef::ReifyShim(def);
}
InstanceDef::Virtual(def_id, _) => {
debug!(" => fn pointer created for virtual call");
@@ -513,23 +473,23 @@ impl<'tcx> Instance<'tcx> {
if resolved.def.requires_caller_location(tcx)
// 2) The caller location parameter comes from having `#[track_caller]`
// on the implementation, and *not* on the trait method.
- && !tcx.should_inherit_track_caller(def.did)
+ && !tcx.should_inherit_track_caller(def)
// If the method implementation comes from the trait definition itself
// (e.g. `trait Foo { #[track_caller] my_fn() { /* impl */ } }`),
// then we don't need to generate a shim. This check is needed because
// `should_inherit_track_caller` returns `false` if our method
// implementation comes from the trait block, and not an impl block
&& !matches!(
- tcx.opt_associated_item(def.did),
+ tcx.opt_associated_item(def),
Some(ty::AssocItem {
container: ty::AssocItemContainer::TraitContainer,
..
})
)
{
- if tcx.is_closure(def.did) {
+ if tcx.is_closure(def) {
debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
- def.did, def_id, substs);
+ def, def_id, substs);
// Create a shim for the `FnOnce/FnMut/Fn` method we are calling
// - unlike functions, invoking a closure always goes through a
@@ -537,9 +497,9 @@ impl<'tcx> Instance<'tcx> {
resolved = Instance { def: InstanceDef::ReifyShim(def_id), substs };
} else {
debug!(
- " => vtable fn pointer created for function with #[track_caller]: {:?}", def.did
+ " => vtable fn pointer created for function with #[track_caller]: {:?}", def
);
- resolved.def = InstanceDef::ReifyShim(def.did);
+ resolved.def = InstanceDef::ReifyShim(def);
}
}
}
@@ -618,14 +578,15 @@ impl<'tcx> Instance<'tcx> {
self.def.has_polymorphic_mir_body().then_some(self.substs)
}
- pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: &T) -> T
+ pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T
where
T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
+ let v = v.map_bound(|v| *v);
if let Some(substs) = self.substs_for_mir_body() {
- EarlyBinder(*v).subst(tcx, substs)
+ v.subst(tcx, substs)
} else {
- *v
+ v.skip_binder()
}
}
@@ -634,7 +595,7 @@ impl<'tcx> Instance<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- v: T,
+ v: EarlyBinder<T>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
@@ -642,7 +603,7 @@ impl<'tcx> Instance<'tcx> {
if let Some(substs) = self.substs_for_mir_body() {
tcx.subst_and_normalize_erasing_regions(substs, param_env, v)
} else {
- tcx.normalize_erasing_regions(param_env, v)
+ tcx.normalize_erasing_regions(param_env, v.skip_binder())
}
}
@@ -651,7 +612,7 @@ impl<'tcx> Instance<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- v: T,
+ v: EarlyBinder<T>,
) -> Result<T, NormalizationError<'tcx>>
where
T: TypeFoldable<TyCtxt<'tcx>> + Clone,
@@ -659,7 +620,7 @@ impl<'tcx> Instance<'tcx> {
if let Some(substs) = self.substs_for_mir_body() {
tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
} else {
- tcx.try_normalize_erasing_regions(param_env, v)
+ tcx.try_normalize_erasing_regions(param_env, v.skip_binder())
}
}
@@ -698,7 +659,7 @@ fn polymorphize<'tcx>(
} else {
None
};
- let has_upvars = upvars_ty.map_or(false, |ty| !ty.tuple_fields().is_empty());
+ let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty());
debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars);
struct PolymorphizationFolder<'tcx> {
@@ -714,11 +675,8 @@ fn polymorphize<'tcx>(
debug!("fold_ty: ty={:?}", ty);
match *ty.kind() {
ty::Closure(def_id, substs) => {
- let polymorphized_substs = polymorphize(
- self.tcx,
- ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
- substs,
- );
+ let polymorphized_substs =
+ polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty
} else {
@@ -726,11 +684,8 @@ fn polymorphize<'tcx>(
}
}
ty::Generator(def_id, substs, movability) => {
- let polymorphized_substs = polymorphize(
- self.tcx,
- ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
- substs,
- );
+ let polymorphized_substs =
+ polymorphize(self.tcx, ty::InstanceDef::Item(def_id), substs);
if substs == polymorphized_substs {
ty
} else {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 195d951f9..b5a743cfe 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,11 +1,12 @@
use crate::fluent_generated as fluent;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::query::TyCtxtAt;
use crate::ty::normalize_erasing_regions::NormalizationError;
use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
use rustc_session::config::OptLevel;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
@@ -210,6 +211,7 @@ pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>),
SizeOverflow(Ty<'tcx>),
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
+ Cycle,
}
impl IntoDiagnostic<'_, !> for LayoutError<'_> {
@@ -230,12 +232,15 @@ impl IntoDiagnostic<'_, !> for LayoutError<'_> {
diag.set_arg("failure_ty", e.get_type_for_failure());
diag.set_primary_message(fluent::middle_cannot_be_normalized);
}
+ LayoutError::Cycle => {
+ diag.set_primary_message(fluent::middle_cycle);
+ }
}
diag
}
}
-// FIXME: Once the other errors that embed this error have been converted to translateable
+// FIXME: Once the other errors that embed this error have been converted to translatable
// diagnostics, this Display impl should be removed.
impl<'tcx> fmt::Display for LayoutError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -250,6 +255,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
t,
e.get_type_for_failure()
),
+ LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"),
}
}
}
@@ -263,7 +269,7 @@ pub struct LayoutCx<'tcx, C> {
impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
type TargetDataLayoutRef = &'tcx TargetDataLayout;
- fn delay_bug(&self, txt: &str) {
+ fn delay_bug(&self, txt: String) {
self.tcx.sess.delay_span_bug(DUMMY_SP, txt);
}
@@ -319,7 +325,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
let non_zero = !ty.is_unsafe_ptr();
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match tail.kind() {
- ty::Param(_) | ty::Alias(ty::Projection, _) => {
+ ty::Param(_) | ty::Alias(ty::Projection | ty::Inherent, _) => {
debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
@@ -458,10 +464,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
}
}
-/// When creating the layout for types with abstract conts in their size (i.e. [usize; 4 * N]),
+/// When creating the layout for types with abstract consts in their size (i.e. [usize; 4 * N]),
/// to ensure that they have a canonical order and can be compared directly we combine all
/// constants, and sort the other terms. This allows comparison of expressions of sizes,
-/// allowing for things like transmutating between types that depend on generic consts.
+/// allowing for things like transmuting between types that depend on generic consts.
/// This returns `None` if multiplication of constants overflows.
fn mul_sorted_consts<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -538,20 +544,20 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
}
}
-impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasDataLayout for TyCtxtAt<'tcx> {
#[inline]
fn data_layout(&self) -> &TargetDataLayout {
&self.data_layout
}
}
-impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTargetSpec for TyCtxtAt<'tcx> {
fn target_spec(&self) -> &Target {
&self.sess.target
}
}
-impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
**self
@@ -678,7 +684,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
}
}
-impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
+impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
#[inline]
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 79365ef28..71911a5a6 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -1,4 +1,5 @@
use crate::arena::Arena;
+use rustc_data_structures::aligned::{align_of, Aligned};
use rustc_serialize::{Encodable, Encoder};
use std::alloc::Layout;
use std::cmp::Ordering;
@@ -198,22 +199,23 @@ impl<'a, T: Copy> IntoIterator for &'a List<T> {
unsafe impl<T: Sync> Sync for List<T> {}
-unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
- const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
-
- #[inline]
- fn into_usize(self) -> usize {
- self as *const List<T> as usize
- }
-
- #[inline]
- unsafe fn from_usize(ptr: usize) -> &'a List<T> {
- &*(ptr as *const List<T>)
- }
+// We need this since `List` uses extern type `OpaqueListContents`.
+#[cfg(parallel_compiler)]
+use rustc_data_structures::sync::DynSync;
+#[cfg(parallel_compiler)]
+unsafe impl<T: DynSync> DynSync for List<T> {}
+
+// Safety:
+// Layouts of `Equivalent<T>` and `List<T>` are the same, modulo opaque tail,
+// thus aligns of `Equivalent<T>` and `List<T>` must be the same.
+unsafe impl<T> Aligned for List<T> {
+ const ALIGN: ptr::Alignment = {
+ #[repr(C)]
+ struct Equivalent<T> {
+ _len: usize,
+ _data: [T; 0],
+ }
- unsafe fn with_ref<R, F: FnOnce(&Self) -> R>(ptr: usize, f: F) -> R {
- // `Self` is `&'a List<T>` which impls `Copy`, so this is fine.
- let ptr = Self::from_usize(ptr);
- f(&ptr)
- }
+ align_of::<Equivalent<T>>()
+ };
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 2e516f291..a8d0dca37 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -21,6 +21,7 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
use crate::metadata::ModChild;
use crate::middle::privacy::EffectiveVisibilities;
use crate::mir::{Body, GeneratorLayout};
+use crate::query::Providers;
use crate::traits::{self, Reveal};
use crate::ty;
use crate::ty::fast_reject::SimplifiedType;
@@ -36,12 +37,12 @@ use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
use rustc_hir::Node;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::{Decodable, Encodable};
@@ -84,8 +85,7 @@ pub use self::consts::{
Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
- tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt,
- TyCtxtFeed,
+ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
};
pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
pub use self::list::List;
@@ -122,7 +122,6 @@ pub mod inhabitedness;
pub mod layout;
pub mod normalize_erasing_regions;
pub mod print;
-pub mod query;
pub mod relate;
pub mod subst;
pub mod trait_def;
@@ -166,8 +165,7 @@ pub struct ResolverGlobalCtxt {
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
- pub module_children_non_reexports: LocalDefIdMap<Vec<LocalDefId>>,
- pub module_children_reexports: LocalDefIdMap<Vec<ModChild>>,
+ pub module_children: LocalDefIdMap<Vec<ModChild>>,
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
pub main_def: Option<MainDefinition>,
pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
@@ -861,6 +859,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
pub fn is_const_if_const(self) -> bool {
self.skip_binder().is_const_if_const()
}
+
+ #[inline]
+ pub fn polarity(self) -> ImplPolarity {
+ self.skip_binder().polarity
+ }
}
/// `A: B`
@@ -993,21 +996,15 @@ impl<'tcx> Term<'tcx> {
}
}
- /// This function returns the inner `AliasTy` if this term is a projection.
- ///
- /// FIXME: rename `AliasTy` to `AliasTerm` and make sure we correctly
- /// deal with constants.
- pub fn to_projection_term(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
+ /// This function returns the inner `AliasTy` for a `ty::Alias` or `ConstKind::Unevaluated`.
+ pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> {
match self.unpack() {
- TermKind::Ty(ty) => match ty.kind() {
- ty::Alias(kind, alias_ty) => match kind {
- AliasKind::Projection => Some(*alias_ty),
- AliasKind::Opaque => None,
- },
+ TermKind::Ty(ty) => match *ty.kind() {
+ ty::Alias(_kind, alias_ty) => Some(alias_ty),
_ => None,
},
TermKind::Const(ct) => match ct.kind() {
- ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def.did, uv.substs)),
+ ConstKind::Unevaluated(uv) => Some(tcx.mk_alias_ty(uv.def, uv.substs)),
_ => None,
},
}
@@ -1067,6 +1064,24 @@ impl ParamTerm {
}
}
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub enum TermVid<'tcx> {
+ Ty(ty::TyVid),
+ Const(ty::ConstVid<'tcx>),
+}
+
+impl From<ty::TyVid> for TermVid<'_> {
+ fn from(value: ty::TyVid) -> Self {
+ TermVid::Ty(value)
+ }
+}
+
+impl<'tcx> From<ty::ConstVid<'tcx>> for TermVid<'tcx> {
+ fn from(value: ty::ConstVid<'tcx>) -> Self {
+ TermVid::Const(value)
+ }
+}
+
/// This kind of predicate has no *direct* correspondent in the
/// syntax, but it roughly corresponds to the syntactic forms:
///
@@ -1207,6 +1222,18 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
}
}
+impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitRef<'tcx> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
+ ty::Binder::dummy(self).to_predicate(tcx)
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx> {
+ fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
+ ty::Binder::dummy(self)
+ }
+}
+
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(|p| PredicateKind::Clause(Clause::Trait(p))).to_predicate(tcx)
@@ -1231,6 +1258,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
}
}
+impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx)
+ }
+}
+
impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind();
@@ -1400,14 +1433,26 @@ pub struct OpaqueHiddenType<'tcx> {
}
impl<'tcx> OpaqueHiddenType<'tcx> {
- pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
+ pub fn report_mismatch(
+ &self,
+ other: &Self,
+ opaque_def_id: LocalDefId,
+ tcx: TyCtxt<'tcx>,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ if let Some(diag) = tcx
+ .sess
+ .diagnostic()
+ .steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch)
+ {
+ diag.cancel();
+ }
// Found different concrete types for the opaque type.
let sub_diag = if self.span == other.span {
TypeMismatchReason::ConflictType { span: self.span }
} else {
TypeMismatchReason::PreviousUse { span: self.span }
};
- tcx.sess.emit_err(OpaqueHiddenTypeMismatch {
+ tcx.sess.create_err(OpaqueHiddenTypeMismatch {
self_ty: self.ty,
other_ty: other.ty,
other_span: other.span,
@@ -1471,135 +1516,6 @@ pub struct BoundConst<'tcx> {
pub type PlaceholderConst<'tcx> = Placeholder<BoundVar>;
-/// A `DefId` which, in case it is a const argument, is potentially bundled with
-/// the `DefId` of the generic parameter it instantiates.
-///
-/// This is used to avoid calls to `type_of` for const arguments during typeck
-/// which cause cycle errors.
-///
-/// ```rust
-/// struct A;
-/// impl A {
-/// fn foo<const N: usize>(&self) -> [u8; N] { [0; N] }
-/// // ^ const parameter
-/// }
-/// struct B;
-/// impl B {
-/// fn foo<const M: u8>(&self) -> usize { 42 }
-/// // ^ const parameter
-/// }
-///
-/// fn main() {
-/// let a = A;
-/// let _b = a.foo::<{ 3 + 7 }>();
-/// // ^^^^^^^^^ const argument
-/// }
-/// ```
-///
-/// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know
-/// which `foo` is used until we know the type of `a`.
-///
-/// We only know the type of `a` once we are inside of `typeck(main)`.
-/// We also end up normalizing the type of `_b` during `typeck(main)` which
-/// requires us to evaluate the const argument.
-///
-/// To evaluate that const argument we need to know its type,
-/// which we would get using `type_of(const_arg)`. This requires us to
-/// resolve `foo` as it can be either `usize` or `u8` in this example.
-/// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`,
-/// which results in a cycle.
-///
-/// In short we must not call `type_of(const_arg)` during `typeck(main)`.
-///
-/// When first creating the `ty::Const` of the const argument inside of `typeck` we have
-/// already resolved `foo` so we know which const parameter this argument instantiates.
-/// This means that we also know the expected result of `type_of(const_arg)` even if we
-/// aren't allowed to call that query: it is equal to `type_of(const_param)` which is
-/// trivial to compute.
-///
-/// If we now want to use that constant in a place which potentially needs its type
-/// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`,
-/// except that instead of a `Ty` we bundle the `DefId` of the const parameter.
-/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some`
-/// to get the type of `did`.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)]
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-#[derive(Hash, HashStable)]
-pub struct WithOptConstParam<T> {
- pub did: T,
- /// The `DefId` of the corresponding generic parameter in case `did` is
- /// a const argument.
- ///
- /// Note that even if `did` is a const argument, this may still be `None`.
- /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)`
- /// to potentially update `param_did` in the case it is `None`.
- pub const_param_did: Option<DefId>,
-}
-
-impl<T> WithOptConstParam<T> {
- /// Creates a new `WithOptConstParam` setting `const_param_did` to `None`.
- #[inline(always)]
- pub fn unknown(did: T) -> WithOptConstParam<T> {
- WithOptConstParam { did, const_param_did: None }
- }
-}
-
-impl WithOptConstParam<LocalDefId> {
- /// Returns `Some((did, param_did))` if `def_id` is a const argument,
- /// `None` otherwise.
- #[inline(always)]
- pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> {
- tcx.opt_const_param_of(did).map(|param_did| (did, param_did))
- }
-
- /// In case `self` is unknown but `self.did` is a const argument, this returns
- /// a `WithOptConstParam` with the correct `const_param_did`.
- #[inline(always)]
- pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> {
- if self.const_param_did.is_none() {
- if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) {
- return Some(WithOptConstParam { did: self.did, const_param_did });
- }
- }
-
- None
- }
-
- pub fn to_global(self) -> WithOptConstParam<DefId> {
- WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did }
- }
-
- pub fn def_id_for_type_of(self) -> DefId {
- if let Some(did) = self.const_param_did { did } else { self.did.to_def_id() }
- }
-}
-
-impl WithOptConstParam<DefId> {
- pub fn as_local(self) -> Option<WithOptConstParam<LocalDefId>> {
- self.did
- .as_local()
- .map(|did| WithOptConstParam { did, const_param_did: self.const_param_did })
- }
-
- pub fn as_const_arg(self) -> Option<(LocalDefId, DefId)> {
- if let Some(param_did) = self.const_param_did {
- if let Some(did) = self.did.as_local() {
- return Some((did, param_did));
- }
- }
-
- None
- }
-
- pub fn is_local(self) -> bool {
- self.did.is_local()
- }
-
- pub fn def_id_for_type_of(self) -> DefId {
- self.const_param_did.unwrap_or(self.did)
- }
-}
-
/// When type checking, we use the `ParamEnv` to track
/// details about the set of where-clauses that are in scope at this
/// particular point.
@@ -1626,27 +1542,12 @@ struct ParamTag {
constness: hir::Constness,
}
-unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
- const BITS: usize = 2;
- #[inline]
- fn into_usize(self) -> usize {
- match self {
- Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0,
- Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1,
- Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2,
- Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3,
- }
- }
- #[inline]
- unsafe fn from_usize(ptr: usize) -> Self {
- match ptr {
- 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
- 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst },
- 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const },
- 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const },
- _ => std::hint::unreachable_unchecked(),
- }
- }
+impl_tag! {
+ impl Tag for ParamTag;
+ ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
+ ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst },
+ ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const },
+ ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const },
}
impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
@@ -1850,12 +1751,6 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> {
pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
(self.param_env, self.value)
}
-
- #[inline]
- pub fn without_const(mut self) -> Self {
- self.param_env = self.param_env.without_const();
- self
- }
}
#[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
@@ -1868,7 +1763,7 @@ pub struct Destructor {
bitflags! {
#[derive(HashStable, TyEncodable, TyDecodable)]
- pub struct VariantFlags: u32 {
+ pub struct VariantFlags: u8 {
const NO_VARIANT_FLAGS = 0;
/// Indicates whether the field list of this variant is `#[non_exhaustive]`.
const IS_FIELD_LIST_NON_EXHAUSTIVE = 1 << 0;
@@ -1969,6 +1864,16 @@ impl VariantDef {
pub fn ctor_def_id(&self) -> Option<DefId> {
self.ctor.map(|(_, def_id)| def_id)
}
+
+ /// Returns the one field in this variant.
+ ///
+ /// `panic!`s if there are no fields or multiple fields.
+ #[inline]
+ pub fn single_field(&self) -> &FieldDef {
+ assert!(self.fields.len() == 1);
+
+ &self.fields[FieldIdx::from_u32(0)]
+ }
}
impl PartialEq for VariantDef {
@@ -1983,7 +1888,20 @@ impl PartialEq for VariantDef {
let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
- lhs_def_id == rhs_def_id
+
+ let res = lhs_def_id == rhs_def_id;
+
+ // Double check that implicit assumption detailed above.
+ if cfg!(debug_assertions) && res {
+ let deep = self.ctor == other.ctor
+ && self.name == other.name
+ && self.discr == other.discr
+ && self.fields == other.fields
+ && self.flags == other.flags;
+ assert!(deep, "VariantDef for the same def-id has differing data");
+ }
+
+ res
}
}
@@ -2038,7 +1956,15 @@ impl PartialEq for FieldDef {
let Self { did: rhs_did, name: _, vis: _ } = other;
- lhs_did == rhs_did
+ let res = lhs_did == rhs_did;
+
+ // Double check that implicit assumption detailed above.
+ if cfg!(debug_assertions) && res {
+ let deep = self.name == other.name && self.vis == other.vis;
+ assert!(deep, "FieldDef for the same def-id has differing data");
+ }
+
+ res
}
}
@@ -2245,10 +2171,9 @@ impl<'tcx> TyCtxt<'tcx> {
/// See [`item_name`][Self::item_name] for more information.
pub fn opt_item_ident(self, def_id: DefId) -> Option<Ident> {
let def = self.opt_item_name(def_id)?;
- let span = def_id
- .as_local()
- .and_then(|id| self.def_ident_span(id))
- .unwrap_or(rustc_span::DUMMY_SP);
+ let span = self
+ .def_ident_span(def_id)
+ .unwrap_or_else(|| bug!("missing ident span for {def_id:?}"));
Some(Ident::new(def, span))
}
@@ -2289,8 +2214,8 @@ impl<'tcx> TyCtxt<'tcx> {
let impl_trait_ref2 = self.impl_trait_ref(def_id2);
// If either trait impl references an error, they're allowed to overlap,
// as one of them essentially doesn't exist.
- if impl_trait_ref1.map_or(false, |tr| tr.subst_identity().references_error())
- || impl_trait_ref2.map_or(false, |tr| tr.subst_identity().references_error())
+ if impl_trait_ref1.is_some_and(|tr| tr.subst_identity().references_error())
+ || impl_trait_ref2.is_some_and(|tr| tr.subst_identity().references_error())
{
return Some(ImplOverlapKind::Permitted { marker: false });
}
@@ -2311,7 +2236,7 @@ impl<'tcx> TyCtxt<'tcx> {
let is_marker_overlap = {
let is_marker_impl = |trait_ref: Option<EarlyBinder<TraitRef<'_>>>| -> bool {
- trait_ref.map_or(false, |tr| self.trait_def(tr.skip_binder().def_id).is_marker)
+ trait_ref.is_some_and(|tr| self.trait_def(tr.skip_binder().def_id).is_marker)
};
is_marker_impl(impl_trait_ref1) && is_marker_impl(impl_trait_ref2)
};
@@ -2361,7 +2286,7 @@ impl<'tcx> TyCtxt<'tcx> {
match instance {
ty::InstanceDef::Item(def) => {
debug!("calling def_kind on def: {:?}", def);
- let def_kind = self.def_kind(def.did);
+ let def_kind = self.def_kind(def);
debug!("returned from def_kind: {:?}", def_kind);
match def_kind {
DefKind::Const
@@ -2369,13 +2294,10 @@ impl<'tcx> TyCtxt<'tcx> {
| DefKind::AssocConst
| DefKind::Ctor(..)
| DefKind::AnonConst
- | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
+ | DefKind::InlineConst => self.mir_for_ctfe(def),
// If the caller wants `mir_for_ctfe` of a function they should not be using
// `instance_mir`, so we'll assume const fn also wants the optimized version.
- _ => {
- assert_eq!(def.const_param_did, None);
- self.optimized_mir(def.did)
- }
+ _ => self.optimized_mir(def),
}
}
ty::InstanceDef::VTableShim(..)
@@ -2566,9 +2488,7 @@ impl<'tcx> TyCtxt<'tcx> {
&& if self.features().collapse_debuginfo {
span.in_macro_expansion_with_collapse_debuginfo()
} else {
- // Inlined spans should not be collapsed as that leads to all of the
- // inlined code being attributed to the inline callsite.
- span.from_expansion() && !span.is_inlined()
+ span.from_expansion()
}
}
@@ -2599,6 +2519,18 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
+ /// Returns the `DefId` of the item within which the `impl Trait` is declared.
+ /// For type-alias-impl-trait this is the `type` alias.
+ /// For impl-trait-in-assoc-type this is the assoc type.
+ /// For return-position-impl-trait this is the function.
+ pub fn impl_trait_parent(self, mut def_id: LocalDefId) -> LocalDefId {
+ // Find the surrounding item (type alias or assoc type)
+ while let DefKind::OpaqueTy = self.def_kind(def_id) {
+ def_id = self.local_parent(def_id);
+ }
+ def_id
+ }
+
pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
if self.def_kind(def_id) != DefKind::AssocFn {
return false;
@@ -2643,7 +2575,7 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId>
hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
Some(parent)
}
- hir::OpaqueTyOrigin::TyAlias => None,
+ hir::OpaqueTyOrigin::TyAlias { .. } => None,
};
}
}
@@ -2701,7 +2633,7 @@ pub fn ast_uint_ty(uty: UintTy) -> ast::UintTy {
}
}
-pub fn provide(providers: &mut ty::query::Providers) {
+pub fn provide(providers: &mut Providers) {
closure::provide(providers);
context::provide(providers);
erase_regions::provide(providers);
@@ -2710,7 +2642,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
print::provide(providers);
super::util::bug::provide(providers);
super::middle::provide(providers);
- *providers = ty::query::Providers {
+ *providers = Providers {
trait_impls_of: trait_def::trait_impls_of_provider,
incoherent_impls: trait_def::incoherent_impls_provider,
const_param_default: consts::const_param_default,
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 7c59879a1..a0c8d299f 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -32,7 +32,7 @@ impl<'tcx> TyCtxt<'tcx> {
///
/// This should only be used outside of type inference. For example,
/// it assumes that normalization will succeed.
- #[tracing::instrument(level = "debug", skip(self, param_env))]
+ #[tracing::instrument(level = "debug", skip(self, param_env), ret)]
pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
@@ -139,7 +139,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
param_substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- value: T,
+ value: EarlyBinder<T>,
) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
@@ -151,7 +151,7 @@ impl<'tcx> TyCtxt<'tcx> {
param_env={:?})",
param_substs, value, param_env,
);
- let substituted = EarlyBinder(value).subst(self, param_substs);
+ let substituted = value.subst(self, param_substs);
self.normalize_erasing_regions(param_env, substituted)
}
@@ -163,7 +163,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
param_substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- value: T,
+ value: EarlyBinder<T>,
) -> Result<T, NormalizationError<'tcx>>
where
T: TypeFoldable<TyCtxt<'tcx>>,
@@ -175,7 +175,7 @@ impl<'tcx> TyCtxt<'tcx> {
param_env={:?})",
param_substs, value, param_env,
);
- let substituted = EarlyBinder(value).subst(self, param_substs);
+ let substituted = value.subst(self, param_substs);
self.try_normalize_erasing_regions(param_env, substituted)
}
}
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 751f3066c..1b336b7bf 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -177,7 +177,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
.sess
.struct_span_err(
self.span,
- &format!(
+ format!(
"type parameter `{}` is part of concrete type but not \
used in parameter list for the `impl Trait` type alias",
ty
@@ -207,14 +207,16 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
Some(GenericArgKind::Const(c1)) => c1,
Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
None => {
- if !self.ignore_errors {
- self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
+ let guar = self
+ .tcx
+ .sess
+ .create_err(ConstNotUsedTraitAlias {
ct: ct.to_string(),
span: self.span,
- });
- }
+ })
+ .emit_unless(self.ignore_errors);
- self.interner().const_error(ct.ty())
+ self.interner().const_error(ct.ty(), guar)
}
}
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 7534d06ae..a2e77d9cd 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -1,6 +1,6 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefIndex;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
use crate::ty;
@@ -56,6 +56,7 @@ trivially_parameterized_over_tcx! {
std::string::String,
crate::metadata::ModChild,
crate::middle::codegen_fn_attrs::CodegenFnAttrs,
+ crate::middle::debugger_visualizer::DebuggerVisualizerFile,
crate::middle::exported_symbols::SymbolExportInfo,
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
@@ -91,7 +92,6 @@ trivially_parameterized_over_tcx! {
rustc_session::cstore::ForeignModule,
rustc_session::cstore::LinkagePreference,
rustc_session::cstore::NativeLib,
- rustc_span::DebuggerVisualizerFile,
rustc_span::ExpnData,
rustc_span::ExpnHash,
rustc_span::ExpnId,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index d947d9604..64e7480e6 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -169,8 +169,11 @@ pub trait Printer<'tcx>: Sized {
self.path_append(
|cx: Self| {
if trait_qualify_parent {
- let trait_ref =
- cx.tcx().mk_trait_ref(parent_def_id, parent_substs.iter().copied());
+ let trait_ref = ty::TraitRef::new(
+ cx.tcx(),
+ parent_def_id,
+ parent_substs.iter().copied(),
+ );
cx.path_qualified(trait_ref.self_ty(), Some(trait_ref))
} else {
cx.print_def_path(parent_def_id, parent_substs)
@@ -327,6 +330,6 @@ pub fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
if def_id.is_top_level_module() {
"top-level module".to_string()
} else {
- format!("module `{}`", tcx.def_path_str(def_id.to_def_id()))
+ format!("module `{}`", tcx.def_path_str(def_id))
}
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 72caadaf6..d6c88ea96 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,4 +1,6 @@
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
+use crate::query::IntoQueryParam;
+use crate::query::Providers;
use crate::ty::{
self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -698,10 +700,10 @@ pub trait PrettyPrinter<'tcx>:
if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
}
}
- ty::Error(_) => p!("[type error]"),
+ ty::Error(_) => p!("{{type error}}"),
ty::Param(ref param_ty) => p!(print(param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
- ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
+ ty::BoundTyKind::Anon => debug_bound_var(&mut self, debruijn, bound_ty.var)?,
ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
true => p!(write("^{}_{}", debruijn.index(), s)),
@@ -728,7 +730,7 @@ pub trait PrettyPrinter<'tcx>:
ty::Foreign(def_id) => {
p!(print_def_path(def_id, &[]));
}
- ty::Alias(ty::Projection, ref data) => {
+ ty::Alias(ty::Projection | ty::Inherent, ref data) => {
if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
&& self.tcx().is_impl_trait_in_trait(data.def_id)
{
@@ -738,7 +740,9 @@ pub trait PrettyPrinter<'tcx>:
}
}
ty::Placeholder(placeholder) => match placeholder.bound.kind {
- ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
+ ty::BoundTyKind::Anon => {
+ debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound.var)?;
+ }
ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
},
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
@@ -911,7 +915,7 @@ pub trait PrettyPrinter<'tcx>:
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
- let bounds = tcx.bound_explicit_item_bounds(def_id);
+ let bounds = tcx.explicit_item_bounds(def_id);
let mut traits = FxIndexMap::default();
let mut fn_traits = FxIndexMap::default();
@@ -1160,16 +1164,20 @@ pub trait PrettyPrinter<'tcx>:
traits.entry(trait_ref).or_default().extend(proj_ty);
}
- fn pretty_print_bound_var(
- &mut self,
- debruijn: ty::DebruijnIndex,
- var: ty::BoundVar,
- ) -> Result<(), Self::Error> {
- if debruijn == ty::INNERMOST {
- write!(self, "^{}", var.index())
- } else {
- write!(self, "^{}_{}", debruijn.index(), var.index())
- }
+ fn pretty_print_inherent_projection(
+ self,
+ alias_ty: &ty::AliasTy<'tcx>,
+ ) -> Result<Self::Path, Self::Error> {
+ let def_key = self.tcx().def_key(alias_ty.def_id);
+ self.path_generic_args(
+ |cx| {
+ cx.path_append(
+ |cx| cx.path_qualified(alias_ty.self_ty(), None),
+ &def_key.disambiguated_data,
+ )
+ },
+ &alias_ty.substs[1..],
+ )
}
fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
@@ -1305,7 +1313,7 @@ pub trait PrettyPrinter<'tcx>:
define_scoped_cx!(self);
if self.should_print_verbose() {
- p!(write("Const({:?}: {:?})", ct.kind(), ct.ty()));
+ p!(write("{:?}", ct));
return Ok(self);
}
@@ -1328,13 +1336,13 @@ pub trait PrettyPrinter<'tcx>:
match ct.kind() {
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
- match self.tcx().def_kind(def.did) {
+ match self.tcx().def_kind(def) {
DefKind::Const | DefKind::AssocConst => {
- p!(print_value_path(def.did, substs))
+ p!(print_value_path(def, substs))
}
DefKind::AnonConst => {
if def.is_local()
- && let span = self.tcx().def_span(def.did)
+ && let span = self.tcx().def_span(def)
&& let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
{
p!(write("{}", snip))
@@ -1344,7 +1352,7 @@ pub trait PrettyPrinter<'tcx>:
// cause printing to enter an infinite recursion if the anon const is in the self type i.e.
// `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {`
// where we would try to print `<[T; /* print `constant#0` again */] as Default>::{constant#0}`
- p!(write("{}::{}", self.tcx().crate_name(def.did.krate), self.tcx().def_path(def.did).to_string_no_crate_verbose()))
+ p!(write("{}::{}", self.tcx().crate_name(def.krate), self.tcx().def_path(def).to_string_no_crate_verbose()))
}
}
defkind => bug!("`{:?}` has unexpected defkind {:?}", ct, defkind),
@@ -1364,13 +1372,15 @@ pub trait PrettyPrinter<'tcx>:
}
ty::ConstKind::Bound(debruijn, bound_var) => {
- self.pretty_print_bound_var(debruijn, bound_var)?
+ debug_bound_var(&mut self, debruijn, bound_var)?
}
- ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
+ ty::ConstKind::Placeholder(placeholder) => {
+ debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound)?;
+ },
// FIXME(generic_const_exprs):
// write out some legible representation of an abstract const?
- ty::ConstKind::Expr(_) => p!("[const expr]"),
- ty::ConstKind::Error(_) => p!("[const error]"),
+ ty::ConstKind::Expr(_) => p!("{{const expr}}"),
+ ty::ConstKind::Error(_) => p!("{{const error}}"),
};
Ok(self)
}
@@ -1787,17 +1797,27 @@ fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
impl<'t> TyCtxt<'t> {
/// Returns a string identifying this `DefId`. This string is
/// suitable for user output.
- pub fn def_path_str(self, def_id: DefId) -> String {
+ pub fn def_path_str(self, def_id: impl IntoQueryParam<DefId>) -> String {
self.def_path_str_with_substs(def_id, &[])
}
- pub fn def_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
+ pub fn def_path_str_with_substs(
+ self,
+ def_id: impl IntoQueryParam<DefId>,
+ substs: &'t [GenericArg<'t>],
+ ) -> String {
+ let def_id = def_id.into_query_param();
let ns = guess_def_namespace(self, def_id);
debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
FmtPrinter::new(self, ns).print_def_path(def_id, substs).unwrap().into_buffer()
}
- pub fn value_path_str_with_substs(self, def_id: DefId, substs: &'t [GenericArg<'t>]) -> String {
+ pub fn value_path_str_with_substs(
+ self,
+ def_id: impl IntoQueryParam<DefId>,
+ substs: &'t [GenericArg<'t>],
+ ) -> String {
+ let def_id = def_id.into_query_param();
let ns = guess_def_namespace(self, def_id);
debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns);
FmtPrinter::new(self, ns).print_value_path(def_id, substs).unwrap().into_buffer()
@@ -2518,7 +2538,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
self.used_region_names.insert(name);
}
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
// We collect types in order to prevent really large types from compiling for
@@ -2608,6 +2628,12 @@ macro_rules! define_print_and_forward_display {
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
+impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintOnlyTraitPath<'tcx> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, f)
@@ -2665,7 +2691,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> {
}
}
-#[derive(Debug, Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Debug, Copy, Clone, Lift)]
pub struct PrintClosureAsImpl<'tcx> {
pub closure: ty::ClosureSubsts<'tcx>,
}
@@ -2791,6 +2817,9 @@ define_print_and_forward_display! {
if let ty::BoundConstness::ConstIfConst = self.constness && cx.tcx().features().const_trait_impl {
p!("~const ");
}
+ if let ty::ImplPolarity::Negative = self.polarity {
+ p!("!");
+ }
p!(print(self.trait_ref.print_only_trait_path()))
}
@@ -2808,7 +2837,11 @@ define_print_and_forward_display! {
}
ty::AliasTy<'tcx> {
- p!(print_def_path(self.def_id, self.substs));
+ if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) {
+ p!(pretty_print_inherent_projection(self))
+ } else {
+ p!(print_def_path(self.def_id, self.substs));
+ }
}
ty::ClosureKind {
@@ -3020,8 +3053,8 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
map
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers { trimmed_def_paths, ..*providers };
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers { trimmed_def_paths, ..*providers };
}
#[derive(Default)]
@@ -3032,3 +3065,27 @@ pub struct OpaqueFnEntry<'tcx> {
fn_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
return_ty: Option<ty::Binder<'tcx, Term<'tcx>>>,
}
+
+pub fn debug_bound_var<T: std::fmt::Write>(
+ fmt: &mut T,
+ debruijn: ty::DebruijnIndex,
+ var: ty::BoundVar,
+) -> Result<(), std::fmt::Error> {
+ if debruijn == ty::INNERMOST {
+ write!(fmt, "^{}", var.index())
+ } else {
+ write!(fmt, "^{}_{}", debruijn.index(), var.index())
+ }
+}
+
+pub fn debug_placeholder_var<T: std::fmt::Write>(
+ fmt: &mut T,
+ universe: ty::UniverseIndex,
+ bound: ty::BoundVar,
+) -> Result<(), std::fmt::Error> {
+ if universe == ty::UniverseIndex::ROOT {
+ write!(fmt, "!{}", bound.index())
+ } else {
+ write!(fmt, "!{}_{}", universe.index(), bound.index())
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
deleted file mode 100644
index fa9fea723..000000000
--- a/compiler/rustc_middle/src/ty/query.rs
+++ /dev/null
@@ -1,606 +0,0 @@
-#![allow(unused_parens)]
-
-use crate::dep_graph;
-use crate::infer::canonical::{self, Canonical};
-use crate::lint::LintExpectation;
-use crate::metadata::ModChild;
-use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
-use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
-use crate::middle::lib_features::LibFeatures;
-use crate::middle::privacy::EffectiveVisibilities;
-use crate::middle::resolve_bound_vars::{ObjectLifetimeDefault, ResolveBoundVars, ResolvedArg};
-use crate::middle::stability::{self, DeprecationEntry};
-use crate::mir;
-use crate::mir::interpret::GlobalId;
-use crate::mir::interpret::{
- ConstValue, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult,
-};
-use crate::mir::interpret::{LitToConstError, LitToConstInput};
-use crate::mir::mono::CodegenUnit;
-use crate::query::erase::{erase, restore, Erase};
-use crate::query::{AsLocalKey, Key};
-use crate::thir;
-use crate::traits::query::{
- CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
- CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
- CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution,
-};
-use crate::traits::query::{
- DropckConstraint, DropckOutlivesResult, MethodAutoderefStepsResult, NormalizationResult,
- OutlivesBound,
-};
-use crate::traits::specialization_graph;
-use crate::traits::{self, ImplSource};
-use crate::ty::context::TyCtxtFeed;
-use crate::ty::fast_reject::SimplifiedType;
-use crate::ty::layout::ValidityRequirement;
-use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::util::AlwaysRequiresDrop;
-use crate::ty::GeneratorDiagnosticData;
-use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt, UnusedGenericParams};
-use rustc_arena::TypedArena;
-use rustc_ast as ast;
-use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_attr as attr;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
-use rustc_data_structures::steal::Steal;
-use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::sync::WorkerLocal;
-use rustc_data_structures::unord::UnordSet;
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, DocLinkResMap};
-use rustc_hir::def_id::{
- CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet,
-};
-use rustc_hir::hir_id::OwnerId;
-use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
-use rustc_index::vec::IndexVec;
-pub(crate) use rustc_query_system::query::QueryJobId;
-use rustc_query_system::query::*;
-use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
-use rustc_session::cstore::{CrateDepKind, CrateSource};
-use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
-use rustc_session::lint::LintExpectationId;
-use rustc_session::Limits;
-use rustc_span::symbol::Symbol;
-use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi;
-use rustc_target::spec::PanicStrategy;
-
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::Deref;
-use std::path::PathBuf;
-use std::sync::Arc;
-
-#[derive(Default)]
-pub struct QuerySystem<'tcx> {
- pub arenas: QueryArenas<'tcx>,
- pub caches: QueryCaches<'tcx>,
- // Since we erase query value types we tell the typesystem about them with `PhantomData`.
- _phantom_values: QueryPhantomValues<'tcx>,
-}
-
-#[derive(Copy, Clone)]
-pub struct TyCtxtAt<'tcx> {
- pub tcx: TyCtxt<'tcx>,
- pub span: Span,
-}
-
-impl<'tcx> Deref for TyCtxtAt<'tcx> {
- type Target = TyCtxt<'tcx>;
- #[inline(always)]
- fn deref(&self) -> &Self::Target {
- &self.tcx
- }
-}
-
-#[derive(Copy, Clone)]
-pub struct TyCtxtEnsure<'tcx> {
- pub tcx: TyCtxt<'tcx>,
-}
-
-#[derive(Copy, Clone)]
-pub struct TyCtxtEnsureWithValue<'tcx> {
- pub tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> TyCtxt<'tcx> {
- /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
- /// are executed instead of just returning their results.
- #[inline(always)]
- pub fn ensure(self) -> TyCtxtEnsure<'tcx> {
- TyCtxtEnsure { tcx: self }
- }
-
- /// Returns a transparent wrapper for `TyCtxt`, which ensures queries
- /// are executed instead of just returning their results.
- ///
- /// This version verifies that the computed result exists in the cache before returning.
- #[inline(always)]
- pub fn ensure_with_value(self) -> TyCtxtEnsureWithValue<'tcx> {
- TyCtxtEnsureWithValue { tcx: self }
- }
-
- /// Returns a transparent wrapper for `TyCtxt` which uses
- /// `span` as the location of queries performed through it.
- #[inline(always)]
- pub fn at(self, span: Span) -> TyCtxtAt<'tcx> {
- TyCtxtAt { tcx: self, span }
- }
-
- pub fn try_mark_green(self, dep_node: &dep_graph::DepNode) -> bool {
- self.queries.try_mark_green(self, dep_node)
- }
-}
-
-macro_rules! query_helper_param_ty {
- (DefId) => { impl IntoQueryParam<DefId> };
- (LocalDefId) => { impl IntoQueryParam<LocalDefId> };
- ($K:ty) => { $K };
-}
-
-macro_rules! query_if_arena {
- ([] $arena:tt $no_arena:tt) => {
- $no_arena
- };
- ([(arena_cache) $($rest:tt)*] $arena:tt $no_arena:tt) => {
- $arena
- };
- ([$other:tt $($modifiers:tt)*]$($args:tt)*) => {
- query_if_arena!([$($modifiers)*]$($args)*)
- };
-}
-
-/// If `separate_provide_if_extern`, then the key can be projected to its
-/// local key via `<$K as AsLocalKey>::LocalKey`.
-macro_rules! local_key_if_separate_extern {
- ([] $($K:tt)*) => {
- $($K)*
- };
- ([(separate_provide_extern) $($rest:tt)*] $($K:tt)*) => {
- <$($K)* as AsLocalKey>::LocalKey
- };
- ([$other:tt $($modifiers:tt)*] $($K:tt)*) => {
- local_key_if_separate_extern!([$($modifiers)*] $($K)*)
- };
-}
-
-macro_rules! separate_provide_extern_decl {
- ([][$name:ident]) => {
- ()
- };
- ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
- for<'tcx> fn(
- TyCtxt<'tcx>,
- query_keys::$name<'tcx>,
- ) -> query_provided::$name<'tcx>
- };
- ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
- separate_provide_extern_decl!([$($modifiers)*][$($args)*])
- };
-}
-
-macro_rules! separate_provide_extern_default {
- ([][$name:ident]) => {
- ()
- };
- ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
- |_, key| bug!(
- "`tcx.{}({:?})` unsupported by its crate; \
- perhaps the `{}` query was never assigned a provider function",
- stringify!($name),
- key,
- stringify!($name),
- )
- };
- ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
- separate_provide_extern_default!([$($modifiers)*][$($args)*])
- };
-}
-
-macro_rules! opt_remap_env_constness {
- ([][$name:ident]) => {};
- ([(remap_env_constness) $($rest:tt)*][$name:ident]) => {
- let $name = $name.without_const();
- };
- ([$other:tt $($modifiers:tt)*][$name:ident]) => {
- opt_remap_env_constness!([$($modifiers)*][$name])
- };
-}
-
-macro_rules! define_callbacks {
- (
- $($(#[$attr:meta])*
- [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
-
- // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
- // below, but using type aliases instead of associated types, to bypass
- // the limitations around normalizing under HRTB - for example, this:
- // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
- // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
- // This is primarily used by the `provide!` macro in `rustc_metadata`.
- #[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_keys {
- use super::*;
-
- $(pub type $name<'tcx> = $($K)*;)*
- }
- #[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_keys_local {
- use super::*;
-
- $(pub type $name<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);)*
- }
- #[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_values {
- use super::*;
-
- $(pub type $name<'tcx> = $V;)*
- }
-
- /// This module specifies the type returned from query providers and the type used for
- /// decoding. For regular queries this is the declared returned type `V`, but
- /// `arena_cache` will use `<V as Deref>::Target` instead.
- #[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_provided {
- use super::*;
-
- $(
- pub type $name<'tcx> = query_if_arena!([$($modifiers)*] (<$V as Deref>::Target) ($V));
- )*
- }
-
- /// This module has a function per query which takes a `query_provided` value and coverts
- /// it to a regular `V` value by allocating it on an arena if the query has the
- /// `arena_cache` modifier. This will happen when computing the query using a provider or
- /// decoding a stored result.
- #[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_provided_to_value {
- use super::*;
-
- $(
- #[inline(always)]
- pub fn $name<'tcx>(
- _tcx: TyCtxt<'tcx>,
- value: query_provided::$name<'tcx>,
- ) -> Erase<query_values::$name<'tcx>> {
- erase(query_if_arena!([$($modifiers)*]
- {
- if mem::needs_drop::<query_provided::$name<'tcx>>() {
- &*_tcx.query_system.arenas.$name.alloc(value)
- } else {
- &*_tcx.arena.dropless.alloc(value)
- }
- }
- (value)
- ))
- }
- )*
- }
- #[allow(nonstandard_style, unused_lifetimes)]
- pub mod query_storage {
- use super::*;
-
- $(
- pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>>::Cache;
- )*
- }
-
- $(
- // Ensure that keys grow no larger than 64 bytes
- #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
- const _: () = {
- if mem::size_of::<query_keys::$name<'static>>() > 64 {
- panic!("{}", concat!(
- "the query `",
- stringify!($name),
- "` has a key type `",
- stringify!($($K)*),
- "` that is too large"
- ));
- }
- };
-
- // Ensure that values grow no larger than 64 bytes
- #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
- const _: () = {
- if mem::size_of::<query_values::$name<'static>>() > 64 {
- panic!("{}", concat!(
- "the query `",
- stringify!($name),
- "` has a value type `",
- stringify!($V),
- "` that is too large"
- ));
- }
- };
- )*
-
- pub struct QueryArenas<'tcx> {
- $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
- (WorkerLocal<TypedArena<<$V as Deref>::Target>>)
- ()
- ),)*
- }
-
- impl Default for QueryArenas<'_> {
- fn default() -> Self {
- Self {
- $($name: query_if_arena!([$($modifiers)*]
- (WorkerLocal::new(|_| Default::default()))
- ()
- ),)*
- }
- }
- }
-
- #[derive(Default)]
- pub struct QueryPhantomValues<'tcx> {
- $($(#[$attr])* pub $name: PhantomData<query_values::$name<'tcx>>,)*
- }
-
- #[derive(Default)]
- pub struct QueryCaches<'tcx> {
- $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
- }
-
- impl<'tcx> TyCtxtEnsure<'tcx> {
- $($(#[$attr])*
- #[inline(always)]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
- let key = key.into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
-
- match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
- Some(_) => return,
- None => self.tcx.queries.$name(
- self.tcx,
- DUMMY_SP,
- key,
- QueryMode::Ensure { check_cache: false },
- ),
- };
- })*
- }
-
- impl<'tcx> TyCtxtEnsureWithValue<'tcx> {
- $($(#[$attr])*
- #[inline(always)]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) {
- let key = key.into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
-
- match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
- Some(_) => return,
- None => self.tcx.queries.$name(
- self.tcx,
- DUMMY_SP,
- key,
- QueryMode::Ensure { check_cache: true },
- ),
- };
- })*
- }
-
- impl<'tcx> TyCtxt<'tcx> {
- $($(#[$attr])*
- #[inline(always)]
- #[must_use]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
- {
- self.at(DUMMY_SP).$name(key)
- })*
- }
-
- impl<'tcx> TyCtxtAt<'tcx> {
- $($(#[$attr])*
- #[inline(always)]
- pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> $V
- {
- let key = key.into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
-
- restore::<$V>(match try_get_cached(self.tcx, &self.tcx.query_system.caches.$name, &key) {
- Some(value) => value,
- None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
- })
- })*
- }
-
- pub struct Providers {
- $(pub $name: for<'tcx> fn(
- TyCtxt<'tcx>,
- query_keys_local::$name<'tcx>,
- ) -> query_provided::$name<'tcx>,)*
- }
-
- pub struct ExternProviders {
- $(pub $name: separate_provide_extern_decl!([$($modifiers)*][$name]),)*
- }
-
- impl Default for Providers {
- fn default() -> Self {
- Providers {
- $($name: |_, key| bug!(
- "`tcx.{}({:?})` is not supported for this key;\n\
- hint: Queries can be either made to the local crate, or the external crate. \
- This error means you tried to use it for one that's not supported.\n\
- If that's not the case, {} was likely never assigned to a provider function.\n",
- stringify!($name),
- key,
- stringify!($name),
- ),)*
- }
- }
- }
-
- impl Default for ExternProviders {
- fn default() -> Self {
- ExternProviders {
- $($name: separate_provide_extern_default!([$($modifiers)*][$name]),)*
- }
- }
- }
-
- impl Copy for Providers {}
- impl Clone for Providers {
- fn clone(&self) -> Self { *self }
- }
-
- impl Copy for ExternProviders {}
- impl Clone for ExternProviders {
- fn clone(&self) -> Self { *self }
- }
-
- pub trait QueryEngine<'tcx>: rustc_data_structures::sync::Sync {
- fn as_any(&'tcx self) -> &'tcx dyn std::any::Any;
-
- fn try_mark_green(&'tcx self, tcx: TyCtxt<'tcx>, dep_node: &dep_graph::DepNode) -> bool;
-
- $($(#[$attr])*
- fn $name(
- &'tcx self,
- tcx: TyCtxt<'tcx>,
- span: Span,
- key: query_keys::$name<'tcx>,
- mode: QueryMode,
- ) -> Option<Erase<$V>>;)*
- }
- };
-}
-
-macro_rules! hash_result {
- ([]) => {{
- Some(dep_graph::hash_result)
- }};
- ([(no_hash) $($rest:tt)*]) => {{
- None
- }};
- ([$other:tt $($modifiers:tt)*]) => {
- hash_result!([$($modifiers)*])
- };
-}
-
-macro_rules! define_feedable {
- ($($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
- $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
- $(#[$attr])*
- #[inline(always)]
- pub fn $name(self, value: query_provided::$name<'tcx>) -> $V {
- let key = self.key().into_query_param();
- opt_remap_env_constness!([$($modifiers)*][key]);
-
- let tcx = self.tcx;
- let erased = query_provided_to_value::$name(tcx, value);
- let value = restore::<$V>(erased);
- let cache = &tcx.query_system.caches.$name;
-
- match try_get_cached(tcx, cache, &key) {
- Some(old) => {
- let old = restore::<$V>(old);
- bug!(
- "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
- stringify!($name),
- )
- }
- None => {
- let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
- let dep_node_index = tcx.dep_graph.with_feed_task(
- dep_node,
- tcx,
- key,
- &value,
- hash_result!([$($modifiers)*]),
- );
- cache.complete(key, erased, dep_node_index);
- value
- }
- }
- }
- })*
- }
-}
-
-// Each of these queries corresponds to a function pointer field in the
-// `Providers` struct for requesting a value of that type, and a method
-// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
-// which memoizes and does dep-graph tracking, wrapping around the actual
-// `Providers` that the driver creates (using several `rustc_*` crates).
-//
-// The result type of each query must implement `Clone`, and additionally
-// `ty::query::values::Value`, which produces an appropriate placeholder
-// (error) value if the query resulted in a query cycle.
-// Queries marked with `fatal_cycle` do not need the latter implementation,
-// as they will raise an fatal error on query cycles instead.
-
-rustc_query_append! { define_callbacks! }
-rustc_feedable_queries! { define_feedable! }
-
-mod sealed {
- use super::{DefId, LocalDefId, OwnerId};
-
- /// An analogue of the `Into` trait that's intended only for query parameters.
- ///
- /// This exists to allow queries to accept either `DefId` or `LocalDefId` while requiring that the
- /// user call `to_def_id` to convert between them everywhere else.
- pub trait IntoQueryParam<P> {
- fn into_query_param(self) -> P;
- }
-
- impl<P> IntoQueryParam<P> for P {
- #[inline(always)]
- fn into_query_param(self) -> P {
- self
- }
- }
-
- impl<'a, P: Copy> IntoQueryParam<P> for &'a P {
- #[inline(always)]
- fn into_query_param(self) -> P {
- *self
- }
- }
-
- impl IntoQueryParam<LocalDefId> for OwnerId {
- #[inline(always)]
- fn into_query_param(self) -> LocalDefId {
- self.def_id
- }
- }
-
- impl IntoQueryParam<DefId> for LocalDefId {
- #[inline(always)]
- fn into_query_param(self) -> DefId {
- self.to_def_id()
- }
- }
-
- impl IntoQueryParam<DefId> for OwnerId {
- #[inline(always)]
- fn into_query_param(self) -> DefId {
- self.to_def_id()
- }
- }
-}
-
-use sealed::IntoQueryParam;
-
-impl<'tcx> TyCtxt<'tcx> {
- pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
- let def_id = def_id.into_query_param();
- self.opt_def_kind(def_id)
- .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
- }
-}
-
-impl<'tcx> TyCtxtAt<'tcx> {
- pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
- let def_id = def_id.into_query_param();
- self.opt_def_kind(def_id)
- .unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
- }
-}
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 46c931d61..3bbe6a23b 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -7,7 +7,7 @@
use crate::ty::error::{ExpectedFound, TypeError};
use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
use crate::ty::{GenericArg, GenericArgKind, SubstsRef};
-use rustc_hir as ast;
+use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_target::spec::abi;
use std::iter;
@@ -123,8 +123,8 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
} else {
let mutbl = a.mutbl;
let (variance, info) = match mutbl {
- ast::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
- ast::Mutability::Mut => {
+ hir::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
+ hir::Mutability::Mut => {
(ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: base_ty, param_index: 0 })
}
};
@@ -239,12 +239,12 @@ impl<'tcx> Relate<'tcx> for ty::BoundConstness {
}
}
-impl<'tcx> Relate<'tcx> for ast::Unsafety {
+impl<'tcx> Relate<'tcx> for hir::Unsafety {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
- a: ast::Unsafety,
- b: ast::Unsafety,
- ) -> RelateResult<'tcx, ast::Unsafety> {
+ a: hir::Unsafety,
+ b: hir::Unsafety,
+ ) -> RelateResult<'tcx, hir::Unsafety> {
if a != b {
Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b)))
} else {
@@ -315,7 +315,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
Err(TypeError::Traits(expected_found(relation, a.def_id, b.def_id)))
} else {
let substs = relate_substs(relation, a.substs, b.substs)?;
- Ok(relation.tcx().mk_trait_ref(a.def_id, substs))
+ Ok(ty::TraitRef::new(relation.tcx(), a.def_id, substs))
}
}
}
@@ -388,24 +388,24 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> {
}
}
-/// The main "type relation" routine. Note that this does not handle
-/// inference artifacts, so you should filter those out before calling
-/// it.
-pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of projections, and inference variables have to be
+/// handled by the caller.
+pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
a: Ty<'tcx>,
b: Ty<'tcx>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let tcx = relation.tcx();
- debug!("super_relate_tys: a={:?} b={:?}", a, b);
+ debug!("structurally_relate_tys: a={:?} b={:?}", a, b);
match (a.kind(), b.kind()) {
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
// The caller should handle these cases!
- bug!("var types encountered in super_relate_tys")
+ bug!("var types encountered in structurally_relate_tys")
}
(ty::Bound(..), _) | (_, ty::Bound(..)) => {
- bug!("bound types encountered in super_relate_tys")
+ bug!("bound types encountered in structurally_relate_tys")
}
(&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
@@ -550,6 +550,11 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
}
+ (&ty::Alias(ty::Inherent, a_data), &ty::Alias(ty::Inherent, b_data)) => {
+ let alias_ty = relation.relate(a_data, b_data)?;
+ Ok(tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(alias_ty.def_id, alias_ty.substs)))
+ }
+
(
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
@@ -570,15 +575,18 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
}
}
-/// The main "const relation" routine. Note that this does not handle
-/// inference artifacts, so you should filter those out before calling
-/// it.
-pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
+/// Relates `a` and `b` structurally, calling the relation for all nested values.
+/// Any semantic equality, e.g. of unevaluated consts, and inference variables have
+/// to be handled by the caller.
+///
+/// FIXME: This is not totally structual, which probably should be fixed.
+/// See the HACKs below.
+pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
relation: &mut R,
mut a: ty::Const<'tcx>,
mut b: ty::Const<'tcx>,
) -> RelateResult<'tcx, ty::Const<'tcx>> {
- debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
+ debug!("{}.structurally_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
let tcx = relation.tcx();
// HACK(const_generics): We still need to eagerly evaluate consts when
@@ -597,7 +605,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
b = tcx.expand_abstract_consts(b);
}
- debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+ debug!("{}.structurally_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
@@ -605,7 +613,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
let is_match = match (a.kind(), b.kind()) {
(ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => {
// The caller should handle these cases!
- bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b)
+ bug!("var types encountered in structurally_relate_consts: {:?} {:?}", a, b)
}
(ty::ConstKind::Error(_), _) => return Ok(a),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 5c604bb6d..16cb6c910 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -4,13 +4,12 @@
//! to help with the tedium.
use crate::mir::interpret;
-use crate::mir::ProjectionKind;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
use rustc_hir::def::Namespace;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
use rustc_target::abi::TyAndLayout;
use std::fmt;
@@ -95,7 +94,7 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "_#{}c", self.index)
+ write!(f, "?{}c", self.index)
}
}
@@ -193,11 +192,49 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> {
}
}
+impl<'tcx> fmt::Debug for ty::InferConst<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ InferConst::Var(var) => write!(f, "{var:?}"),
+ InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
+ }
+ }
+}
+
+impl<'tcx> fmt::Debug for ty::Const<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // This reflects what `Const` looked liked before `Interned` was
+ // introduced. We print it like this to avoid having to update expected
+ // output in a lot of tests.
+ write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
+ }
+}
+
+impl<'tcx> fmt::Debug for ty::ConstKind<'tcx> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ use ty::ConstKind::*;
+ match self {
+ Param(param) => write!(f, "{param:?}"),
+ Infer(var) => write!(f, "{var:?}"),
+ Bound(debruijn, var) => ty::print::debug_bound_var(f, *debruijn, *var),
+ Placeholder(placeholder) => {
+ ty::print::debug_placeholder_var(f, placeholder.universe, placeholder.bound)
+ }
+ Unevaluated(uv) => {
+ f.debug_tuple("Unevaluated").field(&uv.substs).field(&uv.def).finish()
+ }
+ Value(valtree) => write!(f, "{valtree:?}"),
+ Error(_) => write!(f, "[const error]"),
+ Expr(expr) => write!(f, "{expr:?}"),
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// Atomic structs
//
// For things that don't carry any arena-allocated data (and are
-// copy...), just add them to one of these lists as appropriat.
+// copy...), just add them to one of these lists as appropriate.
// For things for which the type library provides traversal implementations
// for all Interners, we only need to provide a Lift implementation:
@@ -205,6 +242,7 @@ CloneLiftImpls! {
(),
bool,
usize,
+ u8,
u16,
u32,
u64,
@@ -276,9 +314,7 @@ TrivialTypeTraversalAndLiftImpls! {
}
TrivialTypeTraversalAndLiftImpls! {
- for<'tcx> {
- ty::ValTree<'tcx>,
- }
+ ty::ValTree<'tcx>,
}
///////////////////////////////////////////////////////////////////////////
@@ -375,16 +411,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
///////////////////////////////////////////////////////////////////////////
// Traversal implementations.
-/// AdtDefs are basically the same as a DefId.
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- _folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(self)
- }
-}
-
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
&self,
@@ -447,15 +473,6 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> {
}
}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ProjectionKind> {
- fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- ty::util::fold_list(self, folder, |tcx, v| tcx.mk_projs(v))
- }
-}
-
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
@@ -583,24 +600,6 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
}
}
-impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
- self,
- _folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(self)
- }
-}
-
-impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
- fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
- &self,
- _visitor: &mut V,
- ) -> ControlFlow<V::BreakTy> {
- ControlFlow::Continue(())
- }
-}
-
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 96c1577d5..e6d51c4ec 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -19,7 +19,7 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
-use rustc_index::vec::Idx;
+use rustc_index::Idx;
use rustc_macros::HashStable;
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
@@ -631,7 +631,7 @@ impl<'tcx> UpvarSubsts<'tcx> {
/// type of the constant. The reason that `R` is represented as an extra type parameter
/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
/// inline const can reference lifetimes that are internal to the creating function.
-#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
+#[derive(Copy, Clone, Debug)]
pub struct InlineConstSubsts<'tcx> {
/// Generic parameters from the enclosing item,
/// concatenated with the inferred type of the constant.
@@ -727,13 +727,13 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
ExistentialPredicate::AutoTrait(did) => {
let generics = tcx.generics_of(did);
let trait_ref = if generics.params.len() == 1 {
- tcx.mk_trait_ref(did, [self_ty])
+ ty::TraitRef::new(tcx, did, [self_ty])
} else {
// If this is an ill-formed auto trait, then synthesize
// new error substs for the missing generics.
let err_substs =
ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]);
- tcx.mk_trait_ref(did, err_substs)
+ ty::TraitRef::new(tcx, did, err_substs)
};
self.rebind(trait_ref).without_const().to_predicate(tcx)
}
@@ -820,36 +820,68 @@ pub struct TraitRef<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
/// This field exists to prevent the creation of `TraitRef` without
- /// calling [TyCtxt::mk_trait_ref].
- pub(super) _use_mk_trait_ref_instead: (),
+ /// calling [`TraitRef::new`].
+ pub(super) _use_trait_ref_new_instead: (),
}
impl<'tcx> TraitRef<'tcx> {
+ pub fn new(
+ tcx: TyCtxt<'tcx>,
+ trait_def_id: DefId,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+ ) -> Self {
+ let substs = tcx.check_and_mk_substs(trait_def_id, substs);
+ Self { def_id: trait_def_id, substs, _use_trait_ref_new_instead: () }
+ }
+
+ pub fn from_lang_item(
+ tcx: TyCtxt<'tcx>,
+ trait_lang_item: LangItem,
+ span: Span,
+ substs: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
+ ) -> Self {
+ let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span));
+ Self::new(tcx, trait_def_id, substs)
+ }
+
+ pub fn from_method(
+ tcx: TyCtxt<'tcx>,
+ trait_id: DefId,
+ substs: SubstsRef<'tcx>,
+ ) -> ty::TraitRef<'tcx> {
+ let defs = tcx.generics_of(trait_id);
+ ty::TraitRef::new(tcx, trait_id, tcx.mk_substs(&substs[..defs.params.len()]))
+ }
+
+ /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
+ /// are the parameters defined on trait.
+ pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> {
+ ty::TraitRef::new(tcx, def_id, InternalSubsts::identity_for_item(tcx, def_id))
+ }
+
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
- tcx.mk_trait_ref(
+ ty::TraitRef::new(
+ tcx,
self.def_id,
[self_ty.into()].into_iter().chain(self.substs.iter().skip(1)),
)
}
- /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
- /// are the parameters defined on trait.
- pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> {
- ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id)))
+ /// Converts this trait ref to a trait predicate with a given `constness` and a positive polarity.
+ #[inline]
+ pub fn with_constness(self, constness: ty::BoundConstness) -> ty::TraitPredicate<'tcx> {
+ ty::TraitPredicate { trait_ref: self, constness, polarity: ty::ImplPolarity::Positive }
}
+ /// Converts this trait ref to a trait predicate without `const` and a positive polarity.
#[inline]
- pub fn self_ty(&self) -> Ty<'tcx> {
- self.substs.type_at(0)
+ pub fn without_const(self) -> ty::TraitPredicate<'tcx> {
+ self.with_constness(ty::BoundConstness::NotConst)
}
- pub fn from_method(
- tcx: TyCtxt<'tcx>,
- trait_id: DefId,
- substs: SubstsRef<'tcx>,
- ) -> ty::TraitRef<'tcx> {
- let defs = tcx.generics_of(trait_id);
- tcx.mk_trait_ref(trait_id, tcx.mk_substs(&substs[..defs.params.len()]))
+ #[inline]
+ pub fn self_ty(&self) -> Ty<'tcx> {
+ self.substs.type_at(0)
}
}
@@ -907,7 +939,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
// otherwise the escaping vars would be captured by the binder
// debug_assert!(!self_ty.has_escaping_bound_vars());
- tcx.mk_trait_ref(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter()))
+ ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter()))
}
}
@@ -1158,9 +1190,9 @@ where
/// Represents the projection of an associated type.
///
-/// For a projection, this would be `<Ty as Trait<...>>::N`.
-///
-/// For an opaque type, there is no explicit syntax.
+/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
+/// * For an inherent projection, this would be `Ty::N<...>`.
+/// * For an opaque type, there is no explicit syntax.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct AliasTy<'tcx> {
@@ -1169,12 +1201,16 @@ pub struct AliasTy<'tcx> {
/// For a projection, these are the substitutions for the trait and the
/// GAT substitutions, if there are any.
///
+ /// For an inherent projection, they consist of the self type and the GAT substitutions,
+ /// if there are any.
+ ///
/// For RPIT the substitutions are for the generics of the function,
/// while for TAIT it is used for the generic parameters of the alias.
pub substs: SubstsRef<'tcx>,
- /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection,
- /// or the `OpaqueType` item if this is an opaque.
+ /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
+ /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
+ /// this is an opaque.
///
/// During codegen, `tcx.type_of(def_id)` can be used to get the type of the
/// underlying type if the type is an opaque.
@@ -1192,6 +1228,7 @@ pub struct AliasTy<'tcx> {
impl<'tcx> AliasTy<'tcx> {
pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
match tcx.def_kind(self.def_id) {
+ DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent,
DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
DefKind::OpaqueTy => ty::Opaque,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
@@ -1205,6 +1242,17 @@ impl<'tcx> AliasTy<'tcx> {
/// The following methods work only with associated type projections.
impl<'tcx> AliasTy<'tcx> {
+ pub fn self_ty(self) -> Ty<'tcx> {
+ self.substs.type_at(0)
+ }
+
+ pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
+ tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)))
+ }
+}
+
+/// The following methods work only with trait associated type projections.
+impl<'tcx> AliasTy<'tcx> {
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
match tcx.def_kind(self.def_id) {
DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
@@ -1217,7 +1265,7 @@ impl<'tcx> AliasTy<'tcx> {
/// Extracts the underlying trait reference and own substs from this projection.
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
- /// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs
+ /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own substs
pub fn trait_ref_and_own_substs(
self,
tcx: TyCtxt<'tcx>,
@@ -1226,7 +1274,7 @@ impl<'tcx> AliasTy<'tcx> {
let trait_def_id = self.trait_def_id(tcx);
let trait_generics = tcx.generics_of(trait_def_id);
(
- tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
+ ty::TraitRef::new(tcx, trait_def_id, self.substs.truncate_to(tcx, trait_generics)),
&self.substs[trait_generics.count()..],
)
}
@@ -1240,15 +1288,30 @@ impl<'tcx> AliasTy<'tcx> {
/// as well.
pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> {
let def_id = self.trait_def_id(tcx);
- tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
+ ty::TraitRef::new(tcx, def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id)))
}
+}
- pub fn self_ty(self) -> Ty<'tcx> {
- self.substs.type_at(0)
- }
+/// The following methods work only with inherent associated type projections.
+impl<'tcx> AliasTy<'tcx> {
+ /// Transform the substitutions to have the given `impl` substs as the base and the GAT substs on top of that.
+ ///
+ /// Does the following transformation:
+ ///
+ /// ```text
+ /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m]
+ ///
+ /// I_i impl subst
+ /// P_j GAT subst
+ /// ```
+ pub fn rebase_substs_onto_impl(
+ self,
+ impl_substs: ty::SubstsRef<'tcx>,
+ tcx: TyCtxt<'tcx>,
+ ) -> ty::SubstsRef<'tcx> {
+ debug_assert_eq!(self.kind(tcx), ty::Inherent);
- pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
- tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)))
+ tcx.mk_substs_from_iter(impl_substs.into_iter().chain(self.substs.into_iter().skip(1)))
}
}
@@ -1436,7 +1499,7 @@ pub struct ConstVid<'tcx> {
rustc_index::newtype_index! {
/// A **region** (lifetime) **v**ariable **ID**.
#[derive(HashStable)]
- #[debug_format = "'_#{}r"]
+ #[debug_format = "'?{}"]
pub struct RegionVid {}
}
@@ -1645,7 +1708,9 @@ impl<'tcx> Region<'tcx> {
ty::ReErased => {
flags = flags | TypeFlags::HAS_RE_ERASED;
}
- ty::ReError(_) => {}
+ ty::ReError(_) => {
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ }
}
debug!("type_flags({:?}) = {:?}", self, flags);
@@ -2303,13 +2368,11 @@ impl<'tcx> Ty<'tcx> {
ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
- ty::Alias(..) | ty::Param(_) => false,
+ ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
ty::Infer(ty::TyVar(_)) => false,
- ty::Bound(..)
- | ty::Placeholder(..)
- | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+ ty::Bound(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("`is_trivially_sized` applied to unexpected type: {:?}", self)
}
}
@@ -2400,6 +2463,13 @@ impl<'tcx> Ty<'tcx> {
_ => None,
}
}
+
+ pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool {
+ match self.kind() {
+ ty::Adt(adt, _) => tcx.lang_items().get(LangItem::CVoid) == Some(adt.did()),
+ _ => false,
+ }
+ }
}
/// Extra information about why we ended up with a particular variance.
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index f05b87343..43f95635a 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -21,7 +21,6 @@ use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
use std::ops::{ControlFlow, Deref};
-use std::slice;
/// An entity in the Rust type system, which can be one of
/// several kinds (types, lifetimes, and consts).
@@ -48,38 +47,13 @@ const TYPE_TAG: usize = 0b00;
const REGION_TAG: usize = 0b01;
const CONST_TAG: usize = 0b10;
-#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
pub enum GenericArgKind<'tcx> {
Lifetime(ty::Region<'tcx>),
Type(Ty<'tcx>),
Const(ty::Const<'tcx>),
}
-/// This function goes from `&'a [Ty<'tcx>]` to `&'a [GenericArg<'tcx>]`
-///
-/// This is sound as, for types, `GenericArg` is just
-/// `NonZeroUsize::new_unchecked(ty as *const _ as usize)` as
-/// long as we use `0` for the `TYPE_TAG`.
-pub fn ty_slice_as_generic_args<'a, 'tcx>(ts: &'a [Ty<'tcx>]) -> &'a [GenericArg<'tcx>] {
- assert_eq!(TYPE_TAG, 0);
- // SAFETY: the whole slice is valid and immutable.
- // `Ty` and `GenericArg` is explained above.
- unsafe { slice::from_raw_parts(ts.as_ptr().cast(), ts.len()) }
-}
-
-impl<'tcx> List<Ty<'tcx>> {
- /// Allows to freely switch between `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>`.
- ///
- /// As lists are interned, `List<Ty<'tcx>>` and `List<GenericArg<'tcx>>` have
- /// be interned together, see `mk_type_list` for more details.
- #[inline]
- pub fn as_substs(&'tcx self) -> SubstsRef<'tcx> {
- assert_eq!(TYPE_TAG, 0);
- // SAFETY: `List<T>` is `#[repr(C)]`. `Ty` and `GenericArg` is explained above.
- unsafe { &*(self as *const List<Ty<'tcx>> as *const List<GenericArg<'tcx>>) }
- }
-}
-
impl<'tcx> GenericArgKind<'tcx> {
#[inline]
fn pack(self) -> GenericArg<'tcx> {
@@ -180,30 +154,45 @@ impl<'tcx> GenericArg<'tcx> {
}
}
- /// Unpack the `GenericArg` as a region when it is known certainly to be a region.
- pub fn expect_region(self) -> ty::Region<'tcx> {
+ #[inline]
+ pub fn as_type(self) -> Option<Ty<'tcx>> {
match self.unpack() {
- GenericArgKind::Lifetime(lt) => lt,
- _ => bug!("expected a region, but found another kind"),
+ GenericArgKind::Type(ty) => Some(ty),
+ _ => None,
}
}
+ #[inline]
+ pub fn as_region(self) -> Option<ty::Region<'tcx>> {
+ match self.unpack() {
+ GenericArgKind::Lifetime(re) => Some(re),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub fn as_const(self) -> Option<ty::Const<'tcx>> {
+ match self.unpack() {
+ GenericArgKind::Const(ct) => Some(ct),
+ _ => None,
+ }
+ }
+
+ /// Unpack the `GenericArg` as a region when it is known certainly to be a region.
+ pub fn expect_region(self) -> ty::Region<'tcx> {
+ self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind"))
+ }
+
/// Unpack the `GenericArg` as a type when it is known certainly to be a type.
/// This is true in cases where `Substs` is used in places where the kinds are known
/// to be limited (e.g. in tuples, where the only parameters are type parameters).
pub fn expect_ty(self) -> Ty<'tcx> {
- match self.unpack() {
- GenericArgKind::Type(ty) => ty,
- _ => bug!("expected a type, but found another kind"),
- }
+ self.as_type().unwrap_or_else(|| bug!("expected a type, but found another kind"))
}
/// Unpack the `GenericArg` as a const when it is known certainly to be a const.
pub fn expect_const(self) -> ty::Const<'tcx> {
- match self.unpack() {
- GenericArgKind::Const(c) => c,
- _ => bug!("expected a const, but found another kind"),
- }
+ self.as_const().unwrap_or_else(|| bug!("expected a const, but found another kind"))
}
pub fn is_non_region_infer(self) -> bool {
@@ -268,13 +257,16 @@ pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
impl<'tcx> InternalSubsts<'tcx> {
- /// Checks whether all elements of this list are types, if so, transmute.
- pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List<Ty<'tcx>>> {
- self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))).then(|| {
- assert_eq!(TYPE_TAG, 0);
- // SAFETY: All elements are types, see `List<Ty<'tcx>>::as_substs`.
- unsafe { &*(self as *const List<GenericArg<'tcx>> as *const List<Ty<'tcx>>) }
- })
+ /// Converts substs to a type list.
+ ///
+ /// # Panics
+ ///
+ /// If any of the generic arguments are not types.
+ pub fn into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>> {
+ tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.unpack() {
+ GenericArgKind::Type(ty) => ty,
+ _ => bug!("`into_type_list` called on substs with non-types"),
+ }))
}
/// Interpret these substitutions as the substitutions of a closure type.
@@ -379,22 +371,17 @@ impl<'tcx> InternalSubsts<'tcx> {
#[inline]
pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx {
- self.iter()
- .filter_map(|k| if let GenericArgKind::Type(ty) = k.unpack() { Some(ty) } else { None })
+ self.iter().filter_map(|k| k.as_type())
}
#[inline]
pub fn regions(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'tcx {
- self.iter().filter_map(|k| {
- if let GenericArgKind::Lifetime(lt) = k.unpack() { Some(lt) } else { None }
- })
+ self.iter().filter_map(|k| k.as_region())
}
#[inline]
pub fn consts(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'tcx {
- self.iter().filter_map(|k| {
- if let GenericArgKind::Const(ct) = k.unpack() { Some(ct) } else { None }
- })
+ self.iter().filter_map(|k| k.as_const())
}
#[inline]
@@ -410,31 +397,21 @@ impl<'tcx> InternalSubsts<'tcx> {
#[inline]
#[track_caller]
pub fn type_at(&self, i: usize) -> Ty<'tcx> {
- if let GenericArgKind::Type(ty) = self[i].unpack() {
- ty
- } else {
- bug!("expected type for param #{} in {:?}", i, self);
- }
+ self[i].as_type().unwrap_or_else(|| bug!("expected type for param #{} in {:?}", i, self))
}
#[inline]
#[track_caller]
pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
- if let GenericArgKind::Lifetime(lt) = self[i].unpack() {
- lt
- } else {
- bug!("expected region for param #{} in {:?}", i, self);
- }
+ self[i]
+ .as_region()
+ .unwrap_or_else(|| bug!("expected region for param #{} in {:?}", i, self))
}
#[inline]
#[track_caller]
pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
- if let GenericArgKind::Const(ct) = self[i].unpack() {
- ct
- } else {
- bug!("expected const for param #{} in {:?}", i, self);
- }
+ self[i].as_const().unwrap_or_else(|| bug!("expected const for param #{} in {:?}", i, self))
}
#[inline]
@@ -635,6 +612,12 @@ where
) -> SubstIter<'s, 'tcx, I> {
SubstIter { it: self.0.into_iter(), tcx, substs }
}
+
+ /// Similar to [`subst_identity`](EarlyBinder::subst_identity),
+ /// but on an iterator of `TypeFoldable` values.
+ pub fn subst_identity_iter(self) -> I::IntoIter {
+ self.0.into_iter()
+ }
}
pub struct SubstIter<'s, 'tcx, I: IntoIterator> {
@@ -687,6 +670,12 @@ where
) -> SubstIterCopied<'s, 'tcx, I> {
SubstIterCopied { it: self.0.into_iter(), tcx, substs }
}
+
+ /// Similar to [`subst_identity`](EarlyBinder::subst_identity),
+ /// but on an iterator of values that deref to a `TypeFoldable`.
+ pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> {
+ self.0.into_iter().map(|v| *v)
+ }
}
pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> {
@@ -772,7 +761,7 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
/// Returns the inner value, but only if it contains no bound vars.
pub fn no_bound_vars(self) -> Option<T> {
- if !self.0.needs_subst() { Some(self.0) } else { None }
+ if !self.0.has_param() { Some(self.0) } else { None }
}
}
@@ -840,12 +829,18 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> {
None => region_param_out_of_range(data, self.substs),
}
}
- _ => r,
+ ty::ReLateBound(..)
+ | ty::ReFree(_)
+ | ty::ReStatic
+ | ty::RePlaceholder(_)
+ | ty::ReErased
+ | ty::ReError(_) => r,
+ ty::ReVar(_) => bug!("unexpected region: {r:?}"),
}
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if !t.needs_subst() {
+ if !t.has_param() {
return t;
}
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 6747da7ab..e61037e5e 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -139,40 +139,6 @@ impl<'tcx> TyCtxt<'tcx> {
treat_projections: TreatProjections,
mut f: impl FnMut(DefId),
) {
- let _: Option<()> =
- self.find_map_relevant_impl(trait_def_id, self_ty, treat_projections, |did| {
- f(did);
- None
- });
- }
-
- /// `trait_def_id` MUST BE the `DefId` of a trait.
- pub fn non_blanket_impls_for_ty(
- self,
- trait_def_id: DefId,
- self_ty: Ty<'tcx>,
- ) -> impl Iterator<Item = DefId> + 'tcx {
- let impls = self.trait_impls_of(trait_def_id);
- if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
- if let Some(impls) = impls.non_blanket_impls.get(&simp) {
- return impls.iter().copied();
- }
- }
-
- [].iter().copied()
- }
-
- /// Applies function to every impl that could possibly match the self type `self_ty` and returns
- /// the first non-none value.
- ///
- /// `trait_def_id` MUST BE the `DefId` of a trait.
- pub fn find_map_relevant_impl<T>(
- self,
- trait_def_id: DefId,
- self_ty: Ty<'tcx>,
- treat_projections: TreatProjections,
- mut f: impl FnMut(DefId) -> Option<T>,
- ) -> Option<T> {
// FIXME: This depends on the set of all impls for the trait. That is
// unfortunate wrt. incremental compilation.
//
@@ -181,9 +147,7 @@ impl<'tcx> TyCtxt<'tcx> {
let impls = self.trait_impls_of(trait_def_id);
for &impl_def_id in impls.blanket_impls.iter() {
- if let result @ Some(_) = f(impl_def_id) {
- return result;
- }
+ f(impl_def_id);
}
// Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using
@@ -199,20 +163,30 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
- if let result @ Some(_) = f(impl_def_id) {
- return result;
- }
+ f(impl_def_id);
}
}
} else {
for &impl_def_id in impls.non_blanket_impls.values().flatten() {
- if let result @ Some(_) = f(impl_def_id) {
- return result;
- }
+ f(impl_def_id);
}
}
+ }
- None
+ /// `trait_def_id` MUST BE the `DefId` of a trait.
+ pub fn non_blanket_impls_for_ty(
+ self,
+ trait_def_id: DefId,
+ self_ty: Ty<'tcx>,
+ ) -> impl Iterator<Item = DefId> + 'tcx {
+ let impls = self.trait_impls_of(trait_def_id);
+ if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::AsCandidateKey) {
+ if let Some(impls) = impls.non_blanket_impls.get(&simp) {
+ return impls.iter().copied();
+ }
+ }
+
+ [].iter().copied()
}
/// Returns an iterator containing all impls for `trait_def_id`.
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 47943b94c..e04dbbff9 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -20,7 +20,7 @@ use rustc_hir::{
hir_id::OwnerId,
HirId, ItemLocalId, ItemLocalMap, ItemLocalSet,
};
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_middle::mir::FakeReadCause;
use rustc_session::Session;
@@ -151,10 +151,14 @@ pub struct TypeckResults<'tcx> {
/// this field will be set to `Some(ErrorGuaranteed)`.
pub tainted_by_errors: Option<ErrorGuaranteed>,
- /// All the opaque types that have hidden types set
- /// by this function. We also store the
- /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
- /// even if they are only set in dead code (which doesn't show up in MIR).
+ /// All the opaque types that have hidden types set by this function.
+ /// We also store the type here, so that the compiler can use it as a hint
+ /// for figuring out hidden types, even if they are only set in dead code
+ /// (which doesn't show up in MIR).
+ ///
+ /// These types are mapped back to the opaque's identity substitutions
+ /// (with erased regions), which is why we don't associated substs with any
+ /// of these usages.
pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure;
@@ -208,6 +212,9 @@ pub struct TypeckResults<'tcx> {
/// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
/// on closure size.
pub closure_size_eval: FxHashMap<LocalDefId, ClosureSizeProfileData<'tcx>>,
+
+ /// Container types and field indices of `offset_of!` expressions
+ offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<FieldIdx>)>,
}
/// Whenever a value may be live across a generator yield, the type of that value winds up in the
@@ -280,6 +287,7 @@ impl<'tcx> TypeckResults<'tcx> {
generator_interior_predicates: Default::default(),
treat_byte_string_as_slice: Default::default(),
closure_size_eval: Default::default(),
+ offset_of_data: Default::default(),
}
}
@@ -530,6 +538,14 @@ impl<'tcx> TypeckResults<'tcx> {
pub fn coercion_casts(&self) -> &ItemLocalSet {
&self.coercion_casts
}
+
+ pub fn offset_of_data(&self) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
+ LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
+ }
+
+ pub fn offset_of_data_mut(&mut self) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<FieldIdx>)> {
+ LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
+ }
}
/// Validate that the given HirId (respectively its `local_id` part) can be
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index c8a78ec03..ba0513563 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,7 +2,7 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir;
-use crate::ty::fast_reject::TreatProjections;
+use crate::query::Providers;
use crate::ty::layout::IntegerExt;
use crate::ty::{
self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -11,13 +11,13 @@ use crate::ty::{
use crate::ty::{GenericArgKind, SubstsRef};
use rustc_apfloat::Float as _;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_index::bit_set::GrowableBitSet;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_session::Limit;
use rustc_span::sym;
@@ -35,9 +35,14 @@ pub struct Discr<'tcx> {
/// Used as an input to [`TyCtxt::uses_unique_generic_params`].
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum IgnoreRegions {
- Yes,
+pub enum CheckRegions {
No,
+ /// Only permit early bound regions. This is useful for Adts which
+ /// can never have late bound regions.
+ OnlyEarlyBound,
+ /// Permit both late bound and early bound regions. Use this for functions,
+ /// which frequently have late bound regions.
+ Bound,
}
#[derive(Copy, Clone, Debug)]
@@ -124,7 +129,7 @@ impl IntTypeExt for IntegerType {
impl<'tcx> TyCtxt<'tcx> {
/// Creates a hash of the type `Ty` which will be the same no matter what crate
/// context it's calculated within. This is used by the `type_id` intrinsic.
- pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
+ pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash64 {
// We want the type_id be independent of the types free regions, so we
// erase them. The erase_regions() call will also anonymize bound
// regions, which is desirable too.
@@ -359,21 +364,29 @@ impl<'tcx> TyCtxt<'tcx> {
self.ensure().coherent_trait(drop_trait);
let ty = self.type_of(adt_did).subst_identity();
- let (did, constness) = self.find_map_relevant_impl(
- drop_trait,
- ty,
- // FIXME: This could also be some other mode, like "unexpected"
- TreatProjections::ForLookup,
- |impl_did| {
- if let Some(item_id) = self.associated_item_def_ids(impl_did).first() {
- if validate(self, impl_did).is_ok() {
- return Some((*item_id, self.constness(impl_did)));
- }
- }
- None
- },
- )?;
+ let mut dtor_candidate = None;
+ self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
+ if validate(self, impl_did).is_err() {
+ // Already `ErrorGuaranteed`, no need to delay a span bug here.
+ return;
+ }
+ let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
+ self.sess.delay_span_bug(self.def_span(impl_did), "Drop impl without drop function");
+ return;
+ };
+
+ if let Some((old_item_id, _)) = dtor_candidate {
+ self.sess
+ .struct_span_err(self.def_span(item_id), "multiple drop impls found")
+ .span_note(self.def_span(old_item_id), "other impl here")
+ .delay_as_bug();
+ }
+
+ dtor_candidate = Some((*item_id, self.constness(impl_did)));
+ });
+
+ let (did, constness) = dtor_candidate?;
Some(ty::Destructor { did, constness })
}
@@ -461,21 +474,28 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn uses_unique_generic_params(
self,
substs: SubstsRef<'tcx>,
- ignore_regions: IgnoreRegions,
+ ignore_regions: CheckRegions,
) -> Result<(), NotUniqueParam<'tcx>> {
let mut seen = GrowableBitSet::default();
+ let mut seen_late = FxHashSet::default();
for arg in substs {
match arg.unpack() {
- GenericArgKind::Lifetime(lt) => {
- if ignore_regions == IgnoreRegions::No {
- let ty::ReEarlyBound(p) = lt.kind() else {
- return Err(NotUniqueParam::NotParam(lt.into()))
- };
+ GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) {
+ (CheckRegions::Bound, ty::ReLateBound(di, reg)) => {
+ if !seen_late.insert((di, reg)) {
+ return Err(NotUniqueParam::DuplicateParam(lt.into()));
+ }
+ }
+ (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, ty::ReEarlyBound(p)) => {
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(lt.into()));
}
}
- }
+ (CheckRegions::OnlyEarlyBound | CheckRegions::Bound, _) => {
+ return Err(NotUniqueParam::NotParam(lt.into()));
+ }
+ (CheckRegions::No, _) => {}
+ },
GenericArgKind::Type(t) => match t.kind() {
ty::Param(p) => {
if !seen.insert(p.index) {
@@ -498,6 +518,42 @@ impl<'tcx> TyCtxt<'tcx> {
Ok(())
}
+ /// Checks whether each generic argument is simply a unique generic placeholder.
+ ///
+ /// This is used in the new solver, which canonicalizes params to placeholders
+ /// for better caching.
+ pub fn uses_unique_placeholders_ignoring_regions(
+ self,
+ substs: SubstsRef<'tcx>,
+ ) -> Result<(), NotUniqueParam<'tcx>> {
+ let mut seen = GrowableBitSet::default();
+ for arg in substs {
+ match arg.unpack() {
+ // Ignore regions, since we can't resolve those in a canonicalized
+ // query in the trait solver.
+ GenericArgKind::Lifetime(_) => {}
+ GenericArgKind::Type(t) => match t.kind() {
+ ty::Placeholder(p) => {
+ if !seen.insert(p.bound.var) {
+ return Err(NotUniqueParam::DuplicateParam(t.into()));
+ }
+ }
+ _ => return Err(NotUniqueParam::NotParam(t.into())),
+ },
+ GenericArgKind::Const(c) => match c.kind() {
+ ty::ConstKind::Placeholder(p) => {
+ if !seen.insert(p.bound) {
+ return Err(NotUniqueParam::DuplicateParam(c.into()));
+ }
+ }
+ _ => return Err(NotUniqueParam::NotParam(c.into())),
+ },
+ }
+ }
+
+ Ok(())
+ }
+
/// Returns `true` if `def_id` refers to a closure (e.g., `|x| x * 2`). Note
/// that closures have a `DefId`, but the closure *expression* also
/// has a `HirId` that is located within the context where the
@@ -642,16 +698,16 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- /// Return the set of types that should be taken into accound when checking
+ /// Return the set of types that should be taken into account when checking
/// trait bounds on a generator's internal state.
pub fn generator_hidden_types(
self,
def_id: DefId,
) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
- let generator_layout = &self.mir_generator_witnesses(def_id);
+ let generator_layout = self.mir_generator_witnesses(def_id);
generator_layout
- .field_tys
- .iter()
+ .as_ref()
+ .map_or_else(|| [].iter(), |l| l.field_tys.iter())
.filter(|decl| !decl.ignore_for_traits)
.map(|decl| ty::EarlyBinder(decl.ty))
}
@@ -694,20 +750,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}
- pub fn bound_return_position_impl_trait_in_trait_tys(
- self,
- def_id: DefId,
- ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> {
- ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id))
- }
-
- pub fn bound_explicit_item_bounds(
- self,
- def_id: DefId,
- ) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> {
- ty::EarlyBinder(self.explicit_item_bounds(def_id))
- }
-
/// Returns names of captured upvars for closures and generators.
///
/// Here are some examples:
@@ -1158,7 +1200,7 @@ impl<'tcx> Ty<'tcx> {
// context, or *something* like that, but for now just avoid passing inference
// variables to queries that can't cope with them. Instead, conservatively
// return "true" (may change drop order).
- if query_ty.needs_infer() {
+ if query_ty.has_infer() {
return true;
}
@@ -1260,7 +1302,7 @@ pub enum ExplicitSelf<'tcx> {
impl<'tcx> ExplicitSelf<'tcx> {
/// Categorizes an explicit self declaration like `self: SomeType`
- /// into either `self`, `&self`, `&mut self`, `Box<self>`, or
+ /// into either `self`, `&self`, `&mut self`, `Box<Self>`, or
/// `Other`.
/// This is mainly used to require the arbitrary_self_types feature
/// in the case of `Other`, to improve error messages in the common cases,
@@ -1402,7 +1444,7 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool {
}
/// Does the equivalent of
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
/// let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
/// folder.tcx().intern_*(&v)
/// ```
@@ -1479,8 +1521,8 @@ pub fn is_intrinsic(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic | Abi::PlatformIntrinsic)
}
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers = ty::query::Providers {
+pub fn provide(providers: &mut Providers) {
+ *providers = Providers {
reveal_opaque_types_in_bounds,
is_doc_hidden,
is_doc_notable_trait,
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 08a62c900..520bb55e0 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -33,6 +33,14 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
}
fn has_type_flags(&self, flags: TypeFlags) -> bool {
+ // N.B. Even though this uses a visitor, the visitor does not actually
+ // recurse through the whole `TypeVisitable` implementor type.
+ //
+ // Instead it stops on the first "level", visiting types, regions,
+ // consts and predicates just fetches their type flags.
+ //
+ // Thus this is a lot faster than it might seem and should be
+ // optimized to a simple field access.
let res =
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags);
trace!(?self, ?flags, ?res, "has_type_flags");
@@ -41,6 +49,9 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
fn has_projections(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PROJECTION)
}
+ fn has_inherent_projections(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_TY_INHERENT)
+ }
fn has_opaque_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
}
@@ -62,7 +73,7 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
}
}
fn has_non_region_param(&self) -> bool {
- self.has_type_flags(TypeFlags::NEEDS_SUBST - TypeFlags::HAS_RE_PARAM)
+ self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM)
}
fn has_infer_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_INFER)
@@ -71,10 +82,10 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
fn has_non_region_infer(&self) -> bool {
- self.has_type_flags(TypeFlags::NEEDS_INFER - TypeFlags::HAS_RE_INFER)
+ self.has_type_flags(TypeFlags::HAS_INFER - TypeFlags::HAS_RE_INFER)
}
- fn needs_infer(&self) -> bool {
- self.has_type_flags(TypeFlags::NEEDS_INFER)
+ fn has_infer(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_INFER)
}
fn has_placeholders(&self) -> bool {
self.has_type_flags(
@@ -86,8 +97,8 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
fn has_non_region_placeholders(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER)
}
- fn needs_subst(&self) -> bool {
- self.has_type_flags(TypeFlags::NEEDS_SUBST)
+ fn has_param(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_PARAM)
}
/// "Free" regions in this context means that it has any region
/// that is not (a) erased or (b) late-bound.
@@ -364,7 +375,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
_ => (),
};
- r.super_visit_with(self)
+ ControlFlow::Continue(())
}
}
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index 182945b9c..04a635a68 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -194,7 +194,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
| ty::FnDef(_, substs) => {
stack.extend(substs.iter().rev());
}
- ty::Tuple(ts) => stack.extend(ts.as_substs().iter().rev()),
+ ty::Tuple(ts) => stack.extend(ts.iter().rev().map(GenericArg::from)),
ty::GeneratorWitness(ts) => {
stack.extend(ts.skip_binder().iter().rev().map(|ty| ty.into()));
}