Skip to content

Commit c0e7eda

Browse files
committed
Add custom note in case Any was forced
1 parent 0f47216 commit c0e7eda

4 files changed

Lines changed: 66 additions & 30 deletions

File tree

mypy/checkexpr.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4919,6 +4919,7 @@ def visit_type_application(self, tapp: TypeApplication) -> Type:
49194919
tapp.expr.node,
49204920
tapp.types,
49214921
self.chk.fail,
4922+
self.chk.note,
49224923
tapp.expr.node.no_args,
49234924
tapp,
49244925
self.chk.options,

mypy/message_registry.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def with_additional_msg(self, info: str) -> ErrorMessage:
180180
IMPLICIT_GENERIC_ANY_BUILTIN: Final = (
181181
'Implicit generic "Any". Use "{}" and specify generic parameters'
182182
)
183+
NO_CYCLIC_DEFAULT: Final = "Cyclic type variable defaults are not supported"
183184
INVALID_UNPACK: Final = "{} cannot be unpacked (must be tuple or TypeVarTuple)"
184185
INVALID_UNPACK_POSITION: Final = "Unpack is only valid in a variadic position"
185186
INVALID_PARAM_SPEC_LOCATION: Final = "Invalid location for ParamSpec {}"

mypy/typeanal.py

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ def visit_unbound_type_nonoptional(self, t: UnboundType, defining_literal: bool)
480480
node,
481481
an_args,
482482
self.fail,
483+
self.note,
483484
node.no_args,
484485
t,
485486
self.options,
@@ -908,6 +909,7 @@ def analyze_type_with_type_info(
908909
# TODO: should we allow NamedTuples generic in ParamSpec?
909910
self.anal_array(args, allow_unpack=True),
910911
self.fail,
912+
self.note,
911913
False,
912914
ctx,
913915
self.options,
@@ -932,6 +934,7 @@ def analyze_type_with_type_info(
932934
# TODO: should we allow TypedDicts generic in ParamSpec?
933935
self.anal_array(args, allow_unpack=True),
934936
self.fail,
937+
self.note,
935938
False,
936939
ctx,
937940
self.options,
@@ -2051,6 +2054,7 @@ def get_omitted_any(
20512054
options: Options,
20522055
fullname: str | None = None,
20532056
unexpanded_type: Type | None = None,
2057+
used_default: bool = False,
20542058
) -> AnyType:
20552059
if disallow_any:
20562060
typ = unexpanded_type or orig_type
@@ -2061,6 +2065,8 @@ def get_omitted_any(
20612065
typ,
20622066
code=codes.TYPE_ARG,
20632067
)
2068+
if used_default:
2069+
note(message_registry.NO_CYCLIC_DEFAULT, typ, code=codes.TYPE_ARG)
20642070

20652071
any_type = AnyType(TypeOfAny.from_error, line=typ.line, column=typ.column)
20662072
else:
@@ -2130,7 +2136,14 @@ def fix_instance(
21302136
if any_type is None:
21312137
fullname = None if use_generic_error else t.type.fullname
21322138
any_type = get_omitted_any(
2133-
disallow_any, fail, note, t, options, fullname, unexpanded_type
2139+
disallow_any,
2140+
fail,
2141+
note,
2142+
t,
2143+
options,
2144+
fullname,
2145+
unexpanded_type,
2146+
used_default,
21342147
)
21352148
arg = any_type
21362149
else:
@@ -2151,6 +2164,7 @@ def instantiate_type_alias(
21512164
node: TypeAlias,
21522165
args: list[Type],
21532166
fail: MsgCallback,
2167+
note: MsgCallback,
21542168
no_args: bool,
21552169
ctx: Context,
21562170
options: Options,
@@ -2180,15 +2194,7 @@ def instantiate_type_alias(
21802194
if any(unknown_unpack(a) for a in args):
21812195
# This type is not ready to be validated, because of unknown total count.
21822196
# Note that we keep the kind of Any for consistency.
2183-
return set_any_tvars(
2184-
node,
2185-
[],
2186-
ctx.line,
2187-
ctx.column,
2188-
options,
2189-
special_form=True,
2190-
analyzing_tvar_def=analyzing_tvar_def,
2191-
)
2197+
return set_any_tvars(node, [], ctx.line, ctx.column, options, special_form=True)
21922198

21932199
if (
21942200
no_args
@@ -2215,6 +2221,7 @@ def instantiate_type_alias(
22152221
options,
22162222
disallow_any=disallow_any,
22172223
fail=fail,
2224+
note=note,
22182225
unexpanded_type=unexpanded_type,
22192226
analyzing_tvar_def=analyzing_tvar_def,
22202227
)
@@ -2241,15 +2248,7 @@ def instantiate_type_alias(
22412248
if any(isinstance(a, UnpackType) for a in args):
22422249
# A variadic unpack in fixed size alias (fixed unpacks must be flattened by the caller)
22432250
fail(message_registry.INVALID_UNPACK_POSITION, ctx, code=codes.VALID_TYPE)
2244-
return set_any_tvars(
2245-
node,
2246-
[],
2247-
ctx.line,
2248-
ctx.column,
2249-
options,
2250-
from_error=True,
2251-
analyzing_tvar_def=analyzing_tvar_def,
2252-
)
2251+
return set_any_tvars(node, [], ctx.line, ctx.column, options, from_error=True)
22532252
min_tv_count = sum(not tv.has_default() for tv in node.alias_tvars)
22542253
fill_typevars = act_len != max_tv_count
22552254
correct = min_tv_count <= act_len <= max_tv_count
@@ -2296,7 +2295,10 @@ def instantiate_type_alias(
22962295
ctx.line,
22972296
ctx.column,
22982297
options,
2299-
from_error=True,
2298+
disallow_any=disallow_any,
2299+
fail=fail,
2300+
note=note,
2301+
from_error=not correct,
23002302
analyzing_tvar_def=analyzing_tvar_def,
23012303
)
23022304
elif node.tvar_tuple_index is not None:
@@ -2312,15 +2314,7 @@ def instantiate_type_alias(
23122314
act_suffix = len(args) - unpack - 1
23132315
if act_prefix < exp_prefix or act_suffix < exp_suffix:
23142316
fail("TypeVarTuple cannot be split", ctx, code=codes.TYPE_ARG)
2315-
return set_any_tvars(
2316-
node,
2317-
[],
2318-
ctx.line,
2319-
ctx.column,
2320-
options,
2321-
from_error=True,
2322-
analyzing_tvar_def=analyzing_tvar_def,
2323-
)
2317+
return set_any_tvars(node, [], ctx.line, ctx.column, options, from_error=True)
23242318
# TODO: we need to check args validity w.r.t alias.alias_tvars.
23252319
# Otherwise invalid instantiations will be allowed in runtime context.
23262320
# Note: in type context, these will be still caught by semanal_typeargs.
@@ -2348,6 +2342,7 @@ def set_any_tvars(
23482342
disallow_any: bool = False,
23492343
special_form: bool = False,
23502344
fail: MsgCallback | None = None,
2345+
note: MsgCallback | None = None,
23512346
unexpanded_type: Type | None = None,
23522347
analyzing_tvar_def: bool = False,
23532348
) -> tuple[TypeAliasType, bool]:
@@ -2374,6 +2369,7 @@ def set_any_tvars(
23742369
used_default = True
23752370
if is_typevar_default_recursive(tv.fullname, node):
23762371
arg = any_type
2372+
used_any_type = True
23772373
else:
23782374
arg = any_type
23792375
used_any_type = True
@@ -2390,7 +2386,7 @@ def set_any_tvars(
23902386
assert isinstance(fixed, TypeAliasType)
23912387
t.args = fixed.args
23922388

2393-
if used_any_type and disallow_any and node.alias_tvars:
2389+
if used_any_type and disallow_any and node.alias_tvars and not from_error:
23942390
assert fail is not None
23952391
if unexpanded_type:
23962392
type_str = (
@@ -2406,6 +2402,13 @@ def set_any_tvars(
24062402
Context(newline, newcolumn),
24072403
code=codes.TYPE_ARG,
24082404
)
2405+
if used_default:
2406+
assert note is not None
2407+
note(
2408+
message_registry.NO_CYCLIC_DEFAULT,
2409+
Context(newline, newcolumn),
2410+
code=codes.TYPE_ARG,
2411+
)
24092412
return t, used_default
24102413

24112414

test-data/unit/check-flags.test

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,3 +2717,34 @@ if (
27172717
or z is None
27182718
):
27192719
pass
2720+
2721+
[case testRecursiveTypeVarDefaultMutualDisallow]
2722+
# flags: --disallow-any-generic
2723+
from typing import TypeVar, Generic
2724+
2725+
class C(Generic["T"]):
2726+
pass
2727+
2728+
class D(Generic["S"]):
2729+
pass
2730+
2731+
T = TypeVar("T", default=D) # E: Missing type arguments for generic type "D" \
2732+
# N: Cyclic type variable defaults are not supported
2733+
S = TypeVar("S", default=C) # E: Missing type arguments for generic type "C" \
2734+
# N: Cyclic type variable defaults are not supported
2735+
2736+
c: C
2737+
d: D
2738+
reveal_type(c) # N: Revealed type is "__main__.C[__main__.D[Any]]"
2739+
reveal_type(d) # N: Revealed type is "__main__.D[__main__.C[Any]]"
2740+
2741+
[case testRecursiveTypeVarDefaultOnlyAliasDisallow]
2742+
# flags: --disallow-any-generic
2743+
from typing import TypeVar
2744+
2745+
T = TypeVar("T", default="A") # E: Missing type arguments for generic type "A" \
2746+
# N: Cyclic type variable defaults are not supported
2747+
A = list[T]
2748+
a: A
2749+
reveal_type(a) # N: Revealed type is "builtins.list[builtins.list[Any]]"
2750+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)