|
167 | 167 | TypeAliasStmt,
|
168 | 168 | TypeApplication,
|
169 | 169 | TypedDictExpr,
|
| 170 | + TypeFormExpr, |
170 | 171 | TypeInfo,
|
171 | 172 | TypeParam,
|
172 | 173 | TypeVarExpr,
|
|
186 | 187 | type_aliases_source_versions,
|
187 | 188 | typing_extensions_aliases,
|
188 | 189 | )
|
189 |
| -from mypy.options import Options |
| 190 | +from mypy.options import Options, TYPE_FORM |
190 | 191 | from mypy.patterns import (
|
191 | 192 | AsPattern,
|
192 | 193 | ClassPattern,
|
@@ -3151,6 +3152,7 @@ def visit_assignment_stmt(self, s: AssignmentStmt) -> None:
|
3151 | 3152 | self.store_final_status(s)
|
3152 | 3153 | self.check_classvar(s)
|
3153 | 3154 | self.process_type_annotation(s)
|
| 3155 | + self.analyze_rvalue_as_type_form(s) |
3154 | 3156 | self.apply_dynamic_class_hook(s)
|
3155 | 3157 | if not s.type:
|
3156 | 3158 | self.process_module_assignment(s.lvalues, s.rvalue, s)
|
@@ -3479,6 +3481,10 @@ def analyze_lvalues(self, s: AssignmentStmt) -> None:
|
3479 | 3481 | has_explicit_value=has_explicit_value,
|
3480 | 3482 | )
|
3481 | 3483 |
|
| 3484 | + def analyze_rvalue_as_type_form(self, s: AssignmentStmt) -> None: |
| 3485 | + if TYPE_FORM in self.options.enable_incomplete_feature: |
| 3486 | + s.rvalue.as_type = self.try_parse_as_type_expression(s.rvalue) |
| 3487 | + |
3482 | 3488 | def apply_dynamic_class_hook(self, s: AssignmentStmt) -> None:
|
3483 | 3489 | if not isinstance(s.rvalue, CallExpr):
|
3484 | 3490 | return
|
@@ -5161,6 +5167,8 @@ def visit_return_stmt(self, s: ReturnStmt) -> None:
|
5161 | 5167 | self.fail('"return" outside function', s)
|
5162 | 5168 | if s.expr:
|
5163 | 5169 | s.expr.accept(self)
|
| 5170 | + if TYPE_FORM in self.options.enable_incomplete_feature: |
| 5171 | + s.expr.as_type = self.try_parse_as_type_expression(s.expr) |
5164 | 5172 |
|
5165 | 5173 | def visit_raise_stmt(self, s: RaiseStmt) -> None:
|
5166 | 5174 | self.statement = s
|
@@ -5674,10 +5682,33 @@ def visit_call_expr(self, expr: CallExpr) -> None:
|
5674 | 5682 | with self.allow_unbound_tvars_set():
|
5675 | 5683 | for a in expr.args:
|
5676 | 5684 | a.accept(self)
|
| 5685 | + elif refers_to_fullname( |
| 5686 | + expr.callee, ("typing.TypeForm", "typing_extensions.TypeForm") |
| 5687 | + ): |
| 5688 | + # Special form TypeForm(...). |
| 5689 | + if not self.check_fixed_args(expr, 1, "TypeForm"): |
| 5690 | + return |
| 5691 | + # Translate first argument to an unanalyzed type. |
| 5692 | + try: |
| 5693 | + typ = self.expr_to_unanalyzed_type(expr.args[0]) |
| 5694 | + except TypeTranslationError: |
| 5695 | + self.fail("TypeForm argument is not a type", expr) |
| 5696 | + # Suppress future error: "<typing special form>" not callable |
| 5697 | + expr.analyzed = CastExpr(expr.args[0], AnyType(TypeOfAny.from_error)) |
| 5698 | + return |
| 5699 | + # Piggyback TypeFormExpr object to the CallExpr object; it takes |
| 5700 | + # precedence over the CallExpr semantics. |
| 5701 | + expr.analyzed = TypeFormExpr(typ) |
| 5702 | + expr.analyzed.line = expr.line |
| 5703 | + expr.analyzed.column = expr.column |
| 5704 | + expr.analyzed.accept(self) |
5677 | 5705 | else:
|
5678 | 5706 | # Normal call expression.
|
| 5707 | + calculate_type_forms = TYPE_FORM in self.options.enable_incomplete_feature |
5679 | 5708 | for a in expr.args:
|
5680 | 5709 | a.accept(self)
|
| 5710 | + if calculate_type_forms: |
| 5711 | + a.as_type = self.try_parse_as_type_expression(a) |
5681 | 5712 |
|
5682 | 5713 | if (
|
5683 | 5714 | isinstance(expr.callee, MemberExpr)
|
@@ -5946,6 +5977,11 @@ def visit_cast_expr(self, expr: CastExpr) -> None:
|
5946 | 5977 | if analyzed is not None:
|
5947 | 5978 | expr.type = analyzed
|
5948 | 5979 |
|
| 5980 | + def visit_type_form_expr(self, expr: TypeFormExpr) -> None: |
| 5981 | + analyzed = self.anal_type(expr.type) |
| 5982 | + if analyzed is not None: |
| 5983 | + expr.type = analyzed |
| 5984 | + |
5949 | 5985 | def visit_assert_type_expr(self, expr: AssertTypeExpr) -> None:
|
5950 | 5986 | expr.expr.accept(self)
|
5951 | 5987 | analyzed = self.anal_type(expr.type)
|
@@ -7381,6 +7417,37 @@ def parse_dataclass_transform_field_specifiers(self, arg: Expression) -> tuple[s
|
7381 | 7417 | names.append(specifier.fullname)
|
7382 | 7418 | return tuple(names)
|
7383 | 7419 |
|
| 7420 | + def try_parse_as_type_expression(self, maybe_type_expr: Expression) -> Type|None: |
| 7421 | + """Try to parse maybe_type_expr as a type expression. |
| 7422 | + If parsing fails return None and emit no errors.""" |
| 7423 | + # Save SemanticAnalyzer state |
| 7424 | + original_errors = self.errors # altered by fail() |
| 7425 | + original_num_incomplete_refs = self.num_incomplete_refs # altered by record_incomplete_ref() |
| 7426 | + original_progress = self.progress # altered by defer() |
| 7427 | + original_deferred = self.deferred # altered by defer() |
| 7428 | + original_deferral_debug_context_len = len(self.deferral_debug_context) # altered by defer() |
| 7429 | + |
| 7430 | + self.errors = Errors(Options()) |
| 7431 | + try: |
| 7432 | + t = self.expr_to_analyzed_type(maybe_type_expr) |
| 7433 | + if self.errors.is_errors(): |
| 7434 | + raise TypeTranslationError |
| 7435 | + if isinstance(t, UnboundType): |
| 7436 | + raise TypeTranslationError |
| 7437 | + if isinstance(t, PlaceholderType): |
| 7438 | + raise TypeTranslationError |
| 7439 | + except TypeTranslationError: |
| 7440 | + # Not a type expression. It must be a value expression. |
| 7441 | + t = None |
| 7442 | + finally: |
| 7443 | + # Restore SemanticAnalyzer state |
| 7444 | + self.errors = original_errors |
| 7445 | + self.num_incomplete_refs = original_num_incomplete_refs |
| 7446 | + self.progress = original_progress |
| 7447 | + self.deferred = original_deferred |
| 7448 | + del self.deferral_debug_context[original_deferral_debug_context_len:] |
| 7449 | + return t |
| 7450 | + |
7384 | 7451 |
|
7385 | 7452 | def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike:
|
7386 | 7453 | if isinstance(sig, CallableType):
|
|
0 commit comments