-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Evaluate repeat expression lengths as late as possible #69981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
799b15e
fa5a15c
3f89c38
770be24
9bcd9fe
124ab20
5aa15bf
4f513b5
9b1893f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,7 +149,9 @@ impl<'tcx> Rvalue<'tcx> { | |
{ | ||
match *self { | ||
Rvalue::Use(ref operand) => operand.ty(local_decls, tcx), | ||
Rvalue::Repeat(ref operand, count) => tcx.mk_array(operand.ty(local_decls, tcx), count), | ||
Rvalue::Repeat(ref operand, count) => { | ||
tcx.mk_ty(ty::Array(operand.ty(local_decls, tcx), count)) | ||
Comment on lines
-152
to
+153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder when we can have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likely never, we have 14 uses in the code base, and half of them are |
||
} | ||
Rvalue::Ref(reg, bk, ref place) => { | ||
let place_ty = place.ty(local_decls, tcx).ty; | ||
tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() }) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ use self::TyKind::*; | |
use crate::infer::canonical::Canonical; | ||
use crate::middle::region; | ||
use crate::mir::interpret::ConstValue; | ||
use crate::mir::interpret::Scalar; | ||
use crate::mir::interpret::{LitToConstInput, Scalar}; | ||
use crate::mir::Promoted; | ||
use crate::ty::layout::VariantIdx; | ||
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; | ||
|
@@ -20,7 +20,7 @@ use polonius_engine::Atom; | |
use rustc_ast::ast::{self, Ident}; | ||
use rustc_data_structures::captures::Captures; | ||
use rustc_hir as hir; | ||
use rustc_hir::def_id::DefId; | ||
use rustc_hir::def_id::{DefId, LocalDefId}; | ||
use rustc_index::vec::Idx; | ||
use rustc_macros::HashStable; | ||
use rustc_span::symbol::{kw, Symbol}; | ||
|
@@ -2402,17 +2402,89 @@ pub struct Const<'tcx> { | |
static_assert_size!(Const<'_>, 48); | ||
|
||
impl<'tcx> Const<'tcx> { | ||
/// Literals and const generic parameters are eagerly converted to a constant, everything else | ||
/// becomes `Unevaluated`. | ||
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx Self { | ||
debug!("Const::from_anon_const(id={:?})", def_id); | ||
|
||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); | ||
|
||
let body_id = match tcx.hir().get(hir_id) { | ||
hir::Node::AnonConst(ac) => ac.body, | ||
_ => span_bug!(tcx.def_span(def_id.to_def_id()), "from_anon_const can only process anonymous constants"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My kingdom for a custom coercion |
||
}; | ||
|
||
let expr = &tcx.hir().body(body_id).value; | ||
|
||
let ty = tcx.type_of(def_id.to_def_id()); | ||
|
||
let lit_input = match expr.kind { | ||
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), | ||
hir::ExprKind::Unary(hir::UnOp::UnNeg, ref expr) => match expr.kind { | ||
hir::ExprKind::Lit(ref lit) => { | ||
Some(LitToConstInput { lit: &lit.node, ty, neg: true }) | ||
} | ||
_ => None, | ||
}, | ||
_ => None, | ||
}; | ||
|
||
if let Some(lit_input) = lit_input { | ||
// If an error occurred, ignore that it's a literal and leave reporting the error up to | ||
// mir. | ||
if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { | ||
return c; | ||
} else { | ||
tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const"); | ||
oli-obk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments | ||
// currently have to be wrapped in curly brackets, so it's necessary to special-case. | ||
let expr = match &expr.kind { | ||
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { | ||
block.expr.as_ref().unwrap() | ||
} | ||
_ => expr, | ||
}; | ||
|
||
use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; | ||
let val = match expr.kind { | ||
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { | ||
// Find the name and index of the const parameter by indexing the generics of | ||
// the parent item and construct a `ParamConst`. | ||
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); | ||
let item_id = tcx.hir().get_parent_node(hir_id); | ||
let item_def_id = tcx.hir().local_def_id(item_id); | ||
let generics = tcx.generics_of(item_def_id); | ||
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(hir_id)]; | ||
let name = tcx.hir().name(hir_id); | ||
ty::ConstKind::Param(ty::ParamConst::new(index, name)) | ||
} | ||
_ => ty::ConstKind::Unevaluated( | ||
def_id.to_def_id(), | ||
InternalSubsts::identity_for_item(tcx, def_id.to_def_id()), | ||
None, | ||
), | ||
}; | ||
|
||
tcx.mk_const(ty::Const { val, ty }) | ||
} | ||
|
||
#[inline] | ||
/// Interns the given value as a constant. | ||
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { | ||
tcx.mk_const(Self { val: ConstKind::Value(val), ty }) | ||
} | ||
|
||
#[inline] | ||
/// Interns the given scalar as a constant. | ||
pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self { | ||
Self::from_value(tcx, ConstValue::Scalar(val), ty) | ||
} | ||
|
||
#[inline] | ||
/// Creates a constant with the given integer value and interns it. | ||
pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx Self { | ||
let size = tcx | ||
.layout_of(ty) | ||
|
@@ -2422,21 +2494,27 @@ impl<'tcx> Const<'tcx> { | |
} | ||
|
||
#[inline] | ||
/// Creates an interned zst constant. | ||
pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { | ||
Self::from_scalar(tcx, Scalar::zst(), ty) | ||
} | ||
|
||
#[inline] | ||
/// Creates an interned bool constant. | ||
pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> &'tcx Self { | ||
Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) | ||
} | ||
|
||
#[inline] | ||
/// Creates an interned usize constant. | ||
pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> &'tcx Self { | ||
Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) | ||
} | ||
|
||
#[inline] | ||
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of | ||
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it | ||
/// contains const generic parameters or pointers). | ||
pub fn try_eval_bits( | ||
&self, | ||
tcx: TyCtxt<'tcx>, | ||
|
@@ -2450,6 +2528,8 @@ impl<'tcx> Const<'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> { | ||
let try_const_eval = |did, param_env: ParamEnv<'tcx>, substs, promoted| { | ||
let param_env_and_substs = param_env.with_reveal_all().and(substs); | ||
|
@@ -2506,12 +2586,14 @@ impl<'tcx> Const<'tcx> { | |
} | ||
|
||
#[inline] | ||
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. | ||
pub fn eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { | ||
self.try_eval_bits(tcx, param_env, ty) | ||
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) | ||
} | ||
|
||
#[inline] | ||
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. | ||
pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { | ||
self.eval_bits(tcx, param_env, tcx.types.usize) as u64 | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.