Skip to content

Commit fed35a2

Browse files
authored
[red-knot] Fix is_assignable_to for unions (#14196)
## Summary Fix `Type::is_assignable_to` for union types on the left hand side (of `.is_assignable_to`; or the right hand side of the `… = …` assignment): `Literal[1, 2]` should be assignable to `int`. ## Test Plan New unit tests that were previously failing.
1 parent d1ef418 commit fed35a2

File tree

1 file changed

+20
-0
lines changed
  • crates/red_knot_python_semantic/src

1 file changed

+20
-0
lines changed

crates/red_knot_python_semantic/src/types.rs

+20
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,10 @@ impl<'db> Type<'db> {
626626
match (self, target) {
627627
(Type::Unknown | Type::Any | Type::Todo, _) => true,
628628
(_, Type::Unknown | Type::Any | Type::Todo) => true,
629+
(Type::Union(union), ty) => union
630+
.elements(db)
631+
.iter()
632+
.all(|&elem_ty| elem_ty.is_assignable_to(db, ty)),
629633
(ty, Type::Union(union)) => union
630634
.elements(db)
631635
.iter()
@@ -2765,6 +2769,14 @@ mod tests {
27652769
#[test_case(Ty::IntLiteral(1), Ty::Union(vec![Ty::BuiltinInstance("int"), Ty::BuiltinInstance("str")]))]
27662770
#[test_case(Ty::IntLiteral(1), Ty::Union(vec![Ty::Unknown, Ty::BuiltinInstance("str")]))]
27672771
#[test_case(Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]))]
2772+
#[test_case(
2773+
Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]),
2774+
Ty::BuiltinInstance("int")
2775+
)]
2776+
#[test_case(
2777+
Ty::Union(vec![Ty::IntLiteral(1), Ty::None]),
2778+
Ty::Union(vec![Ty::BuiltinInstance("int"), Ty::None])
2779+
)]
27682780
#[test_case(Ty::Tuple(vec![Ty::Todo]), Ty::Tuple(vec![Ty::IntLiteral(2)]))]
27692781
#[test_case(Ty::Tuple(vec![Ty::IntLiteral(2)]), Ty::Tuple(vec![Ty::Todo]))]
27702782
fn is_assignable_to(from: Ty, to: Ty) {
@@ -2776,6 +2788,14 @@ mod tests {
27762788
#[test_case(Ty::IntLiteral(1), Ty::BuiltinInstance("str"))]
27772789
#[test_case(Ty::BuiltinInstance("int"), Ty::BuiltinInstance("str"))]
27782790
#[test_case(Ty::BuiltinInstance("int"), Ty::IntLiteral(1))]
2791+
#[test_case(
2792+
Ty::Union(vec![Ty::IntLiteral(1), Ty::None]),
2793+
Ty::BuiltinInstance("int")
2794+
)]
2795+
#[test_case(
2796+
Ty::Union(vec![Ty::IntLiteral(1), Ty::None]),
2797+
Ty::Union(vec![Ty::BuiltinInstance("str"), Ty::None])
2798+
)]
27792799
fn is_not_assignable_to(from: Ty, to: Ty) {
27802800
let db = setup_db();
27812801
assert!(!from.into_type(&db).is_assignable_to(&db, to.into_type(&db)));

0 commit comments

Comments
 (0)