Ticket #1113 (assigned defect)

Opened 7 months ago

Last modified 7 months ago

defstruct types aren't properly recognized by subsequent forms

Reported by: stassats Owned by: gb
Priority: normal Milestone:
Component: ANSI CL Compliance Version: trunk
Keywords: Cc:



(defstruct a-type)
(defun b ()
  (the a-type t))

Error: Unknown type specifier: A-TYPE While executing: CCL::%%TYPEP, in process listener(1). Type :GO to continue, :POP to abort, :R for a list of available restarts.

CLHS says: If a defstruct form appears as a top level form, the compiler must make the structure type name recognized as a valid type name in subsequent declarations (as for deftype) and make the structure slot readers known to setf. Compiling

(defstruct a-type)
(defun b ()
  (the a-type t))

Change History

comment:1 Changed 7 months ago by gb

  • Owner set to gb
  • Status changed from new to assigned

I don't know. At the very least your example deserves a pretty stern warning (since T pretty clearly can't be an A-TYPE), but whether your example's correct or not there's clearly a bug here. Another way of demonstrating that bug is:

(defun odd-integer-p (x) (if (typep x 'integer) (oddp x)))
(deftype odd-integer () `(satisfies odd-integer-p))
(defun foo (x) (the odd-integer x))
(defun bar (x) (the undefined-type x))
(defun baz () (the odd-integer 1))

Just as in the case of a type defined by DEFSTRUCT, the compiler can't warn about the use of ODD-INTEGER while compiling FOO; it could warn about the use of UNDEFINED-TYPE while compiling BAR. It can't tell at compile-time whether or not the constant 1 is of type ODD-INTEGER and it will error out while trying to do so; it should either not try or ignore the error in this case.

In your example, we can't tell at compile-time whether the constant T is of type A-TYPE or not (at least we can't tell that by calling TYPEP at compile-time; we could know that A-TYPE will define a structure type and that T couldn't possibly be an instance of that type.)

At some optimization settings, THE can perform runtime typechecking and I think that this bug was likely introduced in response to a complaint that that runtime typechecking was too slow to be usable. The test case in that complaint involved code that did a lot of things like:

   (the fixnum 1)

and recognizing that that case never needed to check that 1 was indeed a FIXNUM by testing the constant at compile-time can't hurt anything and helped in that case. (Again, the bug isn't that types defined by DEFSTRUCT aren't recognized as being valid even though they aren't yet defined, it's that they're being treated as if they're defined at compile time when in fact they aren't.)

comment:2 Changed 7 months ago by stassats

This is of course not the actual code, just a reduced test case. The original crash came from (the (or a-type symbol) t)

Note: See TracTickets for help on using tickets.