66 */
77
88use std:: borrow:: Cow ;
9+ use std:: cmp:: Ord ;
10+ use std:: cmp:: Ordering ;
911use std:: fmt;
1012use std:: fmt:: Display ;
13+ use std:: hash:: Hash ;
14+ use std:: hash:: Hasher ;
1115
16+ use dupe:: Dupe ;
1217use pyrefly_derive:: TypeEq ;
1318use pyrefly_derive:: Visit ;
1419use pyrefly_derive:: VisitMut ;
1520use pyrefly_python:: dunder;
21+ use pyrefly_python:: module:: Module ;
1622use pyrefly_python:: module_name:: ModuleName ;
23+ use pyrefly_python:: module_path:: ModulePath ;
1724use pyrefly_util:: display:: commas_iter;
1825use pyrefly_util:: prelude:: VecExt ;
26+ use pyrefly_util:: visit:: Visit ;
1927use pyrefly_util:: visit:: VisitMut ;
2028use ruff_python_ast:: Keyword ;
2129use ruff_python_ast:: name:: Name ;
2230
31+ use crate :: class:: Class ;
2332use crate :: class:: ClassType ;
33+ use crate :: equality:: TypeEq ;
2434use crate :: keywords:: DataclassTransformKeywords ;
2535use crate :: types:: Type ;
2636
@@ -297,12 +307,12 @@ pub struct FuncMetadata {
297307}
298308
299309impl FuncMetadata {
300- pub fn def ( module : ModuleName , cls : Name , func : Name ) -> Self {
310+ pub fn def ( module : Module , cls : Class , func : Name ) -> Self {
301311 Self {
302312 kind : FunctionKind :: Def ( Box :: new ( FuncId {
303313 module,
304314 cls : Some ( cls) ,
305- func,
315+ name : func,
306316 } ) ) ,
307317 flags : FuncFlags :: default ( ) ,
308318 }
@@ -341,29 +351,89 @@ pub struct FuncFlags {
341351 pub dataclass_transform_metadata : Option < DataclassTransformKeywords > ,
342352}
343353
344- #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
345- #[ derive( Visit , VisitMut , TypeEq ) ]
354+ #[ derive( Debug , Clone ) ]
346355pub struct FuncId {
347- pub module : ModuleName ,
348- pub cls : Option < Name > ,
349- pub func : Name ,
356+ pub module : Module ,
357+ pub cls : Option < Class > ,
358+ pub name : Name ,
359+ }
360+
361+ impl PartialEq for FuncId {
362+ fn eq ( & self , other : & Self ) -> bool {
363+ self . key_eq ( ) . eq ( & other. key_eq ( ) )
364+ }
365+ }
366+
367+ impl Eq for FuncId { }
368+ impl TypeEq for FuncId { }
369+
370+ impl Ord for FuncId {
371+ fn cmp ( & self , other : & Self ) -> Ordering {
372+ self . key_ord ( ) . cmp ( & other. key_ord ( ) )
373+ }
374+ }
375+
376+ impl PartialOrd for FuncId {
377+ fn partial_cmp ( & self , other : & Self ) -> Option < Ordering > {
378+ Some ( self . cmp ( other) )
379+ }
380+ }
381+
382+ impl Hash for FuncId {
383+ fn hash < H : Hasher > ( & self , state : & mut H ) {
384+ self . key_eq ( ) . hash ( state)
385+ }
386+ }
387+
388+ impl VisitMut < Type > for FuncId {
389+ fn recurse_mut ( & mut self , _: & mut dyn FnMut ( & mut Type ) ) { }
390+ }
391+ impl Visit < Type > for FuncId {
392+ fn recurse < ' a > ( & ' a self , _: & mut dyn FnMut ( & ' a Type ) ) { }
350393}
351394
352395impl FuncId {
353- pub fn format ( & self , current_module : ModuleName ) -> String {
396+ fn key_eq ( & self ) -> ( ModuleName , ModulePath , Option < Class > , & Name ) {
397+ (
398+ self . module . name ( ) ,
399+ self . module . path ( ) . to_key_eq ( ) ,
400+ self . cls . clone ( ) ,
401+ & self . name ,
402+ )
403+ }
404+
405+ fn key_ord ( & self ) -> ( ModuleName , ModulePath , Option < Class > , & Name ) {
406+ self . key_eq ( )
407+ }
408+
409+ fn format_impl (
410+ func_module : ModuleName ,
411+ func_cls : Option < Class > ,
412+ func_name : & Name ,
413+ current_module : ModuleName ,
414+ ) -> String {
354415 let module_prefix =
355- if self . module == current_module || self . module == ModuleName :: builtins ( ) {
416+ if func_module == current_module || func_module == ModuleName :: builtins ( ) {
356417 "" . to_owned ( )
357418 } else {
358- format ! ( "{}." , self . module )
419+ format ! ( "{}." , func_module )
359420 } ;
360- let class_prefix = match & self . cls {
421+ let class_prefix = match & func_cls {
361422 Some ( cls) => {
362- format ! ( "{cls }." )
423+ format ! ( "{}." , cls . name ( ) )
363424 }
364425 None => "" . to_owned ( ) ,
365426 } ;
366- format ! ( "{module_prefix}{class_prefix}{}" , self . func)
427+ format ! ( "{module_prefix}{class_prefix}{}" , func_name)
428+ }
429+
430+ pub fn format ( & self , current_module : ModuleName ) -> String {
431+ Self :: format_impl (
432+ self . module . name ( ) ,
433+ self . cls . clone ( ) ,
434+ & self . name ,
435+ current_module,
436+ )
367437 }
368438}
369439
@@ -628,8 +698,8 @@ impl Display for Param {
628698}
629699
630700impl FunctionKind {
631- pub fn from_name ( module : ModuleName , cls : Option < & Name > , func : & Name ) -> Self {
632- match ( module. as_str ( ) , cls, func. as_str ( ) ) {
701+ pub fn from_name ( module : Module , cls : Option < Class > , func : & Name ) -> Self {
702+ match ( module. name ( ) . as_str ( ) , cls. as_ref ( ) , func. as_str ( ) ) {
633703 ( "builtins" , None , "isinstance" ) => Self :: IsInstance ,
634704 ( "builtins" , None , "issubclass" ) => Self :: IsSubclass ,
635705 ( "builtins" , None , "classmethod" ) => Self :: ClassMethod ,
@@ -648,95 +718,31 @@ impl FunctionKind {
648718 ( "functools" , None , "total_ordering" ) => Self :: TotalOrdering ,
649719 _ => Self :: Def ( Box :: new ( FuncId {
650720 module,
651- cls : cls . cloned ( ) ,
652- func : func. clone ( ) ,
721+ cls,
722+ name : func. clone ( ) ,
653723 } ) ) ,
654724 }
655725 }
656726
657- pub fn as_func_id ( & self ) -> FuncId {
727+ pub fn module_name ( & self ) -> ModuleName {
658728 match self {
659- Self :: IsInstance => FuncId {
660- module : ModuleName :: builtins ( ) ,
661- cls : None ,
662- func : Name :: new_static ( "isinstance" ) ,
663- } ,
664- Self :: IsSubclass => FuncId {
665- module : ModuleName :: builtins ( ) ,
666- cls : None ,
667- func : Name :: new_static ( "issubclass" ) ,
668- } ,
669- Self :: ClassMethod => FuncId {
670- module : ModuleName :: builtins ( ) ,
671- cls : None ,
672- func : Name :: new_static ( "classmethod" ) ,
673- } ,
674- Self :: Dataclass => FuncId {
675- module : ModuleName :: dataclasses ( ) ,
676- cls : None ,
677- func : Name :: new_static ( "dataclass" ) ,
678- } ,
679- Self :: DataclassField => FuncId {
680- module : ModuleName :: dataclasses ( ) ,
681- cls : None ,
682- func : Name :: new_static ( "field" ) ,
683- } ,
684- Self :: DataclassTransform => FuncId {
685- module : ModuleName :: typing ( ) ,
686- cls : None ,
687- func : Name :: new_static ( "dataclass_transform" ) ,
688- } ,
689- Self :: Final => FuncId {
690- module : ModuleName :: typing ( ) ,
691- cls : None ,
692- func : Name :: new_static ( "final" ) ,
693- } ,
694- Self :: Overload => FuncId {
695- module : ModuleName :: typing ( ) ,
696- cls : None ,
697- func : Name :: new_static ( "overload" ) ,
698- } ,
699- Self :: Override => FuncId {
700- module : ModuleName :: typing ( ) ,
701- cls : None ,
702- func : Name :: new_static ( "override" ) ,
703- } ,
704- Self :: Cast => FuncId {
705- module : ModuleName :: typing ( ) ,
706- cls : None ,
707- func : Name :: new_static ( "cast" ) ,
708- } ,
709- Self :: AssertType => FuncId {
710- module : ModuleName :: typing ( ) ,
711- cls : None ,
712- func : Name :: new_static ( "assert_type" ) ,
713- } ,
714- Self :: RevealType => FuncId {
715- module : ModuleName :: typing ( ) ,
716- cls : None ,
717- func : Name :: new_static ( "reveal_type" ) ,
718- } ,
719- Self :: RuntimeCheckable => FuncId {
720- module : ModuleName :: typing ( ) ,
721- cls : None ,
722- func : Name :: new_static ( "runtime_checkable" ) ,
723- } ,
724- Self :: CallbackProtocol ( cls) => FuncId {
725- module : cls. qname ( ) . module_name ( ) ,
726- cls : Some ( cls. name ( ) . clone ( ) ) ,
727- func : dunder:: CALL ,
728- } ,
729- Self :: AbstractMethod => FuncId {
730- module : ModuleName :: abc ( ) ,
731- cls : None ,
732- func : Name :: new_static ( "abstractmethod" ) ,
733- } ,
734- Self :: TotalOrdering => FuncId {
735- module : ModuleName :: functools ( ) ,
736- cls : None ,
737- func : Name :: new_static ( "total_ordering" ) ,
738- } ,
739- Self :: Def ( func_id) => ( * * func_id) . clone ( ) ,
729+ Self :: IsInstance => ModuleName :: builtins ( ) ,
730+ Self :: IsSubclass => ModuleName :: builtins ( ) ,
731+ Self :: ClassMethod => ModuleName :: builtins ( ) ,
732+ Self :: Dataclass => ModuleName :: dataclasses ( ) ,
733+ Self :: DataclassField => ModuleName :: dataclasses ( ) ,
734+ Self :: DataclassTransform => ModuleName :: typing ( ) ,
735+ Self :: Final => ModuleName :: typing ( ) ,
736+ Self :: Overload => ModuleName :: typing ( ) ,
737+ Self :: Override => ModuleName :: typing ( ) ,
738+ Self :: Cast => ModuleName :: typing ( ) ,
739+ Self :: AssertType => ModuleName :: typing ( ) ,
740+ Self :: RevealType => ModuleName :: typing ( ) ,
741+ Self :: RuntimeCheckable => ModuleName :: typing ( ) ,
742+ Self :: CallbackProtocol ( cls) => cls. qname ( ) . module_name ( ) ,
743+ Self :: AbstractMethod => ModuleName :: abc ( ) ,
744+ Self :: TotalOrdering => ModuleName :: functools ( ) ,
745+ Self :: Def ( func_id) => func_id. module . name ( ) . dupe ( ) ,
740746 }
741747 }
742748
@@ -758,9 +764,40 @@ impl FunctionKind {
758764 Self :: CallbackProtocol ( _) => Cow :: Owned ( dunder:: CALL ) ,
759765 Self :: AbstractMethod => Cow :: Owned ( Name :: new_static ( "abstractmethod" ) ) ,
760766 Self :: TotalOrdering => Cow :: Owned ( Name :: new_static ( "total_ordering" ) ) ,
761- Self :: Def ( func_id) => Cow :: Borrowed ( & func_id. func ) ,
767+ Self :: Def ( func_id) => Cow :: Borrowed ( & func_id. name ) ,
762768 }
763769 }
770+
771+ pub fn class ( & self ) -> Option < Class > {
772+ match self {
773+ Self :: IsInstance => None ,
774+ Self :: IsSubclass => None ,
775+ Self :: ClassMethod => None ,
776+ Self :: Dataclass => None ,
777+ Self :: DataclassField => None ,
778+ Self :: DataclassTransform => None ,
779+ Self :: Final => None ,
780+ Self :: Overload => None ,
781+ Self :: Override => None ,
782+ Self :: Cast => None ,
783+ Self :: AssertType => None ,
784+ Self :: RevealType => None ,
785+ Self :: RuntimeCheckable => None ,
786+ Self :: CallbackProtocol ( cls) => Some ( cls. class_object ( ) . dupe ( ) ) ,
787+ Self :: AbstractMethod => None ,
788+ Self :: TotalOrdering => None ,
789+ Self :: Def ( func_id) => func_id. cls . clone ( ) ,
790+ }
791+ }
792+
793+ pub fn format ( & self , current_module : ModuleName ) -> String {
794+ FuncId :: format_impl (
795+ self . module_name ( ) ,
796+ self . class ( ) ,
797+ self . function_name ( ) . as_ref ( ) ,
798+ current_module,
799+ )
800+ }
764801}
765802
766803pub fn unexpected_keyword ( error : & dyn Fn ( String ) , func : & str , keyword : & Keyword ) {
0 commit comments