None of the following sections apply to SBCL built without package locksing support.

The interface described here is experimental: incompatible changes in future SBCL releases are possible, even expected: most notably the consept of implementation packages and the associated operators may be renamed.

Package Lock Concepts
=====================

Package Locking Overview
------------------------

Package locks protect against unintentional modifications of a package: they provide similar protection to user packages as is mandated to common-lisp package by the ANSI specification. They are not, and should not be used as a security measure.

Newly created packages are by default unlocked (see the :lock option to defpackage).

The package common-lisp and SBCL internal implementation packages are locked by default, including sb-ext.

It may be beneficial to lock common-lisp-user as well, to ensure that various libraries don't pollute it without asking, but this is not currently done by default.

Implementation Packages
-----------------------

Each package has a list of associated implementation packages. A locked package, and the symbols whose home package it is, can be modified without violating package locks only when *package* is bound to one of the implementation packages of the locked package.

Unless explicitly altered by defpackage, sb-ext:add-implementation-package, or sb-ext:remove-implementation-package each package is its own (only) implementation package.

Package Lock Violations
-----------------------

If an operation violates a package lock, a continuable error that is of a subtype of sb-ext:package-lock-violation (subtype of package-error) is signalled when the operation is attempted.

Additional restarts may be established for continuable package lock violations for interactive use.

The actual type of the error depends on circumstances that caused the violation: operations on packages signal errors of type sb-ext:package-locked-error, and operations on symbols signal errors of type sb-ext:symbol-package-locked-error.

Package Locks in Compiled Code
------------------------------

Lexical bindings and declarations
.................................

Compiling lexical binding constructs or lexical declarations that violate package locks causes a compile-time package-lock violation. A complete listing of operators affect by this is: let, let*, flet, labels, macrolet, and symbol-macrolet, declare.

Package locks affecting both lexical bindings and declarations can be disabled at compile-time with sb-ext:disable-package-locks declaration, and re-enabled with sb-ext:enable-package-locks declaration. Constructs compiled with package locks thusly disabled are guaranteed not to signal package lock violation errors at runtime.

Example:

     (in-package :locked)

     (defun foo () ...)

     (defmacro with-foo (&body body)
       `(locally (declare (disable-package-locks locked:foo))
          (flet ((foo () ...))
            (declare (enable-package-locks locked:foo)) ; re-enable for body
            ,@body)))

Interned symbols
................

If compiled code contains interned symbols, then loading that code into an image without the said symbols will not cause a package lock violation even if the packages in question are locked.

Other limitations on compiled code
..................................

With the exception of the aforementioned contructs, and interned symbols, behaviour is unspecified if package locks affecting compiled code are not the same during loading of the code or execution.

Specifically, code compiled with packages unlocked may or may not fail to signal package-lock-violations even if the packages are locked at runtime, and code compiled with packages locked may or may not signal spurious package-lock-violations at runtime even if the packages are unlocked.

In practise all this means that package-locks have a neglible performance penalty in compiled code as long as they are not violated.

Operations Violating Package Locks
----------------------------------

Operations on Packages
......................

Following actions cause a package lock violation if the package operated on is locked, and *package* is not an implementation package of that package, and the action would cause a change in the state of the package (eg. exporting already external symbols is allowed). Package lock violations caused by these operations signal errors of type sb-ext:package-locked-error.

 1. Shadowing a symbol in a package.

 2. Importing a symbol to a package.

 3. Uninterning a symbol from a package.

 4. Exporting a symbol from a package.

 5. Unexporting a symbol from a package.

 6. Changing the packages used by a package.

 7. Renaming a package.

 8. Deleting a package.

Operations on Symbols
.....................

Following actions cause a package lock violation if the home package of the symbol operated on is locked, and *package* is not an implementation package of that package. Package lock violations caused by these action signal errors of type sb-ext:symbol-package-locked-error.

These actions cause only one package lock violation per lexically apparent violated package.

Example:

     ;; Packages FOO and BAR are locked.
     ;;
     ;; Two lexically apparent violated packages: exactly two
     ;; package-locked-errors will be signalled.

     (defclass foo:point ()
       ((x :accessor bar:x)
        (y :accessor bar:y)))

 1. Binding or altering its value lexically or dynamically, or establishing it as a symbol-macro.

     Exceptions:

       - If the symbol is not defined as a constant, global symbol-macro or a global dynamic variable, it may be lexically bound or established as a local symbol macro.

       - If the symbol is defined as a global dynamic variable, it may be assigned or bound.

 2. Defining, undefining, or binding it, or its setf name as a function.

     Exceptions:

       - If the symbol is not defined as a function, macro, or special operator it and its setf name may be lexically bound as a function.

 3. Defining, undefining, or binding it as a macro or compiler macro.

     Exceptions:

       - If the symbol is not defined as a function, macro, or special operator it may be lexically bound as a macro.

 4. Defining it as a type specifier or structure.

 5. Defining it as a declaration with a declaration proclamation.

 6. Declaring or proclaiming it special.

 7. Declaring or proclaiming its type or ftype.

     Exceptions:

       - If the symbol may be lexically bound, the type of that binding may be declared.

       - If the symbol may be lexically bound as a function, the ftype of that binding may be declared.

 8. Defining a setf expander for it.

 9. Defining it as a method combination type.

 10. Using it as the class-name argument to setf of find-class.

Package Lock Dictionary
=======================

 -- Declaration: sb-ext:disable-package-locks

     Syntax: (sb-ext:disable-package-locks symbol*)

     Disables package locks affecting the named symbols during compilation in the lexical scope of the declaration. Disabling locks on symbols whose home package is unlocked, or disabling an already disabled lock, has no effect.

 -- Declaration: sb-ext:enable-package-locks

     Syntax: (sb-ext:enable-package-locks symbol*)

     Re-enables package locks affecting the named symbols during compilation in the lexical scope of the declaration. Enabling locks that were not first disabled with sb-ext:disable-package-locks declararion, or enabling locks that are already enabled has no effect.

     [file condition-sb-ext-package-lock-violation.texinfo not included]
     [file condition-sb-ext-package-locked-error.texinfo not included]
     [file condition-sb-ext-symbol-package-locked-error.texinfo not included]

 -- Function: sb-ext:package-locked-error-symbol SYMBOL-PACKAGE-LOCKED-ERROR

     Returns the symbol that caused the symbol-package-locked-error condition.

     [file fun-sb-ext-package-locked-p.texinfo not included]
     [file fun-sb-ext-lock-package.texinfo not included]
     [file fun-sb-ext-unlock-package.texinfo not included]
     [file fun-sb-ext-package-implemented-by-list.texinfo not included]
     [file fun-sb-ext-package-implements-list.texinfo not included]
     [file fun-sb-ext-add-implementation-package.texinfo not included]
     [file fun-sb-ext-remove-implementation-package.texinfo not included]
     [file macro-sb-ext-without-package-locks.texinfo not included]
     [file macro-sb-ext-with-unlocked-packages.texinfo not included]

 -- Macro: defpackage name [[OPTION]]* => package

     Options are extended to include the following:

       * :lock BOOLEAN

          If the argument to :lock is t, the package is initially locked.  If :lock is not provided it defaults to nil.

       * :implement PACKAGE-DESIGNATOR*

          The package is added as an implementation package to the packages named. If :implement is not provided, it defaults to the package itself.

     Example:

          (defpackage "FOO" (:export "BAR") (:lock t) (:implement))
          (defpackage "FOO-INT" (:use "FOO") (:implement "FOO" "FOO-INT"))

          ;;; is equivalent to

          (defpackage "FOO") (:export "BAR"))
          (lock-package "FOO")
          (remove-implementation-package "FOO" "FOO")
          (defpackage "FOO-INT" (:use "BAR"))
          (add-implementation-package "FOO-INT" "FOO")