@@ -15,7 +15,8 @@ use crate::pyobject::{
15
15
} ;
16
16
use crate :: scope:: Scope ;
17
17
use crate :: slots:: { SlotCall , SlotDescriptor } ;
18
- use crate :: vm:: VirtualMachine ;
18
+ use crate :: VirtualMachine ;
19
+ use itertools:: Itertools ;
19
20
20
21
pub type PyFunctionRef = PyRef < PyFunction > ;
21
22
@@ -72,6 +73,7 @@ impl PyFunction {
72
73
) -> PyResult < ( ) > {
73
74
let nargs = func_args. args . len ( ) ;
74
75
let nexpected_args = code_object. arg_names . len ( ) ;
76
+ let posonly_args = & code_object. arg_names [ ..code_object. posonlyarg_count ] ;
75
77
76
78
// This parses the arguments from args and kwargs into
77
79
// the proper variables keeping into account default values
@@ -126,12 +128,16 @@ impl PyFunction {
126
128
bytecode:: Varargs :: None => None ,
127
129
} ;
128
130
131
+ let mut posonly_passed_as_kwarg = Vec :: new ( ) ;
129
132
// Handle keyword arguments
130
133
for ( name, value) in func_args. kwargs {
131
134
// Check if we have a parameter with this name:
132
135
if code_object. arg_names . contains ( & name) || code_object. kwonlyarg_names . contains ( & name)
133
136
{
134
- if locals. contains_key ( & name, vm) {
137
+ if posonly_args. contains ( & name) {
138
+ posonly_passed_as_kwarg. push ( name) ;
139
+ continue ;
140
+ } else if locals. contains_key ( & name, vm) {
135
141
return Err (
136
142
vm. new_type_error ( format ! ( "Got multiple values for argument '{}'" , name) )
137
143
) ;
@@ -146,6 +152,13 @@ impl PyFunction {
146
152
) ;
147
153
}
148
154
}
155
+ if !posonly_passed_as_kwarg. is_empty ( ) {
156
+ return Err ( vm. new_type_error ( format ! (
157
+ "{}() got some positional-only arguments passed as keyword arguments: '{}'" ,
158
+ & code_object. obj_name,
159
+ posonly_passed_as_kwarg. into_iter( ) . format( ", " ) ,
160
+ ) ) ) ;
161
+ }
149
162
150
163
// Add missing positional arguments, if we have fewer positional arguments than the
151
164
// function definition calls for
0 commit comments