about summary refs log tree commit diff
path: root/compiler/rustc_mir_build/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_build/src')
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_constant.rs27
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs80
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs6
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs29
-rw-r--r--compiler/rustc_mir_build/src/errors.rs32
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/block.rs38
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs39
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs12
8 files changed, 120 insertions, 143 deletions
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
index d0d0c21463f..0e0c7a7fa4f 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
@@ -3,7 +3,7 @@
 use rustc_abi::Size;
 use rustc_ast as ast;
 use rustc_hir::LangItem;
-use rustc_middle::mir::interpret::{Allocation, CTFE_ALLOC_SALT, LitToConstInput, Scalar};
+use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, LitToConstInput, Scalar};
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::{
@@ -120,17 +120,18 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
 
     let value = match (lit, lit_ty.kind()) {
         (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
-            let s = s.as_str();
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes(), ());
-            let allocation = tcx.mk_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
+            let s = s.as_str().as_bytes();
+            let len = s.len();
+            let allocation = tcx.allocate_bytes_dedup(s, CTFE_ALLOC_SALT);
+            ConstValue::Slice { alloc_id: allocation, meta: len.try_into().unwrap() }
         }
-        (ast::LitKind::ByteStr(data, _), ty::Ref(_, inner_ty, _))
+        (ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _))
             if matches!(inner_ty.kind(), ty::Slice(_)) =>
         {
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(data.as_byte_str(), ());
-            let allocation = tcx.mk_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
+            let data = byte_sym.as_byte_str();
+            let len = data.len();
+            let allocation = tcx.allocate_bytes_dedup(data, CTFE_ALLOC_SALT);
+            ConstValue::Slice { alloc_id: allocation, meta: len.try_into().unwrap() }
         }
         (ast::LitKind::ByteStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
             let id = tcx.allocate_bytes_dedup(byte_sym.as_byte_str(), CTFE_ALLOC_SALT);
@@ -138,10 +139,10 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
         }
         (ast::LitKind::CStr(byte_sym, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::CStr)) =>
         {
-            let allocation =
-                Allocation::from_bytes_byte_aligned_immutable(byte_sym.as_byte_str(), ());
-            let allocation = tcx.mk_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, meta: allocation.inner().size().bytes() }
+            let data = byte_sym.as_byte_str();
+            let len = data.len();
+            let allocation = tcx.allocate_bytes_dedup(data, CTFE_ALLOC_SALT);
+            ConstValue::Slice { alloc_id: allocation, meta: len.try_into().unwrap() }
         }
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
             ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1)))
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
index daf8fa5f19e..a4ef6e92739 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
@@ -1,6 +1,6 @@
 //! See docs in `build/expr/mod.rs`.
 
-use rustc_abi::{BackendRepr, FieldIdx, Primitive};
+use rustc_abi::FieldIdx;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::bug;
@@ -9,7 +9,6 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::cast::{CastTy, mir_cast_kind};
-use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, Ty, UpvarArgs};
 use rustc_span::source_map::Spanned;
@@ -200,8 +199,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 {
                     let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
                     let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
-                    let layout =
-                        this.tcx.layout_of(this.typing_env().as_query_input(source_expr.ty));
                     let discr = this.temp(discr_ty, source_expr.span);
                     this.cfg.push_assign(
                         block,
@@ -209,80 +206,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         discr,
                         Rvalue::Discriminant(temp.into()),
                     );
-                    let (op, ty) = (Operand::Move(discr), discr_ty);
-
-                    if let BackendRepr::Scalar(scalar) = layout.unwrap().backend_repr
-                        && !scalar.is_always_valid(&this.tcx)
-                        && let Primitive::Int(int_width, _signed) = scalar.primitive()
-                    {
-                        let unsigned_ty = int_width.to_ty(this.tcx, false);
-                        let unsigned_place = this.temp(unsigned_ty, expr_span);
-                        this.cfg.push_assign(
-                            block,
-                            source_info,
-                            unsigned_place,
-                            Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr), unsigned_ty),
-                        );
-
-                        let bool_ty = this.tcx.types.bool;
-                        let range = scalar.valid_range(&this.tcx);
-                        let merge_op =
-                            if range.start <= range.end { BinOp::BitAnd } else { BinOp::BitOr };
-
-                        let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
-                            // We can use `ty::TypingEnv::fully_monomorphized()` here
-                            // as we only need it to compute the layout of a primitive.
-                            let range_val = Const::from_bits(
-                                this.tcx,
-                                range,
-                                ty::TypingEnv::fully_monomorphized(),
-                                unsigned_ty,
-                            );
-                            let lit_op = this.literal_operand(expr.span, range_val);
-                            let is_bin_op = this.temp(bool_ty, expr_span);
-                            this.cfg.push_assign(
-                                block,
-                                source_info,
-                                is_bin_op,
-                                Rvalue::BinaryOp(
-                                    bin_op,
-                                    Box::new((Operand::Copy(unsigned_place), lit_op)),
-                                ),
-                            );
-                            is_bin_op
-                        };
-                        let assert_place = if range.start == 0 {
-                            comparer(range.end, BinOp::Le)
-                        } else {
-                            let start_place = comparer(range.start, BinOp::Ge);
-                            let end_place = comparer(range.end, BinOp::Le);
-                            let merge_place = this.temp(bool_ty, expr_span);
-                            this.cfg.push_assign(
-                                block,
-                                source_info,
-                                merge_place,
-                                Rvalue::BinaryOp(
-                                    merge_op,
-                                    Box::new((
-                                        Operand::Move(start_place),
-                                        Operand::Move(end_place),
-                                    )),
-                                ),
-                            );
-                            merge_place
-                        };
-                        this.cfg.push(
-                            block,
-                            Statement::new(
-                                source_info,
-                                StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
-                                    Operand::Move(assert_place),
-                                ))),
-                            ),
-                        );
-                    }
-
-                    (op, ty)
+                    (Operand::Move(discr), discr_ty)
                 } else {
                     let ty = source_expr.ty;
                     let source = unpack!(
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index 3d5f6f4cf45..855cd2f3bc0 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -1045,11 +1045,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 }
 
-fn parse_float_into_constval<'tcx>(
-    num: Symbol,
-    float_ty: ty::FloatTy,
-    neg: bool,
-) -> Option<ConstValue<'tcx>> {
+fn parse_float_into_constval(num: Symbol, float_ty: ty::FloatTy, neg: bool) -> Option<ConstValue> {
     parse_float_into_scalar(num, float_ty, neg).map(|s| ConstValue::Scalar(s.into()))
 }
 
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 12a56d7c5ea..1240b34cf9d 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -100,7 +100,9 @@ use tracing::{debug, instrument};
 
 use super::matches::BuiltMatchTree;
 use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
-use crate::errors::{ConstContinueBadConst, ConstContinueUnknownJumpTarget};
+use crate::errors::{
+    ConstContinueBadConst, ConstContinueNotMonomorphicConst, ConstContinueUnknownJumpTarget,
+};
 
 #[derive(Debug)]
 pub(crate) struct Scopes<'tcx> {
@@ -867,7 +869,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             span_bug!(span, "break value must be a scope")
         };
 
-        let constant = match &self.thir[value].kind {
+        let expr = &self.thir[value];
+        let constant = match &expr.kind {
             ExprKind::Adt(box AdtExpr { variant_index, fields, base, .. }) => {
                 assert!(matches!(base, AdtExprBase::None));
                 assert!(fields.is_empty());
@@ -887,7 +890,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     ),
                 }
             }
-            _ => self.as_constant(&self.thir[value]),
+
+            ExprKind::Literal { .. }
+            | ExprKind::NonHirLiteral { .. }
+            | ExprKind::ZstLiteral { .. }
+            | ExprKind::NamedConst { .. } => self.as_constant(&self.thir[value]),
+
+            other => {
+                use crate::errors::ConstContinueNotMonomorphicConstReason as Reason;
+
+                let span = expr.span;
+                let reason = match other {
+                    ExprKind::ConstParam { .. } => Reason::ConstantParameter { span },
+                    ExprKind::ConstBlock { .. } => Reason::ConstBlock { span },
+                    _ => Reason::Other { span },
+                };
+
+                self.tcx
+                    .dcx()
+                    .emit_err(ConstContinueNotMonomorphicConst { span: expr.span, reason });
+                return block.unit();
+            }
         };
 
         let break_index = self
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 16b49bf384c..f1fbd5c4a49 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1214,6 +1214,38 @@ pub(crate) struct LoopMatchArmWithGuard {
 }
 
 #[derive(Diagnostic)]
+#[diag(mir_build_const_continue_not_const)]
+#[help]
+pub(crate) struct ConstContinueNotMonomorphicConst {
+    #[primary_span]
+    pub span: Span,
+
+    #[subdiagnostic]
+    pub reason: ConstContinueNotMonomorphicConstReason,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ConstContinueNotMonomorphicConstReason {
+    #[label(mir_build_const_continue_not_const_constant_parameter)]
+    ConstantParameter {
+        #[primary_span]
+        span: Span,
+    },
+
+    #[label(mir_build_const_continue_not_const_const_block)]
+    ConstBlock {
+        #[primary_span]
+        span: Span,
+    },
+
+    #[label(mir_build_const_continue_not_const_const_other)]
+    Other {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Diagnostic)]
 #[diag(mir_build_const_continue_bad_const)]
 pub(crate) struct ConstContinueBadConst {
     #[primary_span]
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index e858b629ab1..57ddb8eddb8 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -76,28 +76,24 @@ impl<'tcx> ThirBuildCx<'tcx> {
                         let mut pattern = self.pattern_from_hir(local.pat);
                         debug!(?pattern);
 
-                        if let Some(ty) = &local.ty {
-                            if let Some(&user_ty) =
+                        if let Some(ty) = &local.ty
+                            && let Some(&user_ty) =
                                 self.typeck_results.user_provided_types().get(ty.hir_id)
-                            {
-                                debug!("mirror_stmts: user_ty={:?}", user_ty);
-                                let annotation = CanonicalUserTypeAnnotation {
-                                    user_ty: Box::new(user_ty),
-                                    span: ty.span,
-                                    inferred_ty: self.typeck_results.node_type(ty.hir_id),
-                                };
-                                pattern = Box::new(Pat {
-                                    ty: pattern.ty,
-                                    span: pattern.span,
-                                    kind: PatKind::AscribeUserType {
-                                        ascription: Ascription {
-                                            annotation,
-                                            variance: ty::Covariant,
-                                        },
-                                        subpattern: pattern,
-                                    },
-                                });
-                            }
+                        {
+                            debug!("mirror_stmts: user_ty={:?}", user_ty);
+                            let annotation = CanonicalUserTypeAnnotation {
+                                user_ty: Box::new(user_ty),
+                                span: ty.span,
+                                inferred_ty: self.typeck_results.node_type(ty.hir_id),
+                            };
+                            pattern = Box::new(Pat {
+                                ty: pattern.ty,
+                                span: pattern.span,
+                                kind: PatKind::AscribeUserType {
+                                    ascription: Ascription { annotation, variance: ty::Covariant },
+                                    subpattern: pattern,
+                                },
+                            });
                         }
 
                         let span = match local.init {
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index b694409f327..16df58cd76d 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -105,11 +105,11 @@ impl<'tcx> ThirBuildCx<'tcx> {
         //   // ^ error message points at this expression.
         // }
         let mut adjust_span = |expr: &mut Expr<'tcx>| {
-            if let ExprKind::Block { block } = expr.kind {
-                if let Some(last_expr) = self.thir[block].expr {
-                    span = self.thir[last_expr].span;
-                    expr.span = span;
-                }
+            if let ExprKind::Block { block } = expr.kind
+                && let Some(last_expr) = self.thir[block].expr
+            {
+                span = self.thir[last_expr].span;
+                expr.span = span;
             }
         };
 
@@ -955,21 +955,25 @@ impl<'tcx> ThirBuildCx<'tcx> {
                         dcx.emit_fatal(LoopMatchBadRhs { span: block_body_expr.span })
                     };
 
-                    fn local(expr: &rustc_hir::Expr<'_>) -> Option<hir::HirId> {
-                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind {
-                            if let Res::Local(hir_id) = path.res {
-                                return Some(hir_id);
-                            }
+                    fn local(
+                        cx: &mut ThirBuildCx<'_>,
+                        expr: &rustc_hir::Expr<'_>,
+                    ) -> Option<hir::HirId> {
+                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
+                            && let Res::Local(hir_id) = path.res
+                            && !cx.is_upvar(hir_id)
+                        {
+                            return Some(hir_id);
                         }
 
                         None
                     }
 
-                    let Some(scrutinee_hir_id) = local(scrutinee) else {
+                    let Some(scrutinee_hir_id) = local(self, scrutinee) else {
                         dcx.emit_fatal(LoopMatchInvalidMatch { span: scrutinee.span })
                     };
 
-                    if local(state) != Some(scrutinee_hir_id) {
+                    if local(self, state) != Some(scrutinee_hir_id) {
                         dcx.emit_fatal(LoopMatchInvalidUpdate {
                             scrutinee: scrutinee.span,
                             lhs: state.span,
@@ -1260,10 +1264,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
     fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> {
         // We want upvars here not captures.
         // Captures will be handled in MIR.
-        let is_upvar = self
-            .tcx
-            .upvars_mentioned(self.body_owner)
-            .is_some_and(|upvars| upvars.contains_key(&var_hir_id));
+        let is_upvar = self.is_upvar(var_hir_id);
 
         debug!(
             "convert_var({:?}): is_upvar={}, body_owner={:?}",
@@ -1443,6 +1444,12 @@ impl<'tcx> ThirBuildCx<'tcx> {
         }
     }
 
+    fn is_upvar(&mut self, var_hir_id: hir::HirId) -> bool {
+        self.tcx
+            .upvars_mentioned(self.body_owner)
+            .is_some_and(|upvars| upvars.contains_key(&var_hir_id))
+    }
+
     /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
     fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
         fields
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 7f47754f6bc..ae67bb5075e 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1155,14 +1155,12 @@ fn find_fallback_pattern_typo<'tcx>(
                     }
                     hir::Node::Block(hir::Block { stmts, .. }) => {
                         for stmt in *stmts {
-                            if let hir::StmtKind::Let(let_stmt) = stmt.kind {
-                                if let hir::PatKind::Binding(_, _, binding_name, _) =
+                            if let hir::StmtKind::Let(let_stmt) = stmt.kind
+                                && let hir::PatKind::Binding(_, _, binding_name, _) =
                                     let_stmt.pat.kind
-                                {
-                                    if name == binding_name.name {
-                                        lint.pattern_let_binding = Some(binding_name.span);
-                                    }
-                                }
+                                && name == binding_name.name
+                            {
+                                lint.pattern_let_binding = Some(binding_name.span);
                             }
                         }
                     }