@@ -728,3 +728,110 @@ fn test_map_type_ref_spacing() {
728728 output
729729 ) ;
730730}
731+
732+ /// Test that metadata containers with non-optional Span field work.
733+ /// This is a regression test for issue #53 where Meta<String> with
734+ /// `span: Span` (not Option<Span>) failed with "missing field `span`".
735+ #[ test]
736+ fn test_metadata_container_non_optional_span ( ) {
737+ use facet_reflect:: Span ;
738+
739+ #[ derive( Debug , Facet ) ]
740+ #[ facet( metadata_container) ]
741+ struct Meta < T > {
742+ pub value : T ,
743+ #[ facet( metadata = "span" ) ]
744+ pub span : Span ,
745+ }
746+
747+ #[ derive( Debug , Facet ) ]
748+ struct Config {
749+ name : Meta < String > ,
750+ }
751+
752+ let source = r#"{name "hello"}"# ;
753+ let result: Result < Config , _ > = from_str ( source) ;
754+ match result {
755+ Ok ( config) => {
756+ eprintln ! ( "Success: {:?}" , config) ;
757+ assert_eq ! ( config. name. value, "hello" ) ;
758+ // Span should cover the "hello" string (offset 6, len 7 including quotes)
759+ assert_eq ! ( config. name. span. offset, 6 ) ;
760+ assert_eq ! ( config. name. span. len, 7 ) ;
761+ }
762+ Err ( e) => {
763+ panic ! ( "Failed to parse: {}" , e. render( "<test>" , source) ) ;
764+ }
765+ }
766+ }
767+
768+ /// Test that metadata containers with non-optional Span work as map keys.
769+ /// This is a more specific test for issue #53 where Meta<String> as a
770+ /// flattened map key might fail.
771+ #[ test]
772+ fn test_metadata_container_as_map_key ( ) {
773+ use facet_reflect:: Span ;
774+ use indexmap:: IndexMap ;
775+
776+ #[ derive( Debug , Facet ) ]
777+ #[ facet( metadata_container) ]
778+ struct Meta < T > {
779+ pub value : T ,
780+ #[ facet( metadata = "span" ) ]
781+ pub span : Span ,
782+ }
783+
784+ impl < T : PartialEq > PartialEq for Meta < T > {
785+ fn eq ( & self , other : & Self ) -> bool {
786+ self . value == other. value
787+ }
788+ }
789+ impl < T : Eq > Eq for Meta < T > { }
790+ impl < T : std:: hash:: Hash > std:: hash:: Hash for Meta < T > {
791+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
792+ self . value . hash ( state) ;
793+ }
794+ }
795+
796+ #[ derive( Debug , Facet ) ]
797+ struct QueryFile {
798+ #[ facet( flatten) ]
799+ queries : IndexMap < Meta < String > , Decl > ,
800+ }
801+
802+ #[ derive( Debug , Facet ) ]
803+ #[ facet( rename_all = "lowercase" ) ]
804+ #[ repr( u8 ) ]
805+ enum Decl {
806+ Select ( Select ) ,
807+ }
808+
809+ #[ derive( Debug , Facet ) ]
810+ struct Select {
811+ from : String ,
812+ }
813+
814+ let source = r#"{
815+ GetUsers @select{from users}
816+ GetPosts @select{from posts}
817+ }"# ;
818+
819+ let result: Result < QueryFile , _ > = from_str ( source) ;
820+ match result {
821+ Ok ( file) => {
822+ eprintln ! ( "Success: {:?}" , file) ;
823+ assert_eq ! ( file. queries. len( ) , 2 ) ;
824+
825+ let keys: Vec < _ > = file. queries . keys ( ) . collect ( ) ;
826+ assert_eq ! ( keys[ 0 ] . value, "GetUsers" ) ;
827+ assert_eq ! ( keys[ 1 ] . value, "GetPosts" ) ;
828+
829+ // Check that spans were captured
830+ eprintln ! ( "GetUsers span: {:?}" , keys[ 0 ] . span) ;
831+ eprintln ! ( "GetPosts span: {:?}" , keys[ 1 ] . span) ;
832+ }
833+ Err ( e) => {
834+ panic ! ( "Failed to parse: {}" , e. render( "<test>" , source) ) ;
835+ }
836+ }
837+ }
0 commit comments