summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_const_eval/src/transform
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /compiler/rustc_const_eval/src/transform
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_const_eval/src/transform')
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs8
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs30
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs82
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,
),