diff --git a/collects/data/queue.rkt b/collects/data/queue.rkt index 6095f4a20c..0441541439 100644 --- a/collects/data/queue.rkt +++ b/collects/data/queue.rkt @@ -30,8 +30,13 @@ (define (dequeue! q) (unless (queue? q) (raise-type-error dequeue! "queue" 0 q)) (let ([old (queue-head q)]) - (unless old (error 'dequeue! "empty queue")) - (set-queue-head! q (link-tail old)) + (unless old (raise-type-error 'dequeue! "non-empty queue" 0 q)) + (cond + [(eq? old (queue-tail q)) + (set-queue-tail! q #f) + (set-queue-head! q #f)] + [else + (set-queue-head! q (link-tail old))]) (link-value old))) (define (queue->list queue) diff --git a/collects/tests/data/queue.rkt b/collects/tests/data/queue.rkt index 1a306cd04f..69bd421f3e 100644 --- a/collects/tests/data/queue.rkt +++ b/collects/tests/data/queue.rkt @@ -63,7 +63,19 @@ (enqueue! q 2) (check-equal? (dequeue! q) 1) (check-equal? (dequeue! q) 2) - (check-exn exn:fail? (lambda () (dequeue! q)))))) + (check-exn exn:fail? (lambda () (dequeue! q))))) + (test-case "don't leak last element" + (let* ([thing (box 'box-that-queue-should-not-hold-onto)] + [wb (make-weak-box thing)] + [q (make-queue)]) + (enqueue! q thing) + (set! thing #f) + (dequeue! q) + (collect-garbage) + (check-false (weak-box-value wb)) + ;; need a reference to 'q' after looking in the + ;; box or else the whole queue gets collected + (check-true (queue? q))))) (test-suite "queue misc" (test-case "queue as a sequence" (let ([queue (make-queue)])