Closed WutingjiaX closed 1 week ago
Can you a bit more specific? What changes are you proposing?
As I mentioned earlier, when I want to infer the type of the following code (the type of res), jedi cannot provide a result:
res = "f" in "foo"
the reason of that is in the function def _infer_comparison_part(inference_state, context, left, operator, right)
, When encountering a branch of the in operator,it will return NO_VALUES
elif str_operator in ('in', 'not in'):
return NO_VALUES
So why doesn't this branch return the following content:
return ValueSet([
_bool_to_value(inference_state, True),
_bool_to_value(inference_state, False)
])
Like the returned content in the previous COMPARISON_OPERATORS
branch:
elif str_operator in COMPARISON_OPERATORS:
if left.is_compiled() and right.is_compiled():
# Possible, because the return is not an option. Just compare.
result = left.execute_operation(right, str_operator)
if result:
return result
else:
# Omit some code
return ValueSet([
_bool_to_value(inference_state, True),
_bool_to_value(inference_state, False)
])
After making the modifications, it can infer the correct content and all existing unit tests can still pass
@WutingjiaX thanks for reporting this, you're correct that Jedi currently doesn't infer a type here. I'd guess that the vast majority of uses of x in y
expressions are within conditional statements rather than assignments, which is perhaps why this hasn't been an issue before.
Note that __contains__
is something which types can optionally provide, so not all x in y
tests are valid. The standard data model does indicate it should return True
or False
though, so I think assume that that's the return type (rather than e.g: looking up the real signature) could be a reasonable assumption. Given that many of the basic types do provide it, it may also be reasonable to assume that such a test is valid.
There might also be a broader question of why this comparison is handled separately from the binary comparisons -- that could be useful to understand before we change it. (I can't immediately see any hints from the git history)
It might be useful to understand a bit more about the use-case you have in mind here. Are you hitting an issue in a REPL? In a static code environment (perhaps an IDE)? An example test case might be a useful way to express this.
@davidhalter does Jedi have an opinion about whether (in general) it's better to over-infer (i.e: guess a type that might not actually be there) or under-infer (i.e: miss types which are actually present)?
It looks like currently there's under-inference and the suggestion is to flip that -- assume that in
is always valid and infer accordingly.
@PeterJCLaw We generally over-infer. There is a simple reason for this: Autocompletion will always work in that case. In my Mypy/Jedi rewrite in Rust I'm trying to be very precise about types, because otherwise type-checking won't work and in this case (there I currently return bool
for this case).
@WutingjiaX Can you create a PR for this with a test? I feel like this is not very important, but I would happily merge your proposal. There's probably also a way to return bool
instead of True | False
, but you don't need to care about that for now.
@PeterJCLaw In a static code environment,but not an IDE。 I use plugins such as jedi, ruff, yapf, etc. to provide a language services at the top level for an AI application building platform (similiar to https://buildship.app/onboard/create-project).
In this scenario, I need the ability to infer expression types like "f" in "foo"
.Judging the legality of an expression by its return type
@davidhalter Sure,I‘m glad to create a PR for this。By the way,I have another similar type inference question, and I'm not sure if I should raise it in this issue or create a new one
Feel free to open another issue if it's not related to the same thing.
I found in _infer_comparison_part ,There are the following code snippets:
This will result in the inability to infer the type when cursor under the word res:
Why not return the following code like the previous branch?: