@@ -818,7 +818,11 @@ impl<'db> Type<'db> {
818818 }
819819
820820 pub fn module_literal ( db : & ' db dyn Db , importing_file : File , submodule : & Module ) -> Self {
821- Self :: ModuleLiteral ( ModuleLiteralType :: new ( db, importing_file, submodule) )
821+ Self :: ModuleLiteral ( ModuleLiteralType :: new (
822+ db,
823+ submodule,
824+ submodule. kind ( ) . is_package ( ) . then_some ( importing_file) ,
825+ ) )
822826 }
823827
824828 pub const fn into_module_literal ( self ) -> Option < ModuleLiteralType < ' db > > {
@@ -7503,20 +7507,34 @@ pub enum WrapperDescriptorKind {
75037507#[ salsa:: interned( debug) ]
75047508#[ derive( PartialOrd , Ord ) ]
75057509pub struct ModuleLiteralType < ' db > {
7506- /// The file in which this module was imported.
7507- ///
7508- /// We need this in order to know which submodules should be attached to it as attributes
7509- /// (because the submodules were also imported in this file).
7510- pub importing_file : File ,
7511-
75127510 /// The imported module.
75137511 pub module : Module ,
7512+
7513+ /// The file in which this module was imported.
7514+ ///
7515+ /// If the module is a module that could have submodules (a package),
7516+ /// we need this in order to know which submodules should be attached to it as attributes
7517+ /// (because the submodules were also imported in this file). For a package, this should
7518+ /// therefore always be `Some()`. If the module is not a package, however, this should
7519+ /// always be `None`: this helps reduce memory usage (the information is redundant for
7520+ /// single-file modules), and ensures that two module-literal types that both refer to
7521+ /// the same underlying single-file module are understood by ty as being equivalent types
7522+ /// in all situations.
7523+ _importing_file : Option < File > ,
75147524}
75157525
75167526// The Salsa heap is tracked separately.
75177527impl get_size2:: GetSize for ModuleLiteralType < ' _ > { }
75187528
75197529impl < ' db > ModuleLiteralType < ' db > {
7530+ fn importing_file ( self , db : & ' db dyn Db ) -> Option < File > {
7531+ debug_assert_eq ! (
7532+ self . _importing_file( db) . is_some( ) ,
7533+ self . module( db) . kind( ) . is_package( )
7534+ ) ;
7535+ self . _importing_file ( db)
7536+ }
7537+
75207538 fn static_member ( self , db : & ' db dyn Db , name : & str ) -> PlaceAndQualifiers < ' db > {
75217539 // `__dict__` is a very special member that is never overridden by module globals;
75227540 // we should always look it up directly as an attribute on `types.ModuleType`,
@@ -7536,15 +7554,16 @@ impl<'db> ModuleLiteralType<'db> {
75367554 // the parent module's `__init__.py` file being evaluated. That said, we have
75377555 // chosen to always have the submodule take priority. (This matches pyright's
75387556 // current behavior, but is the opposite of mypy's current behavior.)
7539- if let Some ( submodule_name) = ModuleName :: new ( name) {
7540- let importing_file = self . importing_file ( db) ;
7541- let imported_submodules = imported_modules ( db, importing_file) ;
7542- let mut full_submodule_name = self . module ( db) . name ( ) . clone ( ) ;
7543- full_submodule_name. extend ( & submodule_name) ;
7544- if imported_submodules. contains ( & full_submodule_name) {
7545- if let Some ( submodule) = resolve_module ( db, & full_submodule_name) {
7546- return Place :: bound ( Type :: module_literal ( db, importing_file, & submodule) )
7547- . into ( ) ;
7557+ if let Some ( importing_file) = self . importing_file ( db) {
7558+ if let Some ( submodule_name) = ModuleName :: new ( name) {
7559+ let imported_submodules = imported_modules ( db, importing_file) ;
7560+ let mut full_submodule_name = self . module ( db) . name ( ) . clone ( ) ;
7561+ full_submodule_name. extend ( & submodule_name) ;
7562+ if imported_submodules. contains ( & full_submodule_name) {
7563+ if let Some ( submodule) = resolve_module ( db, & full_submodule_name) {
7564+ return Place :: bound ( Type :: module_literal ( db, importing_file, & submodule) )
7565+ . into ( ) ;
7566+ }
75487567 }
75497568 }
75507569 }
0 commit comments