Coverage not displayed for keyword parameters with -p symbol

Bug #1858373 reported by Paul F. Dietz
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
New
Undecided
Douglas Katzman

Bug Description

Compile and load file containing this, with coverage enabled:

(in-package :cl-user)

(defun f (&key (foo 'a) (bar nil bar-p))
  (list foo bar bar-p))

Turn coverage off.

Then, call f with these parameters:

(f) ==> (A NIL NIL)
(f :foo 1) ==> (1 NIL NIL)
(f :bar t) ==> (A T T)
(f :foo 2 :bar t) ==> (2 T T)

Then, dump coverage with sb-cover:report. The page for this file will show (bar nil bar-p) in read, even though it has been exercised by these calls.

description: updated
description: updated
Douglas Katzman (dougk)
Changed in sbcl:
assignee: nobody → Douglas Katzman (dougk)
Revision history for this message
Douglas Katzman (dougk) wrote :

this may have been a behavior change due to https://sourceforge.net/p/sbcl/sbcl/ci/cda1117f9e34ef323000f7e9be513f41a6997d1b/
however the effect of calling F prior to that change is arguably wrong in a different way,
and I didn't determine that this change per se was the cause.

Coverage of the binding form itself should not show an unreached expression as covered, yet when I evaluate (f :foo 1 :bar 2) in a fresh image, and _ONLY_ that expression, and not the prior expressions that allowed FOO or BAR to take the respective default, I see a fully green line for this: (defun f (&key (foo 'a) (bar nil bar-p))

That's technically wrong because the expression 'A for FOO was never used, nor was the NIL for BAR. However, the way we compile keyword defaulting expressions allows us to plug in constants when they don't matter; then we can simply stomp over whatever value is currently in a given location (for FOO,BAR) with whatever value was passed by the caller.
So we somewhat arbitrarily deem that the initial values _were_ used.
We adopt a different strategy (per lambda variable) when the defaulting expression is non-constant though. If I change the defun to:
  (defun f (&key (foo (get-foo)) (bar (get-bar) bar-p))
and then eval the same call, GET-FOO and GET-BAR both show up as red, which is right, because we never reached them; and this further calls attention to the former behavior being somewhat suspicious. Perhaps one could also argue that all constants are always "reached" which seems to be the stance taken by the former logic. On top of this, for "reasons", we change the way evaluation happens when a supplied-p var - (BAR-P) in the example - is present. As to whether the symbol BAR-P should be red or green, I think we need another color for dont-care. The value stuffed in for the binding is the thing reached, i.e. an implicit T or NIL. The symbol itself is not evaluable code as such.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.