Skip to content

feat: add helpful info to internal AssertionError excs #19404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7273,7 +7273,7 @@ def named_type(self, name: str) -> Instance:
if isinstance(node, TypeAlias):
assert isinstance(node.target, Instance) # type: ignore[misc]
node = node.target.type
assert isinstance(node, TypeInfo)
assert isinstance(node, TypeInfo), node
any_type = AnyType(TypeOfAny.from_omitted_generics)
return Instance(node, [any_type] * len(node.defn.type_vars))

Expand All @@ -7292,7 +7292,7 @@ def lookup_typeinfo(self, fullname: str) -> TypeInfo:
# Assume that the name refers to a class.
sym = self.lookup_qualified(fullname)
node = sym.node
assert isinstance(node, TypeInfo)
assert isinstance(node, TypeInfo), node
return node

def type_type(self) -> Instance:
Expand Down
4 changes: 2 additions & 2 deletions mypy/checkpattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,9 +796,9 @@ def get_var(expr: Expression) -> Var:
Warning: this in only true for expressions captured by a match statement.
Don't call it from anywhere else
"""
assert isinstance(expr, NameExpr)
assert isinstance(expr, NameExpr), expr
node = expr.node
assert isinstance(node, Var)
assert isinstance(node, Var), node
return node


Expand Down
2 changes: 1 addition & 1 deletion mypy/plugins/attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ def _analyze_class(
if isinstance(node, PlaceholderNode):
# This node is not ready yet.
continue
assert isinstance(node, Var)
assert isinstance(node, Var), node
node.is_initialized_in_class = False

# Traverse the MRO and collect attributes from the parents.
Expand Down
2 changes: 1 addition & 1 deletion mypy/plugins/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ def collect_attributes(self) -> list[DataclassAttribute] | None:
# We will issue an error later.
continue

assert isinstance(node, Var)
assert isinstance(node, Var), node

# x: ClassVar[int] is ignored by dataclasses.
if node.is_classvar:
Expand Down
2 changes: 1 addition & 1 deletion mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -6630,7 +6630,7 @@ def named_type(self, fullname: str, args: list[Type] | None = None) -> Instance:
sym = self.lookup_fully_qualified(fullname)
assert sym, "Internal error: attempted to construct unknown type"
node = sym.node
assert isinstance(node, TypeInfo)
assert isinstance(node, TypeInfo), node
if args:
# TODO: assert len(args) == len(node.defn.type_vars)
return Instance(node, args)
Expand Down
2 changes: 1 addition & 1 deletion mypy/semanal_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def process_functions(graph: Graph, scc: list[str], patches: Patches) -> None:

for module, target, node, active_type in order_by_subclassing(all_targets):
analyzer = graph[module].manager.semantic_analyzer
assert isinstance(node, (FuncDef, OverloadedFuncDef, Decorator))
assert isinstance(node, (FuncDef, OverloadedFuncDef, Decorator)), node
process_top_level_function(
analyzer, graph[module], module, target, node, active_type, patches
)
Expand Down
4 changes: 2 additions & 2 deletions mypyc/analysis/attrdefined.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,15 +285,15 @@ def mark_attr_initialization_ops(
def attributes_initialized_by_init_call(op: Call) -> set[str]:
"""Calculate attributes that are always initialized by a super().__init__ call."""
self_type = op.fn.sig.args[0].type
assert isinstance(self_type, RInstance)
assert isinstance(self_type, RInstance), self_type
cl = self_type.class_ir
return {a for base in cl.mro for a in base.attributes if base.is_always_defined(a)}


def attributes_maybe_initialized_by_init_call(op: Call) -> set[str]:
"""Calculate attributes that may be initialized by a super().__init__ call."""
self_type = op.fn.sig.args[0].type
assert isinstance(self_type, RInstance)
assert isinstance(self_type, RInstance), self_type
cl = self_type.class_ir
return attributes_initialized_by_init_call(op) | cl._sometimes_initialized_attrs

Expand Down
2 changes: 1 addition & 1 deletion mypyc/analysis/selfleaks.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def visit_call(self, op: Call) -> GenAndKill:
fn = op.fn
if fn.class_name and fn.name == "__init__":
self_type = op.fn.sig.args[0].type
assert isinstance(self_type, RInstance)
assert isinstance(self_type, RInstance), self_type
cl = self_type.class_ir
if not cl.init_self_leak:
return CLEAN
Expand Down
4 changes: 2 additions & 2 deletions mypyc/codegen/emit.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ def emit_cast_error_handler(
self.emit_traceback(error.source_path, error.module_name, error.traceback_entry)
self.emit_line("goto %s;" % error.label)
else:
assert isinstance(error, ReturnHandler)
assert isinstance(error, ReturnHandler), error
self.emit_line("return %s;" % error.value)

def emit_union_cast(
Expand Down Expand Up @@ -873,7 +873,7 @@ def emit_unbox(
elif isinstance(error, GotoHandler):
failure = "goto %s;" % error.label
else:
assert isinstance(error, ReturnHandler)
assert isinstance(error, ReturnHandler), error
failure = "return %s;" % error.value
if raise_exception:
raise_exc = f'CPy_TypeError("{self.pretty_name(typ)}", {src}); '
Expand Down
8 changes: 4 additions & 4 deletions mypyc/codegen/emitfunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ def generate_native_function(
# eliminated during code generation.
for block in fn.blocks:
terminator = block.terminator
assert isinstance(terminator, ControlOp)
assert isinstance(terminator, ControlOp), terminator

for target in terminator.targets():
is_next_block = target.label == block.label + 1
Expand Down Expand Up @@ -309,7 +309,7 @@ def visit_assign(self, op: Assign) -> None:

def visit_assign_multi(self, op: AssignMulti) -> None:
typ = op.dest.type
assert isinstance(typ, RArray)
assert isinstance(typ, RArray), typ
dest = self.reg(op.dest)
# RArray values can only be assigned to once, so we can always
# declare them on initialization.
Expand Down Expand Up @@ -586,7 +586,7 @@ def visit_method_call(self, op: MethodCall) -> None:
def emit_method_call(self, dest: str, op_obj: Value, name: str, op_args: list[Value]) -> None:
obj = self.reg(op_obj)
rtype = op_obj.type
assert isinstance(rtype, RInstance)
assert isinstance(rtype, RInstance), rtype
class_ir = rtype.class_ir
method = rtype.class_ir.get_method(name)
assert method is not None
Expand Down Expand Up @@ -805,7 +805,7 @@ def visit_get_element_ptr(self, op: GetElementPtr) -> None:
dest = self.reg(op)
src = self.reg(op.src)
# TODO: support tuple type
assert isinstance(op.src_type, RStruct)
assert isinstance(op.src_type, RStruct), op.src_type
assert op.field in op.src_type.names, "Invalid field name."
self.emit_line(
"{} = ({})&(({} *){})->{};".format(
Expand Down
10 changes: 5 additions & 5 deletions mypyc/irbuild/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,8 +551,8 @@ def init_final_static(
*,
type_override: RType | None = None,
) -> None:
assert isinstance(lvalue, NameExpr)
assert isinstance(lvalue.node, Var)
assert isinstance(lvalue, NameExpr), lvalue
assert isinstance(lvalue.node, Var), lvalue.node
if lvalue.node.final_value is None:
if class_name is None:
name = lvalue.name
Expand Down Expand Up @@ -1271,7 +1271,7 @@ def add_local(self, symbol: SymbolNode, typ: RType, is_arg: bool = False) -> Reg
Args:
is_arg: is this a function argument
"""
assert isinstance(symbol, SymbolNode)
assert isinstance(symbol, SymbolNode), symbol
reg = Register(
typ, remangle_redefinition_name(symbol.name), is_arg=is_arg, line=symbol.line
)
Expand All @@ -1286,7 +1286,7 @@ def add_local_reg(
"""Like add_local, but return an assignment target instead of value."""
self.add_local(symbol, typ, is_arg)
target = self.symtables[-1][symbol]
assert isinstance(target, AssignmentTargetRegister)
assert isinstance(target, AssignmentTargetRegister), target
return target

def add_self_to_env(self, cls: ClassIR) -> AssignmentTargetRegister:
Expand Down Expand Up @@ -1446,7 +1446,7 @@ def get_default() -> Value:
GetAttr(builder.fn_info.callable_class.self_reg, name, arg.line)
)

assert isinstance(target, AssignmentTargetRegister)
assert isinstance(target, AssignmentTargetRegister), target
reg = target.register
if not reg.type.error_overlap:
builder.assign_if_null(target.register, get_default, arg.initializer.line)
Expand Down
8 changes: 4 additions & 4 deletions mypyc/irbuild/classdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ def get_type_annotation(self, stmt: AssignmentStmt) -> TypeInfo | None:
type_name = stmt.rvalue.args[index]
if isinstance(type_name, NameExpr) and isinstance(type_name.node, TypeInfo):
lvalue = stmt.lvalues[0]
assert isinstance(lvalue, NameExpr)
assert isinstance(lvalue, NameExpr), lvalue
return type_name.node
return None

Expand Down Expand Up @@ -756,7 +756,7 @@ def generate_attr_defaults_init(
self_var = builder.self()
for stmt in default_assignments:
lvalue = stmt.lvalues[0]
assert isinstance(lvalue, NameExpr)
assert isinstance(lvalue, NameExpr), lvalue
if not stmt.is_final_def and not is_constant(stmt.rvalue):
builder.warning("Unsupported default attribute value", stmt.rvalue.line)

Expand Down Expand Up @@ -862,7 +862,7 @@ def load_decorated_class(builder: IRBuilder, cdef: ClassDef, type_obj: Value) ->
dec_class = type_obj
for d in reversed(decorators):
decorator = d.accept(builder.visitor)
assert isinstance(decorator, Value)
assert isinstance(decorator, Value), decorator
dec_class = builder.py_call(decorator, [dec_class], dec_class.line)
return dec_class

Expand All @@ -873,7 +873,7 @@ def cache_class_attrs(
"""Add class attributes to be cached to the global cache."""
typ = builder.load_native_type_object(cdef.info.fullname)
for lval, rtype in attrs_to_cache:
assert isinstance(lval, NameExpr)
assert isinstance(lval, NameExpr), lval
rval = builder.py_get_attr(typ, lval.name, cdef.line)
builder.init_final_static(lval, rval, cdef.name, type_override=rtype)

Expand Down
4 changes: 2 additions & 2 deletions mypyc/irbuild/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ def translate_method_call(builder: IRBuilder, expr: CallExpr, callee: MemberExpr
and all(kind in (ARG_POS, ARG_NAMED) for kind in expr.arg_kinds)
):
# Call a method via the *class*
assert isinstance(callee.expr.node, TypeInfo)
assert isinstance(callee.expr.node, TypeInfo), callee.expr.node
ir = builder.mapper.type_to_ir[callee.expr.node]
return call_classmethod(builder, ir, expr, callee)
elif builder.is_module_member_expr(callee):
Expand Down Expand Up @@ -722,7 +722,7 @@ def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value:
mypy_file = builder.graph["builtins"].tree
assert mypy_file is not None
info = mypy_file.names["bool"].node
assert isinstance(info, TypeInfo)
assert isinstance(info, TypeInfo), info
bool_type = Instance(info, [])
exprs = []
for item in items:
Expand Down
2 changes: 1 addition & 1 deletion mypyc/irbuild/for_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ def begin_body(self) -> None:
value = builder.add(TupleGet(self.next_tuple, 3, line))

# Coerce just in case e.g. key is itself a tuple to be unpacked.
assert isinstance(self.target_type, RTuple)
assert isinstance(self.target_type, RTuple), self.target_type
key = builder.coerce(key, self.target_type.types[0], line)
value = builder.coerce(value, self.target_type.types[1], line)

Expand Down
19 changes: 8 additions & 11 deletions mypyc/irbuild/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def transform_decorator(builder: IRBuilder, dec: Decorator) -> None:

def transform_lambda_expr(builder: IRBuilder, expr: LambdaExpr) -> Value:
typ = get_proper_type(builder.types[expr])
assert isinstance(typ, CallableType)
assert isinstance(typ, CallableType), typ

runtime_args = []
for arg, arg_type in zip(expr.arguments, typ.arg_types):
Expand Down Expand Up @@ -269,7 +269,7 @@ def c() -> None:
# add the generated main singledispatch function
builder.functions.append(func_ir)
# create the dispatch function
assert isinstance(fitem, FuncDef)
assert isinstance(fitem, FuncDef), fitem
return gen_dispatch_func_ir(builder, fitem, fn_info.name, name, sig)

return func_ir, func_reg
Expand Down Expand Up @@ -336,8 +336,9 @@ def gen_func_ir(
add_get_to_callable_class(builder, fn_info)
func_reg = instantiate_callable_class(builder, fn_info)
else:
assert isinstance(fn_info.fitem, FuncDef)
func_decl = builder.mapper.func_to_decl[fn_info.fitem]
fitem = fn_info.fitem
assert isinstance(fitem, FuncDef), fitem
func_decl = builder.mapper.func_to_decl[fitem]
if fn_info.is_decorated or is_singledispatch_main_func:
class_name = None if cdef is None else cdef.name
func_decl = FuncDecl(
Expand All @@ -349,13 +350,9 @@ def gen_func_ir(
func_decl.is_prop_getter,
func_decl.is_prop_setter,
)
func_ir = FuncIR(
func_decl, args, blocks, fn_info.fitem.line, traceback_name=fn_info.fitem.name
)
func_ir = FuncIR(func_decl, args, blocks, fitem.line, traceback_name=fitem.name)
else:
func_ir = FuncIR(
func_decl, args, blocks, fn_info.fitem.line, traceback_name=fn_info.fitem.name
)
func_ir = FuncIR(func_decl, args, blocks, fitem.line, traceback_name=fitem.name)
return (func_ir, func_reg)


Expand Down Expand Up @@ -483,7 +480,7 @@ def load_decorated_func(builder: IRBuilder, fdef: FuncDef, orig_func_reg: Value)
func_reg = orig_func_reg
for d in reversed(decorators):
decorator = d.accept(builder.visitor)
assert isinstance(decorator, Value)
assert isinstance(decorator, Value), decorator
func_reg = builder.py_call(decorator, [func_reg], func_reg.line)
return func_reg

Expand Down
2 changes: 1 addition & 1 deletion mypyc/irbuild/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def instantiate_generator_class(builder: IRBuilder) -> Value:

def setup_generator_class(builder: IRBuilder) -> ClassIR:
mapper = builder.mapper
assert isinstance(builder.fn_info.fitem, FuncDef)
assert isinstance(builder.fn_info.fitem, FuncDef), builder.fn_info.fitem
generator_class_ir = mapper.fdef_to_generator[builder.fn_info.fitem]
if builder.fn_info.can_merge_generator_and_env_classes():
builder.fn_info.env_class = generator_class_ir
Expand Down
9 changes: 5 additions & 4 deletions mypyc/irbuild/ll_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ def coerce(

def coerce_int_to_fixed_width(self, src: Value, target_type: RType, line: int) -> Value:
assert is_fixed_width_rtype(target_type), target_type
assert isinstance(target_type, RPrimitive)
assert isinstance(target_type, RPrimitive), target_type

res = Register(target_type)

Expand Down Expand Up @@ -538,10 +538,11 @@ def coerce_fixed_width_to_int(self, src: Value, line: int) -> Value:
line,
)

assert is_fixed_width_rtype(src.type)
assert isinstance(src.type, RPrimitive)
src_type = src.type

assert is_fixed_width_rtype(src_type), src_type
assert isinstance(src_type, RPrimitive), src_type

res = Register(int_rprimitive)

fast, fast2, slow, end = BasicBlock(), BasicBlock(), BasicBlock(), BasicBlock()
Expand Down Expand Up @@ -1504,7 +1505,7 @@ def compare_bytes(self, lhs: Value, rhs: Value, op: str, line: int) -> Value:
def compare_tuples(self, lhs: Value, rhs: Value, op: str, line: int = -1) -> Value:
"""Compare two tuples item by item"""
# type cast to pass mypy check
assert isinstance(lhs.type, RTuple) and isinstance(rhs.type, RTuple)
assert isinstance(lhs.type, RTuple) and isinstance(rhs.type, RTuple), (lhs.type, rhs.type)
equal = True if op == "==" else False
result = Register(bool_rprimitive)
# tuples of different lengths
Expand Down
4 changes: 2 additions & 2 deletions mypyc/irbuild/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def visit_class_pattern(self, pattern: ClassPattern) -> None:
return

node = pattern.class_ref.node
assert isinstance(node, TypeInfo)
assert isinstance(node, TypeInfo), node
match_args = extract_dunder_match_args_names(node)

for i, expr in enumerate(pattern.positionals):
Expand Down Expand Up @@ -345,7 +345,7 @@ def extract_dunder_match_args_names(info: TypeInfo) -> list[str]:
ty = info.names.get("__match_args__")
assert ty
match_args_type = get_proper_type(ty.type)
assert isinstance(match_args_type, TupleType)
assert isinstance(match_args_type, TupleType), match_args_type

match_args: list[str] = []
for item in match_args_type.items:
Expand Down
2 changes: 1 addition & 1 deletion mypyc/irbuild/nonlocalcontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def gen_return(self, builder: IRBuilder, value: Value, line: int) -> None:
self.ret_reg = Register(builder.ret_types[-1])
# assert needed because of apparent mypy bug... it loses track of the union
# and infers the type as object
assert isinstance(self.ret_reg, (Register, AssignmentTarget))
assert isinstance(self.ret_reg, (Register, AssignmentTarget)), self.ret_reg
builder.assign(self.ret_reg, value, line)

builder.add(Goto(self.target))
Expand Down
2 changes: 1 addition & 1 deletion mypyc/irbuild/statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ def maybe_natively_call_exit(exc_info: bool) -> Value:
args = [none, none, none]

if is_native:
assert isinstance(mgr_v.type, RInstance)
assert isinstance(mgr_v.type, RInstance), mgr_v.type
exit_val = builder.gen_method_call(
builder.read(mgr),
f"__{al}exit__",
Expand Down
2 changes: 1 addition & 1 deletion mypyc/lower/list_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def buf_init_item(builder: LowLevelIRBuilder, args: list[Value], line: int) -> V
base = args[0]
index_value = args[1]
value = args[2]
assert isinstance(index_value, Integer)
assert isinstance(index_value, Integer), index_value
index = index_value.numeric_value()
if index == 0:
ptr = base
Expand Down
2 changes: 1 addition & 1 deletion mypyc/transform/ir_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ def visit_get_element_ptr(self, op: GetElementPtr) -> None:
def visit_load_address(self, op: LoadAddress) -> None:
if isinstance(op.src, LoadStatic):
new = self.fix_op(op.src)
assert isinstance(new, LoadStatic)
assert isinstance(new, LoadStatic), new
op.src = new

def visit_keep_alive(self, op: KeepAlive) -> None:
Expand Down
Loading