@@ -14,6 +14,7 @@ use rustc_middle::hir::nested_filter;
14
14
use rustc_middle:: query:: Providers ;
15
15
use rustc_middle:: ty:: TyCtxt ;
16
16
use rustc_span:: { Ident , Span , Symbol } ;
17
+ use smallvec:: SmallVec ;
17
18
use std:: rc:: Rc ;
18
19
19
20
// FIXME(eddyb) replace with `ArrayVec<[Word; 3]>`.
@@ -529,25 +530,33 @@ fn parse_attrs_for_checking<'a>(
529
530
Attribute :: Unparsed ( item) => {
530
531
// #[...]
531
532
let s = & item. path . segments ;
532
- if s. len ( ) > 1 && s[ 0 ] . name == sym. rust_gpu {
533
+ if let Some ( rust_gpu) = s. get ( 0 )
534
+ && rust_gpu. name == sym. rust_gpu
535
+ {
533
536
// #[rust_gpu ...]
534
- if s. len ( ) != 2 || s[ 1 ] . name != sym. spirv {
535
- // #[rust_gpu::...] but not #[rust_gpu::spirv]
536
- Err ( (
537
- attr. span ( ) ,
538
- "unknown `rust_gpu` attribute, expected `rust_gpu::spirv`"
539
- . to_string ( ) ,
540
- ) )
541
- } else if let Some ( args) = attr. meta_item_list ( ) {
542
- // #[rust_gpu::spirv(...)]
543
- Ok ( args)
544
- } else {
545
- // #[rust_gpu::spirv]
546
- Err ( (
547
- attr. span ( ) ,
548
- "#[rust_gpu::spirv(..)] attribute must have at least one argument"
549
- . to_string ( ) ,
550
- ) )
537
+ match s. get ( 1 ) {
538
+ Some ( command) if command. name == sym. spirv => {
539
+ // #[rust_gpu::spirv ...]
540
+ if let Some ( args) = attr. meta_item_list ( ) {
541
+ // #[rust_gpu::spirv(...)]
542
+ Ok ( parse_spirv_attr ( sym, args. iter ( ) ) )
543
+ } else {
544
+ // #[rust_gpu::spirv]
545
+ Err ( (
546
+ attr. span ( ) ,
547
+ "#[spirv(..)] attribute must have at least one argument"
548
+ . to_string ( ) ,
549
+ ) )
550
+ }
551
+ }
552
+ _ => {
553
+ // #[rust_gpu::...] but not a know version
554
+ Err ( (
555
+ attr. span ( ) ,
556
+ "unknown `rust_gpu` attribute, expected `rust_gpu::spirv`"
557
+ . to_string ( ) ,
558
+ ) )
559
+ }
551
560
}
552
561
} else {
553
562
// #[...] but not #[rust_gpu ...]
@@ -558,52 +567,54 @@ fn parse_attrs_for_checking<'a>(
558
567
}
559
568
} )
560
569
. flat_map ( |result| {
561
- // parse each element of the inner list
562
- let ( v, e) = match result {
563
- Ok ( v) => ( Some ( v) , None ) ,
564
- Err ( e) => ( None , Some ( e) ) ,
565
- } ;
566
- v. unwrap_or_default ( )
570
+ result
571
+ . unwrap_or_else ( |err| SmallVec :: from_iter ( [ Err ( err) ] ) )
567
572
. into_iter ( )
568
- . map ( |ref arg| {
569
- let span = arg. span ( ) ;
570
- let parsed_attr = if arg. has_name ( sym. descriptor_set ) {
571
- SpirvAttribute :: DescriptorSet ( parse_attr_int_value ( arg) ?)
572
- } else if arg. has_name ( sym. binding ) {
573
- SpirvAttribute :: Binding ( parse_attr_int_value ( arg) ?)
574
- } else if arg. has_name ( sym. input_attachment_index ) {
575
- SpirvAttribute :: InputAttachmentIndex ( parse_attr_int_value ( arg) ?)
576
- } else if arg. has_name ( sym. spec_constant ) {
577
- SpirvAttribute :: SpecConstant ( parse_spec_constant_attr ( sym, arg) ?)
578
- } else {
579
- let name = match arg. ident ( ) {
580
- Some ( i) => i,
581
- None => {
582
- return Err ( (
583
- span,
584
- "#[spirv(..)] attribute argument must be single identifier"
585
- . to_string ( ) ,
586
- ) ) ;
587
- }
588
- } ;
589
- sym. attributes . get ( & name. name ) . map_or_else (
590
- || Err ( ( name. span , "unknown argument to spirv attribute" . to_string ( ) ) ) ,
591
- |a| {
592
- Ok ( match a {
593
- SpirvAttribute :: Entry ( entry) => SpirvAttribute :: Entry (
594
- parse_entry_attrs ( sym, arg, & name, entry. execution_model ) ?,
595
- ) ,
596
- _ => a. clone ( ) ,
597
- } )
598
- } ,
599
- ) ?
600
- } ;
601
- Ok ( ( span, parsed_attr) )
602
- } )
603
- . chain ( e. map ( |e| Err ( e) ) )
604
573
} )
605
574
}
606
575
576
+ fn parse_spirv_attr < ' a > (
577
+ sym : & Symbols ,
578
+ iter : impl Iterator < Item = & ' a MetaItemInner > ,
579
+ ) -> SmallVec < [ Result < ( Span , SpirvAttribute ) , ParseAttrError > ; 4 ] > {
580
+ iter. map ( |arg| {
581
+ let span = arg. span ( ) ;
582
+ let parsed_attr =
583
+ if arg. has_name ( sym. descriptor_set ) {
584
+ SpirvAttribute :: DescriptorSet ( parse_attr_int_value ( arg) ?)
585
+ } else if arg. has_name ( sym. binding ) {
586
+ SpirvAttribute :: Binding ( parse_attr_int_value ( arg) ?)
587
+ } else if arg. has_name ( sym. input_attachment_index ) {
588
+ SpirvAttribute :: InputAttachmentIndex ( parse_attr_int_value ( arg) ?)
589
+ } else if arg. has_name ( sym. spec_constant ) {
590
+ SpirvAttribute :: SpecConstant ( parse_spec_constant_attr ( sym, arg) ?)
591
+ } else {
592
+ let name = match arg. ident ( ) {
593
+ Some ( i) => i,
594
+ None => {
595
+ return Err ( (
596
+ span,
597
+ "#[spirv(..)] attribute argument must be single identifier" . to_string ( ) ,
598
+ ) ) ;
599
+ }
600
+ } ;
601
+ sym. attributes . get ( & name. name ) . map_or_else (
602
+ || Err ( ( name. span , "unknown argument to spirv attribute" . to_string ( ) ) ) ,
603
+ |a| {
604
+ Ok ( match a {
605
+ SpirvAttribute :: Entry ( entry) => SpirvAttribute :: Entry (
606
+ parse_entry_attrs ( sym, arg, & name, entry. execution_model ) ?,
607
+ ) ,
608
+ _ => a. clone ( ) ,
609
+ } )
610
+ } ,
611
+ ) ?
612
+ } ;
613
+ Ok ( ( span, parsed_attr) )
614
+ } )
615
+ . collect ( )
616
+ }
617
+
607
618
fn parse_spec_constant_attr (
608
619
sym : & Symbols ,
609
620
arg : & MetaItemInner ,
0 commit comments