diff --git a/pkgs/racket-test-core/tests/racket/chaperone.rktl b/pkgs/racket-test-core/tests/racket/chaperone.rktl index 4af967da22..d206bb87d8 100644 --- a/pkgs/racket-test-core/tests/racket/chaperone.rktl +++ b/pkgs/racket-test-core/tests/racket/chaperone.rktl @@ -2583,6 +2583,19 @@ (struct b a (z w)) (test #t impersonator? (impersonate-struct (b 1 2 3 4) set-a-y! void))) +;; ---------------------------------------- +;; Make sure `struct->vector` doesnt' have memory-management issues +;; with impersonated structs: + +(let () + (struct s (x y z) #:mutable #:transparent) + (test #(struct:s 1 2 3) + struct->vector + (impersonate-struct (s 1 2 3) + s-x (lambda (s v) (collect-garbage 'minor) v) + s-y (lambda (s v) (collect-garbage 'minor) v) + s-z (lambda (s v) (collect-garbage 'minor) v)))) + ;; ---------------------------------------- (report-errs) diff --git a/racket/src/racket/src/struct.c b/racket/src/racket/src/struct.c index 7c8e9f0194..05df88dcde 100644 --- a/racket/src/racket/src/struct.c +++ b/racket/src/racket/src/struct.c @@ -3302,8 +3302,12 @@ Scheme_Object *scheme_struct_to_vector(Scheme_Object *_s, Scheme_Object *unknown --i; if (SAME_OBJ((Scheme_Object *)s, _s)) elem = s->slots[i]; - else + else { + /* scheme_struct_ref() may trigger a GC; see "BEWARE" above */ + array = NULL; elem = scheme_struct_ref(_s, i); + array = SCHEME_VEC_ELS(v); + } array[1 + (--m)] = elem; } }