diff --git a/racket/src/cs/rumble/string.ss b/racket/src/cs/rumble/string.ss index 53441a12c0..dbf767d595 100644 --- a/racket/src/cs/rumble/string.ss +++ b/racket/src/cs/rumble/string.ss @@ -17,17 +17,30 @@ [(dest d-start src s-start) (string-copy! dest d-start src s-start (and (string? src) (string-length src)))] [(dest d-start src s-start s-end) - (check who mutable-string? :contract "(and/c string? (not/c immutable?))" dest) - (check who exact-nonnegative-integer? d-start) - (check who string? src) - (check who exact-nonnegative-integer? s-start) - (check who exact-nonnegative-integer? s-end) - (let ([d-len (string-length dest)]) - (check-range who "string" dest d-start #f d-len) - (check-range who "string" src s-start s-end (string-length src)) - (let ([s-len (fx- s-end s-start)]) - (check-space who "string" d-start d-len s-len) - (#%string-copy! src s-start dest d-start s-len)))])) + ;; start with fast, inlined checks for valid calls, then use + ;; slower tests with consistent reporting if fast tests fail + (cond + [(and (mutable-string? dest) + (string? src) + (fixnum? d-start) + (fixnum? s-start) + (fixnum? s-end) + (fx- s-end s-start) + (fx<= 0 d-start (fx+ d-start (fx- s-end s-start)) (string-length dest)) + (fx<= 0 s-start s-end (string-length src))) + (#%string-copy! src s-start dest d-start (fx- s-end s-start))] + [else + (check who mutable-string? :contract "(and/c string? (not/c immutable?))" dest) + (check who exact-nonnegative-integer? d-start) + (check who string? src) + (check who exact-nonnegative-integer? s-start) + (check who exact-nonnegative-integer? s-end) + (let ([d-len (string-length dest)]) + (check-range who "string" dest d-start #f d-len) + (check-range who "string" src s-start s-end (string-length src)) + (let ([s-len (fx- s-end s-start)]) + (check-space who "string" d-start d-len s-len) + (#%string-copy! src s-start dest d-start s-len)))])])) (define/who substring (case-lambda