Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 39 additions & 29 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,13 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
self.api.record_incomplete_ref()
# Always allow ParamSpec for placeholders, if they are actually not valid,
# they will be reported later, after we resolve placeholders.
with self.set_allow_param_spec_literals(True):
return PlaceholderType(
node.fullname, self.anal_array(t.args, allow_param_spec=True), t.line
)
return PlaceholderType(
node.fullname,
self.anal_array(
t.args, allow_param_spec=True, allow_param_spec_literals=True
),
t.line,
)
else:
if self.api.final_iteration:
self.cannot_resolve_type(t)
Expand Down Expand Up @@ -382,10 +385,13 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
return special
if isinstance(node, TypeAlias):
self.aliases_used.add(fullname)
with self.set_allow_param_spec_literals(node.has_param_spec_type):
an_args = self.anal_array(t.args, allow_param_spec=True)
if node.has_param_spec_type and len(node.alias_tvars) == 1:
an_args = self.pack_paramspec_args(an_args)
an_args = self.anal_array(
t.args,
allow_param_spec=True,
allow_param_spec_literals=node.has_param_spec_type,
)
if node.has_param_spec_type and len(node.alias_tvars) == 1:
an_args = self.pack_paramspec_args(an_args)

disallow_any = self.options.disallow_any_generics and not self.is_typeshed_stub
res = expand_type_alias(
Expand Down Expand Up @@ -660,17 +666,22 @@ def analyze_type_with_type_info(
fallback = Instance(info, [AnyType(TypeOfAny.special_form)], ctx.line)
return TupleType(self.anal_array(args), fallback, ctx.line)

# This is a heuristic: it will be checked later anyways but the error
# message may be worse.
with self.set_allow_param_spec_literals(info.has_param_spec_type):
# Analyze arguments and (usually) construct Instance type. The
# number of type arguments and their values are
# checked only later, since we do not always know the
# valid count at this point. Thus we may construct an
# Instance with an invalid number of type arguments.
instance = Instance(
info, self.anal_array(args, allow_param_spec=True), ctx.line, ctx.column
)
# Analyze arguments and (usually) construct Instance type. The
# number of type arguments and their values are
# checked only later, since we do not always know the
# valid count at this point. Thus we may construct an
# Instance with an invalid number of type arguments.
#
# We allow ParamSpec literals based on a heuristic: it will be
# checked later anyways but the error message may be worse.
instance = Instance(
info,
self.anal_array(
args, allow_param_spec=True, allow_param_spec_literals=info.has_param_spec_type
),
ctx.line,
ctx.column,
)
if len(info.type_vars) == 1 and info.has_param_spec_type:
instance.args = tuple(self.pack_paramspec_args(instance.args))

Expand Down Expand Up @@ -1466,11 +1477,19 @@ def is_defined_type_var(self, tvar: str, context: Context) -> bool:
return self.tvar_scope.get_binding(tvar_node) is not None

def anal_array(
self, a: Iterable[Type], nested: bool = True, *, allow_param_spec: bool = False
self,
a: Iterable[Type],
nested: bool = True,
*,
allow_param_spec: bool = False,
allow_param_spec_literals: bool = False,
) -> list[Type]:
old_allow_param_spec_literals = self.allow_param_spec_literals
self.allow_param_spec_literals = allow_param_spec_literals
res: list[Type] = []
for t in a:
res.append(self.anal_type(t, nested, allow_param_spec=allow_param_spec))
self.allow_param_spec_literals = old_allow_param_spec_literals
return self.check_unpacks_in_list(res)

def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = False) -> Type:
Expand Down Expand Up @@ -1558,15 +1577,6 @@ def tuple_type(self, items: list[Type]) -> TupleType:
any_type = AnyType(TypeOfAny.special_form)
return TupleType(items, fallback=self.named_type("builtins.tuple", [any_type]))

@contextmanager
def set_allow_param_spec_literals(self, to: bool) -> Iterator[None]:
old = self.allow_param_spec_literals
try:
self.allow_param_spec_literals = to
yield
finally:
self.allow_param_spec_literals = old


TypeVarLikeList = List[Tuple[str, TypeVarLikeExpr]]

Expand Down