Auto merge of #131934 - matthiaskrgr:rollup-pd3dwxu, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #127462 (std: uefi: Add basic Env variables)
 - #131537 (Fix range misleading field access)
 - #131838 (bootstrap: allow setting `--jobs` in config.toml)
 - #131890 (Update `use` keyword docs to describe precise capturing)
 - #131899 (Mark unexpected variant res suggestion as having placeholders)
 - #131908 (rustdoc: Switch from FxHash to sha256 for static file hashing.)
 - #131916 (small interpreter error cleanup)
 - #131919 (zero-sized accesses are fine on null pointers)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-10-19 16:46:43 +00:00
commit 8069f8d17a
36 changed files with 395 additions and 175 deletions

View File

@ -4584,6 +4584,7 @@ dependencies = [
"rustdoc-json-types",
"serde",
"serde_json",
"sha2",
"smallvec",
"tempfile",
"threadpool",

View File

@ -11,7 +11,8 @@ use rustc_span::{Span, Symbol};
use super::CompileTimeMachine;
use crate::errors::{self, FrameNote, ReportErrorExt};
use crate::interpret::{
ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType, err_inval, err_machine_stop,
ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType, err_inval,
err_machine_stop,
};
/// The CTFE machine has some custom error kinds.
@ -57,7 +58,7 @@ impl MachineStopType for ConstEvalErrKind {
}
}
/// The errors become [`InterpError::MachineStop`] when being raised.
/// The errors become [`InterpErrorKind::MachineStop`] when being raised.
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
fn into(self) -> InterpErrorInfo<'tcx> {
err_machine_stop!(self).into()
@ -124,7 +125,7 @@ pub fn get_span_and_frames<'tcx>(
/// `get_span_and_frames`.
pub(super) fn report<'tcx, C, F, E>(
tcx: TyCtxt<'tcx>,
error: InterpError<'tcx>,
error: InterpErrorKind<'tcx>,
span: Span,
get_span_and_frames: C,
mk: F,

View File

@ -18,7 +18,7 @@ use tracing::{debug, instrument, trace};
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
use crate::const_eval::CheckAlignment;
use crate::interpret::{
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpError,
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpErrorKind,
InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, create_static_alloc,
eval_nullary_intrinsic, intern_const_alloc_recursive, interp_ok, throw_exhaust,
};
@ -463,7 +463,7 @@ fn report_validation_error<'tcx>(
error: InterpErrorInfo<'tcx>,
alloc_id: AllocId,
) -> ErrorHandled {
if !matches!(error.kind(), InterpError::UndefinedBehavior(_)) {
if !matches!(error.kind(), InterpErrorKind::UndefinedBehavior(_)) {
// Some other error happened during validation, e.g. an unsupported operation.
return report_eval_error(ecx, cid, error);
}

View File

@ -9,7 +9,7 @@ use rustc_errors::{
use rustc_hir::ConstContext;
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::mir::interpret::{
CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpError, InvalidMetaKind,
CheckInAllocMsg, CtfeProvenance, ExpectedKind, InterpErrorKind, InvalidMetaKind,
InvalidProgramInfo, Misalignment, Pointer, PointerKind, ResourceExhaustionInfo,
UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
};
@ -835,23 +835,23 @@ impl ReportErrorExt for UnsupportedOpInfo {
}
}
impl<'tcx> ReportErrorExt for InterpError<'tcx> {
impl<'tcx> ReportErrorExt for InterpErrorKind<'tcx> {
fn diagnostic_message(&self) -> DiagMessage {
match self {
InterpError::UndefinedBehavior(ub) => ub.diagnostic_message(),
InterpError::Unsupported(e) => e.diagnostic_message(),
InterpError::InvalidProgram(e) => e.diagnostic_message(),
InterpError::ResourceExhaustion(e) => e.diagnostic_message(),
InterpError::MachineStop(e) => e.diagnostic_message(),
InterpErrorKind::UndefinedBehavior(ub) => ub.diagnostic_message(),
InterpErrorKind::Unsupported(e) => e.diagnostic_message(),
InterpErrorKind::InvalidProgram(e) => e.diagnostic_message(),
InterpErrorKind::ResourceExhaustion(e) => e.diagnostic_message(),
InterpErrorKind::MachineStop(e) => e.diagnostic_message(),
}
}
fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
match self {
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| {
InterpErrorKind::UndefinedBehavior(ub) => ub.add_args(diag),
InterpErrorKind::Unsupported(e) => e.add_args(diag),
InterpErrorKind::InvalidProgram(e) => e.add_args(diag),
InterpErrorKind::ResourceExhaustion(e) => e.add_args(diag),
InterpErrorKind::MachineStop(e) => e.add_args(&mut |name, value| {
diag.arg(name, value);
}),
}

View File

@ -471,7 +471,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Don't forget to mark "initially live" locals as live.
self.storage_live_for_always_live_locals()?;
};
res.inspect_err(|_| {
res.inspect_err_kind(|_| {
// Don't show the incomplete stack frame in the error stacktrace.
self.stack_mut().pop();
})

View File

@ -19,7 +19,7 @@ use rustc_trait_selection::traits::ObligationCtxt;
use tracing::{debug, instrument, trace};
use super::{
Frame, FrameInfo, GlobalId, InterpError, InterpErrorInfo, InterpResult, MPlaceTy, Machine,
Frame, FrameInfo, GlobalId, InterpErrorInfo, InterpErrorKind, InterpResult, MPlaceTy, Machine,
MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance,
err_inval, interp_ok, throw_inval, throw_ub, throw_ub_custom,
};
@ -73,7 +73,7 @@ where
}
impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> {
type LayoutOfResult = Result<TyAndLayout<'tcx>, InterpError<'tcx>>;
type LayoutOfResult = Result<TyAndLayout<'tcx>, InterpErrorKind<'tcx>>;
#[inline]
fn layout_tcx_at_span(&self) -> Span {
@ -82,20 +82,25 @@ impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> {
}
#[inline]
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> InterpError<'tcx> {
fn handle_layout_err(
&self,
err: LayoutError<'tcx>,
_: Span,
_: Ty<'tcx>,
) -> InterpErrorKind<'tcx> {
err_inval!(Layout(err))
}
}
impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
type FnAbiOfResult = Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, InterpError<'tcx>>;
type FnAbiOfResult = Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, InterpErrorKind<'tcx>>;
fn handle_fn_abi_err(
&self,
err: FnAbiError<'tcx>,
_span: Span,
_fn_abi_request: FnAbiRequest<'tcx>,
) -> InterpError<'tcx> {
) -> InterpErrorKind<'tcx> {
match err {
FnAbiError::Layout(err) => err_inval!(Layout(err)),
FnAbiError::AdjustForForeignAbi(err) => {

View File

@ -324,13 +324,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
dist.checked_neg().unwrap(), // i64::MIN is impossible as no allocation can be that large
CheckInAllocMsg::OffsetFromTest,
)
.map_err(|_| {
.map_err_kind(|_| {
// Make the error more specific.
err_ub_custom!(
fluent::const_eval_offset_from_different_allocations,
name = intrinsic_name,
)
.into()
})?;
// Perform division by size to compute return value.

View File

@ -17,8 +17,8 @@ use rustc_hir as hir;
use rustc_middle::bug;
use rustc_middle::mir::interpret::ValidationErrorKind::{self, *};
use rustc_middle::mir::interpret::{
ExpectedKind, InterpError, InterpErrorInfo, InvalidMetaKind, Misalignment, PointerKind,
Provenance, UnsupportedOpInfo, ValidationErrorInfo, alloc_range, interp_ok,
ExpectedKind, InterpErrorKind, InvalidMetaKind, Misalignment, PointerKind, Provenance,
UnsupportedOpInfo, ValidationErrorInfo, alloc_range, interp_ok,
};
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Ty};
@ -37,8 +37,8 @@ use super::{
// for the validation errors
#[rustfmt::skip]
use super::InterpError::UndefinedBehavior as Ub;
use super::InterpError::Unsupported as Unsup;
use super::InterpErrorKind::UndefinedBehavior as Ub;
use super::InterpErrorKind::Unsupported as Unsup;
use super::UndefinedBehaviorInfo::*;
use super::UnsupportedOpInfo::*;
@ -97,20 +97,19 @@ macro_rules! try_validation {
($e:expr, $where:expr,
$( $( $p:pat_param )|+ => $kind: expr ),+ $(,)?
) => {{
$e.map_err(|e| {
$e.map_err_kind(|e| {
// We catch the error and turn it into a validation failure. We are okay with
// allocation here as this can only slow down builds that fail anyway.
let (kind, backtrace) = e.into_parts();
match kind {
match e {
$(
$($p)|+ => {
err_validation_failure!(
$where,
$kind
).into()
)
}
),+,
_ => InterpErrorInfo::from_parts(kind, backtrace),
e => e,
}
})?
}};
@ -1230,11 +1229,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
// No need for an alignment check here, this is not an actual memory access.
let alloc = self.ecx.get_ptr_alloc(mplace.ptr(), size)?.expect("we already excluded size 0");
alloc.get_bytes_strip_provenance().map_err(|err| {
alloc.get_bytes_strip_provenance().map_err_kind(|kind| {
// Some error happened, try to provide a more detailed description.
// For some errors we might be able to provide extra information.
// (This custom logic does not fit the `try_validation!` macro.)
let (kind, backtrace) = err.into_parts();
match kind {
Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => {
// Some byte was uninitialized, determine which
@ -1247,14 +1245,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
self.path.push(PathElem::ArrayElem(i));
if matches!(kind, Ub(InvalidUninitBytes(_))) {
err_validation_failure!(self.path, Uninit { expected }).into()
err_validation_failure!(self.path, Uninit { expected })
} else {
err_validation_failure!(self.path, PointerAsInt { expected }).into()
err_validation_failure!(self.path, PointerAsInt { expected })
}
}
// Propagate upwards (that will also check for unexpected errors).
_ => return InterpErrorInfo::from_parts(kind, backtrace),
err => err,
}
})?;
@ -1368,12 +1366,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
v.reset_padding(val)?;
interp_ok(())
})
.map_err(|err| {
.map_err_info(|err| {
if !matches!(
err.kind(),
err_ub!(ValidationError { .. })
| InterpError::InvalidProgram(_)
| InterpError::Unsupported(UnsupportedOpInfo::ExternTypeField)
| InterpErrorKind::InvalidProgram(_)
| InterpErrorKind::Unsupported(UnsupportedOpInfo::ExternTypeField)
) {
bug!(
"Unexpected error during validation: {}",

View File

@ -419,7 +419,7 @@ fn report_unexpected_variant_res(
}
}
err.multipart_suggestion_verbose(descr, suggestion, Applicability::MaybeIncorrect);
err.multipart_suggestion_verbose(descr, suggestion, Applicability::HasPlaceholders);
err
}
Res::Def(DefKind::Variant, _) if expr.is_none() => {

View File

@ -18,9 +18,9 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_target::abi::{Align, HasDataLayout, Size};
use super::{
AllocId, BadBytesAccess, CtfeProvenance, InterpError, InterpResult, Pointer, PointerArithmetic,
Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch, UndefinedBehaviorInfo,
UnsupportedOpInfo, interp_ok, read_target_uint, write_target_uint,
AllocId, BadBytesAccess, CtfeProvenance, InterpErrorKind, InterpResult, Pointer,
PointerArithmetic, Provenance, ResourceExhaustionInfo, Scalar, ScalarSizeMismatch,
UndefinedBehaviorInfo, UnsupportedOpInfo, interp_ok, read_target_uint, write_target_uint,
};
use crate::ty;
@ -199,22 +199,22 @@ impl From<ScalarSizeMismatch> for AllocError {
}
impl AllocError {
pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpError<'tcx> {
pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpErrorKind<'tcx> {
use AllocError::*;
match self {
ScalarSizeMismatch(s) => {
InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s))
}
ReadPointerAsInt(info) => InterpError::Unsupported(
ReadPointerAsInt(info) => InterpErrorKind::Unsupported(
UnsupportedOpInfo::ReadPointerAsInt(info.map(|b| (alloc_id, b))),
),
OverwritePartialPointer(offset) => InterpError::Unsupported(
OverwritePartialPointer(offset) => InterpErrorKind::Unsupported(
UnsupportedOpInfo::OverwritePartialPointer(Pointer::new(alloc_id, offset)),
),
ReadPartialPointer(offset) => InterpError::Unsupported(
ReadPartialPointer(offset) => InterpErrorKind::Unsupported(
UnsupportedOpInfo::ReadPartialPointer(Pointer::new(alloc_id, offset)),
),
InvalidUninitBytes(info) => InterpError::UndefinedBehavior(
InvalidUninitBytes(info) => InterpErrorKind::UndefinedBehavior(
UndefinedBehaviorInfo::InvalidUninitBytes(info.map(|b| (alloc_id, b))),
),
}
@ -318,7 +318,7 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
Self::uninit_inner(size, align, || {
ty::tls::with(|tcx| tcx.dcx().delayed_bug("exhausted memory during interpretation"));
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
InterpErrorKind::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
})
.into()
}

View File

@ -113,7 +113,7 @@ pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
#[derive(Debug)]
struct InterpErrorInfoInner<'tcx> {
kind: InterpError<'tcx>,
kind: InterpErrorKind<'tcx>,
backtrace: InterpErrorBacktrace,
}
@ -154,21 +154,21 @@ impl InterpErrorBacktrace {
}
impl<'tcx> InterpErrorInfo<'tcx> {
pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
pub fn into_parts(self) -> (InterpErrorKind<'tcx>, InterpErrorBacktrace) {
let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
(kind, backtrace)
}
pub fn into_kind(self) -> InterpError<'tcx> {
pub fn into_kind(self) -> InterpErrorKind<'tcx> {
self.0.kind
}
pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
pub fn from_parts(kind: InterpErrorKind<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
}
#[inline]
pub fn kind(&self) -> &InterpError<'tcx> {
pub fn kind(&self) -> &InterpErrorKind<'tcx> {
&self.0.kind
}
}
@ -179,13 +179,13 @@ fn print_backtrace(backtrace: &Backtrace) {
impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
fn from(err: ErrorGuaranteed) -> Self {
InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
InterpErrorKind::InvalidProgram(InvalidProgramInfo::AlreadyReported(err.into())).into()
}
}
impl From<ErrorHandled> for InterpErrorInfo<'_> {
fn from(err: ErrorHandled) -> Self {
InterpError::InvalidProgram(match err {
InterpErrorKind::InvalidProgram(match err {
ErrorHandled::Reported(r, _span) => InvalidProgramInfo::AlreadyReported(r),
ErrorHandled::TooGeneric(_span) => InvalidProgramInfo::TooGeneric,
})
@ -193,8 +193,8 @@ impl From<ErrorHandled> for InterpErrorInfo<'_> {
}
}
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
impl<'tcx> From<InterpErrorKind<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpErrorKind<'tcx>) -> Self {
InterpErrorInfo(Box::new(InterpErrorInfoInner {
kind,
backtrace: InterpErrorBacktrace::new(),
@ -590,7 +590,7 @@ impl dyn MachineStopType {
}
#[derive(Debug)]
pub enum InterpError<'tcx> {
pub enum InterpErrorKind<'tcx> {
/// The program caused undefined behavior.
UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
/// The program did something the interpreter does not support (some of these *might* be UB
@ -606,25 +606,25 @@ pub enum InterpError<'tcx> {
MachineStop(Box<dyn MachineStopType>),
}
impl InterpError<'_> {
impl InterpErrorKind<'_> {
/// Some errors do string formatting even if the error is never printed.
/// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
/// so this method lets us detect them and `bug!` on unexpected errors.
pub fn formatted_string(&self) -> bool {
matches!(
self,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
InterpErrorKind::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ValidationError { .. })
| InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
)
}
}
// Macros for constructing / throwing `InterpError`
// Macros for constructing / throwing `InterpErrorKind`
#[macro_export]
macro_rules! err_unsup {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::Unsupported(
$crate::mir::interpret::InterpErrorKind::Unsupported(
$crate::mir::interpret::UnsupportedOpInfo::$($tt)*
)
};
@ -638,7 +638,7 @@ macro_rules! err_unsup_format {
#[macro_export]
macro_rules! err_inval {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::InvalidProgram(
$crate::mir::interpret::InterpErrorKind::InvalidProgram(
$crate::mir::interpret::InvalidProgramInfo::$($tt)*
)
};
@ -647,7 +647,7 @@ macro_rules! err_inval {
#[macro_export]
macro_rules! err_ub {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::UndefinedBehavior(
$crate::mir::interpret::InterpErrorKind::UndefinedBehavior(
$crate::mir::interpret::UndefinedBehaviorInfo::$($tt)*
)
};
@ -680,7 +680,7 @@ macro_rules! err_ub_custom {
#[macro_export]
macro_rules! err_exhaust {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::ResourceExhaustion(
$crate::mir::interpret::InterpErrorKind::ResourceExhaustion(
$crate::mir::interpret::ResourceExhaustionInfo::$($tt)*
)
};
@ -689,7 +689,7 @@ macro_rules! err_exhaust {
#[macro_export]
macro_rules! err_machine_stop {
($($tt:tt)*) => {
$crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*))
$crate::mir::interpret::InterpErrorKind::MachineStop(Box::new($($tt)*))
};
}
@ -792,9 +792,9 @@ impl<'tcx, T> ops::FromResidual for InterpResult_<'tcx, T> {
}
// Allow `yeet`ing `InterpError` in functions returning `InterpResult_`.
impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpError<'tcx>>> for InterpResult_<'tcx, T> {
impl<'tcx, T> ops::FromResidual<ops::Yeet<InterpErrorKind<'tcx>>> for InterpResult_<'tcx, T> {
#[inline]
fn from_residual(ops::Yeet(e): ops::Yeet<InterpError<'tcx>>) -> Self {
fn from_residual(ops::Yeet(e): ops::Yeet<InterpErrorKind<'tcx>>) -> Self {
Self::new(Err(e.into()))
}
}
@ -856,7 +856,7 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
}
#[inline]
pub fn map_err(
pub fn map_err_info(
self,
f: impl FnOnce(InterpErrorInfo<'tcx>) -> InterpErrorInfo<'tcx>,
) -> InterpResult<'tcx, T> {
@ -864,8 +864,19 @@ impl<'tcx, T> InterpResult_<'tcx, T> {
}
#[inline]
pub fn inspect_err(self, f: impl FnOnce(&InterpErrorInfo<'tcx>)) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().inspect_err(f))
pub fn map_err_kind(
self,
f: impl FnOnce(InterpErrorKind<'tcx>) -> InterpErrorKind<'tcx>,
) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().map_err(|mut e| {
e.0.kind = f(e.0.kind);
e
}))
}
#[inline]
pub fn inspect_err_kind(self, f: impl FnOnce(&InterpErrorKind<'tcx>)) -> InterpResult<'tcx, T> {
InterpResult_::new(self.disarm().inspect_err(|e| f(&e.0.kind)))
}
#[inline]

View File

@ -36,7 +36,7 @@ pub use self::allocation::{
pub use self::error::{
BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult,
EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, ExpectedKind,
InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind, InvalidProgramInfo,
InterpErrorInfo, InterpErrorKind, InterpResult, InvalidMetaKind, InvalidProgramInfo,
MachineStopType, Misalignment, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
ValidationErrorKind, interp_ok,

View File

@ -232,7 +232,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
{
f(self)
.map_err(|err| {
.map_err_info(|err| {
trace!("InterpCx operation failed: {:?}", err);
// Some errors shouldn't come up because creating them causes
// an allocation, which we should avoid. When that happens,

View File

@ -4011,6 +4011,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
let instead = res.is_some();
let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
&& path[0].ident.span.lo() == end.span.lo()
&& !matches!(start.kind, ExprKind::Lit(_))
{
let mut sugg = ".";
let mut span = start.span.between(end.span);

View File

@ -414,6 +414,11 @@
# Specify the location of the Android NDK. Used when targeting Android.
#android-ndk = "/path/to/android-ndk-r26d"
# Number of parallel jobs to be used for building and testing. If set to `0` or
# omitted, it will be automatically determined. This is the `-j`/`--jobs` flag
# passed to cargo invocations.
#jobs = 0
# =============================================================================
# General install configuration options
# =============================================================================

View File

@ -3138,7 +3138,7 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
/// [violate memory safety][read-ownership].
///
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
/// `0`, the pointers must be non-null and properly aligned.
/// `0`, the pointers must be properly aligned.
///
/// [`read`]: crate::ptr::read
/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
@ -3261,7 +3261,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
/// [violate memory safety][read-ownership].
///
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
/// `0`, the pointers must be non-null and properly aligned.
/// `0`, the pointers must be properly aligned.
///
/// [`read`]: crate::ptr::read
/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
@ -3342,7 +3342,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
/// * `dst` must be properly aligned.
///
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
/// `0`, the pointer must be non-null and properly aligned.
/// `0`, the pointer must be properly aligned.
///
/// Additionally, note that changing `*dst` in this way can easily lead to undefined behavior (UB)
/// later if the written bytes are not a valid representation of some `T`. For instance, the

View File

@ -505,9 +505,11 @@ impl () {}
///
/// *[See also the `std::ptr` module](ptr).*
///
/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns.
/// Raw pointers can be unaligned or [`null`]. However, when a raw pointer is
/// dereferenced (using the `*` operator), it must be non-null and aligned.
/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns. Raw pointers
/// can be out-of-bounds, unaligned, or [`null`]. However, when loading from or storing to a raw
/// pointer, it must be [valid] for the given access and aligned. When using a field expression,
/// tuple index expression, or array/slice index expression on a raw pointer, it follows the rules
/// of [in-bounds pointer arithmetic][`offset`].
///
/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so
/// [`write`] must be used if the type has drop glue and memory is not already
@ -613,6 +615,7 @@ impl () {}
/// [`offset`]: pointer::offset
/// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
/// [`write`]: ptr::write
/// [valid]: ptr#safety
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_pointer {}

View File

@ -1024,7 +1024,7 @@ pub const fn slice_from_raw_parts_mut<T>(data: *mut T, len: usize) -> *mut [T] {
///
/// * Both `x` and `y` must be properly aligned.
///
/// Note that even if `T` has size `0`, the pointers must be non-null and properly aligned.
/// Note that even if `T` has size `0`, the pointers must be properly aligned.
///
/// [valid]: self#safety
///
@ -1110,7 +1110,7 @@ pub const unsafe fn swap<T>(x: *mut T, y: *mut T) {
/// beginning at `y` with the same size.
///
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is `0`,
/// the pointers must be non-null and properly aligned.
/// the pointers must be properly aligned.
///
/// [valid]: self#safety
///
@ -1243,7 +1243,7 @@ const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, coun
///
/// * `dst` must point to a properly initialized value of type `T`.
///
/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
///
/// [valid]: self#safety
///
@ -1300,7 +1300,7 @@ pub const unsafe fn replace<T>(dst: *mut T, src: T) -> T {
///
/// * `src` must point to a properly initialized value of type `T`.
///
/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
///
/// # Examples
///
@ -1555,7 +1555,7 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
/// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the
/// case.
///
/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
///
/// [valid]: self#safety
///
@ -1774,7 +1774,7 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
/// However, storing non-[`Copy`] types in volatile memory is almost certainly
/// incorrect.
///
/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
///
/// [valid]: self#safety
/// [read-ownership]: read#ownership-of-the-returned-value
@ -1853,7 +1853,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
///
/// * `dst` must be properly aligned.
///
/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
///
/// [valid]: self#safety
///

View File

@ -2146,10 +2146,13 @@ mod unsafe_keyword {}
#[doc(keyword = "use")]
//
/// Import or rename items from other crates or modules.
/// Import or rename items from other crates or modules, or specify precise capturing
/// with `use<..>`.
///
/// Usually a `use` keyword is used to shorten the path required to refer to a module item.
/// The keyword may appear in modules, blocks and even functions, usually at the top.
/// ## Importing items
///
/// The `use` keyword is employed to shorten the path required to refer to a module item.
/// The keyword may appear in modules, blocks, and even functions, typically at the top.
///
/// The most basic usage of the keyword is `use path::to::item;`,
/// though a number of convenient shortcuts are supported:
@ -2190,19 +2193,48 @@ mod unsafe_keyword {}
/// // Compiles.
/// let _ = VariantA;
///
/// // Does not compile !
/// // Does not compile!
/// let n = new();
/// ```
///
/// For more information on `use` and paths in general, see the [Reference].
/// For more information on `use` and paths in general, see the [Reference][ref-use-decls].
///
/// The differences about paths and the `use` keyword between the 2015 and 2018 editions
/// can also be found in the [Reference].
/// can also be found in the [Reference][ref-use-decls].
///
/// ## Precise capturing
///
/// The `use<..>` syntax is used within certain `impl Trait` bounds to control which generic
/// parameters are captured. This is important for return-position `impl Trait` (RPIT) types,
/// as it affects borrow checking by controlling which generic parameters can be used in the
/// hidden type.
///
/// For example, the following function demonstrates an error without precise capturing in
/// Rust 2021 and earlier editions:
///
/// ```rust,compile_fail,edition2021
/// fn f(x: &()) -> impl Sized { x }
/// ```
///
/// By using `use<'_>` for precise capturing, it can be resolved:
///
/// ```rust
/// fn f(x: &()) -> impl Sized + use<'_> { x }
/// ```
///
/// This syntax specifies that the elided lifetime be captured and therefore available for
/// use in the hidden type.
///
/// In Rust 2024, opaque types automatically capture all lifetime parameters in scope.
/// `use<..>` syntax serves as an important way of opting-out of that default.
///
/// For more details about precise capturing, see the [Reference][ref-impl-trait].
///
/// [`crate`]: keyword.crate.html
/// [`self`]: keyword.self.html
/// [`super`]: keyword.super.html
/// [Reference]: ../reference/items/use-declarations.html
/// [ref-use-decls]: ../reference/items/use-declarations.html
/// [ref-impl-trait]: ../reference/types/impl-trait.html
mod use_keyword {}
#[doc(keyword = "where")]

View File

@ -10,7 +10,7 @@
//! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
use r_efi::efi::{self, Guid};
use r_efi::protocols::{device_path, device_path_to_text};
use r_efi::protocols::{device_path, device_path_to_text, shell};
use crate::ffi::{OsStr, OsString};
use crate::io::{self, const_io_error};
@ -424,3 +424,24 @@ pub(crate) fn os_string_to_raw(s: &OsStr) -> Option<Box<[r_efi::efi::Char16]>> {
let temp = s.encode_wide().chain(Some(0)).collect::<Box<[r_efi::efi::Char16]>>();
if temp[..temp.len() - 1].contains(&0) { None } else { Some(temp) }
}
pub(crate) fn open_shell() -> Option<NonNull<shell::Protocol>> {
static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
AtomicPtr::new(crate::ptr::null_mut());
if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
if let Ok(protocol) = open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) {
return Some(protocol);
}
}
let handles = locate_handles(shell::PROTOCOL_GUID).ok()?;
for handle in handles {
if let Ok(protocol) = open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) {
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
return Some(protocol);
}
}
None
}

View File

@ -125,7 +125,7 @@ pub fn error_string(errno: RawOsError) -> String {
}
pub fn getcwd() -> io::Result<PathBuf> {
match uefi_shell::open_shell() {
match helpers::open_shell() {
Some(shell) => {
// SAFETY: path_ptr is managed by UEFI shell and should not be deallocated
let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) };
@ -144,7 +144,7 @@ pub fn getcwd() -> io::Result<PathBuf> {
}
pub fn chdir(p: &path::Path) -> io::Result<()> {
let shell = uefi_shell::open_shell().ok_or(unsupported_err())?;
let shell = helpers::open_shell().ok_or(unsupported_err())?;
let mut p = helpers::os_string_to_raw(p.as_os_str())
.ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?;
@ -192,44 +192,58 @@ pub fn current_exe() -> io::Result<PathBuf> {
helpers::device_path_to_text(protocol).map(PathBuf::from)
}
pub struct Env(!);
pub struct EnvStrDebug<'a> {
iter: &'a [(OsString, OsString)],
}
impl fmt::Debug for EnvStrDebug<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut list = f.debug_list();
for (a, b) in self.iter {
list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
}
list.finish()
}
}
pub struct Env(crate::vec::IntoIter<(OsString, OsString)>);
impl Env {
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
let Self(inner) = self;
match *inner {}
EnvStrDebug { iter: self.0.as_slice() }
}
}
impl Iterator for Env {
type Item = (OsString, OsString);
fn next(&mut self) -> Option<(OsString, OsString)> {
self.0
self.0.next()
}
}
impl fmt::Debug for Env {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self(inner) = self;
match *inner {}
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
pub fn env() -> Env {
panic!("not supported on this platform")
let env = uefi_env::get_all().expect("not supported on this platform");
Env(env.into_iter())
}
pub fn getenv(_: &OsStr) -> Option<OsString> {
None
pub fn getenv(key: &OsStr) -> Option<OsString> {
uefi_env::get(key)
}
pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
uefi_env::set(key, val)
}
pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
uefi_env::unset(key)
}
pub fn temp_dir() -> PathBuf {
@ -261,36 +275,84 @@ pub fn getpid() -> u32 {
panic!("no pids on this platform")
}
mod uefi_shell {
use r_efi::protocols::shell;
use super::super::helpers;
mod uefi_env {
use crate::ffi::{OsStr, OsString};
use crate::io;
use crate::os::uefi::ffi::OsStringExt;
use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys::{helpers, unsupported_err};
pub fn open_shell() -> Option<NonNull<shell::Protocol>> {
static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
AtomicPtr::new(crate::ptr::null_mut());
pub(crate) fn get(key: &OsStr) -> Option<OsString> {
let shell = helpers::open_shell()?;
let mut key_ptr = helpers::os_string_to_raw(key)?;
unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }
}
if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
if let Ok(protocol) = helpers::open_protocol::<shell::Protocol>(
handle,
r_efi::protocols::shell::PROTOCOL_GUID,
) {
return Some(protocol);
pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {
let mut key_ptr = helpers::os_string_to_raw(key)
.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;
let mut val_ptr = helpers::os_string_to_raw(val)
.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;
unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }
}
pub(crate) fn unset(key: &OsStr) -> io::Result<()> {
let mut key_ptr = helpers::os_string_to_raw(key)
.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;
unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }
}
pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {
let shell = helpers::open_shell().ok_or(unsupported_err())?;
let mut vars = Vec::new();
let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };
if val.is_null() {
return Ok(vars);
}
let mut start = 0;
// UEFI Shell returns all keys seperated by NULL.
// End of string is denoted by two NULLs
for i in 0.. {
if unsafe { *val.add(i) } == 0 {
// Two NULL signal end of string
if i == start {
break;
}
let key = OsString::from_wide(unsafe {
crate::slice::from_raw_parts(val.add(start), i - start)
});
// SAFETY: val.add(start) is always NULL terminated
let val = unsafe { get_raw(shell, val.add(start)) }
.ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;
vars.push((key, val));
start = i + 1;
}
}
let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?;
for handle in handles {
if let Ok(protocol) =
helpers::open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID)
{
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
return Some(protocol);
}
}
Ok(vars)
}
None
unsafe fn get_raw(
shell: NonNull<r_efi::efi::protocols::shell::Protocol>,
key_ptr: *mut r_efi::efi::Char16,
) -> Option<OsString> {
let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };
helpers::os_string_from_raw(val)
}
unsafe fn set_raw(
key_ptr: *mut r_efi::efi::Char16,
val_ptr: *mut r_efi::efi::Char16,
) -> io::Result<()> {
let shell = helpers::open_shell().ok_or(unsupported_err())?;
let r =
unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
}

View File

@ -891,6 +891,7 @@ define_config! {
metrics: Option<bool> = "metrics",
android_ndk: Option<PathBuf> = "android-ndk",
optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
jobs: Option<u32> = "jobs",
}
}
@ -1289,7 +1290,6 @@ impl Config {
config.rustc_error_format = flags.rustc_error_format;
config.json_output = flags.json_output;
config.on_fail = flags.on_fail;
config.jobs = Some(threads_from_config(flags.jobs as u32));
config.cmd = flags.cmd;
config.incremental = flags.incremental;
config.dry_run = if flags.dry_run { DryRun::UserSelected } else { DryRun::Disabled };
@ -1511,8 +1511,11 @@ impl Config {
metrics: _,
android_ndk,
optimized_compiler_builtins,
jobs,
} = toml.build.unwrap_or_default();
config.jobs = Some(threads_from_config(flags.jobs.unwrap_or(jobs.unwrap_or(0))));
if let Some(file_build) = build {
config.build = TargetSelection::from_user(&file_build);
};

View File

@ -110,11 +110,10 @@ pub struct Flags {
short,
long,
value_hint = clap::ValueHint::Other,
default_value_t = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get),
value_name = "JOBS"
)]
/// number of jobs to run in parallel
pub jobs: usize,
pub jobs: Option<u32>,
// This overrides the deny-warnings configuration option,
// which passes -Dwarnings to the compiler invocations.
#[arg(global = true, long)]

View File

@ -352,3 +352,61 @@ fn parse_rust_std_features_empty() {
fn parse_rust_std_features_invalid() {
parse("rust.std-features = \"backtrace\"");
}
#[test]
fn parse_jobs() {
assert_eq!(parse("build.jobs = 1").jobs, Some(1));
}
#[test]
fn jobs_precedence() {
// `--jobs` should take precedence over using `--set build.jobs`.
let config = Config::parse_inner(
Flags::parse(&[
"check".to_owned(),
"--config=/does/not/exist".to_owned(),
"--jobs=67890".to_owned(),
"--set=build.jobs=12345".to_owned(),
]),
|&_| toml::from_str(""),
);
assert_eq!(config.jobs, Some(67890));
// `--set build.jobs` should take precedence over `config.toml`.
let config = Config::parse_inner(
Flags::parse(&[
"check".to_owned(),
"--config=/does/not/exist".to_owned(),
"--set=build.jobs=12345".to_owned(),
]),
|&_| {
toml::from_str(
r#"
[build]
jobs = 67890
"#,
)
},
);
assert_eq!(config.jobs, Some(12345));
// `--jobs` > `--set build.jobs` > `config.toml`
let config = Config::parse_inner(
Flags::parse(&[
"check".to_owned(),
"--jobs=123".to_owned(),
"--config=/does/not/exist".to_owned(),
"--set=build.jobs=456".to_owned(),
]),
|&_| {
toml::from_str(
r#"
[build]
jobs = 789
"#,
)
},
);
assert_eq!(config.jobs, Some(123));
}

View File

@ -275,4 +275,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Info,
summary: "New option `./x setup editor` added, replacing `./x setup vscode` and adding support for vim, emacs and helix.",
},
ChangeInfo {
change_id: 131838,
severity: ChangeSeverity::Info,
summary: "Allow setting `--jobs` in config.toml with `build.jobs`.",
},
];

View File

@ -24,6 +24,7 @@ tracing = "0.1"
tracing-tree = "0.3.0"
threadpool = "1.8.1"
unicode-segmentation = "1.9"
sha2 = "0.10.8"
[dependencies.tracing-subscriber]
version = "0.3.3"

View File

@ -44,7 +44,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
font-style: normal;
font-weight: 400;
src: local('Fira Sans'),
url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");
url("FiraSans-Regular-0fe48ade.woff2") format("woff2");
font-display: swap;
}
@font-face {
@ -52,7 +52,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
font-style: normal;
font-weight: 500;
src: local('Fira Sans Medium'),
url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");
url("FiraSans-Medium-e1aa3f0a.woff2") format("woff2");
font-display: swap;
}
@ -62,7 +62,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
font-style: normal;
font-weight: 400;
src: local('Source Serif 4'),
url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");
url("SourceSerif4-Regular-6b053e98.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
@ -70,7 +70,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
font-style: italic;
font-weight: 400;
src: local('Source Serif 4 Italic'),
url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");
url("SourceSerif4-It-ca3b17ed.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
@ -78,7 +78,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
font-style: normal;
font-weight: 700;
src: local('Source Serif 4 Bold'),
url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");
url("SourceSerif4-Bold-6d4fd4c0.ttf.woff2") format("woff2");
font-display: swap;
}
@ -89,28 +89,28 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
font-weight: 400;
/* Avoid using locally installed font because bad versions are in circulation:
* see https://github.com/rust-lang/rust/issues/24355 */
src: url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");
src: url("SourceCodePro-Regular-8badfe75.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
font-family: 'Source Code Pro';
font-style: italic;
font-weight: 400;
src: url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");
src: url("SourceCodePro-It-fc8b9304.ttf.woff2") format("woff2");
font-display: swap;
}
@font-face {
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 600;
src: url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");
src: url("SourceCodePro-Semibold-aa29a496.ttf.woff2") format("woff2");
font-display: swap;
}
/* Avoid using legacy CJK serif fonts in Windows like Batang. */
@font-face {
font-family: 'NanumBarunGothic';
src: url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");
src: url("NanumBarunGothic-13b3dcba.ttf.woff2") format("woff2");
font-display: swap;
unicode-range: U+AC00-D7AF, U+1100-11FF, U+3130-318F, U+A960-A97F, U+D7B0-D7FF;
}

View File

@ -3,12 +3,9 @@
//! All the static files are included here for centralized access in case anything other than the
//! HTML rendering code (say, the theme checker) needs to access one of these files.
use std::hash::Hasher;
use std::path::{Path, PathBuf};
use std::{fmt, str};
use rustc_data_structures::fx::FxHasher;
pub(crate) struct StaticFile {
pub(crate) filename: PathBuf,
pub(crate) bytes: &'static [u8],
@ -64,9 +61,11 @@ pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf {
}
fn static_suffix(bytes: &[u8]) -> String {
let mut hasher = FxHasher::default();
hasher.write(bytes);
format!("-{:016x}", hasher.finish())
use sha2::Digest;
let bytes = sha2::Sha256::digest(bytes);
let mut digest = format!("-{bytes:x}");
digest.truncate(9);
digest
}
macro_rules! static_files {

View File

@ -13,7 +13,7 @@ fn err_sb_ub<'tcx>(
msg: String,
help: Vec<String>,
history: Option<TagHistory>,
) -> InterpError<'tcx> {
) -> InterpErrorKind<'tcx> {
err_machine_stop!(TerminationInfo::StackedBorrowsUb { msg, help, history })
}
@ -376,7 +376,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
/// Report a descriptive error when `new` could not be granted from `derived_from`.
#[inline(never)] // This is only called on fatal code paths
pub(super) fn grant_error(&self, stack: &Stack) -> InterpError<'tcx> {
pub(super) fn grant_error(&self, stack: &Stack) -> InterpErrorKind<'tcx> {
let Operation::Retag(op) = &self.operation else {
unreachable!("grant_error should only be called during a retag")
};
@ -402,7 +402,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
/// Report a descriptive error when `access` is not permitted based on `tag`.
#[inline(never)] // This is only called on fatal code paths
pub(super) fn access_error(&self, stack: &Stack) -> InterpError<'tcx> {
pub(super) fn access_error(&self, stack: &Stack) -> InterpErrorKind<'tcx> {
// Deallocation and retagging also do an access as part of their thing, so handle that here, too.
let op = match &self.operation {
Operation::Access(op) => op,
@ -424,7 +424,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
}
#[inline(never)] // This is only called on fatal code paths
pub(super) fn protector_error(&self, item: &Item, kind: ProtectorKind) -> InterpError<'tcx> {
pub(super) fn protector_error(&self, item: &Item, kind: ProtectorKind) -> InterpErrorKind<'tcx> {
let protected = match kind {
ProtectorKind::WeakProtector => "weakly protected",
ProtectorKind::StrongProtector => "strongly protected",
@ -445,7 +445,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> {
}
#[inline(never)] // This is only called on fatal code paths
pub fn dealloc_error(&self, stack: &Stack) -> InterpError<'tcx> {
pub fn dealloc_error(&self, stack: &Stack) -> InterpErrorKind<'tcx> {
let Operation::Dealloc(op) = &self.operation else {
unreachable!("dealloc_error should only be called during a deallocation")
};

View File

@ -298,7 +298,7 @@ pub(super) struct TbError<'node> {
impl TbError<'_> {
/// Produce a UB error.
pub fn build<'tcx>(self) -> InterpError<'tcx> {
pub fn build<'tcx>(self) -> InterpErrorKind<'tcx> {
use TransitionError::*;
let cause = self.access_cause;
let accessed = self.accessed_info;

View File

@ -674,7 +674,7 @@ impl<'tcx> Tree {
Ok(())
}
},
|args: ErrHandlerArgs<'_, TransitionError>| -> InterpError<'tcx> {
|args: ErrHandlerArgs<'_, TransitionError>| -> InterpErrorKind<'tcx> {
let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
TbError {
conflicting_info,
@ -772,7 +772,7 @@ impl<'tcx> Tree {
let err_handler = |perms_range: Range<u64>,
access_cause: diagnostics::AccessCause,
args: ErrHandlerArgs<'_, TransitionError>|
-> InterpError<'tcx> {
-> InterpErrorKind<'tcx> {
let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
TbError {
conflicting_info,

View File

@ -214,7 +214,7 @@ pub fn report_error<'tcx>(
ecx: &InterpCx<'tcx, MiriMachine<'tcx>>,
e: InterpErrorInfo<'tcx>,
) -> Option<(i64, bool)> {
use InterpError::*;
use InterpErrorKind::*;
use UndefinedBehaviorInfo::*;
let mut msg = vec![];

View File

@ -245,17 +245,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let val = match which {
Op::MirOp(mir_op) => {
// This does NaN adjustments.
let val = this.binary_op(mir_op, &left, &right).map_err(|err| {
match err.kind() {
&InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => {
let val = this.binary_op(mir_op, &left, &right).map_err_kind(|kind| {
match kind {
InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::ShiftOverflow { shift_amount, .. }) => {
// This resets the interpreter backtrace, but it's not worth avoiding that.
let shift_amount = match shift_amount {
Either::Left(v) => v.to_string(),
Either::Right(v) => v.to_string(),
};
err_ub_format!("overflowing shift by {shift_amount} in `simd_{intrinsic_name}` in lane {i}").into()
err_ub_format!("overflowing shift by {shift_amount} in `simd_{intrinsic_name}` in lane {i}")
}
_ => err
kind => kind
}
})?;
if matches!(mir_op, BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge) {

View File

@ -289,11 +289,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
"miri_get_alloc_id" => {
let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err(|_e| {
let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err_kind(|_e| {
err_machine_stop!(TerminationInfo::Abort(format!(
"pointer passed to `miri_get_alloc_id` must not be dangling, got {ptr:?}"
)))
.into()
})?;
this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
}

View File

@ -0,0 +1,8 @@
// Check if rustc still displays the misleading hint to write `.` instead of `..`
fn main() {
let width = 10;
// ...
for _ in 0..w {
//~^ ERROR cannot find value `w`
}
}

View File

@ -0,0 +1,9 @@
error[E0425]: cannot find value `w` in this scope
--> $DIR/misleading-field-access-hint.rs:5:17
|
LL | for _ in 0..w {
| ^ not found in this scope
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0425`.