Skip to content

Commit f95056a

Browse files
committed
add some nice ascii art
1 parent d9ff400 commit f95056a

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

crates/ty_python_semantic/src/types/constraints.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,29 @@ impl<'db> AtomicConstraint<'db> {
492492
/// Panics if the two constraints have different typevars.
493493
fn intersect(self, db: &'db dyn Db, other: Self) -> IntersectionResult<AtomicConstraint<'db>> {
494494
debug_assert!(self.typevar == other.typevar);
495+
496+
// We'll show our work for each match arm with a case analysis. We calculate "min" using
497+
// intersection, and "max" using union.
498+
//
499+
// We use `s : t` for the positive constraint `s ≤: T ≤: t`, and draw it like this:
500+
//
501+
// s┠───┨t
502+
//
503+
// We use `¬(s : t)` for the corresponding negative constraint, and draw it like this:
504+
//
505+
// 0┠───┤s t├───┨1
506+
495507
match (self.sign, other.sign) {
508+
// When both constraints are positive, the result is always
509+
// max(s₁,s₂) : min(t₁,t₂)
510+
//
511+
// self: s₁┠─────┨t₁ s₁┠────┨t₁ s₁┠─┨t₁
512+
// other: s₂┠─┨t₂ s₂┠────┨t₂ s₂┠─┨t₂
513+
//
514+
// result: s₂┠─┨t₂ s₂┠─┨t₁ ∅
515+
//
516+
// Note that in the last case, max(s₁,s₂) ≥: min(t₁,t₂), which will get simplified to ∅
517+
// by the `positive` and `from_one` helpers.
496518
(ConstraintSign::Positive, ConstraintSign::Positive) => {
497519
IntersectionResult::from_one(Self::positive(
498520
db,
@@ -502,6 +524,20 @@ impl<'db> AtomicConstraint<'db> {
502524
))
503525
}
504526

527+
// When both constraints are negative, the result is always
528+
// ¬(min(s₁,s₂) : max(t₁,t₂)) ⊔ (min(t₁,t₂) : max(s₁,s₂))
529+
//
530+
// self: 0┠─┤s₁ t₁├─┨1 0┠───┤s₁ t₁├─┨1 0┠─┤s₁ t₁├─────────┨1
531+
// other: 0┠───┤s₂ t₂├───┨1 0┠─┤s₂ t₂├───┨1 0┠─────────┤s₂ t₂├─┨1
532+
//
533+
// result: 0┠─┤s₁ t₁├─┨1 0┠─┤s₂ t₁├─┨1 0┠─┤s₁ t₂├─┨1
534+
// ∅ ∅ t₁├─┤s₂
535+
//
536+
// Note that in the first two cases, min(t₁,t₂) ≥: max(s₁,s₂), which will get
537+
// simplified to ∅ by the `positive` and `from_two` helpers.
538+
//
539+
// TODO: Oof, the positive constraint in the final example should have open lower and
540+
// upper bounds, not closed... (i.e, t₁ < T < s₂, not t₁ ≤ T ≤ s₂)
505541
(ConstraintSign::Negative, ConstraintSign::Negative) => IntersectionResult::from_two(
506542
Self::negative(
507543
db,
@@ -517,6 +553,20 @@ impl<'db> AtomicConstraint<'db> {
517553
),
518554
),
519555

556+
// When one constraint is positive and the other negative, the result is always
557+
// (s₊ : min(s₋, t₊)) ⊔ (max(s₊,t₋) : t₊)
558+
//
559+
// self: s₊┠─────────┨t₊ s₊┠─┨t₊ s₊┠───┨t₊
560+
// other: 0┠────┤s₋ t₋├────┨1 0┠──┤s₋ t₋├──┨1 0┠────┤s₋ t₋├──┨1
561+
//
562+
// result: s₊┠─┤s₋ ∅ s₊┠─┤s₋
563+
// t₋├─┨t₊ ∅ ∅
564+
//
565+
// self: s₊┠───┨t₊ s₊┠─┨t₊ s₊┠─┨t₊
566+
// other: 0┠──┤s₋ t₋├────┨1 0┠───────┤s₋ t₋├─┨1 0┠─┤s₋ t₋├───────┨1
567+
//
568+
// result: ∅ s₊┠─┨t₊ ∅
569+
// t₋├─┨t₊ ∅ s₊┠─┨t₊
520570
(ConstraintSign::Positive, ConstraintSign::Negative) => IntersectionResult::from_two(
521571
Self::positive(
522572
db,
@@ -531,7 +581,6 @@ impl<'db> AtomicConstraint<'db> {
531581
self.upper,
532582
),
533583
),
534-
535584
(ConstraintSign::Negative, ConstraintSign::Positive) => IntersectionResult::from_two(
536585
Self::positive(
537586
db,

0 commit comments

Comments
 (0)