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
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)
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)
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)
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)
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)
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
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:], )
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), )
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
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)
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)
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)
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 )
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)
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)
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)