Skip to content
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

Add a NoImplicit return type specifier. #16095

Closed
jakethesnake420 opened this issue Sep 12, 2023 · 3 comments
Closed

Add a NoImplicit return type specifier. #16095

jakethesnake420 opened this issue Sep 12, 2023 · 3 comments
Labels

Comments

@jakethesnake420
Copy link

jakethesnake420 commented Sep 12, 2023

Feature

Example:

cdef foo(): # Type: Any
  ...
  return ...

def bar() -> Any:
   if bool:
      return foo()
   else:
     var = foo() + 1
     # forgot to return so implicitly return None which is a valid Any type
     

mypy won't flag this as an error

Proposed functionality example:

cdef foo(): # Type: Any
  ...
  return ...

def bar() -> NoImplicit[Any]: # the new function specific NoImplicit type specifier
   if bool:
      return foo()
   else:
     var = foo() + foo()
     # forgot to return
     

mypy flags it. error: Implicit return [None]

sometimes when using cython functions it is difficult to specify the return type and sometimes the exact type is not important. I just want to specify that the return is not implicit for only some functions in a large codebase.

Its possible to cast the return type and specify but it seems overly complex and messy when does this way:

cdef foo():
  ...
  return ...
  
def bar() -> List[Union[int, bytes, float]], List[Union[str, int, bytes]
   if bool:
     return cast(List[Union[int, bytes, float]], List[Union[str, int, bytes], foo())
   else:
     var = foo() + foo()
     # forgot to return. error: Missing return statement  [return]

And then imagine how cluttered it gets after calling foo hundreds of times across the codebase

@KotlinIsland
Copy link
Contributor

KotlinIsland commented Sep 13, 2023

@jakethesnake420 here is a bit of a hack that achieves exactly what you want:

from typing import Any, Never

NoImplicitAny = Any | Never  # `Any | Any` would also work

def f() -> NoImplicitAny:  # error: Missing return statement  [return]
    if bool():
        return "amongus"

But I would Never recommend using Any, it's way too dangerous to use in real code. If the issue is that foo isn't typed and you are unable to edit it's definition, then you could wrap it with something that is typed, and use a TypeAlias for shorthand:

from somewhere import foo as real_foo

FooResult = list[int | bytes | float], list[str | int | bytes]
def foo() -> FooResult:
  return real_foo()

def bar() -> FooResult:
   if bool:
     return foo()  # can cast(FooResult, x) if needed
   else:
     var = foo() + foo()
     # forgot to return. error: Missing return statement  [return]

hauntsaninja added a commit to hauntsaninja/mypy that referenced this issue Sep 13, 2023
As discussed in python#7511, mypy's
`--warn-no-return` isn't really a question of type safety. It does
however enforce a rule that is "dear to Guido's heart", and I think we
should enforce it for functions that explicitly return Any as well.

Fixes python#16095
@hauntsaninja
Copy link
Collaborator

We can maybe just make this the default behaviour, let's see how #16102 goes

@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Mar 7, 2024

Closing this as won't fix, see #16102 (comment)

Maybe basedmypy can pick up the patch though ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants