1
1
use crate :: attributes:: { self , get_pyo3_options, CrateAttribute } ;
2
2
use crate :: utils:: Ctx ;
3
3
use proc_macro2:: { Span , TokenStream } ;
4
- use quote:: { format_ident, quote} ;
4
+ use quote:: { format_ident, quote, quote_spanned } ;
5
5
use syn:: ext:: IdentExt ;
6
6
use syn:: parse:: { Parse , ParseStream } ;
7
7
use syn:: spanned:: Spanned as _;
@@ -81,9 +81,12 @@ struct IntoPyObjectImpl {
81
81
82
82
struct NamedStructField < ' a > {
83
83
ident : & ' a syn:: Ident ,
84
+ field : & ' a syn:: Field ,
84
85
}
85
86
86
- struct TupleStructField { }
87
+ struct TupleStructField < ' a > {
88
+ field : & ' a syn:: Field ,
89
+ }
87
90
88
91
/// Container Style
89
92
///
@@ -101,7 +104,7 @@ enum ContainerType<'a> {
101
104
///
102
105
/// Variant contains a list of conversion methods for each of the fields that are directly
103
106
/// extracted from the tuple.
104
- Tuple ( Vec < TupleStructField > ) ,
107
+ Tuple ( Vec < TupleStructField < ' a > > ) ,
105
108
/// Tuple newtype, e.g. `#[transparent] struct Foo(String)`
106
109
///
107
110
/// The wrapped field is directly extracted from the object.
@@ -142,7 +145,7 @@ impl<'a> Container<'a> {
142
145
let tuple_fields = unnamed
143
146
. unnamed
144
147
. iter ( )
145
- . map ( |_field | Ok ( TupleStructField { } ) )
148
+ . map ( |field | Ok ( TupleStructField { field } ) )
146
149
. collect :: < Result < Vec < _ > > > ( ) ?;
147
150
148
151
ContainerType :: Tuple ( tuple_fields)
@@ -167,7 +170,7 @@ impl<'a> Container<'a> {
167
170
. as_ref ( )
168
171
. expect ( "Named fields should have identifiers" ) ;
169
172
170
- Ok ( NamedStructField { ident } )
173
+ Ok ( NamedStructField { ident, field } )
171
174
} )
172
175
. collect :: < Result < Vec < _ > > > ( ) ?;
173
176
ContainerType :: Struct ( struct_fields)
@@ -241,7 +244,7 @@ impl<'a> Container<'a> {
241
244
target : quote ! { <#ty as #pyo3_path:: conversion:: IntoPyObject <' py>>:: Target } ,
242
245
output : quote ! { <#ty as #pyo3_path:: conversion:: IntoPyObject <' py>>:: Output } ,
243
246
error : quote ! { <#ty as #pyo3_path:: conversion:: IntoPyObject <' py>>:: Error } ,
244
- body : quote ! {
247
+ body : quote_spanned ! { ty . span ( ) =>
245
248
#unpack
246
249
<#ty as #pyo3_path:: conversion:: IntoPyObject <' py>>:: into_pyobject( arg0, py)
247
250
} ,
@@ -265,7 +268,7 @@ impl<'a> Container<'a> {
265
268
. enumerate ( )
266
269
. map ( |( i, f) | {
267
270
let key = f. ident . unraw ( ) . to_string ( ) ;
268
- let value = format_ident ! ( "arg{i}" ) ;
271
+ let value = Ident :: new ( & format ! ( "arg{i}" ) , f . field . ty . span ( ) ) ;
269
272
quote ! {
270
273
#pyo3_path:: types:: PyDictMethods :: set_item( & dict, #key, #value) ?;
271
274
}
@@ -285,7 +288,7 @@ impl<'a> Container<'a> {
285
288
}
286
289
}
287
290
288
- fn build_tuple_struct ( & self , fields : & [ TupleStructField ] , ctx : & Ctx ) -> IntoPyObjectImpl {
291
+ fn build_tuple_struct ( & self , fields : & [ TupleStructField < ' _ > ] , ctx : & Ctx ) -> IntoPyObjectImpl {
289
292
let Ctx { pyo3_path, .. } = ctx;
290
293
291
294
let unpack = self
@@ -300,10 +303,11 @@ impl<'a> Container<'a> {
300
303
let setter = fields
301
304
. iter ( )
302
305
. enumerate ( )
303
- . map ( |( i, _) | {
304
- let value = format_ident ! ( "arg{i}" ) ;
305
- quote ! {
306
- #pyo3_path:: conversion:: IntoPyObject :: into_pyobject( #value, py)
306
+ . map ( |( i, f) | {
307
+ let ty = & f. field . ty ;
308
+ let value = Ident :: new ( & format ! ( "arg{i}" ) , f. field . ty . span ( ) ) ;
309
+ quote_spanned ! { f. field. ty. span( ) =>
310
+ <#ty as #pyo3_path:: conversion:: IntoPyObject >:: into_pyobject( #value, py)
307
311
. map( #pyo3_path:: BoundObject :: into_any)
308
312
. map( #pyo3_path:: BoundObject :: into_bound) ?,
309
313
}
0 commit comments