 be defined permanently."
   :type 'hook)
 
-(defun el-patch--classify-definition-type (type)
-  "Classifies a definition TYPE as a `function' or `variable'.
-TYPE is a symbol `defun', `defmacro', etc."
-  (if-let ((classify (assoc type el-patch-deftype-alist)))
-      (pcase (plist-get (cdr classify) :classify)
-        ('el-patch-classify-function 'function)
-        ('el-patch-classify-define-minor-mode 'function)
-        ('el-patch-classify-variable 'variable))
-    (error "Unexpected definition type `%S'" type)))
-
-(defun el-patch--find-symbol (name type)
-  "Return the Lisp form that defines the symbol NAME.
+(defun el-patch--locate (definition)
+  "Return the Lisp form corresponding to the given DEFINITION.
 Return nil if such a definition cannot be found. (That would
 happen if the definition were generated dynamically.) TYPE is a
 symbol `defun', `defmacro', etc. which is used to determine
 whether the symbol is a function or variable."
-  (let ((classification (el-patch--classify-definition-type type)))
-    (when (pcase classification
-            ('function (fboundp name))
-            ('variable (boundp name)))
-      (let* (;; Since Emacs actually opens the source file in a (hidden)
-             ;; buffer, it can try to apply local variables, which might
-             ;; result in an annoying interactive prompt. Let's disable
-             ;; that.
-             (enable-local-variables nil)
-             (enable-dir-local-variables nil)
-             ;; This is supposed to be noninteractive so we also
-             ;; suppress all the messages. This has the side effect of
-             ;; masking all debugging messages (you can use `insert'
-             ;; instead, or temporarily remove these bindings), but
-             ;; there are just so many different messages that can
-             ;; happen for various reasons and I haven't found any other
-             ;; standard way to suppress them.
-             (inhibit-message t)
-             (message-log-max nil)
-             ;; Now we actually do the find-function operation.
-             (buffer-point (save-excursion
-                             ;; This horrifying bit of hackery on
-                             ;; `get-file-buffer' prevents
-                             ;; `find-function-noselect' from
-                             ;; returning an existing buffer, so that
-                             ;; later on when we jump to the
-                             ;; definition, we don't temporarily
-                             ;; scroll the window if the definition
-                             ;; happens to be in the *current* buffer.
-                             (cl-letf (((symbol-function #'get-file-buffer)
-                                        (symbol-function #'ignore)))
-                               (pcase classification
-                                 ('function
-                                  (find-function-noselect name 'lisp-only))
-                                 ('variable
-                                  (find-variable-noselect name))))))
-             (defun-buffer (car buffer-point))
-             (defun-point (cdr buffer-point)))
-        (and defun-buffer
-             defun-point
-             (with-current-buffer defun-buffer
-               (save-excursion
-                 (goto-char defun-point)
-                 (read defun-buffer))))))))
+  (let* ((type (nth 0 definition))
+         (props (alist-get type el-patch-deftype-alist))
+         (locator (plist-get props :locate)))
+    (unless locator
+      (error
+       "Definition type `%S' has no `:locate' in `el-patch-deftype-alist'"))
+    (funcall locator definition)))
 
 ;;;###autoload
 (defun el-patch-validate (name type &optional nomsg run-hooks)

          :value-type (plist
                       :key-type (choice
                                  (const :classify)
                                  (const :declare)
                                  (const :macro-name))
                       :value-type sexp)))

;;;###autoload
(progn
  (cl-defmacro el-patch-deftype
      (type &rest kwargs &key classify locate declare macro-name)
    "Allow `el-patch' to patch definitions of the given TYPE.
TYPE is a symbol like `defun', `define-minor-mode', etc. This
updates `el-patch-deftype-alist' (which see) with the provided
