Skip to content

Commit 9b28d3b

Browse files
committed
try to evaluate in from_opt_const_arg_anon_const
1 parent d0e05f0 commit 9b28d3b

File tree

2 files changed

+78
-8
lines changed
  • compiler

2 files changed

+78
-8
lines changed

compiler/rustc_middle/src/mir/mod.rs

+73-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::ty::adjustment::PointerCast;
99
use crate::ty::codec::{TyDecoder, TyEncoder};
1010
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor};
1111
use crate::ty::print::{FmtPrinter, Printer};
12-
use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
12+
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
1313
use crate::ty::{self, List, Ty, TyCtxt};
1414
use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex};
1515

@@ -2901,14 +2901,19 @@ impl<'tcx> ConstantKind<'tcx> {
29012901

29022902
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
29032903
/// converted to a constant, everything else becomes `Unevaluated`.
2904-
pub fn from_anon_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
2905-
Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id))
2904+
pub fn from_anon_const(
2905+
tcx: TyCtxt<'tcx>,
2906+
def_id: LocalDefId,
2907+
param_env: ty::ParamEnv<'tcx>,
2908+
) -> Self {
2909+
Self::from_opt_const_arg_anon_const(tcx, ty::WithOptConstParam::unknown(def_id), param_env)
29062910
}
29072911

29082912
#[instrument(skip(tcx), level = "debug")]
29092913
fn from_opt_const_arg_anon_const(
29102914
tcx: TyCtxt<'tcx>,
29112915
def: ty::WithOptConstParam<LocalDefId>,
2916+
param_env: ty::ParamEnv<'tcx>,
29122917
) -> Self {
29132918
let body_id = match tcx.hir().get_by_def_id(def.did) {
29142919
hir::Node::AnonConst(ac) => ac.body,
@@ -2921,11 +2926,72 @@ impl<'tcx> ConstantKind<'tcx> {
29212926
let expr = &tcx.hir().body(body_id).value;
29222927
debug!(?expr);
29232928

2929+
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
2930+
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
2931+
let expr = match &expr.kind {
2932+
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
2933+
block.expr.as_ref().unwrap()
2934+
}
2935+
_ => expr,
2936+
};
2937+
29242938
let ty = tcx.type_of(def.def_id_for_type_of());
29252939

2926-
match Self::try_eval_lit_or_param(tcx, ty, expr) {
2927-
Some(v) => v,
2928-
None => {
2940+
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
2941+
// does not provide the parents generics to anonymous constants. We still allow generic const
2942+
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
2943+
// ever try to substitute the generic parameters in their bodies.
2944+
//
2945+
// While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does
2946+
// cause issues if we were to remove that special-case and try to evaluate the constant instead.
2947+
use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
2948+
match expr.kind {
2949+
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
2950+
// Find the name and index of the const parameter by indexing the generics of
2951+
// the parent item and construct a `ParamConst`.
2952+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
2953+
let item_id = tcx.hir().get_parent_node(hir_id);
2954+
let item_def_id = tcx.hir().local_def_id(item_id);
2955+
let generics = tcx.generics_of(item_def_id.to_def_id());
2956+
let index = generics.param_def_id_to_index[&def_id];
2957+
let name = tcx.hir().name(hir_id);
2958+
let ty_const = tcx.mk_const(ty::ConstS {
2959+
val: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
2960+
ty,
2961+
});
2962+
2963+
return Self::Ty(ty_const);
2964+
}
2965+
_ => {}
2966+
}
2967+
2968+
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
2969+
let parent_substs = if let Some(parent_hir_id) = tcx.hir().find_parent_node(hir_id) {
2970+
if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) {
2971+
InternalSubsts::identity_for_item(tcx, parent_did.to_def_id())
2972+
} else {
2973+
tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
2974+
}
2975+
} else {
2976+
tcx.mk_substs(Vec::<GenericArg<'tcx>>::new().into_iter())
2977+
};
2978+
debug!(?parent_substs);
2979+
2980+
let did = def.did.to_def_id();
2981+
let child_substs = InternalSubsts::identity_for_item(tcx, did);
2982+
let substs = tcx.mk_substs(parent_substs.into_iter().chain(child_substs.into_iter()));
2983+
debug!(?substs);
2984+
2985+
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
2986+
let span = tcx.hir().span(hir_id);
2987+
let uneval = ty::Unevaluated::new(def.to_global(), substs);
2988+
debug!(?span, ?param_env);
2989+
2990+
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
2991+
Ok(val) => Self::Val(val, ty),
2992+
Err(_) => {
2993+
// Error was handled in `const_eval_resolve`. Here we just create a
2994+
// new unevaluated const and error hard later in codegen
29292995
let ty_const = tcx.mk_const(ty::ConstS {
29302996
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
29312997
def: def.to_global(),
@@ -2934,6 +3000,7 @@ impl<'tcx> ConstantKind<'tcx> {
29343000
}),
29353001
ty,
29363002
});
3003+
29373004
Self::Ty(ty_const)
29383005
}
29393006
}

compiler/rustc_mir_build/src/thir/cx/expr.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,11 @@ impl<'tcx> Cx<'tcx> {
491491
hir::InlineAsmOperand::Const { ref anon_const } => {
492492
let anon_const_def_id =
493493
self.tcx.hir().local_def_id(anon_const.hir_id);
494-
let value =
495-
mir::ConstantKind::from_anon_const(self.tcx, anon_const_def_id);
494+
let value = mir::ConstantKind::from_anon_const(
495+
self.tcx,
496+
anon_const_def_id,
497+
self.param_env,
498+
);
496499
let span = self.tcx.hir().span(anon_const.hir_id);
497500

498501
InlineAsmOperand::Const { value, span }

0 commit comments

Comments
 (0)