Skip to content

Commit 6361989

Browse files
Rollup merge of #116446 - compiler-errors:yeet-mir-from_anon_const, r=b-naber
Yeet `mir::Const::from_anon_const` Only had one callsite which was easily simplified. Uplifted a comment that I think is much more useful living in `ty::Const` world.
2 parents fe3038f + 8bf9c18 commit 6361989

File tree

5 files changed

+54
-103
lines changed

5 files changed

+54
-103
lines changed

compiler/rustc_middle/src/mir/consts.rs

+14-99
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
use std::fmt::{self, Debug, Display, Formatter};
22

33
use rustc_hir;
4-
use rustc_hir::def_id::{DefId, LocalDefId};
5-
use rustc_hir::{self as hir};
4+
use rustc_hir::def_id::DefId;
65
use rustc_session::RemapFileNameExt;
76
use rustc_span::Span;
87
use rustc_target::abi::{HasDataLayout, Size};
98

109
use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar};
1110
use crate::mir::{pretty_print_const_value, Promoted};
11+
use crate::ty::GenericArgsRef;
1212
use crate::ty::ScalarInt;
13-
use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt};
14-
use crate::ty::{GenericArgs, GenericArgsRef};
13+
use crate::ty::{self, print::pretty_print_const, Ty, TyCtxt};
1514

1615
///////////////////////////////////////////////////////////////////////////
1716
/// Evaluated Constants
@@ -220,6 +219,17 @@ pub enum Const<'tcx> {
220219
}
221220

222221
impl<'tcx> Const<'tcx> {
222+
pub fn identity_unevaluated(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::EarlyBinder<Const<'tcx>> {
223+
ty::EarlyBinder::bind(Const::Unevaluated(
224+
UnevaluatedConst {
225+
def: def_id,
226+
args: ty::GenericArgs::identity_for_item(tcx, def_id),
227+
promoted: None,
228+
},
229+
tcx.type_of(def_id).skip_binder(),
230+
))
231+
}
232+
223233
#[inline(always)]
224234
pub fn ty(&self) -> Ty<'tcx> {
225235
match self {
@@ -399,101 +409,6 @@ impl<'tcx> Const<'tcx> {
399409
Self::Val(val, ty)
400410
}
401411

402-
/// Literals are converted to `Const::Val`, const generic parameters are eagerly
403-
/// converted to a constant, everything else becomes `Unevaluated`.
404-
#[instrument(skip(tcx), level = "debug", ret)]
405-
pub fn from_anon_const(
406-
tcx: TyCtxt<'tcx>,
407-
def: LocalDefId,
408-
param_env: ty::ParamEnv<'tcx>,
409-
) -> Self {
410-
let body_id = match tcx.hir().get_by_def_id(def) {
411-
hir::Node::AnonConst(ac) => ac.body,
412-
_ => {
413-
span_bug!(tcx.def_span(def), "from_anon_const can only process anonymous constants")
414-
}
415-
};
416-
417-
let expr = &tcx.hir().body(body_id).value;
418-
debug!(?expr);
419-
420-
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
421-
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
422-
let expr = match &expr.kind {
423-
hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
424-
block.expr.as_ref().unwrap()
425-
}
426-
_ => expr,
427-
};
428-
debug!("expr.kind: {:?}", expr.kind);
429-
430-
let ty = tcx.type_of(def).instantiate_identity();
431-
debug!(?ty);
432-
433-
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
434-
// does not provide the parents generics to anonymous constants. We still allow generic const
435-
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
436-
// ever try to substitute the generic parameters in their bodies.
437-
//
438-
// While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does
439-
// cause issues if we were to remove that special-case and try to evaluate the constant instead.
440-
use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath};
441-
match expr.kind {
442-
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
443-
// Find the name and index of the const parameter by indexing the generics of
444-
// the parent item and construct a `ParamConst`.
445-
let item_def_id = tcx.parent(def_id);
446-
let generics = tcx.generics_of(item_def_id);
447-
let index = generics.param_def_id_to_index[&def_id];
448-
let name = tcx.item_name(def_id);
449-
let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty);
450-
debug!(?ty_const);
451-
452-
return Self::Ty(ty_const);
453-
}
454-
_ => {}
455-
}
456-
457-
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
458-
let parent_args = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id)
459-
&& let Some(parent_did) = parent_hir_id.as_owner()
460-
{
461-
GenericArgs::identity_for_item(tcx, parent_did)
462-
} else {
463-
List::empty()
464-
};
465-
debug!(?parent_args);
466-
467-
let did = def.to_def_id();
468-
let child_args = GenericArgs::identity_for_item(tcx, did);
469-
let args = tcx.mk_args_from_iter(parent_args.into_iter().chain(child_args.into_iter()));
470-
debug!(?args);
471-
472-
let span = tcx.def_span(def);
473-
let uneval = UnevaluatedConst::new(did, args);
474-
debug!(?span, ?param_env);
475-
476-
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
477-
Ok(val) => {
478-
debug!("evaluated const value");
479-
Self::Val(val, ty)
480-
}
481-
Err(_) => {
482-
debug!("error encountered during evaluation");
483-
// Error was handled in `const_eval_resolve`. Here we just create a
484-
// new unevaluated const and error hard later in codegen
485-
Self::Unevaluated(
486-
UnevaluatedConst {
487-
def: did,
488-
args: GenericArgs::identity_for_item(tcx, did),
489-
promoted: None,
490-
},
491-
ty,
492-
)
493-
}
494-
}
495-
}
496-
497412
pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
498413
match c.kind() {
499414
ty::ConstKind::Value(valtree) => {

compiler/rustc_middle/src/ty/consts.rs

+4
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ impl<'tcx> Const<'tcx> {
216216
}
217217
}
218218

219+
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
220+
// does not provide the parents generics to anonymous constants. We still allow generic const
221+
// parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to
222+
// ever try to substitute the generic parameters in their bodies.
219223
match expr.kind {
220224
hir::ExprKind::Path(hir::QPath::Resolved(
221225
_,

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

+12-4
Original file line numberDiff line numberDiff line change
@@ -642,15 +642,23 @@ impl<'tcx> Cx<'tcx> {
642642
}
643643
}
644644
hir::InlineAsmOperand::Const { ref anon_const } => {
645-
let value =
646-
mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env);
645+
let value = mir::Const::identity_unevaluated(
646+
tcx,
647+
anon_const.def_id.to_def_id(),
648+
)
649+
.instantiate_identity()
650+
.normalize(tcx, self.param_env);
647651
let span = tcx.def_span(anon_const.def_id);
648652

649653
InlineAsmOperand::Const { value, span }
650654
}
651655
hir::InlineAsmOperand::SymFn { ref anon_const } => {
652-
let value =
653-
mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env);
656+
let value = mir::Const::identity_unevaluated(
657+
tcx,
658+
anon_const.def_id.to_def_id(),
659+
)
660+
.instantiate_identity()
661+
.normalize(tcx, self.param_env);
654662
let span = tcx.def_span(anon_const.def_id);
655663

656664
InlineAsmOperand::SymFn { value, span }

tests/ui/asm/const-error.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// only-x86_64
2+
// needs-asm-support
3+
4+
#![feature(asm_const)]
5+
6+
// Test to make sure that we emit const errors eagerly for inline asm
7+
8+
use std::arch::asm;
9+
10+
fn test<T>() {
11+
unsafe { asm!("/* {} */", const 1 / 0); }
12+
//~^ ERROR evaluation of
13+
}
14+
15+
fn main() {}

tests/ui/asm/const-error.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0080]: evaluation of `test::<T>::{constant#0}` failed
2+
--> $DIR/const-error.rs:11:37
3+
|
4+
LL | unsafe { asm!("/* {} */", const 1 / 0); }
5+
| ^^^^^ attempt to divide `1_i32` by zero
6+
7+
error: aborting due to 1 previous error
8+
9+
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)