diff options
| author | bors <bors@rust-lang.org> | 2024-02-13 08:33:04 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-02-13 08:33:04 +0000 |
| commit | 41555ab4a39e18f59387a576bf1c19ef39093a60 (patch) | |
| tree | 5ed166021ffb0cc6a84667f2801a90486858a747 /compiler/rustc_const_eval/src | |
| parent | d2e446d39e2390093042a7fd8676cc85f2b573d7 (diff) | |
| parent | 43e9411db839747f650e1125ed06266566c20b65 (diff) | |
| download | rust-41555ab4a39e18f59387a576bf1c19ef39093a60.tar.gz rust-41555ab4a39e18f59387a576bf1c19ef39093a60.zip | |
Auto merge of #3298 - rust-lang:rustup-2024-02-13, r=oli-obk
Automatic Rustup
Diffstat (limited to 'compiler/rustc_const_eval/src')
14 files changed, 130 insertions, 144 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 71085c2b2a5..80d02589900 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -151,7 +151,7 @@ where let mut err = tcx.dcx().create_err(err); let msg = error.diagnostic_message(); - error.add_args(tcx.dcx(), &mut err); + error.add_args(&mut err); // Use *our* span to label the interp error err.span_label(our_span, msg); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 0844cdbe99b..c55d899e4d5 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -356,22 +356,13 @@ pub fn const_validate_mplace<'mir, 'tcx>( let mut inner = false; while let Some((mplace, path)) = ref_tracking.todo.pop() { let mode = match ecx.tcx.static_mutability(cid.instance.def_id()) { - Some(_) if cid.promoted.is_some() => { - // Promoteds in statics are consts that re allowed to point to statics. - CtfeValidationMode::Const { - allow_immutable_unsafe_cell: false, - allow_extern_static_ptrs: true, - } - } + _ if cid.promoted.is_some() => CtfeValidationMode::Promoted, Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static` None => { // In normal `const` (not promoted), the outermost allocation is always only copied, // so having `UnsafeCell` in there is okay despite them being in immutable memory. let allow_immutable_unsafe_cell = cid.promoted.is_none() && !inner; - CtfeValidationMode::Const { - allow_immutable_unsafe_cell, - allow_extern_static_ptrs: false, - } + CtfeValidationMode::Const { allow_immutable_unsafe_cell } } }; ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?; diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index a649526c196..11679ab77e3 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -426,7 +426,7 @@ pub struct UndefinedBehavior { pub trait ReportErrorExt { /// Returns the diagnostic message for this error. fn diagnostic_message(&self) -> DiagnosticMessage; - fn add_args<G: EmissionGuarantee>(self, dcx: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>); + fn add_args<G: EmissionGuarantee>(self, diag: &mut DiagnosticBuilder<'_, G>); fn debug(self) -> String where @@ -434,11 +434,11 @@ pub trait ReportErrorExt { { ty::tls::with(move |tcx| { let dcx = tcx.dcx(); - let mut builder = dcx.struct_allow(DiagnosticMessage::Str(String::new().into())); + let mut diag = dcx.struct_allow(DiagnosticMessage::Str(String::new().into())); let message = self.diagnostic_message(); - self.add_args(dcx, &mut builder); - let s = dcx.eagerly_translate_to_string(message, builder.args()); - builder.cancel(); + self.add_args(&mut diag); + let s = dcx.eagerly_translate_to_string(message, diag.args()); + diag.cancel(); s }) } @@ -505,20 +505,17 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { } } - fn add_args<G: EmissionGuarantee>( - self, - dcx: &DiagCtxt, - builder: &mut DiagnosticBuilder<'_, G>, - ) { + fn add_args<G: EmissionGuarantee>(self, diag: &mut DiagnosticBuilder<'_, G>) { use UndefinedBehaviorInfo::*; + let dcx = diag.dcx; match self { Ub(_) => {} Custom(custom) => { (custom.add_args)(&mut |name, value| { - builder.arg(name, value); + diag.arg(name, value); }); } - ValidationError(e) => e.add_args(dcx, builder), + ValidationError(e) => e.add_args(diag), Unreachable | DivisionByZero @@ -533,20 +530,18 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { | UninhabitedEnumVariantWritten(_) | UninhabitedEnumVariantRead(_) => {} BoundsCheckFailed { len, index } => { - builder.arg("len", len); - builder.arg("index", index); + diag.arg("len", len); + diag.arg("index", index); } UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => { - builder.arg("pointer", ptr); + diag.arg("pointer", ptr); } PointerUseAfterFree(alloc_id, msg) => { - builder - .arg("alloc_id", alloc_id) + diag.arg("alloc_id", alloc_id) .arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => { - builder - .arg("alloc_id", alloc_id) + diag.arg("alloc_id", alloc_id) .arg("alloc_size", alloc_size.bytes()) .arg("ptr_offset", ptr_offset) .arg("ptr_size", ptr_size.bytes()) @@ -554,47 +549,47 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { } DanglingIntPointer(ptr, msg) => { if ptr != 0 { - builder.arg("pointer", format!("{ptr:#x}[noalloc]")); + diag.arg("pointer", format!("{ptr:#x}[noalloc]")); } - builder.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); + diag.arg("bad_pointer_message", bad_pointer_message(msg, dcx)); } AlignmentCheckFailed(Misalignment { required, has }, msg) => { - builder.arg("required", required.bytes()); - builder.arg("has", has.bytes()); - builder.arg("msg", format!("{msg:?}")); + diag.arg("required", required.bytes()); + diag.arg("has", has.bytes()); + diag.arg("msg", format!("{msg:?}")); } WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => { - builder.arg("allocation", alloc); + diag.arg("allocation", alloc); } InvalidBool(b) => { - builder.arg("value", format!("{b:02x}")); + diag.arg("value", format!("{b:02x}")); } InvalidChar(c) => { - builder.arg("value", format!("{c:08x}")); + diag.arg("value", format!("{c:08x}")); } InvalidTag(tag) => { - builder.arg("tag", format!("{tag:x}")); + diag.arg("tag", format!("{tag:x}")); } InvalidStr(err) => { - builder.arg("err", format!("{err}")); + diag.arg("err", format!("{err}")); } InvalidUninitBytes(Some((alloc, info))) => { - builder.arg("alloc", alloc); - builder.arg("access", info.access); - builder.arg("uninit", info.bad); + diag.arg("alloc", alloc); + diag.arg("access", info.access); + diag.arg("uninit", info.bad); } ScalarSizeMismatch(info) => { - builder.arg("target_size", info.target_size); - builder.arg("data_size", info.data_size); + diag.arg("target_size", info.target_size); + diag.arg("data_size", info.data_size); } InvalidNichedEnumVariantWritten { enum_ty } => { - builder.arg("ty", enum_ty.to_string()); + diag.arg("ty", enum_ty.to_string()); } AbiMismatchArgument { caller_ty, callee_ty } | AbiMismatchReturn { caller_ty, callee_ty } => { - builder.arg("caller_ty", caller_ty.to_string()); - builder.arg("callee_ty", callee_ty.to_string()); + diag.arg("caller_ty", caller_ty.to_string()); + diag.arg("callee_ty", callee_ty.to_string()); } } } @@ -674,7 +669,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } } - fn add_args<G: EmissionGuarantee>(self, dcx: &DiagCtxt, err: &mut DiagnosticBuilder<'_, G>) { + fn add_args<G: EmissionGuarantee>(self, err: &mut DiagnosticBuilder<'_, G>) { use crate::fluent_generated as fluent; use rustc_middle::mir::interpret::ValidationErrorKind::*; @@ -684,12 +679,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } let message = if let Some(path) = self.path { - dcx.eagerly_translate_to_string( + err.dcx.eagerly_translate_to_string( fluent::const_eval_validation_front_matter_invalid_value_with_path, [("path".into(), DiagnosticArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)), ) } else { - dcx.eagerly_translate_to_string( + err.dcx.eagerly_translate_to_string( fluent::const_eval_validation_front_matter_invalid_value, [].into_iter(), ) @@ -700,7 +695,6 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { fn add_range_arg<G: EmissionGuarantee>( r: WrappingRange, max_hi: u128, - dcx: &DiagCtxt, err: &mut DiagnosticBuilder<'_, G>, ) { let WrappingRange { start: lo, end: hi } = r; @@ -724,7 +718,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ("hi".into(), DiagnosticArgValue::Str(hi.to_string().into())), ]; let args = args.iter().map(|(a, b)| (a, b)); - let message = dcx.eagerly_translate_to_string(msg, args); + let message = err.dcx.eagerly_translate_to_string(msg, args); err.arg("in_range", message); } @@ -746,7 +740,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { ExpectedKind::EnumTag => fluent::const_eval_validation_expected_enum_tag, ExpectedKind::Str => fluent::const_eval_validation_expected_str, }; - let msg = dcx.eagerly_translate_to_string(msg, [].into_iter()); + let msg = err.dcx.eagerly_translate_to_string(msg, [].into_iter()); err.arg("expected", msg); } InvalidEnumTag { value } @@ -757,11 +751,11 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { err.arg("value", value); } NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => { - add_range_arg(range, max_value, dcx, err) + add_range_arg(range, max_value, err) } OutOfRange { range, max_value, value } => { err.arg("value", value); - add_range_arg(range, max_value, dcx, err); + add_range_arg(range, max_value, err); } UnalignedPtr { required_bytes, found_bytes, .. } => { err.arg("required_bytes", required_bytes); @@ -802,13 +796,13 @@ impl ReportErrorExt for UnsupportedOpInfo { UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static, } } - fn add_args<G: EmissionGuarantee>(self, _: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>) { + fn add_args<G: EmissionGuarantee>(self, diag: &mut DiagnosticBuilder<'_, G>) { use crate::fluent_generated::*; use UnsupportedOpInfo::*; if let ReadPointerAsInt(_) | OverwritePartialPointer(_) | ReadPartialPointer(_) = self { - builder.help(const_eval_ptr_as_bytes_1); - builder.help(const_eval_ptr_as_bytes_2); + diag.help(const_eval_ptr_as_bytes_1); + diag.help(const_eval_ptr_as_bytes_2); } match self { // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to @@ -816,10 +810,10 @@ impl ReportErrorExt for UnsupportedOpInfo { // print. So it's not worth the effort of having diagnostics that can print the `info`. UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {} OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => { - builder.arg("ptr", ptr); + diag.arg("ptr", ptr); } ThreadLocalStatic(did) | ExternStatic(did) => { - builder.arg("did", format!("{did:?}")); + diag.arg("did", format!("{did:?}")); } } } @@ -835,18 +829,14 @@ impl<'tcx> ReportErrorExt for InterpError<'tcx> { InterpError::MachineStop(e) => e.diagnostic_message(), } } - fn add_args<G: EmissionGuarantee>( - self, - dcx: &DiagCtxt, - builder: &mut DiagnosticBuilder<'_, G>, - ) { + fn add_args<G: EmissionGuarantee>(self, diag: &mut DiagnosticBuilder<'_, G>) { match self { - InterpError::UndefinedBehavior(ub) => ub.add_args(dcx, builder), - InterpError::Unsupported(e) => e.add_args(dcx, builder), - InterpError::InvalidProgram(e) => e.add_args(dcx, builder), - InterpError::ResourceExhaustion(e) => e.add_args(dcx, builder), + InterpError::UndefinedBehavior(ub) => ub.add_args(diag), + InterpError::Unsupported(e) => e.add_args(diag), + InterpError::InvalidProgram(e) => e.add_args(diag), + InterpError::ResourceExhaustion(e) => e.add_args(diag), InterpError::MachineStop(e) => e.add_args(&mut |name, value| { - builder.arg(name, value); + diag.arg(name, value); }), } } @@ -864,28 +854,24 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { } } } - fn add_args<G: EmissionGuarantee>( - self, - dcx: &DiagCtxt, - builder: &mut DiagnosticBuilder<'_, G>, - ) { + fn add_args<G: EmissionGuarantee>(self, diag: &mut DiagnosticBuilder<'_, G>) { match self { InvalidProgramInfo::TooGeneric | InvalidProgramInfo::AlreadyReported(_) => {} InvalidProgramInfo::Layout(e) => { - // The level doesn't matter, `diag` is consumed without it being used. + // The level doesn't matter, `dummy_diag` is consumed without it being used. let dummy_level = Level::Bug; - let diag: DiagnosticBuilder<'_, ()> = - e.into_diagnostic().into_diagnostic(dcx, dummy_level); - for (name, val) in diag.args() { - builder.arg(name.clone(), val.clone()); + let dummy_diag: DiagnosticBuilder<'_, ()> = + e.into_diagnostic().into_diagnostic(diag.dcx, dummy_level); + for (name, val) in dummy_diag.args() { + diag.arg(name.clone(), val.clone()); } - diag.cancel(); + dummy_diag.cancel(); } InvalidProgramInfo::FnAbiAdjustForForeignAbi( AdjustForForeignAbiError::Unsupported { arch, abi }, ) => { - builder.arg("arch", arch); - builder.arg("abi", abi.name()); + diag.arg("arch", arch); + diag.arg("abi", abi.name()); } } } @@ -900,7 +886,7 @@ impl ReportErrorExt for ResourceExhaustionInfo { ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full, } } - fn add_args<G: EmissionGuarantee>(self, _: &DiagCtxt, _: &mut DiagnosticBuilder<'_, G>) {} + fn add_args<G: EmissionGuarantee>(self, _: &mut DiagnosticBuilder<'_, G>) {} } impl rustc_errors::IntoDiagnosticArg for InternKind { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index dd9dfe3fe79..33e96e7faa8 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -445,7 +445,7 @@ pub fn format_interp_error<'tcx>(dcx: &DiagCtxt, e: InterpErrorInfo<'tcx>) -> St #[allow(rustc::untranslatable_diagnostic)] let mut diag = dcx.struct_allow(""); let msg = e.diagnostic_message(); - e.add_args(dcx, &mut diag); + e.add_args(&mut diag); let s = dcx.eagerly_translate_to_string(msg, diag.args()); diag.cancel(); s @@ -554,18 +554,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Call this on things you got out of the MIR (so it is as generic as the current /// stack frame), to bring it into the proper environment for this interpreter. - pub(super) fn subst_from_current_frame_and_normalize_erasing_regions< + pub(super) fn instantiate_from_current_frame_and_normalize_erasing_regions< T: TypeFoldable<TyCtxt<'tcx>>, >( &self, value: T, ) -> Result<T, ErrorHandled> { - self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value) + self.instantiate_from_frame_and_normalize_erasing_regions(self.frame(), value) } /// Call this on things you got out of the MIR (so it is as generic as the provided /// stack frame), to bring it into the proper environment for this interpreter. - pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<TyCtxt<'tcx>>>( + pub(super) fn instantiate_from_frame_and_normalize_erasing_regions< + T: TypeFoldable<TyCtxt<'tcx>>, + >( &self, frame: &Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>, value: T, @@ -656,7 +658,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let layout = from_known_layout(self.tcx, self.param_env, layout, || { let local_ty = frame.body.local_decls[local].ty; - let local_ty = self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?; + let local_ty = + self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; self.layout_of(local_ty) })?; @@ -791,8 +794,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check). if M::POST_MONO_CHECKS { for &const_ in &body.required_consts { - let c = - self.subst_from_current_frame_and_normalize_erasing_regions(const_.const_)?; + let c = self + .instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; c.eval(*self.tcx, self.param_env, Some(const_.span)).map_err(|err| { err.emit_note(*self.tcx); err diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 4653c9016c6..317e5673b51 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -696,9 +696,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("eval_place_to_op: got {:?}", op); // Sanity-check the type we ended up with. if cfg!(debug_assertions) { - let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions( - mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, - )?; + let normalized_place_ty = self + .instantiate_from_current_frame_and_normalize_erasing_regions( + mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, + )?; if !mir_assign_valid_types( *self.tcx, self.param_env, @@ -731,8 +732,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &Copy(place) | &Move(place) => self.eval_place_to_op(place, layout)?, Constant(constant) => { - let c = - self.subst_from_current_frame_and_normalize_erasing_regions(constant.const_)?; + let c = self.instantiate_from_current_frame_and_normalize_erasing_regions( + constant.const_, + )?; // This can still fail: // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 772445f4f62..03d1dc9fd3d 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -542,9 +542,10 @@ where trace!("{:?}", self.dump_place(&place)); // Sanity-check the type we ended up with. if cfg!(debug_assertions) { - let normalized_place_ty = self.subst_from_current_frame_and_normalize_erasing_regions( - mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, - )?; + let normalized_place_ty = self + .instantiate_from_current_frame_and_normalize_erasing_regions( + mir_place.ty(&self.frame().body.local_decls, *self.tcx).ty, + )?; if !mir_assign_valid_types( *self.tcx, self.param_env, diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index f0f1008aba8..23f3d7eb67d 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -235,7 +235,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } NullaryOp(ref null_op, ty) => { - let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?; + let ty = self.instantiate_from_current_frame_and_normalize_erasing_regions(ty)?; let layout = self.layout_of(ty)?; if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op && layout.is_unsized() @@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Cast(cast_kind, ref operand, cast_ty) => { let src = self.eval_operand(operand, None)?; let cast_ty = - self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?; + self.instantiate_from_current_frame_and_normalize_erasing_regions(cast_ty)?; self.cast(&src, cast_kind, cast_ty, &dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index ff20fc5092c..4037220e5ed 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -173,7 +173,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Drop { place, target, unwind, replace: _ } => { let frame = self.frame(); let ty = place.ty(&frame.body.local_decls, *self.tcx).ty; - let ty = self.subst_from_frame_and_normalize_erasing_regions(frame, ty)?; + let ty = self.instantiate_from_frame_and_normalize_erasing_regions(frame, ty)?; let instance = Instance::resolve_drop_in_place(*self.tcx, ty); if let ty::InstanceDef::DropGlue(_, None) = instance.def { // This is the branch we enter if and only if the dropped type has no drop glue @@ -672,8 +672,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Construct the destination place for this argument. At this point all // locals are still dead, so we cannot construct a `PlaceTy`. let dest = mir::Place::from(local); - // `layout_of_local` does more than just the substitution we need to get the - // type, but the result gets cached so this avoids calling the substitution + // `layout_of_local` does more than just the instantiation we need to get the + // type, but the result gets cached so this avoids calling the instantiation // query *again* the next time this local is accessed. let ty = self.layout_of_local(self.frame(), local, None)?.ty; if Some(local) == body.spread_arg { diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 416443f5f4d..3a9ee904734 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -19,11 +19,11 @@ where } struct FoundParam; - struct UsedParamsNeedSubstVisitor<'tcx> { + struct UsedParamsNeedInstantiationVisitor<'tcx> { tcx: TyCtxt<'tcx>, } - impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedSubstVisitor<'tcx> { + impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor<'tcx> { type BreakTy = FoundParam; fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { @@ -34,21 +34,22 @@ where match *ty.kind() { ty::Param(_) => ControlFlow::Break(FoundParam), ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args, ..) | ty::Coroutine(def_id, args, ..) | ty::FnDef(def_id, args) => { let instance = ty::InstanceDef::Item(def_id); let unused_params = self.tcx.unused_generic_params(instance); - for (index, subst) in args.into_iter().enumerate() { + for (index, arg) in args.into_iter().enumerate() { let index = index .try_into() .expect("more generic parameters than can fit into a `u32`"); // Only recurse when generic parameters in fns, closures and coroutines // are used and have to be instantiated. // - // Just in case there are closures or coroutines within this subst, + // Just in case there are closures or coroutines within this arg, // recurse. - if unused_params.is_used(index) && subst.has_param() { - return subst.visit_with(self); + if unused_params.is_used(index) && arg.has_param() { + return arg.visit_with(self); } } ControlFlow::Continue(()) @@ -65,7 +66,7 @@ where } } - let mut vis = UsedParamsNeedSubstVisitor { tcx }; + let mut vis = UsedParamsNeedInstantiationVisitor { tcx }; if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) { throw_inval!(TooGeneric); } else { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 38aeace02ba..eb9f3fee165 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -129,17 +129,20 @@ pub enum PathElem { pub enum CtfeValidationMode { /// Validation of a `static` Static { mutbl: Mutability }, - /// Validation of a `const` (including promoteds). + /// Validation of a promoted. + Promoted, + /// Validation of a `const`. /// `allow_immutable_unsafe_cell` says whether we allow `UnsafeCell` in immutable memory (which is the /// case for the top-level allocation of a `const`, where this is fine because the allocation will be /// copied at each use site). - Const { allow_immutable_unsafe_cell: bool, allow_extern_static_ptrs: bool }, + Const { allow_immutable_unsafe_cell: bool }, } impl CtfeValidationMode { fn allow_immutable_unsafe_cell(self) -> bool { match self { CtfeValidationMode::Static { .. } => false, + CtfeValidationMode::Promoted { .. } => false, CtfeValidationMode::Const { allow_immutable_unsafe_cell, .. } => { allow_immutable_unsafe_cell } @@ -149,6 +152,7 @@ impl CtfeValidationMode { fn may_contain_mutable_ref(self) -> bool { match self { CtfeValidationMode::Static { mutbl } => mutbl == Mutability::Mut, + CtfeValidationMode::Promoted { .. } => false, CtfeValidationMode::Const { .. } => false, } } @@ -236,8 +240,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Now we know we are projecting to a field, so figure out which one. match layout.ty.kind() { - // coroutines and closures. - ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { + // coroutines, closures, and coroutine-closures all have upvars that may be named. + ty::Closure(def_id, _) | ty::Coroutine(def_id, _) | ty::CoroutineClosure(def_id, _) => { let mut name = None; // FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar // https://github.com/rust-lang/project-rfc-2229/issues/46 @@ -476,34 +480,32 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' throw_validation_failure!(self.path, MutableRefToImmutable); } } + // Mode-specific checks match self.ctfe_mode { - Some(CtfeValidationMode::Static { .. }) => { + Some( + CtfeValidationMode::Static { .. } + | CtfeValidationMode::Promoted { .. }, + ) => { // We skip recursively checking other statics. These statics must be sound by // themselves, and the only way to get broken statics here is by using // unsafe code. // The reasons we don't check other statics is twofold. For one, in all // sound cases, the static was already validated on its own, and second, we // trigger cycle errors if we try to compute the value of the other static - // and that static refers back to us. + // and that static refers back to us (potentially through a promoted). // This could miss some UB, but that's fine. return Ok(()); } - Some(CtfeValidationMode::Const { - allow_extern_static_ptrs, .. - }) => { + Some(CtfeValidationMode::Const { .. }) => { // For consts on the other hand we have to recursively check; // pattern matching assumes a valid value. However we better make // sure this is not mutable. if is_mut { throw_validation_failure!(self.path, ConstRefToMutable); } + // We can't recursively validate `extern static`, so we better reject them. if self.ecx.tcx.is_foreign_item(did) { - if !allow_extern_static_ptrs { - throw_validation_failure!(self.path, ConstRefToExtern); - } else { - // We can't validate this... - return Ok(()); - } + throw_validation_failure!(self.path, ConstRefToExtern); } } None => {} 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 28dc69859fd..43048dc41d3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -619,9 +619,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if base_ty.is_unsafe_ptr() { if place_ref.projection.is_empty() { let decl = &self.body.local_decls[place_ref.local]; - if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() { - let span = decl.source_info.span; - self.check_static(def_id, span); + // If this is a static, then this is not really dereferencing a pointer, + // just directly accessing a static. That is not subject to any feature + // gates (except for the one about whether statics can even be used, but + // that is checked already by `visit_operand`). + if let LocalInfo::StaticRef { .. } = *decl.local_info() { return; } } 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 1be2a2bc1f3..12e7ec15e32 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -72,7 +72,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn fn_sig(&self) -> PolyFnSig<'tcx> { let did = self.def_id().to_def_id(); - if self.tcx.is_closure_or_coroutine(did) { + if self.tcx.is_closure_like(did) { let ty = self.tcx.type_of(did).instantiate_identity(); let ty::Closure(_, args) = ty.kind() else { bug!("type_of closure not ty::Closure") }; args.as_closure().sig() 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 a9d472d377c..0c93cfaa546 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -409,11 +409,6 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { Status::Unstable(sym::const_refs_to_cell) } - fn importance(&self) -> DiagnosticImportance { - // The cases that cannot possibly work will already emit a `CellBorrow`, so we should - // not additionally emit a feature gate error if activating the feature gate won't work. - DiagnosticImportance::Secondary - } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx .sess @@ -427,6 +422,11 @@ impl<'tcx> NonConstOp<'tcx> for TransientCellBorrow { /// it in the future for static items. pub struct CellBorrow; impl<'tcx> NonConstOp<'tcx> for CellBorrow { + fn importance(&self) -> DiagnosticImportance { + // Most likely the code will try to do mutation with these borrows, which + // triggers its own errors. Only show this one if that does not happen. + DiagnosticImportance::Secondary + } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: Maybe a more elegant solution to this if else case if let hir::ConstContext::Static(_) = ccx.const_kind() { @@ -459,8 +459,8 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow { } fn importance(&self) -> DiagnosticImportance { - // If there were primary errors (like non-const function calls), do not emit further - // errors about mutable references. + // Most likely the code will try to do mutation with these borrows, which + // triggers its own errors. Only show this one if that does not happen. DiagnosticImportance::Secondary } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index a23922c778f..2c835f6750f 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -96,7 +96,7 @@ where }); } - fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool { + fn address_of_allows_mutation(&self) -> bool { // Exact set of permissions granted by AddressOf is undecided. Conservatively assume that // it might allow mutation until resolution of #56604. true @@ -171,10 +171,8 @@ where self.super_rvalue(rvalue, location); match rvalue { - mir::Rvalue::AddressOf(mt, borrowed_place) => { - if !borrowed_place.is_indirect() - && self.address_of_allows_mutation(*mt, *borrowed_place) - { + mir::Rvalue::AddressOf(_mt, borrowed_place) => { + if !borrowed_place.is_indirect() && self.address_of_allows_mutation() { let place_ty = borrowed_place.ty(self.ccx.body, self.ccx.tcx).ty; if Q::in_any_value_of_ty(self.ccx, place_ty) { self.state.qualif.insert(borrowed_place.local); |
