Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions crates/vm/src/builtins/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,18 @@ impl Constructor for PyFloat {
type Args = OptionalArg<PyObjectRef>;

fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
// Bind before the fast path so FromArgs::arity decides how many arguments
// are acceptable, rather than a count repeated here.
let arg: Self::Args = args.bind(vm)?;

// Optimization: return exact float as-is
if cls.is(vm.ctx.types.float_type)
&& args.kwargs.is_empty()
&& let Some(first) = args.args.first()
&& let OptionalArg::Present(first) = &arg
&& first.class().is(vm.ctx.types.float_type)
{
return Ok(first.clone());
}

let arg: Self::Args = args.bind(vm)?;
let payload = Self::py_new(&cls, arg, vm)?;
payload.into_ref_with_type(vm, cls).map(Into::into)
}
Expand Down
9 changes: 9 additions & 0 deletions extra_tests/snippets/builtin_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,12 @@ def _check_msg(call, exc_type, expected_msg):
assert repr(1.5) == "1.5"
assert repr(0.1) == "0.1"
assert repr(100.0) == "100.0"


# float() takes at most one positional argument; the exact-float fast path
# must not let extra ones through.
assert_raises(TypeError, float, 1.5, True)
assert_raises(TypeError, float, 1.5, 2, 3)
assert_raises(TypeError, float, "1.5", 2)
assert float(1.5) == 1.5
assert float() == 0.0
Loading