[red-knot] Migrate is_disjoint_from unit tests to Markdown tests (#15580)

## Summary

Part of and resolves #15397, built on top of #15579.

## Test Plan

Markdown tests.
This commit is contained in:
InSync 2025-01-20 14:42:22 +07:00 committed by GitHub
parent d97502d647
commit 975d1457c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 156 additions and 191 deletions

View file

@ -4679,196 +4679,6 @@ pub(crate) mod tests {
}
}
#[test_case(Ty::Never, Ty::Never)]
#[test_case(Ty::Never, Ty::None)]
#[test_case(Ty::Never, Ty::BuiltinInstance("int"))]
#[test_case(Ty::None, Ty::BooleanLiteral(true))]
#[test_case(Ty::None, Ty::IntLiteral(1))]
#[test_case(Ty::None, Ty::StringLiteral("test"))]
#[test_case(Ty::None, Ty::BytesLiteral("test"))]
#[test_case(Ty::None, Ty::LiteralString)]
#[test_case(Ty::None, Ty::BuiltinInstance("int"))]
#[test_case(Ty::None, Ty::Tuple(vec![Ty::None]))]
#[test_case(Ty::BooleanLiteral(true), Ty::BooleanLiteral(false))]
#[test_case(Ty::BooleanLiteral(true), Ty::Tuple(vec![Ty::None]))]
#[test_case(Ty::BooleanLiteral(true), Ty::IntLiteral(1))]
#[test_case(Ty::BooleanLiteral(false), Ty::IntLiteral(0))]
#[test_case(Ty::IntLiteral(1), Ty::IntLiteral(2))]
#[test_case(Ty::IntLiteral(1), Ty::Tuple(vec![Ty::None]))]
#[test_case(Ty::StringLiteral("a"), Ty::StringLiteral("b"))]
#[test_case(Ty::StringLiteral("a"), Ty::Tuple(vec![Ty::None]))]
#[test_case(Ty::LiteralString, Ty::BytesLiteral("a"))]
#[test_case(Ty::BytesLiteral("a"), Ty::BytesLiteral("b"))]
#[test_case(Ty::BytesLiteral("a"), Ty::Tuple(vec![Ty::None]))]
#[test_case(Ty::BytesLiteral("a"), Ty::StringLiteral("a"))]
#[test_case(Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::IntLiteral(3))]
#[test_case(Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::Union(vec![Ty::IntLiteral(3), Ty::IntLiteral(4)]))]
#[test_case(Ty::Intersection{pos: vec![Ty::BuiltinInstance("int"), Ty::IntLiteral(1)], neg: vec![]}, Ty::IntLiteral(2))]
#[test_case(Ty::Tuple(vec![Ty::IntLiteral(1)]), Ty::Tuple(vec![Ty::IntLiteral(2)]))]
#[test_case(Ty::Tuple(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::Tuple(vec![Ty::IntLiteral(1)]))]
#[test_case(Ty::Tuple(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::Tuple(vec![Ty::IntLiteral(1), Ty::IntLiteral(3)]))]
#[test_case(Ty::Tuple(vec![]), Ty::BuiltinClassLiteral("object"))]
#[test_case(Ty::SubclassOfBuiltinClass("object"), Ty::None)]
#[test_case(Ty::SubclassOfBuiltinClass("str"), Ty::LiteralString)]
#[test_case(Ty::AlwaysFalsy, Ty::AlwaysTruthy)]
#[test_case(Ty::Tuple(vec![]), Ty::TypingLiteral)]
#[test_case(Ty::TypingLiteral, Ty::SubclassOfBuiltinClass("object"))]
fn is_disjoint_from(a: Ty, b: Ty) {
let db = setup_db();
let a = a.into_type(&db);
let b = b.into_type(&db);
assert!(a.is_disjoint_from(&db, b));
assert!(b.is_disjoint_from(&db, a));
}
#[test_case(Ty::Any, Ty::BuiltinInstance("int"))]
#[test_case(Ty::None, Ty::None)]
#[test_case(Ty::None, Ty::BuiltinInstance("object"))]
#[test_case(Ty::BuiltinInstance("int"), Ty::BuiltinInstance("int"))]
#[test_case(Ty::BuiltinInstance("str"), Ty::LiteralString)]
#[test_case(Ty::BooleanLiteral(true), Ty::BooleanLiteral(true))]
#[test_case(Ty::BooleanLiteral(false), Ty::BooleanLiteral(false))]
#[test_case(Ty::BooleanLiteral(true), Ty::BuiltinInstance("bool"))]
#[test_case(Ty::BooleanLiteral(true), Ty::BuiltinInstance("int"))]
#[test_case(Ty::IntLiteral(1), Ty::IntLiteral(1))]
#[test_case(Ty::StringLiteral("a"), Ty::StringLiteral("a"))]
#[test_case(Ty::StringLiteral("a"), Ty::LiteralString)]
#[test_case(Ty::StringLiteral("a"), Ty::BuiltinInstance("str"))]
#[test_case(Ty::LiteralString, Ty::LiteralString)]
#[test_case(Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::IntLiteral(2))]
#[test_case(Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::Union(vec![Ty::IntLiteral(2), Ty::IntLiteral(3)]))]
#[test_case(Ty::Intersection{pos: vec![Ty::BuiltinInstance("int"), Ty::IntLiteral(2)], neg: vec![]}, Ty::IntLiteral(2))]
#[test_case(Ty::Tuple(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]), Ty::Tuple(vec![Ty::IntLiteral(1), Ty::BuiltinInstance("int")]))]
#[test_case(Ty::BuiltinClassLiteral("str"), Ty::BuiltinInstance("type"))]
#[test_case(Ty::BuiltinClassLiteral("str"), Ty::SubclassOfAny)]
#[test_case(Ty::AbcClassLiteral("ABC"), Ty::AbcInstance("ABCMeta"))]
#[test_case(Ty::BuiltinInstance("str"), Ty::AlwaysTruthy)]
#[test_case(Ty::BuiltinInstance("str"), Ty::AlwaysFalsy)]
fn is_not_disjoint_from(a: Ty, b: Ty) {
let db = setup_db();
let a = a.into_type(&db);
let b = b.into_type(&db);
assert!(!a.is_disjoint_from(&db, b));
assert!(!b.is_disjoint_from(&db, a));
}
#[test]
fn is_disjoint_from_union_of_class_types() {
let mut db = setup_db();
db.write_dedented(
"/src/module.py",
"
class A: ...
class B: ...
U = A if flag else B
",
)
.unwrap();
let module = ruff_db::files::system_path_to_file(&db, "/src/module.py").unwrap();
let type_a = super::global_symbol(&db, module, "A").expect_type();
let type_u = super::global_symbol(&db, module, "U").expect_type();
assert!(type_a.is_class_literal());
assert!(type_u.is_union());
assert!(!type_a.is_disjoint_from(&db, type_u));
}
#[test]
fn is_disjoint_type_subclass_of() {
let mut db = setup_db();
db.write_dedented(
"/src/module.py",
"
class A: ...
class B: ...
",
)
.unwrap();
let module = ruff_db::files::system_path_to_file(&db, "/src/module.py").unwrap();
let literal_a = super::global_symbol(&db, module, "A").expect_type();
let literal_b = super::global_symbol(&db, module, "B").expect_type();
let subclass_of_a = SubclassOfType::from(&db, literal_a.expect_class_literal().class);
let subclass_of_b = SubclassOfType::from(&db, literal_b.expect_class_literal().class);
// Class literals are always disjoint. They are singleton types
assert!(literal_a.is_disjoint_from(&db, literal_b));
// The class A is a subclass of A, so A is not disjoint from type[A]
assert!(!literal_a.is_disjoint_from(&db, subclass_of_a));
// The class A is disjoint from type[B] because it's not a subclass
// of B:
assert!(literal_a.is_disjoint_from(&db, subclass_of_b));
// However, type[A] is not disjoint from type[B], as there could be
// classes that inherit from both A and B:
assert!(!subclass_of_a.is_disjoint_from(&db, subclass_of_b));
}
#[test]
fn is_disjoint_module_literals() {
let mut db = setup_db();
db.write_dedented(
"/src/module.py",
"
import random
import math
",
)
.unwrap();
let module = ruff_db::files::system_path_to_file(&db, "/src/module.py").unwrap();
let module_literal_random = super::global_symbol(&db, module, "random").expect_type();
let module_literal_math = super::global_symbol(&db, module, "math").expect_type();
assert!(module_literal_random.is_disjoint_from(&db, module_literal_math));
assert!(!module_literal_random.is_disjoint_from(
&db,
Ty::KnownClassInstance(KnownClass::ModuleType).into_type(&db)
));
assert!(!module_literal_random.is_disjoint_from(
&db,
Ty::KnownClassInstance(KnownClass::Object).into_type(&db)
));
}
#[test]
fn is_disjoint_function_literals() {
let mut db = setup_db();
db.write_dedented(
"/src/module.py",
"
def f(): ...
def g(): ...
",
)
.unwrap();
let module = ruff_db::files::system_path_to_file(&db, "/src/module.py").unwrap();
let function_literal_f = super::global_symbol(&db, module, "f").expect_type();
let function_literal_g = super::global_symbol(&db, module, "g").expect_type();
assert!(function_literal_f.is_disjoint_from(&db, function_literal_g));
assert!(!function_literal_f.is_disjoint_from(
&db,
Ty::KnownClassInstance(KnownClass::FunctionType).into_type(&db)
));
assert!(!function_literal_f.is_disjoint_from(
&db,
Ty::KnownClassInstance(KnownClass::Object).into_type(&db)
));
}
/// Explicitly test for Python version <3.13 and >=3.13, to ensure that
/// the fallback to `typing_extensions` is working correctly.
/// See [`KnownClass::canonical_module`] for more information.

View file

@ -454,4 +454,12 @@ mod flaky {
.permutations(2)
.all(|vec_of_unions| vec_of_unions[0].is_equivalent_to(db, vec_of_unions[1]))
);
// `S | T` is always a supertype of `S`.
// Thus, `S` is never disjoint from `S | T`.
type_property_test!(
constituent_members_of_union_is_not_disjoint_from_that_union, db,
forall types s, t.
!s.is_disjoint_from(db, union(db, [s, t])) && !t.is_disjoint_from(db, union(db, [s, t]))
);
}