# Buggy code
def from_params(
    cls: Type[T],
    params: Params,
    constructor_to_call: Callable[..., T] = None,
    constructor_to_inspect: Callable[..., T] = None,
    **extras,
) -> T:
    """
    This is the automatic implementation of `from_params`. Any class that subclasses
    `FromParams` (or `Registrable`, which itself subclasses `FromParams`) gets this
    implementation for free.  If you want your class to be instantiated from params in the
    "obvious" way -- pop off parameters and hand them to your constructor with the same names --
    this provides that functionality.

    If you need more complex logic in your from `from_params` method, you'll have to implement
    your own method that overrides this one.

    The `constructor_to_call` and `constructor_to_inspect` arguments deal with a bit of
    redirection that we do.  We allow you to register particular `@classmethods` on a class as
    the constructor to use for a registered name.  This lets you, e.g., have a single
    `Vocabulary` class that can be constructed in two different ways, with different names
    registered to each constructor.  In order to handle this, we need to know not just the class
    we're trying to construct (`cls`), but also what method we should inspect to find its
    arguments (`constructor_to_inspect`), and what method to call when we're done constructing
    arguments (`constructor_to_call`).  These two methods are the same when you've used a
    `@classmethod` as your constructor, but they are `different` when you use the default
    constructor (because you inspect `__init__`, but call `cls()`).
    """

    from allennlp.common.registrable import (
        Registrable,
    )  # import here to avoid circular imports

    logger.debug(
        f"instantiating class {cls} from params {getattr(params, 'params', params)} "
        f"and extras {set(extras.keys())}"
    )

    if params is None:
        return None

    if isinstance(params, str):
        params = Params({"type": params})

    if not isinstance(params, Params):
        raise ConfigurationError(
            "from_params was passed a `params` object that was not a `Params`. This probably "
            "indicates malformed parameters in a configuration file, where something that "
            "should have been a dictionary was actually a list, or something else. "
            f"This happened when constructing an object of type {cls}."
        )

    registered_subclasses = Registrable._registry.get(cls)

    if is_base_registrable(cls) and registered_subclasses is None:
        # NOTE(mattg): There are some potential corner cases in this logic if you have nested
        # Registrable types.  We don't currently have any of those, but if we ever get them,
        # adding some logic to check `constructor_to_call` should solve the issue.  Not
        # bothering to add that unnecessary complexity for now.
        raise ConfigurationError(
            "Tried to construct an abstract Registrable base class that has no registered "
            "concrete types. This might mean that you need to use --include-package to get "
            "your concrete classes actually registered."
        )

    if registered_subclasses is not None and not constructor_to_call:
        # We know `cls` inherits from Registrable, so we'll use a cast to make mypy happy.

        as_registrable = cast(Type[Registrable], cls)
        default_to_first_choice = as_registrable.default_implementation is not None
        choice = params.pop_choice(
            "type",
            choices=as_registrable.list_available(),
            default_to_first_choice=default_to_first_choice,
        )
        subclass, constructor_name = as_registrable.resolve_class_name(choice)
        # See the docstring for an explanation of what's going on here.
        if not constructor_name:
            constructor_to_inspect = subclass.__init__
            constructor_to_call = subclass  # type: ignore
        else:
            constructor_to_inspect = getattr(subclass, constructor_name)
            constructor_to_call = constructor_to_inspect

        if hasattr(subclass, "from_params"):
            # We want to call subclass.from_params.
            extras = create_extras(subclass, extras)
            # mypy can't follow the typing redirection that we do, so we explicitly cast here.
            retyped_subclass = cast(Type[T], subclass)
            return retyped_subclass.from_params(
                params=params,
                constructor_to_call=constructor_to_call,
                constructor_to_inspect=constructor_to_inspect,
                **extras,
            )
        else:
            # In some rare cases, we get a registered subclass that does _not_ have a
            # from_params method (this happens with Activations, for instance, where we
            # register pytorch modules directly).  This is a bit of a hack to make those work,
            # instead of adding a `from_params` method for them somehow.  We just trust that
            # you've done the right thing in passing your parameters, and nothing else needs to
            # be recursively constructed.
            extras = create_extras(subclass, extras)
            constructor_args = {**params, **extras}
            return subclass(**constructor_args)  # type: ignore
    else:
        # This is not a base class, so convert our params and extras into a dict of kwargs.

        # See the docstring for an explanation of what's going on here.
        if not constructor_to_inspect:
            constructor_to_inspect = cls.__init__
        if not constructor_to_call:
            constructor_to_call = cls

        if constructor_to_inspect == object.__init__:
            # This class does not have an explicit constructor, so don't give it any kwargs.
            # Without this logic, create_kwargs will look at object.__init__ and see that
            # it takes *args and **kwargs and look for those.
            kwargs: Dict[str, Any] = {}
            params.assert_empty(cls.__name__)
        else:
            # This class has a constructor, so create kwargs for it.
            kwargs = create_kwargs(constructor_to_inspect, cls, params, **extras)

        return constructor_to_call(**kwargs)  # type: ignore


# Traceback (RuntimeError)
Traceback (most recent call last):
File "tmp.py", line 10, in <module>
Foo.from_params(Params({"a": 2, "b": "hi"}))
File "/Users/evanw/AllenAI/allennlp/allennlp/common/from_params.py", line 610, in from_params
kwargs = create_kwargs(constructor_to_inspect, cls, params, **extras)
File "/Users/evanw/AllenAI/allennlp/allennlp/common/from_params.py", line 163, in create_kwargs
parameters = infer_params(cls, constructor)
File "/Users/evanw/AllenAI/allennlp/allennlp/common/from_params.py", line 140, in infer_params
super_parameters = infer_params(super_class)
File "/Users/evanw/AllenAI/allennlp/allennlp/common/from_params.py", line 139, in infer_params
raise RuntimeError("found a kwargs parameter with no inspectable super class")
RuntimeError: found a kwargs parameter with no inspectable super class

# Fixed code
def from_params(
    cls: Type[T],
    params: Params,
    constructor_to_call: Callable[..., T] = None,
    constructor_to_inspect: Callable[..., T] = None,
    **extras,
) -> T:
    """
    This is the automatic implementation of `from_params`. Any class that subclasses
    `FromParams` (or `Registrable`, which itself subclasses `FromParams`) gets this
    implementation for free.  If you want your class to be instantiated from params in the
    "obvious" way -- pop off parameters and hand them to your constructor with the same names --
    this provides that functionality.

    If you need more complex logic in your from `from_params` method, you'll have to implement
    your own method that overrides this one.

    The `constructor_to_call` and `constructor_to_inspect` arguments deal with a bit of
    redirection that we do.  We allow you to register particular `@classmethods` on a class as
    the constructor to use for a registered name.  This lets you, e.g., have a single
    `Vocabulary` class that can be constructed in two different ways, with different names
    registered to each constructor.  In order to handle this, we need to know not just the class
    we're trying to construct (`cls`), but also what method we should inspect to find its
    arguments (`constructor_to_inspect`), and what method to call when we're done constructing
    arguments (`constructor_to_call`).  These two methods are the same when you've used a
    `@classmethod` as your constructor, but they are `different` when you use the default
    constructor (because you inspect `__init__`, but call `cls()`).
    """

    from allennlp.common.registrable import (
        Registrable,
    )  # import here to avoid circular imports

    logger.debug(
        f"instantiating class {cls} from params {getattr(params, 'params', params)} "
        f"and extras {set(extras.keys())}"
    )

    if params is None:
        return None

    if isinstance(params, str):
        params = Params({"type": params})

    if not isinstance(params, Params):
        raise ConfigurationError(
            "from_params was passed a `params` object that was not a `Params`. This probably "
            "indicates malformed parameters in a configuration file, where something that "
            "should have been a dictionary was actually a list, or something else. "
            f"This happened when constructing an object of type {cls}."
        )

    registered_subclasses = Registrable._registry.get(cls)

    if is_base_registrable(cls) and registered_subclasses is None:
        # NOTE(mattg): There are some potential corner cases in this logic if you have nested
        # Registrable types.  We don't currently have any of those, but if we ever get them,
        # adding some logic to check `constructor_to_call` should solve the issue.  Not
        # bothering to add that unnecessary complexity for now.
        raise ConfigurationError(
            "Tried to construct an abstract Registrable base class that has no registered "
            "concrete types. This might mean that you need to use --include-package to get "
            "your concrete classes actually registered."
        )

    if registered_subclasses is not None and not constructor_to_call:
        # We know `cls` inherits from Registrable, so we'll use a cast to make mypy happy.

        as_registrable = cast(Type[Registrable], cls)
        default_to_first_choice = as_registrable.default_implementation is not None
        choice = params.pop_choice(
            "type",
            choices=as_registrable.list_available(),
            default_to_first_choice=default_to_first_choice,
        )
        subclass, constructor_name = as_registrable.resolve_class_name(choice)
        # See the docstring for an explanation of what's going on here.
        if not constructor_name:
            constructor_to_inspect = subclass.__init__
            constructor_to_call = subclass  # type: ignore
        else:
            constructor_to_inspect = getattr(subclass, constructor_name)
            constructor_to_call = constructor_to_inspect

        if hasattr(subclass, "from_params"):
            # We want to call subclass.from_params.
            extras = create_extras(subclass, extras)
            # mypy can't follow the typing redirection that we do, so we explicitly cast here.
            retyped_subclass = cast(Type[T], subclass)
            return retyped_subclass.from_params(
                params=params,
                constructor_to_call=constructor_to_call,
                constructor_to_inspect=constructor_to_inspect,
                **extras,
            )
        else:
            # In some rare cases, we get a registered subclass that does _not_ have a
            # from_params method (this happens with Activations, for instance, where we
            # register pytorch modules directly).  This is a bit of a hack to make those work,
            # instead of adding a `from_params` method for them somehow.  We just trust that
            # you've done the right thing in passing your parameters, and nothing else needs to
            # be recursively constructed.
            return subclass(**params)  # type: ignore
    else:
        # This is not a base class, so convert our params and extras into a dict of kwargs.

        # See the docstring for an explanation of what's going on here.
        if not constructor_to_inspect:
            constructor_to_inspect = cls.__init__
        if not constructor_to_call:
            constructor_to_call = cls

        if constructor_to_inspect == object.__init__:
            # This class does not have an explicit constructor, so don't give it any kwargs.
            # Without this logic, create_kwargs will look at object.__init__ and see that
            # it takes *args and **kwargs and look for those.
            kwargs: Dict[str, Any] = {}
            params.assert_empty(cls.__name__)
        else:
            # This class has a constructor, so create kwargs for it.
            kwargs = create_kwargs(constructor_to_inspect, cls, params, **extras)

        return constructor_to_call(**kwargs)  # type: ignore