
    X-Ph;                       U d Z ddlmZ ddlmZ ddlmZmZmZm	Z	m
Z
mZ ddlmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZ ddlmZ d	Z d
e!d<   d5dZ"d6dZ#d7d!Z$d8d"Z%d9d#Z&e'e(e)         e(e)         f         Z*d:d&Z+d:d'Z, G d( d)e	e)                   Z-d;d-Z. G d. d/e	e)                   Z/d<d1Z0d6d2Z1d6d3Z2d4S )=a_	  Always defined attribute analysis.

An always defined attribute has some statements in __init__ or the
class body that cause the attribute to be always initialized when an
instance is constructed. It must also not be possible to read the
attribute before initialization, and it can't be deletable.

We can assume that the value is always defined when reading an always
defined attribute. Otherwise we'll need to raise AttributeError if the
value is undefined (i.e. has the error value).

We use data flow analysis to figure out attributes that are always
defined. Example:

  class C:
      def __init__(self) -> None:
          self.x = 0
          if func():
              self.y = 1
          else:
              self.y = 2
              self.z = 3

In this example, the attributes 'x' and 'y' are always defined, but 'z'
is not. The analysis assumes that we know that there won't be any subclasses.

The analysis also works if there is a known, closed set of subclasses.
An attribute defined in a base class can only be always defined if it's
also always defined in all subclasses.

As soon as __init__ contains an op that can 'leak' self to another
function, we will stop inferring always defined attributes, since the
analysis is mostly intra-procedural and only looks at __init__ methods.
The called code could read an uninitialized attribute. Example:

  class C:
      def __init__(self) -> None:
          self.x = self.foo()

      def foo(self) -> int:
          ...

Now we won't infer 'x' as always defined, since 'foo' might read 'x'
before initialization.

As an exception to the above limitation, we perform inter-procedural
analysis of super().__init__ calls, since these are very common.

Our analysis is somewhat optimistic. We assume that nobody calls a
method of a partially uninitialized object through gc.get_objects(), in
particular. Code like this could potentially cause a segfault with a null
pointer dereference. This seems very unlikely to be an issue in practice,
however.

Accessing an attribute via getattr always checks for undefined attributes
and thus works if the object is partially uninitialized. This can be used
as a workaround if somebody ever needs to inspect partially uninitialized
objects via gc.get_objects().

The analysis runs after IR building as a separate pass. Since we only
run this on __init__ methods, this analysis pass will be fairly quick.
    )annotations)Final)CFGMAYBE_ANALYSISAnalysisResultBaseAnalysisVisitorget_cfgrun_analysis)analyze_self_leaks)ClassIR)AssignAssignMulti
BasicBlockBranchCall	ControlOpGetAttrRegister
RegisterOpReturnSetAttrSetMemUnreachable)	RInstanceFr   dump_always_defined	class_irslist[ClassIR]returnNonec                    t                      }| D ]}t          ||           t                      }| D ]}t          ||           t                      }| D ]}t          ||           dS )ak  Find always defined attributes all classes of a compilation unit.

    Also tag attribute initialization ops to not decref the previous
    value (as this would read a NULL pointer and segfault).

    Update the _always_initialized_attrs, _sometimes_initialized_attrs
    and init_self_leak attributes in ClassIR instances.

    This is the main entry point.
    N)set%analyze_always_defined_attrs_in_class,update_always_defined_attrs_using_subclassesdetect_undefined_bitmap)r   seencls      Z/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/mypyc/analysis/attrdefined.pyanalyze_always_defined_attrsr(   d   s     D  8 8-b$7777 55D ? ?4R>>>> 55D * *D))))* *    r&   r   r%   set[ClassIR]c                     |v rd S |                                  j        s0 j        s) j        s" j         j                                         rd S  j        dd          D ]}t          ||            	                    d          }|> j
                                         _         j
                                         _        d S |j        d         }t          |j                  }t#          |j        ||          }t%          |j        | j
        |          }t'                      } j        D ]}|                    |j                   t-          |j        || j
        z
  |          }	t/          |j        ||||	|          }
 fd|
D             }
|
 _        t0          r"t3           j        t7          |
                     t9          |j        |||           _        t;          |j        |||           d}|j        D ]D}t=          |j                  D ]-\  }}|j         ||f         rtC          |tD                    sd} n.E| _#        d S )N   __init__r   )initial_undefinedcfgc                >    h | ]}                     |          |S  )is_deletable).0ar&   s     r'   	<setcomp>z8analyze_always_defined_attrs_in_class.<locals>.<setcomp>   s*    JJJArq7I7IJaJJJr)   FT)$addis_traitinherits_pythonallow_interpreted_subclassesbuiltin_basechildrenis_serializablemror"   
get_methodattrs_with_defaultscopy_always_initialized_attrs_sometimes_initialized_attrsarg_regsr	   blocksr   #analyze_maybe_defined_attrs_in_initr!   update
attributes%analyze_maybe_undefined_attrs_in_initfind_always_defined_attributesr   printnamesorted!find_sometimes_defined_attributesmark_attr_initialization_ops	enumerateopsafter
isinstancer   init_self_leak)r&   r%   basemself_regr/   dirtymaybe_defined	all_attrsmaybe_undefinedalways_defined	any_dirtybiops   `              r'   r"   r"      s   	TzzHHRLLL 			 *	 ?&;  	 qrr
 : :-dD9999
j!!Ay')'='B'B'D'D$*,*@*E*E*G*G'z!}H
!(

Cqx377E7	(B2C M %%I * *))));	(i":P.PVY  O 4	(I}ou N KJJJJJJN#1B  /bgvn--...&G	(M5' 'B# !8]EJJJ IX  qu%% 	 	EAr{1a4  B)?)?  	!Br)   rD   list[BasicBlock]rV   r   rY   set[str]rX   AnalysisResult[str]rZ   rW   AnalysisResult[None]c                4   |                                 }| D ]}t          |j                  D ]f\  }}	t          |	t                    r9|	j        |u r0|	j        |j        ||f         v r|                    |	j                   t          |	t                    rO|	j        |u rF|	j        |j        ||f         v r0|	j        |j        ||f         v r|                    |	j                   |j
        ||f         r3|j        ||f         s"||j
        ||f         |j
        ||f         z
  z  } nnt          |	t                    rW|	                                D ]B}
|j
        ||f         s1|j        |
df         r"||j
        |
df         |j
        |
df         z
  z  }Ch|S )zFind attributes that are always initialized in some basic blocks.

    The analysis results are expected to be up-to-date for the blocks.

    Return a set of always defined attributes.
    r   )r@   rO   rP   rR   r   objattrbeforediscardr   rQ   r   targets)rD   rV   rY   rX   rZ   rW   attrsblockr^   r_   targets              r'   rI   rI      s    NNE  uy)) 	 	EAr"g&& +26X+=+=7o4UAX>>>MM"'***
 "g&& +26X+=+=G5eQh???=#7q#AAAMM"'*** {5!8$ |E1H- !%+E1H58MeUVh8WWE "i((  jjll  F ;uax0 U\&!)5L  %)/	:_=RSY[\S\=]]! Lr)   c                |   t                      }| D ]}t          |j                  D ]\  }}|j        ||f         r#|j        ||f         s||j        ||f         z  } n]t          |t                    rG|                                D ]2}|j        ||f         s!|j        |df         r||j        |df         z  }3|S )zDFind attributes that are sometimes initialized in some basic blocks.r   )r!   rO   rP   rQ   rg   rR   r   ri   )	rD   rV   rX   rW   rj   rk   r^   r_   rl   s	            r'   rM   rM      s     eeE 
G 
Guy)) 		G 		GEAr{5!8$ |E1H- B!M$7q$AAE"i(( G jjll G GF ;uax0 GU\&!)5L G %(;FAI(F FLr)   c                    | D ]u}t          |j                  D ]^\  }}t          |t                    rD|j        |u r;|j        }||j        ||f         vr#|j        ||f         s|                                 _vdS )zTag all SetAttr ops in the basic blocks that initialize attributes.

    Initialization ops assume that the previous attribute value is the error value,
    so there's no need to decref or check for definedness.
    N)	rO   rP   rR   r   re   rf   rg   rQ   mark_as_initializer)rD   rV   rX   rW   rk   r^   r_   rf   s           r'   rN   rN     s      - -uy)) 	- 	-EAr"g&& -26X+=+=w}3E1H===ekRWYZRZF[=**,,,		-- -r)   r_   r   c                    | j         j        j        d         j        }t	          |t
                    sJ |j        }d |j        D             S )zLCalculate attributes that are always initialized by a super().__init__ call.r   c                P    h | ]#}|j         D ]}|                    |          |$S r1   )rG   is_always_defined)r3   rT   r4   s      r'   r5   z6attributes_initialized_by_init_call.<locals>.<setcomp>"  s;    WWW$$/WWQT=S=STU=V=VWAWWWWr)   )fnsigargstyperR   r   class_irr=   r_   	self_typer&   s      r'   #attributes_initialized_by_init_callrz     sI    	q!&Ii+++++		BWW"&WWWWr)   c                    | j         j        j        d         j        }t	          |t
                    sJ |j        }t          |           |j        z  S )zHCalculate attributes that may be initialized by a super().__init__ call.r   )	rs   rt   ru   rv   rR   r   rw   rz   rB   rx   s      r'   )attributes_maybe_initialized_by_init_callr|   %  sI    	q!&Ii+++++		B.r22R5TTTr)   c                  R    e Zd ZdZddZdd
ZddZddZddZddZ	ddZ
ddZdS ) AttributeMaybeDefinedVisitorzFind attributes that may have been defined via some code path.

    Consider initializations in class body and assignments to 'self.x'
    and calls to base class '__init__'.
    rV   r   r   r   c                    || _         d S NrV   selfrV   s     r'   r-   z%AttributeMaybeDefinedVisitor.__init__4       r)   r_   r   tuple[set[str], set[str]]c                :    t                      t                      fS r   r!   r   r_   s     r'   visit_branchz)AttributeMaybeDefinedVisitor.visit_branch7      uucee|r)   r   c                :    t                      t                      fS r   r   r   s     r'   visit_returnz)AttributeMaybeDefinedVisitor.visit_return:  r   r)   r   c                :    t                      t                      fS r   r   r   s     r'   visit_unreachablez.AttributeMaybeDefinedVisitor.visit_unreachable=  r   r)   r   c                H   t          |t                    r$|j        | j        u r|j        ht                      fS t          |t                    r9|j        j        r-|j        j	        dk    rt          |          t                      fS t                      t                      fS Nr-   )rR   r   re   rV   rf   r!   r   rs   
class_namerK   r|   r   s     r'   visit_register_opz.AttributeMaybeDefinedVisitor.visit_register_op@  s    b'"" 	$rv'>'>G9cee##b$ 	HBE$4 	Hz9Q9Q<R@@#%%GGuucee|r)   r   c                :    t                      t                      fS r   r   r   s     r'   visit_assignz)AttributeMaybeDefinedVisitor.visit_assignG  r   r)   r   c                :    t                      t                      fS r   r   r   s     r'   visit_assign_multiz/AttributeMaybeDefinedVisitor.visit_assign_multiJ  r   r)   r   c                :    t                      t                      fS r   r   r   s     r'   visit_set_memz*AttributeMaybeDefinedVisitor.visit_set_memM  r   r)   NrV   r   r   r   r_   r   r   r   r_   r   r   r   r_   r   r   r   r_   r   r   r   r_   r   r   r   r_   r   r   r   r_   r   r   r   __name__
__module____qualname____doc__r-   r   r   r   r   r   r   r   r1   r)   r'   r~   r~   -           ! ! ! !                       r)   r~   r?   r/   r   c                P    t          | |t          |          |dt                    S NF)rD   r/   gen_and_killinitialbackwardkind)r
   r~   r   )rD   rV   r?   r/   s       r'   rE   rE   Q  s5     1(;;#   r)   c                  R    e Zd ZdZddZdd
ZddZddZddZddZ	ddZ
ddZdS ) AttributeMaybeUndefinedVisitorzFind attributes that may be undefined via some code path.

    Consider initializations in class body, assignments to 'self.x'
    and calls to base class '__init__'.
    rV   r   r   r   c                    || _         d S r   r   r   s     r'   r-   z'AttributeMaybeUndefinedVisitor.__init__e  r   r)   r_   r   r   c                :    t                      t                      fS r   r   r   s     r'   r   z+AttributeMaybeUndefinedVisitor.visit_branchh  r   r)   r   c                :    t                      t                      fS r   r   r   s     r'   r   z+AttributeMaybeUndefinedVisitor.visit_returnk  r   r)   r   c                :    t                      t                      fS r   r   r   s     r'   r   z0AttributeMaybeUndefinedVisitor.visit_unreachablen  r   r)   r   c                H   t          |t                    r$|j        | j        u rt	                      |j        hfS t          |t                    r9|j        j        r-|j        j	        dk    rt	                      t          |          fS t	                      t	                      fS r   )rR   r   re   rV   r!   rf   r   rs   r   rK   rz   r   s     r'   r   z0AttributeMaybeUndefinedVisitor.visit_register_opq  s    b'"" 	$rv'>'>5527)##b$ 	BBE$4 	Bz9Q9Q55=bAAAAuucee|r)   r   c                :    t                      t                      fS r   r   r   s     r'   r   z+AttributeMaybeUndefinedVisitor.visit_assignx  r   r)   r   c                :    t                      t                      fS r   r   r   s     r'   r   z1AttributeMaybeUndefinedVisitor.visit_assign_multi{  r   r)   r   c                :    t                      t                      fS r   r   r   s     r'   r   z,AttributeMaybeUndefinedVisitor.visit_set_mem~  r   r)   Nr   r   r   r   r   r   r   r   r   r1   r)   r'   r   r   ^  r   r)   r   r.   c                P    t          | |t          |          |dt                    S r   )r
   r   r   )rD   rV   r.   r/   s       r'   rH   rH     s5     3H==!   r)   c                   | |v rdS | j         dS t                      }| j        D ]:}| j         D ]0}t          ||           ||j        vr|                    |           1;| xj        |z  c_        |                    |            dS )zJRemove attributes not defined in all subclasses from always defined attrs.N)r;   r!   rA   r#   r6   )r&   r%   removedrf   childs        r'   r#   r#     s    	Tzz	{eeG, " "[ 	" 	"E8EEE5:::D!!!	"   G+  HHRLLLLLr)   c                   | j         rd S | |v rd S |                    |            | j        dd          D ]}t          | |           t	          | j                  dk    r*| j                            | j        d         j                   | j                                        D ];\  }}|j	        r/| 
                    |          s| j                            |           <| j        dd          D ]g}|j         r^|j                                        D ]D\  }}|j	        r8| 
                    |          s#|| j        vr| j                            |           Ehd S )Nr,   )r7   r6   base_mror$   lenbitmap_attrsextendrG   itemserror_overlaprr   appendr=   )r&   r%   rT   nts        r'   r$   r$     sx   	{ 	TzzHHRLLLABB * *D))))
2;!
r{1~:;;;##%% & &1? 	&2#7#7#:#: 	&O""1%%%qrr
 . .= 	.--// . .1? .2+?+?+B+B .qPRP_G_G_O**1---	. .r)   N)r   r   r   r   )r&   r   r%   r*   r   r   )rD   r`   rV   r   rY   ra   rX   rb   rZ   rb   rW   rc   r   ra   )
rD   r`   rV   r   rX   rb   rW   rc   r   ra   )
rD   r`   rV   r   rX   rb   rW   rc   r   r   )r_   r   r   ra   )
rD   r`   rV   r   r?   ra   r/   r   r   rb   )
rD   r`   rV   r   r.   ra   r/   r   r   rb   )3r   
__future__r   typingr   mypyc.analysis.dataflowr   r   r   r   r	   r
   mypyc.analysis.selfleaksr   mypyc.ir.class_irr   mypyc.ir.opsr   r   r   r   r   r   r   r   r   r   r   r   r   mypyc.ir.rtypesr   r   __annotations__r(   r"   rI   rM   rN   tupler!   str
GenAndKillrz   r|   r~   rE   r   rH   r#   r$   r1   r)   r'   <module>r      s  = = =~ # " " " " "                      8 7 7 7 7 7 % % % % % %                              & % % % % % #  " " " "* * * *8<" <" <" <"~/ / / /d   ,- - - -& 3s8SX%&
X X X XU U U U! ! ! ! !#6s#; ! ! !H
 
 
 
! ! ! ! !%8%= ! ! !H
 
 
 
   ". . . . . .r)   