diff --git a/pkgs/racket-test-core/tests/racket/basic.rktl b/pkgs/racket-test-core/tests/racket/basic.rktl index 13d0210b2b..6eb15b5077 100644 --- a/pkgs/racket-test-core/tests/racket/basic.rktl +++ b/pkgs/racket-test-core/tests/racket/basic.rktl @@ -732,6 +732,13 @@ (err/rt-test (read (open-input-string "#1234567890(0)")) exn:fail:out-of-memory?)) (test #t vector? (make-vector 0)) +(let ([b (vector 1 2 3)]) + (vector-copy! b 0 b 1) + (test '#(2 3 3) values b)) +(let ([b (vector 2 3 4)]) + (vector-copy! b 1 b 0 2) + (test '#(2 2 3) values b)) + (define f (make-string 3 #\*)) (test "?**" 'string-set! (begin (string-set! f 0 #\?) f)) (arity-test string-set! 3 3) diff --git a/pkgs/racket-test-core/tests/racket/chaperone.rktl b/pkgs/racket-test-core/tests/racket/chaperone.rktl index 9daffd02ac..f6c740f80a 100644 --- a/pkgs/racket-test-core/tests/racket/chaperone.rktl +++ b/pkgs/racket-test-core/tests/racket/chaperone.rktl @@ -223,6 +223,20 @@ (define-values (a b c) (vector->values b2)) (test '(1 2 3) list a b c))) +;; vector-copy! and chaperones +(let ([b (vector 1 2 3)]) + (let ([b2 (impersonate-vector b + (lambda (b i v) v) + (lambda (b i v) v))]) + (vector-copy! b 0 b2 1) + (test '#(2 3 3) values b))) +(let ([b (vector 2 3 4)]) + (let ([b2 (impersonate-vector b + (lambda (b i v) v) + (lambda (b i v) v))]) + (vector-copy! b 1 b2 0 2) + (test '#(2 2 3) values b))) + (define unsafe-chaperone-vector-name "unsafe-chaperone-vector") (define unsafe-impersonate-vector-name "unsafe-impersonate-vector") (define chaperone-vector*-name "chaperone-vector*") diff --git a/racket/src/racket/src/vector.c b/racket/src/racket/src/vector.c index 5ef93fb5c0..ef89019bd1 100644 --- a/racket/src/racket/src/vector.c +++ b/racket/src/racket/src/vector.c @@ -825,8 +825,19 @@ static Scheme_Object *vector_copy_bang(int argc, Scheme_Object *argv[]) if (slow) { int i, o; - for (i = istart, o = ostart; i < ifinish; i++, o++) { - scheme_chaperone_vector_set(argv[0], o, scheme_chaperone_vector_ref(argv[2], i)); + if ((s2 == s1) + && (((istart <= ostart) && (ifinish > ostart)) + || ((ostart <= istart) && (ofinish > istart))) + && (istart < ostart)) { + /* ranges overlap and shifting up: copy from end */ + for (i = ifinish, o = ofinish; i-- > istart; ) { + o--; + scheme_chaperone_vector_set(argv[0], o, scheme_chaperone_vector_ref(argv[2], i)); + } + } else { + for (i = istart, o = ostart; i < ifinish; i++, o++) { + scheme_chaperone_vector_set(argv[0], o, scheme_chaperone_vector_ref(argv[2], i)); + } } } else { memmove(SCHEME_VEC_ELS(s1) + ostart,