diff --git a/pkgs/racket-doc/scribblings/foreign/types.scrbl b/pkgs/racket-doc/scribblings/foreign/types.scrbl index 5e671355f0..8f20fa5eb3 100644 --- a/pkgs/racket-doc/scribblings/foreign/types.scrbl +++ b/pkgs/racket-doc/scribblings/foreign/types.scrbl @@ -1016,7 +1016,7 @@ Examples: Creates a C pointer type, where @racket[mode] indicates input or output pointers (or both). The @racket[mode] can be one of the -following: +following (matched as a symbol independent of binding): @itemize[ @@ -1058,7 +1058,11 @@ following type: creates a function that calls the foreign function with a fresh integer pointer, and use the value that is placed there as a second -return value.} +return value. + +@history[#:changed "7.7.0.6" @elem{The modes @racket[i], @racket[o], + and @racket[io] match as symbols + instead of free identifiers.}]} @defform[(_box type)]{ @@ -1124,7 +1128,10 @@ return two values, the vector and the boolean. -> (values vec res)) ] -@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].}]} +@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].}] + #:changed "7.7.0.6" @elem{The modes @racket[i], @racket[o], + and @racket[io] match as symbols + instead of free identifiers.}]} @defform[(_vector mode type maybe-len maybe-mode)]{ @@ -1145,7 +1152,10 @@ Examples: See @racket[_list] for more explanation about the examples. -@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].}]} +@history[#:changed "7.7.0.2" @elem{Added @racket[maybe-mode].} + #:changed "7.7.0.6" @elem{The modes @racket[i], @racket[o], + and @racket[io] match as symbols + instead of free identifiers.}]} @defform*[#:id _bytes diff --git a/pkgs/racket-test-core/tests/racket/foreign-test.rktl b/pkgs/racket-test-core/tests/racket/foreign-test.rktl index 4d1884e271..632059fb0b 100644 --- a/pkgs/racket-test-core/tests/racket/foreign-test.rktl +++ b/pkgs/racket-test-core/tests/racket/foreign-test.rktl @@ -1145,6 +1145,22 @@ (define-serializable-cstruct _serializable-example-1 ([a _int])) (test 17 serializable-example-1-a (deserialize (serialize (make-serializable-example-1 17)))) +;; ---------------------------------------- +;; Check that `i`, `o`, and `io` are matched as symbols, not by binding: + +(let ([i 'no] + [o 'no] + [io 'no]) + (test #t ctype? (_ptr i _int)) + (test #t ctype? (_ptr o _int)) + (test #t ctype? (_ptr io _int)) + (test #t ctype? (_list i _int)) + (test #t ctype? (_list o _int 10)) + (test #t ctype? (_list io _int 10)) + (test #t ctype? (_vector i _int)) + (test #t ctype? (_vector o _int 10)) + (test #t ctype? (_vector io _int 10))) + ;; ---------------------------------------- (define-cpointer-type _foo) diff --git a/racket/collects/ffi/unsafe.rkt b/racket/collects/ffi/unsafe.rkt index 7c44a712dc..de34f80289 100644 --- a/racket/collects/ffi/unsafe.rkt +++ b/racket/collects/ffi/unsafe.rkt @@ -1054,13 +1054,19 @@ (define-fun-syntax _? (syntax-id-rules () [(_ . xs) ((type: #f) . xs)] [_ (type: #f)])) +(begin-for-syntax + (define-syntax-rule (syntax-rules/symbol-literals (lit ...) [pat tmpl] ...) + (lambda (stx) + (syntax-case* stx (lit ...) (lambda (a b) (eq? (syntax-e a) (syntax-e b))) + [pat (syntax-protect (syntax/loc stx tmpl))] ...)))) + ;; (_ptr ) ;; This is for pointers, where mode indicates input or output pointers (or ;; both). If the mode is `o' (output), then the wrapper will not get an ;; argument for it, instead it generates the matching argument. (provide _ptr) (define-fun-syntax _ptr - (syntax-rules (i o io) + (syntax-rules/symbol-literals (i o io) [(_ i t) (type: _pointer pre: (x => (let ([p (malloc t)]) (ptr-set! p t x) p)))] [(_ o t) (type: _pointer @@ -1090,7 +1096,7 @@ ;; the C function will most likely require. (provide _list) (define-fun-syntax _list - (syntax-rules (i o io) + (syntax-rules/symbol-literals (i o io) [(_ i t ) (type: _pointer pre: (x => (list->cblock x t)))] [(_ i t mode) (type: _pointer @@ -1112,7 +1118,7 @@ ;; Same as _list, except that it uses Scheme vectors. (provide _vector) (define-fun-syntax _vector - (syntax-rules (i o io) + (syntax-rules/symbol-literals (i o io) [(_ i t ) (type: _pointer pre: (x => (vector->cblock x t)))] [(_ i t mode) (type: _pointer