Exemple #1
0
def fix_instance(t: Instance, fail: Callable[[str, Context], None]) -> None:
    """Fix a malformed instance by replacing all type arguments with Any.

    Also emit a suitable error if this is not due to implicit Any's.
    """
    if len(t.args) == 0:
        any_type = AnyType(TypeOfAny.from_omitted_generics,
                           line=t.line, column=t.column)
        t.args = [any_type] * len(t.type.type_vars)
        return
    # Invalid number of type parameters.
    n = len(t.type.type_vars)
    s = '{} type arguments'.format(n)
    if n == 0:
        s = 'no type arguments'
    elif n == 1:
        s = '1 type argument'
    act = str(len(t.args))
    if act == '0':
        act = 'none'
    fail('"{}" expects {}, but {} given'.format(
        t.type.name(), s, act), t)
    # Construct the correct number of type arguments, as
    # otherwise the type checker may crash as it expects
    # things to be right.
    t.args = [AnyType(TypeOfAny.from_error) for _ in t.type.type_vars]
    t.invalid = True
Exemple #2
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     if info.replaced or info.tuple_type:
         self.indicator['synthetic'] = True
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             from_builtins = t.type.fullname(
             ) in nongen_builtins and not t.from_generic_builtin
             if (self.options.disallow_any_generics
                     and not self.is_typeshed_stub and from_builtins):
                 alternative = nongen_builtins[t.type.fullname()]
                 self.fail(
                     messages.IMPLICIT_GENERIC_ANY_BUILTIN.format(
                         alternative), t)
             # Insert implicit 'Any' type arguments.
             if from_builtins:
                 # this 'Any' was already reported elsewhere
                 any_type = AnyType(TypeOfAny.special_form,
                                    line=t.line,
                                    column=t.column)
             else:
                 any_type = AnyType(TypeOfAny.from_omitted_generics,
                                    line=t.line,
                                    column=t.column)
             t.args = [any_type] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail(
             '"{}" expects {}, but {} given'.format(info.name(), s, act), t)
         # Construct the correct number of type arguments, as
         # otherwise the type checker may crash as it expects
         # things to be right.
         t.args = [AnyType(TypeOfAny.from_error) for _ in info.type_vars]
         t.invalid = True
     elif info.defn.type_vars:
         # Check type argument values. This is postponed to the end of semantic analysis
         # since we need full MROs and resolved forward references.
         for tvar in info.defn.type_vars:
             if (tvar.values or not isinstance(tvar.upper_bound, Instance)
                     or
                     tvar.upper_bound.type.fullname() != 'builtins.object'):
                 # Some restrictions on type variable. These can only be checked later
                 # after we have final MROs and forward references have been resolved.
                 self.indicator['typevar'] = True
     for arg in t.args:
         arg.accept(self)
     if info.is_newtype:
         for base in info.bases:
             base.accept(self)
Exemple #3
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             from_builtins = t.type.fullname() in nongen_builtins and not t.from_generic_builtin
             if ('generics' in self.options.disallow_any and
                     not self.is_typeshed_stub and
                     from_builtins):
                 alternative = nongen_builtins[t.type.fullname()]
                 self.fail(messages.IMPLICIT_GENERIC_ANY_BUILTIN.format(alternative), t)
             # Insert implicit 'Any' type arguments.
             any_type = AnyType(from_omitted_generics=not from_builtins, line=t.line,
                                column=t.line)
             t.args = [any_type] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail('"{}" expects {}, but {} given'.format(
             info.name(), s, act), t)
         # Construct the correct number of type arguments, as
         # otherwise the type checker may crash as it expects
         # things to be right.
         t.args = [AnyType() for _ in info.type_vars]
         t.invalid = True
     elif info.defn.type_vars:
         # Check type argument values.
         for (i, arg), tvar in zip(enumerate(t.args), info.defn.type_vars):
             if tvar.values:
                 if isinstance(arg, TypeVarType):
                     arg_values = arg.values
                     if not arg_values:
                         self.fail('Type variable "{}" not valid as type '
                                   'argument value for "{}"'.format(
                                       arg.name, info.name()), t)
                         continue
                 else:
                     arg_values = [arg]
                 self.check_type_var_values(info, arg_values,
                                            tvar.values, i + 1, t)
             if not is_subtype(arg, tvar.upper_bound):
                 self.fail('Type argument "{}" of "{}" must be '
                           'a subtype of "{}"'.format(
                               arg, info.name(), tvar.upper_bound), t)
     for arg in t.args:
         arg.accept(self)
     if info.is_newtype:
         for base in info.bases:
             base.accept(self)
Exemple #4
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     if info.replaced or info.tuple_type:
         self.indicator['synthetic'] = True
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             from_builtins = t.type.fullname() in nongen_builtins and not t.from_generic_builtin
             if (self.options.disallow_any_generics and
                     not self.is_typeshed_stub and
                     from_builtins):
                 alternative = nongen_builtins[t.type.fullname()]
                 self.fail(messages.IMPLICIT_GENERIC_ANY_BUILTIN.format(alternative), t)
             # Insert implicit 'Any' type arguments.
             if from_builtins:
                 # this 'Any' was already reported elsewhere
                 any_type = AnyType(TypeOfAny.special_form,
                                    line=t.line, column=t.column)
             else:
                 any_type = AnyType(TypeOfAny.from_omitted_generics,
                                    line=t.line, column=t.column)
             t.args = [any_type] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail('"{}" expects {}, but {} given'.format(
             info.name(), s, act), t)
         # Construct the correct number of type arguments, as
         # otherwise the type checker may crash as it expects
         # things to be right.
         t.args = [AnyType(TypeOfAny.from_error) for _ in info.type_vars]
         t.invalid = True
     elif info.defn.type_vars:
         # Check type argument values. This is postponed to the end of semantic analysis
         # since we need full MROs and resolved forward references.
         for tvar in info.defn.type_vars:
             if (tvar.values
                     or not isinstance(tvar.upper_bound, Instance)
                     or tvar.upper_bound.type.fullname() != 'builtins.object'):
                 # Some restrictions on type variable. These can only be checked later
                 # after we have final MROs and forward references have been resolved.
                 self.indicator['typevar'] = True
     for arg in t.args:
         arg.accept(self)
     if info.is_newtype:
         for base in info.bases:
             base.accept(self)
Exemple #5
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             # Insert implicit 'Any' type arguments.
             t.args = [AnyType()] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail(
             '"{}" expects {}, but {} given'.format(info.name(), s, act), t)
         # Construct the correct number of type arguments, as
         # otherwise the type checker may crash as it expects
         # things to be right.
         t.args = [AnyType() for _ in info.type_vars]
         t.invalid = True
     elif info.defn.type_vars:
         # Check type argument values.
         for (i, arg), tvar in zip(enumerate(t.args), info.defn.type_vars):
             if tvar.values:
                 if isinstance(arg, TypeVarType):
                     arg_values = arg.values
                     if not arg_values:
                         self.fail(
                             'Type variable "{}" not valid as type '
                             'argument value for "{}"'.format(
                                 arg.name, info.name()), t)
                         continue
                 else:
                     arg_values = [arg]
                 self.check_type_var_values(info, arg_values, tvar.values,
                                            i + 1, t)
             if not is_subtype(arg, tvar.upper_bound):
                 self.fail(
                     'Type argument "{}" of "{}" must be '
                     'a subtype of "{}"'.format(arg, info.name(),
                                                tvar.upper_bound), t)
     for arg in t.args:
         arg.accept(self)
     if info.is_newtype:
         for base in info.bases:
             base.accept(self)
Exemple #6
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             # Insert implicit 'Any' type arguments.
             t.args = [AnyType()] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = "{} type arguments".format(n)
         if n == 0:
             s = "no type arguments"
         elif n == 1:
             s = "1 type argument"
         act = str(len(t.args))
         if act == "0":
             act = "none"
         self.fail('"{}" expects {}, but {} given'.format(info.name(), s, act), t)
         # Construct the correct number of type arguments, as
         # otherwise the type checker may crash as it expects
         # things to be right.
         t.args = [AnyType() for _ in info.type_vars]
     elif info.defn.type_vars:
         # Check type argument values.
         for arg, TypeVar in zip(t.args, info.defn.type_vars):
             if TypeVar.values:
                 if isinstance(arg, TypeVarType):
                     arg_values = arg.values
                     if not arg_values:
                         self.fail(
                             'Type variable "{}" not valid as type '
                             'argument value for "{}"'.format(arg.name, info.name()),
                             t,
                         )
                         continue
                 else:
                     arg_values = [arg]
                 self.check_type_var_values(info, arg_values, TypeVar.values, t)
             if not satisfies_upper_bound(arg, TypeVar.upper_bound):
                 self.fail(
                     'Type argument "{}" of "{}" must be '
                     'a subtype of "{}"'.format(arg, info.name(), TypeVar.upper_bound),
                     t,
                 )
     for arg in t.args:
         arg.accept(self)
Exemple #7
0
 def _process_typeclass_def_return_type(
     self,
     typeclass_intermediate_def: Instance,
     defn: FunctionLike,
     ctx: FunctionContext,
 ) -> MypyType:
     type_info = defn.type_object()
     instance = Instance(type_info, [])
     typeclass_intermediate_def.args = (instance, )
     return typeclass_intermediate_def
Exemple #8
0
 def _add_new_instance_type(
     self,
     typeclass: Instance,
     new_type: MypyType,
     ctx: MethodContext,
 ) -> None:
     typeclass.args = (
         instance_args.add_unique(new_type, typeclass.args[0]),
         *typeclass.args[1:],
     )
Exemple #9
0
def mutate_typeclass_def(
    typeclass: Instance,
    definition_fullname: str,
    ctx: Union[FunctionContext, MethodContext],
) -> None:
    """Adds definition fullname to the typeclass type."""
    str_fallback = ctx.api.str_type()  # type: ignore

    typeclass.args = (
        *typeclass.args[:3],
        LiteralType(definition_fullname, str_fallback),
    )
Exemple #10
0
    def analyze_type_with_type_info(self, info: TypeInfo, args: List[Type], ctx: Context) -> Type:
        """Bind unbound type when were able to find target TypeInfo.

        This handles simple cases like 'int', 'modname.UserClass[str]', etc.
        """
        if len(args) > 0 and info.fullname() == 'builtins.tuple':
            fallback = Instance(info, [AnyType(TypeOfAny.special_form)], ctx.line)
            return TupleType(self.anal_array(args), fallback, ctx.line)
        # 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), ctx.line, ctx.column)
        # Check type argument count.
        if len(instance.args) != len(info.type_vars) and not self.defining_alias:
            fix_instance(instance, self.fail)
        if not args and self.options.disallow_any_generics and not self.defining_alias:
            # We report/patch invalid built-in instances already during second pass.
            # This is done to avoid storing additional state on instances.
            # All other (including user defined) generics will be patched/reported
            # in the third pass.
            if not self.is_typeshed_stub and info.fullname() in nongen_builtins:
                alternative = nongen_builtins[info.fullname()]
                self.fail(message_registry.IMPLICIT_GENERIC_ANY_BUILTIN.format(alternative), ctx)
                any_type = AnyType(TypeOfAny.from_error, line=ctx.line)
            else:
                any_type = AnyType(TypeOfAny.from_omitted_generics, line=ctx.line)
            instance.args = [any_type] * len(info.type_vars)

        tup = info.tuple_type
        if tup is not None:
            # The class has a Tuple[...] base class so it will be
            # represented as a tuple type.
            if args:
                self.fail('Generic tuple types not supported', ctx)
                return AnyType(TypeOfAny.from_error)
            return tup.copy_modified(items=self.anal_array(tup.items),
                                     fallback=instance)
        td = info.typeddict_type
        if td is not None:
            # The class has a TypedDict[...] base class so it will be
            # represented as a typeddict type.
            if args:
                self.fail('Generic TypedDict types not supported', ctx)
                return AnyType(TypeOfAny.from_error)
            # Create a named TypedDictType
            return td.copy_modified(item_types=self.anal_array(list(td.items.values())),
                                    fallback=instance)
        return instance
Exemple #11
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             # Implicit 'Any' type arguments.
             # TODO remove <Type> below
             t.args = [AnyType()] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail('"{}" expects {}, but {} given'.format(
             info.name(), s, act), t)
     for arg in t.args:
         arg.accept(self)
Exemple #12
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             # Insert implicit 'Any' type arguments.
             t.args = [AnyType()] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail(
             '"{}" expects {}, but {} given'.format(info.name(), s, act), t)
     elif info.defn.type_vars:
         # Check type argument values.
         for arg, TypeVar in zip(t.args, info.defn.type_vars):
             if TypeVar.values:
                 if isinstance(arg, TypeVarType):
                     arg_values = arg.values
                     if not arg_values:
                         self.fail(
                             'Type variable "{}" not valid as type '
                             'argument value for "{}"'.format(
                                 arg.name, info.name()), t)
                         continue
                 else:
                     arg_values = [arg]
                 self.check_type_var_values(info, arg_values,
                                            TypeVar.values, t)
     for arg in t.args:
         arg.accept(self)
Exemple #13
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             # Insert implicit 'Any' type arguments.
             t.args = [AnyType()] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail('"{}" expects {}, but {} given'.format(
             info.name(), s, act), t)
     elif info.defn.type_vars:
         # Check type argument values.
         for arg, TypeVar in zip(t.args, info.defn.type_vars):
             if TypeVar.values:
                 if isinstance(arg, TypeVarType):
                     arg_values = arg.values
                     if not arg_values:
                         self.fail('Type variable "{}" not valid as type '
                                   'argument value for "{}"'.format(
                                       arg.name, info.name()), t)
                         continue
                 else:
                     arg_values = [arg]
                 self.check_type_var_values(info, arg_values,
                                            TypeVar.values, t)
     for arg in t.args:
         arg.accept(self)
Exemple #14
0
def mutate_typeclass_instance_def(
    instance: Instance,
    *,
    passed_types: List[MypyType],
    typeclass: Instance,
    ctx: Union[MethodContext, FunctionContext],
) -> None:
    """
    Mutates ``TypeClassInstanceDef`` args.

    That's where we fill their values.
    Why? Because we need all types from ``some.instance()`` call.
    Including ``is_protocol`` for later checks.
    """
    tuple_type = TupleType(
        # We now store passed arg types in a single tuple:
        passed_types,
        fallback=ctx.api.named_type('builtins.tuple'),  # type: ignore
    )

    instance.args = (
        tuple_type,  # Passed runtime types, like str in `@some.instance(str)`
        typeclass,  # `_TypeClass` instance itself
    )
Exemple #15
0
    def visit_unbound_type_nonoptional(self, t: UnboundType) -> Type:
        sym = self.lookup(t.name, t, suppress_errors=self.third_pass)
        if '.' in t.name:
            # Handle indirect references to imported names.
            #
            # TODO: Do this for module-local references as well and remove ImportedName
            #    type check below.
            sym = self.api.dereference_module_cross_ref(sym)
        if sym is not None:
            if isinstance(sym.node, ImportedName):
                # Forward reference to an imported name that hasn't been processed yet.
                # To maintain backward compatibility, these get translated to Any.
                #
                # TODO: Remove this special case.
                return AnyType(TypeOfAny.implementation_artifact)
            if sym.node is None:
                # UNBOUND_IMPORTED can happen if an unknown name was imported.
                if sym.kind != UNBOUND_IMPORTED:
                    self.fail(
                        'Internal error (node is None, kind={})'.format(
                            sym.kind), t)
                return AnyType(TypeOfAny.special_form)
            fullname = sym.node.fullname()
            hook = self.plugin.get_type_analyze_hook(fullname)
            if hook:
                return hook(AnalyzeTypeContext(t, t, self))
            if (fullname in nongen_builtins and t.args
                    and not self.allow_unnormalized):
                self.fail(
                    no_subscript_builtin_alias(
                        fullname, propose_alt=not self.defining_alias), t)
            if self.tvar_scope:
                tvar_def = self.tvar_scope.get_binding(sym)
            else:
                tvar_def = None
            if sym.kind == TVAR and tvar_def is not None and self.defining_alias:
                self.fail(
                    'Can\'t use bound type variable "{}"'
                    ' to define generic alias'.format(t.name), t)
                return AnyType(TypeOfAny.from_error)
            elif sym.kind == TVAR and tvar_def is not None:
                if len(t.args) > 0:
                    self.fail(
                        'Type variable "{}" used with arguments'.format(
                            t.name), t)
                return TypeVarType(tvar_def, t.line)
            elif fullname == 'builtins.None':
                return NoneTyp()
            elif fullname == 'typing.Any' or fullname == 'builtins.Any':
                return AnyType(TypeOfAny.explicit)
            elif fullname in ('typing.Final', 'typing_extensions.Final'):
                self.fail(
                    "Final can be only used as an outermost qualifier"
                    " in a variable annotation", t)
                return AnyType(TypeOfAny.from_error)
            elif fullname == 'typing.Tuple':
                if len(t.args) == 0 and not t.empty_tuple_index:
                    # Bare 'Tuple' is same as 'tuple'
                    if self.options.disallow_any_generics and not self.is_typeshed_stub:
                        self.fail(messages.BARE_GENERIC, t)
                    return self.named_type('builtins.tuple',
                                           line=t.line,
                                           column=t.column)
                if len(t.args) == 2 and isinstance(t.args[1], EllipsisType):
                    # Tuple[T, ...] (uniform, variable-length tuple)
                    instance = self.named_type('builtins.tuple',
                                               [self.anal_type(t.args[0])])
                    instance.line = t.line
                    return instance
                return self.tuple_type(self.anal_array(t.args))
            elif fullname == 'typing.Union':
                items = self.anal_array(t.args)
                return UnionType.make_union(items)
            elif fullname == 'typing.Optional':
                if len(t.args) != 1:
                    self.fail(
                        'Optional[...] must have exactly one type argument', t)
                    return AnyType(TypeOfAny.from_error)
                item = self.anal_type(t.args[0])
                return make_optional_type(item)
            elif fullname == 'typing.Callable':
                return self.analyze_callable_type(t)
            elif fullname == 'typing.Type':
                if len(t.args) == 0:
                    any_type = AnyType(TypeOfAny.from_omitted_generics,
                                       line=t.line,
                                       column=t.column)
                    return TypeType(any_type, line=t.line, column=t.column)
                if len(t.args) != 1:
                    self.fail('Type[...] must have exactly one type argument',
                              t)
                item = self.anal_type(t.args[0])
                return TypeType.make_normalized(item, line=t.line)
            elif fullname == 'typing.ClassVar':
                if self.nesting_level > 0:
                    self.fail(
                        'Invalid type: ClassVar nested inside other type', t)
                if len(t.args) == 0:
                    return AnyType(TypeOfAny.from_omitted_generics,
                                   line=t.line,
                                   column=t.column)
                if len(t.args) != 1:
                    self.fail(
                        'ClassVar[...] must have at most one type argument', t)
                    return AnyType(TypeOfAny.from_error)
                item = self.anal_type(t.args[0])
                if isinstance(item, TypeVarType) or get_type_vars(item):
                    self.fail('Invalid type: ClassVar cannot be generic', t)
                    return AnyType(TypeOfAny.from_error)
                return item
            elif fullname in ('mypy_extensions.NoReturn', 'typing.NoReturn'):
                return UninhabitedType(is_noreturn=True)
            elif isinstance(sym.node, TypeAlias):
                self.aliases_used.add(sym.node.fullname())
                all_vars = sym.node.alias_tvars
                target = sym.node.target
                an_args = self.anal_array(t.args)
                return expand_type_alias(target, all_vars, an_args, self.fail,
                                         sym.node.no_args, t)
            elif not isinstance(sym.node, TypeInfo):
                # Something unusual. We try our best to find out what it is.
                name = sym.fullname
                if name is None:
                    name = sym.node.name()
                # Option 1:
                # Something with an Any type -- make it an alias for Any in a type
                # context. This is slightly problematic as it allows using the type 'Any'
                # as a base class -- however, this will fail soon at runtime so the problem
                # is pretty minor.
                if isinstance(sym.node, Var) and isinstance(
                        sym.node.type, AnyType):
                    return AnyType(
                        TypeOfAny.from_unimported_type,
                        missing_import_name=sym.node.type.missing_import_name)
                # Option 2:
                # Unbound type variable. Currently these may be still valid,
                # for example when defining a generic type alias.
                unbound_tvar = ((sym.kind == TVAR) and
                                (not self.tvar_scope
                                 or self.tvar_scope.get_binding(sym) is None))
                if self.allow_unbound_tvars and unbound_tvar and not self.third_pass:
                    return t
                # Option 3:
                # If it is not something clearly bad (like a known function, variable,
                # type variable, or module), and it is still not too late, we try deferring
                # this type using a forward reference wrapper. It will be revisited in
                # the third pass.
                allow_forward_ref = not (
                    self.third_pass or isinstance(sym.node,
                                                  (FuncDef, Decorator))
                    or isinstance(sym.node, Var) and sym.node.is_ready
                    or sym.kind in (MODULE_REF, TVAR))
                if allow_forward_ref:
                    # We currently can't support subscripted forward refs in functions;
                    # see https://github.com/python/mypy/pull/3952#discussion_r139950690
                    # for discussion.
                    if t.args and not self.global_scope:
                        if not self.in_dynamic_func:
                            self.fail(
                                'Unsupported forward reference to "{}"'.format(
                                    t.name), t)
                        return AnyType(TypeOfAny.from_error)
                    return ForwardRef(t)
                # None of the above options worked, we give up.
                self.fail('Invalid type "{}"'.format(name), t)
                if self.third_pass and sym.kind == TVAR:
                    self.note_func(
                        "Forward references to type variables are prohibited",
                        t)
                    return AnyType(TypeOfAny.from_error)
                # TODO: Would it be better to always return Any instead of UnboundType
                # in case of an error? On one hand, UnboundType has a name so error messages
                # are more detailed, on the other hand, some of them may be bogus.
                return t
            info = sym.node  # type: TypeInfo
            if len(t.args) > 0 and info.fullname() == 'builtins.tuple':
                fallback = Instance(info, [AnyType(TypeOfAny.special_form)],
                                    t.line)
                return TupleType(self.anal_array(t.args), fallback, t.line)
            else:
                # Analyze arguments and 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(t.args), t.line,
                                    t.column)
                if not t.args and self.options.disallow_any_generics and not self.defining_alias:
                    # We report/patch invalid built-in instances already during second pass.
                    # This is done to avoid storing additional state on instances.
                    # All other (including user defined) generics will be patched/reported
                    # in the third pass.
                    if not self.is_typeshed_stub and info.fullname(
                    ) in nongen_builtins:
                        alternative = nongen_builtins[info.fullname()]
                        self.fail(
                            messages.IMPLICIT_GENERIC_ANY_BUILTIN.format(
                                alternative), t)
                        any_type = AnyType(TypeOfAny.from_error, line=t.line)
                    else:
                        any_type = AnyType(TypeOfAny.from_omitted_generics,
                                           line=t.line)
                    instance.args = [any_type] * len(info.type_vars)

                tup = info.tuple_type
                if tup is not None:
                    # The class has a Tuple[...] base class so it will be
                    # represented as a tuple type.
                    if t.args:
                        self.fail('Generic tuple types not supported', t)
                        return AnyType(TypeOfAny.from_error)
                    return tup.copy_modified(items=self.anal_array(tup.items),
                                             fallback=instance)
                td = info.typeddict_type
                if td is not None:
                    # The class has a TypedDict[...] base class so it will be
                    # represented as a typeddict type.
                    if t.args:
                        self.fail('Generic TypedDict types not supported', t)
                        return AnyType(TypeOfAny.from_error)
                    # Create a named TypedDictType
                    return td.copy_modified(item_types=self.anal_array(
                        list(td.items.values())),
                                            fallback=instance)
                return instance
        else:
            if self.third_pass:
                self.fail('Invalid type "{}"'.format(t.name), t)
                return AnyType(TypeOfAny.from_error)
            return AnyType(TypeOfAny.special_form)
Exemple #16
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     if info.replaced or info.tuple_type:
         self.indicator['synthetic'] = True
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             from_builtins = t.type.fullname(
             ) in nongen_builtins and not t.from_generic_builtin
             if (self.options.disallow_any_generics
                     and not self.is_typeshed_stub and from_builtins):
                 alternative = nongen_builtins[t.type.fullname()]
                 self.fail(
                     messages.IMPLICIT_GENERIC_ANY_BUILTIN.format(
                         alternative), t)
             # Insert implicit 'Any' type arguments.
             if from_builtins:
                 # this 'Any' was already reported elsewhere
                 any_type = AnyType(TypeOfAny.special_form,
                                    line=t.line,
                                    column=t.column)
             else:
                 any_type = AnyType(TypeOfAny.from_omitted_generics,
                                    line=t.line,
                                    column=t.column)
             t.args = [any_type] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail(
             '"{}" expects {}, but {} given'.format(info.name(), s, act), t)
         # Construct the correct number of type arguments, as
         # otherwise the type checker may crash as it expects
         # things to be right.
         t.args = [AnyType(TypeOfAny.from_error) for _ in info.type_vars]
         t.invalid = True
     elif info.defn.type_vars:
         # Check type argument values.
         # TODO: Calling is_subtype and is_same_types in semantic analysis is a bad idea
         for (i, arg), tvar in zip(enumerate(t.args), info.defn.type_vars):
             if tvar.values:
                 if isinstance(arg, TypeVarType):
                     arg_values = arg.values
                     if not arg_values:
                         self.fail(
                             'Type variable "{}" not valid as type '
                             'argument value for "{}"'.format(
                                 arg.name, info.name()), t)
                         continue
                 else:
                     arg_values = [arg]
                 self.check_type_var_values(info, arg_values, tvar.name,
                                            tvar.values, i + 1, t)
             # TODO: These hacks will be not necessary when this will be moved to later stage.
             arg = self.resolve_type(arg)
             bound = self.resolve_type(tvar.upper_bound)
             if not is_subtype(arg, bound):
                 self.fail(
                     'Type argument "{}" of "{}" must be '
                     'a subtype of "{}"'.format(arg, info.name(), bound), t)
     for arg in t.args:
         arg.accept(self)
     if info.is_newtype:
         for base in info.bases:
             base.accept(self)
Exemple #17
0
 def visit_instance(self, t: Instance) -> None:
     info = t.type
     if info.replaced or info.tuple_type:
         self.indicator['synthetic'] = True
     # Check type argument count.
     if len(t.args) != len(info.type_vars):
         if len(t.args) == 0:
             from_builtins = t.type.fullname() in nongen_builtins and not t.from_generic_builtin
             if (self.options.disallow_any_generics and
                     not self.is_typeshed_stub and
                     from_builtins):
                 alternative = nongen_builtins[t.type.fullname()]
                 self.fail(messages.IMPLICIT_GENERIC_ANY_BUILTIN.format(alternative), t)
             # Insert implicit 'Any' type arguments.
             if from_builtins:
                 # this 'Any' was already reported elsewhere
                 any_type = AnyType(TypeOfAny.special_form,
                                    line=t.line, column=t.column)
             else:
                 any_type = AnyType(TypeOfAny.from_omitted_generics,
                                    line=t.line, column=t.column)
             t.args = [any_type] * len(info.type_vars)
             return
         # Invalid number of type parameters.
         n = len(info.type_vars)
         s = '{} type arguments'.format(n)
         if n == 0:
             s = 'no type arguments'
         elif n == 1:
             s = '1 type argument'
         act = str(len(t.args))
         if act == '0':
             act = 'none'
         self.fail('"{}" expects {}, but {} given'.format(
             info.name(), s, act), t)
         # Construct the correct number of type arguments, as
         # otherwise the type checker may crash as it expects
         # things to be right.
         t.args = [AnyType(TypeOfAny.from_error) for _ in info.type_vars]
         t.invalid = True
     elif info.defn.type_vars:
         # Check type argument values.
         # TODO: Calling is_subtype and is_same_types in semantic analysis is a bad idea
         for (i, arg), tvar in zip(enumerate(t.args), info.defn.type_vars):
             if tvar.values:
                 if isinstance(arg, TypeVarType):
                     arg_values = arg.values
                     if not arg_values:
                         self.fail('Type variable "{}" not valid as type '
                                   'argument value for "{}"'.format(
                                       arg.name, info.name()), t)
                         continue
                 else:
                     arg_values = [arg]
                 self.check_type_var_values(info, arg_values, tvar.name, tvar.values, i + 1, t)
             # TODO: These hacks will be not necessary when this will be moved to later stage.
             arg = self.resolve_type(arg)
             bound = self.resolve_type(tvar.upper_bound)
             if not is_subtype(arg, bound):
                 self.fail('Type argument "{}" of "{}" must be '
                           'a subtype of "{}"'.format(
                               arg, info.name(), bound), t)
     for arg in t.args:
         arg.accept(self)
     if info.is_newtype:
         for base in info.bases:
             base.accept(self)