Skip to content

Commit 542fed5

Browse files
rchen152facebook-github-bot
authored andcommitted
Support forward references in assert_type
Reviewed By: samwgoldman Differential Revision: D70024022 fbshipit-source-id: ab0bbc1b5b608d371edd061978fa3316046efe0c
1 parent b349638 commit 542fed5

File tree

6 files changed

+43
-29
lines changed

6 files changed

+43
-29
lines changed

pyre2/conformance/third_party/conformance.exp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4877,26 +4877,6 @@
48774877
}
48784878
],
48794879
"directives_assert_type.py": [
4880-
{
4881-
"code": -2,
4882-
"column": 5,
4883-
"concise_description": "assert_type(ForwardReference, Any) failed",
4884-
"description": "assert_type(ForwardReference, Any) failed",
4885-
"line": 24,
4886-
"name": "PyreError",
4887-
"stop_column": 39,
4888-
"stop_line": 24
4889-
},
4890-
{
4891-
"code": -2,
4892-
"column": 20,
4893-
"concise_description": "untype, got Literal['ForwardReference']",
4894-
"description": "untype, got Literal['ForwardReference']",
4895-
"line": 24,
4896-
"name": "PyreError",
4897-
"stop_column": 38,
4898-
"stop_line": 24
4899-
},
49004880
{
49014881
"code": -2,
49024882
"column": 5,

pyre2/conformance/third_party/conformance.result

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,7 @@
376376
"Line 106: Unexpected errors ['assert_type(BoundMethod[DC6, (str) -> int], (str) -> int) failed']",
377377
"Line 205: Unexpected errors ['EXPECTED DC15 <: DataclassProto']"
378378
],
379-
"directives_assert_type.py": [
380-
"Line 24: Unexpected errors ['assert_type(ForwardReference, Any) failed', \"untype, got Literal['ForwardReference']\"]"
381-
],
379+
"directives_assert_type.py": [],
382380
"directives_cast.py": [
383381
"Line 16: Expected 1 errors"
384382
],

pyre2/conformance/third_party/results.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"total": 133,
3-
"pass": 21,
4-
"fail": 112,
5-
"pass_rate": 0.16,
6-
"differences": 807,
3+
"pass": 22,
4+
"fail": 111,
5+
"pass_rate": 0.17,
6+
"differences": 806,
77
"passing": [
88
"annotations_coroutines.py",
99
"dataclasses_hash.py",
1010
"dataclasses_order.py",
11+
"directives_assert_type.py",
1112
"directives_no_type_check.py",
1213
"directives_type_ignore.py",
1314
"directives_type_ignore_file2.py",
@@ -64,7 +65,6 @@
6465
"dataclasses_transform_func.py": 7,
6566
"dataclasses_transform_meta.py": 9,
6667
"dataclasses_usage.py": 7,
67-
"directives_assert_type.py": 1,
6868
"directives_cast.py": 1,
6969
"directives_deprecated.py": 11,
7070
"directives_reveal_type.py": 4,

pyre2/pyre2/lib/binding/expr.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use ruff_python_ast::Comprehension;
1313
use ruff_python_ast::Decorator;
1414
use ruff_python_ast::Expr;
1515
use ruff_python_ast::ExprBoolOp;
16+
use ruff_python_ast::ExprCall;
1617
use ruff_python_ast::ExprLambda;
1718
use ruff_python_ast::ExprSubscript;
1819
use ruff_python_ast::Identifier;
@@ -141,6 +142,27 @@ impl<'a> BindingsBuilder<'a> {
141142
self.negate_and_merge_flow(base, &narrow_ops, None, *range);
142143
return;
143144
}
145+
Expr::Call(ExprCall {
146+
range: _,
147+
func,
148+
arguments,
149+
}) if self.as_special_export(func) == Some(SpecialExport::AssertType)
150+
&& arguments.args.len() > 1 =>
151+
{
152+
// Handle forward references in the second argument to an assert_type call
153+
self.ensure_expr(func);
154+
for (i, arg) in arguments.args.iter_mut().enumerate() {
155+
if i == 1 {
156+
self.ensure_type(arg, &mut None);
157+
} else {
158+
self.ensure_expr(arg);
159+
}
160+
}
161+
for kw in arguments.keywords.iter_mut() {
162+
self.ensure_expr(&mut kw.value);
163+
}
164+
return;
165+
}
144166
Expr::Name(x) => {
145167
let name = Ast::expr_name_identifier(x.clone());
146168
let binding = self.forward_lookup(&name);

pyre2/pyre2/lib/export/special.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub enum SpecialExport {
2727
TypedDict,
2828
CollectionsNamedTuple,
2929
TypingNamedTuple,
30+
AssertType,
3031
}
3132

3233
impl SpecialExport {
@@ -44,6 +45,7 @@ impl SpecialExport {
4445
"TypedDict" => Some(Self::TypedDict),
4546
"namedtuple" => Some(Self::CollectionsNamedTuple),
4647
"NamedTuple" => Some(Self::TypingNamedTuple),
48+
"assert_type" => Some(Self::AssertType),
4749
_ => None,
4850
}
4951
}
@@ -57,7 +59,8 @@ impl SpecialExport {
5759
| Self::Annotated
5860
| Self::Literal
5961
| Self::TypedDict
60-
| Self::TypingNamedTuple => {
62+
| Self::TypingNamedTuple
63+
| Self::AssertType => {
6164
matches!(m.as_str(), "typing" | "typing_extensions")
6265
}
6366
Self::CollectionsNamedTuple => matches!(m.as_str(), "collections"),

pyre2/pyre2/lib/test/simple.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,3 +1165,14 @@ from typing import Literal as L
11651165
x: L["foo"] = "foo"
11661166
"#,
11671167
);
1168+
1169+
testcase!(
1170+
test_assert_type_forward_ref,
1171+
r#"
1172+
from typing import assert_type
1173+
x: "ForwardRef"
1174+
assert_type(x, "ForwardRef")
1175+
class ForwardRef:
1176+
pass
1177+
"#,
1178+
);

0 commit comments

Comments
 (0)