Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 52134fe

Browse files
[codex] Remove redundant type-param and constructor fallback logic (#450)
## Summary This removes another round of redundant fallback logic that had accumulated around generic class registration and synthetic constructor handling. The main changes are: - remove redundant class type-parameter recovery and registration branches in `name_check_visitor.py` - remove dead class-scope and inferred-registration fallback paths that no longer affect behavior after the earlier type-param cleanup - remove dead synthetic-constructor fallback branches in `checker.py`, including a late dataclass constructor retry and a manual synthetic `__init__` signature reconstruction path - trim a now-unused helper parameter in the synthetic member initializer path ## Why These paths were re-deriving information that pycroscope already computes canonically from class bases, declared type parameters, and the main synthetic constructor machinery. Keeping the extra fallback branches around made the code harder to reason about and increased the risk of the branches drifting apart. This PR keeps the canonical abstractions in charge: - class type parameters come from class analysis and base handling - synthetic constructor signatures come from the main constructor selection logic rather than ad hoc late fallbacks ## Impact This is a cleanup/refactor PR with no intended user-visible behavior change. The result is less code, fewer fallback paths, and tighter adherence to the existing abstractions around `TypeObject`, generic metadata, and synthetic constructor handling. ## Validation - `uv run --python 3.14 --extra tests pytest` - `uv run --python 3.12 python tools/conformance_ci.py --typing-repo ~/py/typing`
1 parent 37e61f1 commit 52134fe

2 files changed

Lines changed: 5 additions & 140 deletions

File tree

pycroscope/checker.py

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,7 +1500,7 @@ def _synthetic_new_cls_annotation_matches(
15001500
new_symbol = tobj.get_declared_symbol("__new__")
15011501
has_direct_new = new_symbol is not None and new_symbol.is_method
15021502
if has_direct_new:
1503-
method = get_synthetic_member_initializer(tobj, "__new__", self)
1503+
method = get_synthetic_member_initializer(tobj, "__new__")
15041504
if method is None:
15051505
return True
15061506
else:
@@ -1567,7 +1567,7 @@ def _get_synthetic_constructor_method_signature(
15671567
tobj = self.make_type_object(value.class_type.typ)
15681568
if use_direct_method:
15691569
method = (
1570-
get_synthetic_member_initializer(tobj, method_name, self)
1570+
get_synthetic_member_initializer(tobj, method_name)
15711571
or UNINITIALIZED_VALUE
15721572
)
15731573
if not isinstance(method, Value):
@@ -1895,14 +1895,6 @@ def _get_synthetic_constructor_signature(
18951895
return new_sig
18961896
if init_sig is not None:
18971897
return init_sig
1898-
if dataclass_info is not None and dataclass_init_enabled:
1899-
dataclass_sig = dataclass_helpers.get_synthetic_constructor_signature(
1900-
type_object,
1901-
instance_type,
1902-
get_field_parameters=self.get_synthetic_dataclass_field_parameters,
1903-
)
1904-
if dataclass_sig is not None:
1905-
return dataclass_sig
19061898
if get_call_attribute is not None:
19071899
call_method = get_call_attribute(value)
19081900
else:
@@ -2435,20 +2427,6 @@ def signature_from_value(
24352427
value.class_type.typ, allow_synthetic_type=True
24362428
)
24372429
if argspec is None:
2438-
tobj = self.make_type_object(value.class_type.typ)
2439-
init_attr = get_synthetic_member_initializer(tobj, "__init__", self)
2440-
if init_attr is not None:
2441-
init_sig = self.signature_from_value(init_attr)
2442-
if isinstance(init_sig, BoundMethodSignature):
2443-
init_sig = init_sig.get_signature(ctx=self)
2444-
if isinstance(init_sig, (Signature, OverloadedSignature)):
2445-
bound_init = init_sig.bind_self(
2446-
self_annotation_value=value.class_type, ctx=self
2447-
)
2448-
if bound_init is not None:
2449-
return _replace_signature_return(
2450-
bound_init, value.class_type
2451-
)
24522430
return Signature.make([ELLIPSIS_PARAM], value.class_type)
24532431
return argspec
24542432
elif isinstance(value, TypedValue):
@@ -2867,9 +2845,7 @@ def get_bound_self_type(self) -> Value | None:
28672845
return None
28682846

28692847

2870-
def get_synthetic_member_initializer(
2871-
tobj: TypeObject, name: str, ctx: CanAssignContext
2872-
) -> Value | None:
2848+
def get_synthetic_member_initializer(tobj: TypeObject, name: str) -> Value | None:
28732849
symbol = tobj.get_synthetic_declared_symbols().get(name)
28742850
if symbol is None:
28752851
return None
@@ -2887,7 +2863,7 @@ def get_inherited_synthetic_member_initializer(
28872863
if class_key in seen:
28882864
return None
28892865
seen = seen | {class_key}
2890-
direct = get_synthetic_member_initializer(tobj, name, ctx)
2866+
direct = get_synthetic_member_initializer(tobj, name)
28912867
if direct is not None:
28922868
return direct
28932869
for base_value in tobj.get_direct_bases():

pycroscope/name_check_visitor.py

Lines changed: 1 addition & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -4225,9 +4225,6 @@ def visit_ClassDef(self, node: ast.ClassDef) -> Value:
42254225
class_scope_object if isinstance(class_scope_object, type) else None
42264226
)
42274227
is_protocol_class = self._is_protocol_class(base_values, class_scope_object)
4228-
analyzed_base_values = self._base_values_for_generic_analysis(
4229-
node, base_values
4230-
)
42314228
class_type_param_polarities: dict[object, set[int]] = {}
42324229
if not is_protocol_class:
42334230
for base_variance_info in base_type_param_variance_infos:
@@ -4243,41 +4240,6 @@ def visit_ClassDef(self, node: ast.ClassDef) -> Value:
42434240
if type_param_values
42444241
else self._type_params_from_base_values(base_values)
42454242
)
4246-
if (
4247-
not type_param_values
4248-
and self.module is None
4249-
and not effective_type_param_values
4250-
and analyzed_base_values is not base_values
4251-
):
4252-
effective_type_param_values = (
4253-
self._order_type_params_by_base_annotation_appearance(
4254-
node.bases,
4255-
self._type_params_from_base_values(analyzed_base_values),
4256-
)
4257-
)
4258-
if not effective_type_param_values and self.module is None:
4259-
# In static-fallback mode we can lose Generic[...] type arguments
4260-
# from base values; recover from base annotation expressions.
4261-
recovered_type_param_values = (
4262-
self._type_params_from_base_annotations_for_default_rules(
4263-
node.bases
4264-
)
4265-
)
4266-
should_use_recovered_type_params = any(
4267-
not isinstance(type_param, TypeVarParam)
4268-
or _type_param_uses_infer_variance(type_param)
4269-
for type_param in recovered_type_param_values
4270-
)
4271-
if not should_use_recovered_type_params:
4272-
# Recovering type parameters here is still important for
4273-
# classes that expose non-constructor generic methods.
4274-
should_use_recovered_type_params = any(
4275-
isinstance(statement, (ast.FunctionDef, ast.AsyncFunctionDef))
4276-
and statement.name not in {"__init__", "__new__"}
4277-
for statement in node.body
4278-
)
4279-
if should_use_recovered_type_params:
4280-
effective_type_param_values = recovered_type_param_values
42814243
annotation_type_param_values = (
42824244
self._type_params_from_base_annotations_for_default_rules(node.bases)
42834245
)
@@ -4312,50 +4274,7 @@ def visit_ClassDef(self, node: ast.ClassDef) -> Value:
43124274
tobj.set_declared_type_params(tuple(registered_type_param_values))
43134275
else:
43144276
tobj.clear_declared_type_params()
4315-
method_type_params = (
4316-
type_param_values
4317-
if type_param_values
4318-
else self._merge_type_params_using_declared_identities(
4319-
self._type_params_from_base_values(base_values),
4320-
annotation_type_param_values,
4321-
append_unmatched_declared=True,
4322-
)
4323-
)
4324-
if (
4325-
not type_param_values
4326-
and self.module is None
4327-
and analyzed_base_values is not base_values
4328-
):
4329-
method_type_params = self._merge_type_params_using_declared_identities(
4330-
self._order_type_params_by_base_annotation_appearance(
4331-
node.bases,
4332-
self._type_params_from_base_values(analyzed_base_values),
4333-
),
4334-
annotation_type_param_values,
4335-
append_unmatched_declared=True,
4336-
)
4337-
if not method_type_params and self.module is None:
4338-
method_type_params = annotation_type_param_values
4339-
if (
4340-
not method_type_params
4341-
and effective_type_param_values
4342-
and any(
4343-
isinstance(type_param, ParamSpecParam)
4344-
or isinstance(type_param, TypeVarTupleParam)
4345-
for type_param in effective_type_param_values
4346-
)
4347-
):
4348-
method_type_params = effective_type_param_values
4349-
method_type_param_values = method_type_params
4350-
if not type_param_values:
4351-
method_type_param_values = self._align_type_params_with_runtime_class(
4352-
runtime_class_for_type_params, method_type_param_values
4353-
)
4354-
class_scope_type_params = (
4355-
tuple(registered_type_param_values)
4356-
if registered_type_param_values
4357-
else tuple(method_type_param_values)
4358-
)
4277+
class_scope_type_params = tuple(registered_type_param_values)
43594278
should_register_generic_bases = synthetic_typeddict is None and (
43604279
isinstance(generic_class_key, str) or bool(registered_type_param_values)
43614280
)
@@ -4422,34 +4341,6 @@ def visit_ClassDef(self, node: ast.ClassDef) -> Value:
44224341
is_protocol=False,
44234342
)
44244343
)
4425-
elif any(
4426-
_type_param_uses_infer_variance(type_param)
4427-
for type_param in registered_type_param_values
4428-
):
4429-
inferred_type_params = (
4430-
self._infer_type_param_variances_from_polarities(
4431-
registered_type_param_values,
4432-
class_type_param_polarities,
4433-
is_protocol=False,
4434-
)
4435-
)
4436-
inferred_by_identity = {
4437-
type_param.typevar: type_param.variance
4438-
for type_param in inferred_type_params
4439-
}
4440-
inferred_registration_type_params = [
4441-
(
4442-
replace(
4443-
type_param,
4444-
variance=inferred_by_identity.get(
4445-
type_param.typevar, type_param.variance
4446-
),
4447-
)
4448-
if _type_param_uses_infer_variance(type_param)
4449-
else type_param
4450-
)
4451-
for type_param in registered_type_param_values
4452-
]
44534344

44544345
if inferred_registration_type_params is not None:
44554346
self.checker.register_synthetic_type_bases(
@@ -4476,8 +4367,6 @@ def visit_ClassDef(self, node: ast.ClassDef) -> Value:
44764367
append_unmatched_declared=False,
44774368
)
44784369
)
4479-
elif not declared_type_params:
4480-
declared_type_params = annotation_declared_type_params
44814370
self._check_class_type_param_default_rules(node, declared_type_params)
44824371
self._check_class_base_type_param_variances(
44834372
node,

0 commit comments

Comments
 (0)