Skip to content

Commit

Permalink
fix: improve error messages when typing.Any type is encountered
Browse files Browse the repository at this point in the history
  • Loading branch information
achidlow committed Jun 25, 2024
1 parent c8bc70e commit c2cfaf5
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
30 changes: 27 additions & 3 deletions src/puya/awst_build/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ def type_to_pytype(
return pytypes.NoneType
case mypy.types.UninhabitedType():
raise CodeError("Cannot resolve empty type", loc)
case mypy.types.AnyType():
# TODO: look at type_of_any to improve error message
raise CodeError("Any type is not supported", loc)
case mypy.types.AnyType(type_of_any=type_of_any):
msg = _type_of_any_to_error_message(type_of_any, loc)
raise CodeError(msg, loc)
case mypy.types.FunctionLike() as func_like:
if func_like.is_type_obj():
msg = "References to type objects are not supported"
Expand Down Expand Up @@ -219,3 +219,27 @@ def _parameterise_pytype(
type_args_resolved.append(self.type_to_pytype(ta, source_location=loc))
result = generic.parameterise(type_args_resolved, loc)
return result


def _type_of_any_to_error_message(type_of_any: int, source_location: SourceLocation) -> str:
from mypy.types import TypeOfAny

match type_of_any:
case TypeOfAny.unannotated:
msg = "type annotation is required at this location"
case TypeOfAny.explicit | TypeOfAny.from_another_any:
msg = "Any type is not supported"
case TypeOfAny.from_unimported_type:
msg = "unknown type from import"
case TypeOfAny.from_omitted_generics:
msg = "type parameters are required at this location"
case TypeOfAny.from_error:
msg = "typing error prevents type resolution"
case TypeOfAny.special_form:
msg = "unsupported type form"
case TypeOfAny.implementation_artifact | TypeOfAny.suggestion_engine:
msg = "mypy cannot handle this type form, try providing an explicit annotation"
case _:
logger.debug(f"Unknown TypeOfAny value: {type_of_any}", location=source_location)
msg = "Any type is not supported"
return msg
4 changes: 2 additions & 2 deletions src/puya/awst_build/subroutine.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,8 @@ def _handle_proxy_assignment(
raise InternalError("Assignment to self outside of a contract class", stmt_loc)
if self.func_def.name != "__init__":
raise CodeError(
f"{rvalue_pytyp} can only be assigned to a member variable"
" in the __init__ method",
f"{rvalue_pytyp.generic or rvalue_pytyp}"
" can only be assigned to a member variable in the __init__ method",
stmt_loc,
)
cref = self.contract_method_info.cref
Expand Down
4 changes: 2 additions & 2 deletions tests/test_expected_output/expected_errors.test
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ class Derived3(Base):
class Derived4(Base):
def __init__(self) -> None:
super().__init__()
self.bar_p = GlobalState(Bytes(b"bbb")) # type: ignore[arg-type] ## E: some error message here about redefining proxies
self.bar_p = GlobalState(Bytes(b"bbb")) # type: ignore[arg-type] ## E: Assignment target type algopy.UInt64 differs from expression value type algopy.Bytes


## case: void_state
Expand All @@ -309,7 +309,7 @@ class Con(Contract):
x: None ## E: None is not supported as a value, only a return type

def approval_program(self) -> bool:
self.x = log(b"") # type: ignore[func-returns-value] ## E: None indicates an empty return and cannot be assigned
self.x = log(b"") # type: ignore[func-returns-value] ## E: typing error prevents type resolution
return True

def clear_state_program(self) -> bool:
Expand Down

0 comments on commit c2cfaf5

Please sign in to comment.