Skip to content

Commit e68eb9c

Browse files
authored
Merge pull request RustPython#750 from RustPython/joey/cleanup-type-protocol
Clean up type protocol
2 parents 17b816f + 625d235 commit e68eb9c

21 files changed

+104
-130
lines changed

vm/src/builtins.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn builtin_bin(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
8888

8989
fn builtin_callable(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
9090
arg_check!(vm, args, required = [(obj, None)]);
91-
let is_callable = objtype::class_has_attr(&obj.type_pyref(), "__call__");
91+
let is_callable = objtype::class_has_attr(&obj.class(), "__call__");
9292
Ok(vm.new_bool(is_callable))
9393
}
9494

@@ -240,7 +240,7 @@ fn make_scope(
240240
} else if vm.isinstance(arg, &dict_type)? {
241241
Some(arg)
242242
} else {
243-
let arg_typ = arg.typ();
243+
let arg_typ = arg.class();
244244
let actual_type = vm.to_pystr(&arg_typ)?;
245245
let expected_type_name = vm.to_pystr(&dict_type)?;
246246
return Err(vm.new_type_error(format!(
@@ -368,7 +368,7 @@ fn builtin_len(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
368368
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
369369
Err(..) => Err(vm.new_type_error(format!(
370370
"object of type '{}' has no method {:?}",
371-
objtype::get_type_name(&obj.typ()),
371+
obj.class().name,
372372
len_method_name
373373
))),
374374
}
@@ -605,10 +605,9 @@ fn builtin_reversed(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
605605
match vm.get_method(obj.clone(), "__reversed__") {
606606
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
607607
// TODO: fallback to using __len__ and __getitem__, if object supports sequence protocol
608-
Err(..) => Err(vm.new_type_error(format!(
609-
"'{}' object is not reversible",
610-
objtype::get_type_name(&obj.typ()),
611-
))),
608+
Err(..) => {
609+
Err(vm.new_type_error(format!("'{}' object is not reversible", obj.class().name)))
610+
}
612611
}
613612
}
614613
// builtin_reversed
@@ -802,9 +801,9 @@ pub fn builtin_build_class_(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResu
802801
};
803802

804803
for base in bases.clone() {
805-
if objtype::issubclass(&base.type_pyref(), &metaclass) {
806-
metaclass = base.type_pyref();
807-
} else if !objtype::issubclass(&metaclass, &base.type_pyref()) {
804+
if objtype::issubclass(&base.class(), &metaclass) {
805+
metaclass = base.class();
806+
} else if !objtype::issubclass(&metaclass, &base.class()) {
808807
return Err(vm.new_type_error("metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases".to_string()));
809808
}
810809
}

vm/src/exceptions.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ fn exception_str(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
6868
args,
6969
required = [(exc, Some(vm.ctx.exceptions.exception_type.clone()))]
7070
);
71-
let type_name = objtype::get_type_name(&exc.typ());
7271
let msg = if let Ok(m) = vm.get_attribute(exc.clone(), "msg") {
7372
match vm.to_pystr(&m) {
7473
Ok(msg) => msg,
@@ -77,7 +76,7 @@ fn exception_str(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
7776
} else {
7877
panic!("Error message must be set");
7978
};
80-
let s = format!("{}: {}", type_name, msg);
79+
let s = format!("{}: {}", exc.class().name, msg);
8180
Ok(vm.new_str(s))
8281
}
8382

vm/src/frame.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ impl Frame {
949949
// let args = PyFuncArgs::default();
950950
// TODO: what happens when we got an error during handling exception?
951951
let args = if let Some(exc) = exc {
952-
let exc_type = exc.typ();
952+
let exc_type = exc.class().into_object();
953953
let exc_val = exc.clone();
954954
let exc_tb = vm.ctx.none(); // TODO: retrieve traceback?
955955
vec![exc_type, exc_val, exc_tb]
@@ -1093,7 +1093,7 @@ impl Frame {
10931093
Ok(found) => Ok(found),
10941094
Err(_) => Err(vm.new_type_error(format!(
10951095
"{} has no __contains__ method",
1096-
objtype::get_type_name(&haystack.typ())
1096+
haystack.class().name
10971097
))),
10981098
}
10991099
}
@@ -1103,7 +1103,7 @@ impl Frame {
11031103
Ok(found) => Ok(vm.ctx.new_bool(!objbool::get_value(&found))),
11041104
Err(_) => Err(vm.new_type_error(format!(
11051105
"{} has no __contains__ method",
1106-
objtype::get_type_name(&haystack.typ())
1106+
haystack.class().name
11071107
))),
11081108
}
11091109
}

vm/src/function.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl PyFuncArgs {
9999
Ok(Some(kwarg))
100100
} else {
101101
let expected_ty_name = vm.to_pystr(&ty)?;
102-
let actual_ty_name = vm.to_pystr(&kwarg.typ())?;
102+
let actual_ty_name = vm.to_pystr(&kwarg.class())?;
103103
Err(vm.new_type_error(format!(
104104
"argument of type {} is required for named parameter `{}` (got: {})",
105105
expected_ty_name, key, actual_ty_name

vm/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ macro_rules! type_check {
2020
let arg = &$args.args[$arg_count];
2121

2222
if !$crate::obj::objtype::isinstance(arg, &expected_type) {
23-
let arg_typ = arg.typ();
23+
let arg_typ = arg.class();
2424
let expected_type_name = $vm.to_pystr(&expected_type)?;
2525
let actual_type = $vm.to_pystr(&arg_typ)?;
2626
return Err($vm.new_type_error(format!(

vm/src/obj/objfloat.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,7 @@ impl PyFloatRef {
190190
}
191191
}
192192
} else {
193-
let type_name = objtype::get_type_name(&arg.typ());
194-
return Err(vm.new_type_error(format!("can't convert {} to float", type_name)));
193+
return Err(vm.new_type_error(format!("can't convert {} to float", arg.class().name)));
195194
};
196195
PyFloat { value }.into_ref_with_type(vm, cls)
197196
}

vm/src/obj/objfunction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn bind_method(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
7676
required = [(function, None), (obj, None), (cls, None)]
7777
);
7878

79-
if obj.is(&vm.get_none()) && !cls.is(&obj.typ()) {
79+
if obj.is(&vm.get_none()) && !cls.is(&obj.class()) {
8080
Ok(function.clone())
8181
} else {
8282
Ok(vm.ctx.new_bound_method(function.clone(), obj.clone()))

vm/src/obj/objint.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,7 @@ impl PyIntRef {
211211

212212
fn lshift(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
213213
if !objtype::isinstance(&other, &vm.ctx.int_type()) {
214-
return Err(vm.new_type_error(format!(
215-
"unsupported operand type(s) for << '{}' and '{}'",
216-
objtype::get_type_name(&self.as_object().typ()),
217-
objtype::get_type_name(&other.typ())
218-
)));
214+
return Ok(vm.ctx.not_implemented());
219215
}
220216

221217
if let Some(n_bits) = get_value(&other).to_usize() {
@@ -234,11 +230,7 @@ impl PyIntRef {
234230

235231
fn rshift(self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
236232
if !objtype::isinstance(&other, &vm.ctx.int_type()) {
237-
return Err(vm.new_type_error(format!(
238-
"unsupported operand type(s) for >> '{}' and '{}'",
239-
objtype::get_type_name(&self.as_object().typ()),
240-
objtype::get_type_name(&other.typ())
241-
)));
233+
return Ok(vm.ctx.not_implemented());
242234
}
243235

244236
if let Some(n_bits) = get_value(&other).to_usize() {
@@ -420,10 +412,9 @@ pub fn to_int(vm: &VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<Big
420412
}
421413
}
422414
} else {
423-
let type_name = objtype::get_type_name(&obj.typ());
424415
return Err(vm.new_type_error(format!(
425416
"int() argument must be a string or a number, not '{}'",
426-
type_name
417+
obj.class().name
427418
)));
428419
};
429420
Ok(val)

vm/src/obj/objiter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::obj::objtype::PyClassRef;
2121
*/
2222
pub fn get_iter(vm: &VirtualMachine, iter_target: &PyObjectRef) -> PyResult {
2323
vm.call_method(iter_target, "__iter__", vec![])
24-
// let type_str = objstr::get_value(&vm.to_str(iter_target.typ()).unwrap());
24+
// let type_str = objstr::get_value(&vm.to_str(iter_target.class()).unwrap());
2525
// let type_error = vm.new_type_error(format!("Cannot iterate over {}", type_str));
2626
// return Err(type_error);
2727
}

vm/src/obj/objnone.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub type PyNoneRef = PyRef<PyNone>;
1212

1313
impl PyValue for PyNone {
1414
fn class(vm: &VirtualMachine) -> PyClassRef {
15-
vm.ctx.none().type_pyref()
15+
vm.ctx.none().class()
1616
}
1717
}
1818

@@ -44,7 +44,7 @@ impl PyNoneRef {
4444

4545
fn get_attribute(self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {
4646
trace!("None.__getattribute__({:?}, {:?})", self, name);
47-
let cls = self.typ();
47+
let cls = self.class();
4848

4949
// Properties use a comparision with None to determine if they are either invoked by am
5050
// instance binding or a class binding. But if the object itself is None then this detection
@@ -69,7 +69,7 @@ impl PyNoneRef {
6969
}
7070

7171
if let Some(attr) = class_get_attr(&cls, &name.value) {
72-
let attr_class = attr.type_pyref();
72+
let attr_class = attr.class();
7373
if class_has_attr(&attr_class, "__set__") {
7474
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
7575
return call_descriptor(
@@ -88,7 +88,7 @@ impl PyNoneRef {
8888
// Ok(obj_attr)
8989
// } else
9090
if let Some(attr) = class_get_attr(&cls, &name.value) {
91-
let attr_class = attr.type_pyref();
91+
let attr_class = attr.class();
9292
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
9393
call_descriptor(attr, get_func, self.into_object(), cls.into_object(), vm)
9494
} else {
@@ -107,7 +107,7 @@ fn none_new(_: PyClassRef, vm: &VirtualMachine) -> PyNoneRef {
107107
}
108108

109109
pub fn init(context: &PyContext) {
110-
extend_class!(context, &context.none.typ(), {
110+
extend_class!(context, &context.none.class(), {
111111
"__new__" => context.new_rustfunc(none_new),
112112
"__repr__" => context.new_rustfunc(PyNoneRef::repr),
113113
"__bool__" => context.new_rustfunc(PyNoneRef::bool),

vm/src/obj/objobject.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,10 @@ fn object_setattr(
104104
vm: &VirtualMachine,
105105
) -> PyResult<()> {
106106
trace!("object.__setattr__({:?}, {}, {:?})", obj, attr_name, value);
107-
let cls = obj.type_pyref();
107+
let cls = obj.class();
108108

109109
if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) {
110-
if let Some(descriptor) = objtype::class_get_attr(&attr.type_pyref(), "__set__") {
110+
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__set__") {
111111
return vm
112112
.invoke(descriptor, vec![attr, obj.clone(), value])
113113
.map(|_| ());
@@ -118,19 +118,19 @@ fn object_setattr(
118118
dict.set_item(&vm.ctx, &attr_name.value, value);
119119
Ok(())
120120
} else {
121-
let type_name = objtype::get_type_name(obj.type_ref());
122121
Err(vm.new_attribute_error(format!(
123122
"'{}' object has no attribute '{}'",
124-
type_name, &attr_name.value
123+
obj.class().name,
124+
&attr_name.value
125125
)))
126126
}
127127
}
128128

129129
fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
130-
let cls = obj.type_pyref();
130+
let cls = obj.class();
131131

132132
if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) {
133-
if let Some(descriptor) = objtype::class_get_attr(&attr.type_pyref(), "__delete__") {
133+
if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__delete__") {
134134
return vm.invoke(descriptor, vec![attr, obj.clone()]).map(|_| ());
135135
}
136136
}
@@ -139,10 +139,10 @@ fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine)
139139
dict.del_item(&attr_name.value);
140140
Ok(())
141141
} else {
142-
let type_name = objtype::get_type_name(obj.type_ref());
143142
Err(vm.new_attribute_error(format!(
144143
"'{}' object has no attribute '{}'",
145-
type_name, &attr_name.value
144+
obj.class().name,
145+
&attr_name.value
146146
)))
147147
}
148148
}
@@ -154,9 +154,8 @@ fn object_str(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
154154

155155
fn object_repr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
156156
arg_check!(vm, args, required = [(obj, Some(vm.ctx.object()))]);
157-
let type_name = objtype::get_type_name(&obj.typ());
158157
let address = obj.get_id();
159-
Ok(vm.new_str(format!("<{} object at 0x{:x}>", type_name, address)))
158+
Ok(vm.new_str(format!("<{} object at 0x{:x}>", obj.class().name, address)))
160159
}
161160

162161
pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyList {
@@ -216,15 +215,15 @@ fn object_init(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult {
216215
}
217216

218217
fn object_class(obj: PyObjectRef, _vm: &VirtualMachine) -> PyObjectRef {
219-
obj.typ()
218+
obj.class().into_object()
220219
}
221220

222221
fn object_class_setter(
223222
instance: PyObjectRef,
224223
_value: PyObjectRef,
225224
vm: &VirtualMachine,
226225
) -> PyResult {
227-
let type_repr = vm.to_pystr(&instance.typ())?;
226+
let type_repr = vm.to_pystr(&instance.class())?;
228227
Err(vm.new_type_error(format!("can't change class of type '{}'", type_repr)))
229228
}
230229

@@ -247,10 +246,10 @@ fn object_getattribute(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
247246
);
248247
let name = objstr::get_value(&name_str);
249248
trace!("object.__getattribute__({:?}, {:?})", obj, name);
250-
let cls = obj.type_pyref();
249+
let cls = obj.class();
251250

252251
if let Some(attr) = objtype::class_get_attr(&cls, &name) {
253-
let attr_class = attr.type_pyref();
252+
let attr_class = attr.class();
254253
if objtype::class_has_attr(&attr_class, "__set__") {
255254
if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") {
256255
return vm.invoke(descriptor, vec![attr, obj.clone(), cls.into_object()]);
@@ -279,7 +278,7 @@ fn object_getattr(obj: &PyObjectRef, attr_name: &str) -> Option<PyObjectRef> {
279278

280279
pub fn get_attributes(obj: &PyObjectRef) -> PyAttributes {
281280
// Get class attributes:
282-
let mut attributes = objtype::get_attributes(obj.type_pyref());
281+
let mut attributes = objtype::get_attributes(obj.class());
283282

284283
// Get instance attributes:
285284
if let Some(dict) = &obj.dict {

vm/src/obj/objproperty.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use crate::function::IntoPyNativeFunc;
66
use crate::function::OptionalArg;
77
use crate::obj::objstr::PyStringRef;
88
use crate::obj::objtype::PyClassRef;
9-
use crate::pyobject::{IdProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue};
9+
use crate::pyobject::{
10+
IdProtocol, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
11+
};
1012
use crate::vm::VirtualMachine;
1113

1214
/// Read-only property, doesn't have __set__ or __delete__
@@ -137,7 +139,7 @@ impl PyPropertyRef {
137139
setter: self.setter.clone(),
138140
deleter: self.deleter.clone(),
139141
}
140-
.into_ref_with_type(vm, self.typ())
142+
.into_ref_with_type(vm, TypeProtocol::class(&self))
141143
}
142144

143145
fn setter(self, setter: Option<PyObjectRef>, vm: &VirtualMachine) -> PyResult<Self> {
@@ -146,7 +148,7 @@ impl PyPropertyRef {
146148
setter: setter.or_else(|| self.setter.clone()),
147149
deleter: self.deleter.clone(),
148150
}
149-
.into_ref_with_type(vm, self.typ())
151+
.into_ref_with_type(vm, TypeProtocol::class(&self))
150152
}
151153

152154
fn deleter(self, deleter: Option<PyObjectRef>, vm: &VirtualMachine) -> PyResult<Self> {
@@ -155,7 +157,7 @@ impl PyPropertyRef {
155157
setter: self.setter.clone(),
156158
deleter: deleter.or_else(|| self.deleter.clone()),
157159
}
158-
.into_ref_with_type(vm, self.typ())
160+
.into_ref_with_type(vm, TypeProtocol::class(&self))
159161
}
160162
}
161163

vm/src/obj/objsequence.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,13 @@ pub fn get_item(
163163
if sequence.payload::<PyList>().is_some() {
164164
Ok(PyObject::new(
165165
PyList::from(elements.to_vec().get_slice_items(vm, &subscript)?),
166-
sequence.type_pyref(),
166+
sequence.class(),
167167
None,
168168
))
169169
} else if sequence.payload::<PyTuple>().is_some() {
170170
Ok(PyObject::new(
171171
PyTuple::from(elements.to_vec().get_slice_items(vm, &subscript)?),
172-
sequence.type_pyref(),
172+
sequence.class(),
173173
None,
174174
))
175175
} else {

0 commit comments

Comments
 (0)