Skip to content

Commit 768b54c

Browse files
committed
Address reviews
1 parent bbb830f commit 768b54c

File tree

3 files changed

+37
-12
lines changed

3 files changed

+37
-12
lines changed

mypy/constraints.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,15 @@ def infer_constraints_for_callable(
126126
param_spec_arg_names = []
127127
param_spec_arg_kinds = []
128128

129+
incomplete_star_mapping = False
130+
for i, actuals in enumerate(formal_to_actual): # TODO: isn't this `enumerate(arg_types)`?
131+
for actual in actuals:
132+
if actual is None and callee.arg_kinds[i] in (ARG_STAR, ARG_STAR2): # type: ignore[unreachable]
133+
# We can't use arguments to infer ParamSpec constraint, if only some
134+
# are present in the current inference pass.
135+
incomplete_star_mapping = True # type: ignore[unreachable]
136+
break
137+
129138
for i, actuals in enumerate(formal_to_actual):
130139
if isinstance(callee.arg_types[i], UnpackType):
131140
unpack_type = callee.arg_types[i]
@@ -221,16 +230,17 @@ def infer_constraints_for_callable(
221230
# constraints, instead store them and infer single constraint at the end.
222231
# It is impossible to map actual kind to formal kind, so use some heuristic.
223232
# This inference is used as a fallback, so relying on heuristic should be OK.
224-
param_spec_arg_types.append(
225-
mapper.expand_actual_type(
226-
actual_arg_type, arg_kinds[actual], None, arg_kinds[actual]
233+
if not incomplete_star_mapping:
234+
param_spec_arg_types.append(
235+
mapper.expand_actual_type(
236+
actual_arg_type, arg_kinds[actual], None, arg_kinds[actual]
237+
)
227238
)
228-
)
229-
actual_kind = arg_kinds[actual]
230-
param_spec_arg_kinds.append(
231-
ARG_POS if actual_kind not in (ARG_STAR, ARG_STAR2) else actual_kind
232-
)
233-
param_spec_arg_names.append(arg_names[actual] if arg_names else None)
239+
actual_kind = arg_kinds[actual]
240+
param_spec_arg_kinds.append(
241+
ARG_POS if actual_kind not in (ARG_STAR, ARG_STAR2) else actual_kind
242+
)
243+
param_spec_arg_names.append(arg_names[actual] if arg_names else None)
234244
else:
235245
actual_type = mapper.expand_actual_type(
236246
actual_arg_type,
@@ -240,7 +250,11 @@ def infer_constraints_for_callable(
240250
)
241251
c = infer_constraints(callee.arg_types[i], actual_type, SUPERTYPE_OF)
242252
constraints.extend(c)
243-
if param_spec and not any(c.type_var == param_spec.id for c in constraints):
253+
if (
254+
param_spec
255+
and not any(c.type_var == param_spec.id for c in constraints)
256+
and not incomplete_star_mapping
257+
):
244258
# Use ParamSpec constraint from arguments only if there are no other constraints,
245259
# since as explained above it is quite ad-hoc.
246260
constraints.append(

mypy/nodes.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,11 @@ class Node(Context):
171171
__slots__ = ()
172172

173173
def __str__(self) -> str:
174-
return self.accept(mypy.strconv.StrConv(options=Options()))
174+
ans = self.accept(mypy.strconv.StrConv(options=Options()))
175+
if ans is None:
176+
# Some visitors might have empty bodies and actually return `None`
177+
return repr(self) # type: ignore[unreachable]
178+
return ans
175179

176180
def str_with_options(self, options: Options) -> str:
177181
ans = self.accept(mypy.strconv.StrConv(options=options))
@@ -867,6 +871,8 @@ def deserialize(cls, data: JsonDict) -> FuncDef:
867871

868872
# All types that are both SymbolNodes and FuncBases. See the FuncBase
869873
# docstring for the rationale.
874+
# See https://github.com/python/mypy/pull/13607#issuecomment-1236357236
875+
# TODO: we want to remove this at some point and just use `FuncBase` ideally.
870876
SYMBOL_FUNCBASE_TYPES: Final = (OverloadedFuncDef, FuncDef)
871877

872878

mypy/server/mergecheck.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,18 @@ def check_consistency(o: object) -> None:
2525
if isinstance(sym, FakeInfo):
2626
continue
2727

28+
fn = sym.fullname
29+
# Skip None and empty names, since they are ambiguous.
30+
# TODO: Everything should have a proper full name?
31+
if not fn:
32+
continue
33+
2834
# Skip stuff that should be expected to have duplicate names
2935
if isinstance(sym, (Var, Decorator)):
3036
continue
3137
if isinstance(sym, FuncDef) and sym.is_overload:
3238
continue
3339

34-
fn = sym.fullname
3540
if fn not in m:
3641
m[fn] = sym
3742
continue

0 commit comments

Comments
 (0)