Repository: mit-ll-responsible-ai/hydra-zen
Pull request #553 (2023-10-19 16:09:12)

Add customizable auto-config support to `builds` et al
This PR introduces a type `BuildsFn`, which exposes all of the type-refinement and auto-config capabilities that are leverages by `builds`, `just`, and `make_config`.  The idea here is that **users can now add customized auto-config and type-refinement support for their own types** to their own versions of `builds`, `just,` etc.

This has been a feature that we have considered adding to hydra-zen for a while, but the issue was that we did not know how to provide type-checking support when users could ostensibly make new types acceptable to, e.g., `builds`. The way that this is solved is that `BuildsFn` is a generic, whose type-var describes the types that are accepted by that specific implementation of `BuildsFn`.

E.g. `builds = BuildsFn[SupportedPrimitives](name='builds')` reflects the typical `builds` function. But suppose you want to add custom auto-config support for instances of `MyType`. You can do:

```python
class CustomBuildsFn(BuildsFn[MyType | SupportedPrimitives]):
    """
    - To customize type-refinement support, override `_sanitized_type`.
    - To customize auto-config support, override `_make_hydra_compatible`.
    - To customize the ability to resolve import paths, override `_get_obj_path`.
    """
    # add support for `MyType` here.

my_builds = CustomBuildsFn.builds
my_just = CustomBuildsFn.just
my_make_config = CustomBuildsFn.make_config
```

Now you can do

```python
def foo(x: MyType = MyType("blah")): ...

my_builds(foo, populate_full_signature=True)
```

and `my_builds` will know how to automatically (and recursively!) convert `MyType` into a hydra-compatible config!

## Defining a Protocol for Automatic Configurablility
Here is an example where we define a protocol that enables a type to describe how to access the kwargs that describe one of its instances. We will create a version of `BuildsFn` that will check if an object implements this protocol; if it does, the `builds`/`just`/`make_config` functions will know how to "automatically" create a config describing the object.

This is an extremely powerful pattern. It means that **3rd party types can make themselves automatically-configurable in your experiment framework by implementing simply this simple protocol**, which you designed. 3rd parties need not modify your implementation of `BuildsFn`.

```python
from typing import (
    Optional,
    Protocol,
    Union,
    Any,
    Tuple,
    Sequence,
    Mapping,
    Type,
    Dict,
    runtime_checkable,
)


from hydra_zen import BuildsFn
from hydra_zen.typing import HydraSupportedType

Tp = Union[
    "AutoConfig",  # <-- the protocol we are introducing
    HydraSupportedType,
    Tuple["Tp", ...],
    Sequence["Tp"],
    Mapping[Any, "Tp"],
]
"Any type supported by hydra-zen, or that implements  `AutoConfig`"


@runtime_checkable
class AutoConfig(Protocol):
    """Implementing this protocol will enable an object to be passed directly to
    config-creation functions."""
    
    def _hydra_config(self, BldFn: Type[BuildsFn[Any]]) -> Dict[str, Tp]:
        """Return a dict of hydra-zen-compatible kwargs that should be used to recreate this instance from a config.
        """
        ...


class CustomBuilds(BuildsFn[Tp]):
    """Exposes config-creation functions that are compatible with objects that implement
        the `AutoConfig` protocol."""
    @classmethod
    def _make_hydra_compatible(
        cls, value: Any, *, structured_conf_permitted: bool = True, **kw
    ) -> HydraSupportedType:
        if structured_conf_permitted and isinstance(value, AutoConfig):
            return cls.builds(type(value), **value._hydra_config(cls))  # type: ignore

        return super()._make_hydra_compatible(
            value,
            structured_conf_permitted=structured_conf_permitted,
            **kw,
        )


just = CustomBuilds.just
builds = CustomBuilds.builds
make_config = CustomBuilds.make_config
```

Seeing the config-creation functions in action.

```python
from hydra_zen import to_yaml

class SomeType:
    """Some type that implements the AutoConfig protocol."""
    def __repr__(self) -> str:
        return f"SomeType({self._x!r}, {self._y!r})"

    def __init__(self, x: int, y: Optional["SomeType"] = None) -> None:
        self._x = x
        self._y = y

    def _hydra_config(self, BldFn: Type[BuildsFn[Any]]) -> Dict[str, Tp]:
        # hydra-zen will apply auto-config logic recursively, so there
        # we can return `self._y`, which is of type `SomeType`, as-is.
        return {"x": self._x, "y": self._y}


def pyaml(x): print(to_yaml(x))

>>> pyaml(just(SomeType(1, SomeType(2))))
_target_: __main__.SomeType
x: 1
'y':
  _target_: __main__.SomeType
  x: 2
  'y': null

>>> pyaml(builds(dict, w=[SomeType(8), SomeType(9)]))
_target_: builtins.dict
w:
- _target_: __main__.SomeType
  x: 8
  'y': null
- _target_: __main__.SomeType
  x: 9
  'y': null

>>> pyaml(make_config(z=SomeType(-1)))
z:
  _target_: __main__.SomeType
  x: -1
  'y': null
```


Patch:
diff --git a/docs/source/changes.rst b/docs/source/changes.rst
index 8ac3ccfb..33f97a23 100644
--- a/docs/source/changes.rst
+++ b/docs/source/changes.rst
@@ -8,6 +8,60 @@ Changelog
 This is a record of all past hydra-zen releases and what went into them, in reverse 
 chronological order. All previous releases should still be available on pip.
 
+.. _v0.12.0:
+
+----------------------
+0.12.0rc1 - 2023-10-23
+----------------------
+
+
+.. note:: This is documentation for an unreleased version of hydra-zen. You can try out this pre-release version using `pip install --pre hydra-zen`
+
+This release makes hydra-zen's :ref:`auto-config <additional-types>` and :ref:`type-refinement <type-support>` capabilities fully customizable and extensible, while still preserving static type-checking 🎉.
+
+It does so by exposing a customizable class – `hydra_zen.BuildsFn` – with methods that can be overridden to modify the aforementioned auto-config and type-refinement capabilities. This class then exposes the classmethods `just`, `builds`, and `make_config`, which will leverage these customized capabilities.
+
+Here is a stripped-down example.
+
+.. code-block:: python
+   :caption: Basic structure for adding custom auto-config support for a type.
+
+   from hydra_zen import BuildsFn
+   from hydra_zen.typing import SupportedPrimitive
+   
+   # We want builds/just/make_config to be able to automatically
+   # configure instances of `SomeType`
+   class SomeType:
+       ...
+   
+   # The type parameter provided to `BuildsFn[...]` updates the type
+   # annotations of the config-creation functions so that type-checkers
+   # know that `SomeType` is now supported.
+   class CustomBuilds(BuildsFn[SomeType | SupportedPrimitive]):
+       """
+       - To customize type-refinement support, override `_sanitized_type`.
+       - To customize auto-config support, override `_make_hydra_compatible`.
+       - To customize the ability to resolve import paths, override `_get_obj_path`.
+       """
+       @classmethod
+       def _make_hydra_compatible(
+           cls, value, **kw
+       ) -> SupportedPrimitive:
+           # Take some value and return a Hydra-compatible config for it.
+           if isinstance(value, SomeType):
+               return cls.builds(SomeType)
+           return super()._make_hydra_compatible(value, **kw)
+   
+   # These config-creation functions now know how to automatically
+   # - and recursively - generate configs instances of `SomeType`
+   builds = CustomBuilds.builds
+   just = CustomBuilds.just
+   make_config = CustomBuilds.make_config
+
+
+
+For more details and examples, see :pull:`553`.
+
 .. _v0.11.0:
 
 -------------------
diff --git a/src/hydra_zen/__init__.py b/src/hydra_zen/__init__.py
index b3d6a747..a1f76147 100644
--- a/src/hydra_zen/__init__.py
+++ b/src/hydra_zen/__init__.py
@@ -19,12 +19,14 @@ from .structured_configs import (
     make_custom_builds_fn,
     mutable_value,
 )
-from .structured_configs._implementations import get_target
+from .structured_configs._implementations import BuildsFn, DefaultBuilds, get_target
 from .structured_configs._type_guards import is_partial_builds, uses_zen_processing
 from .wrapper import ZenStore, store, zen
 
 __all__ = [
     "builds",
+    "BuildsFn",
+    "DefaultBuilds",
     "hydrated_dataclass",
     "just",
     "mutable_value",
diff --git a/src/hydra_zen/_hydra_overloads.py b/src/hydra_zen/_hydra_overloads.py
index 42f6b717..4e785f9c 100644
--- a/src/hydra_zen/_hydra_overloads.py
+++ b/src/hydra_zen/_hydra_overloads.py
@@ -28,8 +28,11 @@ from typing import IO, Any, Callable, Dict, List, Type, TypeVar, Union, cast, ov
 from hydra.utils import instantiate as hydra_instantiate
 from omegaconf import MISSING, DictConfig, ListConfig, OmegaConf
 
-from .structured_configs._just import just
-from .structured_configs._value_conversion import ConfigComplex, ConfigPath
+from .structured_configs._implementations import (
+    ConfigComplex,
+    ConfigPath,
+    DefaultBuilds,
+)
 from .typing import Builds, Just, Partial
 from .typing._implementations import DataClass_, HasTarget, InstOrType, IsPartial
 
@@ -219,7 +222,7 @@ def _apply_just(fn: F) -> F:
     @wraps(fn)
     def wrapper(cfg: Any, *args: Any, **kwargs: Any):
         if not is_dataclass(cfg):
-            cfg = just(cfg)
+            cfg = DefaultBuilds.just(cfg)
         return fn(cfg, *args, **kwargs)
 
     return cast(F, wrapper)
diff --git a/src/hydra_zen/_utils/coerce.py b/src/hydra_zen/_utils/coerce.py
index 883721fe..9b866a3e 100644
--- a/src/hydra_zen/_utils/coerce.py
+++ b/src/hydra_zen/_utils/coerce.py
@@ -12,14 +12,14 @@ from typing import (
     TypeVar,
     Union,
     cast,
+    get_args,
+    get_origin,
     get_type_hints,
 )
 
 from omegaconf import ListConfig
 from typing_extensions import TypeGuard
 
-from hydra_zen.structured_configs._utils import get_args, get_origin
-
 _T = TypeVar("_T", bound=Callable)
 
 __all__ = ["coerce_sequences"]
diff --git a/src/hydra_zen/structured_configs/_globals.py b/src/hydra_zen/structured_configs/_globals.py
index 8d387e04..6f9cae6e 100644
--- a/src/hydra_zen/structured_configs/_globals.py
+++ b/src/hydra_zen/structured_configs/_globals.py
@@ -5,8 +5,7 @@ from typing import FrozenSet
 
 from typing_extensions import Final
 
-from hydra_zen.funcs import get_obj, zen_processing
-from hydra_zen.structured_configs import _utils
+from hydra_zen.funcs import zen_processing
 
 # Hydra-specific fields
 TARGET_FIELD_NAME: Final[str] = "_target_"
@@ -30,8 +29,9 @@ HYDRA_FIELD_NAMES: FrozenSet[str] = frozenset(_names)
 del _names
 
 # hydra-zen-specific fields
-ZEN_PROCESSING_LOCATION: Final[str] = _utils.get_obj_path(zen_processing)
-GET_OBJ_LOCATION: Final[str] = _utils.get_obj_path(get_obj)
+ZEN_PROCESSING_LOCATION: Final[str] = ".".join(
+    [zen_processing.__module__, zen_processing.__name__]
+)
 ZEN_TARGET_FIELD_NAME: Final[str] = "_zen_target"
 ZEN_PARTIAL_FIELD_NAME: Final[str] = "_zen_partial"
 META_FIELD_NAME: Final[str] = "_zen_exclude"
diff --git a/src/hydra_zen/structured_configs/_implementations.py b/src/hydra_zen/structured_configs/_implementations.py
index 21cf2377..5dbcdfb2 100644
--- a/src/hydra_zen/structured_configs/_implementations.py
+++ b/src/hydra_zen/structured_configs/_implementations.py
@@ -4,9 +4,11 @@ import functools
 import inspect
 import sys
 import warnings
+from collections import Counter, deque
 from dataclasses import (  # use this for runtime checks
     MISSING,
     Field as _Field,
+    InitVar,
     dataclass,
     field,
     fields,
@@ -14,11 +16,15 @@ from dataclasses import (  # use this for runtime checks
     make_dataclass,
 )
 from enum import Enum
+from functools import partial
 from itertools import chain
+from pathlib import Path, PosixPath, WindowsPath
 from typing import (
     Any,
     Callable,
     Dict,
+    FrozenSet,
+    Generic,
     List,
     Mapping,
     Optional,
@@ -29,16 +35,32 @@ from typing import (
     TypeVar,
     Union,
     cast,
+    get_args,
+    get_origin,
     get_type_hints,
     overload,
 )
 
 from omegaconf import DictConfig, ListConfig
-from typing_extensions import Final, Literal, ParamSpec, TypeAlias, dataclass_transform
+from typing_extensions import (
+    Annotated,
+    Final,
+    Literal,
+    ParamSpec,
+    ParamSpecArgs,
+    ParamSpecKwargs,
+    TypeAlias,
+    Unpack,
+    _AnnotatedAlias,
+    dataclass_transform,
+)
 
 from hydra_zen._compatibility import (
+    HYDRA_SUPPORTED_PRIMITIVE_TYPES,
     HYDRA_SUPPORTED_PRIMITIVES,
+    OMEGACONF_VERSION,
     ZEN_SUPPORTED_PRIMITIVES,
+    Version,
 )
 from hydra_zen.errors import (
     HydraZenDeprecationWarning,
@@ -53,18 +75,28 @@ from hydra_zen.typing import (
     DataclassOptions,
     PartialBuilds,
     SupportedPrimitive,
+    ZenConvert,
     ZenWrappers,
 )
+from hydra_zen.typing._builds_overloads import StdBuilds
 from hydra_zen.typing._implementations import (
     AllConvert,
     AnyBuilds,
+    Builds,
     BuildsWithSig,
+    DataClass,
     DataClass_,
+    DataclassOptions,
     DefaultsList,
     Field,
     HasTarget,
+    HydraSupportedType,
     InstOrType,
+    Just as JustT,
+    Partial,
     ZenConvert,
+    _HydraPrimitive,
+    _SupportedViaBuilds,
 )
 
 from ._globals import (
@@ -89,13 +121,23 @@ from ._type_guards import (
     safe_getattr,
     uses_zen_processing,
 )
+from ._utils import merge_settings
 
+T = TypeVar("T")
 _T = TypeVar("_T")
-Importable = TypeVar("Importable", bound=Callable[..., Any])
 P = ParamSpec("P")
 R = TypeVar("R")
+
+TD = TypeVar("TD", bound=DataClass_)
+TC = TypeVar("TC", bound=Callable[..., Any])
+TP = TypeVar("TP", bound=_HydraPrimitive)
+TB = TypeVar("TB", bound=Union[_SupportedViaBuilds, FrozenSet[Any]])
+
+Importable = TypeVar("Importable", bound=Callable[..., Any])
 Field_Entry: TypeAlias = Tuple[str, type, Field[Any]]
 
+_JUST_CONVERT_SETTINGS = AllConvert(dataclass=True, flat_target=False)
+
 # default zen_convert settings for `builds` and `hydrated_dataclass`
 _BUILDS_CONVERT_SETTINGS = AllConvert(dataclass=True, flat_target=True)
 
@@ -111,6 +153,17 @@ _KEYWORD_ONLY: Final = inspect.Parameter.KEYWORD_ONLY
 _VAR_KEYWORD: Final = inspect.Parameter.VAR_KEYWORD
 
 
+NoneType = type(None)
+_supported_types = HYDRA_SUPPORTED_PRIMITIVE_TYPES | {
+    list,
+    dict,
+    tuple,
+    List,
+    Tuple,
+    Dict,
+}
+
+
 _builtin_function_or_method_type = type(len)
 # fmt: off
 _lru_cache_type = type(functools.lru_cache(maxsize=128)(lambda: None))  # pragma: no branch
@@ -148,47 +201,6 @@ def _retain_type_info(type_: type, value: Any, hydra_recursive: Optional[bool]):
     return False
 
 
-def mutable_value(x: _T, *, zen_convert: Optional[ZenConvert] = None) -> _T:
-    """Used to set a mutable object as a default value for a field
-    in a dataclass.
-
-    This is an alias for ``field(default_factory=lambda: type(x)(x))``
-
-    Note that ``type(x)(...)`` serves to make a copy
-
-    Examples
-    --------
-    >>> from hydra_zen import mutable_value
-    >>> from dataclasses import dataclass
-
-    See https://docs.python.org/3/library/dataclasses.html#mutable-default-values
-
-    >>> @dataclass  # doctest: +SKIP
-    ... class HasMutableDefault:
-    ...     a_list: list  = [1, 2, 3]  # error: mutable default
-
-    Using `mutable_value` to specify the default list:
-
-    >>> @dataclass
-    ... class HasMutableDefault:
-    ...     a_list: list  = mutable_value([1, 2, 3])  # ok
-
-    >>> x = HasMutableDefault()
-    >>> x.a_list.append(-1)  # does not append to `HasMutableDefault.a_list`
-    >>> x
-    HasMutableDefault(a_list=[1, 2, 3, -1])
-    >>> HasMutableDefault()
-    HasMutableDefault(a_list=[1, 2, 3])"""
-    cast = type(x)  # ensure that we return a copy of the default value
-    settings = _utils.merge_settings(zen_convert, _BUILDS_CONVERT_SETTINGS)
-    del zen_convert
-
-    if cast in {list, tuple, dict}:
-        x = sanitize_collection(x, convert_dataclass=settings["dataclass"])
-        return field(default_factory=lambda: cast(x))
-    return field(default_factory=lambda: x)
-
-
 @dataclass_transform()
 def hydrated_dataclass(
     target: Callable[..., Any],
@@ -453,7 +465,7 @@ def hydrated_dataclass(
         else:
             kwargs: Dict[str, Any] = {}
 
-        out = builds(
+        out = DefaultBuilds.builds(
             target,
             *pos_args,
             **kwargs,
@@ -494,10 +506,6 @@ class Just:
     _target_: str = field(default="hydra_zen.funcs.get_obj", init=False, repr=False)
 
 
-def _just(obj: Any) -> Just:
-    return Just(path=_utils.get_obj_path(obj))
-
-
 def _is_ufunc(value: Any) -> bool:
     # checks without importing numpy
     numpy = sys.modules.get("numpy")
@@ -562,1727 +570,2552 @@ def _check_for_dynamically_defined_dataclass_type(target_path: str, value: Any)
         )
 
 
-def sanitized_default_value(
-    value: Any,
-    allow_zen_conversion: bool = True,
-    *,
-    error_prefix: str = "",
-    field_name: str = "",
-    structured_conf_permitted: bool = True,
-    convert_dataclass: bool,
-    hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
-    zen_dataclass: Optional[DataclassOptions] = None,
-) -> Any:
-    """Converts `value` to Hydra-supported type if necessary and possible. Otherwise
-    raises `HydraZenUnsupportedPrimitiveError`"""
-    # Common primitives supported by Hydra.
-    # We check exhaustively for all Hydra-supported primitives below but seek to
-    # speedup checks for common types here.
-    if value is None or type(value) in {str, int, bool, float}:
-        return value
-
-    # non-str collection
-    if hasattr(value, "__iter__"):
-        value = sanitize_collection(
-            value,
-            convert_dataclass=convert_dataclass,
-            hydra_convert=hydra_convert,
-            hydra_recursive=hydra_recursive,
-        )
+class NOTHING:
+    def __init__(self) -> None:  # pragma: no cover
+        raise TypeError("`NOTHING` cannot be instantiated")
+
+
+@dataclass(unsafe_hash=True)
+class ZenField:
+    """
+    ZenField(hint=Any, default=<class 'NOTHING'>, name=<class 'NOTHING'>)
+
+    Specifies a field's name and/or type-annotation and/or default value.
+    Designed to specify fields in `make_config`.
+
+    See the Examples section of the docstring for `make_config` for examples of using
+    `ZenField`.
+
+    Parameters
+    ----------
+    hint : type, optional (default=Any)
+    default : Any, optional
+    name : str, optional
+
+    Notes
+    -----
+    ``default`` will be returned as an instance of :class:`dataclasses.Field`.
+    Mutable values (e.g. lists or dictionaries) passed to ``default`` will automatically
+    be "packaged" in a default-factory function [1]_.
+
+    A type passed to ``hint`` will automatically be "broadened" such that the resulting
+    type is compatible with Hydra's set of supported type annotations [2]_.
+
+    References
+    ----------
+    .. [1] https://docs.python.org/3/library/dataclasses.html#default-factory-functions
+    .. [2] https://hydra.cc/docs/next/tutorials/structured_config/intro/#structured-configs-supports
+
+    See Also
+    --------
+    make_config: create a config with customized field names, default values, and annotations.
+    """
 
-    if zen_dataclass is None:
-        zen_dataclass = {}
-
-    # non-targeted dataclass instance
-    if (
-        structured_conf_permitted
-        and convert_dataclass
-        and not is_builds(value)
-        and (is_dataclass(value) and not isinstance(value, type))
-    ):
-        # Auto-config dataclass instance
-        # TODO: handle position-only arguments
-        _val_fields = fields(value)
-        if set(inspect.signature(type(value)).parameters) != {
-            f.name for f in _val_fields if f.init
-        }:
-            raise HydraZenUnsupportedPrimitiveError(
-                f"Configuring {value}: Cannot auto-config a dataclass instance whose "
-                f"type has an Init-only field. Consider using "
-                f"`builds({type(value).__name__}, ...)` instead."
+    hint: type = Any
+    default: Union[Any, Field[Any]] = _utils.field(default=NOTHING)
+    name: Union[str, Type[NOTHING]] = NOTHING
+    zen_convert: InitVar[Optional[ZenConvert]] = None
+    _builds_fn: "Union[BuildsFn[Any], Type[BuildsFn[Any]]]" = _utils.field(default_factory=lambda: DefaultBuilds)  # type: ignore
+
+    def __post_init__(
+        self,
+        zen_convert: Optional[ZenConvert],
+    ) -> None:
+        if not isinstance(self.name, str):
+            if self.name is not NOTHING:
+                raise TypeError(f"`ZenField.name` expects a string, got: {self.name}")
+        convert_settings = _utils.merge_settings(zen_convert, _BUILDS_CONVERT_SETTINGS)
+        del zen_convert
+
+        self.hint = self._builds_fn._sanitized_type(self.hint)
+
+        if self.default is not NOTHING:
+            self.default = self._builds_fn._sanitized_field(
+                self.default,
+                convert_dataclass=convert_settings["dataclass"],
             )
 
-        converted_fields = {}
-        for _field in _val_fields:
-            if _field.init and hasattr(value, _field.name):
-                _val = safe_getattr(value, _field.name)
-                converted_fields[_field.name] = sanitized_default_value(
-                    _val,
-                    allow_zen_conversion=allow_zen_conversion,
-                    field_name=_field.name,
-                    convert_dataclass=convert_dataclass,
+
+_MAKE_CONFIG_SETTINGS = AllConvert(dataclass=False, flat_target=False)
+
+
+class BuildsFn(Generic[T]):
+    """builds(hydra_target, /, *pos_args, zen_partial=None, zen_wrappers=(), zen_meta=None, populate_full_signature=False, hydra_recursive=None, hydra_convert=None, hydra_defaults=None, frozen=False, dataclass_name=None, builds_bases=(), **kwargs_for_target)
+
+    To customize type-refinement support, override `_sanitized_type`.
+    To customize auto-config support, override `_make_hydra_compatible`.
+    To customize the ability to resolve import paths, override `_get_obj_path`.
+    """
+
+    __slots__ = ("__name__", "__qualname__")
+
+    def __init__(self, name: str, qualname: Optional[str] = None) -> None:
+        super().__init__()
+        self.__name__: str = name
+        self.__qualname__: str = qualname if qualname is not None else name
+
+    @classmethod
+    def _sanitized_type(
+        cls,
+        type_: Any,
+        *,
+        primitive_only: bool = False,
+        wrap_optional: bool = False,
+        nested: bool = False,
+    ) -> type:
+        """Broadens a type annotation until it is compatible with Hydra.
+
+        Override this to change how `builds` refines the type annotations
+        of the configs that it produces.
+
+        Parameters
+        ----------
+        type_ : Any
+            The type being sanitized.
+
+        primitive_only: bool, optional (default=False)
+            If true, only `bool` | `None` | `int` | `float` | str`
+            is permitted.
+
+        wrap_optional: bool, optional (default=False)
+            `True` indicates that the resulting type should be
+            wrapped in `Optional`.
+
+        nested: bool, optional (default=False)
+            `True` indicates that this function is processing a type within
+            a container type.
+
+        Examples
+        --------
+        >>> sanitized_type(int)
+        <class 'int'>
+
+        >>> sanitized_type(frozenset)  # not supported by hydra
+        typing.Any
+
+        >>> sanitized_type(int, wrap_optional=True)
+        typing.Union[int, NoneType]
+
+        >>> sanitized_type(List[int])
+        List[int]
+
+        >>> sanitized_type(List[int], primitive_only=True)
+        Any
+
+        >>> sanitized_type(Dict[str, frozenset])
+        Dict[str, Any]
+        """
+        if hasattr(type_, "__supertype__"):
+            # is NewType
+            return cls._sanitized_type(
+                type_.__supertype__,
+                primitive_only=primitive_only,
+                wrap_optional=wrap_optional,
+                nested=nested,
+            )
+
+        if OMEGACONF_VERSION < Version(2, 2, 3):  # pragma: no cover
+            try:
+                type_ = {list: List, tuple: Tuple, dict: Dict}.get(type_, type_)
+            except TypeError:
+                pass
+
+        # Warning: mutating `type_` will mutate the signature being inspected
+        # Even calling deepcopy(`type_`) silently fails to prevent this.
+        origin = get_origin(type_)
+
+        if origin is not None:
+            # Support for Annotated[x, y]
+            # Python 3.9+
+            # # type_: Annotated[x, y]; origin -> Annotated; args -> (x, y)
+            if origin is Annotated:  # pragma: no cover
+                return cls._sanitized_type(
+                    get_args(type_)[0],
+                    primitive_only=primitive_only,
+                    wrap_optional=wrap_optional,
+                    nested=nested,
                 )
 
-        out = builds(
-            type(value),
-            **converted_fields,
-            hydra_recursive=hydra_recursive,
-            hydra_convert=hydra_convert,
-            zen_dataclass=zen_dataclass,
-        )
-        _check_for_dynamically_defined_dataclass_type(
-            safe_getattr(out, TARGET_FIELD_NAME), value
-        )
-        return out
+            # Python 3.7-3.8
+            # type_: Annotated[x, y]; origin -> x
+            if isinstance(type_, _AnnotatedAlias):  # pragma: no cover
+                return cls._sanitized_type(
+                    origin,
+                    primitive_only=primitive_only,
+                    wrap_optional=wrap_optional,
+                    nested=nested,
+                )
 
-    # importable callable (function, type, or method)
-    if (
-        structured_conf_permitted
-        and callable(value)
-        and (
-            inspect.isfunction(value)
-            or (
-                (
-                    not is_dataclass(value)
-                    or (convert_dataclass and not is_builds(value))
+            if primitive_only:  # pragma: no cover
+                return Any
+
+            args = get_args(type_)
+            if origin is Union:
+                # Hydra only supports Optional[<type>] unions
+                if len(args) != 2 or NoneType not in args:
+                    # isn't Optional[<type>]
+                    return Any
+
+                args = cast(Tuple[type, type], args)
+
+                optional_type, none_type = args
+                if none_type is not NoneType:
+                    optional_type = none_type
+
+                optional_type = cls._sanitized_type(optional_type)
+
+                if optional_type is Any:  # Union[Any, T] is just Any
+                    return Any
+
+                return Union[optional_type, NoneType]
+
+            if origin is list or origin is List:
+                if args:
+                    return List[
+                        cls._sanitized_type(args[0], primitive_only=False, nested=True)
+                    ]
+                return List
+
+            if origin is dict or origin is Dict:
+                if args:
+                    KeyType = cls._sanitized_type(
+                        args[0], primitive_only=True, nested=True
+                    )
+                    ValueType = cls._sanitized_type(
+                        args[1], primitive_only=False, nested=True
+                    )
+                    return Dict[KeyType, ValueType]
+                return Dict
+
+            if (origin is tuple or origin is Tuple) and not nested:
+                # hydra silently supports tuples of homogeneous types
+                # It has some weird behavior. It treats `Tuple[t1, t2, ...]` as `List[t1]`
+                # It isn't clear that we want to perpetrate this on our end..
+                # So we deal with inhomogeneous types as e.g. `Tuple[str, int]` -> `Tuple[Any, Any]`.
+                #
+                # Otherwise we preserve the annotation as accurately as possible
+                if not args:
+                    return Any if OMEGACONF_VERSION < (2, 2, 3) else Tuple
+
+                args = cast(Tuple[type, ...], args)
+                unique_args = set(args)
+
+                if any(get_origin(tp) is Unpack for tp in unique_args):
+                    # E.g. Tuple[*Ts]
+                    return Tuple[Any, ...]
+
+                has_ellipses = Ellipsis in unique_args
+
+                # E.g. Tuple[int, int, int] or Tuple[int, ...]
+                _unique_type = (
+                    cls._sanitized_type(args[0], primitive_only=False, nested=True)
+                    if len(unique_args) == 1 or (len(unique_args) == 2 and has_ellipses)
+                    else Any
                 )
-                and inspect.isclass(value)
+
+                if has_ellipses:
+                    return Tuple[_unique_type, ...]
+                else:
+                    return Tuple[(_unique_type,) * len(args)]  # type: ignore
+
+            return Any
+
+        if isinstance(type_, type) and issubclass(type_, Path):
+            type_ = Path
+
+        if isinstance(type_, (ParamSpecArgs, ParamSpecKwargs)):  # pragma: no cover
+            # Python 3.7 - 3.9
+            # these aren't hashable -- can't check for membership in set
+            return Any
+
+        if isinstance(type_, InitVar):
+            return cls._sanitized_type(
+                type_.type,
+                primitive_only=primitive_only,
+                wrap_optional=wrap_optional,
+                nested=nested,
             )
-            or inspect.ismethod(value)
-            or isinstance(value, _BUILTIN_TYPES)
-            or _is_ufunc(value)
-            or _is_numpy_array_func_dispatcher(value=value)
-            or _is_jax_compiled_func(value=value)
-        )
-    ):
-        # `value` is importable callable -- create config that will import
-        # `value` upon instantiation
-        out = _just(value)
-        if convert_dataclass and is_dataclass(value):
-            _check_for_dynamically_defined_dataclass_type(
-                safe_getattr(out, JUST_FIELD_NAME), value
+        if (
+            type_ is Any
+            or type_ in _supported_types
+            or is_dataclass(type_)
+            or (isinstance(type_, type) and issubclass(type_, Enum))
+        ):
+            if sys.version_info[:2] == (3, 6) and type_ is Dict:  # pragma: no cover
+                type_ = Dict[Any, Any]
+
+            if wrap_optional and type_ is not Any:  # pragma: no cover
+                # normally get_type_hints automatically resolves Optional[...]
+                # when None is set as the default, but this has been flaky
+                # for some pytorch-lightning classes. So we just do it ourselves...
+                # It might be worth removing this later since none of our standard tests
+                # cover it.
+                type_ = Optional[type_]
+            return type_
+
+        return Any
+
+    @classmethod
+    def _get_obj_path(cls, target: Any) -> str:
+        """Used to get the `_target_` value for the resulting config.
+
+        Override this to control how `builds` determines the _target_ field
+        in the configs that it produces."""
+        name = _utils.safe_name(target, repr_allowed=False)
+
+        if name == _utils.UNKNOWN_NAME:
+            raise AttributeError(f"{target} does not have a `__name__` attribute")
+
+        module = getattr(target, "__module__", None)
+        qualname = getattr(target, "__qualname__", None)
+
+        if (qualname is not None and "<" in qualname) or module is None:
+            # NumPy's ufuncs do not have an inspectable `__module__` attribute, so we
+            # check to see if the object lives in NumPy's top-level namespace.
+            #
+            # or..
+            #
+            # Qualname produced a name from a local namespace.
+            # E.g. jax.numpy.add.__qualname__ is '_maybe_bool_binop.<locals>.fn'
+            # Thus we defer to the name of the object and look for it in the
+            # top-level namespace of the known suspects
+            #
+            # or...
+            #
+            # module is None, which is apparently a thing..:
+            # __module__ is None for both numpy.random.rand and random.random
+            #
+
+            # don't use qualname for obfuscated paths
+            for new_module in _utils.COMMON_MODULES_WITH_OBFUSCATED_IMPORTS:
+                if getattr(sys.modules.get(new_module), name, None) is target:
+                    module = new_module
+                    break
+            else:
+                raise ModuleNotFoundError(f"{name} is not importable")
+
+        if not _utils.is_classmethod(target):
+            return f"{module}.{name}"
+        else:
+            # __qualname__ reflects name of class that originally defines classmethod.
+            # Does not point to child in case of inheritance.
+            #
+            # obj.__self__ -> parent object
+            # obj.__name__ -> name of classmethod
+            return f"{cls._get_obj_path(target.__self__)}.{target.__name__}"
+
+    @classmethod
+    def _just(cls, obj: Any) -> Just:
+        return Just(path=cls._get_obj_path(obj))
+
+    @classmethod
+    def _mutable_value(cls, x: _T, *, zen_convert: Optional[ZenConvert] = None) -> _T:
+        """Used to set a mutable object as a default value for a field
+        in a dataclass.
+
+        This is an alias for ``field(default_factory=lambda: type(x)(x))``
+
+        Note that ``type(x)(...)`` serves to make a copy
+
+        Examples
+        --------
+        >>> from hydra_zen import mutable_value
+        >>> from dataclasses import dataclass
+
+        See https://docs.python.org/3/library/dataclasses.html#mutable-default-values
+
+        >>> @dataclass  # doctest: +SKIP
+        ... class HasMutableDefault:
+        ...     a_list: list  = [1, 2, 3]  # error: mutable default
+
+        Using `mutable_value` to specify the default list:
+
+        >>> @dataclass
+        ... class HasMutableDefault:
+        ...     a_list: list  = mutable_value([1, 2, 3])  # ok
+
+        >>> x = HasMutableDefault()
+        >>> x.a_list.append(-1)  # does not append to `HasMutableDefault.a_list`
+        >>> x
+        HasMutableDefault(a_list=[1, 2, 3, -1])
+        >>> HasMutableDefault()
+        HasMutableDefault(a_list=[1, 2, 3])"""
+        cast = type(x)  # ensure that we return a copy of the default value
+        settings = _utils.merge_settings(zen_convert, _BUILDS_CONVERT_SETTINGS)
+        del zen_convert
+
+        if cast in {list, tuple, dict}:
+            x = cls._sanitize_collection(x, convert_dataclass=settings["dataclass"])
+            return field(default_factory=lambda: cast(x))
+        return field(default_factory=lambda: x)
+
+    @classmethod
+    def _make_hydra_compatible(
+        cls,
+        value: Any,
+        *,
+        allow_zen_conversion: bool = True,
+        error_prefix: str = "",
+        field_name: str = "",
+        structured_conf_permitted: bool = True,
+        convert_dataclass: bool,
+        hydra_recursive: Optional[bool] = None,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
+        zen_dataclass: Optional[DataclassOptions] = None,
+    ) -> HydraSupportedType:
+        """Converts `value` to Hydra-supported type if necessary and possible. Otherwise
+        raises `HydraZenUnsupportedPrimitiveError`.
+
+        Override this method to add support for adding auto-config support to custom
+        types.
+
+        Notes
+        -----
+        Hydra supports the following types:
+            `bool`, `None`, `int`, `float`, `str`, `ByteString`, `pathlib.Path`,
+            `dataclasses.MISSING`. As well as lists, tuples, dicts, and omegaconf
+            containers containing the above.
+        """
+        # Common primitives supported by Hydra.
+        # We check exhaustively for all Hydra-supported primitives below but seek to
+        # speedup checks for common types here.
+        if value is None or type(value) in {str, int, bool, float}:
+            return value
+
+        # non-str collection
+        if hasattr(value, "__iter__"):
+            value = cls._sanitize_collection(
+                value,
+                convert_dataclass=convert_dataclass,
+                hydra_convert=hydra_convert,
+                hydra_recursive=hydra_recursive,
             )
-        return out
 
-    resolved_value = value
-    type_of_value = type(resolved_value)
+        if zen_dataclass is None:
+            zen_dataclass = {}
 
-    # hydra-zen supported primitives from stdlib
-    #
-    # Note: we don't use isinstance because we don't permit subclasses of supported
-    # primitives
-    if allow_zen_conversion and type_of_value in ZEN_SUPPORTED_PRIMITIVES:
-        type_ = type(resolved_value)
-        conversion_fn = ZEN_VALUE_CONVERSION[type_]
+        # non-targeted dataclass instance
+        if (
+            structured_conf_permitted
+            and convert_dataclass
+            and not is_builds(value)
+            and (is_dataclass(value) and not isinstance(value, type))
+        ):
+            # Auto-config dataclass instance
+            # TODO: handle position-only arguments
+            _val_fields = fields(value)
+            if set(inspect.signature(type(value)).parameters) != {
+                f.name for f in _val_fields if f.init
+            }:
+                raise HydraZenUnsupportedPrimitiveError(
+                    f"Configuring {value}: Cannot auto-config a dataclass instance whose "
+                    f"type has an Init-only field. Consider using "
+                    f"`builds({type(value).__name__}, ...)` instead."
+                )
+
+            converted_fields = {}
+            for _field in _val_fields:
+                if _field.init and hasattr(value, _field.name):
+                    _val = safe_getattr(value, _field.name)
+                    converted_fields[_field.name] = cls._make_hydra_compatible(
+                        _val,
+                        allow_zen_conversion=allow_zen_conversion,
+                        field_name=_field.name,
+                        convert_dataclass=convert_dataclass,
+                    )
+
+            out = cls.__call__(
+                type(value),
+                **converted_fields,
+                hydra_recursive=hydra_recursive,
+                hydra_convert=hydra_convert,
+                zen_dataclass=zen_dataclass,
+            )
+            _check_for_dynamically_defined_dataclass_type(
+                safe_getattr(out, TARGET_FIELD_NAME), value
+            )
+            return out
+
+        # importable callable (function, type, or method)
+        if (
+            structured_conf_permitted
+            and callable(value)
+            and (
+                inspect.isfunction(value)
+                or (
+                    (
+                        not is_dataclass(value)
+                        or (convert_dataclass and not is_builds(value))
+                    )
+                    and inspect.isclass(value)
+                )
+                or inspect.ismethod(value)
+                or isinstance(value, _BUILTIN_TYPES)
+                or _is_ufunc(value)
+                or _is_numpy_array_func_dispatcher(value=value)
+                or _is_jax_compiled_func(value=value)
+            )
+        ):
+            # `value` is importable callable -- create config that will import
+            # `value` upon instantiation
+            out = cls._just(value)
+            if convert_dataclass and is_dataclass(value):
+                _check_for_dynamically_defined_dataclass_type(
+                    safe_getattr(out, JUST_FIELD_NAME), value
+                )
+            return out
 
-        resolved_value = conversion_fn(resolved_value)
+        resolved_value = value
         type_of_value = type(resolved_value)
 
-    if type_of_value in HYDRA_SUPPORTED_PRIMITIVES or (
-        structured_conf_permitted
-        and (
-            is_dataclass(resolved_value)
-            or isinstance(resolved_value, (Enum, ListConfig, DictConfig))
-        )
-    ):
-        return resolved_value
-
-    # pydantic objects
-    pydantic = sys.modules.get("pydantic")
-    if pydantic is not None and isinstance(value, pydantic.fields.FieldInfo):
-        _val = (
-            value.default_factory()  # type: ignore
-            if value.default_factory is not None  # type: ignore
-            else value.default  # type: ignore
-        )
-        if isinstance(_val, pydantic.fields.UndefinedType):
+        # hydra-zen supported primitives from stdlib
+        #
+        # Note: we don't use isinstance because we don't permit subclasses of supported
+        # primitives
+        if allow_zen_conversion and type_of_value in ZEN_SUPPORTED_PRIMITIVES:
+            type_ = type(resolved_value)
+            conversion_fn = ZEN_VALUE_CONVERSION[type_]
+
+            resolved_value = conversion_fn(resolved_value)
+            type_of_value = type(resolved_value)
+
+        if type_of_value in HYDRA_SUPPORTED_PRIMITIVES or (
+            structured_conf_permitted
+            and (
+                is_dataclass(resolved_value)
+                or isinstance(resolved_value, (Enum, ListConfig, DictConfig))
+            )
+        ):
+            return resolved_value
+
+        # pydantic objects
+        pydantic = sys.modules.get("pydantic")
+        if pydantic is not None and isinstance(value, pydantic.fields.FieldInfo):
+            _val = (
+                value.default_factory()  # type: ignore
+                if value.default_factory is not None  # type: ignore
+                else value.default  # type: ignore
+            )
+            if isinstance(_val, pydantic.fields.UndefinedType):
+                return MISSING
+
+            return cls._make_hydra_compatible(
+                _val,
+                allow_zen_conversion=allow_zen_conversion,
+                error_prefix=error_prefix,
+                field_name=field_name,
+                structured_conf_permitted=structured_conf_permitted,
+                convert_dataclass=convert_dataclass,
+                hydra_convert=hydra_convert,
+                hydra_recursive=hydra_recursive,
+            )
+
+        if isinstance(value, str):
+            # Supports pydantic.AnyURL
+            _v = str(value)
+            if type(_v) is str:  # pragma: no branch
+                return _v
+            else:  # pragma: no cover
+                del _v
+
+        # support for torch/jax MISSING proxies
+        if _is_torch_optim_required(value=value) or _is_jax_unspecified(
+            value=value
+        ):  # pragma: no cover
             return MISSING
 
-        return sanitized_default_value(
-            _val,
+        # `value` could no be converted to Hydra-compatible representation.
+        # Raise error
+        if field_name:
+            field_name = f", for field `{field_name}`,"
+
+        err_msg = (
+            error_prefix
+            + f" The configured value {value}{field_name} is not supported by Hydra -- "
+            f"serializing or instantiating this config would ultimately result in an error."
+        )
+
+        if structured_conf_permitted:
+            err_msg += (
+                f"\n\nConsider using `hydra_zen.builds({type(value)}, ...)` create "
+                "a config for this particular value."
+            )
+
+        raise HydraZenUnsupportedPrimitiveError(err_msg)
+
+    @classmethod
+    def _sanitize_collection(
+        cls,
+        x: _T,
+        *,
+        convert_dataclass: bool,
+        hydra_recursive: Optional[bool] = None,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
+    ) -> _T:
+        """Pass contents of lists, tuples, or dicts through sanitized_default_values"""
+        type_x = type(x)
+        if type_x in {list, tuple}:
+            return type_x(
+                cls._make_hydra_compatible(
+                    _x,
+                    convert_dataclass=convert_dataclass,
+                    hydra_convert=hydra_convert,
+                    hydra_recursive=hydra_recursive,
+                )
+                for _x in x  # type: ignore
+            )
+        elif type_x is dict:
+            return {
+                # Hydra doesn't permit structured configs for keys, thus we only
+                # support its basic primitives here.
+                cls._make_hydra_compatible(
+                    k,
+                    allow_zen_conversion=False,
+                    structured_conf_permitted=False,
+                    error_prefix="Configuring dictionary key:",
+                    convert_dataclass=False,
+                ): cls._make_hydra_compatible(
+                    v,
+                    convert_dataclass=convert_dataclass,
+                    hydra_convert=hydra_convert,
+                    hydra_recursive=hydra_recursive,
+                )
+                for k, v in x.items()  # type: ignore
+            }
+        else:
+            # pass-through
+            return x
+
+    @classmethod
+    def _sanitized_field(
+        cls,
+        value: Any,
+        init: bool = True,
+        allow_zen_conversion: bool = True,
+        *,
+        error_prefix: str = "",
+        field_name: str = "",
+        convert_dataclass: bool,
+    ) -> Field[Any]:
+        value = cls._make_hydra_compatible(
+            value,
             allow_zen_conversion=allow_zen_conversion,
             error_prefix=error_prefix,
             field_name=field_name,
-            structured_conf_permitted=structured_conf_permitted,
             convert_dataclass=convert_dataclass,
-            hydra_convert=hydra_convert,
-            hydra_recursive=hydra_recursive,
         )
 
-    if isinstance(value, str):
-        # Supports pydantic.AnyURL
-        _v = str(value)
-        if type(_v) is str:  # pragma: no branch
-            return _v
-        else:  # pragma: no cover
-            del _v
-
-    # support for torch/jax MISSING proxies
-    if _is_torch_optim_required(value=value) or _is_jax_unspecified(
-        value=value
-    ):  # pragma: no cover
-        return MISSING
-
-    # `value` could no be converted to Hydra-compatible representation.
-    # Raise error
-    if field_name:
-        field_name = f", for field `{field_name}`,"
-
-    err_msg = (
-        error_prefix
-        + f" The configured value {value}{field_name} is not supported by Hydra -- "
-        f"serializing or instantiating this config would ultimately result in an error."
-    )
+        type_value = type(value)
+        if (
+            type_value in _utils.KNOWN_MUTABLE_TYPES
+            and type_value in HYDRA_SUPPORTED_PRIMITIVES
+        ) or (
+            is_dataclass(value)
+            and not isinstance(value, type)
+            and value.__hash__ is None
+        ):
+            return cast(
+                Field[Any],
+                mutable_value(value, zen_convert={"dataclass": convert_dataclass}),
+            )
+        return _utils.field(default=value, init=init)
+
+    @classmethod
+    def _get_sig_obj(cls, target: Any) -> Any:
+        """Return the signature object for `target`.
+
+        `inspect.signature` has inconsistent/buggy behaviors across
+        versions, so we implement our own."""
+        if not inspect.isclass(target):
+            return target
+
+        # This implements the same method prioritization as
+        # `inspect.signature` for Python >= 3.9.1
+        if "__new__" in target.__dict__:
+            return target.__new__
+        if "__init__" in target.__dict__:
+            return target.__init__
+
+        if len(target.__mro__) > 2:
+            for parent in target.__mro__[1:-1]:
+                if "__new__" in parent.__dict__:
+                    return target.__new__
+                elif "__init__" in parent.__dict__:
+                    return target.__init__
+        return getattr(target, "__init__", target)
+
+    # partial=False, pop-sig=True; no *args, **kwargs, nor builds_bases
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Type[BuildsWithSig[Type[R], P]],
+        *,
+        zen_partial: Literal[False, None] = ...,
+        populate_full_signature: Literal[True],
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[()] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+    ) -> Type[BuildsWithSig[Type[R], P]]:
+        ...
+
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Callable[P, R],
+        *,
+        zen_partial: Literal[False, None] = ...,
+        populate_full_signature: Literal[True],
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[()] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+    ) -> Type[BuildsWithSig[Type[R], P]]:
+        ...
+
+    # partial=False, pop-sig=bool
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Type[AnyBuilds[Importable]],
+        *pos_args: T,
+        zen_partial: Literal[False, None] = ...,
+        populate_full_signature: bool = ...,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[Type[DataClass_], ...] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+        **kwargs_for_target: T,
+    ) -> Type[Builds[Importable]]:
+        ...
+
+    # partial=False, pop-sig=bool
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Importable,
+        *pos_args: T,
+        zen_partial: Literal[False, None] = ...,
+        populate_full_signature: bool = ...,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[Type[DataClass_], ...] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+        **kwargs_for_target: T,
+    ) -> Type[Builds[Importable]]:
+        ...
+
+    # partial=True, pop-sig=bool
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Type[AnyBuilds[Importable]],
+        *pos_args: T,
+        zen_partial: Literal[True] = ...,
+        populate_full_signature: bool = ...,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[Type[DataClass_], ...] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+        **kwargs_for_target: T,
+    ) -> Type[PartialBuilds[Importable]]:
+        ...
+
+    # partial=True, pop-sig=bool
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Importable,
+        *pos_args: T,
+        zen_partial: Literal[True] = ...,
+        populate_full_signature: bool = ...,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[Type[DataClass_], ...] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+        **kwargs_for_target: T,
+    ) -> Type[PartialBuilds[Importable]]:
+        ...
+
+    # partial=bool, pop-sig=False
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Type[AnyBuilds[Importable]],
+        *pos_args: T,
+        zen_partial: Optional[bool] = ...,
+        populate_full_signature: Literal[False] = ...,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[Type[DataClass_], ...] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+        **kwargs_for_target: T,
+    ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]]]:
+        ...
+
+    # partial=bool, pop-sig=False
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Importable,
+        *pos_args: T,
+        zen_partial: Optional[bool] = ...,
+        populate_full_signature: Literal[False] = ...,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[Type[DataClass_], ...] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+        **kwargs_for_target: T,
+    ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]]]:
+        ...
+
+    # partial=bool, pop-sig=bool
+    @overload
+    @classmethod
+    def builds(
+        cls,
+        __hydra_target: Union[Callable[P, R], Type[Builds[Importable]], Importable],
+        *pos_args: T,
+        zen_partial: Optional[bool],
+        populate_full_signature: bool = ...,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        hydra_defaults: Optional[DefaultsList] = ...,
+        dataclass_name: Optional[str] = ...,
+        builds_bases: Tuple[Type[DataClass_], ...] = ...,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        frozen: bool = ...,
+        zen_convert: Optional[ZenConvert] = ...,
+        **kwargs_for_target: T,
+    ) -> Union[
+        Type[Builds[Importable]],
+        Type[PartialBuilds[Importable]],
+        Type[BuildsWithSig[Type[R], P]],
+    ]:
+        ...
+
+    @classmethod
+    def builds(
+        cls,
+        *pos_args: Union[Importable, Callable[P, R], Type[AnyBuilds[Importable]], Any],
+        zen_partial: Optional[bool] = None,
+        zen_wrappers: ZenWrappers[Callable[..., Any]] = tuple(),
+        zen_meta: Optional[Mapping[str, SupportedPrimitive]] = None,
+        populate_full_signature: bool = False,
+        zen_convert: Optional[ZenConvert] = None,
+        hydra_recursive: Optional[bool] = None,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
+        hydra_defaults: Optional[DefaultsList] = None,
+        builds_bases: Union[Tuple[Type[DataClass_], ...], Tuple[()]] = (),
+        zen_dataclass: Optional[DataclassOptions] = None,
+        **kwargs_for_target: Any,
+    ) -> Union[
+        Type[Builds[Importable]],
+        Type[PartialBuilds[Importable]],
+        Type[BuildsWithSig[Type[R], P]],
+    ]:
+        """builds(hydra_target, /, *pos_args, zen_partial=None, zen_wrappers=(), zen_meta=None, populate_full_signature=False, hydra_recursive=None, hydra_convert=None, hydra_defaults=None, frozen=False, dataclass_name=None, builds_bases=(), **kwargs_for_target)
+
+        `builds(target, *args, **kw)` returns a Hydra-compatible config that, when
+        instantiated, returns `target(*args, **kw)`.
+
+        I.e., `instantiate(builds(target, *args, **kw)) == target(*args, **kw)`
+
+        Consult the Notes section for more details, and the Examples section to see
+        the various features of `builds` in action.
+
+        Parameters
+        ----------
+        hydra_target : T (Callable)
+            The target object to be configured. This is a required, **positional-only**
+            argument.
+
+        *pos_args : SupportedPrimitive
+            Positional arguments passed as ``<hydra_target>(*pos_args, ...)`` upon
+            instantiation.
+
+            Arguments specified positionally are not included in the config's signature
+            and are stored as a tuple bound to in the ``_args_`` field.
+
+        **kwargs_for_target : SupportedPrimitive
+            The keyword arguments passed as ``<hydra_target>(..., **kwargs_for_target)``
+            upon instantiation.
+
+            The arguments specified here determine the signature of the resulting
+            config, unless ``populate_full_signature=True`` is specified (see below).
+
+            Named parameters of the forms that have the prefixes ``hydra_``, ``zen_`` or
+            ``_zen_`` are reserved to ensure future-compatibility, and thus cannot be
+            specified by the user.
+
+        zen_partial : Optional[bool]
+            If ``True``, then the resulting config will instantiate as
+            ``functools.partial(<hydra_target>, *pos_args, **kwargs_for_target)``. Thus
+            this enables the partial-configuration of objects.
+
+            Specifying ``zen_partial=True`` and ``populate_full_signature=True`` together
+            will populate the config's signature only with parameters that: are explicitly
+            specified by the user, or that have default values specified in the target's
+            signature. I.e. it is presumed that un-specified parameters that have no
+            default values are to be excluded from the config.
+
+        zen_wrappers : None | Callable | Builds | InterpStr | Sequence[None | Callable | Builds | InterpStr]
+            One or more wrappers, which will wrap ``hydra_target`` prior to instantiation.
+            E.g. specifying the wrappers ``[f1, f2, f3]`` will instantiate as::
+
+                f3(f2(f1(<hydra_target>)))(*args, **kwargs)
+
+            Wrappers can also be specified as interpolated strings [2]_ or targeted
+            configs.
+
+        zen_meta : Optional[Mapping[str, SupportedPrimitive]]
+            Specifies field-names and corresponding values that will be included in the
+            resulting config, but that will *not* be used to instantiate
+            ``<hydra_target>``. These are called "meta" fields.
+
+        populate_full_signature : bool, optional (default=False)
+            If ``True``, then the resulting config's signature and fields will be populated
+            according to the signature of ``<hydra_target>``; values also specified in
+            ``**kwargs_for_target`` take precedent.
+
+            This option is not available for objects with inaccessible signatures, such as
+            NumPy's various ufuncs.
+
+        zen_convert : Optional[ZenConvert]
+            A dictionary that modifies hydra-zen's value and type conversion behavior.
+            Consists of the following optional key-value pairs (:ref:`zen-convert`):
+
+            - `dataclass` : `bool` (default=True):
+                If `True` any dataclass type/instance without a
+                `_target_` field is automatically converted to a targeted config
+                that will instantiate to that type/instance. Otherwise the dataclass
+                type/instance will be passed through as-is.
+
+            - `flat_target`: `bool` (default=True)
+                If `True` (default), `builds(builds(f))` is equivalent to `builds(f)`. I.e. the second `builds` call will use the `_target_` field of its input, if it exists.
+
+        builds_bases : Tuple[Type[DataClass], ...]
+            Specifies a tuple of parent classes that the resulting config inherits from.
+
+        hydra_recursive : Optional[bool], optional (default=True)
+            If ``True``, then Hydra will recursively instantiate all other
+            hydra-config objects nested within this config [3]_.
+
+            If ``None``, the ``_recursive_`` attribute is not set on the resulting config.
+
+        hydra_convert : Optional[Literal["none", "partial", "all", "object"]], optional (default="none")
+            Determines how Hydra handles the non-primitive, omegaconf-specific objects passed to
+            ``<hydra_target>`` [4]_.
+
+            - ``"none"``: No conversion occurs; omegaconf containers are passed through (Default)
+            - ``"partial"``: ``DictConfig`` and ``ListConfig`` objects converted to ``dict`` and
+            ``list``, respectively. Structured configs and their fields are passed without conversion.
+            - ``"all"``: All passed objects are converted to dicts, lists, and primitives, without
+            a trace of OmegaConf containers.
+            - ``"object"``: Passed objects are converted to dict and list. Structured Configs are converted to instances of the backing dataclass / attr class.
 
-    if structured_conf_permitted:
-        err_msg += (
-            f"\n\nConsider using `hydra_zen.builds({type(value)}, ...)` create "
-            "a config for this particular value."
-        )
+            If ``None``, the ``_convert_`` attribute is not set on the resulting config.
 
-    raise HydraZenUnsupportedPrimitiveError(err_msg)
+        hydra_defaults : None | list[str | dict[str, str | list[str] | None ]], optional (default = None)
+            A list in an input config that instructs Hydra how to build the output config
+            [6]_ [7]_. Each input config can have a Defaults List as a top level element. The
+            Defaults List itself is not a part of output config.
 
+        zen_dataclass : Optional[DataclassOptions]
+            A dictionary that can specify any option that is supported by
+            :py:func:`dataclasses.make_dataclass` other than `fields`.
+            The default value for `unsafe_hash` is `True`.
 
-def sanitize_collection(
-    x: _T,
-    *,
-    convert_dataclass: bool,
-    hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
-) -> _T:
-    """Pass contents of lists, tuples, or dicts through sanitized_default_values"""
-    type_x = type(x)
-    if type_x in {list, tuple}:
-        return type_x(sanitized_default_value(_x, convert_dataclass=convert_dataclass, hydra_convert=hydra_convert, hydra_recursive=hydra_recursive) for _x in x)  # type: ignore
-    elif type_x is dict:
-        return {
-            # Hydra doesn't permit structured configs for keys, thus we only
-            # support its basic primitives here.
-            sanitized_default_value(
-                k,
-                allow_zen_conversion=False,
-                structured_conf_permitted=False,
-                error_prefix="Configuring dictionary key:",
-                convert_dataclass=False,
-            ): sanitized_default_value(
-                v,
-                convert_dataclass=convert_dataclass,
-                hydra_convert=hydra_convert,
-                hydra_recursive=hydra_recursive,
-            )
-            for k, v in x.items()  # type: ignore
-        }
-    else:
-        # pass-through
-        return x
+            Additionally, the `module` field can be specified to enable pickle
+            compatibility. See `hydra_zen.typing.DataclassOptions` for details.
 
+        frozen : bool, optional (default=False)
+            .. deprecated:: 0.9.0
+                `frozen` will be removed in hydra-zen 0.10.0. It is replaced by
+                `zen_dataclass={'frozen': <bool>}`.
 
-def sanitized_field(
-    value: Any,
-    init: bool = True,
-    allow_zen_conversion: bool = True,
-    *,
-    error_prefix: str = "",
-    field_name: str = "",
-    convert_dataclass: bool,
-) -> Field[Any]:
-    value = sanitized_default_value(
-        value,
-        allow_zen_conversion=allow_zen_conversion,
-        error_prefix=error_prefix,
-        field_name=field_name,
-        convert_dataclass=convert_dataclass,
-    )
+            If ``True``, the resulting config will create frozen (i.e. immutable) instances.
+            I.e. setting/deleting an attribute of an instance will raise
+            :py:class:`dataclasses.FrozenInstanceError` at runtime.
 
-    type_value = type(value)
-    if (
-        type_value in _utils.KNOWN_MUTABLE_TYPES
-        and type_value in HYDRA_SUPPORTED_PRIMITIVES
-    ) or (
-        is_dataclass(value) and not isinstance(value, type) and value.__hash__ is None
-    ):
-        return cast(
-            Field[Any],
-            mutable_value(value, zen_convert={"dataclass": convert_dataclass}),
-        )
-    return _utils.field(default=value, init=init)
+        dataclass_name : Optional[str]
+            .. deprecated:: 0.9.0
+                `dataclass_name` will be removed in hydra-zen 0.10.0. It is replaced by
+                `zen_dataclass={'cls_name': <str>}`.
 
+            If specified, determines the name of the returned class object.
+
+        Returns
+        -------
+        Config : Type[Builds[Type[T]]] | Type[PartialBuilds[Type[T]]]
+            A dynamically-generated structured config (i.e. a dataclass type) that
+            describes how to build ``hydra_target``.
 
-def _get_sig_obj(target):
-    if not inspect.isclass(target):
-        return target
+        Raises
+        ------
+        hydra_zen.errors.HydraZenUnsupportedPrimitiveError
+            The provided configured value cannot be serialized by Hydra, nor does hydra-zen
+            provide specialized support for it. See :ref:`valid-types` for more details.
 
-    # This implements the same method prioritization as
-    # `inspect.signature` for Python >= 3.9.1
-    if "__new__" in target.__dict__:
-        return target.__new__
-    if "__init__" in target.__dict__:
-        return target.__init__
+        Notes
+        -----
+        The following pseudo code conveys the core functionality of `builds`:
 
-    if len(target.__mro__) > 2:
-        for parent in target.__mro__[1:-1]:
-            if "__new__" in parent.__dict__:
-                return target.__new__
-            elif "__init__" in parent.__dict__:
-                return target.__init__
-    return getattr(target, "__init__", target)
+        .. code-block:: python
 
+            from dataclasses import make_dataclass
 
-# partial=False, pop-sig=True; no *args, **kwargs, nor builds_bases
-@overload
-def builds(
-    __hydra_target: Type[BuildsWithSig[Type[R], P]],
-    *,
-    zen_partial: Literal[False, None] = ...,
-    populate_full_signature: Literal[True],
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[()] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-) -> Type[BuildsWithSig[Type[R], P]]:
-    ...
+            def builds(self,target, populate_full_signature=False, **kw):
+                # Dynamically defines a Hydra-compatible dataclass type.
+                # Akin to doing:
+                #
+                # @dataclass
+                # class Builds_thing:
+                #     _target_: str = get_import_path(target)
+                #     # etc.
 
+                _target_ = get_import_path(target)
 
-@overload
-def builds(
-    __hydra_target: Callable[P, R],
-    *,
-    zen_partial: Literal[False, None] = ...,
-    populate_full_signature: Literal[True],
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[()] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-) -> Type[BuildsWithSig[Type[R], P]]:
-    ...
+                if populate_full_signature:
+                    sig = get_signature(target)
+                    kw = {**sig, **kw}  # merge w/ preference for kw
 
+                type_annots = [get_hints(target)[k] for k in kw]
 
-# partial=False, pop-sig=bool
-@overload
-def builds(
-    __hydra_target: Type[AnyBuilds[Importable]],
-    *pos_args: SupportedPrimitive,
-    zen_partial: Literal[False, None] = ...,
-    populate_full_signature: bool = ...,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[Type[DataClass_], ...] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Type[Builds[Importable]]:
-    ...
+                fields = [("_target_", str, _target_)]
+                fields += [
+                    (
+                        field_name,
+                        hydra_compat_type_annot(hint),
+                        hydra_compat_val(v),
+                    )
+                    for hint, (field_name, v) in zip(type_annots, kw.items())
+                ]
 
+                Config = make_dataclass(f"Builds_{target}", fields)
+                return Config
 
-# partial=False, pop-sig=bool
-@overload
-def builds(
-    __hydra_target: Importable,
-    *pos_args: SupportedPrimitive,
-    zen_partial: Literal[False, None] = ...,
-    populate_full_signature: bool = ...,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[Type[DataClass_], ...] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Type[Builds[Importable]]:
-    ...
+        The resulting "config" is a dynamically-generated dataclass type [5]_ with
+        Hydra-specific attributes attached to it [1]_. It possesses a `_target_`
+        attribute that indicates the import path to the configured target as a string.
 
+        Using any of the ``zen_xx`` features will result in a config that depends
+        explicitly on hydra-zen. I.e. hydra-zen must be installed in order to
+        instantiate the resulting config, including its yaml version.
 
-# partial=True, pop-sig=bool
-@overload
-def builds(
-    __hydra_target: Type[AnyBuilds[Importable]],
-    *pos_args: SupportedPrimitive,
-    zen_partial: Literal[True] = ...,
-    populate_full_signature: bool = ...,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[Type[DataClass_], ...] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Type[PartialBuilds[Importable]]:
-    ...
+        For details of the annotation `SupportedPrimitive`, see :ref:`valid-types`.
 
+        Type annotations are inferred from the target's signature and are only
+        retained if they are compatible with Hydra's limited set of supported
+        annotations; otherwise an annotation is automatically 'broadened' until
+        it is made compatible with Hydra.
 
-# partial=True, pop-sig=bool
-@overload
-def builds(
-    __hydra_target: Importable,
-    *pos_args: SupportedPrimitive,
-    zen_partial: Literal[True] = ...,
-    populate_full_signature: bool = ...,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[Type[DataClass_], ...] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Type[PartialBuilds[Importable]]:
-    ...
+        `builds` provides runtime validation of user-specified arguments against
+        the target's signature. E.g. specifying mis-named arguments or too many
+        arguments will cause `builds` to raise.
 
+        References
+        ----------
+        .. [1] https://hydra.cc/docs/tutorials/structured_config/intro/
+        .. [2] https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#variable-interpolation
+        .. [3] https://hydra.cc/docs/advanced/instantiate_objects/overview/#recursive-instantiation
+        .. [4] https://hydra.cc/docs/advanced/instantiate_objects/overview/#parameter-conversion-strategies
+        .. [5] https://docs.python.org/3/library/dataclasses.html
+        .. [6] https://hydra.cc/docs/tutorials/structured_config/defaults/
+        .. [7] https://hydra.cc/docs/advanced/defaults_list/
 
-# partial=bool, pop-sig=False
-@overload
-def builds(
-    __hydra_target: Type[AnyBuilds[Importable]],
-    *pos_args: SupportedPrimitive,
-    zen_partial: Optional[bool] = ...,
-    populate_full_signature: Literal[False] = ...,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[Type[DataClass_], ...] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]]]:
-    ...
+        See Also
+        --------
+        instantiate: Instantiates a configuration created by `builds`, returning the instantiated target.
+        make_custom_builds_fn: Returns a new `builds` function with customized default values.
+        make_config: Creates a general config with customized field names, default values, and annotations.
+        get_target: Returns the target-object from a targeted structured config.
+        just: Produces a config that, when instantiated by Hydra, "just" returns the un-instantiated target-object.
+        to_yaml: Serialize a config as a yaml-formatted string.
 
+        Examples
+        --------
+        These examples describe:
 
-# partial=bool, pop-sig=False
-@overload
-def builds(
-    __hydra_target: Importable,
-    *pos_args: SupportedPrimitive,
-    zen_partial: Optional[bool] = ...,
-    populate_full_signature: Literal[False] = ...,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[Type[DataClass_], ...] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]]]:
-    ...
+        - Basic usage
+        - Creating a partial config
+        - Auto-populating parameters
+        - Composing configs via inheritance
+        - Runtime validation performed by builds
+        - Using meta-fields
+        - Using zen-wrappers
+        - Creating a pickle-compatible config
+        - Creating a frozen config
+        - Support for partial'd targets
 
+        A helpful utility for printing examples
 
-# partial=bool, pop-sig=bool
-@overload
-def builds(
-    __hydra_target: Union[Callable[P, R], Type[Builds[Importable]], Importable],
-    *pos_args: SupportedPrimitive,
-    zen_partial: Optional[bool],
-    populate_full_signature: bool = ...,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = ...,
-    hydra_recursive: Optional[bool] = ...,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
-    hydra_defaults: Optional[DefaultsList] = ...,
-    dataclass_name: Optional[str] = ...,
-    builds_bases: Tuple[Type[DataClass_], ...] = ...,
-    zen_dataclass: Optional[DataclassOptions] = None,
-    frozen: bool = ...,
-    zen_convert: Optional[ZenConvert] = ...,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Union[
-    Type[Builds[Importable]],
-    Type[PartialBuilds[Importable]],
-    Type[BuildsWithSig[Type[R], P]],
-]:
-    ...
+        >>> from hydra_zen import builds, instantiate, to_yaml
+        >>> def pyaml(x):
+        ...     # for pretty printing configs
+        ...     print(to_yaml(x))
 
+        **Basic Usage**
 
-def builds(
-    *pos_args: Union[
-        Importable, Callable[P, R], Type[AnyBuilds[Importable]], SupportedPrimitive
-    ],
-    zen_partial: Optional[bool] = None,
-    zen_wrappers: ZenWrappers[Callable[..., Any]] = tuple(),
-    zen_meta: Optional[Mapping[str, SupportedPrimitive]] = None,
-    populate_full_signature: bool = False,
-    zen_convert: Optional[ZenConvert] = None,
-    hydra_recursive: Optional[bool] = None,
-    hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
-    hydra_defaults: Optional[DefaultsList] = None,
-    builds_bases: Union[Tuple[Type[DataClass_], ...], Tuple[()]] = (),
-    zen_dataclass: Optional[DataclassOptions] = None,
-    **kwargs_for_target: SupportedPrimitive,
-) -> Union[
-    Type[Builds[Importable]],
-    Type[PartialBuilds[Importable]],
-    Type[BuildsWithSig[Type[R], P]],
-]:
-    """builds(hydra_target, /, *pos_args, zen_partial=None, zen_wrappers=(), zen_meta=None, populate_full_signature=False, hydra_recursive=None, hydra_convert=None, hydra_defaults=None, frozen=False, dataclass_name=None, builds_bases=(), **kwargs_for_target)
+        Lets create a basic config that describes how to 'build' a particular dictionary.
 
-    `builds(target, *args, **kw)` returns a Hydra-compatible config that, when
-    instantiated, returns `target(*args, **kw)`.
+        >>> Conf = builds(dict, a=1, b='x')
 
-    I.e., `instantiate(builds(target, *args, **kw)) == target(*args, **kw)`
+        The resulting config is a dataclass with the following signature and attributes:
 
-    Consult the Notes section for more details, and the Examples section to see
-    the various features of `builds` in action.
+        >>> Conf  # signature: Conf(a: Any = 1, b: Any = 'x')
+        <class 'types.Builds_dict'>
 
-    Parameters
-    ----------
-    hydra_target : T (Callable)
-        The target object to be configured. This is a required, **positional-only**
-        argument.
+        >>> pyaml(Conf)
+        _target_: builtins.dict
+        a: 1
+        b: x
 
-    *pos_args : SupportedPrimitive
-        Positional arguments passed as ``<hydra_target>(*pos_args, ...)`` upon
-        instantiation.
+        The `instantiate` function is used to enact this build – to create the dictionary.
 
-        Arguments specified positionally are not included in the config's signature
-        and are stored as a tuple bound to in the ``_args_`` field.
+        >>> instantiate(Conf)  # calls: `dict(a=1, b='x')`
+        {'a': 1, 'b': 'x'}
 
-    **kwargs_for_target : SupportedPrimitive
-        The keyword arguments passed as ``<hydra_target>(..., **kwargs_for_target)``
-        upon instantiation.
+        The default parameters that we provided can be overridden.
 
-        The arguments specified here determine the signature of the resulting
-        config, unless ``populate_full_signature=True`` is specified (see below).
+        >>> new_conf = Conf(a=10, b="hi")  # an instance of our dataclass
+        >>> instantiate(new_conf)  # calls: `dict(a=10, b='hi')`
+        {'a': 10, 'b': 'hi'}
 
-        Named parameters of the forms that have the prefixes ``hydra_``, ``zen_`` or
-        ``_zen_`` are reserved to ensure future-compatibility, and thus cannot be
-        specified by the user.
+        Positional arguments are supported.
 
-    zen_partial : Optional[bool]
-        If ``True``, then the resulting config will instantiate as
-        ``functools.partial(<hydra_target>, *pos_args, **kwargs_for_target)``. Thus
-        this enables the partial-configuration of objects.
+        >>> Conf = builds(len, [1, 2, 3])
+        >>> Conf._args_  # type: ignore
+        [1, 2, 3]
+        >>> instantiate(Conf)
+        3
 
-        Specifying ``zen_partial=True`` and ``populate_full_signature=True`` together
-        will populate the config's signature only with parameters that: are explicitly
-        specified by the user, or that have default values specified in the target's
-        signature. I.e. it is presumed that un-specified parameters that have no
-        default values are to be excluded from the config.
+        **Creating a Partial Config**
 
-    zen_wrappers : None | Callable | Builds | InterpStr | Sequence[None | Callable | Builds | InterpStr]
-        One or more wrappers, which will wrap ``hydra_target`` prior to instantiation.
-        E.g. specifying the wrappers ``[f1, f2, f3]`` will instantiate as::
+        `builds` can be used to partially-configure a target. Let's
+        create a config for the following function
 
-            f3(f2(f1(<hydra_target>)))(*args, **kwargs)
+        >>> def a_two_tuple(x: int, y: float): return x, y
 
-        Wrappers can also be specified as interpolated strings [2]_ or targeted
-        configs.
+        such that we only configure the parameter ``x``.
 
-    zen_meta : Optional[Mapping[str, SupportedPrimitive]]
-        Specifies field-names and corresponding values that will be included in the
-        resulting config, but that will *not* be used to instantiate
-        ``<hydra_target>``. These are called "meta" fields.
+        >>> PartialConf = builds(a_two_tuple, x=1, zen_partial=True)  # configures only `x`
+        >>> pyaml(PartialConf)
+        _target_: __main__.a_two_tuple
+        _partial_: true
+        x: 1
 
-    populate_full_signature : bool, optional (default=False)
-        If ``True``, then the resulting config's signature and fields will be populated
-        according to the signature of ``<hydra_target>``; values also specified in
-        ``**kwargs_for_target`` take precedent.
+        Instantiating this config will return ``functools.partial(a_two_tuple, x=1)``.
 
-        This option is not available for objects with inaccessible signatures, such as
-        NumPy's various ufuncs.
-
-    zen_convert : Optional[ZenConvert]
-        A dictionary that modifies hydra-zen's value and type conversion behavior.
-        Consists of the following optional key-value pairs (:ref:`zen-convert`):
-
-        - `dataclass` : `bool` (default=True):
-            If `True` any dataclass type/instance without a
-            `_target_` field is automatically converted to a targeted config
-            that will instantiate to that type/instance. Otherwise the dataclass
-            type/instance will be passed through as-is.
+        >>> partial_func = instantiate(PartialConf)
+        >>> partial_func
+        functools.partial(<function a_two_tuple at 0x00000220A7820EE0>, x=1)
 
-        - `flat_target`: `bool` (default=True)
-            If `True` (default), `builds(builds(f))` is equivalent to `builds(f)`. I.e. the second `builds` call will use the `_target_` field of its input, if it exists.
+        And thus the remaining parameter can be provided post-instantiation.
 
-    builds_bases : Tuple[Type[DataClass], ...]
-        Specifies a tuple of parent classes that the resulting config inherits from.
+        >>> partial_func(y=22.0)  # providing the remaining parameter
+        (1, 22.0)
 
-    hydra_recursive : Optional[bool], optional (default=True)
-        If ``True``, then Hydra will recursively instantiate all other
-        hydra-config objects nested within this config [3]_.
+        **Auto-populating parameters**
 
-        If ``None``, the ``_recursive_`` attribute is not set on the resulting config.
+        The configurable parameters of a target can be auto-populated in our config.
+        Suppose we want to configure the following function.
 
-    hydra_convert : Optional[Literal["none", "partial", "all", "object"]], optional (default="none")
-        Determines how Hydra handles the non-primitive, omegaconf-specific objects passed to
-        ``<hydra_target>`` [4]_.
+        >>> def bar(x: bool, y: str = 'foo'): return x, y
 
-        - ``"none"``: No conversion occurs; omegaconf containers are passed through (Default)
-        - ``"partial"``: ``DictConfig`` and ``ListConfig`` objects converted to ``dict`` and
-          ``list``, respectively. Structured configs and their fields are passed without conversion.
-        - ``"all"``: All passed objects are converted to dicts, lists, and primitives, without
-          a trace of OmegaConf containers.
-        - ``"object"``: Passed objects are converted to dict and list. Structured Configs are converted to instances of the backing dataclass / attr class.
+        The following config will have a signature that matches ``f``; the
+        annotations and default values of the parameters of ``f`` are explicitly
+        incorporated into the config.
 
-        If ``None``, the ``_convert_`` attribute is not set on the resulting config.
+        >>> # signature: `Builds_bar(x: bool, y: str = 'foo')`
+        >>> Conf = builds(bar, populate_full_signature=True)
+        >>> pyaml(Conf)
+        _target_: __main__.bar
+        x: ???
+        'y': foo
 
-    hydra_defaults : None | list[str | dict[str, str | list[str] | None ]], optional (default = None)
-        A list in an input config that instructs Hydra how to build the output config
-        [6]_ [7]_. Each input config can have a Defaults List as a top level element. The
-        Defaults List itself is not a part of output config.
+        Annotations will be used by Hydra to provide limited runtime type-checking during
+        instantiation. Here, we'll pass a float for ``x``, which expects a boolean value.
 
-    zen_dataclass : Optional[DataclassOptions]
-        A dictionary that can specify any option that is supported by
-        :py:func:`dataclasses.make_dataclass` other than `fields`.
-        The default value for `unsafe_hash` is `True`.
+        >>> instantiate(Conf(x=10.0))  # type: ignore
+        ValidationError: Value '10.0' is not a valid bool (type float)
+            full_key: x
+            object_type=Builds_func
 
-        Additionally, the `module` field can be specified to enable pickle
-        compatibility. See `hydra_zen.typing.DataclassOptions` for details.
+        **Composing configs via inheritance**
 
-    frozen : bool, optional (default=False)
-        .. deprecated:: 0.9.0
-            `frozen` will be removed in hydra-zen 0.10.0. It is replaced by
-            `zen_dataclass={'frozen': <bool>}`.
+        Because a config produced via `builds` is simply a class-object, we can
+        compose configs via class inheritance.
 
-        If ``True``, the resulting config will create frozen (i.e. immutable) instances.
-        I.e. setting/deleting an attribute of an instance will raise
-        :py:class:`dataclasses.FrozenInstanceError` at runtime.
+        >>> ParentConf = builds(dict, a=1, b=2)
+        >>> ChildConf = builds(dict, b=-2, c=-3, builds_bases=(ParentConf,))
+        >>> instantiate(ChildConf)
+        {'a': 1, 'b': -2, 'c': -3}
+        >>> issubclass(ChildConf, ParentConf)
+        True
 
-    dataclass_name : Optional[str]
-        .. deprecated:: 0.9.0
-            `dataclass_name` will be removed in hydra-zen 0.10.0. It is replaced by
-            `zen_dataclass={'cls_name': <str>}`.
+        .. _builds-validation:
 
-        If specified, determines the name of the returned class object.
+        **Runtime validation performed by builds**
 
-    Returns
-    -------
-    Config : Type[Builds[Type[T]]] | Type[PartialBuilds[Type[T]]]
-        A dynamically-generated structured config (i.e. a dataclass type) that
-        describes how to build ``hydra_target``.
+        Misspelled parameter names and other invalid configurations for the target’s
+        signature will be caught by `builds` so that such errors are caught prior to
+        instantiation.
 
-    Raises
-    ------
-    hydra_zen.errors.HydraZenUnsupportedPrimitiveError
-        The provided configured value cannot be serialized by Hydra, nor does hydra-zen
-        provide specialized support for it. See :ref:`valid-types` for more details.
+        >>> def func(a_number: int): pass
 
-    Notes
-    -----
-    The following pseudo code conveys the core functionality of `builds`:
+        >>> builds(func, a_nmbr=2)  # misspelled parameter name
+        TypeError: Building: func ..
 
-    .. code-block:: python
+        >>> builds(func, 1, 2)  # too many arguments
+        TypeError: Building: func ..
 
-       from dataclasses import make_dataclass
+        >>> BaseConf = builds(func, a_number=2)
+        >>> builds(func, 1, builds_bases=(BaseConf,))  # too many args (via inheritance)
+        TypeError: Building: func ..
 
-       def builds(target, populate_full_signature=False, **kw):
-           # Dynamically defines a Hydra-compatible dataclass type.
-           # Akin to doing:
-           #
-           # @dataclass
-           # class Builds_thing:
-           #     _target_: str = get_import_path(target)
-           #     # etc.
+        >>> # value type not supported by Hydra
+        >>> builds(int, (i for i in range(10)))  # type: ignore
+        hydra_zen.errors.HydraZenUnsupportedPrimitiveError: Building: int ..
 
-           _target_ = get_import_path(target)
 
-           if populate_full_signature:
-               sig = get_signature(target)
-               kw = {**sig, **kw}  # merge w/ preference for kw
+        .. _meta-field:
 
-           type_annots = [get_hints(target)[k] for k in kw]
+        **Using meta-fields**
 
-           fields = [("_target_", str, _target_)]
-           fields += [
-               (
-                   field_name,
-                   hydra_compat_type_annot(hint),
-                   hydra_compat_val(v),
-               )
-               for hint, (field_name, v) in zip(type_annots, kw.items())
-           ]
+        Meta-fields are fields that are included in a config but are excluded by the
+        instantiation process. Thus arbitrary metadata can be attached to a config.
 
-           Config = make_dataclass(f"Builds_{target}", fields)
-           return Config
+        Let's create a config whose fields reference a meta-field via
+        relative-interpolation [2]_.
 
-    The resulting "config" is a dynamically-generated dataclass type [5]_ with
-    Hydra-specific attributes attached to it [1]_. It possesses a `_target_`
-    attribute that indicates the import path to the configured target as a string.
+        >>> Conf = builds(dict, a="${.s}", b="${.s}", zen_meta=dict(s=-10))
+        >>> instantiate(Conf)
+        {'a': -10, 'b': -10}
+        >>> instantiate(Conf, s=2)
+        {'a': 2, 'b': 2}
 
-    Using any of the ``zen_xx`` features will result in a config that depends
-    explicitly on hydra-zen. I.e. hydra-zen must be installed in order to
-    instantiate the resulting config, including its yaml version.
+        .. _zen-wrapper:
 
-    For details of the annotation `SupportedPrimitive`, see :ref:`valid-types`.
+        **Using zen-wrappers**
 
-    Type annotations are inferred from the target's signature and are only
-    retained if they are compatible with Hydra's limited set of supported
-    annotations; otherwise an annotation is automatically 'broadened' until
-    it is made compatible with Hydra.
+        Zen-wrappers enables us to make arbitrary changes to ``<hydra_target>``, its inputs,
+        and/or its outputs during the instantiation process.
 
-    `builds` provides runtime validation of user-specified arguments against
-    the target's signature. E.g. specifying mis-named arguments or too many
-    arguments will cause `builds` to raise.
+        Let's use a wrapper to add a unit-conversion step to a config. We'll modify a
+        config that builds a function, which converts a temperature in Fahrenheit to
+        Celsius, and add a wrapper to it so that it will convert from Fahrenheit to
+        Kelvin instead.
 
-    References
-    ----------
-    .. [1] https://hydra.cc/docs/tutorials/structured_config/intro/
-    .. [2] https://omegaconf.readthedocs.io/en/2.1_branch/usage.html#variable-interpolation
-    .. [3] https://hydra.cc/docs/advanced/instantiate_objects/overview/#recursive-instantiation
-    .. [4] https://hydra.cc/docs/advanced/instantiate_objects/overview/#parameter-conversion-strategies
-    .. [5] https://docs.python.org/3/library/dataclasses.html
-    .. [6] https://hydra.cc/docs/tutorials/structured_config/defaults/
-    .. [7] https://hydra.cc/docs/advanced/defaults_list/
+        >>> def faren_to_celsius(temp_f):  # our target
+        ...     return ((temp_f - 32) * 5) / 9
 
-    See Also
-    --------
-    instantiate: Instantiates a configuration created by `builds`, returning the instantiated target.
-    make_custom_builds_fn: Returns a new `builds` function with customized default values.
-    make_config: Creates a general config with customized field names, default values, and annotations.
-    get_target: Returns the target-object from a targeted structured config.
-    just: Produces a config that, when instantiated by Hydra, "just" returns the un-instantiated target-object.
-    to_yaml: Serialize a config as a yaml-formatted string.
+        >>> def change_celcius_to_kelvin(celc_func):  # our wrapper
+        ...     def wraps(*args, **kwargs):
+        ...         return 273.15 + celc_func(*args, **kwargs)
+        ...     return wraps
 
-    Examples
-    --------
-    These examples describe:
+        >>> AsCelcius = builds(faren_to_celsius)
+        >>> AsKelvin = builds(faren_to_celsius, zen_wrappers=change_celcius_to_kelvin)
+        >>> instantiate(AsCelcius, temp_f=32)
+        0.0
+        >>> instantiate(AsKelvin, temp_f=32)
+        273.15
 
-    - Basic usage
-    - Creating a partial config
-    - Auto-populating parameters
-    - Composing configs via inheritance
-    - Runtime validation performed by builds
-    - Using meta-fields
-    - Using zen-wrappers
-    - Creating a pickle-compatible config
-    - Creating a frozen config
-    - Support for partial'd targets
+        **Creating a pickle-compatible config**
 
-    A helpful utility for printing examples
+        The dynamically-generated classes created by `builds` can be made pickle-compatible
+        by specifying the name of the symbol that it is assigned to and the module in which
+        it was defined.
 
-    >>> from hydra_zen import builds, instantiate, to_yaml
-    >>> def pyaml(x):
-    ...     # for pretty printing configs
-    ...     print(to_yaml(x))
+        .. code-block:: python
 
-    **Basic Usage**
+        # contents of mylib/foo.py
+        from pickle import dumps, loads
 
-    Lets create a basic config that describes how to 'build' a particular dictionary.
+        DictConf = builds(dict,
+                            zen_dataclass={'module': 'mylib.foo',
+                                            'cls_name': 'DictConf'})
 
-    >>> Conf = builds(dict, a=1, b='x')
+        assert DictConf is loads(dumps(DictConf))
 
-    The resulting config is a dataclass with the following signature and attributes:
 
-    >>> Conf  # signature: Conf(a: Any = 1, b: Any = 'x')
-    <class 'types.Builds_dict'>
+        **Creating a frozen config**
 
-    >>> pyaml(Conf)
-    _target_: builtins.dict
-    a: 1
-    b: x
+        Let's create a config object whose instances will by "frozen" (i.e., immutable).
 
-    The `instantiate` function is used to enact this build – to create the dictionary.
+        >>> RouterConfig = builds(dict, ip_address=None, zen_dataclass={'frozen': True})
+        >>> my_router = RouterConfig(ip_address="192.168.56.1")  # an immutable instance
 
-    >>> instantiate(Conf)  # calls: `dict(a=1, b='x')`
-    {'a': 1, 'b': 'x'}
+        Attempting to overwrite the attributes of ``my_router`` will raise.
 
-    The default parameters that we provided can be overridden.
+        >>> my_router.ip_address = "148.109.37.2"
+        FrozenInstanceError: cannot assign to field 'ip_address'
 
-    >>> new_conf = Conf(a=10, b="hi")  # an instance of our dataclass
-    >>> instantiate(new_conf)  # calls: `dict(a=10, b='hi')`
-    {'a': 10, 'b': 'hi'}
+        **Support for partial'd targets**
 
-    Positional arguments are supported.
+        Specifying ``builds(functools.partial(<target>, ...), ...)`` is supported; `builds`
+        will automatically "unpack" a partial'd object that is passed as its target.
 
-    >>> Conf = builds(len, [1, 2, 3])
-    >>> Conf._args_  # type: ignore
-    [1, 2, 3]
-    >>> instantiate(Conf)
-    3
+        >>> import functools
+        >>> partiald_dict = functools.partial(dict, a=1, b=2)
+        >>> Conf = builds(partiald_dict)  # signature: (a = 1, b = 2)
+        >>> instantiate(Conf)  # equivalent to calling: `partiald_dict()`
+        {'a': 1, 'b': 2}
+        >>> instantiate(Conf(a=-4))  # equivalent to calling: `partiald_dict(a=-4)`
+        {'a': -4, 'b': 2}
+        """
 
-    **Creating a Partial Config**
+        zen_convert_settings = _utils.merge_settings(
+            zen_convert, _BUILDS_CONVERT_SETTINGS
+        )
+        if zen_dataclass is None:
+            zen_dataclass = {}
 
-    `builds` can be used to partially-configure a target. Let's
-    create a config for the following function
+        # initial validation
+        _utils.parse_dataclass_options(zen_dataclass)
 
-    >>> def a_two_tuple(x: int, y: float): return x, y
+        if "frozen" in kwargs_for_target:
+            warnings.warn(
+                HydraZenDeprecationWarning(
+                    "Specifying `builds(..., frozen=<...>)` is deprecated. Instead, "
+                    "specify `builds(..., zen_dataclass={'frozen': <...>})"
+                ),
+                stacklevel=2,
+            )
+            zen_dataclass["frozen"] = kwargs_for_target.pop("frozen")
 
-    such that we only configure the parameter ``x``.
+        if "dataclass_name" in kwargs_for_target:
+            warnings.warn(
+                HydraZenDeprecationWarning(
+                    "Specifying `builds(..., dataclass_name=<...>)` is deprecated. "
+                    "Instead specify `builds(..., zen_dataclass={'cls_name': <...>})"
+                ),
+                stacklevel=2,
+            )
+            zen_dataclass["cls_name"] = kwargs_for_target.pop("dataclass_name")
+        if not builds_bases:
+            builds_bases = zen_dataclass.get("bases", ())
 
-    >>> PartialConf = builds(a_two_tuple, x=1, zen_partial=True)  # configures only `x`
-    >>> pyaml(PartialConf)
-    _target_: __main__.a_two_tuple
-    _partial_: true
-    x: 1
+        dataclass_options = _utils.parse_dataclass_options(zen_dataclass)
+        dataclass_name = dataclass_options.pop("cls_name", None)
+        module = dataclass_options.pop("module", None)
 
-    Instantiating this config will return ``functools.partial(a_two_tuple, x=1)``.
+        del zen_convert
 
-    >>> partial_func = instantiate(PartialConf)
-    >>> partial_func
-    functools.partial(<function a_two_tuple at 0x00000220A7820EE0>, x=1)
+        if not pos_args and not kwargs_for_target:
+            # `builds()`
+            raise TypeError(
+                "builds() missing 1 required positional argument: 'hydra_target'"
+            )
+        elif not pos_args:
+            # `builds(hydra_target=int)`
+            raise TypeError(
+                "builds() missing 1 required positional-only argument: 'hydra_target'"
+                "\nChange `builds(hydra_target=<target>, ...)` to `builds(<target>, ...)`"
+            )
 
-    And thus the remaining parameter can be provided post-instantiation.
+        target, *_pos_args = pos_args
 
-    >>> partial_func(y=22.0)  # providing the remaining parameter
-    (1, 22.0)
+        if isinstance(target, functools.partial):
+            # partial'd args must come first, then user-specified args
+            # otherwise, the parial'd args will take precedent, which
+            # does not align with the behavior of partial itself
+            _pos_args = list(target.args) + _pos_args
+            kwargs_for_target = {**target.keywords, **kwargs_for_target}
+            target = target.func
 
-    **Auto-populating parameters**
+        BUILDS_ERROR_PREFIX = _utils.building_error_prefix(target)
 
-    The configurable parameters of a target can be auto-populated in our config.
-    Suppose we want to configure the following function.
+        del pos_args
 
-    >>> def bar(x: bool, y: str = 'foo'): return x, y
+        if not callable(target):
+            raise TypeError(
+                BUILDS_ERROR_PREFIX
+                + "In `builds(<target>, ...), `<target>` must be callable/instantiable"
+            )
 
-    The following config will have a signature that matches ``f``; the
-    annotations and default values of the parameters of ``f`` are explicitly
-    incorporated into the config.
+        if not isinstance(populate_full_signature, bool):
+            raise TypeError(
+                f"`populate_full_signature` must be a boolean type, got: {populate_full_signature}"
+            )
 
-    >>> # signature: `Builds_bar(x: bool, y: str = 'foo')`
-    >>> Conf = builds(bar, populate_full_signature=True)
-    >>> pyaml(Conf)
-    _target_: __main__.bar
-    x: ???
-    'y': foo
+        if zen_partial is not None and not isinstance(zen_partial, bool):
+            raise TypeError(f"`zen_partial` must be a boolean type, got: {zen_partial}")
 
-    Annotations will be used by Hydra to provide limited runtime type-checking during
-    instantiation. Here, we'll pass a float for ``x``, which expects a boolean value.
+        _utils.validate_hydra_options(
+            hydra_recursive=hydra_recursive, hydra_convert=hydra_convert
+        )
 
-    >>> instantiate(Conf(x=10.0))  # type: ignore
-    ValidationError: Value '10.0' is not a valid bool (type float)
-        full_key: x
-        object_type=Builds_func
+        if any(not (is_dataclass(_b) and isinstance(_b, type)) for _b in builds_bases):
+            raise TypeError("All `build_bases` must be a tuple of dataclass types")
 
-    **Composing configs via inheritance**
+        if zen_meta is None:
+            zen_meta = {}
 
-    Because a config produced via `builds` is simply a class-object, we can
-    compose configs via class inheritance.
+        if not isinstance(zen_meta, Mapping):
+            raise TypeError(
+                f"`zen_meta` must be a mapping (e.g. a dictionary), got: {zen_meta}"
+            )
 
-    >>> ParentConf = builds(dict, a=1, b=2)
-    >>> ChildConf = builds(dict, b=-2, c=-3, builds_bases=(ParentConf,))
-    >>> instantiate(ChildConf)
-    {'a': 1, 'b': -2, 'c': -3}
-    >>> issubclass(ChildConf, ParentConf)
-    True
+        if any(not isinstance(_key, str) for _key in zen_meta):
+            raise TypeError(
+                f"`zen_meta` must be a mapping whose keys are strings, got key(s):"
+                f" {','.join(str(_key) for _key in zen_meta if not isinstance(_key, str))}"
+            )
 
-    .. _builds-validation:
+        target_path: str
+        if (
+            zen_convert_settings["flat_target"]
+            and isinstance(target, type)
+            and is_dataclass(target)
+            and hasattr(target, TARGET_FIELD_NAME)
+        ):
+            # pass through _target_ field
+            target_path = safe_getattr(target, TARGET_FIELD_NAME)
+        else:
+            target_path = cls._get_obj_path(target)
+
+        if zen_wrappers is not None:
+            if not isinstance(zen_wrappers, Sequence) or isinstance(zen_wrappers, str):
+                zen_wrappers = (zen_wrappers,)
+
+            validated_wrappers: Sequence[Union[str, Builds[Any]]] = []
+            for wrapper in zen_wrappers:
+                if wrapper is None:
+                    continue
+                # We are intentionally keeping each condition branched
+                # so that test-coverage will be checked for each one
+                if isinstance(wrapper, functools.partial):
+                    wrapper = ZEN_VALUE_CONVERSION[functools.partial](wrapper)
+
+                if is_builds(wrapper):
+                    # If Hydra's locate function starts supporting importing literals
+                    # – or if we decide to ship our own locate function –
+                    # then we should get the target of `wrapper` and make sure it is callable
+                    if is_just(wrapper):
+                        # `zen_wrappers` handles importing string; we can
+                        # eliminate the indirection of Just and "flatten" this
+                        # config
+                        validated_wrappers.append(
+                            safe_getattr(wrapper, JUST_FIELD_NAME)
+                        )
+                    else:
+                        if hydra_recursive is False:
+                            warnings.warn(
+                                "A structured config was supplied for `zen_wrappers`. Its parent config has "
+                                "`hydra_recursive=False`.\n If this value is not toggled to `True`, the config's "
+                                "instantiation will result in an error"
+                            )
+                        validated_wrappers.append(wrapper)
+
+                elif callable(wrapper):
+                    validated_wrappers.append(cls._get_obj_path(wrapper))
+
+                elif isinstance(wrapper, str):
+                    # Assumed that wrapper is either a valid omegaconf-style interpolation string
+                    # or a "valid" path for importing an object. The latter seems hopeless for validating:
+                    # https://stackoverflow.com/a/47538106/6592114
+                    # so we can't make any assurances here.
+                    validated_wrappers.append(wrapper)
+                else:
+                    raise TypeError(
+                        f"`zen_wrappers` requires a callable, targeted config, or a string, got: {wrapper}"
+                    )
 
-    **Runtime validation performed by builds**
+            del zen_wrappers
+            validated_wrappers = tuple(validated_wrappers)
+        else:
+            validated_wrappers = ()
+
+        # Check for reserved names
+        for _name in chain(kwargs_for_target, zen_meta):
+            if _name in HYDRA_FIELD_NAMES:
+                err_msg = f"The field-name specified via `builds(..., {_name}=<...>)` is reserved by Hydra."
+                if _name != TARGET_FIELD_NAME:
+                    raise ValueError(
+                        err_msg
+                        + f" You can set this parameter via `builds(..., hydra_{_name[1:-1]}=<...>)`"
+                    )
+                else:
+                    raise ValueError(err_msg)
+            if _name.startswith(("hydra_", "_zen_", "zen_")):
+                raise ValueError(
+                    f"The field-name specified via `{_name}=<...>` is reserved by hydra-zen."
+                    " You can manually create a dataclass to utilize this name in a structured config."
+                )
 
-    Misspelled parameter names and other invalid configurations for the target’s
-    signature will be caught by `builds` so that such errors are caught prior to
-    instantiation.
+        target_field: List[Union[Tuple[str, Type[Any]], Tuple[str, Type[Any], Any]]]
 
-    >>> def func(a_number: int): pass
+        # zen_partial behavior:
+        #
+        # If zen_partial is not None: zen_partial dictates if output is PartialBuilds
+        #
+        # If zen_partial is None:
+        #   - closest parent with partial-flag specified determines
+        #     if output is PartialBuilds
+        #   - if no parent, output is Builds
+        #
+        # If _partial_=True is inherited but zen-processing is used
+        #    then set _partial_=False, _zen_partial=zen_partial
+        #
+        base_hydra_partial: Optional[
+            bool
+        ] = None  # state of closest parent with _partial_
+        base_zen_partial: Optional[
+            bool
+        ] = None  # state of closest parent with _zen_partial
+
+        # reflects state of closest parent that has partial field specified
+        parent_partial: Optional[bool] = None
+
+        for base in builds_bases:
+            _set_this_iteration = False
+            if base_hydra_partial is None:
+                base_hydra_partial = safe_getattr(base, PARTIAL_FIELD_NAME, None)
+                if parent_partial is None:
+                    parent_partial = base_hydra_partial
+                    _set_this_iteration = True
+
+            if base_zen_partial is None:
+                base_zen_partial = safe_getattr(base, ZEN_PARTIAL_FIELD_NAME, None)
+                if parent_partial is None or (
+                    _set_this_iteration and base_zen_partial is not None
+                ):
+                    parent_partial = parent_partial or base_zen_partial
+
+            del _set_this_iteration
+
+        if zen_partial is None:
+            # zen_partial is inherited
+            zen_partial = parent_partial
+
+        del parent_partial
+
+        requires_partial_field = zen_partial is not None
+
+        requires_zen_processing: Final[bool] = (
+            bool(zen_meta)
+            or bool(validated_wrappers)
+            or any(uses_zen_processing(b) for b in builds_bases)
+        )
 
-    >>> builds(func, a_nmbr=2)  # misspelled parameter name
-    TypeError: Building: func ..
+        if base_zen_partial:
+            assert requires_zen_processing
 
-    >>> builds(func, 1, 2)  # too many arguments
-    TypeError: Building: func ..
+        del base_zen_partial
 
-    >>> BaseConf = builds(func, a_number=2)
-    >>> builds(func, 1, builds_bases=(BaseConf,))  # too many args (via inheritance)
-    TypeError: Building: func ..
+        if not requires_zen_processing and requires_partial_field:
+            target_field = [
+                (
+                    TARGET_FIELD_NAME,
+                    str,
+                    _utils.field(default=target_path, init=False),
+                ),
+                (
+                    PARTIAL_FIELD_NAME,
+                    bool,
+                    _utils.field(default=bool(zen_partial), init=False),
+                ),
+            ]
+        elif requires_zen_processing:
+            # target is `hydra_zen.funcs.zen_processing`
+            target_field = [
+                (
+                    TARGET_FIELD_NAME,
+                    str,
+                    _utils.field(default=ZEN_PROCESSING_LOCATION, init=False),
+                ),
+                (
+                    ZEN_TARGET_FIELD_NAME,
+                    str,
+                    _utils.field(default=target_path, init=False),
+                ),
+            ]
 
-    >>> # value type not supported by Hydra
-    >>> builds(int, (i for i in range(10)))  # type: ignore
-    hydra_zen.errors.HydraZenUnsupportedPrimitiveError: Building: int ..
+            if requires_partial_field:
+                target_field.append(
+                    (
+                        ZEN_PARTIAL_FIELD_NAME,
+                        bool,
+                        _utils.field(default=bool(zen_partial), init=False),
+                    ),
+                )
+                if base_hydra_partial:
+                    # Must explicitly set _partial_=False to prevent inheritance
+                    target_field.append(
+                        (
+                            PARTIAL_FIELD_NAME,
+                            bool,
+                            _utils.field(default=False, init=False),
+                        ),
+                    )
 
+            if zen_meta:
+                target_field.append(
+                    (
+                        META_FIELD_NAME,
+                        Tuple[str, ...],
+                        _utils.field(default=tuple(zen_meta), init=False),
+                    ),
+                )
 
-    .. _meta-field:
+            if validated_wrappers:
+                if zen_meta:
+                    # Check to see
+                    tuple(
+                        _utils.check_suspicious_interpolations(
+                            validated_wrappers, zen_meta=zen_meta, target=target
+                        )
+                    )
+                if len(validated_wrappers) == 1:
+                    # we flatten the config to avoid unnecessary list
+                    target_field.append(
+                        (
+                            ZEN_WRAPPERS_FIELD_NAME,
+                            Union[
+                                Union[str, Builds[Any]],
+                                Tuple[Union[str, Builds[Any]], ...],
+                            ],
+                            _utils.field(default=validated_wrappers[0], init=False),
+                        ),
+                    )
+                else:
+                    target_field.append(
+                        (
+                            ZEN_WRAPPERS_FIELD_NAME,
+                            Union[
+                                Union[str, Builds[Any]],
+                                Tuple[Union[str, Builds[Any]], ...],
+                            ],
+                            _utils.field(default=validated_wrappers, init=False),
+                        ),
+                    )
+        else:
+            target_field = [
+                (
+                    TARGET_FIELD_NAME,
+                    str,
+                    _utils.field(default=target_path, init=False),
+                )
+            ]
 
-    **Using meta-fields**
+        del base_hydra_partial
+        del requires_partial_field
 
-    Meta-fields are fields that are included in a config but are excluded by the
-    instantiation process. Thus arbitrary metadata can be attached to a config.
+        base_fields = target_field
 
-    Let's create a config whose fields reference a meta-field via
-    relative-interpolation [2]_.
+        if hydra_recursive is not None:
+            base_fields.append(
+                (
+                    RECURSIVE_FIELD_NAME,
+                    bool,
+                    _utils.field(default=hydra_recursive, init=False),
+                )
+            )
 
-    >>> Conf = builds(dict, a="${.s}", b="${.s}", zen_meta=dict(s=-10))
-    >>> instantiate(Conf)
-    {'a': -10, 'b': -10}
-    >>> instantiate(Conf, s=2)
-    {'a': 2, 'b': 2}
+        if hydra_convert is not None:
+            base_fields.append(
+                (
+                    CONVERT_FIELD_NAME,
+                    str,
+                    _utils.field(default=hydra_convert, init=False),
+                )
+            )
 
-    .. _zen-wrapper:
+        if hydra_defaults is not None:
+            if not _utils.valid_defaults_list(hydra_defaults):
+                raise HydraZenValidationError(
+                    f"`hydra_defaults` must be type `None | list[str | dict[str, str | list[str] | None ]]`"
+                    f", Got: {repr(hydra_defaults)}"
+                )
+            hydra_defaults = cls._sanitize_collection(
+                hydra_defaults, convert_dataclass=False
+            )
+            base_fields.append(
+                (
+                    DEFAULTS_LIST_FIELD_NAME,
+                    List[Any],
+                    _utils.field(
+                        default_factory=lambda: list(hydra_defaults),
+                        init=False,
+                    ),
+                )
+            )
 
-    **Using zen-wrappers**
+        if _pos_args:
+            base_fields.append(
+                (
+                    POS_ARG_FIELD_NAME,
+                    Tuple[Any, ...],
+                    _utils.field(
+                        default=tuple(
+                            cls._make_hydra_compatible(
+                                x,
+                                error_prefix=BUILDS_ERROR_PREFIX,
+                                convert_dataclass=zen_convert_settings["dataclass"],
+                            )
+                            for x in _pos_args
+                        ),
+                        init=False,
+                    ),
+                )
+            )
 
-    Zen-wrappers enables us to make arbitrary changes to ``<hydra_target>``, its inputs,
-    and/or its outputs during the instantiation process.
+        _sig_target = cls._get_sig_obj(target)
 
-    Let's use a wrapper to add a unit-conversion step to a config. We'll modify a
-    config that builds a function, which converts a temperature in Fahrenheit to
-    Celsius, and add a wrapper to it so that it will convert from Fahrenheit to
-    Kelvin instead.
+        try:
+            # We want to rely on `inspect.signature` logic for raising
+            # against an uninspectable sig, before we start inspecting
+            # class-specific attributes below.
+            signature_params = dict(inspect.signature(target).parameters)
+        except ValueError:
+            if populate_full_signature:
+                raise ValueError(
+                    BUILDS_ERROR_PREFIX
+                    + f"{target} does not have an inspectable signature. "
+                    f"`builds({_utils.safe_name(target)}, populate_full_signature=True)` is not supported"
+                )
+            signature_params: Dict[str, inspect.Parameter] = {}
+            # We will turn off signature validation for objects that didn't have
+            # a valid signature. This will enable us to do things like `build(dict, a=1)`
+            target_has_valid_signature: bool = False
+        else:
+            # Dealing with this bug: https://bugs.python.org/issue40897
+            #
+            # In Python < 3.9.1, `inspect.signature will look first to
+            # any implementation __new__, even if it is inherited and if
+            # there is a "fresher" __init__.
+            #
+            # E.g. anything that inherits from `typing.Generic` and
+            # does not implement its own __new__ will have a reported sig
+            # of (*args, **kwargs)
+            #
+            # This looks specifically for the scenario that the target
+            # has inherited from a parent that implements __new__ and
+            # the target implements only __init__.
+
+            if _sig_target is not target:
+                _params = tuple(inspect.signature(_sig_target).parameters.items())
+
+                if (
+                    _params and _params[0][1].kind is not _VAR_POSITIONAL
+                ):  # pragma: no cover
+                    # Exclude self/cls
+                    #
+                    # There are weird edge cases
+                    # where the first arg is *args, not self.
+                    _params = _params[1:]
+                else:  # pragma: no cover
+                    pass
+
+                signature_params = {k: v for k, v in _params}
+                del _params
+
+            target_has_valid_signature: bool = True
+
+        if is_dataclass(target):
+            # Update `signature_params` so that any param with `default=<factory>`
+            # has its default replaced with `<factory>()`
+            # If this is a mutable value, `builds` will automatically re-pack
+            # it using a default factory
+            _fields = {f.name: f for f in fields(target)}
+            _update = {}
+            for name, param in signature_params.items():
+                if name not in _fields:
+                    # field is InitVar
+                    continue
+                f = _fields[name]
+                if f.default_factory is not MISSING:
+                    _update[name] = inspect.Parameter(
+                        name,
+                        param.kind,
+                        annotation=param.annotation,
+                        default=f.default_factory(),
+                    )
+            signature_params.update(_update)
+            if (
+                zen_convert_settings["flat_target"]
+                and TARGET_FIELD_NAME in signature_params
+            ):
+                signature_params.pop(TARGET_FIELD_NAME)
+            del _update
+            del _fields
+
+        # `get_type_hints` properly resolves forward references, whereas annotations from
+        # `inspect.signature` do not
+        try:
+            type_hints = get_type_hints(_sig_target)
+
+            del _sig_target
+            # We don't need to pop self/class because we only make on-demand
+            # requests from `type_hints`
+
+        except (
+            TypeError,  # ufuncs, which do not have inspectable type hints
+            NameError,  # Unresolvable forward reference
+            AttributeError,  # Class doesn't have "__new__" or "__init__"
+        ):
+            type_hints: Dict[str, Any] = {}
+
+        sig_by_kind: Dict[Any, List[inspect.Parameter]] = {
+            _POSITIONAL_ONLY: [],
+            _POSITIONAL_OR_KEYWORD: [],
+            _VAR_POSITIONAL: [],
+            _KEYWORD_ONLY: [],
+            _VAR_KEYWORD: [],
+        }
 
-    >>> def faren_to_celsius(temp_f):  # our target
-    ...     return ((temp_f - 32) * 5) / 9
+        for p in signature_params.values():
+            sig_by_kind[p.kind].append(p)
 
-    >>> def change_celcius_to_kelvin(celc_func):  # our wrapper
-    ...     def wraps(*args, **kwargs):
-    ...         return 273.15 + celc_func(*args, **kwargs)
-    ...     return wraps
+        # these are the names of the only parameters in the signature of `target` that can
+        # be referenced by name
+        nameable_params_in_sig: Set[str] = {
+            p.name
+            for p in chain(
+                sig_by_kind[_POSITIONAL_OR_KEYWORD], sig_by_kind[_KEYWORD_ONLY]
+            )
+        }
 
-    >>> AsCelcius = builds(faren_to_celsius)
-    >>> AsKelvin = builds(faren_to_celsius, zen_wrappers=change_celcius_to_kelvin)
-    >>> instantiate(AsCelcius, temp_f=32)
-    0.0
-    >>> instantiate(AsKelvin, temp_f=32)
-    273.15
+        if not _pos_args and builds_bases:
+            # pos_args is potentially inherited
+            for _base in builds_bases:
+                _pos_args = safe_getattr(_base, POS_ARG_FIELD_NAME, ())
 
-    **Creating a pickle-compatible config**
+                # validates
+                _pos_args = tuple(
+                    cls._make_hydra_compatible(
+                        x, allow_zen_conversion=False, convert_dataclass=False
+                    )
+                    for x in _pos_args
+                )
+                if _pos_args:
+                    break
+
+        fields_set_by_bases: Set[str] = {
+            _field.name
+            for _base in builds_bases
+            for _field in fields(_base)
+            if _field.name not in HYDRA_FIELD_NAMES
+            and not _field.name.startswith("_zen_")
+        }
 
-    The dynamically-generated classes created by `builds` can be made pickle-compatible
-    by specifying the name of the symbol that it is assigned to and the module in which
-    it was defined.
+        # Validate that user-specified arguments satisfy target's signature.
+        # Should catch:
+        #    - bad parameter names
+        #    - too many parameters-by-position
+        #    - multiple values specified for parameter (via positional and by-name)
+        #
+        # We don't raise on an under-specified signature because it is possible that the
+        # resulting dataclass will simply be inherited from and extended.
+        # The issues we catch here cannot be fixed downstream.
+        if target_has_valid_signature:
+            if not sig_by_kind[_VAR_KEYWORD]:
+                # check for unexpected kwargs
+                if not set(kwargs_for_target) <= nameable_params_in_sig:
+                    _unexpected = set(kwargs_for_target) - nameable_params_in_sig
+                    raise TypeError(
+                        BUILDS_ERROR_PREFIX
+                        + f"The following unexpected keyword argument(s) was specified for {target_path} "
+                        f"via `builds`: {', '.join(_unexpected)}"
+                    )
+                if not fields_set_by_bases <= nameable_params_in_sig and not (
+                    fields_set_by_bases - nameable_params_in_sig
+                ) <= set(zen_meta):
+                    # field inherited by base is not present in sig
+                    # AND it is not excluded via `zen_meta`
+                    _unexpected = fields_set_by_bases - nameable_params_in_sig
+                    raise TypeError(
+                        BUILDS_ERROR_PREFIX
+                        + f"The following unexpected keyword argument(s) for {target_path} "
+                        f"was specified via inheritance from a base class: "
+                        f"{', '.join(_unexpected)}"
+                    )
 
-    .. code-block:: python
+            if _pos_args:
+                named_args = set(kwargs_for_target).union(fields_set_by_bases)
 
-       # contents of mylib/foo.py
-       from pickle import dumps, loads
+                # indicates that number of parameters that could be specified by name,
+                # but are specified by position
+                _num_nameable_args_by_position = max(
+                    0, len(_pos_args) - len(sig_by_kind[_POSITIONAL_ONLY])
+                )
+                if named_args:
+                    # check for multiple values for arg, specified both via positional and kwarg
+                    # E.g.: def f(x, y): ...
+                    # f(1, 2, y=3)  # multiple values for `y`
+                    for param in sig_by_kind[_POSITIONAL_OR_KEYWORD][
+                        :_num_nameable_args_by_position
+                    ]:
+                        if param.name in named_args:
+                            raise TypeError(
+                                BUILDS_ERROR_PREFIX
+                                + f"Multiple values for argument {param.name} were specified for "
+                                f"{target_path} via `builds`"
+                            )
+                if not sig_by_kind[
+                    _VAR_POSITIONAL
+                ] and _num_nameable_args_by_position > len(
+                    sig_by_kind[_POSITIONAL_OR_KEYWORD]
+                ):
+                    # Too many positional args specified.
+                    # E.g.: def f(x, y): ...
+                    # f(1, 2, 3)
+                    _num_positional = len(sig_by_kind[_POSITIONAL_ONLY]) + len(
+                        sig_by_kind[_POSITIONAL_OR_KEYWORD]
+                    )
+                    _num_with_default = sum(
+                        p.default is not inspect.Parameter.empty
+                        and p.kind is _POSITIONAL_OR_KEYWORD
+                        for p in signature_params.values()
+                    )
+                    _permissible = (
+                        f"{_num_positional}"
+                        if not _num_with_default
+                        else f"{_num_positional - _num_with_default} to {_num_positional}"
+                    )
+                    raise TypeError(
+                        BUILDS_ERROR_PREFIX
+                        + f"{target_path} takes {_permissible} positional args, but "
+                        f"{len(_pos_args)} were specified via `builds`"
+                    )
 
-       DictConf = builds(dict,
-                         zen_dataclass={'module': 'mylib.foo',
-                                        'cls_name': 'DictConf'})
+        # Create valid dataclass fields from the user-specified values
+        #
+        # user_specified_params: arg-name -> (arg-name, arg-type, field-w-value)
+        #  - arg-type: taken from the parameter's annotation in the target's signature
+        #    and is resolved to one of the type annotations supported by hydra if possible,
+        #    otherwise, is Any
+        #  - arg-value: mutable values are automatically specified using default-factory
+        user_specified_named_params: Dict[str, Tuple[str, type, Any]] = {
+            name: (name, type_hints.get(name, Any), value)
+            for name, value in kwargs_for_target.items()
+        }
 
-       assert DictConf is loads(dumps(DictConf))
+        if populate_full_signature is True:
+            # Populate dataclass fields based on the target's signature.
+            #
+            # A user-specified parameter value (via `kwargs_for_target`) takes precedent over
+            # the default value from the signature
+
+            # Fields with default values must come after those without defaults,
+            # so we will collect these as we loop through the parameters and
+            # add them to the fields at the end.
+            #
+            # Parameter ordering should only differ from the target's signature
+            # if the user specified a value for a parameter that had no default
+            _fields_with_default_values: List[Field_Entry] = []
+
+            # we need to keep track of what user-specified params we have set
+            _seen: Set[str] = set()
+
+            for n, param in enumerate(signature_params.values()):
+                if n + 1 <= len(_pos_args):
+                    # Positional parameters are populated from "left to right" in the signature.
+                    # We have already done validation, so we know that positional params aren't redundant
+                    # with named params (including inherited params).
+                    continue
+
+                if param.name not in nameable_params_in_sig:
+                    # parameter cannot be specified by name
+                    continue
+
+                if param.name in user_specified_named_params:
+                    # user-specified parameter is preferred
+                    _fields_with_default_values.append(
+                        user_specified_named_params[param.name]
+                    )
+                    _seen.add(param.name)
+                else:
+                    # any parameter whose default value is None is automatically
+                    # annotated with `Optional[...]`. This improves flexibility with
+                    # Hydra's type-validation
+                    param_field = (
+                        param.name,
+                        type_hints.get(param.name, Any),
+                    )
 
+                    if param.default is inspect.Parameter.empty:
+                        if not zen_partial:
+                            # No default value specified in signature or by the user.
+                            # We don't include these fields if the user specified a partial build
+                            # because we assume that they want to fill these in by using partial
+                            base_fields.append(param_field)
+                    else:
+                        param_field += (param.default,)
+                        _fields_with_default_values.append(param_field)
+
+            base_fields.extend(_fields_with_default_values)
+
+            if sig_by_kind[_VAR_KEYWORD]:
+                # if the signature has **kwargs, then we need to add any user-specified
+                # parameters that have not already been added
+                base_fields.extend(
+                    entry
+                    for name, entry in user_specified_named_params.items()
+                    if name not in _seen
+                )
+        else:
+            base_fields.extend(user_specified_named_params.values())
 
-    **Creating a frozen config**
+        if zen_meta:
+            _meta_names = set(zen_meta)
 
-    Let's create a config object whose instances will by "frozen" (i.e., immutable).
+            if _meta_names & nameable_params_in_sig:
+                raise ValueError(
+                    f"`builds(..., zen_meta=<...>)`: `zen_meta` cannot not specify "
+                    f"names that exist in the target's signature: "
+                    f"{','.join(_meta_names & nameable_params_in_sig)}"
+                )
 
-    >>> RouterConfig = builds(dict, ip_address=None, zen_dataclass={'frozen': True})
-    >>> my_router = RouterConfig(ip_address="192.168.56.1")  # an immutable instance
+            if _meta_names & set(user_specified_named_params):
+                raise ValueError(
+                    f"`builds(..., zen_meta=<...>)`: `zen_meta` cannot not specify "
+                    f"names that are common with those specified in **kwargs_for_target: "
+                    f"{','.join(_meta_names & set(user_specified_named_params))}"
+                )
 
-    Attempting to overwrite the attributes of ``my_router`` will raise.
+            # We don't check for collisions between `zen_meta` names and the
+            # names of inherited fields. Thus `zen_meta` can effectively be used
+            # to "delete" names from a config, via inheritance.
+            base_fields.extend((name, Any, value) for name, value in zen_meta.items())
 
-    >>> my_router.ip_address = "148.109.37.2"
-    FrozenInstanceError: cannot assign to field 'ip_address'
+        if dataclass_name is None:
+            if zen_partial is not True:
+                dataclass_name = f"Builds_{_utils.safe_name(target)}"
+            else:
+                dataclass_name = f"PartialBuilds_{_utils.safe_name(target)}"
+
+        # validate that fields set via bases are OK; cannot perform zen-casting
+        # on fields
+        for base in builds_bases:
+            for field_ in fields(base):
+                if field_.default is not MISSING:
+                    # performs validation
+                    cls._make_hydra_compatible(
+                        field_.default,
+                        allow_zen_conversion=False,
+                        error_prefix=BUILDS_ERROR_PREFIX,
+                        field_name=field_.name + " (set via inheritance)",
+                        convert_dataclass=False,
+                    )
+                del field_
+
+        # sanitize all types and configured values
+        sanitized_base_fields: List[
+            Union[Tuple[str, Any], Tuple[str, Any, Field[Any]]]
+        ] = []
+
+        for item in base_fields:
+            name = item[0]
+            type_ = item[1]
+            if len(item) == 2:
+                sanitized_base_fields.append((name, cls._sanitized_type(type_)))
+            else:
+                assert len(item) == 3, item
+                value = item[-1]
+
+                if not isinstance(value, _Field):
+                    _field = cls._sanitized_field(
+                        value,
+                        error_prefix=BUILDS_ERROR_PREFIX,
+                        field_name=item[0],
+                        convert_dataclass=zen_convert_settings["dataclass"],
+                    )
+                else:
+                    _field = value
+
+                # If `.default` is not set, then `value` is a Hydra-supported mutable
+                # value, and thus it is "sanitized"
+                sanitized_value = safe_getattr(_field, "default", value)
+                sanitized_type = (
+                    cls._sanitized_type(type_, wrap_optional=sanitized_value is None)
+                    if _retain_type_info(
+                        type_=type_,
+                        value=sanitized_value,
+                        hydra_recursive=hydra_recursive,
+                    )
+                    else Any
+                )
+                sanitized_base_fields.append((name, sanitized_type, _field))
+                del value
+                del _field
+                del sanitized_value
 
-    **Support for partial'd targets**
+        dataclass_options["cls_name"] = dataclass_name
+        dataclass_options["bases"] = builds_bases
+        assert _utils.parse_strict_dataclass_options(dataclass_options)
 
-    Specifying ``builds(functools.partial(<target>, ...), ...)`` is supported; `builds`
-    will automatically "unpack" a partial'd object that is passed as its target.
+        out = make_dataclass(fields=sanitized_base_fields, **dataclass_options)
 
-    >>> import functools
-    >>> partiald_dict = functools.partial(dict, a=1, b=2)
-    >>> Conf = builds(partiald_dict)  # signature: (a = 1, b = 2)
-    >>> instantiate(Conf)  # equivalent to calling: `partiald_dict()`
-    {'a': 1, 'b': 2}
-    >>> instantiate(Conf(a=-4))  # equivalent to calling: `partiald_dict(a=-4)`
-    {'a': -4, 'b': 2}
-    """
-    zen_convert_settings = _utils.merge_settings(zen_convert, _BUILDS_CONVERT_SETTINGS)
-    if zen_dataclass is None:
-        zen_dataclass = {}
-
-    # initial validation
-    _utils.parse_dataclass_options(zen_dataclass)
-
-    if "frozen" in kwargs_for_target:
-        warnings.warn(
-            HydraZenDeprecationWarning(
-                "Specifying `builds(..., frozen=<...>)` is deprecated. Instead, "
-                "specify `builds(..., zen_dataclass={'frozen': <...>})"
-            ),
-            stacklevel=2,
-        )
-        zen_dataclass["frozen"] = kwargs_for_target.pop("frozen")  # type: ignore
+        if module is not None:
+            out.__module__ = module
 
-    if "dataclass_name" in kwargs_for_target:
-        warnings.warn(
-            HydraZenDeprecationWarning(
-                "Specifying `builds(..., dataclass_name=<...>)` is deprecated. "
-                "Instead specify `builds(..., zen_dataclass={'cls_name': <...>})"
-            ),
-            stacklevel=2,
+        out.__doc__ = (
+            f"A structured config designed to {'partially ' if zen_partial else ''}"
+            f"initialize/call `{target_path}` upon instantiation by hydra."
         )
-        zen_dataclass["cls_name"] = kwargs_for_target.pop("dataclass_name")  # type: ignore
-    if not builds_bases:
-        builds_bases = zen_dataclass.get("bases", ())
-
-    dataclass_options = _utils.parse_dataclass_options(zen_dataclass)
-    dataclass_name = dataclass_options.pop("cls_name", None)
-    module = dataclass_options.pop("module", None)
+        if hasattr(target, "__doc__"):  # pragma: no branch
+            target_doc = target.__doc__
+            if target_doc:
+                out.__doc__ += (
+                    f"\n\nThe docstring for {_utils.safe_name(target)} :\n\n"
+                    + target_doc
+                )
 
-    del zen_convert
+        assert requires_zen_processing is uses_zen_processing(out)
 
-    if not pos_args and not kwargs_for_target:
-        # `builds()`
-        raise TypeError(
-            "builds() missing 1 required positional argument: 'hydra_target'"
+        # _partial_=True should never be relied on when zen-processing is being used.
+        assert not (
+            requires_zen_processing and safe_getattr(out, PARTIAL_FIELD_NAME, False)
         )
-    elif not pos_args:
-        # `builds(hydra_target=int)`
-        raise TypeError(
-            "builds() missing 1 required positional-only argument: 'hydra_target'"
-            "\nChange `builds(hydra_target=<target>, ...)` to `builds(<target>, ...)`"
-        )
-
-    target, *_pos_args = pos_args
-
-    if isinstance(target, functools.partial):
-        # partial'd args must come first, then user-specified args
-        # otherwise, the parial'd args will take precedent, which
-        # does not align with the behavior of partial itself
-        _pos_args = list(target.args) + _pos_args
-        kwargs_for_target = {**target.keywords, **kwargs_for_target}
-        target = target.func
-
-    BUILDS_ERROR_PREFIX = _utils.building_error_prefix(target)
-
-    del pos_args
 
-    if not callable(target):
-        raise TypeError(
-            BUILDS_ERROR_PREFIX
-            + "In `builds(<target>, ...), `<target>` must be callable/instantiable"
+        return cast(
+            Union[Type[Builds[Importable]], Type[BuildsWithSig[Type[R], P]]], out
         )
 
-    if not isinstance(populate_full_signature, bool):
-        raise TypeError(
-            f"`populate_full_signature` must be a boolean type, got: {populate_full_signature}"
+    __call__ = builds
+
+    @overload
+    @classmethod
+    def just(
+        cls,
+        obj: TP,
+        *,
+        zen_convert: Optional[ZenConvert] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        zen_dataclass: Optional[DataclassOptions] = ...,
+    ) -> TP:
+        ...
+
+    @overload
+    @classmethod
+    def just(
+        cls,
+        obj: complex,
+        *,
+        zen_convert: Optional[ZenConvert] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        zen_dataclass: Optional[DataclassOptions] = ...,
+    ) -> "ConfigComplex":
+        ...
+
+    @overload
+    @classmethod
+    def just(
+        cls,
+        obj: TC,
+        *,
+        zen_convert: Optional[ZenConvert] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        zen_dataclass: Optional[DataclassOptions] = ...,
+    ) -> JustT[TC]:
+        ...
+
+    @overload
+    @classmethod
+    def just(
+        cls,
+        obj: TB,
+        *,
+        zen_convert: Optional[ZenConvert] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        zen_dataclass: Optional[DataclassOptions] = ...,
+    ) -> Builds[Type[TB]]:
+        ...
+
+    @overload
+    @classmethod
+    def just(
+        cls,
+        obj: TD,
+        *,
+        zen_convert: Literal[None] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        zen_dataclass: Optional[DataclassOptions] = ...,
+    ) -> Type[Builds[Type[TD]]]:
+        ...
+
+    @overload
+    @classmethod
+    def just(
+        cls,
+        obj: DataClass_,
+        *,
+        zen_convert: ZenConvert,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        zen_dataclass: Optional[DataclassOptions] = ...,
+    ) -> Any:
+        ...
+
+    @overload
+    @classmethod
+    def just(
+        cls,
+        obj: Any,
+        *,
+        zen_convert: Optional[ZenConvert] = ...,
+        hydra_recursive: Optional[bool] = ...,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = ...,
+        zen_dataclass: Optional[DataclassOptions] = ...,
+    ) -> Any:
+        ...
+
+    @classmethod
+    def just(
+        cls,
+        obj: Any,
+        *,
+        zen_convert: Optional[ZenConvert] = None,
+        hydra_recursive: Optional[bool] = None,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
+        zen_dataclass: Optional[DataclassOptions] = None,
+    ) -> Any:
+        """`just(obj)` returns a config that, when instantiated, just returns `obj`.
+
+        I.e., `instantiate(just(obj)) == obj`
+
+        `just` is designed to be idempotent. I.e., `just(obj) == just(just(obj))`
+
+        See the docstring for `hydra_zen.just`
+        """
+        convert_settings = merge_settings(zen_convert, _JUST_CONVERT_SETTINGS)
+        del zen_convert
+        _utils.validate_hydra_options(
+            hydra_recursive=hydra_recursive, hydra_convert=hydra_convert
         )
-
-    if zen_partial is not None and not isinstance(zen_partial, bool):
-        raise TypeError(f"`zen_partial` must be a boolean type, got: {zen_partial}")
-
-    _utils.validate_hydra_options(
-        hydra_recursive=hydra_recursive, hydra_convert=hydra_convert
-    )
-
-    if any(not (is_dataclass(_b) and isinstance(_b, type)) for _b in builds_bases):
-        raise TypeError("All `build_bases` must be a tuple of dataclass types")
-
-    if zen_meta is None:
-        zen_meta = {}
-
-    if not isinstance(zen_meta, Mapping):
-        raise TypeError(
-            f"`zen_meta` must be a mapping (e.g. a dictionary), got: {zen_meta}"
+        if zen_dataclass is None:
+            zen_dataclass = {}
+
+        return cls._make_hydra_compatible(
+            obj,
+            allow_zen_conversion=True,
+            structured_conf_permitted=True,
+            field_name="",
+            error_prefix="",
+            convert_dataclass=convert_settings["dataclass"],
+            hydra_convert=hydra_convert,
+            hydra_recursive=hydra_recursive,
+            zen_dataclass=_utils.parse_dataclass_options(zen_dataclass),
         )
 
-    if any(not isinstance(_key, str) for _key in zen_meta):
-        raise TypeError(
-            f"`zen_meta` must be a mapping whose keys are strings, got key(s):"
-            f" {','.join(str(_key) for _key in zen_meta if not isinstance(_key, str))}"
-        )
+    @classmethod
+    def make_config(
+        cls,
+        *fields_as_args: Union[str, ZenField],
+        hydra_recursive: Optional[bool] = None,
+        hydra_convert: Optional[Literal["none", "partial", "all", "object"]] = None,
+        hydra_defaults: Optional[DefaultsList] = None,
+        zen_dataclass: Optional[DataclassOptions] = None,
+        bases: Tuple[Type[DataClass_], ...] = (),
+        zen_convert: Optional[ZenConvert] = None,
+        **fields_as_kwargs: Union[T, ZenField],
+    ) -> Type[DataClass]:
+        """
+        Returns a config with user-defined field names and, optionally,
+        associated default values and/or type annotations.
+
+        See the docstring for hydra_zen.make_config
+        """
+        convert_settings = _utils.merge_settings(zen_convert, _MAKE_CONFIG_SETTINGS)
+        convert_settings = cast(ZenConvert, convert_settings)
+        del zen_convert
+
+        if zen_dataclass is None:
+            zen_dataclass = {}
+
+        # initial validation
+        _utils.parse_dataclass_options(zen_dataclass)
+
+        if "frozen" in fields_as_kwargs:
+            warnings.warn(
+                HydraZenDeprecationWarning(
+                    "Specifying `builds(frozen=<...>)` is deprecated. Instead, "
+                    "specify `builds(zen_dataclass={'frozen': <...>})"
+                ),
+                stacklevel=2,
+            )
+            zen_dataclass["frozen"] = fields_as_kwargs.pop("frozen")  # type: ignore
 
-    target_path: str
-    if (
-        zen_convert_settings["flat_target"]
-        and isinstance(target, type)
-        and is_dataclass(target)
-        and hasattr(target, TARGET_FIELD_NAME)
-    ):
-        # pass through _target_ field
-        target_path = safe_getattr(target, TARGET_FIELD_NAME)
-    else:
-        target_path = _utils.get_obj_path(target)
-
-    if zen_wrappers is not None:
-        if not isinstance(zen_wrappers, Sequence) or isinstance(zen_wrappers, str):
-            zen_wrappers = (zen_wrappers,)
-
-        validated_wrappers: Sequence[Union[str, Builds[Any]]] = []
-        for wrapper in zen_wrappers:
-            if wrapper is None:
-                continue
-            # We are intentionally keeping each condition branched
-            # so that test-coverage will be checked for each one
-            if isinstance(wrapper, functools.partial):
-                wrapper = ZEN_VALUE_CONVERSION[functools.partial](wrapper)
-
-            if is_builds(wrapper):
-                # If Hydra's locate function starts supporting importing literals
-                # – or if we decide to ship our own locate function –
-                # then we should get the target of `wrapper` and make sure it is callable
-                if is_just(wrapper):
-                    # `zen_wrappers` handles importing string; we can
-                    # eliminate the indirection of Just and "flatten" this
-                    # config
-                    validated_wrappers.append(safe_getattr(wrapper, JUST_FIELD_NAME))
-                else:
-                    if hydra_recursive is False:
-                        warnings.warn(
-                            "A structured config was supplied for `zen_wrappers`. Its parent config has "
-                            "`hydra_recursive=False`.\n If this value is not toggled to `True`, the config's "
-                            "instantiation will result in an error"
-                        )
-                    validated_wrappers.append(wrapper)
+        if "config_name" in fields_as_kwargs:
+            warnings.warn(
+                HydraZenDeprecationWarning(
+                    "Specifying `make_config(config_name=<...>)` is deprecated. "
+                    "Instead specify `make_config(zen_dataclass={'cls_name': <...>})"
+                ),
+                stacklevel=2,
+            )
+            zen_dataclass["cls_name"] = fields_as_kwargs.pop("config_name")  # type: ignore
 
-            elif callable(wrapper):
-                validated_wrappers.append(_utils.get_obj_path(wrapper))
+        if not bases:
+            bases = zen_dataclass.get("bases", ())
 
-            elif isinstance(wrapper, str):
-                # Assumed that wrapper is either a valid omegaconf-style interpolation string
-                # or a "valid" path for importing an object. The latter seems hopeless for validating:
-                # https://stackoverflow.com/a/47538106/6592114
-                # so we can't make any assurances here.
-                validated_wrappers.append(wrapper)
-            else:
+        zen_dataclass.setdefault("cls_name", "Config")
+        dataclass_options = _utils.parse_dataclass_options(zen_dataclass)
+
+        for _field in fields_as_args:
+            if not isinstance(_field, (str, ZenField)):
                 raise TypeError(
-                    f"`zen_wrappers` requires a callable, targeted config, or a string, got: {wrapper}"
+                    f"`fields_as_args` can only consist of field-names (i.e. strings) or "
+                    f"`ZenField` instances. Got: "
+                    f"{', '.join(str(x) for x in fields_as_args if not isinstance(x, (str, ZenField)))}"
                 )
-
-        del zen_wrappers
-        validated_wrappers = tuple(validated_wrappers)
-    else:
-        validated_wrappers = ()
-
-    # Check for reserved names
-    for _name in chain(kwargs_for_target, zen_meta):
-        if _name in HYDRA_FIELD_NAMES:
-            err_msg = f"The field-name specified via `builds(..., {_name}=<...>)` is reserved by Hydra."
-            if _name != TARGET_FIELD_NAME:
+            if isinstance(_field, ZenField) and _field.name is NOTHING:
                 raise ValueError(
-                    err_msg
-                    + f" You can set this parameter via `builds(..., hydra_{_name[1:-1]}=<...>)`"
+                    f"All `ZenField` instances specified in `fields_as_args` must have a "
+                    f"name associated with it. Got: {_field}"
                 )
-            else:
-                raise ValueError(err_msg)
-        if _name.startswith(("hydra_", "_zen_", "zen_")):
-            raise ValueError(
-                f"The field-name specified via `{_name}=<...>` is reserved by hydra-zen."
-                " You can manually create a dataclass to utilize this name in a structured config."
-            )
+        for name, _field in fields_as_kwargs.items():
+            if isinstance(_field, ZenField):
+                if _field.name is not NOTHING and _field.name != name:
+                    raise ValueError(
+                        f"`fields_as_kwargs` specifies conflicting names: the kwarg {name} "
+                        f"is associated with a `ZenField` with name {_field.name}"
+                    )
+                else:
+                    _field.name = name
 
-    target_field: List[Union[Tuple[str, Type[Any]], Tuple[str, Type[Any], Any]]]
-
-    # zen_partial behavior:
-    #
-    # If zen_partial is not None: zen_partial dictates if output is PartialBuilds
-    #
-    # If zen_partial is None:
-    #   - closest parent with partial-flag specified determines
-    #     if output is PartialBuilds
-    #   - if no parent, output is Builds
-    #
-    # If _partial_=True is inherited but zen-processing is used
-    #    then set _partial_=False, _zen_partial=zen_partial
-    #
-    base_hydra_partial: Optional[bool] = None  # state of closest parent with _partial_
-    base_zen_partial: Optional[bool] = None  # state of closest parent with _zen_partial
-
-    # reflects state of closest parent that has partial field specified
-    parent_partial: Optional[bool] = None
-
-    for base in builds_bases:
-        _set_this_iteration = False
-        if base_hydra_partial is None:
-            base_hydra_partial = safe_getattr(base, PARTIAL_FIELD_NAME, None)
-            if parent_partial is None:
-                parent_partial = base_hydra_partial
-                _set_this_iteration = True
-
-        if base_zen_partial is None:
-            base_zen_partial = safe_getattr(base, ZEN_PARTIAL_FIELD_NAME, None)
-            if parent_partial is None or (
-                _set_this_iteration and base_zen_partial is not None
-            ):
-                parent_partial = parent_partial or base_zen_partial
+        if fields_as_args:
+            all_names = [
+                f.name if isinstance(f, ZenField) else f for f in fields_as_args
+            ]
+            all_names.extend(fields_as_kwargs)
 
-        del _set_this_iteration
+            if len(all_names) != len(set(all_names)):
+                raise ValueError(
+                    f"`fields_as_args` cannot specify the same field-name multiple times."
+                    f" Got multiple entries for:"
+                    f" {', '.join(str(n) for n, count in Counter(all_names).items() if count > 1)}"
+                )
+            for _name in all_names:
+                if isinstance(_name, str) and _name.startswith("_zen_"):
+                    raise ValueError(
+                        f"The field-name specified via `{_name}=<...>` is reserved by hydra-zen."
+                        " You can manually create a dataclass to utilize this name in a structured config."
+                    )
+            del all_names
 
-    if zen_partial is None:
-        # zen_partial is inherited
-        zen_partial = parent_partial
+        if "defaults" in fields_as_kwargs:
+            if hydra_defaults is not None:
+                raise TypeError(
+                    "`defaults` and `hydra_defaults` cannot be specified simultaneously"
+                )
+            _defaults = fields_as_kwargs.pop("defaults")
 
-    del parent_partial
+            if not isinstance(_defaults, ZenField):  # pragma: no branch
+                hydra_defaults = _defaults  # type: ignore
 
-    requires_partial_field = zen_partial is not None
+        # validate hydra-args via `builds`
+        # also check for use of reserved names
+        _tmp: Any = None
 
-    requires_zen_processing: Final[bool] = (
-        bool(zen_meta)
-        or bool(validated_wrappers)
-        or any(uses_zen_processing(b) for b in builds_bases)
-    )
+        cls.__call__(
+            dict,
+            hydra_convert=hydra_convert,
+            hydra_recursive=hydra_recursive,
+            hydra_defaults=hydra_defaults,
+            **{k: _tmp for k in fields_as_kwargs},
+        )
 
-    if base_zen_partial:
-        assert requires_zen_processing
+        normalized_fields: Dict[str, ZenField] = {}
 
-    del base_zen_partial
+        for _field in fields_as_args:
+            if isinstance(_field, str):
+                normalized_fields[_field] = ZenField(
+                    name=_field,
+                    hint=Any,
+                    zen_convert=convert_settings,
+                    _builds_fn=cls,
+                )
+            else:
+                assert isinstance(_field.name, str)
+                normalized_fields[_field.name] = _field
+
+        for name, value in fields_as_kwargs.items():
+            if not isinstance(value, ZenField):
+                normalized_fields[name] = ZenField(
+                    name=name,
+                    default=value,
+                    zen_convert=convert_settings,
+                    _builds_fn=cls,
+                )
+            else:
+                normalized_fields[name] = value
 
-    if not requires_zen_processing and requires_partial_field:
-        target_field = [
-            (
-                TARGET_FIELD_NAME,
-                str,
-                _utils.field(default=target_path, init=False),
-            ),
-            (
-                PARTIAL_FIELD_NAME,
-                bool,
-                _utils.field(default=bool(zen_partial), init=False),
-            ),
-        ]
-    elif requires_zen_processing:
-        # target is `hydra_zen.funcs.zen_processing`
-        target_field = [
-            (
-                TARGET_FIELD_NAME,
-                str,
-                _utils.field(default=ZEN_PROCESSING_LOCATION, init=False),
-            ),
-            (
-                ZEN_TARGET_FIELD_NAME,
-                str,
-                _utils.field(default=target_path, init=False),
-            ),
+        # fields without defaults must come first
+        config_fields: List[Union[Tuple[str, type], Tuple[str, type, Any]]] = [
+            (str(f.name), f.hint)
+            for f in normalized_fields.values()
+            if f.default is NOTHING
         ]
 
-        if requires_partial_field:
-            target_field.append(
+        config_fields.extend(
+            [
                 (
-                    ZEN_PARTIAL_FIELD_NAME,
-                    bool,
-                    _utils.field(default=bool(zen_partial), init=False),
-                ),
-            )
-            if base_hydra_partial:
-                # Must explicitly set _partial_=False to prevent inheritance
-                target_field.append(
+                    str(f.name),
                     (
-                        PARTIAL_FIELD_NAME,
-                        bool,
-                        _utils.field(default=False, init=False),
+                        # f.default: Field
+                        # f.default.default: Any
+                        f.hint
+                        if _retain_type_info(
+                            type_=f.hint,
+                            value=f.default.default,
+                            hydra_recursive=hydra_recursive,
+                        )
+                        else Any
                     ),
+                    f.default,
                 )
+                for f in normalized_fields.values()
+                if f.default is not NOTHING
+            ]
+        )
 
-        if zen_meta:
-            target_field.append(
+        if hydra_recursive is not None:
+            config_fields.append(
                 (
-                    META_FIELD_NAME,
-                    Tuple[str, ...],
-                    _utils.field(default=tuple(zen_meta), init=False),
-                ),
-            )
-
-        if validated_wrappers:
-            if zen_meta:
-                # Check to see
-                tuple(
-                    _utils.check_suspicious_interpolations(
-                        validated_wrappers, zen_meta=zen_meta, target=target
-                    )
-                )
-            if len(validated_wrappers) == 1:
-                # we flatten the config to avoid unnecessary list
-                target_field.append(
-                    (
-                        ZEN_WRAPPERS_FIELD_NAME,
-                        Union[
-                            Union[str, Builds[Any]], Tuple[Union[str, Builds[Any]], ...]
-                        ],
-                        _utils.field(default=validated_wrappers[0], init=False),
-                    ),
-                )
-            else:
-                target_field.append(
-                    (
-                        ZEN_WRAPPERS_FIELD_NAME,
-                        Union[
-                            Union[str, Builds[Any]], Tuple[Union[str, Builds[Any]], ...]
-                        ],
-                        _utils.field(default=validated_wrappers, init=False),
-                    ),
+                    RECURSIVE_FIELD_NAME,
+                    bool,
+                    _utils.field(default=hydra_recursive, init=False),
                 )
-    else:
-        target_field = [
-            (
-                TARGET_FIELD_NAME,
-                str,
-                _utils.field(default=target_path, init=False),
             )
-        ]
-
-    del base_hydra_partial
-    del requires_partial_field
 
-    base_fields = target_field
-
-    if hydra_recursive is not None:
-        base_fields.append(
-            (
-                RECURSIVE_FIELD_NAME,
-                bool,
-                _utils.field(default=hydra_recursive, init=False),
+        if hydra_convert is not None:
+            config_fields.append(
+                (
+                    CONVERT_FIELD_NAME,
+                    str,
+                    _utils.field(default=hydra_convert, init=False),
+                )
             )
-        )
 
-    if hydra_convert is not None:
-        base_fields.append(
-            (CONVERT_FIELD_NAME, str, _utils.field(default=hydra_convert, init=False))
-        )
-
-    if hydra_defaults is not None:
-        if not _utils.valid_defaults_list(hydra_defaults):
-            raise HydraZenValidationError(
-                f"`hydra_defaults` must be type `None | list[str | dict[str, str | list[str] | None ]]`"
-                f", Got: {repr(hydra_defaults)}"
+        if hydra_defaults is not None:
+            hydra_defaults = cls._sanitize_collection(
+                hydra_defaults, convert_dataclass=False
             )
-        hydra_defaults = sanitize_collection(hydra_defaults, convert_dataclass=False)
-        base_fields.append(
-            (
-                DEFAULTS_LIST_FIELD_NAME,
-                List[Any],
-                _utils.field(
-                    default_factory=lambda: list(hydra_defaults),
-                    init=False,
-                ),
-            )
-        )
-
-    if _pos_args:
-        base_fields.append(
-            (
-                POS_ARG_FIELD_NAME,
-                Tuple[Any, ...],
-                _utils.field(
-                    default=tuple(
-                        sanitized_default_value(
-                            x,
-                            error_prefix=BUILDS_ERROR_PREFIX,
-                            convert_dataclass=zen_convert_settings["dataclass"],
-                        )
-                        for x in _pos_args
+            config_fields.append(
+                (
+                    DEFAULTS_LIST_FIELD_NAME,
+                    List[Any],
+                    _utils.field(
+                        default_factory=lambda: list(hydra_defaults), init=False
                     ),
-                    init=False,
-                ),
-            )
-        )
-
-    _sig_target = _get_sig_obj(target)
-
-    try:
-        # We want to rely on `inspect.signature` logic for raising
-        # against an uninspectable sig, before we start inspecting
-        # class-specific attributes below.
-        signature_params = dict(inspect.signature(target).parameters)
-    except ValueError:
-        if populate_full_signature:
-            raise ValueError(
-                BUILDS_ERROR_PREFIX
-                + f"{target} does not have an inspectable signature. "
-                f"`builds({_utils.safe_name(target)}, populate_full_signature=True)` is not supported"
-            )
-        signature_params: Dict[str, inspect.Parameter] = {}
-        # We will turn off signature validation for objects that didn't have
-        # a valid signature. This will enable us to do things like `build(dict, a=1)`
-        target_has_valid_signature: bool = False
-    else:
-        # Dealing with this bug: https://bugs.python.org/issue40897
-        #
-        # In Python < 3.9.1, `inspect.signature will look first to
-        # any implementation __new__, even if it is inherited and if
-        # there is a "fresher" __init__.
-        #
-        # E.g. anything that inherits from `typing.Generic` and
-        # does not implement its own __new__ will have a reported sig
-        # of (*args, **kwargs)
-        #
-        # This looks specifically for the scenario that the target
-        # has inherited from a parent that implements __new__ and
-        # the target implements only __init__.
-
-        if _sig_target is not target:
-            _params = tuple(inspect.signature(_sig_target).parameters.items())
-
-            if (
-                _params and _params[0][1].kind is not _VAR_POSITIONAL
-            ):  # pragma: no cover
-                # Exclude self/cls
-                #
-                # There are weird edge cases
-                # where the first arg is *args, not self.
-                _params = _params[1:]
-            else:  # pragma: no cover
-                pass
-
-            signature_params = {k: v for k, v in _params}
-            del _params
-
-        target_has_valid_signature: bool = True
-
-    if is_dataclass(target):
-        # Update `signature_params` so that any param with `default=<factory>`
-        # has its default replaced with `<factory>()`
-        # If this is a mutable value, `builds` will automatically re-pack
-        # it using a default factory
-        _fields = {f.name: f for f in fields(target)}
-        _update = {}
-        for name, param in signature_params.items():
-            if name not in _fields:
-                # field is InitVar
-                continue
-            f = _fields[name]
-            if f.default_factory is not MISSING:
-                _update[name] = inspect.Parameter(
-                    name,
-                    param.kind,
-                    annotation=param.annotation,
-                    default=f.default_factory(),
-                )
-        signature_params.update(_update)
-        if (
-            zen_convert_settings["flat_target"]
-            and TARGET_FIELD_NAME in signature_params
-        ):
-            signature_params.pop(TARGET_FIELD_NAME)
-        del _update
-        del _fields
-
-    # `get_type_hints` properly resolves forward references, whereas annotations from
-    # `inspect.signature` do not
-    try:
-        type_hints = get_type_hints(_sig_target)
-
-        del _sig_target
-        # We don't need to pop self/class because we only make on-demand
-        # requests from `type_hints`
-
-    except (
-        TypeError,  # ufuncs, which do not have inspectable type hints
-        NameError,  # Unresolvable forward reference
-        AttributeError,  # Class doesn't have "__new__" or "__init__"
-    ):
-        type_hints: Dict[str, Any] = {}
-
-    sig_by_kind: Dict[Any, List[inspect.Parameter]] = {
-        _POSITIONAL_ONLY: [],
-        _POSITIONAL_OR_KEYWORD: [],
-        _VAR_POSITIONAL: [],
-        _KEYWORD_ONLY: [],
-        _VAR_KEYWORD: [],
-    }
-
-    for p in signature_params.values():
-        sig_by_kind[p.kind].append(p)
-
-    # these are the names of the only parameters in the signature of `target` that can
-    # be referenced by name
-    nameable_params_in_sig: Set[str] = {
-        p.name
-        for p in chain(sig_by_kind[_POSITIONAL_OR_KEYWORD], sig_by_kind[_KEYWORD_ONLY])
-    }
-
-    if not _pos_args and builds_bases:
-        # pos_args is potentially inherited
-        for _base in builds_bases:
-            _pos_args = safe_getattr(_base, POS_ARG_FIELD_NAME, ())
-
-            # validates
-            _pos_args = tuple(
-                sanitized_default_value(
-                    x, allow_zen_conversion=False, convert_dataclass=False
                 )
-                for x in _pos_args
             )
-            if _pos_args:
-                break
-
-    fields_set_by_bases: Set[str] = {
-        _field.name
-        for _base in builds_bases
-        for _field in fields(_base)
-        if _field.name not in HYDRA_FIELD_NAMES and not _field.name.startswith("_zen_")
-    }
-
-    # Validate that user-specified arguments satisfy target's signature.
-    # Should catch:
-    #    - bad parameter names
-    #    - too many parameters-by-position
-    #    - multiple values specified for parameter (via positional and by-name)
-    #
-    # We don't raise on an under-specified signature because it is possible that the
-    # resulting dataclass will simply be inherited from and extended.
-    # The issues we catch here cannot be fixed downstream.
-    if target_has_valid_signature:
-        if not sig_by_kind[_VAR_KEYWORD]:
-            # check for unexpected kwargs
-            if not set(kwargs_for_target) <= nameable_params_in_sig:
-                _unexpected = set(kwargs_for_target) - nameable_params_in_sig
-                raise TypeError(
-                    BUILDS_ERROR_PREFIX
-                    + f"The following unexpected keyword argument(s) was specified for {target_path} "
-                    f"via `builds`: {', '.join(_unexpected)}"
-                )
-            if not fields_set_by_bases <= nameable_params_in_sig and not (
-                fields_set_by_bases - nameable_params_in_sig
-            ) <= set(zen_meta):
-                # field inherited by base is not present in sig
-                # AND it is not excluded via `zen_meta`
-                _unexpected = fields_set_by_bases - nameable_params_in_sig
-                raise TypeError(
-                    BUILDS_ERROR_PREFIX
-                    + f"The following unexpected keyword argument(s) for {target_path} "
-                    f"was specified via inheritance from a base class: "
-                    f"{', '.join(_unexpected)}"
-                )
 
-        if _pos_args:
-            named_args = set(kwargs_for_target).union(fields_set_by_bases)
+        dataclass_options["bases"] = bases
+        module = dataclass_options.pop("module", None)
+        assert _utils.parse_strict_dataclass_options(
+            dataclass_options
+        ), dataclass_options
 
-            # indicates that number of parameters that could be specified by name,
-            # but are specified by position
-            _num_nameable_args_by_position = max(
-                0, len(_pos_args) - len(sig_by_kind[_POSITIONAL_ONLY])
-            )
-            if named_args:
-                # check for multiple values for arg, specified both via positional and kwarg
-                # E.g.: def f(x, y): ...
-                # f(1, 2, y=3)  # multiple values for `y`
-                for param in sig_by_kind[_POSITIONAL_OR_KEYWORD][
-                    :_num_nameable_args_by_position
-                ]:
-                    if param.name in named_args:
-                        raise TypeError(
-                            BUILDS_ERROR_PREFIX
-                            + f"Multiple values for argument {param.name} were specified for "
-                            f"{target_path} via `builds`"
-                        )
-            if not sig_by_kind[
-                _VAR_POSITIONAL
-            ] and _num_nameable_args_by_position > len(
-                sig_by_kind[_POSITIONAL_OR_KEYWORD]
-            ):
-                # Too many positional args specified.
-                # E.g.: def f(x, y): ...
-                # f(1, 2, 3)
-                _num_positional = len(sig_by_kind[_POSITIONAL_ONLY]) + len(
-                    sig_by_kind[_POSITIONAL_OR_KEYWORD]
-                )
-                _num_with_default = sum(
-                    p.default is not inspect.Parameter.empty
-                    and p.kind is _POSITIONAL_OR_KEYWORD
-                    for p in signature_params.values()
-                )
-                _permissible = (
-                    f"{_num_positional}"
-                    if not _num_with_default
-                    else f"{_num_positional - _num_with_default} to {_num_positional}"
-                )
-                raise TypeError(
-                    BUILDS_ERROR_PREFIX
-                    + f"{target_path} takes {_permissible} positional args, but "
-                    f"{len(_pos_args)} were specified via `builds`"
-                )
-
-    # Create valid dataclass fields from the user-specified values
-    #
-    # user_specified_params: arg-name -> (arg-name, arg-type, field-w-value)
-    #  - arg-type: taken from the parameter's annotation in the target's signature
-    #    and is resolved to one of the type annotations supported by hydra if possible,
-    #    otherwise, is Any
-    #  - arg-value: mutable values are automatically specified using default-factory
-    user_specified_named_params: Dict[str, Tuple[str, type, Any]] = {
-        name: (name, type_hints.get(name, Any), value)
-        for name, value in kwargs_for_target.items()
-    }
-
-    if populate_full_signature is True:
-        # Populate dataclass fields based on the target's signature.
-        #
-        # A user-specified parameter value (via `kwargs_for_target`) takes precedent over
-        # the default value from the signature
-
-        # Fields with default values must come after those without defaults,
-        # so we will collect these as we loop through the parameters and
-        # add them to the fields at the end.
-        #
-        # Parameter ordering should only differ from the target's signature
-        # if the user specified a value for a parameter that had no default
-        _fields_with_default_values: List[Field_Entry] = []
-
-        # we need to keep track of what user-specified params we have set
-        _seen: Set[str] = set()
-
-        for n, param in enumerate(signature_params.values()):
-            if n + 1 <= len(_pos_args):
-                # Positional parameters are populated from "left to right" in the signature.
-                # We have already done validation, so we know that positional params aren't redundant
-                # with named params (including inherited params).
-                continue
-
-            if param.name not in nameable_params_in_sig:
-                # parameter cannot be specified by name
-                continue
-
-            if param.name in user_specified_named_params:
-                # user-specified parameter is preferred
-                _fields_with_default_values.append(
-                    user_specified_named_params[param.name]
-                )
-                _seen.add(param.name)
-            else:
-                # any parameter whose default value is None is automatically
-                # annotated with `Optional[...]`. This improves flexibility with
-                # Hydra's type-validation
-                param_field = (
-                    param.name,
-                    type_hints.get(param.name, Any),
-                )
-
-                if param.default is inspect.Parameter.empty:
-                    if not zen_partial:
-                        # No default value specified in signature or by the user.
-                        # We don't include these fields if the user specified a partial build
-                        # because we assume that they want to fill these in by using partial
-                        base_fields.append(param_field)
-                else:
-                    param_field += (param.default,)
-                    _fields_with_default_values.append(param_field)
-
-        base_fields.extend(_fields_with_default_values)
-
-        if sig_by_kind[_VAR_KEYWORD]:
-            # if the signature has **kwargs, then we need to add any user-specified
-            # parameters that have not already been added
-            base_fields.extend(
-                entry
-                for name, entry in user_specified_named_params.items()
-                if name not in _seen
-            )
-    else:
-        base_fields.extend(user_specified_named_params.values())
+        out = make_dataclass(fields=config_fields, **dataclass_options)
 
-    if zen_meta:
-        _meta_names = set(zen_meta)
+        if module is not None:
+            out.__module__ = module
 
-        if _meta_names & nameable_params_in_sig:
+        if hasattr(out, ZEN_TARGET_FIELD_NAME) and not uses_zen_processing(out):
             raise ValueError(
-                f"`builds(..., zen_meta=<...>)`: `zen_meta` cannot not specify "
-                f"names that exist in the target's signature: "
-                f"{','.join(_meta_names & nameable_params_in_sig)}"
+                f"{out.__name__} inherits from base classes that overwrite some fields "
+                f"associated with zen-processing features. As a result, this config will "
+                f"not instantiate correctly."
             )
-
-        if _meta_names & set(user_specified_named_params):
+        if safe_getattr(out, PARTIAL_FIELD_NAME, False) and uses_zen_processing(out):
             raise ValueError(
-                f"`builds(..., zen_meta=<...>)`: `zen_meta` cannot not specify "
-                f"names that are common with those specified in **kwargs_for_target: "
-                f"{','.join(_meta_names & set(user_specified_named_params))}"
+                f"{out.__name__} specifies both `{PARTIAL_FIELD_NAME}=True` and `"
+                f"{ZEN_PARTIAL_FIELD_NAME}=True`. This config will not instantiate "
+                f"correctly. This is typically caused by inheriting from multiple, "
+                f"conflicting configs."
             )
 
-        # We don't check for collisions between `zen_meta` names and the
-        # names of inherited fields. Thus `zen_meta` can effectively be used
-        # to "delete" names from a config, via inheritance.
-        base_fields.extend((name, Any, value) for name, value in zen_meta.items())
+        return cast(Type[DataClass], out)
 
-    if dataclass_name is None:
-        if zen_partial is not True:
-            dataclass_name = f"Builds_{_utils.safe_name(target)}"
-        else:
-            dataclass_name = f"PartialBuilds_{_utils.safe_name(target)}"
-
-    # validate that fields set via bases are OK; cannot perform zen-casting
-    # on fields
-    for base in builds_bases:
-        for field_ in fields(base):
-            if field_.default is not MISSING:
-                # performs validation
-                sanitized_default_value(
-                    field_.default,
-                    allow_zen_conversion=False,
-                    error_prefix=BUILDS_ERROR_PREFIX,
-                    field_name=field_.name + " (set via inheritance)",
-                    convert_dataclass=False,
-                )
-            del field_
-
-    # sanitize all types and configured values
-    sanitized_base_fields: List[
-        Union[Tuple[str, Any], Tuple[str, Any, Field[Any]]]
-    ] = []
-
-    for item in base_fields:
-        name = item[0]
-        type_ = item[1]
-        if len(item) == 2:
-            sanitized_base_fields.append((name, _utils.sanitized_type(type_)))
-        else:
-            assert len(item) == 3, item
-            value = item[-1]
-
-            if not isinstance(value, _Field):
-                _field = sanitized_field(
-                    value,
-                    error_prefix=BUILDS_ERROR_PREFIX,
-                    field_name=item[0],
-                    convert_dataclass=zen_convert_settings["dataclass"],
-                )
-            else:
-                _field = value
-
-            # If `.default` is not set, then `value` is a Hydra-supported mutable
-            # value, and thus it is "sanitized"
-            sanitized_value = safe_getattr(_field, "default", value)
-            sanitized_type = (
-                _utils.sanitized_type(type_, wrap_optional=sanitized_value is None)
-                if _retain_type_info(
-                    type_=type_, value=sanitized_value, hydra_recursive=hydra_recursive
-                )
-                else Any
-            )
-            sanitized_base_fields.append((name, sanitized_type, _field))
-            del value
-            del _field
-            del sanitized_value
 
-    dataclass_options["cls_name"] = dataclass_name
-    dataclass_options["bases"] = builds_bases
-    assert _utils.parse_strict_dataclass_options(dataclass_options)
+class DefaultBuilds(BuildsFn[SupportedPrimitive]):
+    pass
 
-    out = make_dataclass(fields=sanitized_base_fields, **dataclass_options)
 
-    if module is not None:
-        out.__module__ = module
+builds: StdBuilds[SupportedPrimitive] = cast(
+    StdBuilds[SupportedPrimitive], DefaultBuilds("builds").builds
+)
 
-    out.__doc__ = (
-        f"A structured config designed to {'partially ' if zen_partial else ''}"
-        f"initialize/call `{target_path}` upon instantiation by hydra."
-    )
-    if hasattr(target, "__doc__"):  # pragma: no branch
-        target_doc = target.__doc__
-        if target_doc:
-            out.__doc__ += (
-                f"\n\nThe docstring for {_utils.safe_name(target)} :\n\n" + target_doc
-            )
 
-    assert requires_zen_processing is uses_zen_processing(out)
+@dataclass(unsafe_hash=True)
+class ConfigComplex:
+    real: Any
+    imag: Any
+    _target_: str = field(default=BuildsFn._get_obj_path(complex), init=False)
 
-    # _partial_=True should never be relied on when zen-processing is being used.
-    assert not (
-        requires_zen_processing and safe_getattr(out, PARTIAL_FIELD_NAME, False)
-    )
 
-    return cast(Union[Type[Builds[Importable]], Type[BuildsWithSig[Type[R], P]]], out)
+@dataclass(unsafe_hash=True)
+class ConfigPath:
+    _args_: Tuple[str]
+    _target_: str = field(default=BuildsFn._get_obj_path(Path), init=False)
 
 
 @overload
@@ -2378,3 +3211,135 @@ def get_target(obj: HasTarget) -> Any:
         pass  # makes sure we cover this branch in tests
 
     return target
+
+
+def mutable_value(
+    x: _T,
+    *,
+    zen_convert: Optional[ZenConvert] = None,
+    BuildsFunction: Type[BuildsFn[Any]] = BuildsFn[Any],
+) -> _T:
+    """Used to set a mutable object as a default value for a field
+    in a dataclass.
+
+    This is an alias for ``field(default_factory=lambda: type(x)(x))``
+
+    Note that ``type(x)(...)`` serves to make a copy
+
+    Examples
+    --------
+    >>> from hydra_zen import mutable_value
+    >>> from dataclasses import dataclass
+
+    See https://docs.python.org/3/library/dataclasses.html#mutable-default-values
+
+    >>> @dataclass  # doctest: +SKIP
+    ... class HasMutableDefault:
+    ...     a_list: list  = [1, 2, 3]  # error: mutable default
+
+    Using `mutable_value` to specify the default list:
+
+    >>> @dataclass
+    ... class HasMutableDefault:
+    ...     a_list: list  = mutable_value([1, 2, 3])  # ok
+
+    >>> x = HasMutableDefault()
+    >>> x.a_list.append(-1)  # does not append to `HasMutableDefault.a_list`
+    >>> x
+    HasMutableDefault(a_list=[1, 2, 3, -1])
+    >>> HasMutableDefault()
+    HasMutableDefault(a_list=[1, 2, 3])"""
+    return BuildsFunction._mutable_value(x, zen_convert=zen_convert)
+
+
+def convert_complex(value: complex) -> Builds[Type[complex]]:
+    return cast(Builds[Type[complex]], ConfigComplex(real=value.real, imag=value.imag))
+
+
+ZEN_VALUE_CONVERSION[complex] = convert_complex
+
+
+if Path in ZEN_SUPPORTED_PRIMITIVES:  # pragma: no cover
+
+    def convert_path(value: Path) -> Builds[Type[Path]]:
+        return cast(Builds[Type[Path]], ConfigPath(_args_=(str(value),)))
+
+    ZEN_VALUE_CONVERSION[Path] = convert_path
+    ZEN_VALUE_CONVERSION[PosixPath] = convert_path
+    ZEN_VALUE_CONVERSION[WindowsPath] = convert_path
+
+
+def _unpack_partial(value: Partial[_T]) -> PartialBuilds[Type[_T]]:
+    target = cast(Type[_T], value.func)
+    return builds(target, *value.args, **value.keywords, zen_partial=True)()
+
+
+@dataclass(unsafe_hash=True)
+class ConfigFromTuple:
+    _args_: Tuple[Any, ...]
+    _target_: str
+
+    def __post_init__(self):
+        self._args_ = (
+            BuildsFn._make_hydra_compatible(
+                tuple(self._args_),
+                convert_dataclass=True,
+                allow_zen_conversion=True,
+                structured_conf_permitted=True,
+            ),
+        )
+
+
+@dataclass(unsafe_hash=True)
+class ConfigFromDict:
+    _args_: Any
+    _target_: str
+
+    def __post_init__(self):
+        self._args_ = (
+            BuildsFn._make_hydra_compatible(
+                dict(self._args_),
+                convert_dataclass=True,
+                allow_zen_conversion=True,
+                structured_conf_permitted=True,
+            ),
+        )
+
+
+@dataclass(unsafe_hash=True)
+class ConfigRange:
+    start: InitVar[int]
+    stop: InitVar[int]
+    step: InitVar[int]
+    _target_: str = field(default=BuildsFn._get_obj_path(range), init=False)
+    _args_: Tuple[int, ...] = field(default=(), init=False, repr=False)
+
+    def __post_init__(self, start, stop, step):
+        self._args_ = (start, stop, step)
+
+
+ZEN_VALUE_CONVERSION[set] = partial(
+    ConfigFromTuple, _target_=BuildsFn._get_obj_path(set)
+)
+ZEN_VALUE_CONVERSION[frozenset] = partial(
+    ConfigFromTuple, _target_=BuildsFn._get_obj_path(frozenset)
+)
+ZEN_VALUE_CONVERSION[deque] = partial(
+    ConfigFromTuple, _target_=BuildsFn._get_obj_path(deque)
+)
+
+if bytes in ZEN_SUPPORTED_PRIMITIVES:  # pragma: no cover
+    ZEN_VALUE_CONVERSION[bytes] = partial(
+        ConfigFromTuple, _target_=BuildsFn._get_obj_path(bytes)
+    )
+
+ZEN_VALUE_CONVERSION[bytearray] = partial(
+    ConfigFromTuple, _target_=BuildsFn._get_obj_path(bytearray)
+)
+ZEN_VALUE_CONVERSION[range] = lambda value: ConfigRange(
+    value.start, value.stop, value.step
+)
+ZEN_VALUE_CONVERSION[Counter] = partial(
+    ConfigFromDict, _target_=BuildsFn._get_obj_path(Counter)
+)
+ZEN_VALUE_CONVERSION[functools.partial] = _unpack_partial
diff --git a/src/hydra_zen/structured_configs/_just.py b/src/hydra_zen/structured_configs/_just.py
index ab89c3ef..16d7aa2d 100644
--- a/src/hydra_zen/structured_configs/_just.py
+++ b/src/hydra_zen/structured_configs/_just.py
@@ -1,18 +1,16 @@
 # Copyright (c) 2023 Massachusetts Institute of Technology
 # SPDX-License-Identifier: MIT
+
 from typing import Any, Callable, FrozenSet, Optional, Type, TypeVar, Union, overload
 
 from typing_extensions import Literal
 
-from hydra_zen.structured_configs import _utils
 from hydra_zen.typing import Builds, DataclassOptions, Just
 from hydra_zen.typing._implementations import _HydraPrimitive  # type: ignore
 from hydra_zen.typing._implementations import _SupportedViaBuilds  # type: ignore
-from hydra_zen.typing._implementations import AllConvert, DataClass_, ZenConvert
+from hydra_zen.typing._implementations import DataClass_, ZenConvert
 
-from ._implementations import sanitized_default_value
-from ._utils import merge_settings
-from ._value_conversion import ConfigComplex
+from ._implementations import ConfigComplex, DefaultBuilds
 
 # pyright: strict
 T = TypeVar("T")
@@ -24,9 +22,6 @@ TB = TypeVar("TB", bound=Union[_SupportedViaBuilds, FrozenSet[Any]])
 __all__ = ["just"]
 
 
-_JUST_CONVERT_SETTINGS = AllConvert(dataclass=True, flat_target=False)
-
-
 @overload
 def just(
     obj: TP,
@@ -303,22 +298,4 @@ def just(
     >>> conf.reduction_fn(conf.data)
     (3+5j)
     """
-    convert_settings = merge_settings(zen_convert, _JUST_CONVERT_SETTINGS)
-    del zen_convert
-    _utils.validate_hydra_options(
-        hydra_recursive=hydra_recursive, hydra_convert=hydra_convert
-    )
-    if zen_dataclass is None:
-        zen_dataclass = {}
-
-    return sanitized_default_value(
-        obj,
-        allow_zen_conversion=True,
-        structured_conf_permitted=True,
-        field_name="",
-        error_prefix="",
-        convert_dataclass=convert_settings["dataclass"],
-        hydra_convert=hydra_convert,
-        hydra_recursive=hydra_recursive,
-        zen_dataclass=_utils.parse_dataclass_options(zen_dataclass),
-    )
+    return DefaultBuilds.just(**locals())
diff --git a/src/hydra_zen/structured_configs/_make_config.py b/src/hydra_zen/structured_configs/_make_config.py
index b3740e3a..d03ab584 100644
--- a/src/hydra_zen/structured_configs/_make_config.py
+++ b/src/hydra_zen/structured_configs/_make_config.py
@@ -1,42 +1,19 @@
 # Copyright (c) 2023 Massachusetts Institute of Technology
 # SPDX-License-Identifier: MIT
-import warnings
-from collections import Counter
-from dataclasses import (  # use this for runtime checks
-    InitVar,
-    dataclass,
-    make_dataclass,
-)
-from typing import Any, Dict, List, Optional, Tuple, Type, Union, cast
+from typing import Optional, Tuple, Type, Union
 
 from typing_extensions import Literal
 
-from hydra_zen.errors import HydraZenDeprecationWarning
-from hydra_zen.structured_configs import _utils
-from hydra_zen.structured_configs._implementations import (
-    _BUILDS_CONVERT_SETTINGS,
-    sanitize_collection,
-)
 from hydra_zen.typing import DataclassOptions, SupportedPrimitive
 from hydra_zen.typing._implementations import (
     AllConvert,
     DataClass,
     DataClass_,
     DefaultsList,
-    Field,
     ZenConvert,
 )
 
-from ._globals import (
-    CONVERT_FIELD_NAME,
-    DEFAULTS_LIST_FIELD_NAME,
-    PARTIAL_FIELD_NAME,
-    RECURSIVE_FIELD_NAME,
-    ZEN_PARTIAL_FIELD_NAME,
-    ZEN_TARGET_FIELD_NAME,
-)
-from ._implementations import _retain_type_info, builds, sanitized_field
-from ._type_guards import safe_getattr, uses_zen_processing
+from ._implementations import DefaultBuilds, ZenField
 
 __all__ = ["ZenField", "make_config"]
 
@@ -46,63 +23,6 @@ class NOTHING:
         raise TypeError("`NOTHING` cannot be instantiated")
 
 
-@dataclass(unsafe_hash=True)
-class ZenField:
-    """
-    ZenField(hint=Any, default=<class 'NOTHING'>, name=<class 'NOTHING'>)
-
-    Specifies a field's name and/or type-annotation and/or default value.
-    Designed to specify fields in `make_config`.
-
-    See the Examples section of the docstring for `make_config` for examples of using
-    `ZenField`.
-
-    Parameters
-    ----------
-    hint : type, optional (default=Any)
-    default : Any, optional
-    name : str, optional
-
-    Notes
-    -----
-    ``default`` will be returned as an instance of :class:`dataclasses.Field`.
-    Mutable values (e.g. lists or dictionaries) passed to ``default`` will automatically
-    be "packaged" in a default-factory function [1]_.
-
-    A type passed to ``hint`` will automatically be "broadened" such that the resulting
-    type is compatible with Hydra's set of supported type annotations [2]_.
-
-    References
-    ----------
-    .. [1] https://docs.python.org/3/library/dataclasses.html#default-factory-functions
-    .. [2] https://hydra.cc/docs/next/tutorials/structured_config/intro/#structured-configs-supports
-
-    See Also
-    --------
-    make_config: create a config with customized field names, default values, and annotations.
-    """
-
-    hint: type = Any
-    default: Union[SupportedPrimitive, Field[Any]] = _utils.field(default=NOTHING)
-    name: Union[str, Type[NOTHING]] = NOTHING
-    zen_convert: InitVar[Optional[ZenConvert]] = None
-
-    def __post_init__(self, zen_convert: Optional[ZenConvert]) -> None:
-        if not isinstance(self.name, str):
-            if self.name is not NOTHING:
-                raise TypeError(f"`ZenField.name` expects a string, got: {self.name}")
-        convert_settings = _utils.merge_settings(zen_convert, _BUILDS_CONVERT_SETTINGS)
-        del zen_convert
-
-        self.hint = _utils.sanitized_type(self.hint)
-
-        if self.default is not NOTHING:
-            self.default = sanitized_field(
-                self.default,
-                convert_dataclass=convert_settings["dataclass"],
-            )
-
-
 _MAKE_CONFIG_SETTINGS = AllConvert(dataclass=False, flat_target=False)
 
 
@@ -352,199 +272,7 @@ def make_config(
 
     See :ref:`data-val` for more general data validation capabilities via hydra-zen.
     """
-    convert_settings = _utils.merge_settings(zen_convert, _MAKE_CONFIG_SETTINGS)
-    convert_settings = cast(ZenConvert, convert_settings)
-    del zen_convert
-
-    if zen_dataclass is None:
-        zen_dataclass = {}
-
-    # initial validation
-    _utils.parse_dataclass_options(zen_dataclass)
-
-    if "frozen" in fields_as_kwargs:
-        warnings.warn(
-            HydraZenDeprecationWarning(
-                "Specifying `builds(frozen=<...>)` is deprecated. Instead, "
-                "specify `builds(zen_dataclass={'frozen': <...>})"
-            ),
-            stacklevel=2,
-        )
-        zen_dataclass["frozen"] = fields_as_kwargs.pop("frozen")  # type: ignore
-
-    if "config_name" in fields_as_kwargs:
-        warnings.warn(
-            HydraZenDeprecationWarning(
-                "Specifying `make_config(config_name=<...>)` is deprecated. "
-                "Instead specify `make_config(zen_dataclass={'cls_name': <...>})"
-            ),
-            stacklevel=2,
-        )
-        zen_dataclass["cls_name"] = fields_as_kwargs.pop("config_name")  # type: ignore
-
-    if not bases:
-        bases = zen_dataclass.get("bases", ())
-
-    zen_dataclass.setdefault("cls_name", "Config")
-    dataclass_options = _utils.parse_dataclass_options(zen_dataclass)
-
-    for _field in fields_as_args:
-        if not isinstance(_field, (str, ZenField)):
-            raise TypeError(
-                f"`fields_as_args` can only consist of field-names (i.e. strings) or "
-                f"`ZenField` instances. Got: "
-                f"{', '.join(str(x) for x in fields_as_args if not isinstance(x, (str, ZenField)))}"
-            )
-        if isinstance(_field, ZenField) and _field.name is NOTHING:
-            raise ValueError(
-                f"All `ZenField` instances specified in `fields_as_args` must have a "
-                f"name associated with it. Got: {_field}"
-            )
-    for name, _field in fields_as_kwargs.items():
-        if isinstance(_field, ZenField):
-            if _field.name is not NOTHING and _field.name != name:
-                raise ValueError(
-                    f"`fields_as_kwargs` specifies conflicting names: the kwarg {name} "
-                    f"is associated with a `ZenField` with name {_field.name}"
-                )
-            else:
-                _field.name = name
-
-    if fields_as_args:
-        all_names = [f.name if isinstance(f, ZenField) else f for f in fields_as_args]
-        all_names.extend(fields_as_kwargs)
-
-        if len(all_names) != len(set(all_names)):
-            raise ValueError(
-                f"`fields_as_args` cannot specify the same field-name multiple times."
-                f" Got multiple entries for:"
-                f" {', '.join(str(n) for n, count in Counter(all_names).items() if count > 1)}"
-            )
-        for _name in all_names:
-            if isinstance(_name, str) and _name.startswith("_zen_"):
-                raise ValueError(
-                    f"The field-name specified via `{_name}=<...>` is reserved by hydra-zen."
-                    " You can manually create a dataclass to utilize this name in a structured config."
-                )
-        del all_names
-
-    if "defaults" in fields_as_kwargs:
-        if hydra_defaults is not None:
-            raise TypeError(
-                "`defaults` and `hydra_defaults` cannot be specified simultaneously"
-            )
-        _defaults = fields_as_kwargs.pop("defaults")
-
-        if not isinstance(_defaults, ZenField):  # pragma: no branch
-            hydra_defaults = _defaults  # type: ignore
-
-    # validate hydra-args via `builds`
-    # also check for use of reserved names
-    _tmp: Any = None
-
-    builds(
-        dict,
-        hydra_convert=hydra_convert,
-        hydra_recursive=hydra_recursive,
-        hydra_defaults=hydra_defaults,
-        **{k: _tmp for k in fields_as_kwargs},
-    )
-
-    normalized_fields: Dict[str, ZenField] = {}
-
-    for _field in fields_as_args:
-        if isinstance(_field, str):
-            normalized_fields[_field] = ZenField(
-                name=_field, hint=Any, zen_convert=convert_settings
-            )
-        else:
-            assert isinstance(_field.name, str)
-            normalized_fields[_field.name] = _field
-
-    for name, value in fields_as_kwargs.items():
-        if not isinstance(value, ZenField):
-            normalized_fields[name] = ZenField(
-                name=name,
-                default=value,
-                zen_convert=convert_settings,
-            )
-        else:
-            normalized_fields[name] = value
-
-    # fields without defaults must come first
-    config_fields: List[Union[Tuple[str, type], Tuple[str, type, Any]]] = [
-        (str(f.name), f.hint)
-        for f in normalized_fields.values()
-        if f.default is NOTHING
-    ]
-
-    config_fields.extend(
-        [
-            (
-                str(f.name),
-                (
-                    # f.default: Field
-                    # f.default.default: Any
-                    f.hint
-                    if _retain_type_info(
-                        type_=f.hint,
-                        value=f.default.default,  # type: ignore
-                        hydra_recursive=hydra_recursive,
-                    )
-                    else Any
-                ),
-                f.default,
-            )
-            for f in normalized_fields.values()
-            if f.default is not NOTHING
-        ]
-    )
-
-    if hydra_recursive is not None:
-        config_fields.append(
-            (
-                RECURSIVE_FIELD_NAME,
-                bool,
-                _utils.field(default=hydra_recursive, init=False),
-            )
-        )
-
-    if hydra_convert is not None:
-        config_fields.append(
-            (CONVERT_FIELD_NAME, str, _utils.field(default=hydra_convert, init=False))
-        )
-
-    if hydra_defaults is not None:
-        hydra_defaults = sanitize_collection(hydra_defaults, convert_dataclass=False)
-        config_fields.append(
-            (
-                DEFAULTS_LIST_FIELD_NAME,
-                List[Any],
-                _utils.field(default_factory=lambda: list(hydra_defaults), init=False),
-            )
-        )
-
-    dataclass_options["bases"] = bases
-    module = dataclass_options.pop("module", None)
-    assert _utils.parse_strict_dataclass_options(dataclass_options), dataclass_options
-
-    out = make_dataclass(fields=config_fields, **dataclass_options)
-
-    if module is not None:
-        out.__module__ = module
-
-    if hasattr(out, ZEN_TARGET_FIELD_NAME) and not uses_zen_processing(out):
-        raise ValueError(
-            f"{out.__name__} inherits from base classes that overwrite some fields "
-            f"associated with zen-processing features. As a result, this config will "
-            f"not instantiate correctly."
-        )
-    if safe_getattr(out, PARTIAL_FIELD_NAME, False) and uses_zen_processing(out):
-        raise ValueError(
-            f"{out.__name__} specifies both `{PARTIAL_FIELD_NAME}=True` and `"
-            f"{ZEN_PARTIAL_FIELD_NAME}=True`. This config will not instantiate "
-            f"correctly. This is typically caused by inheriting from multiple, "
-            f"conflicting configs."
-        )
-
-    return cast(Type[DataClass], out)
+    _locals = locals().copy()
+    fields_as_args = _locals.pop("fields_as_args")
+    fields_as_kwargs = _locals.pop("fields_as_kwargs")
+    return DefaultBuilds.make_config(*fields_as_args, **_locals, **fields_as_kwargs)  # type: ignore
diff --git a/src/hydra_zen/structured_configs/_make_custom_builds.py b/src/hydra_zen/structured_configs/_make_custom_builds.py
index 0a4fcafb..117fcb68 100644
--- a/src/hydra_zen/structured_configs/_make_custom_builds.py
+++ b/src/hydra_zen/structured_configs/_make_custom_builds.py
@@ -11,6 +11,7 @@ from typing import (
     Dict,
     Mapping,
     Optional,
+    TypeVar,
     Union,
     cast,
     overload,
@@ -21,9 +22,9 @@ from typing_extensions import Final, Literal
 from hydra_zen.errors import HydraZenDeprecationWarning
 from hydra_zen.typing import DataclassOptions, ZenWrappers
 from hydra_zen.typing._builds_overloads import FullBuilds, PBuilds, StdBuilds
-from hydra_zen.typing._implementations import ZenConvert
+from hydra_zen.typing._implementations import InstOrType, ZenConvert
 
-from ._implementations import builds
+from ._implementations import BuildsFn, DefaultBuilds, builds
 from ._utils import parse_dataclass_options
 
 __all__ = ["make_custom_builds_fn"]
@@ -40,6 +41,11 @@ __BUILDS_DEFAULTS["frozen"] = False
 __BUILDS_DEFAULTS["dataclass_name"] = None
 del _builds_sig
 
+# TODO: parameterize the return types and attach this
+#       as a classmethod to `BuildsFn`
+
+T = TypeVar("T")
+
 
 # partial=False, pop-sig=True
 @overload
@@ -54,7 +60,8 @@ def make_custom_builds_fn(
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
-) -> FullBuilds:
+    builds_fn: InstOrType[BuildsFn[T]] = DefaultBuilds,
+) -> FullBuilds[T]:
     ...
 
 
@@ -71,7 +78,8 @@ def make_custom_builds_fn(
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
-) -> PBuilds:
+    builds_fn: InstOrType[BuildsFn[T]] = DefaultBuilds,
+) -> PBuilds[T]:
     ...
 
 
@@ -88,7 +96,8 @@ def make_custom_builds_fn(
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
-) -> StdBuilds:
+    builds_fn: InstOrType[BuildsFn[T]] = DefaultBuilds,
+) -> StdBuilds[T]:
     ...
 
 
@@ -105,7 +114,8 @@ def make_custom_builds_fn(
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
-) -> Union[FullBuilds, StdBuilds]:
+    builds_fn: InstOrType[BuildsFn[T]] = DefaultBuilds,
+) -> Union[FullBuilds[T], StdBuilds[T]]:
     ...
 
 
@@ -122,7 +132,8 @@ def make_custom_builds_fn(
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
-) -> Union[PBuilds, StdBuilds]:
+    builds_fn: InstOrType[BuildsFn[T]] = DefaultBuilds,
+) -> Union[PBuilds[T], StdBuilds[T]]:
     ...
 
 
@@ -139,7 +150,8 @@ def make_custom_builds_fn(
     zen_dataclass: Optional[DataclassOptions] = ...,
     frozen: bool = ...,
     zen_convert: Optional[ZenConvert] = ...,
-) -> Union[FullBuilds, PBuilds, StdBuilds]:
+    builds_fn: InstOrType[BuildsFn[T]] = DefaultBuilds,
+) -> Union[FullBuilds[T], PBuilds[T], StdBuilds[T],]:
     ...
 
 
@@ -154,7 +166,8 @@ def make_custom_builds_fn(
     zen_dataclass: Optional[DataclassOptions] = None,
     frozen: bool = False,
     zen_convert: Optional[ZenConvert] = None,
-) -> Union[FullBuilds, PBuilds, StdBuilds]:
+    builds_fn: InstOrType[BuildsFn[T]] = DefaultBuilds,
+) -> Union[FullBuilds[T], PBuilds[T], StdBuilds[T],]:
     """Returns the `builds` function, but with customized default values.
 
     E.g. ``make_custom_builds_fn(hydra_convert='all')`` will return a version
@@ -206,9 +219,12 @@ def make_custom_builds_fn(
 
         Specifies a new the default value for ``builds(..., frozen=<..>)``
 
+    builds_fn: BuildsFn[T]
+        The builds-function whose defaults are modified.
+
     Returns
     -------
-    custom_builds
+    custom_builds[T]
         The function `builds`, but with customized default values.
 
     See Also
@@ -266,8 +282,9 @@ def make_custom_builds_fn(
     <Validation error: "c" is not "a" or "b">
     """
     excluded_fields = frozenset({"dataclass_name", "hydra_defaults", "builds_bases"})
+    fn = builds_fn.builds
+    del builds_fn
     LOCALS = locals()
-
     # Ensures that new defaults added to `builds` must be reflected
     # in the signature of `make_custom_builds_fn`.
     assert (set(__BUILDS_DEFAULTS) - excluded_fields) <= set(LOCALS)
@@ -282,7 +299,7 @@ def make_custom_builds_fn(
     # causing them to resolve the return type of this function as "unknown"
     if not TYPE_CHECKING:  # pragma: no branch
         # let `builds` validate the new defaults!
-        builds(builds, **_new_defaults)
+        fn(fn, **_new_defaults)
 
     _zen_dataclass: Optional[DataclassOptions] = _new_defaults.pop("zen_dataclass")
     if _zen_dataclass is None:
@@ -301,7 +318,7 @@ def make_custom_builds_fn(
 
     _zen_dataclass = parse_dataclass_options(_zen_dataclass)
 
-    @wraps(builds)
+    @wraps(fn)
     def wrapped(*args: Any, **kwargs: Any) -> Any:
         merged_kwargs: Dict[str, Any] = {}
         _dataclass: Optional[DataclassOptions] = kwargs.pop("zen_dataclass", None)
@@ -313,6 +330,13 @@ def make_custom_builds_fn(
 
         merged_kwargs.update(_new_defaults)
         merged_kwargs.update(kwargs)
-        return cast(Any, builds(*args, **merged_kwargs))
-
-    return cast(Union[FullBuilds, PBuilds, StdBuilds], wrapped)
+        return cast(Any, fn(*args, **merged_kwargs))
+
+    return cast(
+        Union[
+            FullBuilds[T],
+            PBuilds[T],
+            StdBuilds[T],
+        ],
+        wrapped,
+    )
diff --git a/src/hydra_zen/structured_configs/_utils.py b/src/hydra_zen/structured_configs/_utils.py
index a35f049c..d6a5bc40 100644
--- a/src/hydra_zen/structured_configs/_utils.py
+++ b/src/hydra_zen/structured_configs/_utils.py
@@ -1,12 +1,9 @@
 # Copyright (c) 2023 Massachusetts Institute of Technology
 # SPDX-License-Identifier: MIT
 import inspect
-import sys
 import warnings
-from dataclasses import MISSING, InitVar, field as _field, is_dataclass
-from enum import Enum
+from dataclasses import MISSING, field as _field, is_dataclass
 from keyword import iskeyword
-from pathlib import Path
 from typing import (
     Any,
     Callable,
@@ -23,29 +20,13 @@ from typing import (
     TypeVar,
     Union,
     cast,
-    get_args,
-    get_origin,
     overload,
 )
 
 from omegaconf import II, DictConfig, ListConfig
-from typing_extensions import (
-    Annotated,
-    Final,
-    Literal,
-    ParamSpecArgs,
-    ParamSpecKwargs,
-    TypeGuard,
-    Unpack,
-    _AnnotatedAlias,
-)
+from typing_extensions import Final, Literal, TypeGuard
 
-from hydra_zen._compatibility import (
-    HYDRA_SUPPORTED_PRIMITIVE_TYPES,
-    HYDRA_SUPPORTS_OBJECT_CONVERT,
-    OMEGACONF_VERSION,
-    Version,
-)
+from hydra_zen._compatibility import HYDRA_SUPPORTS_OBJECT_CONVERT
 from hydra_zen.errors import HydraZenValidationError
 from hydra_zen.typing import DataclassOptions, ZenConvert
 from hydra_zen.typing._implementations import (
@@ -186,235 +167,7 @@ def building_error_prefix(target: Any) -> str:
     return f"Building: {safe_name(target)} ..\n"
 
 
-def get_obj_path(obj: Any) -> str:
-    name = safe_name(obj, repr_allowed=False)
-
-    if name == UNKNOWN_NAME:
-        raise AttributeError(f"{obj} does not have a `__name__` attribute")
-
-    module = getattr(obj, "__module__", None)
-    qualname = getattr(obj, "__qualname__", None)
-
-    if (qualname is not None and "<" in qualname) or module is None:
-        # NumPy's ufuncs do not have an inspectable `__module__` attribute, so we
-        # check to see if the object lives in NumPy's top-level namespace.
-        #
-        # or..
-        #
-        # Qualname produced a name from a local namespace.
-        # E.g. jax.numpy.add.__qualname__ is '_maybe_bool_binop.<locals>.fn'
-        # Thus we defer to the name of the object and look for it in the
-        # top-level namespace of the known suspects
-        #
-        # or...
-        #
-        # module is None, which is apparently a thing..:
-        # __module__ is None for both numpy.random.rand and random.random
-        #
-
-        # don't use qualname for obfuscated paths
-        for new_module in COMMON_MODULES_WITH_OBFUSCATED_IMPORTS:
-            if getattr(sys.modules.get(new_module), name, None) is obj:
-                module = new_module
-                break
-        else:
-            raise ModuleNotFoundError(f"{name} is not importable")
-
-    if not is_classmethod(obj):
-        return f"{module}.{name}"
-    else:
-        # __qualname__ reflects name of class that originally defines classmethod.
-        # Does not point to child in case of inheritance.
-        #
-        # obj.__self__ -> parent object
-        # obj.__name__ -> name of classmethod
-        return f"{get_obj_path(obj.__self__)}.{obj.__name__}"
-
-
 NoneType = type(None)
-_supported_types = HYDRA_SUPPORTED_PRIMITIVE_TYPES | {
-    list,
-    dict,
-    tuple,
-    List,
-    Tuple,
-    Dict,
-}
-
-
-def sanitized_type(
-    type_: Any,
-    *,
-    primitive_only: bool = False,
-    wrap_optional: bool = False,
-    nested: bool = False,
-) -> type:
-    """Returns ``type_`` unchanged if it is supported as an annotation by hydra,
-    otherwise returns ``Any``.
-
-    Examples
-    --------
-    >>> sanitized_type(int)
-    <class 'int'>
-
-    >>> sanitized_type(frozenset)  # not supported by hydra
-    typing.Any
-
-    >>> sanitized_type(int, wrap_optional=True)
-    typing.Union[int, NoneType]
-
-    >>> sanitized_type(List[int])
-    List[int]
-
-    >>> sanitized_type(List[int], primitive_only=True)
-    Any
-
-    >>> sanitized_type(Dict[str, frozenset])
-    Dict[str, Any]
-    """
-    if hasattr(type_, "__supertype__"):
-        # is NewType
-        return sanitized_type(
-            type_.__supertype__,
-            primitive_only=primitive_only,
-            wrap_optional=wrap_optional,
-            nested=nested,
-        )
-
-    if OMEGACONF_VERSION < Version(2, 2, 3):  # pragma: no cover
-        try:
-            type_ = {list: List, tuple: Tuple, dict: Dict}.get(type_, type_)
-        except TypeError:
-            pass
-
-    # Warning: mutating `type_` will mutate the signature being inspected
-    # Even calling deepcopy(`type_`) silently fails to prevent this.
-    origin = get_origin(type_)
-
-    if origin is not None:
-        # Support for Annotated[x, y]
-        # Python 3.9+
-        # # type_: Annotated[x, y]; origin -> Annotated; args -> (x, y)
-        if origin is Annotated:  # pragma: no cover
-            return sanitized_type(
-                get_args(type_)[0],
-                primitive_only=primitive_only,
-                wrap_optional=wrap_optional,
-                nested=nested,
-            )
-
-        # Python 3.7-3.8
-        # type_: Annotated[x, y]; origin -> x
-        if isinstance(type_, _AnnotatedAlias):  # pragma: no cover
-            return sanitized_type(
-                origin,
-                primitive_only=primitive_only,
-                wrap_optional=wrap_optional,
-                nested=nested,
-            )
-
-        if primitive_only:  # pragma: no cover
-            return Any
-
-        args = get_args(type_)
-        if origin is Union:
-            # Hydra only supports Optional[<type>] unions
-            if len(args) != 2 or NoneType not in args:
-                # isn't Optional[<type>]
-                return Any
-
-            args = cast(Tuple[type, type], args)
-
-            optional_type, none_type = args
-            if none_type is not NoneType:
-                optional_type = none_type
-
-            optional_type = sanitized_type(optional_type)
-
-            if optional_type is Any:  # Union[Any, T] is just Any
-                return Any
-
-            return Union[optional_type, NoneType]
-
-        if origin is list or origin is List:
-            if args:
-                return List[sanitized_type(args[0], primitive_only=False, nested=True)]
-            return List
-
-        if origin is dict or origin is Dict:
-            if args:
-                KeyType = sanitized_type(args[0], primitive_only=True, nested=True)
-                ValueType = sanitized_type(args[1], primitive_only=False, nested=True)
-                return Dict[KeyType, ValueType]
-            return Dict
-
-        if (origin is tuple or origin is Tuple) and not nested:
-            # hydra silently supports tuples of homogeneous types
-            # It has some weird behavior. It treats `Tuple[t1, t2, ...]` as `List[t1]`
-            # It isn't clear that we want to perpetrate this on our end..
-            # So we deal with inhomogeneous types as e.g. `Tuple[str, int]` -> `Tuple[Any, Any]`.
-            #
-            # Otherwise we preserve the annotation as accurately as possible
-            if not args:
-                return Any if OMEGACONF_VERSION < (2, 2, 3) else Tuple
-
-            args = cast(Tuple[type, ...], args)
-            unique_args = set(args)
-
-            if any(get_origin(tp) is Unpack for tp in unique_args):
-                # E.g. Tuple[*Ts]
-                return Tuple[Any, ...]
-
-            has_ellipses = Ellipsis in unique_args
-
-            # E.g. Tuple[int, int, int] or Tuple[int, ...]
-            _unique_type = (
-                sanitized_type(args[0], primitive_only=False, nested=True)
-                if len(unique_args) == 1 or (len(unique_args) == 2 and has_ellipses)
-                else Any
-            )
-
-            if has_ellipses:
-                return Tuple[_unique_type, ...]
-            else:
-                return Tuple[(_unique_type,) * len(args)]  # type: ignore
-
-        return Any
-
-    if isinstance(type_, type) and issubclass(type_, Path):
-        type_ = Path
-
-    if isinstance(type_, (ParamSpecArgs, ParamSpecKwargs)):  # pragma: no cover
-        # Python 3.7 - 3.9
-        # these aren't hashable -- can't check for membership in set
-        return Any
-
-    if isinstance(type_, InitVar):
-        return sanitized_type(
-            type_.type,
-            primitive_only=primitive_only,
-            wrap_optional=wrap_optional,
-            nested=nested,
-        )
-    if (
-        type_ is Any
-        or type_ in _supported_types
-        or is_dataclass(type_)
-        or (isinstance(type_, type) and issubclass(type_, Enum))
-    ):
-        if sys.version_info[:2] == (3, 6) and type_ is Dict:  # pragma: no cover
-            type_ = Dict[Any, Any]
-
-        if wrap_optional and type_ is not Any:  # pragma: no cover
-            # normally get_type_hints automatically resolves Optional[...]
-            # when None is set as the default, but this has been flaky
-            # for some pytorch-lightning classes. So we just do it ourselves...
-            # It might be worth removing this later since none of our standard tests
-            # cover it.
-            type_ = Optional[type_]
-        return type_
-
-    return Any
 
 
 def is_interpolated_string(x: Any) -> TypeGuard[InterpStr]:
diff --git a/src/hydra_zen/structured_configs/_value_conversion.py b/src/hydra_zen/structured_configs/_value_conversion.py
deleted file mode 100644
index 9fb4d88e..00000000
--- a/src/hydra_zen/structured_configs/_value_conversion.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright (c) 2023 Massachusetts Institute of Technology
-# SPDX-License-Identifier: MIT
-import functools
-from collections import Counter, deque
-from dataclasses import InitVar, dataclass, field
-from functools import partial
-from pathlib import Path, PosixPath, WindowsPath
-from typing import Any, Tuple, Type, TypeVar, cast
-
-from hydra_zen._compatibility import ZEN_SUPPORTED_PRIMITIVES
-from hydra_zen.typing import Builds, Partial, PartialBuilds
-
-from ._implementations import ZEN_VALUE_CONVERSION, builds, sanitized_default_value
-from ._utils import get_obj_path
-
-_T = TypeVar("_T")
-
-
-@dataclass(unsafe_hash=True)
-class ConfigComplex:
-    real: Any
-    imag: Any
-    _target_: str = field(default=get_obj_path(complex), init=False)
-
-
-def convert_complex(value: complex) -> Builds[Type[complex]]:
-    return cast(Builds[Type[complex]], ConfigComplex(real=value.real, imag=value.imag))
-
-
-ZEN_VALUE_CONVERSION[complex] = convert_complex
-
-
-@dataclass(unsafe_hash=True)
-class ConfigPath:
-    _args_: Tuple[str]
-    _target_: str = field(default=get_obj_path(Path), init=False)
-
-
-if Path in ZEN_SUPPORTED_PRIMITIVES:  # pragma: no cover
-
-    def convert_path(value: Path) -> Builds[Type[Path]]:
-        return cast(Builds[Type[Path]], ConfigPath(_args_=(str(value),)))
-
-    ZEN_VALUE_CONVERSION[Path] = convert_path
-    ZEN_VALUE_CONVERSION[PosixPath] = convert_path
-    ZEN_VALUE_CONVERSION[WindowsPath] = convert_path
-
-
-def _unpack_partial(value: Partial[_T]) -> PartialBuilds[Type[_T]]:
-    target = cast(Type[_T], value.func)
-    return builds(target, *value.args, **value.keywords, zen_partial=True)()
-
-
-@dataclass(unsafe_hash=True)
-class ConfigFromTuple:
-    _args_: Tuple[Any, ...]
-    _target_: str
-
-    def __post_init__(self):
-        self._args_ = (
-            sanitized_default_value(
-                tuple(self._args_),
-                convert_dataclass=True,
-                allow_zen_conversion=True,
-                structured_conf_permitted=True,
-            ),
-        )
-
-
-@dataclass(unsafe_hash=True)
-class ConfigFromDict:
-    _args_: Any
-    _target_: str
-
-    def __post_init__(self):
-        self._args_ = (
-            sanitized_default_value(
-                dict(self._args_),
-                convert_dataclass=True,
-                allow_zen_conversion=True,
-                structured_conf_permitted=True,
-            ),
-        )
-
-
-@dataclass(unsafe_hash=True)
-class ConfigRange:
-    start: InitVar[int]
-    stop: InitVar[int]
-    step: InitVar[int]
-    _target_: str = field(default=get_obj_path(range), init=False)
-    _args_: Tuple[int, ...] = field(default=(), init=False, repr=False)
-
-    def __post_init__(self, start, stop, step):
-        self._args_ = (start, stop, step)
-
-
-ZEN_VALUE_CONVERSION[set] = partial(ConfigFromTuple, _target_=get_obj_path(set))
-ZEN_VALUE_CONVERSION[frozenset] = partial(
-    ConfigFromTuple, _target_=get_obj_path(frozenset)
-)
-ZEN_VALUE_CONVERSION[deque] = partial(ConfigFromTuple, _target_=get_obj_path(deque))
-
-if bytes in ZEN_SUPPORTED_PRIMITIVES:  # pragma: no cover
-    ZEN_VALUE_CONVERSION[bytes] = partial(ConfigFromTuple, _target_=get_obj_path(bytes))
-
-ZEN_VALUE_CONVERSION[bytearray] = partial(
-    ConfigFromTuple, _target_=get_obj_path(bytearray)
-)
-ZEN_VALUE_CONVERSION[range] = lambda value: ConfigRange(
-    value.start, value.stop, value.step
-)
-ZEN_VALUE_CONVERSION[Counter] = partial(ConfigFromDict, _target_=get_obj_path(Counter))
-ZEN_VALUE_CONVERSION[functools.partial] = _unpack_partial
diff --git a/src/hydra_zen/typing/__init__.py b/src/hydra_zen/typing/__init__.py
index eb5a7117..312baab6 100644
--- a/src/hydra_zen/typing/__init__.py
+++ b/src/hydra_zen/typing/__init__.py
@@ -5,6 +5,7 @@ from ._implementations import (
     Builds,
     DataclassOptions,
     HydraPartialBuilds,
+    HydraSupportedType,
     Just,
     Partial,
     PartialBuilds,
@@ -22,6 +23,7 @@ __all__ = [
     "Partial",
     "PartialBuilds",
     "SupportedPrimitive",
+    "HydraSupportedType",
     "ZenWrappers",
     "ZenPartialBuilds",
     "HydraPartialBuilds",
diff --git a/src/hydra_zen/typing/_builds_overloads.py b/src/hydra_zen/typing/_builds_overloads.py
index 1a9610be..8eafe36c 100644
--- a/src/hydra_zen/typing/_builds_overloads.py
+++ b/src/hydra_zen/typing/_builds_overloads.py
@@ -3,10 +3,11 @@
 
 # Stores overloads for `builds` with different default-values for signature
 # pyright: strict
-
+# pragma: no cover
 from typing import (
     Any,
     Callable,
+    Generic,
     Mapping,
     Optional,
     Tuple,
@@ -16,7 +17,7 @@ from typing import (
     overload,
 )
 
-from typing_extensions import Literal, ParamSpec, Protocol
+from typing_extensions import Literal, ParamSpec
 
 from ._implementations import (
     AnyBuilds,
@@ -32,13 +33,14 @@ from ._implementations import (
 )
 
 Importable = TypeVar("Importable", bound=Callable[..., Any])
+T = TypeVar("T")
 R = TypeVar("R")
 P = ParamSpec("P")
 
 __all__ = ["FullBuilds", "PBuilds", "StdBuilds"]
 
 
-class StdBuilds(Protocol):
+class StdBuilds(Generic[T]):
     # partial=False, pop-sig=True; no *args, **kwargs, nor builds_bases
     @overload
     def __call__(
@@ -86,7 +88,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[AnyBuilds[Importable]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[False, None] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -99,7 +101,7 @@ class StdBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[Builds[Importable]]:
         ...
 
@@ -107,7 +109,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[False, None] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -120,7 +122,7 @@ class StdBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[Builds[Importable]]:
         ...
 
@@ -129,7 +131,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[AnyBuilds[Importable]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[True] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -142,7 +144,7 @@ class StdBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[PartialBuilds[Importable]]:
         ...
 
@@ -150,7 +152,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[True] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -163,7 +165,7 @@ class StdBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[PartialBuilds[Importable]]:
         ...
 
@@ -172,7 +174,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[AnyBuilds[Importable]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = ...,
         populate_full_signature: Literal[False] = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -185,7 +187,7 @@ class StdBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]],]:
         ...
 
@@ -193,7 +195,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = ...,
         populate_full_signature: Literal[False] = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -206,7 +208,7 @@ class StdBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]],]:
         ...
 
@@ -215,7 +217,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Union[Callable[P, R], Type[AnyBuilds[Importable]], Importable],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool],
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -228,7 +230,7 @@ class StdBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[
         Type[Builds[Importable]],
         Type[PartialBuilds[Importable]],
@@ -239,7 +241,7 @@ class StdBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Union[Callable[P, R], Type[Builds[Importable]], Importable],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = None,
         populate_full_signature: bool = False,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = tuple(),
@@ -252,16 +254,16 @@ class StdBuilds(Protocol):
         dataclass_name: Optional[str] = None,
         zen_dataclass: Optional[DataclassOptions] = None,
         zen_convert: Optional[ZenConvert] = None,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[
         Type[Builds[Importable]],
         Type[PartialBuilds[Importable]],
         Type[BuildsWithSig[Type[R], P]],
-    ]:
+    ]:  # pragma: no cover
         ...
 
 
-class FullBuilds(Protocol):
+class FullBuilds(Generic[T]):
     # full_builds -> populate_full_signature=True  (new default value)
 
     # partial=False, pop_sig=True; no *args, **kwargs, nor builds_bases`
@@ -330,7 +332,7 @@ class FullBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[Union[AnyBuilds[Importable], PartialBuilds[Importable]]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[False, None] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -343,7 +345,7 @@ class FullBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[Builds[Importable]]:
         ...
 
@@ -351,7 +353,7 @@ class FullBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[False, None] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -364,7 +366,7 @@ class FullBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[Builds[Importable]]:
         ...
 
@@ -373,7 +375,7 @@ class FullBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[AnyBuilds[Importable]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[True] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -386,7 +388,7 @@ class FullBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[PartialBuilds[Importable]]:
         ...
 
@@ -394,7 +396,7 @@ class FullBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[True] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -407,7 +409,7 @@ class FullBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[PartialBuilds[Importable]]:
         ...
 
@@ -416,7 +418,7 @@ class FullBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[AnyBuilds[Importable]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = ...,
         populate_full_signature: Literal[False],
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -429,7 +431,7 @@ class FullBuilds(Protocol):
         dataclass_name: Optional[str] = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]]]:
         ...
 
@@ -437,7 +439,7 @@ class FullBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = ...,
         populate_full_signature: Literal[False],
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -450,7 +452,7 @@ class FullBuilds(Protocol):
         dataclass_name: Optional[str] = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]]]:
         ...
 
@@ -459,7 +461,7 @@ class FullBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Union[Callable[P, R], Type[AnyBuilds[Importable]], Importable],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool],
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -472,7 +474,7 @@ class FullBuilds(Protocol):
         dataclass_name: Optional[str] = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[
         Type[Builds[Importable]],
         Type[PartialBuilds[Importable]],
@@ -488,7 +490,7 @@ class FullBuilds(Protocol):
             Type[Builds[Importable]],
             Type[PartialBuilds[Importable]],
         ],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = None,
         populate_full_signature: bool = True,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = tuple(),
@@ -501,16 +503,16 @@ class FullBuilds(Protocol):
         dataclass_name: Optional[str] = None,
         zen_dataclass: Optional[DataclassOptions] = None,
         zen_convert: Optional[ZenConvert] = None,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[
         Type[Builds[Importable]],
         Type[PartialBuilds[Importable]],
         Type[BuildsWithSig[Type[R], P]],
-    ]:
+    ]:  # pragma: no cover
         ...
 
 
-class PBuilds(Protocol):
+class PBuilds(Generic[T]):
     # partial_builds -> zen_partial=True (new default value)
 
     # partial=True, pop-sig=bool
@@ -518,7 +520,7 @@ class PBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[AnyBuilds[Importable]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[True] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -531,7 +533,7 @@ class PBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[PartialBuilds[Importable]]:
         ...
 
@@ -539,7 +541,7 @@ class PBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Literal[True] = ...,
         populate_full_signature: bool = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -552,7 +554,7 @@ class PBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Type[PartialBuilds[Importable]]:
         ...
 
@@ -602,7 +604,7 @@ class PBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Type[AnyBuilds[Importable]],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = ...,
         populate_full_signature: Literal[False] = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -615,7 +617,7 @@ class PBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]],]:
         ...
 
@@ -623,7 +625,7 @@ class PBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Importable,
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = ...,
         populate_full_signature: Literal[False] = ...,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -636,7 +638,7 @@ class PBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[Type[Builds[Importable]], Type[PartialBuilds[Importable]],]:
         ...
 
@@ -645,7 +647,7 @@ class PBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Union[Callable[P, R], Importable],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = ...,
         populate_full_signature: bool,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = ...,
@@ -658,7 +660,7 @@ class PBuilds(Protocol):
         frozen: bool = ...,
         zen_dataclass: Optional[DataclassOptions] = ...,
         zen_convert: Optional[ZenConvert] = ...,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[
         Type[Builds[Importable]],
         Type[PartialBuilds[Importable]],
@@ -669,7 +671,7 @@ class PBuilds(Protocol):
     def __call__(
         self,
         __hydra_target: Union[Callable[P, R], Type[AnyBuilds[Importable]], Importable],
-        *pos_args: SupportedPrimitive,
+        *pos_args: T,
         zen_partial: Optional[bool] = True,
         populate_full_signature: bool = False,
         zen_wrappers: ZenWrappers[Callable[..., Any]] = tuple(),
@@ -682,10 +684,10 @@ class PBuilds(Protocol):
         dataclass_name: Optional[str] = None,
         zen_dataclass: Optional[DataclassOptions] = None,
         zen_convert: Optional[ZenConvert] = None,
-        **kwargs_for_target: SupportedPrimitive,
+        **kwargs_for_target: T,
     ) -> Union[
         Type[Builds[Importable]],
         Type[PartialBuilds[Importable]],
         Type[BuildsWithSig[Type[R], P]],
-    ]:
+    ]:  # pragma: no cover
         ...
diff --git a/src/hydra_zen/typing/_implementations.py b/src/hydra_zen/typing/_implementations.py
index 4f4a9d25..08fb4c14 100644
--- a/src/hydra_zen/typing/_implementations.py
+++ b/src/hydra_zen/typing/_implementations.py
@@ -5,6 +5,7 @@
 
 import sys
 import types
+from dataclasses import MISSING
 from enum import Enum
 from pathlib import Path, PosixPath, WindowsPath
 from typing import (
@@ -15,7 +16,6 @@ from typing import (
     ClassVar,
     Dict,
     FrozenSet,
-    Generic,
     List,
     Mapping,
     NewType,
@@ -90,6 +90,8 @@ else:
 
 @runtime_checkable
 class Partial(Protocol[T2]):
+    """A protocol that matches against `functools.partial`"""
+
     __call__: Callable[..., T2]
 
     @property
@@ -188,6 +190,23 @@ _HydraPrimitive: TypeAlias = Union[
     bool, None, int, float, str, ByteString, Path, WindowsPath, PosixPath
 ]
 
+HydraSupportedType = Union[
+    _HydraPrimitive,
+    DataClass_,
+    Type[DataClass_],
+    ListConfig,
+    DictConfig,
+    Enum,
+    Literal[MISSING],
+    # Even thought this is redundant with Sequence, it seems to
+    # be needed for pyright to do proper checking of tuple contents
+    Tuple["HydraSupportedType", ...],
+    Sequence["HydraSupportedType"],
+    Mapping[Any, "HydraSupportedType"],
+]
+"""Describes types that are compatible with Hydra -- they can be used in
+configs provided to Hydra."""
+
 _SupportedViaBuilds = Union[
     Partial[Any],
     range,
@@ -206,25 +225,23 @@ _SupportedPrimitive: TypeAlias = Union[
     EmptyDict,  # not covered by Mapping[..., ...]]
 ]
 
-if TYPE_CHECKING:
-    SupportedPrimitive: TypeAlias = Union[
-        _SupportedPrimitive,
-        FrozenSet["SupportedPrimitive"],
-        # Even thought this is redundant with Sequence, it seems to
-        # be needed for pyright to do proper checking of tuple contents
-        Tuple["SupportedPrimitive", ...],
-        # Mutable generic containers need to be invariant, so
-        # we have to settle for Sequence/Mapping. While this
-        # is overly permissive in terms of sequence-type, it
-        # at least affords quality checking of sequence content
-        Sequence["SupportedPrimitive"],
-        # Mapping is covariant only in value
-        Mapping[Any, "SupportedPrimitive"],
-    ]
-else:
-    # cleans up annotations for REPLs
-    SupportedPrimitive = TypeVar("SupportedPrimitive")
 
+SupportedPrimitive: TypeAlias = Union[
+    _SupportedPrimitive,
+    FrozenSet["SupportedPrimitive"],
+    # Even thought this is redundant with Sequence, it seems to
+    # be needed for pyright to do proper checking of tuple contents
+    Tuple["SupportedPrimitive", ...],
+    # Mutable generic containers need to be invariant, so
+    # we have to settle for Sequence/Mapping. While this
+    # is overly permissive in terms of sequence-type, it
+    # at least affords quality checking of sequence content
+    Sequence["SupportedPrimitive"],
+    # Mapping is covariant only in value
+    Mapping[Any, "SupportedPrimitive"],
+]
+"""Describes types that are natively supported by hydra-zen's config-creation
+functions."""
 
 ZenWrapper: TypeAlias = Union[
     None,
@@ -237,12 +254,9 @@ ZenWrapper: TypeAlias = Union[
     Callable[[T4], T4],
     str,
 ]
-if TYPE_CHECKING:
-    ZenWrappers: TypeAlias = Union[ZenWrapper[T4], Sequence[ZenWrapper[T4]]]
-else:
-    # cleans up annotations for REPLs
-    class ZenWrappers(Generic[T2]):  # pragma: no cover
-        pass
+
+
+ZenWrappers: TypeAlias = Union[ZenWrapper[T4], Sequence[ZenWrapper[T4]]]
 
 
 DefaultsList = List[
diff --git a/src/hydra_zen/wrapper/_implementations.py b/src/hydra_zen/wrapper/_implementations.py
index 73d31a49..92cec62d 100644
--- a/src/hydra_zen/wrapper/_implementations.py
+++ b/src/hydra_zen/wrapper/_implementations.py
@@ -32,7 +32,6 @@ from typing import (
 import hydra
 from hydra.conf import HydraConf
 from hydra.core.config_store import ConfigStore
-from hydra.utils import instantiate
 from omegaconf import DictConfig, ListConfig, OmegaConf
 from typing_extensions import (
     Final,
@@ -48,8 +47,8 @@ from typing_extensions import (
 from hydra_zen import instantiate, just, make_custom_builds_fn
 from hydra_zen._compatibility import HYDRA_VERSION, Version
 from hydra_zen.errors import HydraZenValidationError
+from hydra_zen.structured_configs._implementations import BuildsFn
 from hydra_zen.structured_configs._type_guards import safe_getattr
-from hydra_zen.structured_configs._utils import get_obj_path
 from hydra_zen.typing._implementations import (
     DataClass_,
     GroupName,
@@ -63,6 +62,7 @@ from ..structured_configs._utils import safe_name
 
 __all__ = ["zen", "store", "Zen"]
 
+get_obj_path = BuildsFn._get_obj_path  # type: ignore
 
 R = TypeVar("R")
 P = ParamSpec("P")


Test patch:
diff --git a/tests/annotations/declarations.py b/tests/annotations/declarations.py
index 542e6fb6..ce25e11d 100644
--- a/tests/annotations/declarations.py
+++ b/tests/annotations/declarations.py
@@ -47,7 +47,11 @@ from hydra_zen import (
     store,
     zen,
 )
-from hydra_zen.structured_configs._value_conversion import ConfigComplex, ConfigPath
+from hydra_zen.structured_configs._implementations import (
+    BuildsFn,
+    ConfigComplex,
+    ConfigPath,
+)
 from hydra_zen.typing import (
     Builds,
     HydraPartialBuilds,
@@ -940,55 +944,66 @@ def check_partial_narrowing_full(
 
 def check_make_custom_builds_overloads(boolean: bool, optional_boolean: Optional[bool]):
     # partial = False, pop-sig = False
-    reveal_type(make_custom_builds_fn(zen_partial=False), expected_text="StdBuilds")
+    assert_type(
+        make_custom_builds_fn(zen_partial=False),
+        StdBuilds[SupportedPrimitive],
+    )
 
-    reveal_type(
+    assert_type(
         make_custom_builds_fn(zen_partial=False, populate_full_signature=False),
-        expected_text="StdBuilds",
+        StdBuilds[SupportedPrimitive],
     )
 
     # Returns `PBuilds`
-    reveal_type(
+    assert_type(
         make_custom_builds_fn(zen_partial=True, populate_full_signature=boolean),
-        expected_text="PBuilds",
+        PBuilds[SupportedPrimitive],
     )
-    reveal_type(make_custom_builds_fn(zen_partial=True), expected_text="PBuilds")
-    reveal_type(
+    assert_type(make_custom_builds_fn(zen_partial=True), PBuilds[SupportedPrimitive])
+    assert_type(
         make_custom_builds_fn(zen_partial=True, populate_full_signature=False),
-        expected_text="PBuilds",
+        PBuilds[SupportedPrimitive],
     )
 
     # Returns `PBuilds | StdBuilds``
-    reveal_type(
+    assert_type(
         make_custom_builds_fn(zen_partial=False, populate_full_signature=boolean),
-        expected_text="FullBuilds | StdBuilds",
+        Union[FullBuilds[SupportedPrimitive], StdBuilds[SupportedPrimitive]],
     )
 
-    reveal_type(
+    assert_type(
         make_custom_builds_fn(zen_partial=optional_boolean),
-        expected_text="PBuilds | StdBuilds",
+        Union[PBuilds[SupportedPrimitive], StdBuilds[SupportedPrimitive]],
     )
 
-    reveal_type(
+    assert_type(
         make_custom_builds_fn(
             populate_full_signature=False, zen_partial=optional_boolean
         ),
-        expected_text="PBuilds | StdBuilds",
+        Union[PBuilds[SupportedPrimitive], StdBuilds[SupportedPrimitive]],
     )
 
     # Returns `FullBuilds | PBuilds | StdBuilds`
-    reveal_type(
+    assert_type(
         make_custom_builds_fn(
             populate_full_signature=True, zen_partial=optional_boolean
         ),
-        expected_text="FullBuilds | PBuilds | StdBuilds",
+        Union[
+            FullBuilds[SupportedPrimitive],
+            PBuilds[SupportedPrimitive],
+            StdBuilds[SupportedPrimitive],
+        ],
     )
 
-    reveal_type(
+    assert_type(
         make_custom_builds_fn(
             populate_full_signature=boolean, zen_partial=optional_boolean
         ),
-        expected_text="FullBuilds | PBuilds | StdBuilds",
+        Union[
+            FullBuilds[SupportedPrimitive],
+            PBuilds[SupportedPrimitive],
+            StdBuilds[SupportedPrimitive],
+        ],
     )
 
 
@@ -1278,7 +1293,8 @@ def builds_target_pass_through():
     def foo(x: int) -> str:
         ...
 
-    c1 = builds(builds(foo, x=1), x=2)
+    _c1 = builds(foo, x=1)
+    c1 = builds(_c1, x=2)
     reveal_type(instantiate(c1), expected_text="str")
 
     _c2 = builds(foo, populate_full_signature=True)
@@ -1286,17 +1302,20 @@ def builds_target_pass_through():
     reveal_type(instantiate(c2), expected_text="str")
     reveal_type(c2, expected_text="type[Builds[type[str]]]")
 
-    c3 = builds(builds(foo, zen_partial=True))
+    _c3 = builds(foo, zen_partial=True)
+    c3 = builds(_c3)
     reveal_type(instantiate(c3), expected_text="str")
 
-    pc1 = builds(builds(foo, x=1), x=2, zen_partial=True)
+    _pc1 = builds(foo, x=1)
+    pc1 = builds(_pc1, x=2, zen_partial=True)
     reveal_type(instantiate(pc1), expected_text="Partial[str]")
 
     _pc2 = builds(foo, populate_full_signature=True)
     pc2 = builds(_pc2, zen_partial=True)
     reveal_type(instantiate(pc2), expected_text="Partial[str]")
 
-    pc3 = builds(builds(foo, zen_partial=True), zen_partial=True)
+    _pc3 = builds(foo, zen_partial=True)
+    pc3 = builds(_pc3, zen_partial=True)
     reveal_type(instantiate(pc3), expected_text="Partial[str]")
 
     tmp = builds(foo, populate_full_signature=True)
@@ -1410,3 +1429,51 @@ def pbuilds_target_pass_through():
     tmp6 = pbuilds(foo, zen_partial=True)
     pc4 = pbuilds(tmp6, zen_partial=True)
     reveal_type(instantiate(pc4), expected_text="Partial[str]")
+
+
+def check_BuildsFn():
+    my_builds = BuildsFn[int]("my_builds")
+    my_builds(int, 1)
+    my_builds(int, "a")  # type: ignore
+
+
+def check_make_custom_reflection():
+    def foo(x: int):
+        ...
+
+    bb = BuildsFn[int]("a")
+
+    pb = make_custom_builds_fn(zen_partial=True, builds_fn=bb)
+    assert_type(pb, PBuilds[int])
+
+    _ = pb(foo)
+    _ = pb(foo, x=1)
+    _ = pb(foo, x="a")  # type: ignore
+
+    fb = make_custom_builds_fn(populate_full_signature=True, builds_fn=bb)
+    assert_type(fb, FullBuilds[int])
+
+    reveal_type(fb(foo), expected_text="type[BuildsWithSig[type[None], (x: int)]]")
+    _ = fb(foo)(x=1)
+    _ = fb(foo)(x="a")  # type: ignore
+
+
+def check_parameterized_BuildsFn():
+    class A:
+        ...
+
+    class B(A):
+        ...
+
+    class C:
+        ...
+
+    def foo(x: A):
+        ...
+
+    bg = BuildsFn[Union[SupportedPrimitive, A]]("a")
+
+    assert_type(bg(A, A()), Type[Builds[Type[A]]])
+    assert_type(bg(A, B()), Type[Builds[Type[A]]])
+    assert_type(bg(A, B(), zen_partial=True), Type[PartialBuilds[Type[A]]])
+    bg(A, C())  # type: ignore
diff --git a/tests/annotations/mypy_checks.py b/tests/annotations/mypy_checks.py
index 65b347a6..34fb97fc 100644
--- a/tests/annotations/mypy_checks.py
+++ b/tests/annotations/mypy_checks.py
@@ -5,6 +5,8 @@
 from typing_extensions import assert_type
 
 from hydra_zen import builds, instantiate, just, make_custom_builds_fn, store
+from hydra_zen.typing import SupportedPrimitive
+from hydra_zen.typing._builds_overloads import FullBuilds, PBuilds, StdBuilds
 from hydra_zen.wrapper import ZenStore
 
 
@@ -33,9 +35,13 @@ def check_make_custom_builds() -> None:
     def f(x: int) -> str:
         ...
 
-    builds_ = make_custom_builds_fn()
-    partial_builds = make_custom_builds_fn(zen_partial=True)
-    full_builds = make_custom_builds_fn(populate_full_signature=True)
+    builds_: StdBuilds[SupportedPrimitive] = make_custom_builds_fn()
+    partial_builds: PBuilds[SupportedPrimitive] = make_custom_builds_fn(
+        zen_partial=True
+    )
+    full_builds: FullBuilds[SupportedPrimitive] = make_custom_builds_fn(
+        populate_full_signature=True
+    )
 
     assert_type(instantiate(builds_(A)), A)
     assert_type(instantiate(full_builds(A)), A)
diff --git a/tests/custom_strategies.py b/tests/custom_strategies.py
index fd40618f..61e9d743 100644
--- a/tests/custom_strategies.py
+++ b/tests/custom_strategies.py
@@ -16,9 +16,8 @@ from typing import (
 
 import hypothesis.strategies as st
 
-from hydra_zen import ZenStore, builds
+from hydra_zen import BuildsFn, ZenStore
 from hydra_zen._compatibility import HYDRA_SUPPORTS_OBJECT_CONVERT
-from hydra_zen.structured_configs._utils import get_obj_path
 from hydra_zen.typing import DataclassOptions
 from hydra_zen.typing._implementations import ZenConvert
 
@@ -35,8 +34,8 @@ def _wrapper(obj):
 # strategies for drawing valid inputs to `zen_wrappers`
 single_wrapper_strat = (
     st.just(_wrapper)
-    | st.just(get_obj_path(_wrapper))
-    | st.just(_wrapper).map(lambda x: builds(x, zen_partial=True))
+    | st.just(BuildsFn._get_obj_path(_wrapper))
+    | st.just(_wrapper).map(lambda x: BuildsFn.builds(x, zen_partial=True))
 )
 wrapper_strat = single_wrapper_strat | st.lists(single_wrapper_strat)
 
@@ -168,7 +167,7 @@ def f():
     pass
 
 
-f_Build = builds(f, zen_dataclass={"cls_name": "f_Build"})
+f_Build = BuildsFn.builds(f, zen_dataclass={"cls_name": "f_Build"})
 
 
 @st.composite
diff --git a/tests/test_BuildsFn.py b/tests/test_BuildsFn.py
new file mode 100644
index 00000000..d58c5bdb
--- /dev/null
+++ b/tests/test_BuildsFn.py
@@ -0,0 +1,167 @@
+# Copyright (c) 2023 Massachusetts Institute of Technology
+# SPDX-License-Identifier: MIT
+
+from inspect import signature
+from typing import Any, List, Union
+
+import pytest
+from typing_extensions import Literal
+
+from hydra_zen import (
+    BuildsFn,
+    ZenField,
+    builds,
+    instantiate,
+    just,
+    make_config,
+    make_custom_builds_fn,
+)
+from hydra_zen.errors import HydraZenUnsupportedPrimitiveError
+from hydra_zen.typing import DataclassOptions, SupportedPrimitive
+from hydra_zen.typing._implementations import DataclassOptions
+
+
+class A:
+    def __init__(self, x: int) -> None:
+        self.x = x
+
+    def __eq__(self, __value: object) -> bool:
+        return isinstance(__value, type(self)) and __value.x == self.x
+
+    @staticmethod
+    def static():
+        return 11
+
+
+class B:
+    ...
+
+
+class MyBuildsFn(
+    BuildsFn[Union[SupportedPrimitive, A, List[Union[SupportedPrimitive, A]]]]
+):
+    @classmethod
+    def _make_hydra_compatible(
+        cls,
+        value: Any,
+        allow_zen_conversion: bool = True,
+        *,
+        error_prefix: str = "",
+        field_name: str = "",
+        structured_conf_permitted: bool = True,
+        convert_dataclass: bool,
+        hydra_recursive: Union[bool, None] = None,
+        hydra_convert: Union[Literal["none", "partial", "all", "object"], None] = None,
+        zen_dataclass: Union[DataclassOptions, None] = None,
+    ) -> Any:
+        if isinstance(value, A):
+            return cls.builds(A, value.x)
+
+        return super()._make_hydra_compatible(
+            value,
+            allow_zen_conversion=allow_zen_conversion,
+            error_prefix=error_prefix,
+            field_name=field_name,
+            structured_conf_permitted=structured_conf_permitted,
+            convert_dataclass=convert_dataclass,
+            hydra_recursive=hydra_recursive,
+            hydra_convert=hydra_convert,
+            zen_dataclass=zen_dataclass,
+        )
+
+    @classmethod
+    def _sanitized_type(
+        cls,
+        type_: Any,
+        *,
+        primitive_only: bool = False,
+        wrap_optional: bool = False,
+        nested: bool = False,
+    ) -> type:
+        if type_ is B:
+            return A
+
+        return super()._sanitized_type(
+            type_,
+            primitive_only=primitive_only,
+            wrap_optional=wrap_optional,
+            nested=nested,
+        )
+
+    @classmethod
+    def _get_obj_path(cls, target: Any) -> str:
+        if target is A.static:
+            return cls._get_obj_path(A) + ".static"
+        return super()._get_obj_path(target)
+
+
+my_builds = MyBuildsFn("my_builds")
+
+
+def f(x):
+    return x
+
+
+def test_call():
+    with pytest.raises(HydraZenUnsupportedPrimitiveError):
+        builds(dict, x=A(22))  # pyright: ignore
+
+    assert instantiate(my_builds(dict, x=A(22))) == {"x": A(22)}
+    assert instantiate(my_builds(dict, x=A(22), zen_partial=True))() == {"x": A(22)}
+    assert instantiate(my_builds(dict, x=[A(22), A(33)], zen_partial=True))() == {
+        "x": [A(22), A(33)]
+    }
+
+
+def test_just():
+    with pytest.raises(HydraZenUnsupportedPrimitiveError):
+        just(A(22))
+
+    assert instantiate(my_builds.just(A(22))) == A(22)
+    assert instantiate(my_builds.just(dict(x=A(22)))) == {"x": A(22)}
+
+
+def foo(x: A = A(5)):
+    return x
+
+
+def test_make_custom_builds():
+    new_builds = make_custom_builds_fn(builds_fn=my_builds)
+    assert instantiate(new_builds(dict, x=A(22))) == {"x": A(22)}
+
+    new_fbuilds = make_custom_builds_fn(
+        builds_fn=my_builds, populate_full_signature=True
+    )
+    assert instantiate(new_fbuilds(foo)().x) == A(5)
+
+    new_pbuilds = make_custom_builds_fn(builds_fn=my_builds, zen_partial=True)
+    assert instantiate(new_pbuilds(foo))() == A(5)
+
+
+def bar(x: B):
+    ...
+
+
+def test_sanitized_type_override():
+    # should swap B -> A in annotation
+    out = signature(my_builds(bar, populate_full_signature=True)).parameters["x"]
+    assert out.annotation is A
+
+
+def test_get_obj_path_override():
+    with pytest.raises(Exception, match="Error locating target"):
+        assert instantiate(builds(A.static)) == 11
+    assert instantiate(my_builds(A.static)) == 11
+
+
+def test_make_config():
+    with pytest.raises(HydraZenUnsupportedPrimitiveError):
+        make_config(x=A(1))  # type: ignore
+
+    assert instantiate(my_builds.make_config(x=A(1))().x) == A(1)
+
+
+def test_zen_field():
+    with pytest.raises(HydraZenUnsupportedPrimitiveError):
+        ZenField(default=A(1))
+    ZenField(default=A(1), _builds_fn=my_builds)
diff --git a/tests/test_compatibility/test_hydra_supports_partial.py b/tests/test_compatibility/test_hydra_supports_partial.py
index 0b0fa20f..19ee3ec6 100644
--- a/tests/test_compatibility/test_hydra_supports_partial.py
+++ b/tests/test_compatibility/test_hydra_supports_partial.py
@@ -5,11 +5,18 @@ from functools import partial
 
 import pytest
 
-from hydra_zen import builds, get_target, instantiate, make_custom_builds_fn
+from hydra_zen import (
+    DefaultBuilds,
+    builds,
+    get_target,
+    instantiate,
+    make_custom_builds_fn,
+)
 from hydra_zen.funcs import zen_processing
-from hydra_zen.structured_configs._utils import get_obj_path
 from hydra_zen.typing import HydraPartialBuilds, ZenPartialBuilds
 
+get_obj_path = DefaultBuilds._get_obj_path
+
 
 @dataclass
 class HydraPartialConf:
diff --git a/tests/test_docs_typecheck.py b/tests/test_docs_typecheck.py
index 470553f8..475c697c 100644
--- a/tests/test_docs_typecheck.py
+++ b/tests/test_docs_typecheck.py
@@ -60,7 +60,7 @@ PYRIGHT_SCAN_RESULTS: Dict[Any, PyrightOutput] = {}
 FUNCS_TO_SCAN = [
     ZenField,
     ZenStore,
-    builds,
+    builds.__call__,
     get_target,
     hydrated_dataclass,
     instantiate,
@@ -92,29 +92,7 @@ if PYRIGHT_PATH is not None:
 
 
 @pytest.mark.skipif(PYRIGHT_PATH is None, reason="pyright is not installed")
-@pytest.mark.parametrize(
-    "func",
-    [
-        ZenField,
-        ZenStore,
-        builds,
-        get_target,
-        hydrated_dataclass,
-        instantiate,
-        is_partial_builds,
-        just,
-        # launch,  # TODO: add after https://github.com/mit-ll-responsible-ai/hydra-zen/pull/313 is merged
-        load_from_yaml,
-        make_config,
-        make_custom_builds_fn,
-        save_as_yaml,
-        to_yaml,
-        uses_zen_processing,
-        zen,
-        ZenConvert,
-        DataclassOptions,
-    ],
-)
+@pytest.mark.parametrize("func", FUNCS_TO_SCAN)
 def test_docstrings_scan_clean_via_pyright(func):
     results = PYRIGHT_SCAN_RESULTS[func]
     assert results["summary"]["errorCount"] == 0, list_error_messages(results)
diff --git a/tests/test_flat_target.py b/tests/test_flat_target.py
index 93c91280..9531ca60 100644
--- a/tests/test_flat_target.py
+++ b/tests/test_flat_target.py
@@ -6,11 +6,11 @@ from dataclasses import dataclass
 
 import pytest
 
-from hydra_zen import builds, instantiate, make_custom_builds_fn
-from hydra_zen.structured_configs._utils import get_obj_path
+from hydra_zen import DefaultBuilds, builds, instantiate, make_custom_builds_fn
 from hydra_zen.typing import ZenConvert
 
 fbuilds = make_custom_builds_fn(populate_full_signature=True)
+get_obj_path = DefaultBuilds._get_obj_path
 
 
 def test_no_flat_target():
diff --git a/tests/test_hydra_behaviors.py b/tests/test_hydra_behaviors.py
index cedcd271..b85db5bf 100644
--- a/tests/test_hydra_behaviors.py
+++ b/tests/test_hydra_behaviors.py
@@ -10,6 +10,7 @@ from omegaconf import DictConfig, ListConfig
 from omegaconf.errors import ValidationError
 
 from hydra_zen import (
+    DefaultBuilds,
     builds,
     hydrated_dataclass,
     instantiate,
@@ -17,7 +18,8 @@ from hydra_zen import (
     mutable_value,
 )
 from hydra_zen._compatibility import HYDRA_SUPPORTS_OBJECT_CONVERT
-from hydra_zen.structured_configs._utils import get_obj_path
+
+get_obj_path = DefaultBuilds._get_obj_path
 
 
 def f_three_vars(x, y, z):
diff --git a/tests/test_just.py b/tests/test_just.py
index 2570c1ea..94850612 100644
--- a/tests/test_just.py
+++ b/tests/test_just.py
@@ -39,6 +39,7 @@ list_of_objects = [
     functools.partial(f, x=1),
     ADataclass,
     ADataclass(x=2),
+    {1, 2, 3},
 ]
 
 
diff --git a/tests/test_py39.py b/tests/test_py39.py
index afcdac96..79b2ad34 100644
--- a/tests/test_py39.py
+++ b/tests/test_py39.py
@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Tuple
 import pytest
 from omegaconf import OmegaConf
 
-from hydra_zen.structured_configs._utils import sanitized_type
+from hydra_zen import DefaultBuilds
 
 
 @pytest.mark.parametrize(
@@ -20,7 +20,7 @@ from hydra_zen.structured_configs._utils import sanitized_type
 )
 def test_sanitized_type_expected_behavior(in_type, expected_type):
     # tests collections-as-generics introduced in py39
-    actual = sanitized_type(in_type)
+    actual = DefaultBuilds._sanitized_type(in_type)
     assert actual is expected_type or actual == expected_type
 
     @dataclass
diff --git a/tests/test_utils.py b/tests/test_utils.py
index d00f26ab..1d8136e8 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -44,7 +44,7 @@ from typing_extensions import (
     Unpack,
 )
 
-from hydra_zen import builds, instantiate, mutable_value
+from hydra_zen import DefaultBuilds, builds, instantiate, mutable_value
 from hydra_zen._compatibility import (
     HYDRA_VERSION,
     OMEGACONF_VERSION,
@@ -57,7 +57,6 @@ from hydra_zen.structured_configs._utils import (
     is_interpolated_string,
     merge_settings,
     safe_name,
-    sanitized_type,
 )
 from hydra_zen.typing import Builds
 from hydra_zen.typing._implementations import AllConvert, ZenConvert
@@ -261,7 +260,7 @@ NoneType: TypeAlias = None
     ],
 )
 def test_sanitized_type_expected_behavior(in_type, expected_type):
-    assert sanitized_type(in_type) == expected_type, in_type
+    assert DefaultBuilds._sanitized_type(in_type) == expected_type, in_type
 
     if in_type != expected_type:
         # In cases where we change the type, it should be because omegaconf
@@ -295,7 +294,7 @@ def test_sanitized_type_expected_behavior(in_type, expected_type):
 
 
 def test_tuple_annotation_normalization():
-    assert sanitized_type(Tuple[int, str, int]) is Tuple[Any, Any, Any]
+    assert DefaultBuilds._sanitized_type(Tuple[int, str, int]) is Tuple[Any, Any, Any]
 
 
 def f_list(x: List):
diff --git a/tests/test_validation.py b/tests/test_validation.py
index fbd6364f..781a6096 100644
--- a/tests/test_validation.py
+++ b/tests/test_validation.py
@@ -14,6 +14,7 @@ from hypothesis import assume, given, settings
 from omegaconf import OmegaConf
 
 from hydra_zen import (
+    DefaultBuilds,
     builds,
     get_target,
     hydrated_dataclass,
@@ -28,9 +29,10 @@ from hydra_zen.structured_configs._globals import (
     HYDRA_FIELD_NAMES,
     ZEN_TARGET_FIELD_NAME,
 )
-from hydra_zen.structured_configs._utils import get_obj_path
 from tests import everything_except
 
+get_obj_path = DefaultBuilds._get_obj_path
+
 
 def test_builds_no_args_raises():
     with pytest.raises(TypeError):
diff --git a/tests/test_value_conversion.py b/tests/test_value_conversion.py
index c984ab44..72a7305a 100644
--- a/tests/test_value_conversion.py
+++ b/tests/test_value_conversion.py
@@ -25,7 +25,7 @@ from hydra_zen import (
     to_yaml,
 )
 from hydra_zen._compatibility import ZEN_SUPPORTED_PRIMITIVES
-from hydra_zen.structured_configs._value_conversion import ZEN_VALUE_CONVERSION
+from hydra_zen.structured_configs._implementations import ZEN_VALUE_CONVERSION
 from hydra_zen.typing import Partial
 from tests import is_same