Skip to content

Raise visibility of errors in back-end provers  #433

@lemmy

Description

@lemmy

The TLA+ specs below causes a Queue.nth: internal error in the SMT back-end (TLAPS 1.4.5). Compared to the visibility of the error with TLAPS 1.4.3, the error is easy to miss. A proper fix would be to increase the visibility of the error in the Toolbox (dialog, high-lighting, ...).

TLAPS1 4 5backenderror

TLAPS1 4 3

---------------------- MODULE BlockingQueueFairMinimal ----------------------
EXTENDS Naturals, Sequences, FiniteSets, TLAPS

Range(f) == { f[x] : x \in DOMAIN f }

IsInjective(s) == \A i, j \in DOMAIN s: (s[i] = s[j]) => (i = j)

CONSTANTS Producers,   (* the (nonempty) set of producers                       *)
          Consumers,   (* the (nonempty) set of consumers                       *)
          BufCapacity  (* the maximum number of messages in the bounded buffer  *)

ASSUME Assumption ==
       /\ Producers # {}                      (* at least one producer *)
       /\ Consumers # {}                      (* at least one consumer *)
       /\ Producers \intersect Consumers = {} (* no thread is both consumer and producer *)
       /\ BufCapacity \in (Nat \ {0})         (* buffer capacity is at least 1 *)
       
-----------------------------------------------------------------------------

VARIABLES buffer, waitSeqC, waitSeqP
vars == <<buffer, waitSeqC, waitSeqP>>

WaitingThreads == Range(waitSeqC) \cup Range(waitSeqP)

RunningThreads == (Producers \cup Consumers) \ WaitingThreads

NotifyOther(ws) ==
            \/ /\ ws = <<>>
               /\ UNCHANGED ws
            \/ /\ ws # <<>>
               /\ ws' = Tail(ws)

(* @see java.lang.Object#wait *)
Wait(ws, t) == 
            /\ ws # <<>>
            /\ ws' = ws \o <<t>>
            /\ UNCHANGED <<buffer>>
           
-----------------------------------------------------------------------------

Put(t, d) ==
/\ t \notin Range(waitSeqP)
/\ \/ 
      /\ Len(buffer) < BufCapacity
      /\ buffer' = Append(buffer, d)
      /\ NotifyOther(waitSeqC)
      /\ UNCHANGED waitSeqP
   \/ /\ Len(buffer) = BufCapacity
      /\ Wait(waitSeqP, t)
      /\ UNCHANGED waitSeqC
      
Get(t) ==
/\ t \notin Range(waitSeqC)
/\ \/ /\ buffer # <<>>
      /\ buffer' = Tail(buffer)
      /\ NotifyOther(waitSeqP)
      /\ UNCHANGED waitSeqC
   \/ /\ buffer = <<>>
      /\ Wait(waitSeqC, t)
      /\ UNCHANGED waitSeqP

-----------------------------------------------------------------------------

Init == /\ buffer = <<>>
        /\ waitSeqC = <<>>
        /\ waitSeqP = <<>>

Next == \/ \E p \in Producers: Put(p, p) \* Add some data to buffer
        \/ \E c \in Consumers: Get(c)

Spec == Init /\ [][Next]_vars 

----------------

BQS == INSTANCE BlockingQueueSplit WITH waitSetC <- Range(waitSeqC), 
                                        waitSetP <- Range(waitSeqP)

TypeInv == /\ Len(buffer) \in 0..BufCapacity
           /\ waitSeqP \in Seq(Producers)
           /\ IsInjective(waitSeqP)
           /\ waitSeqC \in Seq(Consumers)
           /\ IsInjective(waitSeqC)

-----------------------------------------------------------------------------

THEOREM Spec => BQS!Spec
<1> USE Assumption, BQS!Assumption
<1>1. Init => BQS!Init 
<1>2. TypeInv /\ [Next]_vars => [BQS!Next]_BQS!vars
  <2> USE DEF BQS!Next, BQS!vars
  <2> SUFFICES ASSUME TypeInv,
                      [Next]_vars
               PROVE  [BQS!Next]_BQS!vars
    OBVIOUS
  <2>1. ASSUME NEW p \in Producers,
               Put(p, p)
        PROVE  [BQS!Next]_BQS!vars
    <3>1. CASE       /\ Len(buffer) < BufCapacity
                     /\ buffer' = Append(buffer, p)
                     /\ NotifyOther(waitSeqC)
                     /\ UNCHANGED waitSeqP
      <4>1. CASE /\ waitSeqC = <<>>
                 /\ UNCHANGED waitSeqC
      <4>2. CASE /\ waitSeqC # <<>>
                 /\ waitSeqC' = Tail(waitSeqC)
        BY SMT, <4>2, <2>1, <3>1, 
           BQS!ITypeInv \* This causes a "Queue.nth: internal error"
        DEF Put, NotifyOther,
            BQS!Put, BQS!NotifyOther, Range,
            BQS!TypeInv \* This causes a "Queue.nth: internal error"
      <4>3. QED
    <3>2. QED
  <2>2. ASSUME NEW c \in Consumers,
               Get(c)
        PROVE  [BQS!Next]_BQS!vars
  <2>3. CASE UNCHANGED vars
  <2>4. QED
<1>3. QED

===============
--------------------- MODULE BlockingQueueSplitMinimal ---------------------
EXTENDS Naturals, Sequences, FiniteSets, TLAPS

CONSTANTS Producers,   (* the (nonempty) set of producers                       *)
          Consumers,   (* the (nonempty) set of consumers                       *)
          BufCapacity  (* the maximum number of messages in the bounded buffer  *)

ASSUME Assumption ==
       /\ Producers # {}                      (* at least one producer *)
       /\ Consumers # {}                      (* at least one consumer *)
       /\ Producers \intersect Consumers = {} (* no thread is both consumer and producer *)
       /\ BufCapacity \in (Nat \ {0})         (* buffer capacity is at least 1 *)
       
VARIABLES buffer, waitSetC, waitSetP
vars == <<buffer, waitSetC, waitSetP>>

RunningThreads == (Producers \cup Consumers) \ (waitSetC \cup waitSetP)

NotifyOther(ws) == 
         \/ /\ ws = {}
            /\ UNCHANGED ws
         \/ /\ ws # {}
            /\ \E x \in ws: ws' = ws \ {x}

Wait(ws, t) == /\ ws' = ws \cup {t}
               /\ UNCHANGED <<buffer>>
           
Put(t, d) ==
/\ t \notin waitSetP
/\ \/ /\ Len(buffer) < BufCapacity
      /\ buffer' = Append(buffer, d)
      /\ NotifyOther(waitSetC)
      /\ UNCHANGED waitSetP
   \/ /\ Len(buffer) = BufCapacity
      /\ Wait(waitSetP, t)
      /\ UNCHANGED waitSetC
      
Get(t) ==
/\ t \notin waitSetC
/\ \/ /\ buffer # <<>>
      /\ buffer' = Tail(buffer)
      /\ NotifyOther(waitSetP)
      /\ UNCHANGED waitSetC
   \/ /\ buffer = <<>>
      /\ Wait(waitSetC, t)
      /\ UNCHANGED waitSetP


TypeInv == /\ Len(buffer) \in 0..BufCapacity
           /\ waitSetP \in SUBSET Producers
           /\ waitSetC \in SUBSET Consumers

Init == /\ buffer = <<>>
        /\ waitSetC = {}
        /\ waitSetP = {}

Next == \/ \E p \in Producers: Put(p, p)
        \/ \E c \in Consumers: Get(c)

Spec == Init /\ [][Next]_vars

LEMMA ITypeInv == Spec => []TypeInv
<1> USE Assumption DEF TypeInv
<1>1. Init => TypeInv
  BY SMT DEF Init
<1>2. TypeInv /\ [Next]_vars => TypeInv'
  BY SMT DEF Next, vars, Put, Get, Wait, NotifyOther
<1>3. QED
  BY <1>1, <1>2, PTL DEF Spec

=============================================================================

Metadata

Metadata

Assignees

No one assigned

    Labels

    TLAPSToolbox functionality related to the TLA proof system/managerToolboxThe TLA Toolbox/IDEenhancementLets change things for the better

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions