@@ -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