Skip to content

Commit 1cecb3b

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 a492972 commit 1cecb3b

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
@@ -1811,24 +1811,15 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
18111811

18121812
pub fn sentinel_from_call(
18131813
&self,
1814-
name: Identifier,
1814+
assignment_name: Identifier,
18151815
x: &ExprCall,
18161816
errors: &ErrorCollector,
18171817
) -> Sentinel {
1818+
let mut sentinel_name = assignment_name;
18181819
let mut iargs = x.arguments.args.iter();
18191820
if let Some(arg) = iargs.next() {
18201821
if let Expr::StringLiteral(lit) = arg {
1821-
if lit.value.to_str() != name.id.as_str() {
1822-
self.error(
1823-
errors,
1824-
x.range,
1825-
ErrorKind::InvalidSentinel,
1826-
format!(
1827-
"Sentinel must be assigned to a variable named `{}`",
1828-
lit.value.to_str()
1829-
),
1830-
);
1831-
}
1822+
sentinel_name = Identifier::new(lit.value.to_str(), lit.range());
18321823
} else {
18331824
self.error(
18341825
errors,
@@ -1897,7 +1888,7 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
18971888
}
18981889
}
18991890

1900-
Sentinel::new(name, self.module().dupe())
1891+
Sentinel::new(sentinel_name, self.module().dupe())
19011892
}
19021893

19031894
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)