提交 c81935e6 编写于 作者: B Bastian Kauschke

make `ConstEvaluatable` more strict

上级 7bc0bf72
......@@ -186,6 +186,19 @@ pub struct Body<'tcx> {
/// FIXME(oli-obk): rewrite the promoted during promotion to eliminate the cell components.
pub ignore_interior_mut_in_const_validation: bool,
/// Does this body use generic parameters. This is used for the `ConstEvaluatable` check.
///
/// Note that this does not actually mean that this body is not computable right now.
/// The repeat count in the following example is polymorphic, but can still be evaluated
/// without knowing anything about the type parameter `T`.
///
/// ```rust
/// fn test<T>() {
/// let _ = [0; std::mem::size_of::<*mut T>()];
/// }
/// ```
pub is_polymorphic: bool,
predecessor_cache: PredecessorCache,
}
......@@ -208,7 +221,7 @@ pub fn new(
local_decls.len()
);
Body {
let mut body = Body {
phase: MirPhase::Build,
basic_blocks,
source_scopes,
......@@ -224,8 +237,11 @@ pub fn new(
span,
required_consts: Vec::new(),
ignore_interior_mut_in_const_validation: false,
is_polymorphic: false,
predecessor_cache: PredecessorCache::new(),
}
};
body.is_polymorphic = body.has_param_types_or_consts();
body
}
/// Returns a partially initialized MIR body containing only a list of basic blocks.
......@@ -234,7 +250,7 @@ pub fn new(
/// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
/// crate.
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
Body {
let mut body = Body {
phase: MirPhase::Build,
basic_blocks,
source_scopes: IndexVec::new(),
......@@ -250,8 +266,11 @@ pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) ->
generator_kind: None,
var_debug_info: Vec::new(),
ignore_interior_mut_in_const_validation: false,
is_polymorphic: false,
predecessor_cache: PredecessorCache::new(),
}
};
body.is_polymorphic = body.has_param_types_or_consts();
body
}
#[inline]
......
......@@ -10,6 +10,7 @@
use rustc_middle::ty::{self, Binder, Const, Ty, TypeFoldable};
use std::marker::PhantomData;
use super::const_evaluatable;
use super::project;
use super::select::SelectionContext;
use super::wf;
......@@ -458,16 +459,17 @@ fn process_obligation(
}
ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
match self.selcx.infcx().const_eval_resolve(
obligation.param_env,
const_evaluatable::is_const_evaluatable(
self.selcx.infcx(),
def_id,
substs,
None,
Some(obligation.cause.span),
) {
Ok(_) => ProcessResult::Changed(vec![]),
Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))),
}
obligation.param_env,
obligation.cause.span,
)
.map_or_else(
|e| ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))),
|()| ProcessResult::Changed(vec![]),
)
}
ty::PredicateAtom::ConstEquate(c1, c2) => {
......
......@@ -7,6 +7,7 @@
mod chalk_fulfill;
pub mod codegen;
mod coherence;
mod const_evaluatable;
mod engine;
pub mod error_reporting;
mod fulfill;
......
......@@ -6,6 +6,7 @@
use self::SelectionCandidate::*;
use super::coherence::{self, Conflict};
use super::const_evaluatable;
use super::project;
use super::project::normalize_with_depth_to;
use super::util;
......@@ -542,17 +543,18 @@ fn evaluate_predicate_recursively<'o>(
}
ty::PredicateAtom::ConstEvaluatable(def_id, substs) => {
match self.tcx().const_eval_resolve(
obligation.param_env,
const_evaluatable::is_const_evaluatable(
self.infcx,
def_id,
substs,
None,
None,
) {
Ok(_) => Ok(EvaluatedToOk),
Err(ErrorHandled::TooGeneric) => Ok(EvaluatedToAmbig),
Err(_) => Ok(EvaluatedToErr),
}
obligation.param_env,
obligation.cause.span,
)
.map(|()| EvaluatedToOk)
.or_else(|e| match e {
ErrorHandled::TooGeneric => Ok(EvaluatedToAmbig),
_ => Ok(EvaluatedToErr),
})
}
ty::PredicateAtom::ConstEquate(c1, c2) => {
......
use rustc_middle::ty::{self, TypeFoldable};
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_hir::def::DefKind;
pub fn is_const_evaluatable<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>,
def: ty::WithOptConstParam<DefId>,
substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> Result<(), ErrorHandled>
{
let def_kind = infcx.tcx.def_kind(def.did);
match def_kind {
DefKind::AnonConst => {
let mir_body = if let Some(def) = def.as_const_arg() {
infcx.tcx.optimized_mir_of_const_arg(def)
} else {
infcx.tcx.optimized_mir(def.did)
};
if mir_body.is_polymorphic {
return Err(ErrorHandled::TooGeneric);
}
}
_ => {
if substs.has_param_types_or_consts() {
return Err(ErrorHandled::TooGeneric);
}
}
}
match infcx.const_eval_resolve(
param_env,
def,
substs,
None,
Some(span),
) {
Ok(_) => Ok(()),
Err(err) => {
if matches!(err, ErrorHandled::TooGeneric) {
infcx.tcx.sess.delay_span_bug(
span,
&format!("ConstEvaluatable too generic: {:?}, {:?}, {:?}", def, substs, param_env),
);
}
Err(err)
}
}
}
\ No newline at end of file
// check-pass
struct Foo<T>(T);
impl<T> Foo<T> {
const VALUE: usize = std::mem::size_of::<T>();
}
fn test<T>() {
let _ = [0; Foo::<u8>::VALUE];
}
fn main() {}
// run-pass
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
extern crate core;
......@@ -9,6 +7,7 @@
enum MyWeirdOption<T> {
None = 0,
Some(T) = core::mem::size_of::<*mut T>(),
//~^ ERROR constant expression depends on a generic parameter
}
fn main() {
......
error: constant expression depends on a generic parameter
--> $DIR/issue-70453-polymorphic-ctfe.rs:9:15
|
LL | Some(T) = core::mem::size_of::<*mut T>(),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: aborting due to previous error
......@@ -5,8 +5,7 @@
use std::marker::PhantomData;
pub struct S<'a>
{
pub struct S<'a> {
pub m1: PhantomData<&'a u8>,
pub m2: [u8; S::size()],
}
......
// check-pass
#![feature(lazy_normalization_consts)]
#![allow(incomplete_features)]
......@@ -10,5 +9,6 @@ impl<T: ?Sized> L<T> {
}
impl<T> X<T, [u8; L::<T>::S]> {}
//~^ ERROR constant expression depends on a generic parameter
fn main() {}
error: constant expression depends on a generic parameter
--> $DIR/issue-73980.rs:11:9
|
LL | impl<T> X<T, [u8; L::<T>::S]> {}
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: aborting due to previous error
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册