mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-18 17:40:37 +00:00
[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:
parent
d97502d647
commit
975d1457c5
3 changed files with 156 additions and 191 deletions
|
@ -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.
|
||||
|
|
|
@ -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]))
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue