diff --git a/pkgs/racket-test-core/tests/racket/will.rktl b/pkgs/racket-test-core/tests/racket/will.rktl index c1289ee189..ecf0e333b0 100644 --- a/pkgs/racket-test-core/tests/racket/will.rktl +++ b/pkgs/racket-test-core/tests/racket/will.rktl @@ -257,6 +257,38 @@ (for ([t thds]) (kill-thread t))) +;; ---------------------------------------- +;; Check that an unoptimizable `(variable-reference-constant? (#%variable-reference r))` +;; expression does not retain a reference to the namespace --- since not retaining +;; a reference can be important to the expansion to a call to a keyword-accepting +;; function. + +(when (eq? '3m (system-type 'gc)) + (define (mk) + (parameterize ([current-namespace (make-base-namespace)]) + (eval '(module module-with-unoptimized-varref-constant racket/base + (define (r) + (variable-reference-constant? + (#%variable-reference r))) + (define top (box 1)) + (define top-boxed (make-weak-box top)) + (set! r r) + (provide r top-boxed))) + (list (dynamic-require ''module-with-unoptimized-varref-constant 'r) + (dynamic-require ''module-with-unoptimized-varref-constant 'top-boxed)))) + + (let ([l (for/list ([i 10]) + (mk))]) + (collect-garbage) + (define fraction-retained + (/ (for/fold ([n 0]) ([p (in-list l)]) + (if (weak-box-value (cadr p)) + (add1 n) + n)) + (for/fold ([n 0]) ([p (in-list l)]) + (if (car p) (add1 n) n)))) + (test #t < fraction-retained 1/2))) + ;; ---------------------------------------- (report-errs) diff --git a/racket/src/racket/src/compile.c b/racket/src/racket/src/compile.c index e25920f613..89d9deea0a 100644 --- a/racket/src/racket/src/compile.c +++ b/racket/src/racket/src/compile.c @@ -1351,7 +1351,7 @@ ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec, /* retaining `dummy' ensures that the environment stays linked from the actual variable */ - if (rec[drec].comp) + if (rec[drec].comp && ((l == 1) || !rec[drec].testing_constantness)) dummy = scheme_make_environment_dummy(env); else dummy = NULL; @@ -1433,6 +1433,7 @@ ref_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec, o = scheme_alloc_object(); o->type = scheme_varref_form_type; SCHEME_PTR1_VAL(o) = (Scheme_Object *)var; + if (!dummy) dummy = scheme_false; SCHEME_PTR2_VAL(o) = (Scheme_Object *)dummy; return o; } else {