Auto merge of #113370 - compiler-errors:rollup-8gvyy8e, r=compiler-errors
Rollup of 8 pull requests Successful merges: - #113010 (rust-installer & rls: remove exclusion from rustfmt & tidy ) - #113317 ( -Ztrait-solver=next: stop depending on old solver) - #113319 (`TypeParameterDefinition` always require a `DefId`) - #113320 (Add some extra information to opaque type cycle errors) - #113321 (Move `ty::ConstKind` to `rustc_type_ir`) - #113337 (Winnow specialized impls during selection in new solver) - #113355 (Move most coverage code out of `rustc_codegen_ssa`) - #113356 (Add support for NetBSD/riscv64 aka. riscv64gc-unknown-netbsd.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5dac6b320b
84 changed files with 1988 additions and 1412 deletions
|
@ -2329,7 +2329,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
|||
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
|
||||
match self {
|
||||
Self::Ty(c) => {
|
||||
if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
|
||||
if let Some(val) = c.try_eval_for_mir(tcx, param_env) {
|
||||
match val {
|
||||
Ok(val) => Self::Val(val, c.ty()),
|
||||
Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
|
||||
|
@ -2867,7 +2867,7 @@ fn pretty_print_const_value<'tcx>(
|
|||
}
|
||||
}
|
||||
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
|
||||
let n = n.kind().try_to_bits(tcx.data_layout.pointer_size).unwrap();
|
||||
let n = n.try_to_bits(tcx.data_layout.pointer_size).unwrap();
|
||||
// cast is ok because we already checked for pointer size (32 or 64 bit) above
|
||||
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
|
||||
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
|
||||
|
|
|
@ -588,6 +588,10 @@ pub enum SelectionError<'tcx> {
|
|||
/// Signaling that an error has already been emitted, to avoid
|
||||
/// multiple errors being shown.
|
||||
ErrorReporting,
|
||||
/// Computing an opaque type's hidden type caused an error (e.g. a cycle error).
|
||||
/// We can thus not know whether the hidden type implements an auto trait, so
|
||||
/// we should not presume anything about it.
|
||||
OpaqueTypeAutoTraitLeakageUnknown(DefId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, TypeVisitable, Lift)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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;
|
||||
|
@ -14,9 +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]
|
||||
|
@ -32,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> {
|
||||
|
@ -40,7 +54,7 @@ impl<'tcx> Const<'tcx> {
|
|||
|
||||
#[inline]
|
||||
pub fn kind(self) -> ConstKind<'tcx> {
|
||||
self.0.kind
|
||||
self.0.kind.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -293,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]
|
||||
|
@ -307,14 +321,14 @@ 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) => ty::Const::new_value(tcx, val, self.ty()),
|
||||
Err(guar) => ty::Const::new_error(tcx, guar, self.ty()),
|
||||
|
@ -339,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(_))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,14 @@ 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;
|
||||
|
|
|
@ -170,7 +170,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
|
|||
match self {
|
||||
Self::ConstIsZero(c) => {
|
||||
let c = ty::EarlyBinder::bind(c).subst(tcx, substs);
|
||||
let pred = match c.kind().try_to_target_usize(tcx) {
|
||||
let pred = match c.try_to_target_usize(tcx) {
|
||||
Some(0) => Self::True,
|
||||
Some(1..) => Self::False,
|
||||
None => Self::ConstIsZero(c),
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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)
|
||||
),
|
||||
}
|
||||
|
|
|
@ -66,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::*;
|
||||
|
@ -81,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,
|
||||
|
@ -93,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,
|
||||
|
|
|
@ -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;
|
||||
|
@ -241,24 +242,6 @@ 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) => rustc_type_ir::debug_bound_var(f, *debruijn, *var),
|
||||
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
|
||||
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 {
|
||||
|
@ -728,7 +711,18 @@ 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_ct_from_kind(kind, ty))
|
||||
} else {
|
||||
|
@ -743,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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ use std::ops::{ControlFlow, Deref, Range};
|
|||
use ty::util::IntTypeExt;
|
||||
|
||||
use rustc_type_ir::sty::TyKind::*;
|
||||
use rustc_type_ir::ConstKind as IrConstKind;
|
||||
use rustc_type_ir::RegionKind as IrRegionKind;
|
||||
use rustc_type_ir::TyKind as IrTyKind;
|
||||
|
||||
|
@ -40,6 +41,7 @@ use rustc_type_ir::TyKind as IrTyKind;
|
|||
#[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)]
|
||||
|
|
|
@ -1306,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()),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue