def put(self, expr: Expression, typ: Type) -> None: if not isinstance(expr, BindableTypes): return if not literal(expr): return key = literal_hash(expr) assert key is not None, 'Internal error: binder tried to put non-literal' if key not in self.declarations: self.declarations[key] = get_declaration(expr) self._add_dependencies(key) self._put(key, typ)
def put(self, expr: Expression, typ: Type) -> None: if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)): return if not literal(expr): return key = literal_hash(expr) assert key is not None, 'Internal error: binder tried to put non-literal' if key not in self.declarations: self.declarations[key] = get_declaration(expr) self._add_dependencies(key) self._put(key, typ)
def contains_int_or_tuple_of_ints( expr: Expression) -> Union[None, int, Tuple[int], Tuple[int, ...]]: if isinstance(expr, IntExpr): return expr.value if isinstance(expr, TupleExpr): if literal(expr) == LITERAL_YES: thing = [] for x in expr.items: if not isinstance(x, IntExpr): return None thing.append(x.value) return tuple(thing) return None
def contains_int_or_tuple_of_ints(expr: Expression ) -> Union[None, int, Tuple[int], Tuple[int, ...]]: if isinstance(expr, IntExpr): return expr.value if isinstance(expr, TupleExpr): if literal(expr) == LITERAL_YES: thing = [] for x in expr.items: if not isinstance(x, IntExpr): return None thing.append(x.value) return tuple(thing) return None
def assign_type(self, expr: Expression, type: Type, declared_type: Optional[Type], restrict_any: bool = False) -> None: if self.type_assignments is not None: # We are in a multiassign from union, defer the actual binding, # just collect the types. self.type_assignments[expr].append((type, declared_type)) return if not isinstance(expr, BindableTypes): return None if not literal(expr): return self.invalidate_dependencies(expr) if declared_type is None: # Not sure why this happens. It seems to mainly happen in # member initialization. return if not is_subtype(type, declared_type): # Pretty sure this is only happens when there's a type error. # Ideally this function wouldn't be called if the # expression has a type error, though -- do other kinds of # errors cause this function to get called at invalid # times? return enclosing_type = self.most_recent_enclosing_type(expr, type) if (isinstance(enclosing_type, AnyType) and not restrict_any): # If x is Any and y is int, after x = y we do not infer that x is int. # This could be changed. if not isinstance(type, AnyType): # We narrowed type from Any in a recent frame (probably an # isinstance check), but now it is reassigned, so broaden back # to Any (which is the most recent enclosing type) self.put(expr, enclosing_type) elif (isinstance(type, AnyType) and not (isinstance(declared_type, UnionType) and any( isinstance(item, AnyType) for item in declared_type.items))): # Assigning an Any value doesn't affect the type to avoid false negatives, unless # there is an Any item in a declared union type. self.put(expr, declared_type) else: self.put(expr, type) for i in self.try_frames: # XXX This should probably not copy the entire frame, but # just copy this variable into a single stored frame. self.allow_jump(i)
def assign_type(self, expr: Expression, type: Type, declared_type: Optional[Type], restrict_any: bool = False) -> None: if self.type_assignments is not None: # We are in a multiassign from union, defer the actual binding, # just collect the types. self.type_assignments[expr].append((type, declared_type)) return if not isinstance(expr, BindableTypes): return None if not literal(expr): return self.invalidate_dependencies(expr) if declared_type is None: # Not sure why this happens. It seems to mainly happen in # member initialization. return if not is_subtype(type, declared_type): # Pretty sure this is only happens when there's a type error. # Ideally this function wouldn't be called if the # expression has a type error, though -- do other kinds of # errors cause this function to get called at invalid # times? return enclosing_type = self.most_recent_enclosing_type(expr, type) if (isinstance(enclosing_type, AnyType) and not restrict_any): # If x is Any and y is int, after x = y we do not infer that x is int. # This could be changed. if not isinstance(type, AnyType): # We narrowed type from Any in a recent frame (probably an # isinstance check), but now it is reassigned, so broaden back # to Any (which is the most recent enclosing type) self.put(expr, enclosing_type) elif (isinstance(type, AnyType) and not (isinstance(declared_type, UnionType) and any(isinstance(item, AnyType) for item in declared_type.items))): # Assigning an Any value doesn't affect the type to avoid false negatives, unless # there is an Any item in a declared union type. self.put(expr, declared_type) else: self.put(expr, type) for i in self.try_frames: # XXX This should probably not copy the entire frame, but # just copy this variable into a single stored frame. self.allow_jump(i)
def assign_type(self, expr: Expression, type: Type, declared_type: Optional[Type], restrict_any: bool = False) -> None: # We should erase last known value in binder, because if we are using it, # it means that the target is not final, and therefore can't hold a literal. type = remove_instance_last_known_values(type) type = get_proper_type(type) declared_type = get_proper_type(declared_type) if self.type_assignments is not None: # We are in a multiassign from union, defer the actual binding, # just collect the types. self.type_assignments[expr].append((type, declared_type)) return if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)): return None if not literal(expr): return self.invalidate_dependencies(expr) if declared_type is None: # Not sure why this happens. It seems to mainly happen in # member initialization. return if not is_subtype(type, declared_type): # Pretty sure this is only happens when there's a type error. # Ideally this function wouldn't be called if the # expression has a type error, though -- do other kinds of # errors cause this function to get called at invalid # times? return enclosing_type = get_proper_type(self.most_recent_enclosing_type(expr, type)) if isinstance(enclosing_type, AnyType) and not restrict_any: # If x is Any and y is int, after x = y we do not infer that x is int. # This could be changed. # Instead, since we narrowed type from Any in a recent frame (probably an # isinstance check), but now it is reassigned, we broaden back # to Any (which is the most recent enclosing type) self.put(expr, enclosing_type) # As a special case, when assigning Any to a variable with a # declared Optional type that has been narrowed to None, # replace all the Nones in the declared Union type with Any. # This overrides the normal behavior of ignoring Any assignments to variables # in order to prevent false positives. # (See discussion in #3526) elif (isinstance(type, AnyType) and isinstance(declared_type, UnionType) and any(isinstance(item, NoneType) for item in declared_type.items) and isinstance(get_proper_type(self.most_recent_enclosing_type(expr, NoneType())), NoneType)): # Replace any Nones in the union type with Any new_items = [type if isinstance(item, NoneType) else item for item in declared_type.items] self.put(expr, UnionType(new_items)) elif (isinstance(type, AnyType) and not (isinstance(declared_type, UnionType) and any(isinstance(item, AnyType) for item in declared_type.items))): # Assigning an Any value doesn't affect the type to avoid false negatives, unless # there is an Any item in a declared union type. self.put(expr, declared_type) else: self.put(expr, type) for i in self.try_frames: # XXX This should probably not copy the entire frame, but # just copy this variable into a single stored frame. self.allow_jump(i)
def assign_type(self, expr: Expression, type: Type, declared_type: Optional[Type], restrict_any: bool = False) -> None: if self.type_assignments is not None: # We are in a multiassign from union, defer the actual binding, # just collect the types. self.type_assignments[expr].append((type, declared_type)) return if not isinstance(expr, (IndexExpr, MemberExpr, NameExpr)): return None if not literal(expr): return self.invalidate_dependencies(expr) if declared_type is None: # Not sure why this happens. It seems to mainly happen in # member initialization. return if not is_subtype(type, declared_type): # Pretty sure this is only happens when there's a type error. # Ideally this function wouldn't be called if the # expression has a type error, though -- do other kinds of # errors cause this function to get called at invalid # times? return enclosing_type = self.most_recent_enclosing_type(expr, type) if isinstance(enclosing_type, AnyType) and not restrict_any: # If x is Any and y is int, after x = y we do not infer that x is int. # This could be changed. # Instead, since we narrowed type from Any in a recent frame (probably an # isinstance check), but now it is reassigned, we broaden back # to Any (which is the most recent enclosing type) self.put(expr, enclosing_type) # As a special case, when assigning Any to a variable with a # declared Optional type that has been narrowed to None, # replace all the Nones in the declared Union type with Any. # This overrides the normal behavior of ignoring Any assignments to variables # in order to prevent false positives. # (See discussion in #3526) elif (isinstance(type, AnyType) and isinstance(declared_type, UnionType) and any(isinstance(item, NoneTyp) for item in declared_type.items) and isinstance(self.most_recent_enclosing_type(expr, NoneTyp()), NoneTyp)): # Replace any Nones in the union type with Any new_items = [type if isinstance(item, NoneTyp) else item for item in declared_type.items] self.put(expr, UnionType(new_items)) elif (isinstance(type, AnyType) and not (isinstance(declared_type, UnionType) and any(isinstance(item, AnyType) for item in declared_type.items))): # Assigning an Any value doesn't affect the type to avoid false negatives, unless # there is an Any item in a declared union type. self.put(expr, declared_type) else: self.put(expr, type) for i in self.try_frames: # XXX This should probably not copy the entire frame, but # just copy this variable into a single stored frame. self.allow_jump(i)