diff options
Diffstat (limited to 'compiler/rustc_mir_build/src')
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/as_constant.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs | 80 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/mod.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/builder/scope.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/errors.rs | 32 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/block.rs | 38 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/cx/expr.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 12 |
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); } } } |
