|
3 | 3 |
|
4 | 4 | use crate::{ |
5 | 5 | builtins::{ |
6 | | - pystr::IntoPyStrRef, PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyStrRef, |
| 6 | + pystr::IntoPyStrRef, PyBytes, PyDict, PyDictRef, PyGenericAlias, PyInt, PyStr, PyStrRef, |
7 | 7 | PyTupleRef, PyTypeRef, |
8 | 8 | }, |
9 | 9 | bytesinner::ByteInnerNewOptions, |
@@ -330,12 +330,22 @@ impl PyObject { |
330 | 330 |
|
331 | 331 | // Container of the virtual machine state: |
332 | 332 | pub fn str(&self, vm: &VirtualMachine) -> PyResult<PyStrRef> { |
333 | | - if self.class().is(vm.ctx.types.str_type) { |
334 | | - Ok(self.to_owned().downcast().unwrap()) |
335 | | - } else { |
336 | | - let s = vm.call_special_method(self.to_owned(), identifier!(vm, __str__), ())?; |
337 | | - s.try_into_value(vm) |
338 | | - } |
| 333 | + let obj = match self.to_owned().downcast_exact::<PyStr>(vm) { |
| 334 | + Ok(s) => return Ok(s.into_pyref()), |
| 335 | + Err(obj) => obj, |
| 336 | + }; |
| 337 | + // TODO: replace to obj.class().slots.str |
| 338 | + let str_method = match vm.get_special_method(obj, identifier!(vm, __str__))? { |
| 339 | + Ok(str_method) => str_method, |
| 340 | + Err(obj) => return obj.repr(vm), |
| 341 | + }; |
| 342 | + let s = str_method.invoke((), vm)?; |
| 343 | + s.downcast::<PyStr>().map_err(|obj| { |
| 344 | + vm.new_type_error(format!( |
| 345 | + "__str__ returned non-string (type {})", |
| 346 | + obj.class().name() |
| 347 | + )) |
| 348 | + }) |
339 | 349 | } |
340 | 350 |
|
341 | 351 | // Equivalent to check_class. Masks Attribute errors (into TypeErrors) and lets everything |
|
0 commit comments