@@ -14,6 +14,7 @@ use rustc_middle::hir::nested_filter;
1414use rustc_middle:: query:: Providers ;
1515use rustc_middle:: ty:: TyCtxt ;
1616use rustc_span:: { Ident , Span , Symbol } ;
17+ use smallvec:: SmallVec ;
1718use std:: rc:: Rc ;
1819
1920// FIXME(eddyb) replace with `ArrayVec<[Word; 3]>`.
@@ -529,25 +530,33 @@ fn parse_attrs_for_checking<'a>(
529530 Attribute :: Unparsed ( item) => {
530531 // #[...]
531532 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+ {
533536 // #[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+ }
551560 }
552561 } else {
553562 // #[...] but not #[rust_gpu ...]
@@ -558,52 +567,54 @@ fn parse_attrs_for_checking<'a>(
558567 }
559568 } )
560569 . 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) ] ) )
567572 . 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) ) )
604573 } )
605574}
606575
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+
607618fn parse_spec_constant_attr (
608619 sym : & Symbols ,
609620 arg : & MetaItemInner ,
0 commit comments