user3414663
user3414663

Reputation: 583

Suppress style-warning on make-instance in sbcl

I have two packages with a class defined in each. The second class inherits from the first but has a slot of the same name. The intention is indeed to override the slot.

(defpackage :foo
  (:use :cl)
  (:export foo))

(in-package :foo)

(defclass foo () ((s)))

(defpackage :bar
  (:use :cl :foo)
  (:export bar))

(in-package :bar)

(defclass bar (foo) ((s)))

sbcl gives a helpful warning when I make an instance of bar

(make-instance 'bar)

STYLE-WARNING:
   slot names with the same SYMBOL-NAME but different SYMBOL-PACKAGE (possible
   package problem) for class #<STANDARD-CLASS BAR:BAR>:
       (FOO::S BAR::S)

Since it is the intended behaviour, I can suppress that warning like this:

(handler-bind (#+SBCL (style-warning #'muffle-warning))
  (make-instance 'bar))

However I would like users of the bar class to be able to make instances without getting the warning.

I could write a wrapper function containing the code in the previous code block but is it possible to suppress the warning in advance of calls to (make-instance 'bar) without muffling all style warnings?

Upvotes: 1

Views: 421

Answers (2)

coredump
coredump

Reputation: 38967

It seems the warning was useful here, but if you find yourself in a situation where you have to muffle it, the appropriate place would be around class finalization:

#+sbcl
(defmethod sb-mop:finalize-inheritance :around ((c (eql (find-class 'bar))))
   (handler-bind ((sb-int:simple-style-warning #'muffle-warning))
     (call-next-method)))

You had an error when making a new instance, but when I tested the code the error was signaled when defining the class in the REPL. This is a clue that the error is being signaled during class finalization, which has to be done after defclass (but not necessarily immediately after), and before allocating the first instance. See Class finalization protocol:

The exact point at which finalize-inheritance is called depends on the class of the class metaobject; for standard-class it is called sometime after all the superclasses of the class are defined, but no later than when the first instance of the class is allocated (by allocate-instance).

Upvotes: 2

jkiiski
jkiiski

Reputation: 8421

Symbols in Common Lisp usually belong to a package. When the Lisp reader encounters a new symbol, it will put it in the current package (set by IN-PACKAGE), unless a symbol with the same name has been imported from elsewhere. A symbol can be written with the package name by putting a colon between the package and the symbol name (or two colons for internal symbols).

If we add the package prefixes to your code, as the Lisp reader sees them, the error becomes easy to see:

(cl:defpackage keyword:foo
  (keyword:use keyword:cl)
  (keyword:export cl-user::foo)) ;Makes FOO:FOO an external symbol, which will be 
                                 ; imported with the (:USE ... :FOO) below.
(cl:in-package keyword:foo)

(cl:defclass foo:foo () ((foo::s))) ;FOO::S is not exported, so it 
                                    ; is an internal symbol. It will 
                                    ; not be imported by the :USE-clause.

(cl:defpackage keyword:bar
  (keyword:use keyword:cl keyword:foo) ;Import all external symbols from CL and FOO.
  (keyword:export cl-user::bar))

(cl:in-package keyword:bar)

(cl:defclass bar:bar (foo:foo) ;FOO:FOO was imported from the other package.
  ((bar::s))) ;FOO::S (an internal symbol) wasn't imported, so a new
              ; symbol was interned in BAR.

The class BAR:BAR actually has two slots, FOO::S and BAR::S. The slot names have the same SYMBOL-NAME, but a different SYMBOL-PACKAGE. This is rarely what the programmer intended, so SBCL gives a warning about it. To solve the problem, you should export FOO::S, so that writing unqualified S in the package BAR will refer to the same symbol. Alternatively you could write the slot name in the package qualified form, but using internal symbols of other packages is usually not recommended.

Upvotes: 4

Related Questions