You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Incorrect "implicitly abstract" function when function returns None and implementation is 'pass' #13770
This is valid code. The optional_method is optional and is implemented with a valid do-nothing body. It doesn't make sense to return None from this function.
Actual Behavior
% mypy --strict file.py
file.py:13: error: Cannot instantiate abstract class "B" with abstract attribute "optional_method"
file.py:13: note: The following method was marked implicitly abstract because it has an empty function body: "optional_method". If it is not meant to be abstract, explicitly return None.
Found 1 error in 1 file (checked 1 source file)
Your Environment
Mypy version used: 0.981
Mypy command-line flags: --strict
Mypy configuration options from mypy.ini (and other config files): None
It uses a weak heuristic to guess whether a method is abstract and gives no option (that I can find) to disable the guess. How about a a command line option to disable "type checks" that makes wild guesses about the author's intention?
FWIW, pyright treats ... differently from pass when determining whether a protocol method is considered "implicitly abstract", so it does not produce an error for the above code. Apparently mypy treats both ... and pass the same in this regard. Was this intentional? Would it make sense for mypy to treat pass differently here?
I think that treating pass as not being implicitly abstract could be reasonable. One reason for the current behavior may be that Python 2 didn't have ... as a literal, but I'm not sure.
I think that treating pass as not being implicitly abstract could be reasonable.
Yes, I agree. The reason why I did it this way was simply that mypy already had the is_trivial_body function and I re-used it.
In addition to ... and pass, the is_trivial_body function also returns true for function bodies that only contain a docstring and I think also those that only contain raise NotImplementedError:
I don't like an idea of having a flag for this. I also don't like deciding implicit abstractness depending on the return type (optional vs non-optional). We just need to agree on such a set of rules about what is implicitly abstract that would satisfy everyone.
Anecdotally, there are some post-Python 2 code bases that still have pass in protocols. So if we will now exclude pass, those will generate errors (unless return type is optional). We can of course try and see what will be the output from mypy_primer.
I'm pretty happy with the current rules. The error message is clear The following method was marked implicitly abstract because it has an empty function body: "optional_method". If it is not meant to be abstract, explicitly return None. and I don't get the big deal over doing:
def optional_method(self) -> None:
return None
It much more clearly communicates something is different than the difference between "..." and "pass". So I'd vote to close this issue.
To many programmers, particularly from other languages like C++, this goes against common programming idioms. Returning a value from a function typed as void/None is an error.
The ellipses are fine. Why does there need to be more heuristic than that?
Having spurious return statements in functions that are not supposed to return a value is going to lead to readability and other bugs.
I think there's an argument to be made that it is a typing error when functions declared as None return any value, even None.
A return without a value is a reasonable workaround.
I still think pass should also work; but I've already updated our code and this isn't a big issue for me now.
FWIW this overall feature caught a few edge cases (actual missing abstract methods) in our code that I fixed too, although they weren't actually reachable. Thanks!
Activity
cmeyer commentedon Sep 29, 2022
This was implemented in this patch #12118
It uses a weak heuristic to guess whether a method is abstract and gives no option (that I can find) to disable the guess. How about a a command line option to disable "type checks" that makes wild guesses about the author's intention?
erictraut commentedon Sep 29, 2022
FWIW, pyright treats
...differently frompasswhen determining whether a protocol method is considered "implicitly abstract", so it does not produce an error for the above code. Apparently mypy treats both...andpassthe same in this regard. Was this intentional? Would it make sense for mypy to treatpassdifferently here?JukkaL commentedon Sep 29, 2022
I think that treating
passas not being implicitly abstract could be reasonable. One reason for the current behavior may be that Python 2 didn't have...as a literal, but I'm not sure.@ilevkivskyi @thomkeh What do you think?
tmke8 commentedon Sep 29, 2022
Yes, I agree. The reason why I did it this way was simply that mypy already had the
is_trivial_bodyfunction and I re-used it.In addition to
...andpass, theis_trivial_bodyfunction also returnstruefor function bodies that only contain a docstring and I think also those that only containraise NotImplementedError:mypy/mypy/semanal.py
Line 6313 in a68f0a5
Oh, by the way, I initially treated functions returning
NoneandAnydifferently, but that functionality was removed during code reviewilevkivskyi commentedon Sep 29, 2022
I don't like an idea of having a flag for this. I also don't like deciding implicit abstractness depending on the return type (optional vs non-optional). We just need to agree on such a set of rules about what is implicitly abstract that would satisfy everyone.
Anecdotally, there are some post-Python 2 code bases that still have
passin protocols. So if we will now excludepass, those will generate errors (unless return type is optional). We can of course try and see what will be the output frommypy_primer.hauntsaninja commentedon Sep 29, 2022
I'm pretty happy with the current rules. The error message is clear
The following method was marked implicitly abstract because it has an empty function body: "optional_method". If it is not meant to be abstract, explicitly return None.and I don't get the big deal over doing:It much more clearly communicates something is different than the difference between "..." and "pass". So I'd vote to close this issue.
cmeyer commentedon Sep 29, 2022
To many programmers, particularly from other languages like C++, this goes against common programming idioms. Returning a value from a function typed as void/None is an error.
The ellipses are fine. Why does there need to be more heuristic than that?
Having spurious return statements in functions that are not supposed to return a value is going to lead to readability and other bugs.
I think there's an argument to be made that it is a typing error when functions declared as None return any value, even None.
hauntsaninja commentedon Sep 29, 2022
This also works:
I'd be in favour of changing the error message to say "explicitly
returnorreturn None", if that helps address the concern.cmeyer commentedon Sep 30, 2022
A
returnwithout a value is a reasonable workaround.I still think
passshould also work; but I've already updated our code and this isn't a big issue for me now.FWIW this overall feature caught a few edge cases (actual missing abstract methods) in our code that I fixed too, although they weren't actually reachable. Thanks!
Improve error message for implicitly abstract functions
Improve error message for implicitly abstract functions (#13776)
Work around mypy issue