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

[red-knot] Do not panic when encountering string annotations #14091

Merged
merged 2 commits into from
Nov 4, 2024

Conversation

sharkdp
Copy link
Contributor

@sharkdp sharkdp commented Nov 4, 2024

Summary

Encountered this while running red-knot benchmarks on the black codebase.

Fixes two of the issues in #13478.

Test Plan

Added a regression test.

@sharkdp sharkdp added the red-knot Multi-file analysis & type inference label Nov 4, 2024
Comment on lines 195 to 201
infer_deferred_types(db, definition)
.try_expression_ty(expr_id)
.unwrap_or(
// Some deferred cases like string annotations are not yet implemented
Type::Todo,
)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit concerned that will forget to remove this after adding support for stringified type annotations.

Should we instead insert the type TODO here

// https://typing.readthedocs.io/en/latest/spec/annotations.html#string-annotations
ast::Expr::StringLiteral(_literal) => Type::Todo,

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we instead insert the type TODO here

985f211/crates/red_knot_python_semantic/src/types/infer.rs#L3748-L3749

image

😶

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we instead insert the type TODO here

We already have this branch:

// TODO: parse the expression and check whether it is a string annotation.
// https://typing.readthedocs.io/en/latest/spec/annotations.html#string-annotations
ast::Expr::StringLiteral(_literal) => Type::Todo,

It does not prevent the panic.

But I think I know what's wrong. Will push a better fix (hopefully).

Copy link
Contributor

github-actions bot commented Nov 4, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Comment on lines 3658 to 3661
ast::Expr::StringLiteral(_literal) => {
let expr_id = expression.scoped_ast_id(self.db, self.scope());
self.types.expressions.insert(expr_id, Type::Todo);
Type::Todo
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do not add the expression type into self.types.expressions here (like we do for the other branches), it will later lead to a panic here:

infer_deferred_types(db, definition).expression_ty(expr_id)

@sharkdp sharkdp force-pushed the david/no-panic-for-stringified-annotations branch from 7febfdc to 0df668c Compare November 4, 2024 13:40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: If all we're asserting is "make sure we don't panic", then an mdtest is arguably overkill here: this could be better as a snippet added to the corpus directory (we have a test that runs over all the snippets in that directory and checks that we can at least run red-knot over them without panicking)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we would eventually have a Markdown-based test for string annotations anyway, and this test (with a non-@Todo-assertion) could very well be a basic initial test. I agree, so far it does little except document the fact that we don't understand string annotations yet.

But I'm happy to turn it into a snippet, if you prefer that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, fair enough. I suppose the corpus directory becomes less and less useful as we expand our ambitions beyond "do not panic when checking Python" to "infer the correct types consistently everywhere when checking Python" 😆

@sharkdp sharkdp merged commit 6dabf04 into main Nov 4, 2024
20 checks passed
@sharkdp sharkdp deleted the david/no-panic-for-stringified-annotations branch November 4, 2024 14:06
ast::Expr::StringLiteral(_literal) => {
self.store_expression_type(expression, Type::Todo);
Type::Todo
}

// Annotation expressions also get special handling for `*args` and `**kwargs`.
ast::Expr::Starred(starred) => self.infer_starred_expression(starred),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we have the same bug here, for starred expressions in an annotation.

In general the contract is supposed to be that infer_expression takes care of storing the expression type, so we don't have to do it separately for every kind of expression.

For annotations, the tricky thing is the split between annotation expressions (what is valid in an annotation) and type expressions (which is a subset of annotation expressions). Currently infer_type_expression stores the type, but infer_annotation_expression does not, because most of the time it just defers to infer_type_expression, and we don't want to double-store. But we should come up with some general way to ensure annotation expression types are always stored, without having to do it separately in each branch that we add here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I did look at infer_starred_expression and saw that it uses infer_expression (which stores the expression type), but that's probably not enough… I'll look into it!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It uses infer_expression on a sub-part of the starred expression (the value), but never on the starred expression itself. This is the usual pattern for infer_* methods for particular node types, since the assumption is they are called from infer_expression which will store the type they return.

carljm added a commit to Glyphack/ruff that referenced this pull request Nov 5, 2024
* main: (39 commits)
  Also remove trailing comma while fixing C409 and C419 (astral-sh#14097)
  Re-enable clippy `useless-format` (astral-sh#14095)
  Derive message formats macro support to string (astral-sh#14093)
  Avoid cloning `Name` when looking up function and class types (astral-sh#14092)
  Replace `format!` without parameters with `.to_string()` (astral-sh#14090)
  [red-knot] Do not panic when encountering string annotations (astral-sh#14091)
  [red-knot] Add MRO resolution for classes (astral-sh#14027)
  [red-knot] Remove `Type::None` (astral-sh#14024)
  Cached inference of all definitions in an unpacking (astral-sh#13979)
  Update dependency uuid to v11 (astral-sh#14084)
  Update Rust crate notify to v7 (astral-sh#14083)
  Update cloudflare/wrangler-action action to v3.11.0 (astral-sh#14080)
  Update dependency mdformat-mkdocs to v3.1.1 (astral-sh#14081)
  Update pre-commit dependencies (astral-sh#14082)
  Update dependency ruff to v0.7.2 (astral-sh#14077)
  Update NPM Development dependencies (astral-sh#14078)
  Update Rust crate thiserror to v1.0.67 (astral-sh#14076)
  Update Rust crate syn to v2.0.87 (astral-sh#14075)
  Update Rust crate serde to v1.0.214 (astral-sh#14074)
  Update Rust crate pep440_rs to v0.7.2 (astral-sh#14073)
  ...
sharkdp added a commit that referenced this pull request Nov 5, 2024
## Summary

- Store the expression type for annotations that are starred expressions
(see [discussion
here](#14091 (comment)))
- Use `self.store_expression_type(…)` consistently throughout, as it
makes sure that no double-insertion errors occur.

closes #14115

## Test Plan

Added an invalid-syntax example to the corpus which leads to a panic on
`main`. Also added a Markdown test with a valid-syntax example that
would lead to a panic once we implement function parameter inference.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
red-knot Multi-file analysis & type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants