|
16 | 16 | Semantic analysis is the first analysis pass after parsing, and it is
|
17 | 17 | subdivided into three passes:
|
18 | 18 |
|
19 |
| - * SemanticAnalyzerPass1 looks up externally visible names defined in a |
20 |
| - module but ignores imports and local definitions. It helps enable |
21 |
| - (some) cyclic references between modules, such as module 'a' that |
22 |
| - imports module 'b' and used names defined in b *and* vice versa. The |
23 |
| - first pass can be performed before dependent modules have been |
24 |
| - processed. |
| 19 | + * SemanticAnalyzerPass1 is defined in mypy.semanal_pass1. |
25 | 20 |
|
26 | 21 | * SemanticAnalyzerPass2 is the second pass. It does the bulk of the work.
|
27 | 22 | It assumes that dependent modules have been semantically analyzed,
|
@@ -3800,275 +3795,6 @@ def accept(self, node: Node) -> None:
|
3800 | 3795 | report_internal_error(err, self.errors.file, node.line, self.errors, self.options)
|
3801 | 3796 |
|
3802 | 3797 |
|
3803 |
| -class SemanticAnalyzerPass1(NodeVisitor[None]): |
3804 |
| - """First phase of semantic analysis. |
3805 |
| -
|
3806 |
| - See docstring of 'analyze()' below for a description of what this does. |
3807 |
| - """ |
3808 |
| - |
3809 |
| - def __init__(self, sem: SemanticAnalyzerPass2) -> None: |
3810 |
| - self.sem = sem |
3811 |
| - |
3812 |
| - def visit_file(self, file: MypyFile, fnam: str, mod_id: str, options: Options) -> None: |
3813 |
| - """Perform the first analysis pass. |
3814 |
| -
|
3815 |
| - Populate module global table. Resolve the full names of |
3816 |
| - definitions not nested within functions and construct type |
3817 |
| - info structures, but do not resolve inter-definition |
3818 |
| - references such as base classes. |
3819 |
| -
|
3820 |
| - Also add implicit definitions such as __name__. |
3821 |
| -
|
3822 |
| - In this phase we don't resolve imports. For 'from ... import', |
3823 |
| - we generate dummy symbol table nodes for the imported names, |
3824 |
| - and these will get resolved in later phases of semantic |
3825 |
| - analysis. |
3826 |
| - """ |
3827 |
| - sem = self.sem |
3828 |
| - self.sem.options = options # Needed because we sometimes call into it |
3829 |
| - self.pyversion = options.python_version |
3830 |
| - self.platform = options.platform |
3831 |
| - sem.cur_mod_id = mod_id |
3832 |
| - sem.errors.set_file(fnam, mod_id) |
3833 |
| - sem.globals = SymbolTable() |
3834 |
| - sem.global_decls = [set()] |
3835 |
| - sem.nonlocal_decls = [set()] |
3836 |
| - sem.block_depth = [0] |
3837 |
| - |
3838 |
| - defs = file.defs |
3839 |
| - |
3840 |
| - with experiments.strict_optional_set(options.strict_optional): |
3841 |
| - # Add implicit definitions of module '__name__' etc. |
3842 |
| - for name, t in implicit_module_attrs.items(): |
3843 |
| - # unicode docstrings should be accepted in Python 2 |
3844 |
| - if name == '__doc__': |
3845 |
| - if self.pyversion >= (3, 0): |
3846 |
| - typ = UnboundType('__builtins__.str') # type: Type |
3847 |
| - else: |
3848 |
| - typ = UnionType([UnboundType('__builtins__.str'), |
3849 |
| - UnboundType('__builtins__.unicode')]) |
3850 |
| - else: |
3851 |
| - assert t is not None, 'type should be specified for {}'.format(name) |
3852 |
| - typ = UnboundType(t) |
3853 |
| - v = Var(name, typ) |
3854 |
| - v._fullname = self.sem.qualified_name(name) |
3855 |
| - self.sem.globals[name] = SymbolTableNode(GDEF, v) |
3856 |
| - |
3857 |
| - for d in defs: |
3858 |
| - d.accept(self) |
3859 |
| - |
3860 |
| - # Add implicit definition of literals/keywords to builtins, as we |
3861 |
| - # cannot define a variable with them explicitly. |
3862 |
| - if mod_id == 'builtins': |
3863 |
| - literal_types = [ |
3864 |
| - ('None', NoneTyp()), |
3865 |
| - # reveal_type is a mypy-only function that gives an error with |
3866 |
| - # the type of its arg. |
3867 |
| - ('reveal_type', AnyType(TypeOfAny.special_form)), |
3868 |
| - ] # type: List[Tuple[str, Type]] |
3869 |
| - |
3870 |
| - # TODO(ddfisher): This guard is only needed because mypy defines |
3871 |
| - # fake builtins for its tests which often don't define bool. If |
3872 |
| - # mypy is fast enough that we no longer need those, this |
3873 |
| - # conditional check should be removed. |
3874 |
| - if 'bool' in self.sem.globals: |
3875 |
| - bool_type = self.sem.named_type('bool') |
3876 |
| - literal_types.extend([ |
3877 |
| - ('True', bool_type), |
3878 |
| - ('False', bool_type), |
3879 |
| - ('__debug__', bool_type), |
3880 |
| - ]) |
3881 |
| - else: |
3882 |
| - # We are running tests without 'bool' in builtins. |
3883 |
| - # TODO: Find a permanent solution to this problem. |
3884 |
| - # Maybe add 'bool' to all fixtures? |
3885 |
| - literal_types.append(('True', AnyType(TypeOfAny.special_form))) |
3886 |
| - |
3887 |
| - for name, typ in literal_types: |
3888 |
| - v = Var(name, typ) |
3889 |
| - v._fullname = self.sem.qualified_name(name) |
3890 |
| - self.sem.globals[name] = SymbolTableNode(GDEF, v) |
3891 |
| - |
3892 |
| - del self.sem.options |
3893 |
| - |
3894 |
| - def visit_block(self, b: Block) -> None: |
3895 |
| - if b.is_unreachable: |
3896 |
| - return |
3897 |
| - self.sem.block_depth[-1] += 1 |
3898 |
| - for node in b.body: |
3899 |
| - node.accept(self) |
3900 |
| - self.sem.block_depth[-1] -= 1 |
3901 |
| - |
3902 |
| - def visit_assignment_stmt(self, s: AssignmentStmt) -> None: |
3903 |
| - if self.sem.is_module_scope(): |
3904 |
| - for lval in s.lvalues: |
3905 |
| - self.analyze_lvalue(lval, explicit_type=s.type is not None) |
3906 |
| - |
3907 |
| - def visit_func_def(self, func: FuncDef) -> None: |
3908 |
| - sem = self.sem |
3909 |
| - func.is_conditional = sem.block_depth[-1] > 0 |
3910 |
| - func._fullname = sem.qualified_name(func.name()) |
3911 |
| - at_module = sem.is_module_scope() |
3912 |
| - if at_module and func.name() in sem.globals: |
3913 |
| - # Already defined in this module. |
3914 |
| - original_sym = sem.globals[func.name()] |
3915 |
| - if original_sym.kind == UNBOUND_IMPORTED: |
3916 |
| - # Ah this is an imported name. We can't resolve them now, so we'll postpone |
3917 |
| - # this until the main phase of semantic analysis. |
3918 |
| - return |
3919 |
| - if not sem.set_original_def(original_sym.node, func): |
3920 |
| - # Report error. |
3921 |
| - sem.check_no_global(func.name(), func) |
3922 |
| - else: |
3923 |
| - if at_module: |
3924 |
| - sem.globals[func.name()] = SymbolTableNode(GDEF, func) |
3925 |
| - # Also analyze the function body (in case there are conditional imports). |
3926 |
| - sem.function_stack.append(func) |
3927 |
| - sem.errors.push_function(func.name()) |
3928 |
| - sem.enter() |
3929 |
| - func.body.accept(self) |
3930 |
| - sem.leave() |
3931 |
| - sem.errors.pop_function() |
3932 |
| - sem.function_stack.pop() |
3933 |
| - |
3934 |
| - def visit_overloaded_func_def(self, func: OverloadedFuncDef) -> None: |
3935 |
| - kind = self.kind_by_scope() |
3936 |
| - if kind == GDEF: |
3937 |
| - self.sem.check_no_global(func.name(), func, True) |
3938 |
| - func._fullname = self.sem.qualified_name(func.name()) |
3939 |
| - if kind == GDEF: |
3940 |
| - self.sem.globals[func.name()] = SymbolTableNode(kind, func) |
3941 |
| - if func.impl: |
3942 |
| - impl = func.impl |
3943 |
| - # Also analyze the function body (in case there are conditional imports). |
3944 |
| - sem = self.sem |
3945 |
| - |
3946 |
| - if isinstance(impl, FuncDef): |
3947 |
| - sem.function_stack.append(impl) |
3948 |
| - sem.errors.push_function(func.name()) |
3949 |
| - sem.enter() |
3950 |
| - impl.body.accept(self) |
3951 |
| - elif isinstance(impl, Decorator): |
3952 |
| - sem.function_stack.append(impl.func) |
3953 |
| - sem.errors.push_function(func.name()) |
3954 |
| - sem.enter() |
3955 |
| - impl.func.body.accept(self) |
3956 |
| - else: |
3957 |
| - assert False, "Implementation of an overload needs to be FuncDef or Decorator" |
3958 |
| - sem.leave() |
3959 |
| - sem.errors.pop_function() |
3960 |
| - sem.function_stack.pop() |
3961 |
| - |
3962 |
| - def visit_class_def(self, cdef: ClassDef) -> None: |
3963 |
| - kind = self.kind_by_scope() |
3964 |
| - if kind == LDEF: |
3965 |
| - return |
3966 |
| - elif kind == GDEF: |
3967 |
| - self.sem.check_no_global(cdef.name, cdef) |
3968 |
| - cdef.fullname = self.sem.qualified_name(cdef.name) |
3969 |
| - info = TypeInfo(SymbolTable(), cdef, self.sem.cur_mod_id) |
3970 |
| - info.set_line(cdef.line, cdef.column) |
3971 |
| - cdef.info = info |
3972 |
| - if kind == GDEF: |
3973 |
| - self.sem.globals[cdef.name] = SymbolTableNode(kind, info) |
3974 |
| - self.process_nested_classes(cdef) |
3975 |
| - |
3976 |
| - def process_nested_classes(self, outer_def: ClassDef) -> None: |
3977 |
| - self.sem.enter_class(outer_def.info) |
3978 |
| - for node in outer_def.defs.body: |
3979 |
| - if isinstance(node, ClassDef): |
3980 |
| - node.info = TypeInfo(SymbolTable(), node, self.sem.cur_mod_id) |
3981 |
| - if outer_def.fullname: |
3982 |
| - node.info._fullname = outer_def.fullname + '.' + node.info.name() |
3983 |
| - else: |
3984 |
| - node.info._fullname = node.info.name() |
3985 |
| - node.fullname = node.info._fullname |
3986 |
| - symbol = SymbolTableNode(MDEF, node.info) |
3987 |
| - outer_def.info.names[node.name] = symbol |
3988 |
| - self.process_nested_classes(node) |
3989 |
| - elif isinstance(node, (ImportFrom, Import, ImportAll, IfStmt)): |
3990 |
| - node.accept(self) |
3991 |
| - self.sem.leave_class() |
3992 |
| - |
3993 |
| - def visit_import_from(self, node: ImportFrom) -> None: |
3994 |
| - # We can't bind module names during the first pass, as the target module might be |
3995 |
| - # unprocessed. However, we add dummy unbound imported names to the symbol table so |
3996 |
| - # that we at least know that the name refers to a module. |
3997 |
| - at_module = self.sem.is_module_scope() |
3998 |
| - node.is_top_level = at_module |
3999 |
| - if not at_module: |
4000 |
| - return |
4001 |
| - for name, as_name in node.names: |
4002 |
| - imported_name = as_name or name |
4003 |
| - if imported_name not in self.sem.globals: |
4004 |
| - self.sem.add_symbol(imported_name, SymbolTableNode(UNBOUND_IMPORTED, None), node) |
4005 |
| - |
4006 |
| - def visit_import(self, node: Import) -> None: |
4007 |
| - node.is_top_level = self.sem.is_module_scope() |
4008 |
| - # This is similar to visit_import_from -- see the comment there. |
4009 |
| - if not self.sem.is_module_scope(): |
4010 |
| - return |
4011 |
| - for id, as_id in node.ids: |
4012 |
| - imported_id = as_id or id |
4013 |
| - if imported_id not in self.sem.globals: |
4014 |
| - self.sem.add_symbol(imported_id, SymbolTableNode(UNBOUND_IMPORTED, None), node) |
4015 |
| - else: |
4016 |
| - # If the previous symbol is a variable, this should take precedence. |
4017 |
| - self.sem.globals[imported_id] = SymbolTableNode(UNBOUND_IMPORTED, None) |
4018 |
| - |
4019 |
| - def visit_import_all(self, node: ImportAll) -> None: |
4020 |
| - node.is_top_level = self.sem.is_module_scope() |
4021 |
| - |
4022 |
| - def visit_while_stmt(self, s: WhileStmt) -> None: |
4023 |
| - if self.sem.is_module_scope(): |
4024 |
| - s.body.accept(self) |
4025 |
| - if s.else_body: |
4026 |
| - s.else_body.accept(self) |
4027 |
| - |
4028 |
| - def visit_for_stmt(self, s: ForStmt) -> None: |
4029 |
| - if self.sem.is_module_scope(): |
4030 |
| - self.analyze_lvalue(s.index, explicit_type=s.index_type is not None) |
4031 |
| - s.body.accept(self) |
4032 |
| - if s.else_body: |
4033 |
| - s.else_body.accept(self) |
4034 |
| - |
4035 |
| - def visit_with_stmt(self, s: WithStmt) -> None: |
4036 |
| - if self.sem.is_module_scope(): |
4037 |
| - for n in s.target: |
4038 |
| - if n: |
4039 |
| - self.analyze_lvalue(n, explicit_type=s.target_type is not None) |
4040 |
| - s.body.accept(self) |
4041 |
| - |
4042 |
| - def visit_decorator(self, d: Decorator) -> None: |
4043 |
| - d.var._fullname = self.sem.qualified_name(d.var.name()) |
4044 |
| - self.sem.add_symbol(d.var.name(), SymbolTableNode(self.kind_by_scope(), d.var), d) |
4045 |
| - |
4046 |
| - def visit_if_stmt(self, s: IfStmt) -> None: |
4047 |
| - infer_reachability_of_if_statement(s, pyversion=self.pyversion, platform=self.platform) |
4048 |
| - for node in s.body: |
4049 |
| - node.accept(self) |
4050 |
| - if s.else_body: |
4051 |
| - s.else_body.accept(self) |
4052 |
| - |
4053 |
| - def visit_try_stmt(self, s: TryStmt) -> None: |
4054 |
| - if self.sem.is_module_scope(): |
4055 |
| - self.sem.analyze_try_stmt(s, self, add_global=self.sem.is_module_scope()) |
4056 |
| - |
4057 |
| - def analyze_lvalue(self, lvalue: Lvalue, explicit_type: bool = False) -> None: |
4058 |
| - self.sem.analyze_lvalue(lvalue, add_global=self.sem.is_module_scope(), |
4059 |
| - explicit_type=explicit_type) |
4060 |
| - |
4061 |
| - def kind_by_scope(self) -> int: |
4062 |
| - if self.sem.is_module_scope(): |
4063 |
| - return GDEF |
4064 |
| - elif self.sem.is_class_scope(): |
4065 |
| - return MDEF |
4066 |
| - elif self.sem.is_func_scope(): |
4067 |
| - return LDEF |
4068 |
| - else: |
4069 |
| - assert False, "Couldn't determine scope" |
4070 |
| - |
4071 |
| - |
4072 | 3798 | def replace_implicit_first_type(sig: FunctionLike, new: Type) -> FunctionLike:
|
4073 | 3799 | if isinstance(sig, CallableType):
|
4074 | 3800 | return sig.copy_modified(arg_types=[new] + sig.arg_types[1:])
|
|
0 commit comments