diff --git a/collects/racket/private/generic.rkt b/collects/racket/private/generic.rkt index e8e153811c..7d29c5df3a 100644 --- a/collects/racket/private/generic.rkt +++ b/collects/racket/private/generic.rkt @@ -4,7 +4,8 @@ racket/local racket/syntax syntax/stx) - (only-in "define-struct.rkt" define/generic)) + (only-in "define-struct.rkt" define/generic) + (only-in racket/function arity-includes?)) (define-for-syntax (keyword-stx? v) (keyword? (syntax->datum v))) @@ -136,7 +137,20 @@ (let*-values ([(p) (lambda fake-args #f)] [(generic-arity-spec) (procedure-arity p)] [(generic-required-kws generic-allowed-kws) (procedure-keywords p)]) - (lambda (f) + (lambda (method-name f) + (unless (procedure? f) + (raise-arguments-error + 'name + "generic method definition is not a function" + "method" method-name + "given" f)) + (unless (arity-includes? (procedure-arity f) generic-arity-spec) + (raise-arguments-error + 'name + "method definition has an incorrect arity" + "method" method-name + "given arity" (procedure-arity f) + "expected arity" generic-arity-spec)) (procedure-reduce-keyword-arity f generic-arity-spec generic-required-kws generic-allowed-kws)))) ... #,@(if prop-defined-already? @@ -159,7 +173,7 @@ (vector-length generic-vector))) (vector (let ([mthd-generic (vector-ref generic-vector generic-idx)]) (and mthd-generic - (generic-arity-coerce mthd-generic))) + (generic-arity-coerce 'generic mthd-generic))) ...)) null #t)) ;; overrides the interface predicate so that any of the default @@ -185,6 +199,7 @@ ;; Define generic functions (define generic (generic-arity-coerce + 'generic (make-keyword-procedure (lambda (kws kws-args . given-args) (define this (list-ref given-args generic-this-idx)) diff --git a/collects/tests/generic/errors.rkt b/collects/tests/generic/errors.rkt index 062e203492..d82faf7baa 100644 --- a/collects/tests/generic/errors.rkt +++ b/collects/tests/generic/errors.rkt @@ -11,4 +11,33 @@ (check-exn #rx"not a name for a generics group" (lambda () (convert-compile-time-error (struct foo () #:methods bad)))) + (check-exn #rx"method definition has an incorrect arity" + (lambda () (convert-compile-time-error + (let () + (define-generics foobar + [foo foobar x]) + (struct inst () + #:methods gen:foobar + [(define (foo) 0)]) + 'ignore)))) + (check-exn #rx"method definition has an incorrect arity" + (lambda () (convert-compile-time-error + (let () + (define-generics foobar + [foo foobar x] + [bar foobar x]) + (struct inst () + #:methods gen:foobar + [(define (foo foobar x) 0) + (define (bar foobar) 1)]) + 'ignore)))) + (check-exn #rx"generic method definition is not a function" + (lambda () (convert-compile-time-error + (let () + (define-generics foobar + [foo foobar x]) + (struct inst () + #:methods gen:foobar + [(define foo 0)]) + 'ignore)))) )