| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
The primer results are a little mysterious. I could simplify to: for y in [1.0]:
if y is not None or y != "None": # E: Non-overlapping equality check (left operand type: "float", right operand type: "Literal['None']")
...This obvious error is only reported with my change, but I do not know why current master misses it and therefore have no idea what in this PR contributes to detecting it. For whatever reason this happens, I will add a corresponding test case. |
Sorry, something went wrong.
|
Ah, I got it. It is because optuna enables --strict-equality but not unreachable. y is not None is always true, so that the y != "None" mismatch is not reported. I could invest some time so that for y in [1.0]:
if y is not None or y != "None":
...and y = 1.0
if y is not None or y != "None":
...would be handled identically again (no --strict-equality warnings). However, this is a good example that failing to raise warnings in unreachable code can be confusing, and there is already a PR that tries to improve the situation (#18707). Hence, maybe no further action is required here. |
Sorry, something went wrong.
…p errors (return -> break)
|
I revisited the problem and added two lines of code that reset the old behaviour for the discussed problem and make some sense to me. The problem was that "nearer" error watchers could not filter non-overlap reports anymore. Now, the collection mechanism of IterationErrorWatcher only applies if no nearer error watcher has _filter activated. I think this is the place where the now again respected error watcher is created: Lines 5982 to 5999 in 5a78607 |
Sorry, something went wrong.
|
@ilevkivskyi: I don't want to overstretch your willingness to help, but could you also take a look at this one? This PR aligns closely with what we began in #19324 and would enable me to implement reachability checking for functions with constrained type variables. |
Sorry, something went wrong.
| # respective types of the current iteration here so that we can report the error | ||
| # later if it is persistent over all iteration steps: | ||
| for watcher in self.errors.get_watchers(): | ||
| if watcher._filter: |
There was a problem hiding this comment.
Could you move this logic into the watcher itself? This access to private followed by special-casing on watcher type is a bit painful to read, IMO this would be clearer as
for watcher in self.errors.get_watchers():
if watcher.store_nonoverlapping_types(ctx, kind, left, right):
returnWhere store_nonoverlapping_types (not the best name) is a no-op in ErrorWatcher, overridden with this block in IterationErrorWatcher
Sorry, something went wrong.
There was a problem hiding this comment.
Ough, you really need both break and return, sorry.
Sorry, something went wrong.
There was a problem hiding this comment.
No need to excuse. I am obviously using things a little differently from how they were originally intended. Hence, I highly appreciate any thoughts on improving readability.
Sorry, something went wrong.
| # One dictionary of non-overlapping types per iteration step. Meaning of the key | ||
| # tuple items: line, column, end_line, end_column, kind: | ||
| nonoverlapping_types: list[ | ||
| dict[tuple[int, int, int | None, int | None, str], tuple[Type, Type]], |
There was a problem hiding this comment.
Maybe NamedTuple or at least TypeAlias? I'm personally lost in brackets here
Sorry, something went wrong.
There was a problem hiding this comment.
In my opinion, TypeAlias doesn't help much. But using NamedTuple (here and in the similar cases above) would definitely increase readability. I will adjust it if there are no performance concerns.
Sorry, something went wrong.
There was a problem hiding this comment.
Sorry for the slow response: I just introduced the NamedTuple NonOverlapErrorInfo.
It would be good to refactor the other members of IterationDependentErrors as well, but maybe it would distract other reviewers, so I leave this for a separate PR.
Sorry, something went wrong.
Co-authored-by: Stanislav Terliakov <50529348+sterliakov@users.noreply.github.com>
There was a problem hiding this comment.
Sorry for a big delay, LG! Left a couple of nits, but none of them are deal-breakers for me
Sorry, something went wrong.
| defaultdict(lambda: ([], [])) | ||
| ) | ||
| for nonoverlaps in self.nonoverlapping_types: | ||
| for candidate, (left, right) in nonoverlaps.items(): |
There was a problem hiding this comment.
selected is a strict subset of nonoverlaps, right? How big is it usually, relative to nonoverlaps size? If it normally includes a relatively small portion of those, it might be faster to swap these checks (iterate over selected and do left, right = nonoverlaps[candidate] for each).
Sorry, something went wrong.
There was a problem hiding this comment.
selected is only a subset of each nonoverlaps item if the relevant lines are reachable in all iterations. So, I am not really sure about the potential benefits of such a switch. However, maybe performance isn't overly critical here, since the loop's body is only executed if there is, in fact, an overlap issue to report?
Sorry, something went wrong.
Co-authored-by: Stanislav Terliakov <50529348+sterliakov@users.noreply.github.com>
for more information, see https://pre-commit.ci
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
LG, but I am a bit worried about performance. Did you make any measurements with misc/perf_compare.py?
Sorry, something went wrong.
| column: int | ||
| end_line: int | None | ||
| end_column: int | None | ||
| kind: str |
There was a problem hiding this comment.
I think a regular class will be faster when compiled with mypyc.
Sorry, something went wrong.
There was a problem hiding this comment.
Okay. Much boilerplate code (we also need __eq__ and __hash__), but no problem, of course. Done.
Sorry, something went wrong.
| def iteration_dependent_errors(self, iter_errors: IterationDependentErrors) -> None: | ||
| for error_info in iter_errors.yield_uselessness_error_infos(): | ||
| self.fail(*error_info[:2], code=error_info[2]) | ||
| msu = mypy.typeops.make_simplified_union |
There was a problem hiding this comment.
Please don't do this, the effect on readability is ~0, while it may potentially affect compiled performance.
Sorry, something went wrong.
There was a problem hiding this comment.
+0.5 % readability IMO!
Also changed.
Sorry, something went wrong.
|
(oh, you also need to update tests to use new union syntax) |
Sorry, something went wrong.
for more information, see https://pre-commit.ci
|
According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅ |
Sorry, something went wrong.
Also done.
Sorry, I should have done this already. I now performed two runs: master 7.990s (0.0%) | stdev 0.315s fix_strict_quality_in_loops 7.876s (-1.4%) | stdev 0.283s Total time taken by the whole benchmarking program (including any setup): 11 minutes, 4 seconds master 7.894s (0.0%) | stdev 0.415s fix_strict_quality_in_loops 7.931s (+0.5%) | stdev 0.459s Total time taken by the whole benchmarking program (including any setup): 11 minutes, 5 seconds |
Sorry, something went wrong.
|
@ilevkivskyi and @sterliakov : Thanks for the reviews! |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Fixes #19328
Fixes #20294
The logic is very similar to what we did to report different revealed types that were discovered in multiple iteration steps in one line. I think this fix is the last one needed before I can implement #19256.