Skip to content

Commit 81b07ed

Browse files
committed
Inline from_inline_const into its sole call site
1 parent c4d5dde commit 81b07ed

File tree

2 files changed

+62
-78
lines changed
  • compiler
    • rustc_middle/src/mir
    • rustc_mir_build/src/thir/pattern

2 files changed

+62
-78
lines changed

compiler/rustc_middle/src/mir/mod.rs

+1-46
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
44
55
use crate::mir::interpret::{
6-
AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, LitToConstInput, Scalar,
6+
AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
77
};
88
use crate::mir::visit::MirVisitable;
99
use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -2461,51 +2461,6 @@ impl<'tcx> ConstantKind<'tcx> {
24612461
Self::Val(val, ty)
24622462
}
24632463

2464-
#[instrument(skip(tcx), level = "debug", ret)]
2465-
pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
2466-
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
2467-
let body_id = match tcx.hir().get(hir_id) {
2468-
hir::Node::AnonConst(ac) => ac.body,
2469-
_ => span_bug!(
2470-
tcx.def_span(def_id.to_def_id()),
2471-
"from_inline_const can only process anonymous constants"
2472-
),
2473-
};
2474-
let expr = &tcx.hir().body(body_id).value;
2475-
let ty = tcx.typeck(def_id).node_type(hir_id);
2476-
2477-
let lit_input = match expr.kind {
2478-
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
2479-
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
2480-
hir::ExprKind::Lit(ref lit) => {
2481-
Some(LitToConstInput { lit: &lit.node, ty, neg: true })
2482-
}
2483-
_ => None,
2484-
},
2485-
_ => None,
2486-
};
2487-
if let Some(lit_input) = lit_input {
2488-
// If an error occurred, ignore that it's a literal and leave reporting the error up to
2489-
// mir.
2490-
match tcx.at(expr.span).lit_to_const(lit_input) {
2491-
Ok(c) => return Self::Ty(c),
2492-
Err(_) => {}
2493-
}
2494-
}
2495-
2496-
let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
2497-
let parent_substs =
2498-
tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
2499-
let substs =
2500-
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
2501-
.substs;
2502-
2503-
let uneval = UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
2504-
debug_assert!(!uneval.has_free_regions());
2505-
2506-
Self::Unevaluated(uneval, ty)
2507-
}
2508-
25092464
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
25102465
/// converted to a constant, everything else becomes `Unevaluated`.
25112466
#[instrument(skip(tcx), level = "debug", ret)]

compiler/rustc_mir_build/src/thir/pattern/mod.rs

+61-32
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ use rustc_middle::mir::{BorrowKind, Mutability};
2525
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange};
2626
use rustc_middle::ty::subst::{GenericArg, SubstsRef};
2727
use rustc_middle::ty::CanonicalUserTypeAnnotation;
28-
use rustc_middle::ty::{self, AdtDef, ConstKind, Region, Ty, TyCtxt, UserType};
28+
use rustc_middle::ty::TypeVisitableExt;
29+
use rustc_middle::ty::{self, AdtDef, Region, Ty, TyCtxt, UserType};
2930
use rustc_span::{Span, Symbol};
3031
use rustc_target::abi::FieldIdx;
3132

@@ -585,43 +586,71 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
585586
id: hir::HirId,
586587
span: Span,
587588
) -> PatKind<'tcx> {
588-
let value = mir::ConstantKind::from_inline_const(self.tcx, anon_const.def_id);
589-
let value = match value {
590-
mir::ConstantKind::Ty(_) => value,
591-
// Evaluate early like we do in `lower_path`.
592-
mir::ConstantKind::Unevaluated(ct, ty) => {
593-
let ct = ty::UnevaluatedConst { def: ct.def, substs: ct.substs };
594-
if let Ok(Some(valtree)) =
595-
self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
596-
{
597-
mir::ConstantKind::Ty(self.tcx.mk_const(valtree, ty))
598-
} else {
599-
value.eval(self.tcx, self.param_env)
600-
}
601-
}
602-
mir::ConstantKind::Val(_, _) => unreachable!(),
589+
let tcx = self.tcx;
590+
let def_id = anon_const.def_id;
591+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
592+
let body_id = match tcx.hir().get(hir_id) {
593+
hir::Node::AnonConst(ac) => ac.body,
594+
_ => span_bug!(
595+
tcx.def_span(def_id.to_def_id()),
596+
"from_inline_const can only process anonymous constants"
597+
),
603598
};
604-
605-
match value {
606-
mir::ConstantKind::Ty(c) => match c.kind() {
607-
ConstKind::Param(_) => {
608-
self.tcx.sess.emit_err(ConstParamInPattern { span });
609-
return PatKind::Wild;
610-
}
611-
ConstKind::Error(_) => {
612-
return PatKind::Wild;
599+
let expr = &tcx.hir().body(body_id).value;
600+
let ty = tcx.typeck(def_id).node_type(hir_id);
601+
602+
// Special case inline consts that are just literals. This is solely
603+
// a performance optimization, as we could also just go through the regular
604+
// const eval path below.
605+
// FIXME: investigate the performance impact of removing this.
606+
let lit_input = match expr.kind {
607+
hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
608+
hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
609+
hir::ExprKind::Lit(ref lit) => {
610+
Some(LitToConstInput { lit: &lit.node, ty, neg: true })
613611
}
614-
_ => {}
612+
_ => None,
615613
},
616-
mir::ConstantKind::Val(_, _) => {}
617-
mir::ConstantKind::Unevaluated(..) => {
618-
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
619-
self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
620-
return PatKind::Wild;
614+
_ => None,
615+
};
616+
if let Some(lit_input) = lit_input {
617+
match tcx.at(expr.span).lit_to_const(lit_input) {
618+
Ok(c) => return self.const_to_pat(ConstantKind::Ty(c), id, span, None).kind,
619+
// If an error occurred, ignore that it's a literal
620+
// and leave reporting the error up to const eval of
621+
// the unevaluated constant below.
622+
Err(_) => {}
621623
}
622624
}
623625

624-
self.const_to_pat(value, id, span, None).kind
626+
let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
627+
let parent_substs =
628+
tcx.erase_regions(ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
629+
let substs =
630+
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
631+
.substs;
632+
633+
let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
634+
debug_assert!(!substs.has_free_regions());
635+
636+
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), substs: substs };
637+
// First try using a valtree in order to destructure the constant into a pattern.
638+
if let Ok(Some(valtree)) =
639+
self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
640+
{
641+
self.const_to_pat(ConstantKind::Ty(self.tcx.mk_const(valtree, ty)), id, span, None).kind
642+
} else {
643+
// If that fails, convert it to an opaque constant pattern.
644+
match tcx.const_eval_resolve(self.param_env, uneval, None) {
645+
Ok(val) => self.const_to_pat(mir::ConstantKind::Val(val, ty), id, span, None).kind,
646+
Err(ErrorHandled::TooGeneric) => {
647+
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
648+
self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
649+
PatKind::Wild
650+
}
651+
Err(ErrorHandled::Reported(_)) => PatKind::Wild,
652+
}
653+
}
625654
}
626655

627656
/// Converts literals, paths and negation of literals to patterns.

0 commit comments

Comments
 (0)