Skip to content

Commit 77f63bf

Browse files
yangdanny97meta-codesync[bot]
authored andcommitted
fix false-positive in raise..from
Summary: fixes #1405 We had special-casing for None already, but did not handle when it appears in a union. Reviewed By: kinto0 Differential Revision: D85674425 fbshipit-source-id: 258c1c35afe0b3858ecc9519e569788940b44997
1 parent 36cbe0d commit 77f63bf

File tree

4 files changed

+29
-10
lines changed

4 files changed

+29
-10
lines changed

crates/pyrefly_config/src/error_kind.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ pub enum ErrorKind {
117117
/// A subclass method incorrectly changes the name of a positional parameter while overriding
118118
/// a method of a parent class.
119119
BadParamNameOverride,
120+
/// Invalid exception or cause in `raise` statement.
121+
BadRaise,
120122
/// Attempting to return a value that does not match the function's return type.
121123
/// Can also arise when returning values from generators.
122124
BadReturn,

pyrefly/lib/alt/solve.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -799,22 +799,25 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
799799
errors: &ErrorCollector,
800800
) {
801801
let actual_type = self.expr_infer(x, errors);
802-
if allow_none && actual_type.is_none() {
803-
return;
804-
}
805802
let base_exception_class = self.stdlib.base_exception();
806803
let base_exception_class_type = Type::ClassDef(base_exception_class.class_object().dupe());
807804
let base_exception_type = base_exception_class.clone().to_type();
808-
let expected_types = vec![base_exception_type, base_exception_class_type];
805+
let mut expected_types = vec![base_exception_type, base_exception_class_type];
806+
let mut expected = "`BaseException`";
807+
if allow_none {
808+
expected_types.push(Type::None);
809+
expected = "`BaseException` or `None`"
810+
}
809811
if !self.is_subset_eq(&actual_type, &Type::Union(expected_types)) {
810812
self.error(
811813
errors,
812814
range,
813-
ErrorInfo::Kind(ErrorKind::InvalidInheritance),
815+
ErrorInfo::Kind(ErrorKind::BadRaise),
814816
format!(
815-
"Expression `{}` has type `{}` which does not derive from BaseException",
817+
"Expression `{}` has type `{}`, expected {}",
816818
self.module().display(x),
817819
self.for_display(actual_type),
820+
expected,
818821
),
819822
);
820823
}

pyrefly/lib/test/simple.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -422,17 +422,18 @@ assert_type(0 if derp() else 1, Literal[0] | Literal[1])
422422
testcase!(
423423
test_raise,
424424
r#"
425-
def test_raise() -> None:
425+
def test_raise(exception_or_none: BaseException | None) -> None:
426426
raise
427-
raise None # E: does not derive from BaseException
427+
raise None # E: expected `BaseException`
428428
raise BaseException
429429
raise BaseException()
430-
raise 42 # E: does not derive from BaseException
430+
raise 42 # E: expected `BaseException`
431431
raise BaseException from None
432432
raise BaseException() from None
433433
raise BaseException() from BaseException
434434
raise BaseException() from BaseException()
435-
raise BaseException() from 42 # E: does not derive from BaseException
435+
raise BaseException() from 42 # E: expected `BaseException` or `None`
436+
raise BaseException() from exception_or_none
436437
"#,
437438
);
438439

website/docs/error-kinds.mdx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,19 @@ def f(base: Base):
272272
f(Sub()) # oops!
273273
```
274274

275+
## bad-raise
276+
277+
In a `raise` statement of the form `raise x from y`, `x` must be an exception, and `y` must be an exception or `None`.
278+
279+
```python
280+
def bad_raise() -> None:
281+
raise Exception() # ok
282+
raise 1 # error
283+
raise Exception() from None # ok
284+
raise Exception() from Exception() # ok
285+
raise Exception() from 1 # error
286+
```
287+
275288
## bad-return
276289

277290
Arises when a function does not return a value that is compatible with the function's return type annotation.

0 commit comments

Comments
 (0)