diff options
Diffstat (limited to 'compiler/rustc_const_eval/src/transform')
6 files changed, 93 insertions, 43 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 55080d94f..57d939747 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -556,7 +556,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {} Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, operand) => { @@ -872,7 +872,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { debug!("Resolving ({:?}) -> {:?}", callee, instance); if let Ok(Some(func)) = instance { if let InstanceDef::Item(def) = func.def { - callee = def.did; + callee = def; } } } @@ -942,7 +942,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == gate) }; let feature_gate_declared = gate_declared(gate); - let implied_gate_declared = implied_by.map(gate_declared).unwrap_or(false); + let implied_gate_declared = implied_by.is_some_and(gate_declared); if !feature_gate_declared && !implied_gate_declared { self.check_op(ops::FnCallUnstable(callee, Some(gate))); return; @@ -969,7 +969,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // have no `rustc_const_stable` attributes to be const-unstable as well. This // should be fixed later. let callee_is_unstable_unmarked = tcx.lookup_const_stability(callee).is_none() - && tcx.lookup_stability(callee).map_or(false, |s| s.is_unstable()); + && tcx.lookup_stability(callee).is_some_and(|s| s.is_unstable()); if callee_is_unstable_unmarked { trace!("callee_is_unstable_unmarked"); // We do not use `const` modifiers for intrinsic "functions", as intrinsics are diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index 0e4501922..8ebfee887 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -139,5 +139,5 @@ fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { return false; } - tcx.lookup_const_stability(parent.owner).map_or(false, |stab| stab.is_const_stable()) + tcx.lookup_const_stability(parent.owner).is_some_and(|stab| stab.is_const_stable()) } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index c0f5b3725..21f3c2c89 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty}; use rustc_middle::ty::{Binder, TraitRef}; +use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{BytePos, Pos, Span, Symbol}; @@ -21,7 +22,6 @@ use rustc_trait_selection::traits::SelectionContext; use super::ConstCx; use crate::errors; -use crate::util::{call_kind, CallDesugaringKind, CallKind}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Status { @@ -77,7 +77,7 @@ impl<'tcx> NonConstOp<'tcx> for FloatingPointOp { &ccx.tcx.sess.parse_sess, sym::const_fn_floating_point_arithmetic, span, - &format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()), + format!("floating point arithmetic is not allowed in {}s", ccx.const_kind()), ) } } @@ -184,6 +184,9 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { CallDesugaringKind::TryBlockFromOutput => { error!("`try` block cannot convert `{}` to the result in {}s") } + CallDesugaringKind::Await => { + error!("cannot convert `{}` into a future in {}s") + } }; diag_trait(&mut err, self_ty, kind.trait_def_id(tcx)); @@ -208,13 +211,13 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { err.span_note(span, "function defined here, but it is not `const`"); } FnPtr(..) => { - err.note(&format!( + err.note(format!( "function pointers need an RFC before allowed to be called in {}s", ccx.const_kind() )); } Closure(..) => { - err.note(&format!( + err.note(format!( "closures need an RFC before allowed to be called in {}s", ccx.const_kind() )); @@ -286,7 +289,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ccx.const_kind() ); - err.note(&format!("attempting to deref into `{}`", deref_target_ty)); + err.note(format!("attempting to deref into `{}`", deref_target_ty)); // Check first whether the source is accessible (issue #87060) if tcx.sess.source_map().is_span_accessible(deref_target) { @@ -296,7 +299,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span))); err } - _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx + _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => ccx .tcx .sess .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }), @@ -307,14 +310,14 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { }), }; - err.note(&format!( + err.note(format!( "calls in {}s are limited to constant functions, \ tuple structs and tuple variants", ccx.const_kind(), )); if let Some(feature) = feature && ccx.tcx.sess.is_nightly_build() { - err.help(&format!( + err.help(format!( "add `#![feature({})]` to the crate attributes to enable", feature, )); @@ -351,7 +354,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable { err.help("const-stable functions can only call other const-stable functions"); } else if ccx.tcx.sess.is_nightly_build() { if let Some(feature) = feature { - err.help(&format!( + err.help(format!( "add `#![feature({})]` to the crate attributes to enable", feature )); @@ -610,10 +613,11 @@ pub struct RawPtrComparison; impl<'tcx> NonConstOp<'tcx> for RawPtrComparison { fn build_error( &self, - _: &ConstCx<'_, 'tcx>, + ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - span_bug!(span, "raw ptr comparison should already be caught in the trait system"); + // FIXME(const_trait_impl): revert to span_bug? + ccx.tcx.sess.create_err(errors::RawPtrComparisonErr { span }) } } @@ -633,7 +637,7 @@ impl<'tcx> NonConstOp<'tcx> for RawMutPtrDeref { &ccx.tcx.sess.parse_sess, sym::const_mut_refs, span, - &format!("dereferencing raw mutable pointers in {}s is unstable", ccx.const_kind(),), + format!("dereferencing raw mutable pointers in {}s is unstable", ccx.const_kind(),), ) } } @@ -720,7 +724,7 @@ pub mod ty { &ccx.tcx.sess.parse_sess, sym::const_mut_refs, span, - &format!("mutable references are not allowed in {}s", ccx.const_kind()), + format!("mutable references are not allowed in {}s", ccx.const_kind()), ) } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 6758cba2e..1da205790 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -157,7 +157,7 @@ impl Qualif for NeedsNonConstDrop { cx.tcx, ObligationCause::dummy_with_span(cx.body.span), cx.param_env, - ty::Binder::dummy(cx.tcx.at(cx.body.span).mk_trait_ref(LangItem::Destruct, [ty])) + ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty]) .with_constness(ty::BoundConstness::ConstIfConst), ); @@ -364,9 +364,8 @@ where assert!(promoted.is_none() || Q::ALLOW_PROMOTED); // Don't peek inside trait associated constants. - if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() { - assert_eq!(def.const_param_did, None, "expected associated const: {def:?}"); - let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did); + if promoted.is_none() && cx.tcx.trait_of_item(def).is_none() { + let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def); if !Q::in_qualifs(&qualifs) { return false; diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 7919aed09..0e2d9ee8f 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt}; use rustc_span::Span; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; +use rustc_index::{Idx, IndexSlice, IndexVec}; use std::cell::Cell; use std::{cmp, iter, mem}; @@ -514,6 +514,7 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::NullaryOp(op, _) => match op { NullOp::SizeOf => {} NullOp::AlignOf => {} + NullOp::OffsetOf(_) => {} }, Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), @@ -828,7 +829,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> { - let def = self.source.source.with_opt_param(); + let def = self.source.source.def_id(); let mut rvalue = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); @@ -836,7 +837,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let mut promoted_operand = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); - let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did)); + let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def)); let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) }; Operand::Constant(Box::new(Constant { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index d4bed9738..3c350e25b 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -2,15 +2,16 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_infer::traits::Reveal; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, - MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, - RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator, - TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, START_BLOCK, + MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef, + ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, + Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, + START_BLOCK, }; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeStorageLive; @@ -106,7 +107,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // occurred. self.tcx.sess.diagnostic().delay_span_bug( span, - &format!( + format!( "broken MIR in {:?} ({}) at {:?}:\n{}", self.body.source.instance, self.when, @@ -163,7 +164,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Some(root) = post_contract_node.get(&bb) { break *root; } - let parent = doms.immediate_dominator(bb); + let parent = doms.immediate_dominator(bb).unwrap(); dom_path.push(bb); if !self.body.basic_blocks[parent].is_cleanup { break bb; @@ -262,7 +263,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // We sometimes have to use `defining_opaque_types` for subtyping // to succeed here and figuring out how exactly that should work // is annoying. It is harmless enough to just not validate anything - // in that case. We still check this after analysis as all opque + // in that case. We still check this after analysis as all opaque // types have been revealed at this point. if (src, dest).has_opaque_types() { return true; @@ -447,7 +448,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; match debuginfo.value { VarDebugInfoContents::Const(_) => {} - VarDebugInfoContents::Place(place) => check_place(place), + VarDebugInfoContents::Place(place) => { + check_place(place); + if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) { + self.fail( + START_BLOCK.start_location(), + format!("debuginfo {:?}, has both ref and deref", debuginfo), + ); + } + } VarDebugInfoContents::Composite { ty, ref fragments } => { for f in fragments { check_place(f.contents); @@ -711,10 +720,54 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } + Rvalue::NullaryOp(NullOp::OffsetOf(fields), container) => { + let fail_out_of_bounds = |this: &Self, location, field, ty| { + this.fail(location, format!("Out of bounds field {field:?} for {ty:?}")); + }; + + let mut current_ty = *container; + + for field in fields.iter() { + match current_ty.kind() { + ty::Tuple(fields) => { + let Some(&f_ty) = fields.get(field.as_usize()) else { + fail_out_of_bounds(self, location, field, current_ty); + return; + }; + + current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + } + ty::Adt(adt_def, substs) => { + if adt_def.is_enum() { + self.fail( + location, + format!("Cannot get field offset from enum {current_ty:?}"), + ); + return; + } + + let Some(field) = adt_def.non_enum_variant().fields.get(field) else { + fail_out_of_bounds(self, location, field, current_ty); + return; + }; + + let f_ty = field.ty(self.tcx, substs); + current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + } + _ => { + self.fail( + location, + format!("Cannot get field offset from non-adt type {current_ty:?}"), + ); + return; + } + } + } + } Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) - | Rvalue::NullaryOp(_, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::Discriminant(_) => {} } self.super_rvalue(rvalue, location); @@ -757,14 +810,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } - StatementKind::PlaceMention(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { - self.fail( - location, - "`PlaceMention` should have been removed after drop lowering phase", - ); - } - } StatementKind::AscribeUserType(..) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( @@ -874,6 +919,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { StatementKind::StorageDead(_) | StatementKind::Coverage(_) | StatementKind::ConstEvalCounter + | StatementKind::PlaceMention(..) | StatementKind::Nop => {} } @@ -1056,7 +1102,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if self.body.source_scopes.get(scope).is_none() { self.tcx.sess.diagnostic().delay_span_bug( self.body.span, - &format!( + format!( "broken MIR in {:?} ({}):\ninvalid source scope {:?}", self.body.source.instance, self.when, scope, ), |