-
Notifications
You must be signed in to change notification settings - Fork 125
Description
The CharmType type variable used in the _CharmSpec generic is invariant (the default). The variable is defined here. It's probably intended to be covariant, at least as far as _CharmSpec is concerned. That is, anywhere a _CharmSpec[ops.CharmBase] is required, the more specific _CharmSpec[MyCharmBaseSubClass] should be fine.
Invariance is problematic in cases like this one in #2230, which looks like this:
def f(c: _CharmSpec[ops.CharmBase]):
...
charm_spec = _CharmSpec(MyCharmClass, ...) # typed as _CharmSpec[MyCharmClass]
f(charm_spec) # error because f needs exactly a _CharmSpec[ops.CharmBase]It seems pretty clear that _CharmSpec[Specific] should be fine where _CharmSpec[Base] is declared since _CharmSpec is essentially an immutable container here (it's a frozen dataclass). I believe that moving from invariant to covariant here would be backwards compatible. However, we need to check all the uses of the existing TypeVar, or make a new one for this, in case there are any uses that should be invariant (or contravariant).