167167 is_more_precise ,
168168 is_proper_subtype ,
169169 is_same_type ,
170+ is_same_type_ranges ,
170171 is_subtype ,
171172 restrict_subtype_away ,
172173 unify_generic_callable ,
@@ -6252,9 +6253,12 @@ def is_type_call(expr: CallExpr) -> bool:
62526253 current_type = self .get_isinstance_type (expr )
62536254 if current_type is None :
62546255 continue
6255- if type_being_compared is not None and type_being_compared != current_type :
6256+ if type_being_compared is not None and not is_same_type_ranges (
6257+ type_being_compared , current_type
6258+ ):
62566259 # It doesn't really make sense to have several types being
62576260 # compared to the output of type (like type(x) == int == str)
6261+ # unless they are the same (like type(x) == float == float)
62586262 # because whether that's true is solely dependent on what the
62596263 # types being compared are, so we don't try to narrow types any
62606264 # further because we can't really get any information about the
@@ -6269,11 +6273,10 @@ def is_type_call(expr: CallExpr) -> bool:
62696273 return {}, {}
62706274
62716275 if type_being_compared is None :
6272- # TODO: use more accurate lower bound analysis
6273- least_type = self .least_type ([self .lookup_type (expr ) for expr in exprs_in_type_calls ])
6274- type_being_compared = (
6275- None if least_type is None else [TypeRange (least_type , is_upper_bound = True )]
6276+ least_type = reduce (
6277+ meet_types , (self .lookup_type (expr ) for expr in exprs_in_type_calls )
62766278 )
6279+ type_being_compared = [TypeRange (least_type , is_upper_bound = True )]
62776280
62786281 if_maps : list [TypeMap ] = []
62796282 else_maps : list [TypeMap ] = []
@@ -6308,28 +6311,6 @@ def combine_maps(list_maps: list[TypeMap]) -> TypeMap:
63086311 else_map = {}
63096312 return if_map , else_map
63106313
6311- def least_type (self , types : list [Type ]) -> Type | None :
6312- """Find the type of which all other types are supertypes.
6313- `Any` types are i
6314- For example, `least_type([dict, defaultdict, object]) => dict`.
6315- However, `least_type[int, str]) => None`.
6316-
6317- It would be better if we could represent an intersection of types.
6318-
6319- For example, consider `s: str` and `i: int`.
6320- `type(s) == type(i)` implies `s: str & int` and `i: str & int`,
6321- even though `s: object` and `i: object` also hold.
6322- """
6323- types = [typ for typ in types if not isinstance (typ , AnyType )]
6324- if not types :
6325- return None
6326- least_type = reduce (lambda t1 , t2 : t1 if is_subtype (t1 , t2 ) else t2 , types )
6327-
6328- if all (typ is least_type or is_subtype (least_type , typ ) for typ in types ):
6329- # Ensure that this is a least type
6330- return least_type
6331- return None
6332-
63336314 def find_isinstance_check (
63346315 self , node : Expression , * , in_boolean_context : bool = True
63356316 ) -> tuple [TypeMap , TypeMap ]:
0 commit comments