1
Fork 0

use ty::Unevaluated<'tcx, ()> in type system

This commit is contained in:
b-naber 2022-06-27 16:32:47 +02:00
parent 7098c181f8
commit a4bbb8db5c
32 changed files with 304 additions and 192 deletions

View file

@ -288,7 +288,7 @@ dependencies = [
[[package]] [[package]]
name = "cargo" name = "cargo"
version = "0.66.0" version = "0.65.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"atty", "atty",
@ -299,6 +299,7 @@ dependencies = [
"cargo-util", "cargo-util",
"clap", "clap",
"crates-io", "crates-io",
"crossbeam-utils",
"curl", "curl",
"curl-sys", "curl-sys",
"env_logger 0.9.0", "env_logger 0.9.0",
@ -322,6 +323,7 @@ dependencies = [
"libgit2-sys", "libgit2-sys",
"log", "log",
"memchr", "memchr",
"num_cpus",
"opener", "opener",
"openssl", "openssl",
"os_info", "os_info",
@ -381,7 +383,6 @@ dependencies = [
name = "cargo-miri" name = "cargo-miri"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"cargo_metadata 0.15.0",
"directories", "directories",
"rustc-workspace-hack", "rustc-workspace-hack",
"rustc_version", "rustc_version",
@ -430,7 +431,6 @@ dependencies = [
"termcolor", "termcolor",
"toml_edit", "toml_edit",
"url", "url",
"winapi",
] ]
[[package]] [[package]]
@ -1003,6 +1003,16 @@ dependencies = [
"quote", "quote",
] ]
[[package]]
name = "ctor"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "curl" name = "curl"
version = "0.4.43" version = "0.4.43"
@ -1560,9 +1570,9 @@ dependencies = [
[[package]] [[package]]
name = "git2" name = "git2"
version = "0.15.0" version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"libc", "libc",
@ -1575,9 +1585,9 @@ dependencies = [
[[package]] [[package]]
name = "git2-curl" name = "git2-curl"
version = "0.16.0" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed817a00721e2f8037ba722e60358d4956dae9cca10315fc982f967907d3b0cd" checksum = "1ee51709364c341fbb6fe2a385a290fb9196753bdde2fc45447d27cd31b11b13"
dependencies = [ dependencies = [
"curl", "curl",
"git2", "git2",
@ -1934,30 +1944,11 @@ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
[[package]]
name = "libffi"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
dependencies = [
"libc",
"libffi-sys",
]
[[package]]
name = "libffi-sys"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab4106b7f09d7b87d021334d5618fac1dfcfb824d4c5fe111ff0074dfd242e15"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "libgit2-sys" name = "libgit2-sys"
version = "0.14.0+1.5.0" version = "0.13.4+1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b" checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -2247,8 +2238,6 @@ dependencies = [
"getrandom 0.2.0", "getrandom 0.2.0",
"lazy_static", "lazy_static",
"libc", "libc",
"libffi",
"libloading",
"log", "log",
"measureme", "measureme",
"rand 0.8.5", "rand 0.8.5",
@ -2421,6 +2410,15 @@ version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
[[package]]
name = "output_vt100"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "owo-colors" name = "owo-colors"
version = "3.4.0" version = "3.4.0"
@ -2662,6 +2660,18 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "pretty_assertions"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
dependencies = [
"ctor",
"diff",
"output_vt100",
"yansi",
]
[[package]] [[package]]
name = "pretty_env_logger" name = "pretty_env_logger"
version = "0.4.0" version = "0.4.0"
@ -4540,9 +4550,9 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
[[package]] [[package]]
name = "snapbox" name = "snapbox"
version = "0.3.3" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d199ccf8f606592df2d145db26f2aa45344e23c64b074cc5a4047f1d99b0f7" checksum = "767a1d5da232b6959cd1bd5c9e8db8a7cce09c3038e89deedb49a549a2aefd93"
dependencies = [ dependencies = [
"concolor", "concolor",
"content_inspector", "content_inspector",
@ -4558,9 +4568,9 @@ dependencies = [
[[package]] [[package]]
name = "snapbox-macros" name = "snapbox-macros"
version = "0.3.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a253e6f894cfa440cba00600a249fa90869d8e0ec45ab274a456e043a0ce8f2" checksum = "c01dea7e04cbb27ef4c86e9922184608185f7cd95c1763bc30d727cda4a5e930"
[[package]] [[package]]
name = "socket2" name = "socket2"
@ -5039,16 +5049,14 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]] [[package]]
name = "ui_test" name = "ui_test"
version = "0.3.1" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d1f546a5883ae78da735bba529ec1116661e2f73582f23920d994dc97da3a22"
dependencies = [ dependencies = [
"cargo_metadata 0.15.0", "cargo_metadata 0.15.0",
"color-eyre", "color-eyre",
"colored", "colored",
"crossbeam", "crossbeam",
"diff",
"lazy_static", "lazy_static",
"pretty_assertions",
"regex", "regex",
"rustc_version", "rustc_version",
"serde", "serde",

View file

@ -354,11 +354,13 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
let maybe_uneval = match constant.literal { let maybe_uneval = match constant.literal {
ConstantKind::Ty(ct) => match ct.kind() { ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => Some(uv), ty::ConstKind::Unevaluated(uv) => Some(uv.expand()),
_ => None, _ => None,
}, },
ConstantKind::Unevaluated(uv, _) => Some(uv),
_ => None, _ => None,
}; };
if let Some(uv) = maybe_uneval { if let Some(uv) = maybe_uneval {
if let Some(promoted) = uv.promoted { if let Some(promoted) = uv.promoted {
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
@ -1813,11 +1815,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if let Operand::Constant(constant) = op { if let Operand::Constant(constant) = op {
let maybe_uneval = match constant.literal { let maybe_uneval = match constant.literal {
ConstantKind::Ty(ct) => match ct.kind() { ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => Some(uv), ty::ConstKind::Unevaluated(uv) => Some(uv.expand()),
_ => None, _ => None,
}, },
ConstantKind::Unevaluated(uv, _) => Some(uv),
_ => None, _ => None,
}; };
if let Some(uv) = maybe_uneval { if let Some(uv) = maybe_uneval {
if uv.promoted.is_none() { if uv.promoted.is_none() {
let tcx = self.tcx(); let tcx = self.tcx();

View file

@ -124,6 +124,22 @@ pub(crate) fn codegen_constant<'tcx>(
) -> CValue<'tcx> { ) -> CValue<'tcx> {
let const_ = match fx.monomorphize(constant.literal) { let const_ = match fx.monomorphize(constant.literal) {
ConstantKind::Ty(ct) => ct, ConstantKind::Ty(ct) => ct,
ConstantKind::Unevaluated(mir::Unevaluated { def, substs, promoted })
if fx.tcx.is_static(def.did) =>
{
assert!(substs.is_empty());
assert!(promoted.is_none());
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty())).to_cvalue(fx);
}
ConstantKind::Unevaluated(unevaluated) => {
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
Ok(const_val) => const_val,
Err(_) => {
span_bug!(constant.span, "erroneous constant not captured by required_consts");
}
}
}
ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty), ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
}; };
let const_val = match const_.kind() { let const_val = match const_.kind() {
@ -133,17 +149,8 @@ pub(crate) fn codegen_constant<'tcx>(
{ {
assert!(substs.is_empty()); assert!(substs.is_empty());
assert!(promoted.is_none()); assert!(promoted.is_none());
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty())).to_cvalue(fx); return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty())).to_cvalue(fx);
} }
ConstKind::Unevaluated(unevaluated) => {
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
Ok(const_val) => const_val,
Err(_) => {
span_bug!(constant.span, "erroneous constant not captured by required_consts");
}
}
}
ConstKind::Param(_) ConstKind::Param(_)
| ConstKind::Infer(_) | ConstKind::Infer(_)
| ConstKind::Bound(_, _) | ConstKind::Bound(_, _)

View file

@ -25,26 +25,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
constant: &mir::Constant<'tcx>, constant: &mir::Constant<'tcx>,
) -> Result<ConstValue<'tcx>, ErrorHandled> { ) -> Result<ConstValue<'tcx>, ErrorHandled> {
let ct = self.monomorphize(constant.literal); let ct = self.monomorphize(constant.literal);
let ct = match ct { let uv = match ct {
mir::ConstantKind::Ty(ct) => ct, mir::ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => uv.expand(),
ty::ConstKind::Value(val) => {
return Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val)));
}
err => span_bug!(
constant.span,
"encountered bad ConstKind after monomorphizing: {:?}",
err
),
},
mir::ConstantKind::Unevaluated(uv, _) => uv,
mir::ConstantKind::Val(val, _) => return Ok(val), mir::ConstantKind::Val(val, _) => return Ok(val),
}; };
match ct.kind() {
ty::ConstKind::Unevaluated(ct) => self self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
.cx self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
.tcx() err
.const_eval_resolve(ty::ParamEnv::reveal_all(), ct, None) })
.map_err(|err| {
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
err
}),
ty::ConstKind::Value(val) => Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val))),
err => span_bug!(
constant.span,
"encountered bad ConstKind after monomorphizing: {:?}",
err
),
}
} }
/// process constant containing SIMD shuffle indices /// process constant containing SIMD shuffle indices

View file

@ -565,7 +565,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
ty::ConstKind::Unevaluated(uv) => { ty::ConstKind::Unevaluated(uv) => {
let instance = self.resolve(uv.def, uv.substs)?; let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into()) Ok(self.eval_to_allocation(GlobalId { instance, promoted: None })?.into())
} }
ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => { ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c) span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
@ -578,6 +578,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
} }
/// Tries to evaluate an unevaluated constant from the MIR (and not the type-system).
#[inline]
pub fn uneval_to_op(
&self,
uneval: &ty::Unevaluated<'tcx>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
let instance = self.resolve(uneval.def, uneval.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: None })?.into())
}
pub fn mir_const_to_op( pub fn mir_const_to_op(
&self, &self,
val: &mir::ConstantKind<'tcx>, val: &mir::ConstantKind<'tcx>,
@ -586,6 +596,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match val { match val {
mir::ConstantKind::Ty(ct) => self.const_to_op(*ct, layout), mir::ConstantKind::Ty(ct) => self.const_to_op(*ct, layout),
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout), mir::ConstantKind::Val(val, ty) => self.const_val_to_op(*val, *ty, layout),
mir::ConstantKind::Unevaluated(uv, _) => self.uneval_to_op(uv),
} }
} }

View file

@ -347,14 +347,15 @@ where
// Check the qualifs of the value of `const` items. // Check the qualifs of the value of `const` items.
if let Some(ct) = constant.literal.const_for_ty() { if let Some(ct) = constant.literal.const_for_ty() {
if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.kind() if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: _ }) =
ct.kind()
{ {
// Use qualifs of the type for the promoted. Promoteds in MIR body should be possible // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
// only for `NeedsNonConstDrop` with precise drop checking. This is the only const // only for `NeedsNonConstDrop` with precise drop checking. This is the only const
// check performed after the promotion. Verify that with an assertion. // check performed after the promotion. Verify that with an assertion.
assert!(promoted.is_none() || Q::ALLOW_PROMOTED);
// Don't peek inside trait associated constants. // Don't peek inside trait associated constants.
if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() { if cx.tcx.trait_of_item(def.did).is_none() {
let qualifs = if let Some((did, param_did)) = def.as_const_arg() { let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did)) cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
} else { } else {

View file

@ -840,21 +840,15 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
promoted.span = span; promoted.span = span;
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did)); let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
let _const = tcx.mk_const(ty::ConstS { let uneval = ty::Unevaluated { def, substs, promoted: Some(promoted_id) };
ty,
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
substs,
promoted: Some(promoted_id),
}),
});
Operand::Constant(Box::new(Constant { Operand::Constant(Box::new(Constant {
span, span,
user_ty: None, user_ty: None,
literal: ConstantKind::from_const(_const, tcx), literal: ConstantKind::Unevaluated(uneval, ty),
})) }))
}; };
let blocks = self.source.basic_blocks.as_mut(); let blocks = self.source.basic_blocks.as_mut();
let local_decls = &mut self.source.local_decls; let local_decls = &mut self.source.local_decls;
let loc = candidate.location; let loc = candidate.location;

View file

@ -743,7 +743,8 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
} }
} }
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert_eq!(promoted, None); assert_eq!(promoted, ());
let substs = self.relate_with_variance( let substs = self.relate_with_variance(
ty::Variance::Invariant, ty::Variance::Invariant,
ty::VarianceDiagInfo::default(), ty::VarianceDiagInfo::default(),
@ -964,13 +965,15 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
} }
} }
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
assert_eq!(promoted, None); assert_eq!(promoted, ());
let substs = self.relate_with_variance( let substs = self.relate_with_variance(
ty::Variance::Invariant, ty::Variance::Invariant,
ty::VarianceDiagInfo::default(), ty::VarianceDiagInfo::default(),
substs, substs,
substs, substs,
)?; )?;
Ok(self.tcx().mk_const(ty::ConstS { Ok(self.tcx().mk_const(ty::ConstS {
ty: c.ty(), ty: c.ty(),
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),

View file

@ -1673,7 +1673,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn try_const_eval_resolve( pub fn try_const_eval_resolve(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::Unevaluated<'tcx>, unevaluated: ty::Unevaluated<'tcx, ()>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
span: Option<Span>, span: Option<Span>,
) -> Result<ty::Const<'tcx>, ErrorHandled> { ) -> Result<ty::Const<'tcx>, ErrorHandled> {
@ -1708,7 +1708,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn const_eval_resolve( pub fn const_eval_resolve(
&self, &self,
mut param_env: ty::ParamEnv<'tcx>, mut param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::Unevaluated<'tcx>, unevaluated: ty::Unevaluated<'tcx, ()>,
span: Option<Span>, span: Option<Span>,
) -> EvalToValTreeResult<'tcx> { ) -> EvalToValTreeResult<'tcx> {
let mut substs = self.resolve_vars_if_possible(unevaluated.substs); let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
@ -1739,11 +1739,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
debug!(?param_env_erased); debug!(?param_env_erased);
debug!(?substs_erased); debug!(?substs_erased);
let unevaluated = ty::Unevaluated { let unevaluated =
def: unevaluated.def, ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () };
substs: substs_erased,
promoted: unevaluated.promoted,
};
// The return value is the evaluated value which doesn't contain any reference to inference // The return value is the evaluated value which doesn't contain any reference to inference
// variables, thus we don't need to substitute back the original values. // variables, thus we don't need to substitute back the original values.

View file

@ -63,7 +63,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_eval_resolve_for_typeck( pub fn const_eval_resolve_for_typeck(
self, self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
ct: ty::Unevaluated<'tcx>, ct: ty::Unevaluated<'tcx, ()>,
span: Option<Span>, span: Option<Span>,
) -> EvalToValTreeResult<'tcx> { ) -> EvalToValTreeResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference // Cannot resolve `Unevaluated` constants that contain inference
@ -78,7 +78,7 @@ impl<'tcx> TyCtxt<'tcx> {
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
Ok(Some(instance)) => { Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted }; let cid = GlobalId { instance, promoted: None };
self.const_eval_global_id_for_typeck(param_env, cid, span) self.const_eval_global_id_for_typeck(param_env, cid, span)
} }
Ok(None) => Err(ErrorHandled::TooGeneric), Ok(None) => Err(ErrorHandled::TooGeneric),

View file

@ -3,7 +3,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
use crate::mir::interpret::{ use crate::mir::interpret::{
AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar, AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, LitToConstInput, Scalar,
}; };
use crate::mir::visit::MirVisitable; use crate::mir::visit::MirVisitable;
use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::codec::{TyDecoder, TyEncoder};
@ -2061,6 +2061,10 @@ pub struct Constant<'tcx> {
pub enum ConstantKind<'tcx> { pub enum ConstantKind<'tcx> {
/// This constant came from the type system /// This constant came from the type system
Ty(ty::Const<'tcx>), Ty(ty::Const<'tcx>),
/// An unevaluated constant that cannot go back into the type system.
Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>),
/// This constant cannot go back into the type system, as it represents /// This constant cannot go back into the type system, as it represents
/// something the type system cannot handle (e.g. pointers). /// something the type system cannot handle (e.g. pointers).
Val(interpret::ConstValue<'tcx>, Ty<'tcx>), Val(interpret::ConstValue<'tcx>, Ty<'tcx>),
@ -2091,7 +2095,7 @@ impl<'tcx> ConstantKind<'tcx> {
pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> { pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
match self { match self {
ConstantKind::Ty(c) => Some(*c), ConstantKind::Ty(c) => Some(*c),
ConstantKind::Val(..) => None, ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => None,
} }
} }
@ -2099,7 +2103,7 @@ impl<'tcx> ConstantKind<'tcx> {
pub fn ty(&self) -> Ty<'tcx> { pub fn ty(&self) -> Ty<'tcx> {
match self { match self {
ConstantKind::Ty(c) => c.ty(), ConstantKind::Ty(c) => c.ty(),
ConstantKind::Val(_, ty) => *ty, ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => *ty,
} }
} }
@ -2111,6 +2115,7 @@ impl<'tcx> ConstantKind<'tcx> {
_ => None, _ => None,
}, },
ConstantKind::Val(val, _) => Some(val), ConstantKind::Val(val, _) => Some(val),
ConstantKind::Unevaluated(..) => None,
} }
} }
@ -2125,6 +2130,7 @@ impl<'tcx> ConstantKind<'tcx> {
_ => None, _ => None,
}, },
ConstantKind::Val(val, _) => val.try_to_scalar(), ConstantKind::Val(val, _) => val.try_to_scalar(),
ConstantKind::Unevaluated(..) => None,
} }
} }
@ -2157,6 +2163,14 @@ impl<'tcx> ConstantKind<'tcx> {
} }
} }
Self::Val(_, _) => self, Self::Val(_, _) => self,
Self::Unevaluated(uneval, ty) => {
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
match tcx.const_eval_resolve(param_env, uneval, None) {
Ok(val) => Self::Val(val, ty),
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => self,
Err(_) => Self::Ty(tcx.const_error(ty)),
}
}
} }
} }
@ -2182,6 +2196,18 @@ impl<'tcx> ConstantKind<'tcx> {
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
val.try_to_bits(size) val.try_to_bits(size)
} }
Self::Unevaluated(uneval, ty) => {
match tcx.const_eval_resolve(param_env, *uneval, None) {
Ok(val) => {
let size = tcx
.layout_of(param_env.with_reveal_all_normalized(tcx).and(*ty))
.ok()?
.size;
val.try_to_bits(size)
}
Err(_) => None,
}
}
} }
} }
@ -2190,6 +2216,12 @@ impl<'tcx> ConstantKind<'tcx> {
match self { match self {
Self::Ty(ct) => ct.try_eval_bool(tcx, param_env), Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
Self::Val(val, _) => val.try_to_bool(), Self::Val(val, _) => val.try_to_bool(),
Self::Unevaluated(uneval, _) => {
match tcx.const_eval_resolve(param_env, *uneval, None) {
Ok(val) => val.try_to_bool(),
Err(_) => None,
}
}
} }
} }
@ -2198,6 +2230,12 @@ impl<'tcx> ConstantKind<'tcx> {
match self { match self {
Self::Ty(ct) => ct.try_eval_usize(tcx, param_env), Self::Ty(ct) => ct.try_eval_usize(tcx, param_env),
Self::Val(val, _) => val.try_to_machine_usize(tcx), Self::Val(val, _) => val.try_to_machine_usize(tcx),
Self::Unevaluated(uneval, _) => {
match tcx.const_eval_resolve(param_env, *uneval, None) {
Ok(val) => val.try_to_machine_usize(tcx),
Err(_) => None,
}
}
} }
} }
@ -2293,15 +2331,16 @@ impl<'tcx> ConstantKind<'tcx> {
let substs = let substs =
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty }) ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
.substs; .substs;
debug_assert!(!substs.has_free_regions());
Self::Ty(tcx.mk_const(ty::ConstS { let uneval = ty::Unevaluated {
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def: ty::WithOptConstParam::unknown(def_id).to_global(),
def: ty::WithOptConstParam::unknown(def_id).to_global(), substs,
substs, promoted: None,
promoted: None, };
}),
ty, debug_assert!(!uneval.has_free_regions());
}))
Self::Unevaluated(uneval, ty)
} }
#[instrument(skip(tcx), level = "debug", ret)] #[instrument(skip(tcx), level = "debug", ret)]
@ -2398,7 +2437,7 @@ impl<'tcx> ConstantKind<'tcx> {
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: def.to_global(), def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
promoted: None, promoted: (),
}), }),
ty, ty,
})) }))
@ -2412,6 +2451,7 @@ impl<'tcx> ConstantKind<'tcx> {
let const_val = tcx.valtree_to_const_val((c.ty(), valtree)); let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
Self::Val(const_val, c.ty()) Self::Val(const_val, c.ty())
} }
ty::ConstKind::Unevaluated(uv) => Self::Unevaluated(uv.expand(), c.ty()),
_ => Self::Ty(c), _ => Self::Ty(c),
} }
} }
@ -2612,6 +2652,10 @@ impl<'tcx> Display for ConstantKind<'tcx> {
match *self { match *self {
ConstantKind::Ty(c) => pretty_print_const(c, fmt, true), ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true), ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true),
ConstantKind::Unevaluated(..) => {
fmt.write_str("_")?;
Ok(())
}
} }
} }
} }

View file

@ -464,12 +464,14 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
let val = match literal { let val = match literal {
ConstantKind::Ty(ct) => match ct.kind() { ConstantKind::Ty(ct) => match ct.kind() {
ty::ConstKind::Param(p) => format!("Param({})", p), ty::ConstKind::Param(p) => format!("Param({})", p),
ty::ConstKind::Unevaluated(uv) => format!( ty::ConstKind::Unevaluated(uv) => {
"Unevaluated({}, {:?}, {:?})", format!(
self.tcx.def_path_str(uv.def.did), "Unevaluated({}, {:?}, {:?})",
uv.substs, self.tcx.def_path_str(uv.def.did),
uv.promoted, uv.substs,
), uv.promoted,
)
}
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)), ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
ty::ConstKind::Error(_) => "Error".to_string(), ty::ConstKind::Error(_) => "Error".to_string(),
// These variants shouldn't exist in the MIR. // These variants shouldn't exist in the MIR.
@ -477,6 +479,14 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
| ty::ConstKind::Infer(_) | ty::ConstKind::Infer(_)
| ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal), | ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal),
}, },
ConstantKind::Unevaluated(uv, _) => {
format!(
"Unevaluated({}, {:?}, {:?})",
self.tcx.def_path_str(uv.def.did),
uv.substs,
uv.promoted,
)
}
// To keep the diffs small, we render this like we render `ty::Const::Value`. // To keep the diffs small, we render this like we render `ty::Const::Value`.
// //
// This changes once `ty::Const::Value` is represented using valtrees. // This changes once `ty::Const::Value` is represented using valtrees.
@ -702,6 +712,7 @@ pub fn write_allocations<'tcx>(
ConstantKind::Val(val, _) => { ConstantKind::Val(val, _) => {
self.0.extend(alloc_ids_from_const_val(val)); self.0.extend(alloc_ids_from_const_val(val));
} }
ConstantKind::Unevaluated(..) => {}
} }
} }
} }

View file

@ -235,6 +235,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> {
match self { match self {
ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)), ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)), ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
ConstantKind::Unevaluated(uv, t) => {
Ok(ConstantKind::Unevaluated(uv, t.try_fold_with(folder)?))
}
} }
} }
} }

View file

@ -879,6 +879,7 @@ macro_rules! make_mir_visitor {
match literal { match literal {
ConstantKind::Ty(ct) => self.visit_const($(& $mutability)? *ct, location), ConstantKind::Ty(ct) => self.visit_const($(& $mutability)? *ct, location),
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
} }
} }

View file

@ -42,7 +42,7 @@ impl<'tcx> AbstractConst<'tcx> {
ct: ty::Const<'tcx>, ct: ty::Const<'tcx>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> { ) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
match ct.kind() { match ct.kind() {
ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()), ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv),
ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported), ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => Err(reported),
_ => Ok(None), _ => Ok(None),
} }

View file

@ -41,7 +41,7 @@ pub struct ConstS<'tcx> {
} }
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ConstS<'_>, 48); static_assert_size!(ConstS<'_>, 40);
impl<'tcx> Const<'tcx> { impl<'tcx> Const<'tcx> {
#[inline] #[inline]
@ -84,7 +84,7 @@ impl<'tcx> Const<'tcx> {
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: def.to_global(), def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
promoted: None, promoted: (),
}), }),
ty, ty,
}), }),
@ -181,7 +181,7 @@ impl<'tcx> Const<'tcx> {
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: ty::WithOptConstParam::unknown(def_id).to_global(), def: ty::WithOptConstParam::unknown(def_id).to_global(),
substs, substs,
promoted: None, promoted: (),
}), }),
ty, ty,
}) })

View file

@ -11,6 +11,7 @@ use rustc_macros::HashStable;
use rustc_target::abi::Size; use rustc_target::abi::Size;
use super::ScalarInt; use super::ScalarInt;
/// An unevaluated, potentially generic, constant. /// An unevaluated, potentially generic, constant.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
#[derive(Hash, HashStable)] #[derive(Hash, HashStable)]
@ -66,7 +67,7 @@ pub enum ConstKind<'tcx> {
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// 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. /// variants when the code is monomorphic enough for that.
Unevaluated(Unevaluated<'tcx>), Unevaluated(Unevaluated<'tcx, ()>),
/// Used to hold computed value. /// Used to hold computed value.
Value(ty::ValTree<'tcx>), Value(ty::ValTree<'tcx>),
@ -77,7 +78,7 @@ pub enum ConstKind<'tcx> {
} }
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ConstKind<'_>, 40); static_assert_size!(ConstKind<'_>, 32);
impl<'tcx> ConstKind<'tcx> { impl<'tcx> ConstKind<'tcx> {
#[inline] #[inline]
@ -184,6 +185,8 @@ impl<'tcx> ConstKind<'tcx> {
if let ConstKind::Unevaluated(unevaluated) = self { if let ConstKind::Unevaluated(unevaluated) = self {
use crate::mir::interpret::ErrorHandled; use crate::mir::interpret::ErrorHandled;
assert_eq!(unevaluated.promoted, ());
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve` // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
// also does later, but we want to do it before checking for // also does later, but we want to do it before checking for
// inference variables. // inference variables.
@ -204,7 +207,7 @@ impl<'tcx> ConstKind<'tcx> {
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
def: unevaluated.def, def: unevaluated.def,
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
promoted: unevaluated.promoted, promoted: (),
}) })
} else { } else {
param_env_and param_env_and
@ -228,7 +231,7 @@ impl<'tcx> ConstKind<'tcx> {
} }
} }
EvalMode::Mir => { EvalMode::Mir => {
match tcx.const_eval_resolve(param_env, unevaluated, None) { match tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
// NOTE(eddyb) `val` contains no lifetimes/types/consts, // NOTE(eddyb) `val` contains no lifetimes/types/consts,
// and we use the original type, so nothing from `substs` // and we use the original type, so nothing from `substs`
// (which may be identity substs, see above), // (which may be identity substs, see above),

View file

@ -1197,15 +1197,9 @@ pub trait PrettyPrinter<'tcx>:
} }
match ct.kind() { match ct.kind() {
ty::ConstKind::Unevaluated(ty::Unevaluated { ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
def, assert_eq!(promoted, ());
substs,
promoted: Some(promoted),
}) => {
p!(print_value_path(def.did, substs));
p!(write("::{:?}", promoted));
}
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => {
match self.tcx().def_kind(def.did) { match self.tcx().def_kind(def.did) {
DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => { DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(def.did, substs)) p!(print_value_path(def.did, substs))

View file

@ -613,7 +613,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if tcx.features().generic_const_exprs => if tcx.features().generic_const_exprs =>
{ {
tcx.try_unify_abstract_consts(relation.param_env().and((au.shrink(), bu.shrink()))) tcx.try_unify_abstract_consts(relation.param_env().and((au, bu)))
} }
// While this is slightly incorrect, it shouldn't matter for `min_const_generics` // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
@ -622,6 +622,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
if au.def == bu.def && au.promoted == bu.promoted => if au.def == bu.def && au.promoted == bu.promoted =>
{ {
assert_eq!(au.promoted, ());
let substs = relation.relate_with_variance( let substs = relation.relate_with_variance(
ty::Variance::Invariant, ty::Variance::Invariant,
ty::VarianceDiagInfo::default(), ty::VarianceDiagInfo::default(),
@ -632,7 +634,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: au.def, def: au.def,
substs, substs,
promoted: au.promoted, promoted: (),
}), }),
ty: a.ty(), ty: a.ty(),
})); }));

View file

@ -565,23 +565,19 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let value = value.eval(self.tcx, self.param_env); let value = value.eval(self.tcx, self.param_env);
match value { match value {
mir::ConstantKind::Ty(c) => { mir::ConstantKind::Ty(c) => match c.kind() {
match c.kind() { ConstKind::Param(_) => {
ConstKind::Param(_) => { self.errors.push(PatternError::ConstParamInPattern(span));
self.errors.push(PatternError::ConstParamInPattern(span)); return PatKind::Wild;
return PatKind::Wild;
}
ConstKind::Unevaluated(_) => {
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
self.tcx
.sess
.span_err(span, "constant pattern depends on a generic parameter");
return PatKind::Wild;
}
_ => bug!("Expected either ConstKind::Param or ConstKind::Unevaluated"),
} }
} _ => bug!("Expected ConstKind::Param"),
},
mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind, mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
mir::ConstantKind::Unevaluated(..) => {
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter");
return PatKind::Wild;
}
} }
} }

View file

@ -22,9 +22,7 @@ use rustc_middle::mir::{
}; };
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{ use rustc_middle::ty::{self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable};
self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable,
};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::Span; use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout}; use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
@ -301,18 +299,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
let err = ConstEvalErr::new(&self.ecx, error, Some(c.span)); let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
if let Some(lint_root) = self.lint_root(source_info) { if let Some(lint_root) = self.lint_root(source_info) {
let lint_only = match c.literal { let lint_only = match c.literal {
ConstantKind::Ty(ct) => match ct.kind() { ConstantKind::Ty(_) => c.literal.needs_subst(),
ConstantKind::Unevaluated(
ty::Unevaluated { def: _, substs: _, promoted: Some(_) },
_,
) => {
// Promoteds must lint and not error as the user didn't ask for them // Promoteds must lint and not error as the user didn't ask for them
ConstKind::Unevaluated(ty::Unevaluated { true
def: _, }
substs: _, ConstantKind::Unevaluated(_, ty) | ConstantKind::Val(_, ty) => {
promoted: Some(_), ty.needs_subst()
}) => true, }
// Out of backwards compatibility we cannot report hard errors in unused
// generic functions using associated constants of the generic parameters.
_ => c.literal.needs_subst(),
},
ConstantKind::Val(_, ty) => ty.needs_subst(),
}; };
if lint_only { if lint_only {
// Out of backwards compatibility we cannot report hard errors in unused // Out of backwards compatibility we cannot report hard errors in unused

View file

@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}
use rustc_middle::mir::visit::*; use rustc_middle::mir::visit::*;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel; use rustc_session::config::OptLevel;
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span}; use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
@ -606,7 +606,9 @@ impl<'tcx> Inliner<'tcx> {
caller_body.required_consts.extend( caller_body.required_consts.extend(
callee_body.required_consts.iter().copied().filter(|&ct| { callee_body.required_consts.iter().copied().filter(|&ct| {
match ct.literal.const_for_ty() { match ct.literal.const_for_ty() {
Some(ct) => matches!(ct.kind(), ConstKind::Unevaluated(_)), Some(_) => {
bug!("should never encounter ty::Unevaluated in required_consts")
}
None => true, None => true,
} }
}), }),

View file

@ -1,5 +1,5 @@
use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{Constant, Location}; use rustc_middle::mir::{Constant, ConstantKind, Location};
use rustc_middle::ty::ConstKind; use rustc_middle::ty::ConstKind;
pub struct RequiredConstsVisitor<'a, 'tcx> { pub struct RequiredConstsVisitor<'a, 'tcx> {
@ -15,8 +15,18 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
let literal = constant.literal; let literal = constant.literal;
if let Some(ct) = literal.const_for_ty() && let ConstKind::Unevaluated(_) = ct.kind() { match literal {
self.required_consts.push(*constant); ConstantKind::Ty(c) => match c.kind() {
ConstKind::Unevaluated(uv) => {
let literal = ConstantKind::Unevaluated(uv.expand(), c.ty());
let new_constant =
Constant { span: constant.span, user_ty: constant.user_ty, literal };
self.required_consts.push(new_constant);
}
_ => {}
},
ConstantKind::Unevaluated(..) => self.required_consts.push(*constant),
ConstantKind::Val(..) => {}
} }
} }
} }

View file

@ -767,7 +767,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
ty::ConstKind::Unevaluated(ct) => { ty::ConstKind::Unevaluated(ct) => {
debug!(?ct); debug!(?ct);
let param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
match self.tcx.const_eval_resolve(param_env, ct, None) { match self.tcx.const_eval_resolve(param_env, ct.expand(), None) {
// The `monomorphize` call should have evaluated that constant already. // The `monomorphize` call should have evaluated that constant already.
Ok(val) => val, Ok(val) => val,
Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return, Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
@ -780,6 +780,19 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
} }
_ => return, _ => return,
}, },
mir::ConstantKind::Unevaluated(uv, _) => {
let param_env = ty::ParamEnv::reveal_all();
match self.tcx.const_eval_resolve(param_env, uv, None) {
// The `monomorphize` call should have evaluated that constant already.
Ok(val) => val,
Err(ErrorHandled::Reported(_) | ErrorHandled::Linted) => return,
Err(ErrorHandled::TooGeneric) => span_bug!(
self.body.source_info(location).span,
"collection encountered polymorphic constant: {:?}",
literal
),
}
}
}; };
collect_const_value(self.tcx, val, self.output); collect_const_value(self.tcx, val, self.output);
self.visit_ty(literal.ty(), TyContext::Location(location)); self.visit_ty(literal.ty(), TyContext::Location(location));
@ -798,7 +811,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
collect_const_value(self.tcx, const_val, self.output) collect_const_value(self.tcx, const_val, self.output)
} }
ty::ConstKind::Unevaluated(unevaluated) => { ty::ConstKind::Unevaluated(unevaluated) => {
match self.tcx.const_eval_resolve(param_env, unevaluated, None) { match self.tcx.const_eval_resolve(param_env, unevaluated.expand(), None) {
// The `monomorphize` call should have evaluated that constant already. // The `monomorphize` call should have evaluated that constant already.
Ok(val) => span_bug!( Ok(val) => span_bug!(
self.body.source_info(location).span, self.body.source_info(location).span,

View file

@ -9,7 +9,7 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
use rustc_index::bit_set::FiniteBitSet; use rustc_index::bit_set::FiniteBitSet;
use rustc_middle::mir::{ use rustc_middle::mir::{
visit::{TyContext, Visitor}, visit::{TyContext, Visitor},
Local, LocalDecl, Location, ConstantKind, Local, LocalDecl, Location,
}; };
use rustc_middle::ty::{ use rustc_middle::ty::{
self, self,
@ -292,7 +292,29 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.unused_parameters.clear(param.index); self.unused_parameters.clear(param.index);
ControlFlow::CONTINUE ControlFlow::CONTINUE
} }
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)}) ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if matches!(
self.tcx.def_kind(def.did),
DefKind::AnonConst | DefKind::InlineConst
) =>
{
assert_eq!(promoted, ());
self.visit_child_body(def.did, substs);
ControlFlow::CONTINUE
}
_ => c.super_visit_with(self),
}
}
fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
if !constant.has_param_types_or_consts() {
return ControlFlow::CONTINUE;
}
match constant {
ConstantKind::Ty(_) => constant.super_visit_with(self),
ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _)
// Avoid considering `T` unused when constants are of the form: // Avoid considering `T` unused when constants are of the form:
// `<Self as Foo<T>>::foo::promoted[p]` // `<Self as Foo<T>>::foo::promoted[p]`
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
@ -303,13 +325,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.visit_body(&promoted[p]); self.visit_body(&promoted[p]);
ControlFlow::CONTINUE ControlFlow::CONTINUE
} }
ty::ConstKind::Unevaluated(uv) ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => {
if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) => constant.super_visit_with(self)
{
self.visit_child_body(uv.def.did, uv.substs);
ControlFlow::CONTINUE
} }
_ => c.super_visit_with(self),
} }
} }

View file

@ -183,7 +183,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
FailureKind::Concrete => {} FailureKind::Concrete => {}
} }
} }
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span)); let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
match concrete { match concrete {
Err(ErrorHandled::TooGeneric) => { Err(ErrorHandled::TooGeneric) => {
Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug( Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug(
@ -210,7 +210,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
// and hopefully soon change this to an error. // and hopefully soon change this to an error.
// //
// See #74595 for more details about this. // See #74595 for more details about this.
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span)); let concrete = infcx.const_eval_resolve(param_env, uv, Some(span));
match concrete { match concrete {
// If we're evaluating a foreign constant, under a nightly compiler without generic // If we're evaluating a foreign constant, under a nightly compiler without generic

View file

@ -509,11 +509,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.kind(), c2.kind()) (c1.kind(), c2.kind())
{ {
if infcx.try_unify_abstract_consts( if infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
a.shrink(),
b.shrink(),
obligation.param_env,
) {
return ProcessResult::Changed(vec![]); return ProcessResult::Changed(vec![]);
} }
} }

View file

@ -366,7 +366,9 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
_ => mir::ConstantKind::Ty(const_folded), _ => mir::ConstantKind::Ty(const_folded),
} }
} }
mir::ConstantKind::Val(_, _) => constant.try_super_fold_with(self)?, mir::ConstantKind::Val(_, _) | mir::ConstantKind::Unevaluated(..) => {
constant.try_super_fold_with(self)?
}
}) })
} }

View file

@ -699,11 +699,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) = if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.kind(), c2.kind()) (c1.kind(), c2.kind())
{ {
if self.infcx.try_unify_abstract_consts( if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
a.shrink(),
b.shrink(),
obligation.param_env,
) {
return Ok(EvaluatedToOk); return Ok(EvaluatedToOk);
} }
} }

View file

@ -456,7 +456,7 @@ impl<'tcx> WfPredicates<'tcx> {
self.out.extend(obligations); self.out.extend(obligations);
let predicate = let predicate =
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink())) ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
.to_predicate(self.tcx()); .to_predicate(self.tcx());
let cause = self.cause(traits::WellFormed(None)); let cause = self.cause(traits::WellFormed(None));
self.out.push(traits::Obligation::with_depth( self.out.push(traits::Obligation::with_depth(

View file

@ -2372,10 +2372,10 @@ fn const_evaluatable_predicates_of<'tcx>(
let def_id = self.tcx.hir().local_def_id(c.hir_id); let def_id = self.tcx.hir().local_def_id(c.hir_id);
let ct = ty::Const::from_anon_const(self.tcx, def_id); let ct = ty::Const::from_anon_const(self.tcx, def_id);
if let ty::ConstKind::Unevaluated(uv) = ct.kind() { if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
assert_eq!(uv.promoted, None); assert_eq!(uv.promoted, ());
let span = self.tcx.hir().span(c.hir_id); let span = self.tcx.hir().span(c.hir_id);
self.preds.insert(( self.preds.insert((
ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink())) ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
.to_predicate(self.tcx), .to_predicate(self.tcx),
span, span,
)); ));

View file

@ -235,14 +235,13 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() { match n.kind() {
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => { ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
assert_eq!(promoted, ());
let mut s = if let Some(def) = def.as_local() { let mut s = if let Some(def) = def.as_local() {
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did)) print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
} else { } else {
inline::print_inlined_const(cx.tcx, def.did) inline::print_inlined_const(cx.tcx, def.did)
}; };
if let Some(promoted) = promoted {
s.push_str(&format!("::{:?}", promoted))
}
s s
} }
_ => { _ => {