Hi. I am trying to use drracket's syntactic test suite coverage.
It always marks expressions in functions with optional arguments (see the screenshot).
Can I make drracket test coverage to ignore these lines?
This looks like a bug to me.
The expression (func)
calls func
without keyword arguments, so the default expressions 100, 200, and, #t
are used. Therefore the tool shouldn't color them black.
It looks to me like this problem is specific to keyword arguments; when using other default arguments, the coloring appears correct. So, for example,
#lang racket
(define (f [x 99])
(+ x 1234))
(f)
results in full coverage.
File a bug report?
It also looks like it's limited to keyword argument functions that are directly applied:
#lang racket/base
(define (f [x 42])
x)
(f)
(define (g #:x [x 42])
x)
(g) ;<-- actually a macro invocation
(apply g '()) ;<-- actually runtime; now "42" is shown as used
The expansion of f
is not much more than case-lambda
.
The expansion of g
is... fairly complicated. It looks like g
is defined as a runtime function value -- but also an g
is defined as a syntax transformer, for expansion time. Probably an optimization? Anyway in that case 42
seems truly not to be used, at runtime... or something like that?
(module anonymous-module racket/base (#%module-begin (module configure-runtime '#%kernel (#%module-begin (#%require racket/runtime-config) (#%app configure (quote #f)))) (define-values (f) (let-values (((f) (lambda (x1) (let-values (((x) (if (quote #f) (quote 42) x1))) (let-values () x))))) (case-lambda [() (#%app f (quote 42))] [(x1) (#%app f x1)]))) (#%app call-with-values (lambda () (#%app f)) print-values) (define-syntaxes (g) (#%app make-keyword-syntax (lambda () (#%app values (quote-syntax g) (quote-syntax g4))) (quote 0) '() (quote #f) '() '((#:x x2:18 x3:19 #f 42)))) (define-values:20 (g) (lambda (x2:18) (let-values:21 (((x) (if:22 (quote #f) (quote 42) x2:18))) (let-values:23 () x)))) (define-values:24 (g:25) (lambda (given-kws given-args) (let-values:26 (((x3:19) (#%app:27 pair?:27 given-kws))) (let-values:28 (((x2:18) (if:27 x3:19 (#%app:27 car:27 given-args) (quote 42)))) (#%app g x2:18))))) (define-values:29 (g4) (#%app make-optional-keyword-procedure (lambda (given-kws given-argc) (if:30 (#%app:31 =:31 given-argc (quote 2)) (let-values:32 (((l125477:33) given-kws)) (let-values:34 (((l125477:33) (if:33 (#%app:33 null?:33 l125477:33) l125477:33 (if:33 (#%app:33 eq?:33 (#%app:33 car:33 l125477:33) '#:x) (#%app:33 cdr:33 l125477:33) l125477:33)))) (#%app:35 null?:35 l125477:33))) (quote #f))) (case-lambda:36 [(given-kws given-args) (#%app:36 g:25 given-kws given-args)]) null '(#:x) (case-lambda:37 [() (#%app:37 g:25 null null)]))) (#%app:38 call-with-values:38 (lambda:38 () (let-values:39 () (if:40 (#%app:40 variable-reference-constant?:40 (#%variable-reference:40 g4:41)) (#%app:40 g:42 (quote 42)) (#%app:40 g4:41)))) print-values:38) (#%app:43 call-with-values:43 (lambda:43 () (#%app:44 apply:45 g4:46 '())) print-values:43)))
Not looking at the keyword implementation directly but just trying examples it also looks like an optimization to me. While this program shows the 42
as uncovered:
#lang racket
(define (g #:x [x 3])
x)
(g)
This program doesn't:
#lang racket
(define (g #:x [x (+ 41 1)])
x)
(g)
I wonder if one of the quoted 42
s in the fully expanded form needs to have the source location of the constant put onto it?
Ah, that could be it. In the expansion of the direct (g)
, here:
(#%app:38
call-with-values:38
(lambda:38 ()
(let-values:39 ()
(if:40 (#%app:40 variable-reference-constant?:40 (#%variable-reference:40 g4:41))
(#%app:40 g:42 (quote 42))
(#%app:40 g4:41))))
print-values:38)
The 42
has srcloc in private/kw.rkt, not in the user program.
Right, what seems to happen is that the default value is stored in make-keyword-syntax
as a value rather than a syntax object, and so there's no syntax location to re-use. I'm not sure how difficult it would be to change that to using a syntax object instead. The comment on line 1380 of racket/private/kw.rkt suggests that @mflatt thought about at least some aspects of this previously.
I've pushed a repair. Thanks, everyone, for reporting and tracking down the problem.