Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2816884
add test case
dcreager Oct 21, 2025
e111e4e
add BDD graph display
dcreager Oct 17, 2025
0e26c7c
simplify individual clauses for display
dcreager Oct 17, 2025
db63d2a
don't simplify until time to display
dcreager Oct 17, 2025
c334ba6
simplify individual clauses last
dcreager Oct 17, 2025
dc76a71
normalize bounds
dcreager Oct 15, 2025
2a85ed6
order typevars near each other
dcreager Oct 16, 2025
ddb4ca4
clean up implies
dcreager Oct 21, 2025
8be58fc
clippy
dcreager Oct 21, 2025
86047f5
fix implies
dcreager Oct 21, 2025
671582a
remove implications first I guess?
dcreager Oct 21, 2025
be43f6c
dead_code not unused
dcreager Oct 21, 2025
a392d59
add normalization test
dcreager Oct 21, 2025
90460a8
mdformat
dcreager Oct 21, 2025
550c485
Apply suggestion from @AlexWaygood
dcreager Oct 21, 2025
f7ce95c
doc implies
dcreager Oct 21, 2025
dd674c6
def _ -> f
dcreager Oct 21, 2025
4920258
ordering comment
dcreager Oct 21, 2025
9fbec28
document display_graph
dcreager Oct 21, 2025
362a1a2
doc implies 2
dcreager Oct 21, 2025
ae00c34
move bdd ordering into a struct
dcreager Oct 21, 2025
ad54fc3
clippy!!1!!!1
dcreager Oct 21, 2025
c3520f5
typo
dcreager Oct 21, 2025
21f75eb
simplify constraint ordering
dcreager Oct 21, 2025
33816d6
render → display
dcreager Oct 21, 2025
5c1e038
Update crates/ty_python_semantic/src/types/constraints.rs
dcreager Oct 22, 2025
c5ff1fa
Update crates/ty_python_semantic/src/types/constraints.rs
dcreager Oct 22, 2025
9391e42
ordering method
dcreager Oct 22, 2025
86072f4
add snapshot test for graph output
dcreager Oct 22, 2025
2e4332e
clippy
dcreager Oct 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/ty_python_semantic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ ty_vendored = { workspace = true }
anyhow = { workspace = true }
dir-test = { workspace = true }
glob = { workspace = true }
indoc = { workspace = true }
insta = { workspace = true }
pretty_assertions = { workspace = true }
tempfile = { workspace = true }
quickcheck = { version = "1.0.3", default-features = false }
quickcheck_macros = { version = "1.0.0" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,40 @@ def _[T, U]() -> None:
# revealed: ty_extensions.ConstraintSet[always]
reveal_type(~union | union)
```

## Other simplifications

When displaying a constraint set, we transform the internal BDD representation into a DNF formula
(i.e., the logical OR of several clauses, each of which is the logical AND of several constraints).
This section contains several examples that show that we simplify the DNF formula as much as we can
before displaying it.

```py
from ty_extensions import range_constraint

def f[T, U]():
t1 = range_constraint(str, T, str)
t2 = range_constraint(bool, T, bool)
u1 = range_constraint(str, U, str)
u2 = range_constraint(bool, U, bool)

# revealed: ty_extensions.ConstraintSet[(T@f = bool) ∨ (T@f = str)]
reveal_type(t1 | t2)
# revealed: ty_extensions.ConstraintSet[(U@f = bool) ∨ (U@f = str)]
reveal_type(u1 | u2)
# revealed: ty_extensions.ConstraintSet[((T@f = bool) ∧ (U@f = bool)) ∨ ((T@f = bool) ∧ (U@f = str)) ∨ ((T@f = str) ∧ (U@f = bool)) ∨ ((T@f = str) ∧ (U@f = str))]
reveal_type((t1 | t2) & (u1 | u2))
```

The lower and upper bounds of a constraint are normalized, so that we equate unions and
intersections whose elements appear in different orders.

```py
from typing import Never

def f[T]():
# revealed: ty_extensions.ConstraintSet[(T@f ≤ int | str)]
reveal_type(range_constraint(Never, T, str | int))
# revealed: ty_extensions.ConstraintSet[(T@f ≤ int | str)]
reveal_type(range_constraint(Never, T, int | str))
```
5 changes: 5 additions & 0 deletions crates/ty_python_semantic/src/semantic_index/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ use crate::unpack::{Unpack, UnpackPosition};
/// because a new scope gets inserted before the `Definition` or a new place is inserted
/// before this `Definition`. However, the ID can be considered stable and it is okay to use
/// `Definition` in cross-module` salsa queries or as a field on other salsa tracked structs.
///
/// # Ordering
/// Ordering is based on the definition's salsa-assigned id and not on its values.
/// The id may change between runs, or when the definition was garbage collected and recreated.
#[salsa::tracked(debug, heap_size=ruff_memory_usage::heap_size)]
#[derive(Ord, PartialOrd)]
pub struct Definition<'db> {
/// The file in which the definition occurs.
pub file: File,
Expand Down
8 changes: 6 additions & 2 deletions crates/ty_python_semantic/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8430,7 +8430,9 @@ fn lazy_bound_or_constraints_cycle_initial<'db>(
}

/// Where a type variable is bound and usable.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, salsa::Update, get_size2::GetSize)]
#[derive(
Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, salsa::Update, get_size2::GetSize,
)]
pub enum BindingContext<'db> {
/// The definition of the generic class, function, or type alias that binds this typevar.
Definition(Definition<'db>),
Expand Down Expand Up @@ -8464,7 +8466,9 @@ impl<'db> BindingContext<'db> {
/// independent of the typevar's bounds or constraints. Two bound typevars have the same identity
/// if they represent the same logical typevar bound in the same context, even if their bounds
/// have been materialized differently.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize, salsa::Update)]
#[derive(
Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, get_size2::GetSize, salsa::Update,
)]
pub struct BoundTypeVarIdentity<'db> {
pub(crate) identity: TypeVarIdentity<'db>,
pub(crate) binding_context: BindingContext<'db>,
Expand Down
Loading