summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/thir/pattern/mod.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_mir_build/src/thir/pattern/mod.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_mir_build/src/thir/pattern/mod.rs')
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs127
1 files changed, 91 insertions, 36 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 1cf2f7ec0..600995927 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -18,14 +18,15 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::RangeEnd;
use rustc_index::Idx;
use rustc_middle::mir::interpret::{
- ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar,
+ ConstValue, ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar,
};
-use rustc_middle::mir::{self, UserTypeProjection};
+use rustc_middle::mir::{self, ConstantKind, UserTypeProjection};
use rustc_middle::mir::{BorrowKind, Mutability};
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange};
use rustc_middle::ty::subst::{GenericArg, SubstsRef};
use rustc_middle::ty::CanonicalUserTypeAnnotation;
-use rustc_middle::ty::{self, AdtDef, ConstKind, Region, Ty, TyCtxt, UserType};
+use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::{self, AdtDef, Region, Ty, TyCtxt, UserType};
use rustc_span::{Span, Symbol};
use rustc_target::abi::FieldIdx;
@@ -286,7 +287,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
ty::BindByValue(mutbl) => (mutbl, BindingMode::ByValue),
ty::BindByReference(hir::Mutability::Mut) => (
Mutability::Not,
- BindingMode::ByRef(BorrowKind::Mut { allow_two_phase_borrow: false }),
+ BindingMode::ByRef(BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
),
ty::BindByReference(hir::Mutability::Not) => {
(Mutability::Not, BindingMode::ByRef(BorrowKind::Shared))
@@ -518,16 +519,24 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
}
};
- // `mir_const_qualif` must be called with the `DefId` of the item where the const is
- // defined, not where it is declared. The difference is significant for associated
- // constants.
- let mir_structural_match_violation = self.tcx.mir_const_qualif(instance.def_id()).custom_eq;
- debug!("mir_structural_match_violation({:?}) -> {}", qpath, mir_structural_match_violation);
-
- match self.tcx.const_eval_instance(param_env_reveal_all, instance, Some(span)) {
- Ok(literal) => {
- let const_ = mir::ConstantKind::Val(literal, ty);
- let pattern = self.const_to_pat(const_, id, span, mir_structural_match_violation);
+ let cid = GlobalId { instance, promoted: None };
+ // Prefer valtrees over opaque constants.
+ let const_value = self
+ .tcx
+ .const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span))
+ .map(|val| match val {
+ Some(valtree) => mir::ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
+ None => mir::ConstantKind::Val(
+ self.tcx
+ .const_eval_global_id(param_env_reveal_all, cid, Some(span))
+ .expect("const_eval_global_id_for_typeck should have already failed"),
+ ty,
+ ),
+ });
+
+ match const_value {
+ Ok(const_) => {
+ let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id()));
if !is_associated_const {
return pattern;
@@ -573,31 +582,72 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
/// Converts inline const patterns.
fn lower_inline_const(
&mut self,
- anon_const: &'tcx hir::AnonConst,
+ block: &'tcx hir::ConstBlock,
id: hir::HirId,
span: Span,
) -> PatKind<'tcx> {
- let value = mir::ConstantKind::from_inline_const(self.tcx, anon_const.def_id);
-
- // Evaluate early like we do in `lower_path`.
- let value = value.eval(self.tcx, self.param_env);
-
- match value {
- mir::ConstantKind::Ty(c) => match c.kind() {
- ConstKind::Param(_) => {
- self.tcx.sess.emit_err(ConstParamInPattern { span });
- return PatKind::Wild;
+ let tcx = self.tcx;
+ let def_id = block.def_id;
+ let body_id = block.body;
+ let expr = &tcx.hir().body(body_id).value;
+ let ty = tcx.typeck(def_id).node_type(block.hir_id);
+
+ // Special case inline consts that are just literals. This is solely
+ // a performance optimization, as we could also just go through the regular
+ // const eval path below.
+ // FIXME: investigate the performance impact of removing this.
+ let lit_input = match expr.kind {
+ hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
+ hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
+ hir::ExprKind::Lit(ref lit) => {
+ Some(LitToConstInput { lit: &lit.node, ty, neg: true })
}
- ConstKind::Error(_) => {
- return PatKind::Wild;
- }
- _ => bug!("Expected ConstKind::Param"),
+ _ => None,
},
- mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
- mir::ConstantKind::Unevaluated(..) => {
- // If we land here it means the const can't be evaluated because it's `TooGeneric`.
- self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
- return PatKind::Wild;
+ _ => None,
+ };
+ if let Some(lit_input) = lit_input {
+ match tcx.at(expr.span).lit_to_const(lit_input) {
+ Ok(c) => return self.const_to_pat(ConstantKind::Ty(c), id, span, None).kind,
+ // If an error occurred, ignore that it's a literal
+ // and leave reporting the error up to const eval of
+ // the unevaluated constant below.
+ Err(_) => {}
+ }
+ }
+
+ let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
+ let parent_substs =
+ tcx.erase_regions(ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
+ let substs =
+ ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
+ .substs;
+
+ let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
+ debug_assert!(!substs.has_free_regions());
+
+ let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), substs: substs };
+ // First try using a valtree in order to destructure the constant into a pattern.
+ if let Ok(Some(valtree)) =
+ self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
+ {
+ self.const_to_pat(
+ ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
+ id,
+ span,
+ None,
+ )
+ .kind
+ } else {
+ // If that fails, convert it to an opaque constant pattern.
+ match tcx.const_eval_resolve(self.param_env, uneval, None) {
+ Ok(val) => self.const_to_pat(mir::ConstantKind::Val(val, ty), id, span, None).kind,
+ Err(ErrorHandled::TooGeneric) => {
+ // If we land here it means the const can't be evaluated because it's `TooGeneric`.
+ self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
+ PatKind::Wild
+ }
+ Err(ErrorHandled::Reported(_)) => PatKind::Wild,
}
}
}
@@ -626,8 +676,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let lit_input =
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
- match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) {
- Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
+ match self.tcx.at(expr.span).lit_to_const(lit_input) {
+ Ok(constant) => {
+ self.const_to_pat(ConstantKind::Ty(constant), expr.hir_id, lit.span, None).kind
+ }
Err(LitToConstError::Reported(_)) => PatKind::Wild,
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
}
@@ -806,6 +858,9 @@ pub(crate) fn compare_const_vals<'tcx>(
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(a)), _a_ty),
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(b)), _b_ty),
) => return Some(a.cmp(&b)),
+ (mir::ConstantKind::Ty(a), mir::ConstantKind::Ty(b)) => {
+ return Some(a.kind().cmp(&b.kind()));
+ }
_ => {}
},
}