Skip to content

Commit 9405b87

Browse files
committed
Keep NoneType in Union TypeVar values
1 parent ad7af29 commit 9405b87

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

mypy/expandtype.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,25 +50,37 @@
5050

5151
@overload
5252
def expand_type(
53-
typ: ProperType, env: Mapping[TypeVarId, Type], allow_erased_callables: bool = ...
53+
typ: ProperType,
54+
env: Mapping[TypeVarId, Type],
55+
allow_erased_callables: bool = ...,
56+
*,
57+
keep_none_type: bool = ...,
5458
) -> ProperType:
5559
...
5660

5761

5862
@overload
5963
def expand_type(
60-
typ: Type, env: Mapping[TypeVarId, Type], allow_erased_callables: bool = ...
64+
typ: Type,
65+
env: Mapping[TypeVarId, Type],
66+
allow_erased_callables: bool = ...,
67+
*,
68+
keep_none_type: bool = ...,
6169
) -> Type:
6270
...
6371

6472

6573
def expand_type(
66-
typ: Type, env: Mapping[TypeVarId, Type], allow_erased_callables: bool = False
74+
typ: Type,
75+
env: Mapping[TypeVarId, Type],
76+
allow_erased_callables: bool = False,
77+
*,
78+
keep_none_type: bool = False,
6779
) -> Type:
6880
"""Substitute any type variable references in a type given by a type
6981
environment.
7082
"""
71-
return typ.accept(ExpandTypeVisitor(env, allow_erased_callables))
83+
return typ.accept(ExpandTypeVisitor(env, allow_erased_callables, keep_none_type))
7284

7385

7486
@overload
@@ -183,10 +195,14 @@ class ExpandTypeVisitor(TypeVisitor[Type]):
183195
variables: Mapping[TypeVarId, Type] # TypeVar id -> TypeVar value
184196

185197
def __init__(
186-
self, variables: Mapping[TypeVarId, Type], allow_erased_callables: bool = False
198+
self,
199+
variables: Mapping[TypeVarId, Type],
200+
allow_erased_callables: bool = False,
201+
keep_none_type: bool = False,
187202
) -> None:
188203
self.variables = variables
189204
self.allow_erased_callables = allow_erased_callables
205+
self.keep_none_type = keep_none_type
190206
self.recursive_guard: set[Type | tuple[int, Type]] = set()
191207

192208
def visit_unbound_type(self, t: UnboundType) -> Type:
@@ -470,7 +486,7 @@ def visit_union_type(self, t: UnionType) -> Type:
470486
# might be subtypes of others, however calling make_simplified_union()
471487
# can cause recursion, so we just remove strict duplicates.
472488
return UnionType.make_union(
473-
remove_trivial(flatten_nested_unions(expanded)), t.line, t.column
489+
remove_trivial(flatten_nested_unions(expanded), self.keep_none_type), t.line, t.column
474490
)
475491

476492
def visit_partial_type(self, t: PartialType) -> Type:

mypy/typeanal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,7 @@ def fix_instance(
16921692
args.append(arg)
16931693
env[tv.id] = arg
16941694
t.args = tuple(args)
1695-
fixed = expand_type(t, env)
1695+
fixed = expand_type(t, env, keep_none_type=True)
16961696
assert isinstance(fixed, Instance)
16971697
t.args = fixed.args
16981698

mypy/types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3679,7 +3679,7 @@ def store_argument_type(
36793679
defn.arguments[i].variable.type = arg_type
36803680

36813681

3682-
def remove_trivial(types: Iterable[Type]) -> list[Type]:
3682+
def remove_trivial(types: Iterable[Type], keep_none_type: bool = False) -> list[Type]:
36833683
"""Make trivial simplifications on a list of types without calling is_subtype().
36843684
36853685
This makes following simplifications:
@@ -3694,7 +3694,7 @@ def remove_trivial(types: Iterable[Type]) -> list[Type]:
36943694
p_t = get_proper_type(t)
36953695
if isinstance(p_t, UninhabitedType):
36963696
continue
3697-
if isinstance(p_t, NoneType) and not state.strict_optional:
3697+
if isinstance(p_t, NoneType) and not state.strict_optional and not keep_none_type:
36983698
removed_none = True
36993699
continue
37003700
if isinstance(p_t, Instance) and p_t.type.fullname == "builtins.object":

0 commit comments

Comments
 (0)