Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Remove unnecessary string conversions in error message construction #5826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 24, 2025
27 changes: 13 additions & 14 deletions stdlib/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ mod array {
.chars()
.exactly_one()
.map(|ch| Self(ch as _))
.map_err(|_| vm.new_type_error("array item must be unicode character".into()))
.map_err(|_| vm.new_type_error("array item must be unicode character"))
}
fn byteswap(self) -> Self {
Self(self.0.swap_bytes())
Expand Down Expand Up @@ -832,9 +832,9 @@ mod array {
))
})?;
if zelf.read().typecode() != 'u' {
return Err(vm.new_value_error(
"fromunicode() may only be called on unicode type arrays".into(),
));
return Err(
vm.new_value_error("fromunicode() may only be called on unicode type arrays")
);
}
let mut w = zelf.try_resizable(vm)?;
let bytes = Self::_unicode_to_wchar_bytes(wtf8, w.itemsize());
Expand All @@ -846,9 +846,9 @@ mod array {
fn tounicode(&self, vm: &VirtualMachine) -> PyResult<Wtf8Buf> {
let array = self.array.read();
if array.typecode() != 'u' {
return Err(vm.new_value_error(
"tounicode() may only be called on unicode type arrays".into(),
));
return Err(
vm.new_value_error("tounicode() may only be called on unicode type arrays")
);
}
let bytes = array.get_bytes();
Self::_wchar_bytes_to_string(bytes, self.itemsize(), vm)
Expand Down Expand Up @@ -1500,7 +1500,7 @@ mod array {
.unwrap_or(u8::MAX)
.try_into()
.map_err(|_| {
vm.new_value_error("third argument must be a valid machine format code.".into())
vm.new_value_error("third argument must be a valid machine format code.")
})
}
}
Expand Down Expand Up @@ -1572,11 +1572,11 @@ mod array {
fn check_type_code(spec: PyStrRef, vm: &VirtualMachine) -> PyResult<ArrayContentType> {
let spec = spec.as_str().chars().exactly_one().map_err(|_| {
vm.new_type_error(
"_array_reconstructor() argument 2 must be a unicode character, not str".into(),
"_array_reconstructor() argument 2 must be a unicode character, not str",
)
})?;
ArrayContentType::from_char(spec)
.map_err(|_| vm.new_value_error("second argument must be a valid type code".into()))
.map_err(|_| vm.new_value_error("second argument must be a valid type code"))
}

macro_rules! chunk_to_obj {
Expand Down Expand Up @@ -1609,7 +1609,7 @@ mod array {
let format = args.mformat_code;
let bytes = args.items.as_bytes();
if bytes.len() % format.item_size() != 0 {
return Err(vm.new_value_error("bytes length not a multiple of item size".into()));
return Err(vm.new_value_error("bytes length not a multiple of item size"));
}
if MachineFormatCode::from_typecode(array.typecode()) == Some(format) {
array.frombytes(bytes);
Expand Down Expand Up @@ -1642,9 +1642,8 @@ mod array {
})?,
MachineFormatCode::Utf16 { big_endian } => {
let utf16: Vec<_> = chunks.map(|b| chunk_to_obj!(b, u16, big_endian)).collect();
let s = String::from_utf16(&utf16).map_err(|_| {
vm.new_unicode_encode_error("items cannot decode as utf16".into())
})?;
let s = String::from_utf16(&utf16)
.map_err(|_| vm.new_unicode_encode_error("items cannot decode as utf16"))?;
let bytes = PyArray::_unicode_to_wchar_bytes((*s).as_ref(), array.itemsize());
array.frombytes_move(bytes);
}
Expand Down
6 changes: 3 additions & 3 deletions stdlib/src/hashlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub mod _hashlib {

#[pyslot]
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Err(vm.new_type_error("cannot create '_hashlib.HASH' instances".into()))
Err(vm.new_type_error("cannot create '_hashlib.HASH' instances"))
}

#[pygetset]
Expand Down Expand Up @@ -181,7 +181,7 @@ pub mod _hashlib {

#[pyslot]
fn slot_new(_cls: PyTypeRef, _args: FuncArgs, vm: &VirtualMachine) -> PyResult {
Err(vm.new_type_error("cannot create '_hashlib.HASHXOF' instances".into()))
Err(vm.new_type_error("cannot create '_hashlib.HASHXOF' instances"))
}

#[pygetset]
Expand Down Expand Up @@ -347,7 +347,7 @@ pub mod _hashlib {

#[pyfunction]
fn hmac_new(_args: NewHMACHashArgs, vm: &VirtualMachine) -> PyResult<PyObjectRef> {
Err(vm.new_type_error("cannot create 'hmac' instances".into())) // TODO: RUSTPYTHON support hmac
Err(vm.new_type_error("cannot create 'hmac' instances")) // TODO: RUSTPYTHON support hmac
}

pub trait ThreadSafeDynDigest: DynClone + DynDigest + Sync + Send {}
Expand Down
28 changes: 12 additions & 16 deletions vm/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,15 +497,12 @@ fn get_int_or_index<T>(vm: &VirtualMachine, arg: PyObjectRef) -> PyResult<T>
where
T: PrimInt + for<'a> TryFrom<&'a BigInt>,
{
let index = arg.try_index_opt(vm).unwrap_or_else(|| {
Err(new_struct_error(
vm,
"required argument is not an integer".to_owned(),
))
})?;
let index = arg
.try_index_opt(vm)
.unwrap_or_else(|| Err(new_struct_error(vm, "required argument is not an integer")))?;
index
.try_to_primitive(vm)
.map_err(|_| new_struct_error(vm, "argument out of range".to_owned()))
.map_err(|_| new_struct_error(vm, "argument out of range"))
}

make_pack_prim_int!(i8);
Expand Down Expand Up @@ -549,7 +546,7 @@ impl Packable for f16 {
// "from_f64 should be preferred in any non-`const` context" except it gives the wrong result :/
let f_16 = f16::from_f64_const(f_64);
if f_16.is_infinite() != f_64.is_infinite() {
return Err(vm.new_overflow_error("float too large to pack with e format".to_owned()));
return Err(vm.new_overflow_error("float too large to pack with e format"));
}
f_16.to_bits().pack_int::<E>(data);
Ok(())
Expand Down Expand Up @@ -586,12 +583,11 @@ impl Packable for bool {

fn pack_char(vm: &VirtualMachine, arg: PyObjectRef, data: &mut [u8]) -> PyResult<()> {
let v = PyBytesRef::try_from_object(vm, arg)?;
let ch = *v.as_bytes().iter().exactly_one().map_err(|_| {
new_struct_error(
vm,
"char format requires a bytes object of length 1".to_owned(),
)
})?;
let ch = *v
.as_bytes()
.iter()
.exactly_one()
.map_err(|_| new_struct_error(vm, "char format requires a bytes object of length 1"))?;
data[0] = ch;
Ok(())
}
Expand Down Expand Up @@ -647,8 +643,8 @@ pub fn struct_error_type(vm: &VirtualMachine) -> &'static PyTypeRef {
INSTANCE.get_or_init(|| vm.ctx.new_exception_type("struct", "error", None))
}

pub fn new_struct_error(vm: &VirtualMachine, msg: String) -> PyBaseExceptionRef {
pub fn new_struct_error(vm: &VirtualMachine, msg: impl Into<String>) -> PyBaseExceptionRef {
// can't just STRUCT_ERROR.get().unwrap() cause this could be called before from buffer
// machinery, independent of whether _struct was ever imported
vm.new_exception_msg(struct_error_type(vm).clone(), msg)
vm.new_exception_msg(struct_error_type(vm).clone(), msg.into())
}
2 changes: 1 addition & 1 deletion vm/src/builtins/classmethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl Representable for PyClassMethod {
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => return Err(vm.new_type_error("Unknown qualified name".into())),
(None, _) => return Err(vm.new_type_error("Unknown qualified name")),
(Some(qualname), Some(module)) if module != "builtins" => {
format!("<{module}.{qualname}({callable})>")
}
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl Representable for PyModule {
let module_repr = importlib.get_attr("_module_repr", vm)?;
let repr = module_repr.call((zelf.to_owned(),), vm)?;
repr.downcast()
.map_err(|_| vm.new_type_error("_module_repr did not return a string".into()))
.map_err(|_| vm.new_type_error("_module_repr did not return a string"))
}

#[cold]
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ impl PyBaseObject {
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => Err(vm.new_type_error("Unknown qualified name".into())),
(None, _) => Err(vm.new_type_error("Unknown qualified name")),
(Some(qualname), Some(module)) if module != "builtins" => Ok(PyStr::from(format!(
"<{}.{} object at {:#x}>",
module,
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/staticmethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl Representable for PyStaticMethod {
.map(|n| n.as_str()),
class.module(vm).downcast_ref::<PyStr>().map(|m| m.as_str()),
) {
(None, _) => Err(vm.new_type_error("Unknown qualified name".into())),
(None, _) => Err(vm.new_type_error("Unknown qualified name")),
(Some(qualname), Some(module)) if module != "builtins" => {
Ok(format!("<{module}.{qualname}({callable})>"))
}
Expand Down
12 changes: 5 additions & 7 deletions vm/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,7 @@ impl ExceptionCtor {
match (self, exc_inst) {
// both are instances; which would we choose?
(Self::Instance(_exc_a), Some(_exc_b)) => {
Err(vm
.new_type_error("instance exception may not have a separate value".to_owned()))
Err(vm.new_type_error("instance exception may not have a separate value"))
}
// if the "type" is an instance and the value isn't, use the "type"
(Self::Instance(exc), None) => Ok(exc),
Expand Down Expand Up @@ -672,7 +671,7 @@ impl PyRef<PyBaseException> {
if !vm.is_none(&state) {
let dict = state
.downcast::<crate::builtins::PyDict>()
.map_err(|_| vm.new_type_error("state is not a dictionary".to_owned()))?;
.map_err(|_| vm.new_type_error("state is not a dictionary"))?;

for (key, value) in &dict {
let key_str = key.str(vm)?;
Expand All @@ -691,7 +690,7 @@ impl Constructor for PyBaseException {

fn py_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
if cls.is(PyBaseException::class(&vm.ctx)) && !args.kwargs.is_empty() {
return Err(vm.new_type_error("BaseException() takes no keyword arguments".to_owned()));
return Err(vm.new_type_error("BaseException() takes no keyword arguments"));
}
PyBaseException::new(args.args, vm)
.into_ref_with_type(vm, cls)
Expand Down Expand Up @@ -1149,7 +1148,7 @@ impl serde::Serialize for SerializeException<'_, '_> {
}

pub fn cstring_error(vm: &VirtualMachine) -> PyBaseExceptionRef {
vm.new_value_error("embedded null character".to_owned())
vm.new_value_error("embedded null character")
}

impl ToPyException for std::ffi::NulError {
Expand Down Expand Up @@ -1353,8 +1352,7 @@ pub(super) mod types {
// Check for any remaining invalid keyword arguments
if let Some(invalid_key) = kwargs.keys().next() {
return Err(vm.new_type_error(format!(
"'{}' is an invalid keyword argument for ImportError",
invalid_key
"'{invalid_key}' is an invalid keyword argument for ImportError"
)));
}

Expand Down
22 changes: 10 additions & 12 deletions vm/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ impl IntoPyException for FormatSpecError {
vm.new_value_error(msg)
}
FormatSpecError::PrecisionNotAllowed => {
vm.new_value_error("Precision not allowed in integer format specifier".to_owned())
vm.new_value_error("Precision not allowed in integer format specifier")
}
FormatSpecError::NotAllowed(s) => {
let msg = format!("{s} not allowed with integer format specifier 'c'");
vm.new_value_error(msg)
}
FormatSpecError::UnableToConvert => {
vm.new_value_error("Unable to convert int to float".to_owned())
vm.new_value_error("Unable to convert int to float")
}
FormatSpecError::CodeNotInRange => {
vm.new_overflow_error("%c arg not in range(0x110000)".to_owned())
vm.new_overflow_error("%c arg not in range(0x110000)")
}
FormatSpecError::NotImplemented(c, s) => {
let msg = format!("Format code '{c}' for object of type '{s}' not implemented yet");
Expand All @@ -52,9 +52,9 @@ impl ToPyException for FormatParseError {
fn to_pyexception(&self, vm: &VirtualMachine) -> PyBaseExceptionRef {
match self {
FormatParseError::UnmatchedBracket => {
vm.new_value_error("expected '}' before end of string".to_owned())
vm.new_value_error("expected '}' before end of string")
}
_ => vm.new_value_error("Unexpected error parsing format string".to_owned()),
_ => vm.new_value_error("Unexpected error parsing format string"),
}
}
}
Expand Down Expand Up @@ -130,30 +130,28 @@ pub(crate) fn format(
FieldType::Auto => {
if seen_index {
return Err(vm.new_value_error(
"cannot switch from manual field specification to automatic field numbering"
.to_owned(),
"cannot switch from manual field specification to automatic field numbering",
));
}
auto_argument_index += 1;
arguments
.args
.get(auto_argument_index - 1)
.cloned()
.ok_or_else(|| vm.new_index_error("tuple index out of range".to_owned()))
.ok_or_else(|| vm.new_index_error("tuple index out of range"))
}
FieldType::Index(index) => {
if auto_argument_index != 0 {
return Err(vm.new_value_error(
"cannot switch from automatic field numbering to manual field specification"
.to_owned(),
"cannot switch from automatic field numbering to manual field specification",
));
}
seen_index = true;
arguments
.args
.get(index)
.cloned()
.ok_or_else(|| vm.new_index_error("tuple index out of range".to_owned()))
.ok_or_else(|| vm.new_index_error("tuple index out of range"))
}
FieldType::Keyword(keyword) => keyword
.as_str()
Expand All @@ -170,7 +168,7 @@ pub(crate) fn format_map(
) -> PyResult<Wtf8Buf> {
format_internal(vm, format, &mut |field_type| match field_type {
FieldType::Auto | FieldType::Index(_) => {
Err(vm.new_value_error("Format string contains positional fields".to_owned()))
Err(vm.new_value_error("Format string contains positional fields"))
}
FieldType::Keyword(keyword) => dict.get_item(&keyword, vm),
})
Expand Down
2 changes: 1 addition & 1 deletion vm/src/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ where
let n = vm.check_repeat_or_overflow_error(self.as_ref().len(), n)?;

if n > 1 && std::mem::size_of_val(self.as_ref()) >= MAX_MEMORY_SIZE / n {
return Err(vm.new_memory_error("".to_owned()));
return Err(vm.new_memory_error(""));
}

let mut v = Vec::with_capacity(n * self.as_ref().len());
Expand Down
2 changes: 1 addition & 1 deletion vm/src/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub fn assert_in_range(signum: i32, vm: &VirtualMachine) -> PyResult<()> {
if (1..NSIG as i32).contains(&signum) {
Ok(())
} else {
Err(vm.new_value_error("signal number out of range".to_owned()))
Err(vm.new_value_error("signal number out of range"))
}
}

Expand Down
Loading
Loading