Skip to content

Commit 4847feb

Browse files
hrolfurgylfaHrólfur
authored andcommitted
Allow assigning sentinel to variable with different name
This seems to be what is being decided in the python typing spec, see the PR description: python/typing#2277 Although some typecheckers, like pyright, still have the old behaviour recommended in the PEP of giving an error when a different name is assigned.
1 parent d1ce26f commit 4847feb

2 files changed

Lines changed: 30 additions & 15 deletions

File tree

pyrefly/lib/alt/expr.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,24 +1791,15 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
17911791

17921792
pub fn sentinel_from_call(
17931793
&self,
1794-
name: Identifier,
1794+
assignment_name: Identifier,
17951795
x: &ExprCall,
17961796
errors: &ErrorCollector,
17971797
) -> Sentinel {
1798+
let mut sentinel_name = assignment_name;
17981799
let mut iargs = x.arguments.args.iter();
17991800
if let Some(arg) = iargs.next() {
18001801
if let Expr::StringLiteral(lit) = arg {
1801-
if lit.value.to_str() != name.id.as_str() {
1802-
self.error(
1803-
errors,
1804-
x.range,
1805-
ErrorKind::InvalidSentinel,
1806-
format!(
1807-
"Sentinel must be assigned to a variable named `{}`",
1808-
lit.value.to_str()
1809-
),
1810-
);
1811-
}
1802+
sentinel_name = Identifier::new(lit.value.to_str(), lit.range());
18121803
} else {
18131804
self.error(
18141805
errors,
@@ -1877,7 +1868,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
18771868
}
18781869
}
18791870

1880-
Sentinel::new(name, self.module().dupe())
1871+
Sentinel::new(sentinel_name, self.module().dupe())
18811872
}
18821873

18831874
pub fn typevar_from_call(

pyrefly/lib/test/sentinel.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,35 @@ A = Sentinel(name="A") # E: Sentinel requires a name as the first argument # E:
6767
);
6868

6969
testcase!(
70-
test_sentinel_construction_different_names,
70+
test_sentinel_construction_different_names_allowed,
7171
r#"
7272
from typing_extensions import Sentinel
7373
74-
A = Sentinel("B") # E: Sentinel must be assigned to a variable named `B`
74+
A = Sentinel("<A>")
75+
"#,
76+
);
77+
78+
testcase!(
79+
test_sentinel_uses_sentinel_string_literal_name_in_error_messages,
80+
r#"
81+
from typing_extensions import Sentinel
82+
83+
A = Sentinel("<A>")
84+
85+
def foo(a: A):
86+
b: int = a # E: `<A>` is not assignable to `int`
87+
"#,
88+
);
89+
90+
testcase!(
91+
test_sentinel_defaults_to_assignment_name_if_not_constructed_with_name,
92+
r#"
93+
from typing_extensions import Sentinel
94+
95+
A = Sentinel() # E: Sentinel requires a name as the first argument
96+
97+
def foo(a: A):
98+
b: int = a # E: `A` is not assignable to `int`
7599
"#,
76100
);
77101

0 commit comments

Comments
 (0)