From a255def01960a72d2c62be51251c1923a27da18d Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 17 Nov 2018 16:30:56 -0700 Subject: [PATCH] cs: fix state of module instance interrupted by error Closes #2380 --- pkgs/racket-test-core/tests/racket/module.rktl | 15 +++++++++++++++ racket/src/schemify/schemify.rkt | 17 ++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pkgs/racket-test-core/tests/racket/module.rktl b/pkgs/racket-test-core/tests/racket/module.rktl index ae5df56829..af438f2d76 100644 --- a/pkgs/racket-test-core/tests/racket/module.rktl +++ b/pkgs/racket-test-core/tests/racket/module.rktl @@ -2786,6 +2786,21 @@ case of module-leve bindings; it doesn't cover local bindings. 'module-begin (list #'module* #'stop)))) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Check state of a module-instance namespace when initialization +;; is interrupted by an error + +(module fails-after-f-and-before-g racket/base + (provide f g) + (define (f x) (error "boom")) + (f 42) + (define g (if (zero? (random 1)) 'ok 'oops))) + +(err/rt-test (dynamic-require ''fails-after-f-and-before-g #f) + (lambda (x) (and (exn:fail? x) + (regexp-match? #rx"boom" (exn-message x))))) +(test #t procedure? (eval 'f (module->namespace ''fails-after-f-and-before-g))) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/racket/src/schemify/schemify.rkt b/racket/src/schemify/schemify.rkt index 38d9c5dbfe..b62caf4bfb 100644 --- a/racket/src/schemify/schemify.rkt +++ b/racket/src/schemify/schemify.rkt @@ -188,12 +188,13 @@ (define schemified (let loop ([l l] [in-mut-l l] [accum-exprs null] [accum-ids null]) (define mut-l (update-mutated-state! l in-mut-l mutated)) + (define (make-set-variables) + (for/list ([id (in-list accum-ids)] + #:when (hash-ref exports id #f)) + (make-set-variable id exports knowns mutated))) (cond [(null? l) - (define set-vars - (for/list ([id (in-list accum-ids)] - #:when (hash-ref exports id #f)) - (make-set-variable id exports knowns mutated))) + (define set-vars (make-set-variables)) (cond [(null? set-vars) (cond @@ -234,7 +235,13 @@ [else (id-loop (wrap-cdr ids) accum-exprs (cons (unwrap (wrap-car ids)) accum-ids))]))))] [`,_ - (loop (wrap-cdr l) mut-l (cons schemified accum-exprs) accum-ids)])]))) + ;; In case `schemified` triggers an error, sync exported variables + (define set-vars (make-set-variables)) + (cond + [(null? set-vars) + (loop (wrap-cdr l) mut-l (cons schemified accum-exprs) null)] + [else + (loop (wrap-cdr l) mut-l (cons schemified (append (reverse set-vars) accum-exprs)) null)])])]))) ;; Return both schemified and known-binding information, where ;; the later is used for cross-linklet optimization (values schemified knowns mutated))