Matthew Rahtz <matthew.ra...@gmail.com> added the comment:
[Guido] > 1. Some edge case seems to be that if *tuple[...] is involved on either side > we will never simplify. Alright, let me think this through with some examples to get my head round it. It would prohibit the following difficult case: class C(Generic[*Ts]): ... Alias = C[T, *Ts] Alias[*tuple[int, ...]] # Does not simplify; stays C[T, *Ts][*tuple[int, ...]] That seems pretty reasonable. It would also prohibit these other relatively simple cases, but I guess that's fine: Alias = C[*Ts] Alias[*tuple[int, ...]] # Does not simplify; stays C[*Ts][*tuple[int, ...]] Alias = C[T, *tuple[int, ...]] Alias[str] # Does not simplify; stays C[T, *tuple[int, ...]][str] > Or perhaps a better rule is that *tuple[...] is never simplified away (but > fixed items before and after it may be). Is this to say that we effectively prohibit binding *tuple[...] to anything? If we can simplify without binding *tuple[...] to anything, then we do simplify, but otherwise, we don't simplify? So under this rule, the following WOULD work? Alias = C[T, *tuple[int, ...]] Alias[str] # Simplifies to C[str, *tuple[int, ...]], because we didn't have to bind *tuple[int, ...] to do it > 2. Another edge case is that if neither side has any starred items we will > always simplify (since this is the existing behavior in 3.10). This may raise > an error if the number of subscripts on the right does not match the number > of parameters on the left. Alright, so this is business as usual. > 3. If there's a single *Ts on the left but not on the right, we should be > able to simplify, which again may raise an error if there are not enough > values on the right, but if there are more than enough, the excess will be > consumed by *Ts (in fact that's the only way *Ts is fed). So then: class C(Generic[*Ts]): ... Alias = C[T, *Ts] Alias[()] # Raises error Alias[int] # Simplifies to C[int, *Ts] Alias[int, str] # Simplifies to C[int, str] Alias[int, str, bool] # Simplifies to C[int, str, bool] Yup, seems straightforward. > 4. If there's a *Ts on the right but not on the left, we should _not_ > simplify, since whatever we have on the left serves as a constraint for *Ts. Ok, so this is about the following situations: class C(Generic[*Ts]): ... Alias = C[T1, T2] Alias[*Ts] # Does not simplify; stays C[T1, T2][*Ts] Yikes - in fact, this is actually super hairy; I hadn't thought about this edge case at all in the PEP. Agreed that it seems reasonable not to simplify here. > E.g. tuple[int, int][*Ts] constrains *Ts to being (int, int). Was that a typo? Surely tuple[int, int][*Ts] isn't valid - since tuple[int, int] doesn't have any free parameters? > 5. If there's exactly one *Ts on the left and one on the right, we _might__ > be able to simplify if the prefix and suffix of the __parameters__ match the > prefix and suffix of the subscript on the right. E.g. C[int, T, *Ts, > float][str, *Ts] can be simplified to C[int, str, *Ts, float]. OTOH C[int, T, > *Ts, float][*Ts] cannot be simplified -- but we cannot flag it as an error > either. Note that __parameters__ in this example is (T, Ts); we have to > assume that typevartuples in __parameters__ are always used as *Ts (since the > PEP recognizes no valid unstarred uses of Ts). Ok, this also makes sense. --- Still, though, doesn't the point that Serhiy brought up about __origin__, __parameters__ and __args__ still apply? In cases where we *don't* simplify, there'd still be the issue of what we'd set these things to be. This evening I'll also revisit the PRs adding tests for substitution to try and make them a comprehensive reference as to what's currently possible. ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue47006> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com