@@ -402,7 +402,7 @@ cached module PointsToInternal {
402402 or
403403 scope_entry_points_to ( def , context , value , origin )
404404 or
405- InterModulePointsTo:: implicit_submodule_points_to ( def , context , value , origin )
405+ InterModulePointsTo:: implicit_submodule_points_to ( def , value , origin ) and context . isImport ( )
406406 or
407407 iteration_definition_points_to ( def , context , value , origin )
408408 /*
@@ -647,18 +647,22 @@ private module InterModulePointsTo {
647647 )
648648 }
649649
650+ /* Helper for implicit_submodule_points_to */
651+ private ModuleObjectInternal getModule ( ImplicitSubModuleDefinition def ) {
652+ exists ( PackageObjectInternal package |
653+ package .getSourceModule ( ) = def .getDefiningNode ( ) .getScope ( ) and
654+ result = package .submodule ( def .getSourceVariable ( ) .getName ( ) )
655+ )
656+ }
657+
650658 /** Implicit "definition" of the names of submodules at the start of an `__init__.py` file.
651659 *
652660 * PointsTo isn't exactly how the interpreter works, but is the best approximation we can manage statically.
653661 */
654662 pragma [ noinline]
655- predicate implicit_submodule_points_to ( ImplicitSubModuleDefinition def , PointsToContext context , ModuleObjectInternal value , ControlFlowNode origin ) {
656- exists ( PackageObjectInternal package |
657- package .getSourceModule ( ) = def .getDefiningNode ( ) .getScope ( ) |
658- value = package .submodule ( def .getSourceVariable ( ) .getName ( ) ) and
659- origin = CfgOrigin:: fromObject ( value ) .asCfgNodeOrHere ( def .getDefiningNode ( ) ) and
660- context .isImport ( )
661- )
663+ predicate implicit_submodule_points_to ( ImplicitSubModuleDefinition def , ModuleObjectInternal value , ControlFlowNode origin ) {
664+ value = getModule ( def ) and
665+ origin = CfgOrigin:: fromObject ( value ) .asCfgNodeOrHere ( def .getDefiningNode ( ) )
662666 }
663667
664668 /** Points-to for `from ... import *`. */
0 commit comments