mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
make ConstEvaluatable
more strict
This commit is contained in:
parent
7bc0bf7254
commit
c81935e6df
@ -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 @@ impl<'tcx> Body<'tcx> {
|
||||
local_decls.len()
|
||||
);
|
||||
|
||||
Body {
|
||||
let mut body = Body {
|
||||
phase: MirPhase::Build,
|
||||
basic_blocks,
|
||||
source_scopes,
|
||||
@ -224,8 +237,11 @@ impl<'tcx> Body<'tcx> {
|
||||
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 @@ impl<'tcx> Body<'tcx> {
|
||||
/// 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 @@ impl<'tcx> Body<'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::ToPredicate;
|
||||
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 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ pub mod auto_trait;
|
||||
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::EvaluationResult::*;
|
||||
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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
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) => {
|
||||
|
54
src/librustc_trait_selection/traits/const_evaluatable.rs
Normal file
54
src/librustc_trait_selection/traits/const_evaluatable.rs
Normal file
@ -0,0 +1,54 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
11
src/test/ui/const_evaluatable/associated_const.rs
Normal file
11
src/test/ui/const_evaluatable/associated_const.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// 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() {}
|
@ -1,5 +1,3 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(arbitrary_enum_discriminant, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
@ -9,6 +7,7 @@ use core::intrinsics::discriminant_value;
|
||||
enum MyWeirdOption<T> {
|
||||
None = 0,
|
||||
Some(T) = core::mem::size_of::<*mut T>(),
|
||||
//~^ ERROR constant expression depends on a generic parameter
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
@ -0,0 +1,10 @@
|
||||
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()],
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
// 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() {}
|
||||
|
10
src/test/ui/lazy_normalization_consts/issue-73980.stderr
Normal file
10
src/test/ui/lazy_normalization_consts/issue-73980.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user