Skip to content

fix(suppression): handle ignores on multi-line implicit concatenations#3189

Open
rexledesma wants to merge 1 commit intofacebook:mainfrom
rexledesma:rl/reparse-source-on-multiline-suppress
Open

fix(suppression): handle ignores on multi-line implicit concatenations#3189
rexledesma wants to merge 1 commit intofacebook:mainfrom
rexledesma:rl/reparse-source-on-multiline-suppress

Conversation

@rexledesma
Copy link
Copy Markdown
Contributor

Summary

We did not respect ignore comments for the entirety of a multi-line implicit concatenation. This only happened in pyrefly check.

This occurred because we had thrown away the AST by the time we collect and check for errors. Instead, just reparse it.

Fixes #3188.

Test Plan

  • cargo test
  • Manually (e.g. cargo run --check), with the following file:
# lol.py
d = "lol"

x = (
    # pyrefly: ignore [bad-index]                                                                                 
    f"{d['foo']}\n" 
    f"{d['bar']}"
)

@meta-cla
Copy link
Copy Markdown

meta-cla Bot commented Apr 21, 2026

Hi @rexledesma!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@rexledesma rexledesma force-pushed the rl/reparse-source-on-multiline-suppress branch from e79b9a4 to 92a89ee Compare April 21, 2026 03:38
@meta-cla meta-cla Bot added the cla signed label Apr 21, 2026
@github-actions github-actions Bot added size/s and removed size/s labels Apr 21, 2026
@kinto0
Copy link
Copy Markdown
Contributor

kinto0 commented Apr 24, 2026

thank you for the fix! and sorry about the delayed review.

interesting. if this is true, we might have other bugs like this. I don't think that test covers it because the test would not evict. cc @maggiemoss

@github-actions

This comment has been minimized.

@github-actions github-actions Bot added the stale label May 9, 2026
@rexledesma
Copy link
Copy Markdown
Contributor Author

Hi @kinto0 @maggiemoss, any update on this? If this is a wider issue, I'm happy to close my PR for you all to address it.

@yangdanny97 yangdanny97 self-assigned this May 9, 2026
@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync Bot commented May 9, 2026

@yangdanny97 has imported this pull request. If you are a Meta employee, you can view this in D104527589.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 9, 2026

Diff from mypy_primer, showing the effect of this PR on open source code:

pyodide (https://github.com/pyodide/pyodide)
- ERROR src/py/ssl.py:16:75-87: Could not import `_simple_enum` from `enum` [missing-module-attribute]
- ERROR src/py/ssl.py:17:47-70: Could not import `_GLOBAL_DEFAULT_TIMEOUT` from `socket` [missing-module-attribute]
- ERROR src/py/ssl.py:58:1-19: Class `IntEnum` has no class attribute `_convert_` [missing-attribute]
- ERROR src/py/ssl.py:65:1-19: Class `IntFlag` has no class attribute `_convert_` [missing-attribute]
- ERROR src/py/ssl.py:69:1-19: Class `IntEnum` has no class attribute `_convert_` [missing-attribute]
- ERROR src/py/ssl.py:76:1-19: Class `IntEnum` has no class attribute `_convert_` [missing-attribute]
- ERROR src/py/ssl.py:80:1-19: Class `IntFlag` has no class attribute `_convert_` [missing-attribute]
- ERROR src/py/ssl.py:84:1-19: Class `IntEnum` has no class attribute `_convert_` [missing-attribute]
- ERROR src/py/ssl.py:88:19-29: Could not find name `_SSLMethod` [unknown-name]
- ERROR src/py/ssl.py:88:48-58: Could not find name `_SSLMethod` [unknown-name]
- ERROR src/py/ssl.py:89:51-61: Could not find name `_SSLMethod` [unknown-name]
- ERROR src/py/ssl.py:224:7-14: Named tuples do not support multiple inheritance [invalid-inheritance]
- ERROR src/py/ssl.py:245:24-36: Could not find name `PROTOCOL_TLS` [unknown-name]
- ERROR src/py/ssl.py:251:13-25: Could not find name `PROTOCOL_TLS` [unknown-name]
- ERROR src/py/ssl.py:252:13-32: Could not find name `PROTOCOL_TLS_CLIENT` [unknown-name]
- ERROR src/py/ssl.py:253:13-32: Could not find name `PROTOCOL_TLS_SERVER` [unknown-name]
- ERROR src/py/ssl.py:267:24-43: Could not find name `PROTOCOL_TLS_CLIENT` [unknown-name]
- ERROR src/py/ssl.py:269:33-46: Could not find name `CERT_REQUIRED` [unknown-name]
- ERROR src/py/ssl.py:272:33-42: Could not find name `CERT_NONE` [unknown-name]
- ERROR src/py/ssl.py:277:13-20: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:278:15-22: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:279:15-22: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:280:15-22: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:281:15-22: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:282:15-22: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:283:15-22: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:284:15-22: Could not find name `Options` [unknown-name]
- ERROR src/py/ssl.py:286:30-41: Could not find name `VerifyFlags` [unknown-name]
- ERROR src/py/ssl.py:418:58-67: Could not find name `CERT_NONE` [unknown-name]
- ERROR src/py/ssl.py:419:33-46: Could not find name `CERT_REQUIRED` [unknown-name]
- ERROR src/py/ssl.py:439:26-35: Could not find name `CERT_NONE` [unknown-name]
- ERROR src/py/ssl.py:439:37-50: Could not find name `CERT_OPTIONAL` [unknown-name]
- ERROR src/py/ssl.py:439:52-65: Could not find name `CERT_REQUIRED` [unknown-name]
- ERROR src/py/ssl.py:441:46-55: Could not find name `CERT_NONE` [unknown-name]
- ERROR src/py/ssl.py:529:29-48: Could not find name `PROTOCOL_TLS_CLIENT` [unknown-name]
- ERROR src/py/ssl.py:545:30-49: Could not find name `PROTOCOL_TLS_CLIENT` [unknown-name]
- ERROR src/py/ssl.py:546:31-44: Could not find name `CERT_REQUIRED` [unknown-name]
- ERROR src/py/ssl.py:549:30-49: Could not find name `PROTOCOL_TLS_SERVER` [unknown-name]
- ERROR src/py/ssl.py:557:33-42: Could not find name `CERT_NONE` [unknown-name]
- ERROR src/py/ssl.py:570:15-24: Could not find name `CERT_NONE` [unknown-name]
- ERROR src/py/ssl.py:585:24-43: Could not find name `PROTOCOL_TLS_CLIENT` [unknown-name]
- ERROR src/py/ssl.py:588:24-43: Could not find name `PROTOCOL_TLS_SERVER` [unknown-name]
- ERROR src/py/ssl.py:604:33-42: Could not find name `CERT_NONE` [unknown-name]
- ERROR src/py/ssl.py:724:9-26: Object of class `SSLSocket` has no attribute `_io_refs` [missing-attribute]
- ERROR src/py/ssl.py:725:9-25: Object of class `SSLSocket` has no attribute `_closed` [missing-attribute]
- ERROR src/py/ssl.py:730:9-25: Object of class `SSLSocket` has no attribute `_sslobj` [missing-attribute]
- ERROR src/py/ssl.py:731:9-26: Object of class `SSLSocket` has no attribute `_context` [missing-attribute]
- ERROR src/py/ssl.py:732:9-34: Object of class `SSLSocket` has no attribute `_server_hostname` [missing-attribute]
- ERROR src/py/ssl.py:733:9-30: Object of class `SSLSocket` has no attribute `_server_side` [missing-attribute]
- ERROR src/py/ssl.py:734:9-28: Object of class `SSLSocket` has no attribute `_connected` [missing-attribute]
- ERROR src/py/ssl.py:735:9-39: Object of class `SSLSocket` has no attribute `_suppress_ragged_eofs` [missing-attribute]
- ERROR src/py/ssl.py:736:9-26: Object of class `SSLSocket` has no attribute `_session` [missing-attribute]
- ERROR src/py/ssl.py:753:17-20: Expected a callable, got `int` [not-callable]
- ERROR src/py/ssl.py:791:9-15: Class member `SSLSocket.sendto` overrides parent class `socket` in an inconsistent manner [bad-override]
- ERROR src/py/ssl.py:802:9-17: Class member `SSLSocket.sendfile` overrides parent class `socket` in an inconsistent manner [bad-override]
- ERROR src/py/ssl.py:811:9-17: Class member `SSLSocket.recvfrom` overrides parent class `socket` in an inconsistent manner [bad-override]
- ERROR src/py/ssl.py:814:9-22: Class member `SSLSocket.recvfrom_into` overrides parent class `socket` in an inconsistent manner [bad-override]
- ERROR src/py/ssl.py:852:9-19: Class member `SSLSocket.connect_ex` overrides parent class `socket` in an inconsistent manner [bad-override]
- ERROR src/py/ssl.py:855:9-15: Class member `SSLSocket.accept` overrides parent class `socket` in an inconsistent manner [bad-override]
- ERROR src/py/ssl.py:924:17-36: Could not find name `PROTOCOL_TLS_CLIENT` [unknown-name]

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 9, 2026

Primer Diff Classification

✅ 1 improvement(s) | 1 project(s) total | -60 errors

1 improvement(s) across pyodide.

Project Verdict Changes Error Kinds Root Cause
pyodide ✅ Improvement -60 bad-override, invalid-inheritance module_ranges_from()
Detailed analysis

✅ Improvement (1)

pyodide (-60)

The file src/py/ssl.py has # type: ignore on line 1, which should suppress all type errors. Before this PR, pyrefly was not honoring this suppression because the AST was unavailable when computing multi-line ranges for suppression processing. The fix ensures the AST is re-parsed when evicted, allowing all suppression directives to work correctly. All 60 removed errors are false positives that should have been suppressed.
Attribution: The change to module_ranges_from() and the parallel closure in pyrefly/lib/state/state.rs now re-parses the AST via Ast::parse() when get_ast() returns None (AST evicted after Answers step), instead of falling back to an empty default for sorted_multi_line_string_ranges. This ensures suppression directives (including # type: ignore on line 1) are correctly processed even when the AST has been evicted.


Was this helpful? React with 👍 or 👎

Classification by primer-classifier (1 LLM)

@github-actions github-actions Bot removed the stale label May 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Errors in multiline implicit string concatenation not properly suppressed

4 participants