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.rs2
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs6
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs2
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs2
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs2
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs35
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs285
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs9
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs204
-rw-r--r--compiler/rustc_middle/src/ty/context.rs622
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs65
-rw-r--r--compiler/rustc_middle/src/ty/error.rs14
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs22
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs29
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs26
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs19
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs12
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs200
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs333
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs12
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs189
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs83
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs142
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs573
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs61
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs10
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs6
-rw-r--r--compiler/rustc_middle/src/ty/util.rs150
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs2
33 files changed, 1729 insertions, 1396 deletions
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index cbc68fde9..09517200b 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -81,7 +81,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
Err(TypeError::Sorts(relate::expected_found(self, a, b)))
}
- (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(self.tcx().ty_error(guar)),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.tcx(), guar)),
_ => relate::structurally_relate_tys(self, a, b),
}
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index a39631da9..ffee7ba28 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -53,7 +53,7 @@ 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.thir_abstract_const(uv.def) {
- Err(e) => self.tcx.const_error(c.ty(), e),
+ Err(e) => ty::Const::new_error(self.tcx, e, c.ty()),
Ok(Some(bac)) => {
let substs = self.tcx.erase_regions(uv.substs);
let bac = bac.subst(self.tcx, substs);
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index cd0f7e8da..76931ceaa 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -6,7 +6,7 @@ use rustc_span::Span;
use rustc_target::abi::FieldIdx;
#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
-pub enum PointerCast {
+pub enum PointerCoercion {
/// Go from a fn-item type to a fn-pointer type.
ReifyFnPointer,
@@ -99,7 +99,7 @@ pub enum Adjust<'tcx> {
/// Take the address and produce either a `&` or `*` pointer.
Borrow(AutoBorrow<'tcx>),
- Pointer(PointerCast),
+ Pointer(PointerCoercion),
/// Cast into a dyn* object.
DynStar,
@@ -132,7 +132,7 @@ impl<'tcx> OverloadedDeref<'tcx> {
.find(|m| m.kind == ty::AssocKind::Fn)
.unwrap()
.def_id;
- tcx.mk_fn_def(method_def_id, [source])
+ Ty::new_fn_def(tcx, method_def_id, [source])
}
}
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 7c5c030c2..e067d2a98 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -573,7 +573,7 @@ impl<'tcx> AdtDef<'tcx> {
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
- ty::EarlyBinder(tcx.adt_sized_constraint(self.did()))
+ ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did()))
}
}
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 090b76932..cce609c26 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -48,7 +48,7 @@ impl AssocItem {
///
/// [`type_of`]: crate::ty::TyCtxt::type_of
pub fn defaultness(&self, tcx: TyCtxt<'_>) -> hir::Defaultness {
- tcx.impl_defaultness(self.def_id)
+ tcx.defaultness(self.def_id)
}
#[inline]
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index be7b2b7ec..bc9273745 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -427,6 +427,8 @@ pub enum BorrowKind {
/// immutable, but not aliasable. This solves the problem. For
/// simplicity, we don't give users the way to express this
/// borrow, it's just used when translating closures.
+ ///
+ /// FIXME: Rename this to indicate the borrow is actually not immutable.
UniqueImmBorrow,
/// Data is mutable and not aliasable.
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 7fc75674d..6adbb44a1 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -128,6 +128,12 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx>
}
}
+impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Clause<'tcx> {
+ fn encode(&self, e: &mut E) {
+ self.as_predicate().encode(e);
+ }
+}
+
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> {
fn encode(&self, e: &mut E) {
self.kind().encode(e);
@@ -241,6 +247,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx>
}
}
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> {
+ fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
+ let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
+ pred.expect_clause()
+ }
+}
+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for SubstsRef<'tcx> {
fn decode(decoder: &mut D) -> Self {
let len = decoder.read_usize();
@@ -264,7 +277,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> {
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Region<'tcx> {
fn decode(decoder: &mut D) -> Self {
- decoder.interner().mk_region_from_kind(Decodable::decode(decoder))
+ ty::Region::new_from_kind(decoder.interner(), Decodable::decode(decoder))
}
}
@@ -331,7 +344,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> {
fn decode(decoder: &mut D) -> Self {
let consts: ty::ConstData<'tcx> = Decodable::decode(decoder);
- decoder.interner().mk_const(consts.kind, consts.ty)
+ decoder.interner().mk_ct_from_kind(consts.kind, consts.ty)
}
}
@@ -355,16 +368,6 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> {
}
}
-impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
- for [(ty::Predicate<'tcx>, Span)]
-{
- fn decode(decoder: &mut D) -> &'tcx Self {
- decoder.interner().arena.alloc_from_iter(
- (0..decoder.read_usize()).map(|_| Decodable::decode(decoder)).collect::<Vec<_>>(),
- )
- }
-}
-
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
fn decode(decoder: &mut D) -> &'tcx Self {
decoder.interner().arena.alloc_from_iter(
@@ -393,11 +396,11 @@ 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<ty::Predicate<'tcx>> {
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Clause<'tcx>> {
fn decode(decoder: &mut D) -> &'tcx Self {
let len = decoder.read_usize();
- decoder.interner().mk_predicates_from_iter(
- (0..len).map::<ty::Predicate<'tcx>, _>(|_| Decodable::decode(decoder)),
+ decoder.interner().mk_clauses_from_iter(
+ (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)),
)
}
}
@@ -421,7 +424,7 @@ impl_decodable_via_ref! {
&'tcx mir::BorrowCheckResult<'tcx>,
&'tcx mir::coverage::CodeRegion,
&'tcx ty::List<ty::BoundVariableKind>,
- &'tcx ty::List<ty::Predicate<'tcx>>,
+ &'tcx ty::List<ty::Clause<'tcx>>,
&'tcx ty::List<FieldIdx>,
}
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 1a4bd1481..1cbfe99f8 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,7 +1,8 @@
use crate::middle::resolve_bound_vars as rbv;
-use crate::mir::interpret::LitToConstInput;
-use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use crate::mir::interpret::{AllocId, ConstValue, LitToConstInput, Scalar};
+use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use rustc_data_structures::intern::Interned;
+use rustc_error_messages::MultiSpan;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::LocalDefId;
@@ -13,8 +14,13 @@ mod valtree;
pub use int::*;
pub use kind::*;
+use rustc_span::ErrorGuaranteed;
+use rustc_span::DUMMY_SP;
+use rustc_target::abi::Size;
pub use valtree::*;
+use super::sty::ConstKind;
+
/// Use this rather than `ConstData`, whenever possible.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
#[rustc_pass_by_value]
@@ -30,6 +36,16 @@ pub struct ConstData<'tcx> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ConstData<'_>, 40);
+enum EvalMode {
+ Typeck,
+ Mir,
+}
+
+enum EvalResult<'tcx> {
+ ValTree(ty::ValTree<'tcx>),
+ ConstVal(ConstValue<'tcx>),
+}
+
impl<'tcx> Const<'tcx> {
#[inline]
pub fn ty(self) -> Ty<'tcx> {
@@ -38,7 +54,98 @@ impl<'tcx> Const<'tcx> {
#[inline]
pub fn kind(self) -> ConstKind<'tcx> {
- self.0.kind
+ self.0.kind.clone()
+ }
+
+ #[inline]
+ pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ tcx.mk_ct_from_kind(kind, ty)
+ }
+
+ #[inline]
+ pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Param(param), ty)
+ }
+
+ #[inline]
+ pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty)
+ }
+
+ #[inline]
+ pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty)
+ }
+
+ #[inline]
+ pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Infer(infer), ty)
+ }
+
+ #[inline]
+ pub fn new_bound(
+ tcx: TyCtxt<'tcx>,
+ debruijn: ty::DebruijnIndex,
+ var: ty::BoundVar,
+ ty: Ty<'tcx>,
+ ) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty)
+ }
+
+ #[inline]
+ pub fn new_placeholder(
+ tcx: TyCtxt<'tcx>,
+ placeholder: ty::PlaceholderConst<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty)
+ }
+
+ #[inline]
+ pub fn new_unevaluated(
+ tcx: TyCtxt<'tcx>,
+ uv: ty::UnevaluatedConst<'tcx>,
+ ty: Ty<'tcx>,
+ ) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty)
+ }
+
+ #[inline]
+ pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Value(val), ty)
+ }
+
+ #[inline]
+ pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Expr(expr), ty)
+ }
+
+ #[inline]
+ pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new(tcx, ty::ConstKind::Error(e), ty)
+ }
+
+ /// Like [Ty::new_error] but for constants.
+ #[track_caller]
+ pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ Const::new_error_with_message(
+ tcx,
+ ty,
+ DUMMY_SP,
+ "ty::ConstKind::Error constructed but no error reported",
+ )
+ }
+
+ /// Like [Ty::new_error_with_message] but for constants.
+ #[track_caller]
+ pub fn new_error_with_message<S: Into<MultiSpan>>(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ span: S,
+ msg: &'static str,
+ ) -> Const<'tcx> {
+ let reported = tcx.sess.delay_span_bug(span, msg);
+ Const::new_error(tcx, reported, ty)
}
/// Literals and const generic parameters are eagerly converted to a constant, everything else
@@ -60,7 +167,8 @@ impl<'tcx> Const<'tcx> {
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
- None => tcx.mk_const(
+ None => ty::Const::new_unevaluated(
+ tcx,
ty::UnevaluatedConst {
def: def.to_def_id(),
substs: InternalSubsts::identity_for_item(tcx, def.to_def_id()),
@@ -126,13 +234,19 @@ impl<'tcx> Const<'tcx> {
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
- Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
+ Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty))
+ }
+ Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
+ Some(ty::Const::new_bound(
+ tcx,
+ debruijn,
+ ty::BoundVar::from_u32(index),
+ param_ty,
+ ))
+ }
+ Some(rbv::ResolvedArg::Error(guar)) => {
+ Some(ty::Const::new_error(tcx, guar, param_ty))
}
- Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
- ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
- param_ty,
- )),
- Some(rbv::ResolvedArg::Error(guar)) => Some(tcx.const_error(param_ty, guar)),
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
}
}
@@ -155,7 +269,8 @@ impl<'tcx> Const<'tcx> {
.layout_of(ty)
.unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
.size;
- tcx.mk_const(
+ ty::Const::new_value(
+ tcx,
ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()),
ty.value,
)
@@ -164,7 +279,7 @@ impl<'tcx> Const<'tcx> {
#[inline]
/// Creates an interned zst constant.
pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
- tcx.mk_const(ty::ValTree::zst(), ty)
+ ty::Const::new_value(tcx, ty::ValTree::zst(), ty)
}
#[inline]
@@ -192,12 +307,12 @@ impl<'tcx> Const<'tcx> {
assert_eq!(self.ty(), ty);
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
// if `ty` does not depend on generic parameters, use an empty param_env
- self.kind().eval(tcx, param_env).try_to_bits(size)
+ self.eval(tcx, param_env).try_to_bits(size)
}
#[inline]
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
- self.kind().eval(tcx, param_env).try_to_bool()
+ self.eval(tcx, param_env).try_to_bool()
}
#[inline]
@@ -206,17 +321,17 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
) -> Option<u64> {
- self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
+ self.eval(tcx, param_env).try_to_target_usize(tcx)
}
#[inline]
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
/// unevaluated constant.
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
- if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
+ if let Some(val) = self.try_eval_for_typeck(tcx, param_env) {
match val {
- Ok(val) => tcx.mk_const(val, self.ty()),
- Err(guar) => tcx.const_error(self.ty(), guar),
+ Ok(val) => ty::Const::new_value(tcx, val, self.ty()),
+ Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
}
} else {
// Either the constant isn't evaluatable or ValTree creation failed.
@@ -238,6 +353,138 @@ impl<'tcx> Const<'tcx> {
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
}
+ #[inline]
+ /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
+ /// return `None`.
+ // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
+ pub fn try_eval_for_mir(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
+ match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
+ Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
+ Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
+ Some(Err(e)) => Some(Err(e)),
+ None => None,
+ }
+ }
+
+ #[inline]
+ /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
+ /// return `None`.
+ // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
+ pub fn try_eval_for_typeck(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
+ match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
+ Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
+ Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
+ Some(Err(e)) => Some(Err(e)),
+ None => None,
+ }
+ }
+
+ #[inline]
+ fn try_eval_inner(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ eval_mode: EvalMode,
+ ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
+ assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
+ if let ConstKind::Unevaluated(unevaluated) = self.kind() {
+ use crate::mir::interpret::ErrorHandled;
+
+ // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
+ // also does later, but we want to do it before checking for
+ // inference variables.
+ // Note that we erase regions *before* calling `with_reveal_all_normalized`,
+ // so that we don't try to invoke this query with
+ // any region variables.
+
+ // HACK(eddyb) when the query key would contain inference variables,
+ // attempt using identity substs and `ParamEnv` instead, that will succeed
+ // when the expression doesn't depend on any parameters.
+ // 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).and(ty::UnevaluatedConst {
+ def: unevaluated.def,
+ substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
+ })
+ } else {
+ tcx.erase_regions(param_env)
+ .with_reveal_all_normalized(tcx)
+ .and(tcx.erase_regions(unevaluated))
+ };
+
+ // FIXME(eddyb) maybe the `const_eval_*` methods should take
+ // `ty::ParamEnvAnd` instead of having them separate.
+ let (param_env, unevaluated) = param_env_and.into_parts();
+ // try to resolve e.g. associated constants to their definition on an impl, and then
+ // evaluate the const.
+ match eval_mode {
+ EvalMode::Typeck => {
+ match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
+ // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+ // and we use the original type, so nothing from `substs`
+ // (which may be identity substs, see above),
+ // 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.into())),
+ }
+ }
+ EvalMode::Mir => {
+ match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
+ // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+ // and we use the original type, so nothing from `substs`
+ // (which may be identity substs, see above),
+ // 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.into())),
+ }
+ }
+ }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
+ if let ConstKind::Value(val) = self.kind() { Some(val) } else { None }
+ }
+
+ #[inline]
+ pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
+ self.try_to_value()?.try_to_scalar()
+ }
+
+ #[inline]
+ pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
+ self.try_to_value()?.try_to_scalar_int()
+ }
+
+ #[inline]
+ pub fn try_to_bits(self, size: Size) -> Option<u128> {
+ self.try_to_scalar_int()?.to_bits(size).ok()
+ }
+
+ #[inline]
+ pub fn try_to_bool(self) -> Option<bool> {
+ self.try_to_scalar_int()?.try_into().ok()
+ }
+
+ #[inline]
+ pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+ self.try_to_value()?.try_to_target_usize(tcx)
+ }
+
pub fn is_ct_infer(self) -> bool {
matches!(self.kind(), ty::ConstKind::Infer(_))
}
@@ -254,5 +501,5 @@ pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBind
"`const_param_default` expected a generic parameter with a constant"
),
};
- ty::EarlyBinder(Const::from_anon_const(tcx, default_def_id))
+ ty::EarlyBinder::bind(Const::from_anon_const(tcx, default_def_id))
}
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index d1dbc531e..1e43fab45 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -1,5 +1,6 @@
use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_target::abi::Size;
use std::fmt;
@@ -113,6 +114,14 @@ impl std::fmt::Debug for ConstInt {
}
}
+impl IntoDiagnosticArg for ConstInt {
+ // FIXME this simply uses the Debug impl, but we could probably do better by converting both
+ // to an inherent method that returns `Cow`.
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(format!("{self:?}").into())
+ }
+}
+
/// The raw bytes of a simple value.
///
/// This is a packed struct in order to allow this type to be optimally embedded in enums
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 1dd4f8a24..a6bf74911 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,17 +1,11 @@
use super::Const;
use crate::mir;
-use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::ty::abstract_const::CastKind;
-use crate::ty::subst::{InternalSubsts, SubstsRef};
-use crate::ty::ParamEnv;
-use crate::ty::{self, List, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::subst::SubstsRef;
+use crate::ty::{self, List, Ty};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
-use rustc_target::abi::Size;
-
-use super::ScalarInt;
/// An unevaluated (potentially generic) constant used in the type-system.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
@@ -41,45 +35,6 @@ impl<'tcx> UnevaluatedConst<'tcx> {
}
}
-/// Represents a constant in Rust.
-#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
-#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
-#[derive(derive_more::From)]
-pub enum ConstKind<'tcx> {
- /// A const generic parameter.
- Param(ty::ParamConst),
-
- /// Infer the value of the const.
- Infer(InferConst<'tcx>),
-
- /// Bound const variable, used only when preparing a trait query.
- Bound(ty::DebruijnIndex, ty::BoundVar),
-
- /// A placeholder const - universally quantified higher-ranked const.
- Placeholder(ty::PlaceholderConst<'tcx>),
-
- /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
- /// variants when the code is monomorphic enough for that.
- Unevaluated(UnevaluatedConst<'tcx>),
-
- /// Used to hold computed value.
- Value(ty::ValTree<'tcx>),
-
- /// A placeholder for a const which could not be computed; this is
- /// propagated to avoid useless error messages.
- #[from(ignore)]
- Error(ErrorGuaranteed),
-
- /// Expr which contains an expression which has partially evaluated items.
- Expr(Expr<'tcx>),
-}
-
-impl<'tcx> From<ty::ConstVid<'tcx>> for ConstKind<'tcx> {
- fn from(const_vid: ty::ConstVid<'tcx>) -> Self {
- InferConst::Var(const_vid).into()
- }
-}
-
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
pub enum Expr<'tcx> {
@@ -93,39 +48,7 @@ pub enum Expr<'tcx> {
static_assert_size!(Expr<'_>, 24);
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(ConstKind<'_>, 32);
-
-impl<'tcx> ConstKind<'tcx> {
- #[inline]
- pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
- if let ConstKind::Value(val) = self { Some(val) } else { None }
- }
-
- #[inline]
- pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
- self.try_to_value()?.try_to_scalar()
- }
-
- #[inline]
- pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
- self.try_to_value()?.try_to_scalar_int()
- }
-
- #[inline]
- pub fn try_to_bits(self, size: Size) -> Option<u128> {
- self.try_to_scalar_int()?.to_bits(size).ok()
- }
-
- #[inline]
- pub fn try_to_bool(self) -> Option<bool> {
- self.try_to_scalar_int()?.try_into().ok()
- }
-
- #[inline]
- pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
- self.try_to_value()?.try_to_target_usize(tcx)
- }
-}
+static_assert_size!(super::ConstKind<'_>, 32);
/// An inference variable for a const, for use in const generics.
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
@@ -144,124 +67,3 @@ impl<CTX> HashStable<CTX> for InferConst<'_> {
}
}
}
-
-enum EvalMode {
- Typeck,
- Mir,
-}
-
-enum EvalResult<'tcx> {
- ValTree(ty::ValTree<'tcx>),
- ConstVal(ConstValue<'tcx>),
-}
-
-impl<'tcx> ConstKind<'tcx> {
- #[inline]
- /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
- /// unevaluated constant.
- pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
- self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
- }
-
- #[inline]
- /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
- /// return `None`.
- // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
- pub fn try_eval_for_mir(
- self,
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
- match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
- Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
- Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
- Some(Err(e)) => Some(Err(e)),
- None => None,
- }
- }
-
- #[inline]
- /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
- /// return `None`.
- // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
- pub fn try_eval_for_typeck(
- self,
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
- match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
- Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
- Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
- Some(Err(e)) => Some(Err(e)),
- None => None,
- }
- }
-
- #[inline]
- fn try_eval_inner(
- self,
- tcx: TyCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- eval_mode: EvalMode,
- ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
- assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
- if let ConstKind::Unevaluated(unevaluated) = self {
- use crate::mir::interpret::ErrorHandled;
-
- // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
- // also does later, but we want to do it before checking for
- // inference variables.
- // Note that we erase regions *before* calling `with_reveal_all_normalized`,
- // so that we don't try to invoke this query with
- // any region variables.
-
- // HACK(eddyb) when the query key would contain inference variables,
- // attempt using identity substs and `ParamEnv` instead, that will succeed
- // when the expression doesn't depend on any parameters.
- // 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).and(ty::UnevaluatedConst {
- def: unevaluated.def,
- substs: InternalSubsts::identity_for_item(tcx, unevaluated.def),
- })
- } else {
- tcx.erase_regions(param_env)
- .with_reveal_all_normalized(tcx)
- .and(tcx.erase_regions(unevaluated))
- };
-
- // FIXME(eddyb) maybe the `const_eval_*` methods should take
- // `ty::ParamEnvAnd` instead of having them separate.
- let (param_env, unevaluated) = param_env_and.into_parts();
- // try to resolve e.g. associated constants to their definition on an impl, and then
- // evaluate the const.
- match eval_mode {
- EvalMode::Typeck => {
- match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
- // NOTE(eddyb) `val` contains no lifetimes/types/consts,
- // and we use the original type, so nothing from `substs`
- // (which may be identity substs, see above),
- // 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.into())),
- }
- }
- EvalMode::Mir => {
- match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
- // NOTE(eddyb) `val` contains no lifetimes/types/consts,
- // and we use the original type, so nothing from `substs`
- // (which may be identity substs, see above),
- // 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.into())),
- }
- }
- }
- } else {
- None
- }
- }
-}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 2bde55bc4..035e978f6 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -25,10 +25,10 @@ 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, UintTy, Visibility,
+ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Const, ConstData, GenericParamDefKind,
+ ImplPolarity, InferTy, List, ParamConst, ParamTy, PolyExistentialPredicate, PolyFnSig,
+ Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind,
+ TyVid, TypeAndMut, Visibility,
};
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_ast::{self as ast, attr};
@@ -70,10 +70,9 @@ use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}
use rustc_target::spec::abi;
use rustc_type_ir::sty::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
-use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags};
+use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
use std::any::Any;
-use std::assert_matches::debug_assert_matches;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt;
@@ -82,8 +81,6 @@ use std::iter;
use std::mem;
use std::ops::{Bound, Deref};
-const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
-
#[allow(rustc::usage_of_ty_tykind)]
impl<'tcx> Interner for TyCtxt<'tcx> {
type AdtDef = ty::AdtDef<'tcx>;
@@ -110,11 +107,29 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type PredicateKind = ty::PredicateKind<'tcx>;
type AllocId = crate::mir::interpret::AllocId;
+ type InferConst = ty::InferConst<'tcx>;
+ type AliasConst = ty::UnevaluatedConst<'tcx>;
+ type ParamConst = ty::ParamConst;
+ type BoundConst = ty::BoundVar;
+ type PlaceholderConst = ty::PlaceholderConst<'tcx>;
+ type ValueConst = ty::ValTree<'tcx>;
+ type ExprConst = ty::Expr<'tcx>;
+
type EarlyBoundRegion = ty::EarlyBoundRegion;
type BoundRegion = ty::BoundRegion;
type FreeRegion = ty::FreeRegion;
type RegionVid = ty::RegionVid;
type PlaceholderRegion = ty::PlaceholderRegion;
+
+ fn ty_and_mut_to_parts(
+ TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>,
+ ) -> (Self::Ty, Self::Mutability) {
+ (ty, mutbl)
+ }
+
+ fn mutability_is_mut(mutbl: Self::Mutability) -> bool {
+ mutbl.is_mut()
+ }
}
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
@@ -133,7 +148,7 @@ pub struct CtxtInterners<'tcx> {
region: InternedSet<'tcx, RegionKind<'tcx>>,
poly_existential_predicates: InternedSet<'tcx, List<PolyExistentialPredicate<'tcx>>>,
predicate: InternedSet<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
- predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
+ clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
const_: InternedSet<'tcx, ConstData<'tcx>>,
@@ -158,7 +173,7 @@ impl<'tcx> CtxtInterners<'tcx> {
poly_existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
predicate: Default::default(),
- predicates: Default::default(),
+ clauses: Default::default(),
projs: Default::default(),
place_elems: Default::default(),
const_: Default::default(),
@@ -312,6 +327,8 @@ pub struct CommonLifetimes<'tcx> {
pub struct CommonConsts<'tcx> {
pub unit: Const<'tcx>,
+ pub true_: Const<'tcx>,
+ pub false_: Const<'tcx>,
}
impl<'tcx> CommonTypes<'tcx> {
@@ -409,6 +426,14 @@ impl<'tcx> CommonConsts<'tcx> {
kind: ty::ConstKind::Value(ty::ValTree::zst()),
ty: types.unit,
}),
+ true_: mk_const(ty::ConstData {
+ kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)),
+ ty: types.bool,
+ }),
+ false_: mk_const(ty::ConstData {
+ kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)),
+ ty: types.bool,
+ }),
}
}
}
@@ -470,6 +495,17 @@ impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> {
/// [rustc dev guide] for more details.
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/ty.html
+///
+/// An implementation detail: `TyCtxt` is a wrapper type for [GlobalCtxt],
+/// which is the struct that actually holds all the data. `TyCtxt` derefs to
+/// `GlobalCtxt`, and in practice `TyCtxt` is passed around everywhere, and all
+/// operations are done via `TyCtxt`. A `TyCtxt` is obtained for a `GlobalCtxt`
+/// by calling `enter` with a closure `f`. That function creates both the
+/// `TyCtxt`, and an `ImplicitCtxt` around it that is put into TLS. Within `f`:
+/// - The `ImplicitCtxt` is available implicitly via TLS.
+/// - The `TyCtxt` is available explicitly via the `tcx` parameter, and also
+/// implicitly within the `ImplicitCtxt`. Explicit access is preferred when
+/// possible.
#[derive(Copy, Clone)]
#[rustc_diagnostic_item = "TyCtxt"]
#[rustc_pass_by_value]
@@ -485,6 +521,7 @@ impl<'tcx> Deref for TyCtxt<'tcx> {
}
}
+/// See [TyCtxt] for details about this type.
pub struct GlobalCtxt<'tcx> {
pub arena: &'tcx WorkerLocal<Arena<'tcx>>,
pub hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
@@ -689,82 +726,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
- #[track_caller]
- pub fn ty_error(self, reported: ErrorGuaranteed) -> Ty<'tcx> {
- self.mk_ty_from_kind(Error(reported))
- }
-
- /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
- #[track_caller]
- pub fn ty_error_misc(self) -> Ty<'tcx> {
- self.ty_error_with_message(DUMMY_SP, "TyKind::Error constructed but no error reported")
- }
-
- /// 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: impl Into<DiagnosticMessage>,
- ) -> Ty<'tcx> {
- let reported = self.sess.delay_span_bug(span, msg);
- self.mk_ty_from_kind(Error(reported))
- }
-
- /// Constructs a `RegionKind::ReError` lifetime.
- #[track_caller]
- pub fn mk_re_error(self, reported: ErrorGuaranteed) -> Region<'tcx> {
- self.intern_region(ty::ReError(reported))
- }
-
- /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` to ensure it
- /// gets used.
- #[track_caller]
- pub fn mk_re_error_misc(self) -> Region<'tcx> {
- self.mk_re_error_with_message(
- DUMMY_SP,
- "RegionKind::ReError constructed but no error reported",
- )
- }
-
- /// Constructs a `RegionKind::ReError` lifetime and registers a `delay_span_bug` with the given
- /// `msg` to ensure it gets used.
- #[track_caller]
- pub fn mk_re_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Region<'tcx> {
- let reported = self.sess.delay_span_bug(span, msg);
- self.mk_re_error(reported)
- }
-
- /// Like [TyCtxt::ty_error] but for constants, with current `ErrorGuaranteed`
- #[track_caller]
- 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_misc(self, ty: Ty<'tcx>) -> Const<'tcx> {
- self.const_error_with_message(
- ty,
- DUMMY_SP,
- "ty::ConstKind::Error constructed but no error reported",
- )
- }
-
- /// Like [TyCtxt::ty_error_with_message] but for constants.
- #[track_caller]
- pub fn const_error_with_message<S: Into<MultiSpan>>(
- self,
- ty: Ty<'tcx>,
- span: S,
- msg: &str,
- ) -> Const<'tcx> {
- let reported = self.sess.delay_span_bug(span, msg);
- self.mk_const(ty::ConstKind::Error(reported), ty)
- }
-
pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg)
}
@@ -1019,15 +980,6 @@ impl<'tcx> TyCtxt<'tcx> {
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
- /// we still evaluate them eagerly.
- #[inline]
- pub fn lazy_normalization(self) -> bool {
- let features = self.features();
- // Note: We only use lazy normalization for generic const expressions.
- features.generic_const_exprs
- }
-
#[inline]
pub fn local_crate_exports_generics(self) -> bool {
debug_assert!(self.sess.opts.share_generics());
@@ -1167,7 +1119,8 @@ impl<'tcx> TyCtxt<'tcx> {
/// Returns `&'static core::panic::Location<'static>`.
pub fn caller_location_ty(self) -> Ty<'tcx> {
- self.mk_imm_ref(
+ Ty::new_imm_ref(
+ self,
self.lifetimes.re_static,
self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
.subst(self, self.mk_substs(&[self.lifetimes.re_static.into()])),
@@ -1192,14 +1145,6 @@ impl<'tcx> TyCtxt<'tcx> {
self.limits(()).move_size_limit
}
- pub fn const_eval_limit(self) -> Limit {
- if self.sess.opts.unstable_opts.tiny_const_eval_limit {
- TINY_CONST_EVAL_LIMIT
- } else {
- self.limits(()).const_eval_limit
- }
- }
-
pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
iter::once(LOCAL_CRATE)
.chain(self.crates(()).iter().copied())
@@ -1210,6 +1155,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
self.visibility(def_id).expect_local()
}
+
+ /// Returns the origin of the opaque type `def_id`.
+ #[instrument(skip(self), level = "trace", ret)]
+ pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
+ self.hir().expect_item(def_id).expect_opaque_ty().origin
+ }
}
/// A trait implemented for all `X<'a>` types that can be safely and
@@ -1272,10 +1223,11 @@ nop_lift! {region; Region<'a> => Region<'tcx>}
nop_lift! {const_; Const<'a> => Const<'tcx>}
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
+nop_lift! {predicate; Clause<'a> => Clause<'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! {clauses; Clause<'a> => Clause<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind}
@@ -1515,9 +1467,9 @@ macro_rules! direct_interners {
// Functions with a `mk_` prefix are intended for use outside this file and
// crate. Functions with an `intern_` prefix are intended for use within this
-// file only, and have a corresponding `mk_` function.
+// crate only, and have a corresponding `mk_` function.
direct_interners! {
- region: intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
+ region: pub(crate) intern_region(RegionKind<'tcx>): Region -> Region<'tcx>,
const_: intern_const(ConstData<'tcx>): Const -> Const<'tcx>,
const_allocation: pub mk_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: pub mk_layout(LayoutS): Layout -> Layout<'tcx>,
@@ -1553,7 +1505,7 @@ slice_interners!(
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>),
+ clauses: intern_clauses(Clause<'tcx>),
projs: pub mk_projs(ProjectionKind),
place_elems: pub mk_place_elems(PlaceElem<'tcx>),
bound_variable_kinds: pub mk_bound_variable_kinds(ty::BoundVariableKind),
@@ -1566,7 +1518,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// unsafe.
pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
assert_eq!(sig.unsafety(), hir::Unsafety::Normal);
- self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
+ Ty::new_fn_ptr(
+ self,
+ sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }),
+ )
}
/// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
@@ -1585,7 +1540,7 @@ impl<'tcx> TyCtxt<'tcx> {
let future_trait = self.require_lang_item(LangItem::Future, None);
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 {
+ let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else {
return false;
};
trait_predicate.trait_ref.def_id == future_trait
@@ -1608,9 +1563,7 @@ impl<'tcx> TyCtxt<'tcx> {
let generic_predicates = self.super_predicates_of(trait_did);
for (predicate, _) in generic_predicates.predicates {
- if let ty::PredicateKind::Clause(ty::Clause::Trait(data)) =
- predicate.kind().skip_binder()
- {
+ if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() {
if set.insert(data.def_id()) {
stack.push(data.def_id());
}
@@ -1642,18 +1595,6 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
- // Avoid this in favour of more specific `mk_*` methods, where possible.
- #[allow(rustc::usage_of_ty_tykind)]
- #[inline]
- pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
- self.interners.intern_ty(
- st,
- self.sess,
- // This is only used to create a stable hashing context.
- &self.untracked,
- )
- }
-
#[inline]
pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
self.interners.intern_predicate(
@@ -1673,174 +1614,6 @@ impl<'tcx> TyCtxt<'tcx> {
if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
}
- pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
- match tm {
- IntTy::Isize => self.types.isize,
- IntTy::I8 => self.types.i8,
- IntTy::I16 => self.types.i16,
- IntTy::I32 => self.types.i32,
- IntTy::I64 => self.types.i64,
- IntTy::I128 => self.types.i128,
- }
- }
-
- pub fn mk_mach_uint(self, tm: UintTy) -> Ty<'tcx> {
- match tm {
- UintTy::Usize => self.types.usize,
- UintTy::U8 => self.types.u8,
- UintTy::U16 => self.types.u16,
- UintTy::U32 => self.types.u32,
- UintTy::U64 => self.types.u64,
- UintTy::U128 => self.types.u128,
- }
- }
-
- pub fn mk_mach_float(self, tm: FloatTy) -> Ty<'tcx> {
- match tm {
- FloatTy::F32 => self.types.f32,
- FloatTy::F64 => self.types.f64,
- }
- }
-
- #[inline]
- pub fn mk_static_str(self) -> Ty<'tcx> {
- self.mk_imm_ref(self.lifetimes.re_static, self.types.str_)
- }
-
- #[inline]
- pub fn mk_adt(self, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- // Take a copy of substs so that we own the vectors inside.
- self.mk_ty_from_kind(Adt(def, substs))
- }
-
- #[inline]
- pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
- self.mk_ty_from_kind(Foreign(def_id))
- }
-
- fn mk_generic_adt(self, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
- let adt_def = self.adt_def(wrapper_def_id);
- let substs =
- InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind {
- GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
- GenericParamDefKind::Type { has_default, .. } => {
- if param.index == 0 {
- ty_param.into()
- } else {
- assert!(has_default);
- self.type_of(param.def_id).subst(self, substs).into()
- }
- }
- });
- self.mk_ty_from_kind(Adt(adt_def, substs))
- }
-
- #[inline]
- pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- let def_id = self.require_lang_item(LangItem::OwnedBox, None);
- self.mk_generic_adt(def_id, ty)
- }
-
- #[inline]
- pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
- let def_id = self.lang_items().get(item)?;
- Some(self.mk_generic_adt(def_id, ty))
- }
-
- #[inline]
- pub fn mk_diagnostic_item(self, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
- let def_id = self.get_diagnostic_item(name)?;
- Some(self.mk_generic_adt(def_id, ty))
- }
-
- #[inline]
- pub fn mk_maybe_uninit(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- let def_id = self.require_lang_item(LangItem::MaybeUninit, None);
- self.mk_generic_adt(def_id, ty)
- }
-
- #[inline]
- pub fn mk_ptr(self, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(RawPtr(tm))
- }
-
- #[inline]
- pub fn mk_ref(self, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(Ref(r, tm.ty, tm.mutbl))
- }
-
- #[inline]
- pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
- }
-
- #[inline]
- pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
- }
-
- #[inline]
- pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut })
- }
-
- #[inline]
- pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not })
- }
-
- #[inline]
- pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
- self.mk_ty_from_kind(Array(ty, ty::Const::from_target_usize(self, n)))
- }
-
- #[inline]
- pub fn mk_array_with_const_len(self, ty: Ty<'tcx>, ct: Const<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(Array(ty, ct))
- }
-
- #[inline]
- pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(Slice(ty))
- }
-
- #[inline]
- pub fn mk_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
- if ts.is_empty() {
- self.types.unit
- } else {
- self.mk_ty_from_kind(Tuple(self.mk_type_list(&ts)))
- }
- }
-
- pub fn mk_tup_from_iter<I, T>(self, iter: I) -> T::Output
- where
- I: Iterator<Item = T>,
- T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
- {
- T::collect_and_apply(iter, |ts| self.mk_tup(ts))
- }
-
- #[inline]
- pub fn mk_unit(self) -> Ty<'tcx> {
- self.types.unit
- }
-
- #[inline]
- pub fn mk_diverging_default(self) -> Ty<'tcx> {
- if self.features().never_type_fallback { self.types.never } else { self.types.unit }
- }
-
- #[inline]
- pub fn mk_fn_def(
- self,
- def_id: DefId,
- substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
- ) -> Ty<'tcx> {
- let substs = self.check_and_mk_substs(def_id, substs);
- self.mk_ty_from_kind(FnDef(def_id, substs))
- }
-
#[inline(always)]
pub(crate) fn check_and_mk_substs(
self,
@@ -1872,222 +1645,36 @@ impl<'tcx> TyCtxt<'tcx> {
}
#[inline]
- pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(FnPtr(fty))
- }
-
- #[inline]
- pub fn mk_dynamic(
- self,
- obj: &'tcx List<PolyExistentialPredicate<'tcx>>,
- reg: ty::Region<'tcx>,
- repr: DynKind,
- ) -> Ty<'tcx> {
- self.mk_ty_from_kind(Dynamic(obj, reg, repr))
- }
-
- #[inline]
- pub fn mk_projection(
- self,
- item_def_id: DefId,
- substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
- ) -> Ty<'tcx> {
- self.mk_alias(ty::Projection, self.mk_alias_ty(item_def_id, substs))
- }
-
- #[inline]
- pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(Closure(closure_id, closure_substs))
- }
-
- #[inline]
- pub fn mk_generator(
- self,
- id: DefId,
- generator_substs: SubstsRef<'tcx>,
- movability: hir::Movability,
- ) -> Ty<'tcx> {
- self.mk_ty_from_kind(Generator(id, generator_substs, movability))
- }
-
- #[inline]
- pub fn mk_generator_witness(self, types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
- self.mk_ty_from_kind(GeneratorWitness(types))
- }
-
- /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
- pub fn mk_task_context(self) -> Ty<'tcx> {
- let context_did = self.require_lang_item(LangItem::Context, None);
- let context_adt_ref = self.adt_def(context_did);
- let context_substs = self.mk_substs(&[self.lifetimes.re_erased.into()]);
- let context_ty = self.mk_adt(context_adt_ref, context_substs);
- self.mk_mut_ref(self.lifetimes.re_erased, context_ty)
- }
-
- #[inline]
- pub fn mk_generator_witness_mir(self, id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_ty_from_kind(GeneratorWitnessMIR(id, substs))
- }
-
- #[inline]
- pub fn mk_const(self, kind: impl Into<ty::ConstKind<'tcx>>, ty: Ty<'tcx>) -> Const<'tcx> {
- self.intern_const(ty::ConstData { kind: kind.into(), ty })
- }
-
- #[inline]
- pub fn mk_ty_var(self, v: TyVid) -> Ty<'tcx> {
- // Use a pre-interned one when possible.
- self.types
- .ty_vars
- .get(v.as_usize())
- .copied()
- .unwrap_or_else(|| self.mk_ty_from_kind(Infer(TyVar(v))))
- }
-
- #[inline]
- pub fn mk_int_var(self, v: IntVid) -> Ty<'tcx> {
- self.mk_ty_from_kind(Infer(IntVar(v)))
- }
-
- #[inline]
- pub fn mk_float_var(self, v: FloatVid) -> Ty<'tcx> {
- self.mk_ty_from_kind(Infer(FloatVar(v)))
- }
-
- #[inline]
- pub fn mk_fresh_ty(self, n: u32) -> Ty<'tcx> {
- // Use a pre-interned one when possible.
- self.types
- .fresh_tys
- .get(n as usize)
- .copied()
- .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshTy(n))))
- }
-
- #[inline]
- pub fn mk_fresh_int_ty(self, n: u32) -> Ty<'tcx> {
- // Use a pre-interned one when possible.
- self.types
- .fresh_int_tys
- .get(n as usize)
- .copied()
- .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshIntTy(n))))
- }
-
- #[inline]
- pub fn mk_fresh_float_ty(self, n: u32) -> Ty<'tcx> {
- // Use a pre-interned one when possible.
- self.types
- .fresh_float_tys
- .get(n as usize)
- .copied()
- .unwrap_or_else(|| self.mk_ty_from_kind(Infer(ty::FreshFloatTy(n))))
+ pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
+ self.intern_const(ty::ConstData { kind, ty })
}
+ // Avoid this in favour of more specific `Ty::new_*` methods, where possible.
+ #[allow(rustc::usage_of_ty_tykind)]
#[inline]
- pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> {
- self.mk_ty_from_kind(Param(ParamTy { index, name }))
+ pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
+ self.interners.intern_ty(
+ st,
+ self.sess,
+ // This is only used to create a stable hashing context.
+ &self.untracked,
+ )
}
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
- self.mk_re_early_bound(param.to_early_bound_region_data()).into()
- }
- GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(),
- GenericParamDefKind::Const { .. } => self
- .mk_const(
- ParamConst { index: param.index, name: param.name },
- self.type_of(param.def_id)
- .no_bound_vars()
- .expect("const parameter types cannot be generic"),
- )
- .into(),
- }
- }
-
- #[inline]
- pub fn mk_bound(self, index: ty::DebruijnIndex, bound_ty: ty::BoundTy) -> Ty<'tcx> {
- self.mk_ty_from_kind(Bound(index, bound_ty))
- }
-
- #[inline]
- pub fn mk_placeholder(self, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
- self.mk_ty_from_kind(Placeholder(placeholder))
- }
-
- #[inline]
- pub fn mk_alias(self, kind: ty::AliasKind, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> {
- debug_assert_matches!(
- (kind, self.def_kind(alias_ty.def_id)),
- (ty::Opaque, DefKind::OpaqueTy)
- | (ty::Projection | ty::Inherent, DefKind::AssocTy)
- | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
- );
- self.mk_ty_from_kind(Alias(kind, alias_ty))
- }
-
- #[inline]
- pub fn mk_opaque(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
- self.mk_alias(ty::Opaque, self.mk_alias_ty(def_id, substs))
- }
-
- #[inline]
- pub fn mk_re_early_bound(self, early_bound_region: ty::EarlyBoundRegion) -> Region<'tcx> {
- self.intern_region(ty::ReEarlyBound(early_bound_region))
- }
-
- #[inline]
- pub fn mk_re_late_bound(
- self,
- debruijn: ty::DebruijnIndex,
- bound_region: ty::BoundRegion,
- ) -> Region<'tcx> {
- // Use a pre-interned one when possible.
- if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
- && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
- && let Some(re) = inner.get(var.as_usize()).copied()
- {
- re
- } else {
- self.intern_region(ty::ReLateBound(debruijn, bound_region))
- }
- }
-
- #[inline]
- pub fn mk_re_free(self, scope: DefId, bound_region: ty::BoundRegionKind) -> Region<'tcx> {
- self.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
- }
-
- #[inline]
- pub fn mk_re_var(self, v: ty::RegionVid) -> Region<'tcx> {
- // Use a pre-interned one when possible.
- self.lifetimes
- .re_vars
- .get(v.as_usize())
- .copied()
- .unwrap_or_else(|| self.intern_region(ty::ReVar(v)))
- }
-
- #[inline]
- pub fn mk_re_placeholder(self, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
- self.intern_region(ty::RePlaceholder(placeholder))
- }
-
- // Avoid this in favour of more specific `mk_re_*` methods, where possible,
- // to avoid the cost of the `match`.
- pub fn mk_region_from_kind(self, kind: ty::RegionKind<'tcx>) -> Region<'tcx> {
- match kind {
- ty::ReEarlyBound(region) => self.mk_re_early_bound(region),
- ty::ReLateBound(debruijn, region) => self.mk_re_late_bound(debruijn, region),
- ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
- self.mk_re_free(scope, bound_region)
+ ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into()
}
- ty::ReStatic => self.lifetimes.re_static,
- ty::ReVar(vid) => self.mk_re_var(vid),
- ty::RePlaceholder(region) => self.mk_re_placeholder(region),
- ty::ReErased => self.lifetimes.re_erased,
- ty::ReError(reported) => self.mk_re_error(reported),
+ GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
+ GenericParamDefKind::Const { .. } => ty::Const::new_param(
+ self,
+ ParamConst { index: param.index, name: param.name },
+ self.type_of(param.def_id)
+ .no_bound_vars()
+ .expect("const parameter types cannot be generic"),
+ )
+ .into(),
}
}
@@ -2146,11 +1733,11 @@ impl<'tcx> TyCtxt<'tcx> {
self.intern_poly_existential_predicates(eps)
}
- pub fn mk_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
+ pub fn mk_clauses(self, clauses: &[Clause<'tcx>]) -> &'tcx List<Clause<'tcx>> {
// FIXME consider asking the input slice to be sorted to avoid
// re-interning permutations, in which case that would be asserted
// here.
- self.intern_predicates(preds)
+ self.intern_clauses(clauses)
}
pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
@@ -2196,12 +1783,12 @@ impl<'tcx> TyCtxt<'tcx> {
T::collect_and_apply(iter, |xs| self.mk_poly_existential_predicates(xs))
}
- pub fn mk_predicates_from_iter<I, T>(self, iter: I) -> T::Output
+ pub fn mk_clauses_from_iter<I, T>(self, iter: I) -> T::Output
where
I: Iterator<Item = T>,
- T: CollectAndApply<Predicate<'tcx>, &'tcx List<Predicate<'tcx>>>,
+ T: CollectAndApply<Clause<'tcx>, &'tcx List<Clause<'tcx>>>,
{
- T::collect_and_apply(iter, |xs| self.mk_predicates(xs))
+ T::collect_and_apply(iter, |xs| self.mk_clauses(xs))
}
pub fn mk_type_list_from_iter<I, T>(self, iter: I) -> T::Output
@@ -2403,10 +1990,18 @@ impl<'tcx> TyCtxt<'tcx> {
self.opt_local_def_id_to_hir_id(local_def_id).unwrap()
}
- pub fn trait_solver_next(self) -> bool {
+ pub fn next_trait_solver_globally(self) -> bool {
self.sess.opts.unstable_opts.trait_solver == rustc_session::config::TraitSolver::Next
}
+ pub fn next_trait_solver_in_coherence(self) -> bool {
+ matches!(
+ self.sess.opts.unstable_opts.trait_solver,
+ rustc_session::config::TraitSolver::Next
+ | rustc_session::config::TraitSolver::NextCoherence
+ )
+ }
+
pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
}
@@ -2433,21 +2028,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
-impl<'tcx> TyCtxtAt<'tcx> {
- /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
- #[track_caller]
- pub fn ty_error_misc(self) -> Ty<'tcx> {
- self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
- }
-
- /// 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: impl Into<DiagnosticMessage>) -> Ty<'tcx> {
- self.tcx.ty_error_with_message(self.span, msg)
- }
-}
-
/// Parameter attributes that can only be determined by examining the body of a function instead
/// of just its signature.
///
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 6a29063b8..a0b17c374 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,5 +1,6 @@
//! Diagnostics related methods for `Ty`.
+use std::borrow::Cow;
use std::ops::ControlFlow;
use crate::ty::{
@@ -13,8 +14,8 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnostic
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_hir::WherePredicate;
-use rustc_span::Span;
+use rustc_hir::{PredicateOrigin, WherePredicate};
+use rustc_span::{BytePos, Span};
use rustc_type_ir::sty::TyKind::*;
impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
@@ -155,10 +156,11 @@ enum SuggestChangingConstraintsMessage<'a> {
RestrictBoundFurther,
RestrictType { ty: &'a str },
RestrictTypeFurther { ty: &'a str },
- RemovingQSized,
+ RemoveMaybeUnsized,
+ ReplaceMaybeUnsizedWithSized,
}
-fn suggest_removing_unsized_bound(
+fn suggest_changing_unsized_bound(
generics: &hir::Generics<'_>,
suggestions: &mut Vec<(Span, String, SuggestChangingConstraintsMessage<'_>)>,
param: &hir::GenericParam<'_>,
@@ -182,12 +184,25 @@ fn suggest_removing_unsized_bound(
if poly.trait_ref.trait_def_id() != def_id {
continue;
}
- let sp = generics.span_for_bound_removal(where_pos, pos);
- suggestions.push((
- sp,
- String::new(),
- SuggestChangingConstraintsMessage::RemovingQSized,
- ));
+ if predicate.origin == PredicateOrigin::ImplTrait && predicate.bounds.len() == 1 {
+ // For `impl ?Sized` with no other bounds, suggest `impl Sized` instead.
+ let bound_span = bound.span();
+ if bound_span.can_be_used_for_suggestions() {
+ let question_span = bound_span.with_hi(bound_span.lo() + BytePos(1));
+ suggestions.push((
+ question_span,
+ String::new(),
+ SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized,
+ ));
+ }
+ } else {
+ let sp = generics.span_for_bound_removal(where_pos, pos);
+ suggestions.push((
+ sp,
+ String::new(),
+ SuggestChangingConstraintsMessage::RemoveMaybeUnsized,
+ ));
+ }
}
}
}
@@ -236,15 +251,12 @@ pub fn suggest_constraining_type_params<'a>(
{
let mut sized_constraints =
- constraints.drain_filter(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
- if let Some((constraint, def_id)) = sized_constraints.next() {
+ constraints.extract_if(|(_, def_id)| *def_id == tcx.lang_items().sized_trait());
+ if let Some((_, def_id)) = sized_constraints.next() {
applicability = Applicability::MaybeIncorrect;
- err.span_label(
- param.span,
- format!("this type parameter needs to be `{}`", constraint),
- );
- suggest_removing_unsized_bound(generics, &mut suggestions, param, def_id);
+ err.span_label(param.span, "this type parameter needs to be `Sized`");
+ suggest_changing_unsized_bound(generics, &mut suggestions, param, def_id);
}
}
@@ -384,22 +396,21 @@ pub fn suggest_constraining_type_params<'a>(
if suggestions.len() == 1 {
let (span, suggestion, msg) = suggestions.pop().unwrap();
-
- let s;
let msg = match msg {
SuggestChangingConstraintsMessage::RestrictBoundFurther => {
- "consider further restricting this bound"
+ Cow::from("consider further restricting this bound")
}
SuggestChangingConstraintsMessage::RestrictType { ty } => {
- s = format!("consider restricting type parameter `{}`", ty);
- &s
+ Cow::from(format!("consider restricting type parameter `{}`", ty))
}
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty } => {
- s = format!("consider further restricting type parameter `{}`", ty);
- &s
+ Cow::from(format!("consider further restricting type parameter `{}`", ty))
+ }
+ SuggestChangingConstraintsMessage::RemoveMaybeUnsized => {
+ Cow::from("consider removing the `?Sized` bound to make the type parameter `Sized`")
}
- SuggestChangingConstraintsMessage::RemovingQSized => {
- "consider removing the `?Sized` bound to make the type parameter `Sized`"
+ SuggestChangingConstraintsMessage::ReplaceMaybeUnsizedWithSized => {
+ Cow::from("consider replacing `?Sized` with `Sized`")
}
};
@@ -548,7 +559,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
Infer(InferTy::TyVar(_)) if self.infer_suggestable => t,
FnDef(def_id, substs) => {
- self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
+ Ty::new_fn_ptr(self.tcx, self.tcx.fn_sig(def_id).subst(self.tcx, substs))
}
// FIXME(compiler-errors): We could replace these with infer, I guess.
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 49ab9b79e..c794c3fad 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -45,7 +45,6 @@ pub enum TypeError<'tcx> {
RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
- RegionsOverlyPolymorphic(BoundRegionKind, Region<'tcx>),
RegionsPlaceholderMismatch,
Sorts(ExpectedFound<Ty<'tcx>>),
@@ -74,7 +73,6 @@ impl TypeError<'_> {
match self {
TypeError::RegionsDoesNotOutlive(_, _)
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
- | TypeError::RegionsOverlyPolymorphic(_, _)
| TypeError::RegionsPlaceholderMismatch => true,
_ => false,
}
@@ -98,11 +96,6 @@ impl<'tcx> TypeError<'tcx> {
}
}
- let br_string = |br: ty::BoundRegionKind| match br {
- ty::BrNamed(_, name) => format!(" {}", name),
- _ => String::new(),
- };
-
match self {
CyclicTy(_) => "cyclic type of infinite size".into(),
CyclicConst(_) => "encountered a self-referencing constant".into(),
@@ -144,11 +137,6 @@ impl<'tcx> TypeError<'tcx> {
RegionsInsufficientlyPolymorphic(..) => {
"one type is more general than the other".into()
}
- RegionsOverlyPolymorphic(br, _) => format!(
- "expected concrete lifetime, found bound lifetime parameter{}",
- br_string(br)
- )
- .into(),
RegionsPlaceholderMismatch => "one type is more general than the other".into(),
ArgumentSorts(values, _) | Sorts(values) => {
let expected = values.expected.sort_string(tcx);
@@ -228,7 +216,6 @@ impl<'tcx> TypeError<'tcx> {
| FieldMisMatch(..)
| RegionsDoesNotOutlive(..)
| RegionsInsufficientlyPolymorphic(..)
- | RegionsOverlyPolymorphic(..)
| RegionsPlaceholderMismatch
| Traits(_)
| ProjectionMismatched(_)
@@ -313,6 +300,7 @@ impl<'tcx> Ty<'tcx> {
ty::Placeholder(..) => "higher-ranked type".into(),
ty::Bound(..) => "bound type variable".into(),
ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(),
+ ty::Alias(ty::Weak, _) => "type alias".into(),
ty::Param(_) => "type parameter".into(),
ty::Alias(ty::Opaque, ..) => "opaque type".into(),
}
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index d64875a9f..ff3917947 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -178,7 +178,7 @@ impl FlagComputation {
&ty::Alias(kind, data) => {
self.add_flags(match kind {
- ty::Projection => TypeFlags::HAS_TY_PROJECTION,
+ ty::Weak | ty::Projection => TypeFlags::HAS_TY_PROJECTION,
ty::Inherent => TypeFlags::HAS_TY_INHERENT,
ty::Opaque => TypeFlags::HAS_TY_OPAQUE,
});
@@ -237,21 +237,24 @@ impl FlagComputation {
fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
match atom {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) => {
self.add_substs(trait_pred.trait_ref.substs);
}
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(a, b))) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+ a,
+ b,
+ ))) => {
self.add_region(a);
self.add_region(b);
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
ty,
region,
))) => {
self.add_ty(ty);
self.add_region(region);
}
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
self.add_const(ct);
self.add_ty(ty);
}
@@ -263,30 +266,27 @@ impl FlagComputation {
self.add_ty(a);
self.add_ty(b);
}
- ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty,
term,
})) => {
self.add_alias_ty(projection_ty);
self.add_term(term);
}
- ty::PredicateKind::WellFormed(arg) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
self.add_substs(slice::from_ref(&arg));
}
ty::PredicateKind::ObjectSafe(_def_id) => {}
ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
self.add_substs(substs);
}
- ty::PredicateKind::ConstEvaluatable(uv) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
self.add_const(uv);
}
ty::PredicateKind::ConstEquate(expected, found) => {
self.add_const(expected);
self.add_const(found);
}
- ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
- self.add_ty(ty);
- }
ty::PredicateKind::Ambiguous => {}
ty::PredicateKind::AliasRelate(t1, t2, _) => {
self.add_term(t1);
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 25890eb15..77cf6bee7 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -213,7 +213,7 @@ where
// debruijn index. Then we adjust it to the
// correct depth.
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.mk_re_late_bound(debruijn, br)
+ ty::Region::new_late_bound(self.tcx, debruijn, br)
} else {
region
}
@@ -328,7 +328,7 @@ impl<'tcx> TyCtxt<'tcx> {
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions_uncached(value, |br| {
- self.mk_re_free(all_outlive_scope, br.kind)
+ ty::Region::new_free(self, all_outlive_scope, br.kind)
})
}
@@ -341,16 +341,21 @@ impl<'tcx> TyCtxt<'tcx> {
value,
FnMutDelegate {
regions: &mut |r: ty::BoundRegion| {
- self.mk_re_late_bound(
+ ty::Region::new_late_bound(
+ self,
ty::INNERMOST,
ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
)
},
types: &mut |t: ty::BoundTy| {
- self.mk_bound(ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
+ Ty::new_bound(
+ self,
+ ty::INNERMOST,
+ ty::BoundTy { var: shift_bv(t.var), kind: t.kind },
+ )
},
consts: &mut |c, ty: Ty<'tcx>| {
- self.mk_const(ty::ConstKind::Bound(ty::INNERMOST, shift_bv(c)), ty)
+ ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty)
},
},
)
@@ -383,7 +388,7 @@ impl<'tcx> TyCtxt<'tcx> {
.or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
.expect_region();
let br = ty::BoundRegion { var, kind };
- self.tcx.mk_re_late_bound(ty::INNERMOST, br)
+ ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br)
}
fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
let entry = self.map.entry(bt.var);
@@ -392,14 +397,14 @@ impl<'tcx> TyCtxt<'tcx> {
let kind = entry
.or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
.expect_ty();
- self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
+ Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind })
}
fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> {
let entry = self.map.entry(bv);
let index = entry.index();
let var = ty::BoundVar::from_usize(index);
let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const();
- self.tcx.mk_const(ty::ConstKind::Bound(ty::INNERMOST, var), ty)
+ ty::Const::new_bound(self.tcx, ty::INNERMOST, var, ty)
}
}
@@ -451,7 +456,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
match *r {
ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- self.tcx.mk_re_late_bound(debruijn, br)
+ ty::Region::new_late_bound(self.tcx, debruijn, br)
}
_ => r,
}
@@ -461,7 +466,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
match *ty.kind() {
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
let debruijn = debruijn.shifted_in(self.amount);
- self.tcx.mk_bound(debruijn, bound_ty)
+ Ty::new_bound(self.tcx, debruijn, bound_ty)
}
_ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
@@ -474,7 +479,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Shifter<'tcx> {
&& debruijn >= self.current_index
{
let debruijn = debruijn.shifted_in(self.amount);
- self.tcx.mk_const(ty::ConstKind::Bound(debruijn, bound_ct), ct.ty())
+ ty::Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty())
} else {
ct.super_fold_with(self)
}
@@ -492,7 +497,7 @@ pub fn shift_region<'tcx>(
) -> ty::Region<'tcx> {
match *region {
ty::ReLateBound(debruijn, br) if amount > 0 => {
- tcx.mk_re_late_bound(debruijn.shifted_in(amount), br)
+ ty::Region::new_late_bound(tcx, debruijn.shifted_in(amount), br)
}
_ => region,
}
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index b0ffe7829..6c7125c4c 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
-use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt};
+use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind {
@@ -100,11 +100,13 @@ impl GenericParamDef {
preceding_substs: &[ty::GenericArg<'tcx>],
) -> ty::GenericArg<'tcx> {
match &self.kind {
- ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
- ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
- ty::GenericParamDefKind::Const { .. } => {
- tcx.const_error_misc(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
- }
+ ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(),
+ ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(),
+ ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(
+ tcx,
+ tcx.type_of(self.def_id).subst(tcx, preceding_substs),
+ )
+ .into(),
}
}
}
@@ -133,6 +135,9 @@ pub struct Generics {
pub has_self: bool,
pub has_late_bound_regions: Option<Span>,
+
+ // The index of the host effect when substituted. (i.e. might be index to parent substs)
+ pub host_effect_index: Option<usize>,
}
impl<'tcx> Generics {
@@ -323,7 +328,7 @@ impl<'tcx> Generics {
#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>,
- pub predicates: &'tcx [(Predicate<'tcx>, Span)],
+ pub predicates: &'tcx [(Clause<'tcx>, Span)],
}
impl<'tcx> GenericPredicates<'tcx> {
@@ -341,9 +346,8 @@ impl<'tcx> GenericPredicates<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
- ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
- {
- EarlyBinder(self.predicates).subst_iter_copied(tcx, substs)
+ ) -> impl Iterator<Item = (Clause<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator {
+ EarlyBinder::bind(self.predicates).subst_iter_copied(tcx, substs)
}
#[instrument(level = "debug", skip(self, tcx))]
@@ -358,7 +362,7 @@ impl<'tcx> GenericPredicates<'tcx> {
}
instantiated
.predicates
- .extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs)));
+ .extend(self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).subst(tcx, substs)));
instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index ac42d6e05..295cb1464 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -62,7 +62,18 @@ impl<'tcx> InhabitedPredicate<'tcx> {
Some(1..) => Ok(false),
},
Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
- Self::GenericType(_) => Ok(true),
+ // `t` may be a projection, for which `inhabited_predicate` returns a `GenericType`. As
+ // we have a param_env available, we can do better.
+ Self::GenericType(t) => {
+ let normalized_pred = tcx
+ .try_normalize_erasing_regions(param_env, t)
+ .map_or(self, |t| t.inhabited_predicate(tcx));
+ match normalized_pred {
+ // We don't have more information than we started with, so consider inhabited.
+ Self::GenericType(_) => Ok(true),
+ pred => pred.apply_inner(tcx, param_env, in_module),
+ }
+ }
Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
}
@@ -158,8 +169,8 @@ impl<'tcx> InhabitedPredicate<'tcx> {
fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
match self {
Self::ConstIsZero(c) => {
- let c = ty::EarlyBinder(c).subst(tcx, substs);
- let pred = match c.kind().try_to_target_usize(tcx) {
+ let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
+ let pred = match c.try_to_target_usize(tcx) {
Some(0) => Self::True,
Some(1..) => Self::False,
None => Self::ConstIsZero(c),
@@ -167,7 +178,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
Some(pred)
}
Self::GenericType(t) => {
- Some(ty::EarlyBinder(t).subst(tcx, substs).inhabited_predicate(tcx))
+ Some(ty::EarlyBinder::bind(t).subst(tcx, substs).inhabited_predicate(tcx))
}
Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 422350284..b92d84152 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -197,7 +197,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP
// If we can evaluate the array length before having a `ParamEnv`, then
// we can simplify the predicate. This is an optimization.
- Array(ty, len) => match len.kind().try_to_target_usize(tcx) {
+ Array(ty, len) => match len.try_to_target_usize(tcx) {
Some(0) => InhabitedPredicate::True,
Some(1..) => ty.inhabited_predicate(tcx),
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index e641d1ef1..ae57e954f 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -410,8 +410,8 @@ impl<'tcx> Instance<'tcx> {
) -> Instance<'tcx> {
match ty::Instance::resolve(tcx, param_env, def_id, substs) {
Ok(Some(instance)) => instance,
- _ => bug!(
- "failed to resolve instance for {}",
+ instance => bug!(
+ "failed to resolve instance for {}: {instance:#?}",
tcx.def_path_str_with_substs(def_id, substs)
),
}
@@ -552,7 +552,7 @@ impl<'tcx> Instance<'tcx> {
tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller };
- let self_ty = tcx.mk_closure(closure_did, substs);
+ let self_ty = Ty::new_closure(tcx, closure_did, substs);
let sig = substs.as_closure().sig();
let sig =
@@ -586,7 +586,7 @@ impl<'tcx> Instance<'tcx> {
if let Some(substs) = self.substs_for_mir_body() {
v.subst(tcx, substs)
} else {
- v.skip_binder()
+ v.subst_identity()
}
}
@@ -680,7 +680,7 @@ fn polymorphize<'tcx>(
if substs == polymorphized_substs {
ty
} else {
- self.tcx.mk_closure(def_id, polymorphized_substs)
+ Ty::new_closure(self.tcx, def_id, polymorphized_substs)
}
}
ty::Generator(def_id, substs, movability) => {
@@ -689,7 +689,7 @@ fn polymorphize<'tcx>(
if substs == polymorphized_substs {
ty
} else {
- self.tcx.mk_generator(def_id, polymorphized_substs, movability)
+ Ty::new_generator(self.tcx, def_id, polymorphized_substs, movability)
}
}
_ => ty.super_fold_with(self),
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index b5a743cfe..d95b05ef7 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,8 +1,9 @@
-use crate::fluent_generated as fluent;
+use crate::error::UnsupportedFnAbi;
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 crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
+use rustc_error_messages::DiagnosticMessage;
use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@@ -14,7 +15,7 @@ use rustc_target::abi::call::FnAbi;
use rustc_target::abi::*;
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
-use std::cmp::{self};
+use std::cmp;
use std::fmt;
use std::num::NonZeroUsize;
use std::ops::Bound;
@@ -132,7 +133,7 @@ impl PrimitiveExt for Primitive {
F32 => tcx.types.f32,
F64 => tcx.types.f64,
// FIXME(erikdesjardins): handle non-default addrspace ptr sizes
- Pointer(_) => tcx.mk_mut_ptr(tcx.mk_unit()),
+ Pointer(_) => Ty::new_mut_ptr(tcx, Ty::new_unit(tcx)),
}
}
@@ -214,29 +215,29 @@ pub enum LayoutError<'tcx> {
Cycle,
}
-impl IntoDiagnostic<'_, !> for LayoutError<'_> {
- fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
- let mut diag = handler.struct_fatal("");
+impl<'tcx> LayoutError<'tcx> {
+ pub fn diagnostic_message(&self) -> DiagnosticMessage {
+ use crate::fluent_generated::*;
+ use LayoutError::*;
+ match self {
+ Unknown(_) => middle_unknown_layout,
+ SizeOverflow(_) => middle_values_too_big,
+ NormalizationFailure(_, _) => middle_cannot_be_normalized,
+ Cycle => middle_cycle,
+ }
+ }
+ pub fn into_diagnostic(self) -> crate::error::LayoutError<'tcx> {
+ use crate::error::LayoutError as E;
+ use LayoutError::*;
match self {
- LayoutError::Unknown(ty) => {
- diag.set_arg("ty", ty);
- diag.set_primary_message(fluent::middle_unknown_layout);
- }
- LayoutError::SizeOverflow(ty) => {
- diag.set_arg("ty", ty);
- diag.set_primary_message(fluent::middle_values_too_big);
- }
- LayoutError::NormalizationFailure(ty, e) => {
- diag.set_arg("ty", ty);
- 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);
+ Unknown(ty) => E::Unknown { ty },
+ SizeOverflow(ty) => E::Overflow { ty },
+ NormalizationFailure(ty, e) => {
+ E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
}
+ Cycle => E::Cycle,
}
- diag
}
}
@@ -309,7 +310,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- ) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
+ ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> {
debug_assert!(!ty.has_non_region_infer());
// First try computing a static layout.
@@ -317,7 +318,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
Ok(layout) => {
return Ok(SizeSkeleton::Known(layout.size));
}
- Err(err) => err,
+ Err(err @ LayoutError::Unknown(_)) => err,
+ // We can't extract SizeSkeleton info from other layout errors
+ Err(
+ e @ LayoutError::Cycle
+ | e @ LayoutError::SizeOverflow(_)
+ | e @ LayoutError::NormalizationFailure(..),
+ ) => return Err(e),
};
match *ty.kind() {
@@ -330,11 +337,8 @@ impl<'tcx> SizeSkeleton<'tcx> {
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
_ => bug!(
- "SizeSkeleton::compute({}): layout errored ({}), yet \
- tail `{}` is not a type parameter or a projection",
- ty,
- err,
- tail
+ "SizeSkeleton::compute({ty}): layout errored ({err:?}), yet \
+ tail `{tail}` is not a type parameter or a projection",
),
}
}
@@ -349,13 +353,13 @@ impl<'tcx> SizeSkeleton<'tcx> {
let size = s
.bytes()
.checked_mul(c)
- .ok_or_else(|| LayoutError::SizeOverflow(ty))?;
+ .ok_or_else(|| &*tcx.arena.alloc(LayoutError::SizeOverflow(ty)))?;
return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
}
let len = tcx.expand_abstract_consts(len);
let prev = ty::Const::from_target_usize(tcx, s.bytes());
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
- return Err(LayoutError::SizeOverflow(ty));
+ return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
};
Ok(SizeSkeleton::Generic(gen_size))
}
@@ -363,7 +367,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
SizeSkeleton::Generic(g) => {
let len = tcx.expand_abstract_consts(len);
let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
- return Err(LayoutError::SizeOverflow(ty));
+ return Err(tcx.arena.alloc(LayoutError::SizeOverflow(ty)));
};
Ok(SizeSkeleton::Generic(gen_size))
}
@@ -476,13 +480,11 @@ fn mul_sorted_consts<'tcx>(
b: ty::Const<'tcx>,
) -> Option<ty::Const<'tcx>> {
use crate::mir::BinOp::Mul;
- use ty::ConstKind::Expr;
- use ty::Expr::Binop;
let mut work = vec![a, b];
let mut done = vec![];
while let Some(n) = work.pop() {
- if let Expr(Binop(Mul, l, r)) = n.kind() {
+ if let ConstKind::Expr(ty::Expr::Binop(Mul, l, r)) = n.kind() {
work.push(l);
work.push(r)
} else {
@@ -513,7 +515,7 @@ fn mul_sorted_consts<'tcx>(
done.sort_unstable();
// create a single tree from the buffer
- done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty()))
+ done.into_iter().reduce(|acc, n| ty::Const::new_expr(tcx, ty::Expr::Binop(Mul, n, acc), n.ty()))
}
pub trait HasTyCtxt<'tcx>: HasDataLayout {
@@ -668,7 +670,7 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
MaybeResult::from(
tcx.layout_of(self.param_env().and(ty))
- .map_err(|err| self.handle_layout_err(err, span, ty)),
+ .map_err(|err| self.handle_layout_err(*err, span, ty)),
)
}
}
@@ -676,16 +678,21 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {}
impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
- type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+ type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>;
#[inline]
- fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
- err
+ fn handle_layout_err(
+ &self,
+ err: LayoutError<'tcx>,
+ _: Span,
+ _: Ty<'tcx>,
+ ) -> &'tcx LayoutError<'tcx> {
+ self.tcx.arena.alloc(err)
}
}
impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
- type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+ type LayoutOfResult = Result<TyAndLayout<'tcx>, &'tcx LayoutError<'tcx>>;
#[inline]
fn layout_tcx_at_span(&self) -> Span {
@@ -693,8 +700,13 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
}
#[inline]
- fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
- err
+ fn handle_layout_err(
+ &self,
+ err: LayoutError<'tcx>,
+ _: Span,
+ _: Ty<'tcx>,
+ ) -> &'tcx LayoutError<'tcx> {
+ self.tcx.arena.alloc(err)
}
}
@@ -798,11 +810,11 @@ where
// (which may have no non-DST form), and will work as long
// as the `Abi` or `FieldsShape` is checked by users.
if i == 0 {
- let nil = tcx.mk_unit();
+ let nil = Ty::new_unit(tcx);
let unit_ptr_ty = if this.ty.is_unsafe_ptr() {
- tcx.mk_mut_ptr(nil)
+ Ty::new_mut_ptr(tcx, nil)
} else {
- tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
+ Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil)
};
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing
@@ -815,7 +827,11 @@ where
}
let mk_dyn_vtable = || {
- tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3))
+ Ty::new_imm_ref(
+ tcx,
+ tcx.lifetimes.re_static,
+ Ty::new_array(tcx, tcx.types.usize, 3),
+ )
/* FIXME: use actual fn pointers
Warning: naively computing the number of entries in the
vtable by counting the methods on the trait + methods on
@@ -824,9 +840,9 @@ where
Increase this counter if you tried to implement this but
failed to do it without duplicating a lot of code from
other places in the compiler: 2
- tcx.mk_tup(&[
- tcx.mk_array(tcx.types.usize, 3),
- tcx.mk_array(Option<fn()>),
+ Ty::new_tup(tcx,&[
+ Ty::new_array(tcx,tcx.types.usize, 3),
+ Ty::new_array(tcx,Option<fn()>),
])
*/
};
@@ -838,7 +854,7 @@ where
{
let metadata = tcx.normalize_erasing_regions(
cx.param_env(),
- tcx.mk_projection(metadata_def_id, [pointee]),
+ Ty::new_projection(tcx,metadata_def_id, [pointee]),
);
// Map `Metadata = DynMetadata<dyn Trait>` back to a vtable, since it
@@ -913,15 +929,14 @@ where
ty::Dynamic(_, _, ty::DynStar) => {
if i == 0 {
- TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit))
+ TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit))
} else if i == 1 {
// FIXME(dyn-star) same FIXME as above applies here too
- TyMaybeWithLayout::Ty(
- tcx.mk_imm_ref(
- tcx.lifetimes.re_static,
- tcx.mk_array(tcx.types.usize, 3),
- ),
- )
+ TyMaybeWithLayout::Ty(Ty::new_imm_ref(
+ tcx,
+ tcx.lifetimes.re_static,
+ Ty::new_array(tcx, tcx.types.usize, 3),
+ ))
} else {
bug!("no field {i} on dyn*")
}
@@ -940,12 +955,8 @@ where
TyMaybeWithLayout::Ty(field_ty) => {
cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| {
bug!(
- "failed to get layout for `{}`: {},\n\
- despite it being a field (#{}) of an existing layout: {:#?}",
- field_ty,
- e,
- i,
- this
+ "failed to get layout for `{field_ty}`: {e:?},\n\
+ despite it being a field (#{i}) of an existing layout: {this:#?}",
)
})
}
@@ -970,10 +981,8 @@ where
})
}
ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
- tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo {
- size: layout.size,
- align: layout.align.abi,
- safe: None,
+ tcx.layout_of(param_env.and(Ty::new_fn_ptr(tcx, fn_sig))).ok().map(|layout| {
+ PointeeInfo { size: layout.size, align: layout.align.abi, safe: None }
})
}
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
@@ -1101,12 +1110,11 @@ where
///
/// This takes two primary parameters:
///
-/// * `codegen_fn_attr_flags` - these are flags calculated as part of the
-/// codegen attrs for a defined function. For function pointers this set of
-/// flags is the empty set. This is only applicable for Rust-defined
-/// functions, and generally isn't needed except for small optimizations where
-/// we try to say a function which otherwise might look like it could unwind
-/// doesn't actually unwind (such as for intrinsics and such).
+/// * `fn_def_id` - the `DefId` of the function. If this is provided then we can
+/// determine more precisely if the function can unwind. If this is not provided
+/// then we will only infer whether the function can unwind or not based on the
+/// ABI of the function. For example, a function marked with `#[rustc_nounwind]`
+/// is known to not unwind even if it's using Rust ABI.
///
/// * `abi` - this is the ABI that the function is defined with. This is the
/// primary factor for determining whether a function can unwind or not.
@@ -1138,11 +1146,6 @@ where
/// aborts the process.
/// * This affects whether functions have the LLVM `nounwind` attribute, which
/// affects various optimizations and codegen.
-///
-/// FIXME: this is actually buggy with respect to Rust functions. Rust functions
-/// compiled with `-Cpanic=unwind` and referenced from another crate compiled
-/// with `-Cpanic=abort` will look like they can't unwind when in fact they
-/// might (from a foreign exception or similar).
#[inline]
#[tracing::instrument(level = "debug", skip(tcx))]
pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
@@ -1250,33 +1253,18 @@ pub enum FnAbiError<'tcx> {
AdjustForForeignAbi(call::AdjustForForeignAbiError),
}
-impl<'tcx> From<LayoutError<'tcx>> for FnAbiError<'tcx> {
- fn from(err: LayoutError<'tcx>) -> Self {
- Self::Layout(err)
- }
-}
-
-impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> {
- fn from(err: call::AdjustForForeignAbiError) -> Self {
- Self::AdjustForForeignAbi(err)
- }
-}
-
-impl<'tcx> fmt::Display for FnAbiError<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> {
+ fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
match self {
- Self::Layout(err) => err.fmt(f),
- Self::AdjustForForeignAbi(err) => err.fmt(f),
+ Self::Layout(e) => e.into_diagnostic().into_diagnostic(handler),
+ Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported {
+ arch,
+ abi,
+ }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(handler),
}
}
}
-impl IntoDiagnostic<'_, !> for FnAbiError<'_> {
- fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
- handler.struct_fatal(self.to_string())
- }
-}
-
// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
// just for error handling.
#[derive(Debug)]
@@ -1324,7 +1312,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
let tcx = self.tcx().at(span);
MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
- |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
+ |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
))
}
@@ -1351,7 +1339,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
// However, we don't do this early in order to avoid calling
// `def_span` unconditionally (which may have a perf penalty).
let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
- self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
+ self.handle_fn_abi_err(
+ *err,
+ span,
+ FnAbiRequest::OfInstance { instance, extra_args },
+ )
}),
)
}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a8d0dca37..aa8bfd317 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -53,7 +53,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, ExpnKind, Span};
use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
pub use rustc_target::abi::{ReprFlags, ReprOptions};
-use rustc_type_ir::WithCachedTypeInfo;
pub use subst::*;
pub use vtable::*;
@@ -67,6 +66,10 @@ use std::{fmt, str};
pub use crate::ty::diagnostics::*;
pub use rustc_type_ir::AliasKind::*;
+pub use rustc_type_ir::ConstKind::{
+ Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
+ Placeholder as PlaceholderCt, Unevaluated, Value,
+};
pub use rustc_type_ir::DynKind::*;
pub use rustc_type_ir::InferTy::*;
pub use rustc_type_ir::RegionKind::*;
@@ -82,7 +85,7 @@ pub use self::closure::{
CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
- Const, ConstData, ConstInt, ConstKind, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
+ Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
@@ -94,7 +97,7 @@ pub use self::rvalue_scopes::RvalueScopes;
pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
- BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
+ BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstKind, ConstVid,
EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate,
@@ -145,6 +148,7 @@ mod opaque_types;
mod parameterized;
mod rvalue_scopes;
mod structural_impls;
+#[cfg_attr(not(bootstrap), allow(hidden_glob_reexports))]
mod sty;
mod typeck_results;
@@ -456,6 +460,11 @@ impl ty::EarlyBoundRegion {
}
}
+/// A statement that can be proven by a trait solver. This includes things that may
+/// show up in where clauses, such as trait predicates and projection predicates,
+/// and also things that are emitted as part of type checking such as `ObjectSafe`
+/// predicate which is emitted when a type is coerced to a trait object.
+///
/// Use this rather than `PredicateKind`, whenever possible.
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value]
@@ -487,11 +496,11 @@ impl<'tcx> Predicate<'tcx> {
let kind = self
.kind()
.map_bound(|kind| match kind {
- PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness,
polarity,
- })) => Some(PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness,
polarity: polarity.flip()?,
@@ -505,10 +514,10 @@ impl<'tcx> Predicate<'tcx> {
}
pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
- if let PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
+ if let PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder()
&& constness != BoundConstness::NotConst
{
- self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(Clause::Trait(TraitPredicate {
+ self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
trait_ref,
constness: BoundConstness::NotConst,
polarity,
@@ -520,10 +529,10 @@ impl<'tcx> Predicate<'tcx> {
#[instrument(level = "debug", skip(tcx), ret)]
pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
match self.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
tcx.trait_is_coinductive(data.def_id())
}
- ty::PredicateKind::WellFormed(_) => true,
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true,
_ => false,
}
}
@@ -536,21 +545,20 @@ impl<'tcx> Predicate<'tcx> {
#[inline]
pub fn allow_normalization(self) -> bool {
match self.kind().skip_binder() {
- PredicateKind::WellFormed(_) => false,
- PredicateKind::Clause(Clause::Trait(_))
- | PredicateKind::Clause(Clause::RegionOutlives(_))
- | PredicateKind::Clause(Clause::TypeOutlives(_))
- | PredicateKind::Clause(Clause::Projection(_))
- | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
+ PredicateKind::Clause(ClauseKind::Trait(_))
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(_))
+ | PredicateKind::Clause(ClauseKind::TypeOutlives(_))
+ | PredicateKind::Clause(ClauseKind::Projection(_))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::ObjectSafe(_)
| PredicateKind::ClosureKind(_, _, _)
| PredicateKind::Subtype(_)
| PredicateKind::Coerce(_)
- | PredicateKind::ConstEvaluatable(_)
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
| PredicateKind::ConstEquate(_, _)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(_) => true,
+ | PredicateKind::Ambiguous => true,
}
}
}
@@ -561,11 +569,77 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
}
}
+impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
+ }
+}
+
+/// A subset of predicates which can be assumed by the trait solver. They show up in
+/// an item's where clauses, hence the name `Clause`, and may either be user-written
+/// (such as traits) or may be inserted during lowering.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
+#[rustc_pass_by_value]
+pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
+
+impl<'tcx> Clause<'tcx> {
+ pub fn as_predicate(self) -> Predicate<'tcx> {
+ Predicate(self.0)
+ }
+
+ pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> {
+ self.0.internee.map_bound(|kind| match kind {
+ PredicateKind::Clause(clause) => clause,
+ _ => unreachable!(),
+ })
+ }
+
+ pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
+ Some(clause.rebind(trait_clause))
+ } else {
+ None
+ }
+ }
+
+ pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
+ Some(clause.rebind(projection_clause))
+ } else {
+ None
+ }
+ }
+
+ pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
+ Some(clause.rebind(o))
+ } else {
+ None
+ }
+ }
+
+ pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
+ let clause = self.kind();
+ if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
+ Some(clause.rebind(o))
+ } else {
+ None
+ }
+ }
+
+ pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ self.as_predicate().without_const(tcx).expect_clause()
+ }
+}
+
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
/// A clause is something that can appear in where bounds or be inferred
/// by implied bounds.
-pub enum Clause<'tcx> {
+pub enum ClauseKind<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
/// would be the type parameters.
@@ -584,16 +658,19 @@ pub enum Clause<'tcx> {
/// Ensures that a const generic argument to a parameter `const N: u8`
/// is of type `u8`.
ConstArgHasType(Const<'tcx>, Ty<'tcx>),
+
+ /// No syntax: `T` well-formed.
+ WellFormed(GenericArg<'tcx>),
+
+ /// Constant initializer must evaluate successfully.
+ ConstEvaluatable(ty::Const<'tcx>),
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum PredicateKind<'tcx> {
/// Prove a clause
- Clause(Clause<'tcx>),
-
- /// No syntax: `T` well-formed.
- WellFormed(GenericArg<'tcx>),
+ Clause(ClauseKind<'tcx>),
/// Trait must be object-safe.
ObjectSafe(DefId),
@@ -620,22 +697,14 @@ pub enum PredicateKind<'tcx> {
/// logic.
Coerce(CoercePredicate<'tcx>),
- /// Constant initializer must evaluate successfully.
- ConstEvaluatable(ty::Const<'tcx>),
-
/// Constants must be equal. The first component is the const that is expected.
ConstEquate(Const<'tcx>, Const<'tcx>),
- /// Represents a type found in the environment that we can use for implied bounds.
- ///
- /// Only used for Chalk.
- TypeWellFormedFromEnv(Ty<'tcx>),
-
/// A marker predicate that is always ambiguous.
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
Ambiguous,
- /// Separate from `Clause::Projection` which is used for normalization in new solver.
+ /// Separate from `ClauseKind::Projection` which is used for normalization in new solver.
/// This predicate requires two terms to be equal to eachother.
///
/// Only used for new solver
@@ -672,7 +741,7 @@ pub struct CratePredicatesMap<'tcx> {
pub predicates: FxHashMap<DefId, &'tcx [(Clause<'tcx>, Span)]>,
}
-impl<'tcx> Predicate<'tcx> {
+impl<'tcx> Clause<'tcx> {
/// Performs a substitution suitable for going from a
/// poly-trait-ref to supertraits that must hold if that
/// poly-trait-ref holds. This is slightly different from a normal
@@ -682,7 +751,7 @@ impl<'tcx> Predicate<'tcx> {
self,
tcx: TyCtxt<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>,
- ) -> Predicate<'tcx> {
+ ) -> Clause<'tcx> {
// The interaction between HRTB and supertraits is not entirely
// obvious. Let me walk you (and myself) through an example.
//
@@ -764,11 +833,17 @@ impl<'tcx> Predicate<'tcx> {
let shifted_pred =
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
- let new = EarlyBinder(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
+ let new = EarlyBinder::bind(shifted_pred).subst(tcx, trait_ref.skip_binder().substs);
// 3) ['x] + ['b] -> ['x, 'b]
let bound_vars =
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
- tcx.reuse_or_mk_predicate(self, ty::Binder::bind_with_vars(new, bound_vars))
+
+ // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here?
+ tcx.reuse_or_mk_predicate(
+ self.as_predicate(),
+ ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
+ )
+ .expect_clause()
}
}
@@ -1189,13 +1264,41 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
}
}
-impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
+impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
}
}
+impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause))
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
+ self.as_predicate()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause()
+ }
+}
+
impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@@ -1203,6 +1306,29 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
}
}
+impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
+ self.without_const()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
+ }
+}
+
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
@@ -1211,6 +1337,14 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
}
}
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
+ #[inline(always)]
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
+ pred.to_predicate(tcx)
+ }
+}
+
impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
#[inline(always)]
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
@@ -1236,31 +1370,45 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for TraitPredicate<'tcx>
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)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(|p| PredicateKind::Clause(Clause::TypeOutlives(p))).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::TypeOutlives(p))).to_predicate(tcx)
}
}
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.map_bound(|p| PredicateKind::Clause(Clause::Projection(p))).to_predicate(tcx)
+ self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx)
+ }
+}
+
+impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
+ fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
+ let p: Predicate<'tcx> = self.to_predicate(tcx);
+ p.expect_clause()
}
}
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx)
+ PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
}
}
@@ -1268,63 +1416,76 @@ impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Clause(Clause::Trait(t)) => Some(predicate.rebind(t)),
- PredicateKind::Clause(Clause::Projection(..))
- | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
+ PredicateKind::Clause(ClauseKind::Projection(..))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::Clause(Clause::RegionOutlives(..))
- | PredicateKind::WellFormed(..)
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
+ | PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::Clause(Clause::TypeOutlives(..))
- | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(..) => None,
+ | PredicateKind::Ambiguous => None,
}
}
pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Clause(Clause::Projection(t)) => Some(predicate.rebind(t)),
- PredicateKind::Clause(Clause::Trait(..))
- | PredicateKind::Clause(Clause::ConstArgHasType(..))
+ PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
+ PredicateKind::Clause(ClauseKind::Trait(..))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::Clause(Clause::RegionOutlives(..))
- | PredicateKind::WellFormed(..)
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
+ | PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::Clause(Clause::TypeOutlives(..))
- | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(..) => None,
+ | PredicateKind::Ambiguous => None,
}
}
pub fn to_opt_type_outlives(self) -> Option<PolyTypeOutlivesPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Clause(Clause::TypeOutlives(data)) => Some(predicate.rebind(data)),
- PredicateKind::Clause(Clause::Trait(..))
- | PredicateKind::Clause(Clause::ConstArgHasType(..))
- | PredicateKind::Clause(Clause::Projection(..))
+ PredicateKind::Clause(ClauseKind::TypeOutlives(data)) => Some(predicate.rebind(data)),
+ PredicateKind::Clause(ClauseKind::Trait(..))
+ | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
+ | PredicateKind::Clause(ClauseKind::Projection(..))
| PredicateKind::AliasRelate(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
- | PredicateKind::Clause(Clause::RegionOutlives(..))
- | PredicateKind::WellFormed(..)
+ | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
+ | PredicateKind::Clause(ClauseKind::WellFormed(..))
| PredicateKind::ObjectSafe(..)
| PredicateKind::ClosureKind(..)
- | PredicateKind::ConstEvaluatable(..)
+ | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
| PredicateKind::ConstEquate(..)
- | PredicateKind::Ambiguous
- | PredicateKind::TypeWellFormedFromEnv(..) => None,
+ | PredicateKind::Ambiguous => None,
+ }
+ }
+
+ /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`.
+ pub fn as_clause(self) -> Option<Clause<'tcx>> {
+ match self.kind().skip_binder() {
+ PredicateKind::Clause(..) => Some(self.expect_clause()),
+ _ => None,
+ }
+ }
+
+ /// Assert that the predicate is a clause.
+ pub fn expect_clause(self) -> Clause<'tcx> {
+ match self.kind().skip_binder() {
+ PredicateKind::Clause(..) => Clause(self.0),
+ _ => bug!("{self} is not a clause"),
}
}
}
@@ -1350,7 +1511,7 @@ impl<'tcx> Predicate<'tcx> {
/// [usize:Bar<isize>]]`.
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct InstantiatedPredicates<'tcx> {
- pub predicates: Vec<Predicate<'tcx>>,
+ pub predicates: Vec<Clause<'tcx>>,
pub spans: Vec<Span>,
}
@@ -1369,9 +1530,9 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
}
impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
- type Item = (Predicate<'tcx>, Span);
+ type Item = (Clause<'tcx>, Span);
- type IntoIter = std::iter::Zip<std::vec::IntoIter<Predicate<'tcx>>, std::vec::IntoIter<Span>>;
+ type IntoIter = std::iter::Zip<std::vec::IntoIter<Clause<'tcx>>, std::vec::IntoIter<Span>>;
fn into_iter(self) -> Self::IntoIter {
debug_assert_eq!(self.predicates.len(), self.spans.len());
@@ -1380,10 +1541,10 @@ impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> {
}
impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> {
- type Item = (Predicate<'tcx>, Span);
+ type Item = (Clause<'tcx>, Span);
type IntoIter = std::iter::Zip<
- std::iter::Copied<std::slice::Iter<'a, Predicate<'tcx>>>,
+ std::iter::Copied<std::slice::Iter<'a, Clause<'tcx>>>,
std::iter::Copied<std::slice::Iter<'a, Span>>,
>;
@@ -1496,7 +1657,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
/// identified by both a universe, as well as a name residing within that universe. Distinct bound
/// regions/types/consts within the same universe simply have an unknown relationship to one
/// another.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct Placeholder<T> {
pub universe: UniverseIndex,
@@ -1533,7 +1694,7 @@ pub struct ParamEnv<'tcx> {
/// want `Reveal::All`.
///
/// Note: This is packed, use the reveal() method to access it.
- packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>,
+ packed: CopyTaggedPtr<&'tcx List<Clause<'tcx>>, ParamTag, true>,
}
#[derive(Copy, Clone)]
@@ -1599,7 +1760,7 @@ impl<'tcx> ParamEnv<'tcx> {
}
#[inline]
- pub fn caller_bounds(self) -> &'tcx List<Predicate<'tcx>> {
+ pub fn caller_bounds(self) -> &'tcx List<Clause<'tcx>> {
self.packed.pointer()
}
@@ -1633,7 +1794,7 @@ impl<'tcx> ParamEnv<'tcx> {
/// Construct a trait environment with the given set of predicates.
#[inline]
pub fn new(
- caller_bounds: &'tcx List<Predicate<'tcx>>,
+ caller_bounds: &'tcx List<Clause<'tcx>>,
reveal: Reveal,
constness: hir::Constness,
) -> Self {
@@ -1874,6 +2035,22 @@ impl VariantDef {
&self.fields[FieldIdx::from_u32(0)]
}
+
+ /// Returns the last field in this variant, if present.
+ #[inline]
+ pub fn tail_opt(&self) -> Option<&FieldDef> {
+ self.fields.raw.last()
+ }
+
+ /// Returns the last field in this variant.
+ ///
+ /// # Panics
+ ///
+ /// Panics, if the variant has no fields.
+ #[inline]
+ pub fn tail(&self) -> &FieldDef {
+ self.tail_opt().expect("expected unsized ADT to have a tail field")
+ }
}
impl PartialEq for VariantDef {
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
index 1b336b7bf..b10921eff 100644
--- a/compiler/rustc_middle/src/ty/opaque_types.rs
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -141,7 +141,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
)
.emit();
- self.interner().mk_re_error(e)
+ ty::Region::new_error(self.interner(), e)
}
}
}
@@ -150,17 +150,17 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
match *ty.kind() {
ty::Closure(def_id, substs) => {
let substs = self.fold_closure_substs(def_id, substs);
- self.tcx.mk_closure(def_id, substs)
+ Ty::new_closure(self.tcx, def_id, substs)
}
ty::Generator(def_id, substs, movability) => {
let substs = self.fold_closure_substs(def_id, substs);
- self.tcx.mk_generator(def_id, substs, movability)
+ Ty::new_generator(self.tcx, def_id, substs, movability)
}
ty::GeneratorWitnessMIR(def_id, substs) => {
let substs = self.fold_closure_substs(def_id, substs);
- self.tcx.mk_generator_witness_mir(def_id, substs)
+ Ty::new_generator_witness_mir(self.tcx, def_id, substs)
}
ty::Param(param) => {
@@ -186,7 +186,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
.emit();
}
- self.interner().ty_error_misc()
+ Ty::new_misc_error(self.tcx)
}
}
}
@@ -216,7 +216,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
})
.emit_unless(self.ignore_errors);
- self.interner().const_error(ct.ty(), guar)
+ ty::Const::new_error(self.tcx, guar, ct.ty())
}
}
}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index a2e77d9cd..cc2b26a5e 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -73,6 +73,7 @@ trivially_parameterized_over_tcx! {
ty::fast_reject::SimplifiedType,
rustc_ast::Attribute,
rustc_ast::DelimArgs,
+ rustc_ast::expand::StrippedCfgItem<rustc_hir::def_id::DefIndex>,
rustc_attr::ConstStability,
rustc_attr::DefaultBodyStability,
rustc_attr::Deprecation,
@@ -128,5 +129,6 @@ parameterized_over_tcx! {
ty::Const,
ty::Predicate,
ty::Clause,
+ ty::ClauseKind,
ty::GeneratorDiagnosticData,
}
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 64e7480e6..2de0a3f75 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -123,7 +123,7 @@ pub trait Printer<'tcx>: Sized {
impl_trait_ref.map(|i| i.subst(self.tcx(), substs)),
)
} else {
- (self_ty.0, impl_trait_ref.map(|i| i.0))
+ (self_ty.subst_identity(), impl_trait_ref.map(|i| i.subst_identity()))
};
self.print_impl_path(def_id, substs, self_ty, impl_trait_ref)
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index d6c88ea96..96cf36eb9 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -94,6 +94,10 @@ macro_rules! define_helper {
$tl.with(|c| c.set(self.0))
}
}
+
+ pub fn $name() -> bool {
+ $tl.with(|c| c.get())
+ }
)+
}
}
@@ -184,7 +188,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
/// Convenience wrapper for `highlighting_region`.
pub fn highlighting_region_vid(&mut self, vid: ty::RegionVid, number: usize) {
- self.highlighting_region(self.tcx.mk_re_var(vid), number)
+ self.highlighting_region(ty::Region::new_var(self.tcx, vid), number)
}
/// Returns `Some(n)` with the number to use for the given region, if any.
@@ -676,7 +680,7 @@ pub trait PrettyPrinter<'tcx>:
p!(")")
}
ty::FnDef(def_id, substs) => {
- if NO_QUERIES.with(|q| q.get()) {
+ if with_no_queries() {
p!(print_def_path(def_id, substs));
} else {
let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
@@ -685,29 +689,30 @@ pub trait PrettyPrinter<'tcx>:
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::Infer(infer_ty) => {
- let verbose = self.should_print_verbose();
+ if self.should_print_verbose() {
+ p!(write("{:?}", ty.kind()));
+ return Ok(self);
+ }
+
if let ty::TyVar(ty_vid) = infer_ty {
if let Some(name) = self.ty_infer_name(ty_vid) {
p!(write("{}", name))
} else {
- if verbose {
- p!(write("{:?}", infer_ty))
- } else {
- p!(write("{}", infer_ty))
- }
+ p!(write("{}", infer_ty))
}
} else {
- if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
+ p!(write("{}", infer_ty))
}
}
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 => debug_bound_var(&mut self, debruijn, bound_ty.var)?,
+ ty::BoundTyKind::Anon => {
+ rustc_type_ir::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)),
- false => p!(write("{}", s)),
+ true => p!(write("{:?}", ty.kind())),
+ false => p!(write("{s}")),
},
},
ty::Adt(def, substs) => {
@@ -730,8 +735,8 @@ pub trait PrettyPrinter<'tcx>:
ty::Foreign(def_id) => {
p!(print_def_path(def_id, &[]));
}
- ty::Alias(ty::Projection | ty::Inherent, ref data) => {
- if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
+ ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => {
+ if !(self.should_print_verbose() || with_no_queries())
&& self.tcx().is_impl_trait_in_trait(data.def_id)
{
return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
@@ -740,10 +745,11 @@ pub trait PrettyPrinter<'tcx>:
}
}
ty::Placeholder(placeholder) => match placeholder.bound.kind {
- ty::BoundTyKind::Anon => {
- debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound.var)?;
- }
- ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
+ ty::BoundTyKind::Anon => p!(write("{placeholder:?}")),
+ ty::BoundTyKind::Param(_, name) => match self.should_print_verbose() {
+ true => p!(write("{:?}", ty.kind())),
+ false => p!(write("{name}")),
+ },
},
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// We use verbose printing in 'NO_QUERIES' mode, to
@@ -777,7 +783,7 @@ pub trait PrettyPrinter<'tcx>:
return Ok(self);
}
_ => {
- if NO_QUERIES.with(|q| q.get()) {
+ if with_no_queries() {
p!(print_def_path(def_id, &[]));
return Ok(self);
} else {
@@ -926,7 +932,7 @@ pub trait PrettyPrinter<'tcx>:
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
+ ty::ClauseKind::Trait(pred) => {
let trait_ref = bound_predicate.rebind(pred.trait_ref);
// Don't print + Sized, but rather + ?Sized if absent.
@@ -937,7 +943,7 @@ pub trait PrettyPrinter<'tcx>:
self.insert_trait_and_projection(trait_ref, None, &mut traits, &mut fn_traits);
}
- ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+ ty::ClauseKind::Projection(pred) => {
let proj_ref = bound_predicate.rebind(pred);
let trait_ref = proj_ref.required_poly_trait_ref(tcx);
@@ -951,7 +957,7 @@ pub trait PrettyPrinter<'tcx>:
&mut fn_traits,
);
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => {
+ ty::ClauseKind::TypeOutlives(outlives) => {
lifetimes.push(outlives.1);
}
_ => {}
@@ -1222,7 +1228,7 @@ pub trait PrettyPrinter<'tcx>:
// in order to place the projections inside the `<...>`.
if !resugared {
// Use a type that can't appear in defaults of type parameters.
- let dummy_cx = cx.tcx().mk_fresh_ty(0);
+ let dummy_cx = Ty::new_fresh(cx.tcx(), 0);
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
let args = cx
@@ -1372,11 +1378,9 @@ pub trait PrettyPrinter<'tcx>:
}
ty::ConstKind::Bound(debruijn, bound_var) => {
- debug_bound_var(&mut self, debruijn, bound_var)?
+ rustc_type_ir::debug_bound_var(&mut self, debruijn, bound_var)?
}
- ty::ConstKind::Placeholder(placeholder) => {
- debug_placeholder_var(&mut self, placeholder.universe, placeholder.bound)?;
- },
+ ty::ConstKind::Placeholder(placeholder) => p!(write("{placeholder:?}")),
// FIXME(generic_const_exprs):
// write out some legible representation of an abstract const?
ty::ConstKind::Expr(_) => p!("{{const expr}}"),
@@ -1389,11 +1393,12 @@ pub trait PrettyPrinter<'tcx>:
self,
scalar: Scalar,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
match scalar {
- Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty, print_ty),
- Scalar::Int(int) => self.pretty_print_const_scalar_int(int, ty, print_ty),
+ Scalar::Ptr(ptr, _size) => self.pretty_print_const_scalar_ptr(ptr, ty),
+ Scalar::Int(int) => {
+ self.pretty_print_const_scalar_int(int, ty, /* print_ty */ true)
+ }
}
}
@@ -1401,7 +1406,6 @@ pub trait PrettyPrinter<'tcx>:
mut self,
ptr: Pointer,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
define_scoped_cx!(self);
@@ -1455,7 +1459,7 @@ pub trait PrettyPrinter<'tcx>:
_ => {}
}
// Any pointer values not covered by a branch above
- self = self.pretty_print_const_pointer(ptr, ty, print_ty)?;
+ self = self.pretty_print_const_pointer(ptr, ty)?;
Ok(self)
}
@@ -1523,24 +1527,18 @@ pub trait PrettyPrinter<'tcx>:
/// This is overridden for MIR printing because we only want to hide alloc ids from users, not
/// from MIR where it is actually useful.
fn pretty_print_const_pointer<Prov: Provenance>(
- mut self,
+ self,
_: Pointer<Prov>,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
- if print_ty {
- self.typed_value(
- |mut this| {
- this.write_str("&_")?;
- Ok(this)
- },
- |this| this.print_type(ty),
- ": ",
- )
- } else {
- self.write_str("&_")?;
- Ok(self)
- }
+ self.typed_value(
+ |mut this| {
+ this.write_str("&_")?;
+ Ok(this)
+ },
+ |this| this.print_type(ty),
+ ": ",
+ )
}
fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
@@ -1597,7 +1595,8 @@ pub trait PrettyPrinter<'tcx>:
}
// Aggregates, printed as array/tuple/struct/variant construction syntax.
(ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
- let contents = self.tcx().destructure_const(self.tcx().mk_const(valtree, ty));
+ let contents =
+ self.tcx().destructure_const(ty::Const::new_value(self.tcx(), valtree, ty));
let fields = contents.fields.iter().copied();
match *ty.kind() {
ty::Array(..) => {
@@ -1746,7 +1745,8 @@ impl DerefMut for FmtPrinter<'_, '_> {
impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, ns: Namespace) -> Self {
- Self::new_with_limit(tcx, ns, tcx.type_length_limit())
+ let limit = if with_no_queries() { Limit::new(1048576) } else { tcx.type_length_limit() };
+ Self::new_with_limit(tcx, ns, limit)
}
pub fn new_with_limit(tcx: TyCtxt<'tcx>, ns: Namespace, type_length_limit: Limit) -> Self {
@@ -2150,7 +2150,6 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
self,
p: Pointer<Prov>,
ty: Ty<'tcx>,
- print_ty: bool,
) -> Result<Self::Const, Self::Error> {
let print = |mut this: Self| {
define_scoped_cx!(this);
@@ -2161,11 +2160,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
}
Ok(this)
};
- if print_ty {
- self.typed_value(print, |this| this.print_type(ty), ": ")
- } else {
- print(self)
- }
+ self.typed_value(print, |this| this.print_type(ty), ": ")
}
}
@@ -2303,7 +2298,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
};
if let ty::ReLateBound(debruijn1, br) = *region {
assert_eq!(debruijn1, ty::INNERMOST);
- self.tcx.mk_re_late_bound(self.current_index, br)
+ ty::Region::new_late_bound(self.tcx, self.current_index, br)
} else {
region
}
@@ -2415,7 +2410,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
- return tcx.mk_re_late_bound(
+ return ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
);
@@ -2430,7 +2426,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = ty::BrNamed(def_id, name);
- return tcx.mk_re_late_bound(
+ return ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
);
@@ -2443,7 +2440,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
if let Some(lt_idx) = lifetime_idx {
if lt_idx > binder_level_idx {
let kind = br.kind;
- return tcx.mk_re_late_bound(
+ return ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: br.var, kind },
);
@@ -2458,7 +2456,11 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
start_or_continue(&mut self, "for<", ", ");
do_continue(&mut self, name);
}
- tcx.mk_re_late_bound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })
+ ty::Region::new_late_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundRegion { var: br.var, kind },
+ )
};
let mut folder = RegionFolder {
tcx,
@@ -2734,7 +2736,7 @@ define_print_and_forward_display! {
ty::ExistentialTraitRef<'tcx> {
// Use a type that can't appear in defaults of type parameters.
- let dummy_self = cx.tcx().mk_fresh_ty(0);
+ let dummy_self = Ty::new_fresh(cx.tcx(),0);
let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
p!(print(trait_ref.print_only_trait_path()))
}
@@ -2857,20 +2859,35 @@ define_print_and_forward_display! {
p!(print(binder))
}
+ ty::Clause<'tcx> {
+ p!(print(self.kind()))
+ }
+
+ ty::ClauseKind<'tcx> {
+ match *self {
+ ty::ClauseKind::Trait(ref data) => {
+ p!(print(data))
+ }
+ ty::ClauseKind::RegionOutlives(predicate) => p!(print(predicate)),
+ ty::ClauseKind::TypeOutlives(predicate) => p!(print(predicate)),
+ ty::ClauseKind::Projection(predicate) => p!(print(predicate)),
+ ty::ClauseKind::ConstArgHasType(ct, ty) => {
+ p!("the constant `", print(ct), "` has type `", print(ty), "`")
+ },
+ ty::ClauseKind::WellFormed(arg) => p!(print(arg), " well-formed"),
+ ty::ClauseKind::ConstEvaluatable(ct) => {
+ p!("the constant `", print(ct), "` can be evaluated")
+ }
+ }
+ }
+
ty::PredicateKind<'tcx> {
match *self {
- ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
+ ty::PredicateKind::Clause(data) => {
p!(print(data))
}
ty::PredicateKind::Subtype(predicate) => p!(print(predicate)),
ty::PredicateKind::Coerce(predicate) => p!(print(predicate)),
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => p!(print(predicate)),
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => p!(print(predicate)),
- ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => p!(print(predicate)),
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
- p!("the constant `", print(ct), "` has type `", print(ty), "`")
- },
- ty::PredicateKind::WellFormed(arg) => p!(print(arg), " well-formed"),
ty::PredicateKind::ObjectSafe(trait_def_id) => {
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
@@ -2879,15 +2896,9 @@ define_print_and_forward_display! {
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind)
),
- ty::PredicateKind::ConstEvaluatable(ct) => {
- p!("the constant `", print(ct), "` can be evaluated")
- }
ty::PredicateKind::ConstEquate(c1, c2) => {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
- ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
- p!("the type `", print(ty), "` is found in the environment")
- }
ty::PredicateKind::Ambiguous => p!("ambiguous"),
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
}
@@ -2980,7 +2991,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
///
/// The implementation uses similar import discovery logic to that of 'use' suggestions.
///
-/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths`].
+/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
let mut map: FxHashMap<DefId, Symbol> = FxHashMap::default();
@@ -3065,27 +3076,3 @@ 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/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 3bbe6a23b..5741832c9 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -391,13 +391,13 @@ impl<'tcx> Relate<'tcx> for Ty<'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.
+#[instrument(level = "trace", skip(relation), ret)]
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!("structurally_relate_tys: a={:?} b={:?}", a, b);
match (a.kind(), b.kind()) {
(&ty::Infer(_), _) | (_, &ty::Infer(_)) => {
// The caller should handle these cases!
@@ -408,7 +408,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
bug!("bound types encountered in structurally_relate_tys")
}
- (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(tcx.ty_error(guar)),
+ (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(tcx, guar)),
(&ty::Never, _)
| (&ty::Char, _)
@@ -428,10 +428,10 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs)) if a_def == b_def => {
let substs = relation.relate_item_substs(a_def.did(), a_substs, b_substs)?;
- Ok(tcx.mk_adt(a_def, substs))
+ Ok(Ty::new_adt(tcx, a_def, substs))
}
- (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(tcx.mk_foreign(a_id)),
+ (&ty::Foreign(a_id), &ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(tcx, a_id)),
(&ty::Dynamic(a_obj, a_region, a_repr), &ty::Dynamic(b_obj, b_region, b_repr))
if a_repr == b_repr =>
@@ -439,7 +439,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
relation.relate(a_region, b_region)
})?;
- Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound, a_repr))
+ Ok(Ty::new_dynamic(tcx, relation.relate(a_obj, b_obj)?, region_bound, a_repr))
}
(&ty::Generator(a_id, a_substs, movability), &ty::Generator(b_id, b_substs, _))
@@ -449,7 +449,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// the (anonymous) type of the same generator expression. So
// all of their regions should be equated.
let substs = relation.relate(a_substs, b_substs)?;
- Ok(tcx.mk_generator(a_id, substs, movability))
+ Ok(Ty::new_generator(tcx, a_id, substs, movability))
}
(&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
@@ -459,7 +459,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
let b_types = b_types.map_bound(GeneratorWitness);
// Then remove the GeneratorWitness for the result
let types = relation.relate(a_types, b_types)?.map_bound(|witness| witness.0);
- Ok(tcx.mk_generator_witness(types))
+ Ok(Ty::new_generator_witness(tcx, types))
}
(&ty::GeneratorWitnessMIR(a_id, a_substs), &ty::GeneratorWitnessMIR(b_id, b_substs))
@@ -469,7 +469,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// the (anonymous) type of the same generator expression. So
// all of their regions should be equated.
let substs = relation.relate(a_substs, b_substs)?;
- Ok(tcx.mk_generator_witness_mir(a_id, substs))
+ Ok(Ty::new_generator_witness_mir(tcx, a_id, substs))
}
(&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {
@@ -477,12 +477,12 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
// the (anonymous) type of the same closure expression. So
// all of their regions should be equated.
let substs = relation.relate(a_substs, b_substs)?;
- Ok(tcx.mk_closure(a_id, &substs))
+ Ok(Ty::new_closure(tcx, a_id, &substs))
}
(&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
- Ok(tcx.mk_ptr(mt))
+ Ok(Ty::new_ptr(tcx, mt))
}
(&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
@@ -490,13 +490,13 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?;
- Ok(tcx.mk_ref(r, mt))
+ Ok(Ty::new_ref(tcx, r, mt))
}
(&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) => {
let t = relation.relate(a_t, b_t)?;
match relation.relate(sz_a, sz_b) {
- Ok(sz) => Ok(tcx.mk_array_with_const_len(t, sz)),
+ Ok(sz) => Ok(Ty::new_array_with_const_len(tcx, t, sz)),
Err(err) => {
// Check whether the lengths are both concrete/known values,
// but are unequal, for better diagnostics.
@@ -519,12 +519,15 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
(&ty::Slice(a_t), &ty::Slice(b_t)) => {
let t = relation.relate(a_t, b_t)?;
- Ok(tcx.mk_slice(t))
+ Ok(Ty::new_slice(tcx, t))
}
(&ty::Tuple(as_), &ty::Tuple(bs)) => {
if as_.len() == bs.len() {
- Ok(tcx.mk_tup_from_iter(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?)
+ Ok(Ty::new_tup_from_iter(
+ tcx,
+ iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)),
+ )?)
} else if !(as_.is_empty() || bs.is_empty()) {
Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len())))
} else {
@@ -536,25 +539,16 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
if a_def_id == b_def_id =>
{
let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
- Ok(tcx.mk_fn_def(a_def_id, substs))
+ Ok(Ty::new_fn_def(tcx, a_def_id, substs))
}
(&ty::FnPtr(a_fty), &ty::FnPtr(b_fty)) => {
let fty = relation.relate(a_fty, b_fty)?;
- Ok(tcx.mk_fn_ptr(fty))
- }
-
- // these two are already handled downstream in case of lazy normalization
- (&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
- let projection_ty = relation.relate(a_data, b_data)?;
- 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)))
+ Ok(Ty::new_fn_ptr(tcx, fty))
}
+ // The substs of opaque types may not all be invariant, so we have
+ // to treat them separately from other aliases.
(
&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, .. }),
@@ -568,7 +562,20 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
b_substs,
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
)?;
- Ok(tcx.mk_opaque(a_def_id, substs))
+ Ok(Ty::new_opaque(tcx, a_def_id, substs))
+ }
+
+ // Alias tend to mostly already be handled downstream due to normalization.
+ (&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This if can be removed
+ // and the assert uncommented once the new desugaring is stable.
+ if a_kind == b_kind {
+ let alias_ty = relation.relate(a_data, b_data)?;
+ // assert_eq!(a_kind, b_kind);
+ Ok(Ty::new_alias(tcx, a_kind, alias_ty))
+ } else {
+ Err(TypeError::Sorts(expected_found(relation, a, b)))
+ }
}
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
@@ -589,17 +596,6 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
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
- // relating them because during `normalize_param_env_or_error`,
- // we may relate an evaluated constant in a obligation against
- // an unnormalized (i.e. unevaluated) const in the param-env.
- // FIXME(generic_const_exprs): Once we always lazily unify unevaluated constants
- // these `eval` calls can be removed.
- if !tcx.features().generic_const_exprs {
- a = a.eval(tcx, relation.param_env());
- b = b.eval(tcx, relation.param_env());
- }
-
if tcx.features().generic_const_exprs {
a = tcx.expand_abstract_consts(a);
b = tcx.expand_abstract_consts(b);
@@ -634,7 +630,11 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
au.substs,
bu.substs,
)?;
- return Ok(tcx.mk_const(ty::UnevaluatedConst { def: au.def, substs }, a.ty()));
+ return Ok(ty::Const::new_unevaluated(
+ tcx,
+ ty::UnevaluatedConst { def: au.def, substs },
+ a.ty(),
+ ));
}
// Before calling relate on exprs, it is necessary to ensure that the nested consts
// have identical types.
@@ -675,8 +675,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
}
_ => return Err(TypeError::ConstMismatch(expected_found(r, a, b))),
};
- let kind = ty::ConstKind::Expr(expr);
- return Ok(tcx.mk_const(kind, a.ty()));
+ return Ok(ty::Const::new_expr(tcx, expr, a.ty()));
}
_ => false,
};
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 16cb6c910..7220d133f 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -11,6 +11,7 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
use rustc_hir::def::Namespace;
use rustc_index::{Idx, IndexVec};
use rustc_target::abi::TyAndLayout;
+use rustc_type_ir::ConstKind;
use std::fmt;
use std::ops::ControlFlow;
@@ -88,7 +89,35 @@ impl fmt::Debug for ty::FreeRegion {
impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())
+ let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = self;
+
+ write!(f, "{}", unsafety.prefix_str())?;
+ match abi {
+ rustc_target::spec::abi::Abi::Rust => (),
+ abi => write!(f, "extern \"{abi:?}\" ")?,
+ };
+
+ write!(f, "fn(")?;
+ let inputs = self.inputs();
+ match inputs.len() {
+ 0 if *c_variadic => write!(f, "...)")?,
+ 0 => write!(f, ")")?,
+ _ => {
+ for ty in &self.inputs()[0..(self.inputs().len() - 1)] {
+ write!(f, "{ty:?}, ")?;
+ }
+ write!(f, "{:?}", self.inputs().last().unwrap())?;
+ if *c_variadic {
+ write!(f, "...")?;
+ }
+ write!(f, ")")?;
+ }
+ }
+
+ match self.output().kind() {
+ ty::Tuple(list) if list.is_empty() => Ok(()),
+ _ => write!(f, " -> {:?}", self.output()),
+ }
}
}
@@ -145,12 +174,22 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:?}", self.kind())
+ }
+}
+
+impl<'tcx> fmt::Debug for ty::ClauseKind<'tcx> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- ty::Clause::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
- ty::Clause::Trait(ref a) => a.fmt(f),
- ty::Clause::RegionOutlives(ref pair) => pair.fmt(f),
- ty::Clause::TypeOutlives(ref pair) => pair.fmt(f),
- ty::Clause::Projection(ref pair) => pair.fmt(f),
+ ty::ClauseKind::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
+ ty::ClauseKind::Trait(ref a) => a.fmt(f),
+ ty::ClauseKind::RegionOutlives(ref pair) => pair.fmt(f),
+ ty::ClauseKind::TypeOutlives(ref pair) => pair.fmt(f),
+ ty::ClauseKind::Projection(ref pair) => pair.fmt(f),
+ ty::ClauseKind::WellFormed(ref data) => write!(f, "WellFormed({:?})", data),
+ ty::ClauseKind::ConstEvaluatable(ct) => {
+ write!(f, "ConstEvaluatable({ct:?})")
+ }
}
}
}
@@ -161,20 +200,13 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
ty::PredicateKind::Clause(ref a) => a.fmt(f),
ty::PredicateKind::Subtype(ref pair) => pair.fmt(f),
ty::PredicateKind::Coerce(ref pair) => pair.fmt(f),
- ty::PredicateKind::WellFormed(data) => write!(f, "WellFormed({:?})", data),
ty::PredicateKind::ObjectSafe(trait_def_id) => {
write!(f, "ObjectSafe({:?})", trait_def_id)
}
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
}
- ty::PredicateKind::ConstEvaluatable(ct) => {
- write!(f, "ConstEvaluatable({ct:?})")
- }
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
- ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
- write!(f, "TypeWellFormedFromEnv({:?})", ty)
- }
ty::PredicateKind::Ambiguous => write!(f, "Ambiguous"),
ty::PredicateKind::AliasRelate(t1, t2, dir) => {
write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
@@ -210,22 +242,21 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> {
}
}
-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:?}"),
+impl fmt::Debug for ty::BoundTy {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self.kind {
+ ty::BoundTyKind::Anon => write!(f, "{:?}", self.var),
+ ty::BoundTyKind::Param(_, sym) => write!(f, "{sym:?}"),
+ }
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for ty::Placeholder<T> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if self.universe == ty::UniverseIndex::ROOT {
+ write!(f, "!{:?}", self.bound)
+ } else {
+ write!(f, "!{}_{:?}", self.universe.index(), self.bound)
}
}
}
@@ -294,13 +325,14 @@ TrivialTypeTraversalAndLiftImpls! {
crate::ty::AliasRelationDirection,
crate::ty::Placeholder<crate::ty::BoundRegion>,
crate::ty::Placeholder<crate::ty::BoundTy>,
+ crate::ty::Placeholder<ty::BoundVar>,
crate::ty::ClosureKind,
crate::ty::FreeRegion,
crate::ty::InferTy,
crate::ty::IntVarValue,
crate::ty::ParamConst,
crate::ty::ParamTy,
- crate::ty::adjustment::PointerCast,
+ crate::ty::adjustment::PointerCoercion,
crate::ty::RegionVid,
crate::ty::UniverseIndex,
crate::ty::Variance,
@@ -310,7 +342,6 @@ TrivialTypeTraversalAndLiftImpls! {
interpret::Scalar,
rustc_target::abi::Size,
ty::BoundVar,
- ty::Placeholder<ty::BoundVar>,
}
TrivialTypeTraversalAndLiftImpls! {
@@ -609,12 +640,28 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
}
}
+// FIXME(clause): This is wonky
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
+ fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
+ }
+}
+
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_predicate(*self)
}
}
+impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
+ fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ visitor.visit_predicate(self.as_predicate())
+ }
+}
+
impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
self,
@@ -634,12 +681,12 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
}
}
-impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Predicate<'tcx>> {
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Clause<'tcx>> {
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_predicates(v))
+ ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
}
}
@@ -664,9 +711,20 @@ impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
folder: &mut F,
) -> Result<Self, F::Error> {
let ty = self.ty().try_fold_with(folder)?;
- let kind = self.kind().try_fold_with(folder)?;
+ let kind = match self.kind() {
+ ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?),
+ ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?),
+ ConstKind::Bound(d, b) => {
+ ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?)
+ }
+ ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?),
+ ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
+ ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
+ ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?),
+ ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
+ };
if ty != self.ty() || kind != self.kind() {
- Ok(folder.interner().mk_const(kind, ty))
+ Ok(folder.interner().mk_ct_from_kind(kind, ty))
} else {
Ok(self)
}
@@ -679,7 +737,19 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
self.ty().visit_with(visitor)?;
- self.kind().visit_with(visitor)
+ match self.kind() {
+ ConstKind::Param(p) => p.visit_with(visitor),
+ ConstKind::Infer(i) => i.visit_with(visitor),
+ ConstKind::Bound(d, b) => {
+ d.visit_with(visitor)?;
+ b.visit_with(visitor)
+ }
+ ConstKind::Placeholder(p) => p.visit_with(visitor),
+ ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
+ ConstKind::Value(v) => v.visit_with(visitor),
+ ConstKind::Error(e) => e.visit_with(visitor),
+ ConstKind::Expr(e) => e.visit_with(visitor),
+ }
}
}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index e6d51c4ec..94746fbdc 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -15,16 +15,18 @@ use hir::def::DefKind;
use polonius_engine::Atom;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::Interned;
-use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
+use rustc_error_messages::DiagnosticMessage;
+use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::LangItem;
use rustc_index::Idx;
use rustc_macros::HashStable;
use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
use rustc_target::spec::abi::{self, Abi};
+use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt;
@@ -33,13 +35,17 @@ use std::ops::{ControlFlow, Deref, Range};
use ty::util::IntTypeExt;
use rustc_type_ir::sty::TyKind::*;
-use rustc_type_ir::RegionKind as IrRegionKind;
use rustc_type_ir::TyKind as IrTyKind;
+use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind};
+use rustc_type_ir::{DynKind, RegionKind as IrRegionKind};
+
+use super::GenericParamDefKind;
// Re-export the `TyKind` from `rustc_type_ir` here for convenience
#[rustc_diagnostic_item = "TyKind"]
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
+pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
@@ -568,7 +574,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
let layout = tcx.generator_layout(def_id).unwrap();
layout.variant_fields.iter().map(move |variant| {
variant.iter().map(move |field| {
- ty::EarlyBinder(layout.field_tys[*field].ty).subst(tcx, self.substs)
+ ty::EarlyBinder::bind(layout.field_tys[*field].ty).subst(tcx, self.substs)
})
})
}
@@ -715,7 +721,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
/// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
/// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
/// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
- pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> {
+ pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> {
use crate::ty::ToPredicate;
match self.skip_binder() {
ExistentialPredicate::Trait(tr) => {
@@ -1007,7 +1013,10 @@ impl BoundVariableKind {
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(HashStable, Lift)]
-pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
+pub struct Binder<'tcx, T> {
+ value: T,
+ bound_vars: &'tcx List<BoundVariableKind>,
+}
impl<'tcx, T> Binder<'tcx, T>
where
@@ -1023,15 +1032,15 @@ where
!value.has_escaping_bound_vars(),
"`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
);
- Binder(value, ty::List::empty())
+ Binder { value, bound_vars: ty::List::empty() }
}
- pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
+ pub fn bind_with_vars(value: T, bound_vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(vars);
+ let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
- Binder(value, vars)
+ Binder { value, bound_vars }
}
}
@@ -1053,30 +1062,30 @@ impl<'tcx, T> Binder<'tcx, T> {
/// - comparing the self type of a PolyTraitRef to see if it is equal to
/// a type parameter `X`, since the type `X` does not reference any regions
pub fn skip_binder(self) -> T {
- self.0
+ self.value
}
pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
- self.1
+ self.bound_vars
}
pub fn as_ref(&self) -> Binder<'tcx, &T> {
- Binder(&self.0, self.1)
+ Binder { value: &self.value, bound_vars: self.bound_vars }
}
pub fn as_deref(&self) -> Binder<'tcx, &T::Target>
where
T: Deref,
{
- Binder(&self.0, self.1)
+ Binder { value: &self.value, bound_vars: self.bound_vars }
}
pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(&T) -> U,
{
- let value = f(&self.0);
- Binder(value, self.1)
+ let value = f(&self.value);
+ Binder { value, bound_vars: self.bound_vars }
}
pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U>
@@ -1090,12 +1099,13 @@ impl<'tcx, T> Binder<'tcx, T> {
where
F: FnOnce(T) -> U,
{
- let value = f(self.0);
+ let Binder { value, bound_vars } = self;
+ let value = f(value);
if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(self.1);
+ let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
- Binder(value, self.1)
+ Binder { value, bound_vars }
}
pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
@@ -1105,12 +1115,13 @@ impl<'tcx, T> Binder<'tcx, T> {
where
F: FnOnce(T) -> Result<U, E>,
{
- let value = f(self.0)?;
+ let Binder { value, bound_vars } = self;
+ let value = f(value)?;
if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(self.1);
+ let mut validator = ValidateBoundVars::new(bound_vars);
value.visit_with(&mut validator);
}
- Ok(Binder(value, self.1))
+ Ok(Binder { value, bound_vars })
}
/// Wraps a `value` in a binder, using the same bound variables as the
@@ -1126,11 +1137,7 @@ impl<'tcx, T> Binder<'tcx, T> {
where
U: TypeVisitable<TyCtxt<'tcx>>,
{
- if cfg!(debug_assertions) {
- let mut validator = ValidateBoundVars::new(self.bound_vars());
- value.visit_with(&mut validator);
- }
- Binder(value, self.1)
+ Binder::bind_with_vars(value, self.bound_vars)
}
/// Unwraps and returns the value within, but only if it contains
@@ -1147,7 +1154,7 @@ impl<'tcx, T> Binder<'tcx, T> {
where
T: TypeVisitable<TyCtxt<'tcx>>,
{
- if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
+ if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
/// Splits the contents into two things that share the same binder
@@ -1160,22 +1167,23 @@ impl<'tcx, T> Binder<'tcx, T> {
where
F: FnOnce(T) -> (U, V),
{
- let (u, v) = f(self.0);
- (Binder(u, self.1), Binder(v, self.1))
+ let Binder { value, bound_vars } = self;
+ let (u, v) = f(value);
+ (Binder { value: u, bound_vars }, Binder { value: v, bound_vars })
}
}
impl<'tcx, T> Binder<'tcx, Option<T>> {
pub fn transpose(self) -> Option<Binder<'tcx, T>> {
- let bound_vars = self.1;
- self.0.map(|v| Binder(v, bound_vars))
+ let Binder { value, bound_vars } = self;
+ value.map(|value| Binder { value, bound_vars })
}
}
impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
- let bound_vars = self.1;
- self.0.into_iter().map(|v| Binder(v, bound_vars))
+ let Binder { value, bound_vars } = self;
+ value.into_iter().map(|value| Binder { value, bound_vars })
}
}
@@ -1184,7 +1192,7 @@ where
T: IntoDiagnosticArg,
{
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- self.0.into_diagnostic_arg()
+ self.value.into_diagnostic_arg()
}
}
@@ -1231,12 +1239,13 @@ impl<'tcx> AliasTy<'tcx> {
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,
+ DefKind::TyAlias => ty::Weak,
kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
}
}
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- tcx.mk_alias(self.kind(tcx), self)
+ Ty::new_alias(tcx, self.kind(tcx), self)
}
}
@@ -1427,7 +1436,7 @@ impl<'tcx> ParamTy {
#[inline]
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- tcx.mk_ty_param(self.index, self.name)
+ Ty::new_param(tcx, self.index, self.name)
}
pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span {
@@ -1459,6 +1468,103 @@ impl ParamConst {
#[rustc_pass_by_value]
pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
+impl<'tcx> Region<'tcx> {
+ #[inline]
+ pub fn new_early_bound(
+ tcx: TyCtxt<'tcx>,
+ early_bound_region: ty::EarlyBoundRegion,
+ ) -> Region<'tcx> {
+ tcx.intern_region(ty::ReEarlyBound(early_bound_region))
+ }
+
+ #[inline]
+ pub fn new_late_bound(
+ tcx: TyCtxt<'tcx>,
+ debruijn: ty::DebruijnIndex,
+ bound_region: ty::BoundRegion,
+ ) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
+ && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize())
+ && let Some(re) = inner.get(var.as_usize()).copied()
+ {
+ re
+ } else {
+ tcx.intern_region(ty::ReLateBound(debruijn, bound_region))
+ }
+ }
+
+ #[inline]
+ pub fn new_free(
+ tcx: TyCtxt<'tcx>,
+ scope: DefId,
+ bound_region: ty::BoundRegionKind,
+ ) -> Region<'tcx> {
+ tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
+ }
+
+ #[inline]
+ pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.lifetimes
+ .re_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v)))
+ }
+
+ #[inline]
+ pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> {
+ tcx.intern_region(ty::RePlaceholder(placeholder))
+ }
+
+ /// Constructs a `RegionKind::ReError` region.
+ #[track_caller]
+ pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> {
+ tcx.intern_region(ty::ReError(reported))
+ }
+
+ /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` to ensure it
+ /// gets used.
+ #[track_caller]
+ pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> {
+ Region::new_error_with_message(
+ tcx,
+ DUMMY_SP,
+ "RegionKind::ReError constructed but no error reported",
+ )
+ }
+
+ /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` with the given
+ /// `msg` to ensure it gets used.
+ #[track_caller]
+ pub fn new_error_with_message<S: Into<MultiSpan>>(
+ tcx: TyCtxt<'tcx>,
+ span: S,
+ msg: &'static str,
+ ) -> Region<'tcx> {
+ let reported = tcx.sess.delay_span_bug(span, msg);
+ Region::new_error(tcx, reported)
+ }
+
+ /// Avoid this in favour of more specific `new_*` methods, where possible,
+ /// to avoid the cost of the `match`.
+ pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
+ match kind {
+ ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region),
+ ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region),
+ ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
+ Region::new_free(tcx, scope, bound_region)
+ }
+ ty::ReStatic => tcx.lifetimes.re_static,
+ ty::ReVar(vid) => Region::new_var(tcx, vid),
+ ty::RePlaceholder(region) => Region::new_placeholder(tcx, region),
+ ty::ReErased => tcx.lifetimes.re_erased,
+ ty::ReError(reported) => Region::new_error(tcx, reported),
+ }
+ }
+}
+
impl<'tcx> Deref for Region<'tcx> {
type Target = RegionKind<'tcx>;
@@ -1484,7 +1590,7 @@ pub struct EarlyBoundRegion {
impl fmt::Debug for EarlyBoundRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{}, {}", self.index, self.name)
+ write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name)
}
}
@@ -1511,10 +1617,11 @@ impl Atom for RegionVid {
rustc_index::newtype_index! {
#[derive(HashStable)]
+ #[debug_format = "{}"]
pub struct BoundVar {}
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct BoundTy {
pub var: BoundVar,
@@ -1770,6 +1877,390 @@ impl<'tcx> Region<'tcx> {
}
}
+/// Constructors for `Ty`
+impl<'tcx> Ty<'tcx> {
+ // Avoid this in favour of more specific `new_*` methods, where possible.
+ #[allow(rustc::usage_of_ty_tykind)]
+ #[inline]
+ pub fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> {
+ tcx.mk_ty_from_kind(st)
+ }
+
+ #[inline]
+ pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Ty<'tcx> {
+ Ty::new(tcx, TyKind::Infer(infer))
+ }
+
+ #[inline]
+ pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .ty_vars
+ .get(v.as_usize())
+ .copied()
+ .unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v))))
+ }
+
+ #[inline]
+ pub fn new_int_var(tcx: TyCtxt<'tcx>, v: ty::IntVid) -> Ty<'tcx> {
+ Ty::new_infer(tcx, IntVar(v))
+ }
+
+ #[inline]
+ pub fn new_float_var(tcx: TyCtxt<'tcx>, v: ty::FloatVid) -> Ty<'tcx> {
+ Ty::new_infer(tcx, FloatVar(v))
+ }
+
+ #[inline]
+ pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .fresh_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n)))
+ }
+
+ #[inline]
+ pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .fresh_int_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n)))
+ }
+
+ #[inline]
+ pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
+ // Use a pre-interned one when possible.
+ tcx.types
+ .fresh_float_tys
+ .get(n as usize)
+ .copied()
+ .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n)))
+ }
+
+ #[inline]
+ pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> {
+ tcx.mk_ty_from_kind(Param(ParamTy { index, name }))
+ }
+
+ #[inline]
+ pub fn new_bound(
+ tcx: TyCtxt<'tcx>,
+ index: ty::DebruijnIndex,
+ bound_ty: ty::BoundTy,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, Bound(index, bound_ty))
+ }
+
+ #[inline]
+ pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
+ Ty::new(tcx, Placeholder(placeholder))
+ }
+
+ #[inline]
+ pub fn new_alias(
+ tcx: TyCtxt<'tcx>,
+ kind: ty::AliasKind,
+ alias_ty: ty::AliasTy<'tcx>,
+ ) -> Ty<'tcx> {
+ debug_assert_matches!(
+ (kind, tcx.def_kind(alias_ty.def_id)),
+ (ty::Opaque, DefKind::OpaqueTy)
+ | (ty::Projection | ty::Inherent, DefKind::AssocTy)
+ | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
+ | (ty::Weak, DefKind::TyAlias)
+ );
+ Ty::new(tcx, Alias(kind, alias_ty))
+ }
+
+ #[inline]
+ pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
+ Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, substs))
+ }
+
+ /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed`
+ pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Ty<'tcx> {
+ Ty::new(tcx, Error(reported))
+ }
+
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
+ #[track_caller]
+ pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported")
+ }
+
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
+ /// ensure it gets used.
+ #[track_caller]
+ pub fn new_error_with_message<S: Into<MultiSpan>>(
+ tcx: TyCtxt<'tcx>,
+ span: S,
+ msg: impl Into<DiagnosticMessage>,
+ ) -> Ty<'tcx> {
+ let reported = tcx.sess.delay_span_bug(span, msg);
+ Ty::new(tcx, Error(reported))
+ }
+
+ #[inline]
+ pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> {
+ use ty::IntTy::*;
+ match i {
+ Isize => tcx.types.isize,
+ I8 => tcx.types.i8,
+ I16 => tcx.types.i16,
+ I32 => tcx.types.i32,
+ I64 => tcx.types.i64,
+ I128 => tcx.types.i128,
+ }
+ }
+
+ #[inline]
+ pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> {
+ use ty::UintTy::*;
+ match ui {
+ Usize => tcx.types.usize,
+ U8 => tcx.types.u8,
+ U16 => tcx.types.u16,
+ U32 => tcx.types.u32,
+ U64 => tcx.types.u64,
+ U128 => tcx.types.u128,
+ }
+ }
+
+ #[inline]
+ pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> {
+ use ty::FloatTy::*;
+ match f {
+ F32 => tcx.types.f32,
+ F64 => tcx.types.f64,
+ }
+ }
+
+ #[inline]
+ pub fn new_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, Ref(r, tm.ty, tm.mutbl))
+ }
+
+ #[inline]
+ pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
+ }
+
+ #[inline]
+ pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Not })
+ }
+
+ #[inline]
+ pub fn new_ptr(tcx: TyCtxt<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, RawPtr(tm))
+ }
+
+ #[inline]
+ pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Mut })
+ }
+
+ #[inline]
+ pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Not })
+ }
+
+ #[inline]
+ pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, Adt(def, substs))
+ }
+
+ #[inline]
+ pub fn new_foreign(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
+ Ty::new(tcx, Foreign(def_id))
+ }
+
+ #[inline]
+ pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
+ Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n)))
+ }
+
+ #[inline]
+ pub fn new_array_with_const_len(
+ tcx: TyCtxt<'tcx>,
+ ty: Ty<'tcx>,
+ ct: ty::Const<'tcx>,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, Array(ty, ct))
+ }
+
+ #[inline]
+ pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, Slice(ty))
+ }
+
+ #[inline]
+ pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
+ if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) }
+ }
+
+ pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output
+ where
+ I: Iterator<Item = T>,
+ T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
+ {
+ T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts))
+ }
+
+ #[inline]
+ pub fn new_fn_def(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ let substs = tcx.check_and_mk_substs(def_id, substs);
+ Ty::new(tcx, FnDef(def_id, substs))
+ }
+
+ #[inline]
+ pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
+ Ty::new(tcx, FnPtr(fty))
+ }
+
+ #[inline]
+ pub fn new_dynamic(
+ tcx: TyCtxt<'tcx>,
+ obj: &'tcx List<PolyExistentialPredicate<'tcx>>,
+ reg: ty::Region<'tcx>,
+ repr: DynKind,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, Dynamic(obj, reg, repr))
+ }
+
+ #[inline]
+ pub fn new_projection(
+ tcx: TyCtxt<'tcx>,
+ item_def_id: DefId,
+ substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
+ ) -> Ty<'tcx> {
+ Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, substs))
+ }
+
+ #[inline]
+ pub fn new_closure(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ closure_substs: SubstsRef<'tcx>,
+ ) -> Ty<'tcx> {
+ debug_assert_eq!(
+ closure_substs.len(),
+ tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3,
+ "closure constructed with incorrect substitutions"
+ );
+ Ty::new(tcx, Closure(def_id, closure_substs))
+ }
+
+ #[inline]
+ pub fn new_generator(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+ generator_substs: SubstsRef<'tcx>,
+ movability: hir::Movability,
+ ) -> Ty<'tcx> {
+ debug_assert_eq!(
+ generator_substs.len(),
+ tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5,
+ "generator constructed with incorrect number of substitutions"
+ );
+ Ty::new(tcx, Generator(def_id, generator_substs, movability))
+ }
+
+ #[inline]
+ pub fn new_generator_witness(
+ tcx: TyCtxt<'tcx>,
+ types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, GeneratorWitness(types))
+ }
+
+ #[inline]
+ pub fn new_generator_witness_mir(
+ tcx: TyCtxt<'tcx>,
+ id: DefId,
+ substs: SubstsRef<'tcx>,
+ ) -> Ty<'tcx> {
+ Ty::new(tcx, GeneratorWitnessMIR(id, substs))
+ }
+
+ // misc
+
+ #[inline]
+ pub fn new_unit(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ tcx.types.unit
+ }
+
+ #[inline]
+ pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_)
+ }
+
+ #[inline]
+ pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ if tcx.features().never_type_fallback { tcx.types.never } else { tcx.types.unit }
+ }
+
+ // lang and diagnostic tys
+
+ fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
+ let adt_def = tcx.adt_def(wrapper_def_id);
+ let substs =
+ InternalSubsts::for_item(tcx, wrapper_def_id, |param, substs| match param.kind {
+ GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
+ GenericParamDefKind::Type { has_default, .. } => {
+ if param.index == 0 {
+ ty_param.into()
+ } else {
+ assert!(has_default);
+ tcx.type_of(param.def_id).subst(tcx, substs).into()
+ }
+ }
+ });
+ Ty::new(tcx, Adt(adt_def, substs))
+ }
+
+ #[inline]
+ pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
+ let def_id = tcx.lang_items().get(item)?;
+ Some(Ty::new_generic_adt(tcx, def_id, ty))
+ }
+
+ #[inline]
+ pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
+ let def_id = tcx.get_diagnostic_item(name)?;
+ Some(Ty::new_generic_adt(tcx, def_id, ty))
+ }
+
+ #[inline]
+ pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ let def_id = tcx.require_lang_item(LangItem::OwnedBox, None);
+ Ty::new_generic_adt(tcx, def_id, ty)
+ }
+
+ #[inline]
+ pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None);
+ Ty::new_generic_adt(tcx, def_id, ty)
+ }
+
+ /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes.
+ pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+ let context_did = tcx.require_lang_item(LangItem::Context, None);
+ let context_adt_ref = tcx.adt_def(context_did);
+ let context_substs = tcx.mk_substs(&[tcx.lifetimes.re_erased.into()]);
+ let context_ty = Ty::new_adt(tcx, context_adt_ref, context_substs);
+ Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty)
+ }
+}
+
/// Type utilities
impl<'tcx> Ty<'tcx> {
#[inline(always)]
@@ -2213,7 +2704,7 @@ impl<'tcx> Ty<'tcx> {
let assoc_items = tcx.associated_item_def_ids(
tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
);
- tcx.mk_projection(assoc_items[0], tcx.mk_substs(&[self.into()]))
+ Ty::new_projection(tcx, assoc_items[0], tcx.mk_substs(&[self.into()]))
}
ty::Bool
@@ -2366,7 +2857,7 @@ impl<'tcx> Ty<'tcx> {
ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
- ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
+ ty::Adt(def, _substs) => def.sized_constraint(tcx).skip_binder().is_empty(),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 43f95635a..4d5f5b865 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -11,6 +11,7 @@ use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable};
+use rustc_span::sym;
use rustc_type_ir::WithCachedTypeInfo;
use smallvec::SmallVec;
@@ -451,6 +452,10 @@ impl<'tcx> InternalSubsts<'tcx> {
pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> {
tcx.mk_substs_from_iter(self.iter().take(generics.count()))
}
+
+ pub fn host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>> {
+ self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host))
+ }
}
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> {
@@ -538,15 +543,21 @@ impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx
/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable)]
-pub struct EarlyBinder<T>(pub T);
+pub struct EarlyBinder<T> {
+ value: T,
+}
/// For early binders, you should first call `subst` before using any visitors.
impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {}
impl<T> EarlyBinder<T> {
+ pub fn bind(value: T) -> EarlyBinder<T> {
+ EarlyBinder { value }
+ }
+
pub fn as_ref(&self) -> EarlyBinder<&T> {
- EarlyBinder(&self.0)
+ EarlyBinder { value: &self.value }
}
pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
@@ -560,20 +571,20 @@ impl<T> EarlyBinder<T> {
where
F: FnOnce(T) -> U,
{
- let value = f(self.0);
- EarlyBinder(value)
+ let value = f(self.value);
+ EarlyBinder { value }
}
pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
- let value = f(self.0)?;
- Ok(EarlyBinder(value))
+ let value = f(self.value)?;
+ Ok(EarlyBinder { value })
}
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
- EarlyBinder(value)
+ EarlyBinder { value }
}
/// Skips the binder and returns the "bound" value.
@@ -582,22 +593,26 @@ impl<T> EarlyBinder<T> {
/// arguments of an `FnSig`). Otherwise, consider using
/// [`subst_identity`](EarlyBinder::subst_identity).
///
+ /// To skip the binder on `x: &EarlyBinder<T>` to obtain `&T`, leverage
+ /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
+ ///
/// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
/// the analogous operation on [`super::Binder`].
pub fn skip_binder(self) -> T {
- self.0
+ self.value
}
}
impl<T> EarlyBinder<Option<T>> {
pub fn transpose(self) -> Option<EarlyBinder<T>> {
- self.0.map(|v| EarlyBinder(v))
+ self.value.map(|value| EarlyBinder { value })
}
}
impl<T, U> EarlyBinder<(T, U)> {
pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
- (EarlyBinder(self.0.0), EarlyBinder(self.0.1))
+ let EarlyBinder { value: (lhs, rhs) } = self;
+ (EarlyBinder { value: lhs }, EarlyBinder { value: rhs })
}
}
@@ -610,13 +625,13 @@ where
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> SubstIter<'s, 'tcx, I> {
- SubstIter { it: self.0.into_iter(), tcx, substs }
+ SubstIter { it: self.value.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()
+ self.value.into_iter()
}
}
@@ -633,7 +648,7 @@ where
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
- Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs))
+ Some(EarlyBinder { value: self.it.next()? }.subst(self.tcx, self.substs))
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -647,7 +662,7 @@ where
I::Item: TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
- Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs))
+ Some(EarlyBinder { value: self.it.next_back()? }.subst(self.tcx, self.substs))
}
}
@@ -668,13 +683,13 @@ where
tcx: TyCtxt<'tcx>,
substs: &'s [GenericArg<'tcx>],
) -> SubstIterCopied<'s, 'tcx, I> {
- SubstIterCopied { it: self.0.into_iter(), tcx, substs }
+ SubstIterCopied { it: self.value.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)
+ self.value.into_iter().map(|v| *v)
}
}
@@ -692,7 +707,7 @@ where
type Item = <I::Item as Deref>::Target;
fn next(&mut self) -> Option<Self::Item> {
- Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs))
+ self.it.next().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -707,7 +722,7 @@ where
<I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>,
{
fn next_back(&mut self) -> Option<Self::Item> {
- Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs))
+ self.it.next_back().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs))
}
}
@@ -725,7 +740,7 @@ pub struct EarlyBinderIter<T> {
impl<T: IntoIterator> EarlyBinder<T> {
pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
- EarlyBinderIter { t: self.0.into_iter() }
+ EarlyBinderIter { t: self.value.into_iter() }
}
}
@@ -733,7 +748,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> {
type Item = EarlyBinder<T::Item>;
fn next(&mut self) -> Option<Self::Item> {
- self.t.next().map(|i| EarlyBinder(i))
+ self.t.next().map(|value| EarlyBinder { value })
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -744,7 +759,7 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> {
impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T {
let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
- self.0.fold_with(&mut folder)
+ self.value.fold_with(&mut folder)
}
/// Makes the identity substitution `T0 => T0, ..., TN => TN`.
@@ -756,12 +771,12 @@ impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> {
/// - Inside of the body of `foo`, we treat `T` as a placeholder by calling
/// `subst_identity` to discharge the `EarlyBinder`.
pub fn subst_identity(self) -> T {
- self.0
+ self.value
}
/// Returns the inner value, but only if it contains no bound vars.
pub fn no_bound_vars(self) -> Option<T> {
- if !self.0.has_param() { Some(self.0) } else { None }
+ if !self.value.has_param() { Some(self.value) } else { None }
}
}
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index e61037e5e..98c70e330 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -52,6 +52,16 @@ pub struct TraitDef {
/// List of functions from `#[rustc_must_implement_one_of]` attribute one of which
/// must be implemented.
pub must_implement_one_of: Option<Box<[Ident]>>,
+
+ /// Whether to add a builtin `dyn Trait: Trait` implementation.
+ /// This is enabled for all traits except ones marked with
+ /// `#[rustc_deny_explicit_impl(implement_via_object = false)]`.
+ pub implement_via_object: bool,
+
+ /// Whether a trait is fully built-in, and any implementation is disallowed.
+ /// This only applies to built-in traits, and is marked via
+ /// `#[rustc_deny_explicit_impl(implement_via_object = ...)]`.
+ pub deny_explicit_impl: bool,
}
/// Whether this trait is treated specially by the standard library
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index e04dbbff9..8cbffa148 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -155,11 +155,7 @@ pub struct TypeckResults<'tcx> {
/// 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>>,
+ pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index ba0513563..e2e4a2dbd 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1,7 +1,6 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::mir;
use crate::query::Providers;
use crate::ty::layout::IntegerExt;
use crate::ty::{
@@ -11,13 +10,12 @@ 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::{Hash64, HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{Hash128, 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_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_index::bit_set::GrowableBitSet;
-use rustc_index::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_session::Limit;
use rustc_span::sym;
@@ -129,7 +127,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>) -> Hash64 {
+ pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash128 {
// 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.
@@ -173,18 +171,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
- if let ty::Adt(def, substs) = *ty.kind() {
- for field in def.all_fields() {
- let field_ty = field.ty(self, substs);
- if let ty::Error(_) = field_ty.kind() {
- return true;
- }
- }
- }
- false
- }
-
/// Attempts to returns the deeply last field of nested structures, but
/// does not apply any normalization in its search. Returns the same type
/// if input `ty` is not a structure at all.
@@ -237,14 +223,14 @@ impl<'tcx> TyCtxt<'tcx> {
};
let reported =
self.sess.emit_err(crate::error::RecursionLimitReached { ty, suggested_limit });
- return self.ty_error(reported);
+ return Ty::new_error(self, reported);
}
match *ty.kind() {
ty::Adt(def, substs) => {
if !def.is_struct() {
break;
}
- match def.non_enum_variant().fields.raw.last() {
+ match def.non_enum_variant().tail_opt() {
Some(field) => {
f();
ty = field.ty(self, substs);
@@ -318,7 +304,7 @@ impl<'tcx> TyCtxt<'tcx> {
(&ty::Adt(a_def, a_substs), &ty::Adt(b_def, b_substs))
if a_def == b_def && a_def.is_struct() =>
{
- if let Some(f) = a_def.non_enum_variant().fields.raw.last() {
+ if let Some(f) = a_def.non_enum_variant().tail_opt() {
a = f.ty(self, a_substs);
b = f.ty(self, b_substs);
} else {
@@ -624,12 +610,12 @@ impl<'tcx> TyCtxt<'tcx> {
closure_substs: SubstsRef<'tcx>,
env_region: ty::Region<'tcx>,
) -> Option<Ty<'tcx>> {
- let closure_ty = self.mk_closure(closure_def_id, closure_substs);
+ let closure_ty = Ty::new_closure(self, closure_def_id, closure_substs);
let closure_kind_ty = closure_substs.as_closure().kind_ty();
let closure_kind = closure_kind_ty.to_opt_closure_kind()?;
let env_ty = match closure_kind {
- ty::ClosureKind::Fn => self.mk_imm_ref(env_region, closure_ty),
- ty::ClosureKind::FnMut => self.mk_mut_ref(env_region, closure_ty),
+ ty::ClosureKind::Fn => Ty::new_imm_ref(self, env_region, closure_ty),
+ ty::ClosureKind::FnMut => Ty::new_mut_ref(self, env_region, closure_ty),
ty::ClosureKind::FnOnce => closure_ty,
};
Some(env_ty)
@@ -670,12 +656,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn thread_local_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
let static_ty = self.type_of(def_id).subst_identity();
if self.is_mutable_static(def_id) {
- self.mk_mut_ptr(static_ty)
+ Ty::new_mut_ptr(self, static_ty)
} else if self.is_foreign_item(def_id) {
- self.mk_imm_ptr(static_ty)
+ Ty::new_imm_ptr(self, static_ty)
} else {
// FIXME: These things don't *really* have 'static lifetime.
- self.mk_imm_ref(self.lifetimes.re_static, static_ty)
+ Ty::new_imm_ref(self, self.lifetimes.re_static, static_ty)
}
}
@@ -690,11 +676,11 @@ impl<'tcx> TyCtxt<'tcx> {
// Make sure that accesses to unsafe statics end up using raw pointers.
// For thread-locals, this needs to be kept in sync with `Rvalue::ty`.
if self.is_mutable_static(def_id) {
- self.mk_mut_ptr(static_ty)
+ Ty::new_mut_ptr(self, static_ty)
} else if self.is_foreign_item(def_id) {
- self.mk_imm_ptr(static_ty)
+ Ty::new_imm_ptr(self, static_ty)
} else {
- self.mk_imm_ref(self.lifetimes.re_erased, static_ty)
+ Ty::new_imm_ref(self, self.lifetimes.re_erased, static_ty)
}
}
@@ -709,7 +695,7 @@ impl<'tcx> TyCtxt<'tcx> {
.as_ref()
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
.filter(|decl| !decl.ignore_for_traits)
- .map(|decl| ty::EarlyBinder(decl.ty))
+ .map(|decl| ty::EarlyBinder::bind(decl.ty))
}
/// Normalizes all opaque types in the given value, replacing them
@@ -750,80 +736,6 @@ impl<'tcx> TyCtxt<'tcx> {
if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) }
}
- /// Returns names of captured upvars for closures and generators.
- ///
- /// Here are some examples:
- /// - `name__field1__field2` when the upvar is captured by value.
- /// - `_ref__name__field` when the upvar is captured by reference.
- ///
- /// For generators this only contains upvars that are shared by all states.
- pub fn closure_saved_names_of_captured_variables(
- self,
- def_id: DefId,
- ) -> SmallVec<[String; 16]> {
- let body = self.optimized_mir(def_id);
-
- body.var_debug_info
- .iter()
- .filter_map(|var| {
- let is_ref = match var.value {
- mir::VarDebugInfoContents::Place(place)
- if place.local == mir::Local::new(1) =>
- {
- // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
- // implies whether the variable is captured by value or by reference.
- matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
- }
- _ => return None,
- };
- let prefix = if is_ref { "_ref__" } else { "" };
- Some(prefix.to_owned() + var.name.as_str())
- })
- .collect()
- }
-
- // FIXME(eddyb) maybe precompute this? Right now it's computed once
- // per generator monomorphization, but it doesn't depend on substs.
- pub fn generator_layout_and_saved_local_names(
- self,
- def_id: DefId,
- ) -> (
- &'tcx ty::GeneratorLayout<'tcx>,
- IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
- ) {
- let tcx = self;
- let body = tcx.optimized_mir(def_id);
- let generator_layout = body.generator_layout().unwrap();
- let mut generator_saved_local_names =
- IndexVec::from_elem(None, &generator_layout.field_tys);
-
- let state_arg = mir::Local::new(1);
- for var in &body.var_debug_info {
- let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
- if place.local != state_arg {
- continue;
- }
- match place.projection[..] {
- [
- // Deref of the `Pin<&mut Self>` state argument.
- mir::ProjectionElem::Field(..),
- mir::ProjectionElem::Deref,
- // Field of a variant of the state.
- mir::ProjectionElem::Downcast(_, variant),
- mir::ProjectionElem::Field(field, _),
- ] => {
- let name = &mut generator_saved_local_names
- [generator_layout.variant_fields[variant][field]];
- if name.is_none() {
- name.replace(var.name);
- }
- }
- _ => {}
- }
- }
- (generator_layout, generator_saved_local_names)
- }
-
/// Query and get an English description for the item's kind.
pub fn def_descr(self, def_id: DefId) -> &'static str {
self.def_kind_descr(self.def_kind(def_id), def_id)
@@ -857,6 +769,26 @@ impl<'tcx> TyCtxt<'tcx> {
_ => def_kind.article(),
}
}
+
+ /// Return `true` if the supplied `CrateNum` is "user-visible," meaning either a [public]
+ /// dependency, or a [direct] private dependency. This is used to decide whether the crate can
+ /// be shown in `impl` suggestions.
+ ///
+ /// [public]: TyCtxt::is_private_dep
+ /// [direct]: rustc_session::cstore::ExternCrate::is_direct
+ pub fn is_user_visible_dep(self, key: CrateNum) -> bool {
+ // | Private | Direct | Visible | |
+ // |---------|--------|---------|--------------------|
+ // | Yes | Yes | Yes | !true || true |
+ // | No | Yes | Yes | !false || true |
+ // | Yes | No | No | !true || false |
+ // | No | No | Yes | !false || false |
+ !self.is_private_dep(key)
+ // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator).
+ // Treat that kind of crate as "indirect", since it's an implementation detail of
+ // the language.
+ || self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct())
+ }
}
struct OpaqueTypeExpander<'tcx> {
@@ -922,7 +854,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
let hidden_ty = bty.subst(self.tcx, substs);
self.fold_ty(hidden_ty);
}
- let expanded_ty = self.tcx.mk_generator_witness_mir(def_id, substs);
+ let expanded_ty = Ty::new_generator_witness_mir(self.tcx, def_id, substs);
self.expanded_cache.insert((def_id, substs), expanded_ty);
expanded_ty
}
@@ -964,7 +896,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
if let ty::PredicateKind::Clause(clause) = p.kind().skip_binder()
- && let ty::Clause::Projection(projection_pred) = clause
+ && let ty::ClauseKind::Projection(projection_pred) = clause
{
p.kind()
.rebind(ty::ProjectionPredicate {
@@ -1374,7 +1306,7 @@ pub fn needs_drop_components<'tcx>(
ty::Array(elem_ty, size) => {
match needs_drop_components(*elem_ty, target_layout) {
Ok(v) if v.is_empty() => Ok(v),
- res => match size.kind().try_to_bits(target_layout.pointer_size) {
+ res => match size.try_to_bits(target_layout.pointer_size) {
// Arrays of size zero don't need drop, even if their element
// type does.
Some(0) => Ok(SmallVec::new()),
@@ -1487,8 +1419,8 @@ pub struct AlwaysRequiresDrop;
/// with their underlying types.
pub fn reveal_opaque_types_in_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
- val: &'tcx ty::List<ty::Predicate<'tcx>>,
-) -> &'tcx ty::List<ty::Predicate<'tcx>> {
+ val: &'tcx ty::List<ty::Clause<'tcx>>,
+) -> &'tcx ty::List<ty::Clause<'tcx>> {
let mut visitor = OpaqueTypeExpander {
seen_opaque_tys: FxHashSet::default(),
expanded_cache: FxHashMap::default(),
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index b9b1cd73a..443791d0a 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -73,7 +73,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
let ptr_align = tcx.data_layout.pointer_align.abi;
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
- let mut vtable = Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap();
+ let mut vtable = Allocation::uninit(vtable_size, ptr_align);
// No need to do any alignment checks on the memory accesses below, because we know the
// allocation is correctly aligned as we created it above. Also we're only offsetting by