@@ -244,8 +244,18 @@ impl Class {
244244 attr_idxs. push ( i) ;
245245 }
246246 }
247- for idx in attr_idxs {
248- attrs. remove ( idx) ;
247+ let mut i = 0 ;
248+ let mut attr_idxs = & * attr_idxs;
249+ attrs. retain ( |_| {
250+ let drop = attr_idxs. first ( ) . copied ( ) == Some ( i) ;
251+ if drop {
252+ attr_idxs = & attr_idxs[ 1 ..] ;
253+ }
254+ i += 1 ;
255+ !drop
256+ } ) ;
257+ for ( i, idx) in attr_idxs. into_iter ( ) . enumerate ( ) {
258+ attrs. remove ( idx - i) ;
249259 }
250260 Ok ( ( ) )
251261 }
@@ -256,7 +266,10 @@ struct ItemSig<'a> {
256266 sig : & ' a Signature ,
257267}
258268
259- fn extract_impl_items ( mut items : Vec < ItemSig > ) -> Result < TokenStream2 , Diagnostic > {
269+ fn extract_impl_items (
270+ attr : AttributeArgs ,
271+ mut items : Vec < ItemSig > ,
272+ ) -> Result < TokenStream2 , Diagnostic > {
260273 let mut diagnostics: Vec < Diagnostic > = Vec :: new ( ) ;
261274
262275 let mut class = Class :: default ( ) ;
@@ -350,13 +363,36 @@ fn extract_impl_items(mut items: Vec<ItemSig>) -> Result<TokenStream2, Diagnosti
350363
351364 Diagnostic :: from_vec ( diagnostics) ?;
352365
366+ let mut withs = Vec :: new ( ) ;
367+
368+ for attr in attr {
369+ match attr {
370+ NestedMeta :: Meta ( Meta :: List ( syn:: MetaList { path, nested, .. } ) )
371+ if path_eq ( & path, "with" ) =>
372+ {
373+ for meta in nested {
374+ match meta {
375+ NestedMeta :: Meta ( Meta :: Path ( path) ) => {
376+ withs. push ( quote ! {
377+ <Self as #path>:: __extend_py_class( ctx, class) ;
378+ } ) ;
379+ }
380+ meta => bail_span ! ( meta, "#[pyimpl(with(...))] arguments should be paths" ) ,
381+ }
382+ }
383+ }
384+ attr => bail_span ! ( attr, "Unknown pyimpl attribute" ) ,
385+ }
386+ }
387+
353388 Ok ( quote ! {
354389 #( #methods) *
355390 #( #properties) *
391+ #( #withs) *
356392 } )
357393}
358394
359- pub fn impl_pyimpl ( _attr : AttributeArgs , item : Item ) -> Result < TokenStream2 , Diagnostic > {
395+ pub fn impl_pyimpl ( attr : AttributeArgs , item : Item ) -> Result < TokenStream2 , Diagnostic > {
360396 match item {
361397 Item :: Impl ( mut imp) => {
362398 let items = imp
@@ -369,7 +405,7 @@ pub fn impl_pyimpl(_attr: AttributeArgs, item: Item) -> Result<TokenStream2, Dia
369405 _ => None ,
370406 } )
371407 . collect ( ) ;
372- let extend_impl = extract_impl_items ( items) ?;
408+ let extend_impl = extract_impl_items ( attr , items) ?;
373409 let ty = & imp. self_ty ;
374410 let ret = quote ! {
375411 #imp
@@ -395,7 +431,7 @@ pub fn impl_pyimpl(_attr: AttributeArgs, item: Item) -> Result<TokenStream2, Dia
395431 _ => None ,
396432 } )
397433 . collect ( ) ;
398- let extend_impl = extract_impl_items ( items) ?;
434+ let extend_impl = extract_impl_items ( attr , items) ?;
399435 let item = parse_quote ! {
400436 fn __extend_py_class(
401437 ctx: & :: rustpython_vm:: pyobject:: PyContext ,
0 commit comments