From 1e0ffeef0a88350cd7b66142f160f6407076cee8 Mon Sep 17 00:00:00 2001 From: Ilia Gradina Date: Tue, 13 Oct 2026 15:02:07 +0300 Subject: [PATCH 1/3] typ: define stub type aliases after the classes they reference The input type aliases in the stubs (iarb, iacb, ifmpz, ...) were assigned above the class they name, e.g. `iarb = ... | arb` above `class arb`. ty resolves a forward reference in the value of a plain assignment to Unknown, even in a stub, so every parameter annotated with one of these aliases was Unknown under ty: `arb(2) * acb(1)` was inferred as `arb` and `iarb` accepted an `acb`. Defining each alias after the class it references fixes this. mypy and pyright output is unchanged. --- src/flint/types/acb.pyi | 4 +++- src/flint/types/acb_poly.pyi | 4 +++- src/flint/types/acb_series.pyi | 4 +++- src/flint/types/arb.pyi | 4 +++- src/flint/types/arb_poly.pyi | 4 +++- src/flint/types/arb_series.pyi | 4 +++- src/flint/types/arf.pyi | 6 ++++-- src/flint/types/fmpq.pyi | 4 +++- src/flint/types/fmpq_poly.pyi | 6 +++--- src/flint/types/fmpq_series.pyi | 6 +++--- src/flint/types/fmpz.pyi | 3 ++- src/flint/types/fmpz_mod.pyi | 4 +++- src/flint/types/fmpz_mod_poly.pyi | 4 ++-- src/flint/types/fmpz_poly.pyi | 4 ++-- src/flint/types/fmpz_series.pyi | 6 +++--- src/flint/types/fq_default.pyi | 3 ++- src/flint/types/fq_default_poly.pyi | 3 ++- src/flint/types/nmod.pyi | 3 ++- src/flint/types/nmod_poly.pyi | 4 ++-- 19 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/flint/types/acb.pyi b/src/flint/types/acb.pyi index fd68bcc3..775e4f87 100644 --- a/src/flint/types/acb.pyi +++ b/src/flint/types/acb.pyi @@ -13,7 +13,6 @@ ifmpz = int | fmpz_t ifmpq = int | fmpz_t | fmpq_t iarf = int | float | fmpz_t | fmpq_t | arf iarb = int | float | fmpz_t | fmpq_t | arf | arb -iacb = int | float | complex | fmpz_t | fmpq_t | arf | arb | acb class _MpcLike(Protocol): @@ -289,3 +288,6 @@ class acb(flint_scalar): def coulomb(self, l: iacb, eta: iacb) -> tuple[acb, acb, acb, acb]: ... def coulomb_f(self, l: iacb, eta: iacb) -> acb: ... def coulomb_g(self, l: iacb, eta: iacb) -> acb: ... + + +iacb = int | float | complex | fmpz_t | fmpq_t | arf | arb | acb diff --git a/src/flint/types/acb_poly.pyi b/src/flint/types/acb_poly.pyi index ff558897..34ca2c8f 100644 --- a/src/flint/types/acb_poly.pyi +++ b/src/flint/types/acb_poly.pyi @@ -17,7 +17,6 @@ ifmpz = int | fmpz ifmpq = int | fmpz | fmpq iarf = int | float | fmpz | fmpq | arb iacb = int | float | complex | str | fmpz | fmpq | arb | acb -iacb_poly = acb_poly | iacb | fmpz_poly | fmpq_poly | arb_poly class acb_poly(flint_poly[acb]): @@ -80,3 +79,6 @@ class acb_poly(flint_poly[acb]): def roots(self, tol: iarf | None = None, maxprec: int | None = None) -> list[acb]: ... # type: ignore[override] def complex_roots(self, tol: iarf | None = None, maxprec: int | None = None) -> list[acb]: ... def root_bound(self) -> arb: ... + + +iacb_poly = acb_poly | iacb | fmpz_poly | fmpq_poly | arb_poly diff --git a/src/flint/types/acb_series.pyi b/src/flint/types/acb_series.pyi index 44ee7f3e..116361eb 100644 --- a/src/flint/types/acb_series.pyi +++ b/src/flint/types/acb_series.pyi @@ -20,7 +20,6 @@ ifmpz = int | fmpz ifmpq = int | fmpz | fmpq iarf = int | float | fmpz | fmpq | arb iacb = int | float | complex | str | fmpz | fmpq | arb | acb -iacb_series = acb_series | iacb | fmpz_poly | fmpq_poly | fmpz_series | fmpq_series | arb_poly | arb_series | acb_poly class acb_series(flint_series[acb]): @@ -121,3 +120,6 @@ class acb_series(flint_series[acb]): def li(self, offset: bool = ...) -> acb_series: ... def lambertw(self, branch: int = ...) -> acb_series: ... + + +iacb_series = acb_series | iacb | fmpz_poly | fmpq_poly | fmpz_series | fmpq_series | arb_poly | arb_series | acb_poly diff --git a/src/flint/types/arb.pyi b/src/flint/types/arb.pyi index 6f477e4c..6645883d 100644 --- a/src/flint/types/arb.pyi +++ b/src/flint/types/arb.pyi @@ -10,7 +10,6 @@ _str = str ifmpz = int | fmpz_t ifmpq = int | fmpz_t | fmpq_t iarf = int | float | fmpz_t | fmpq_t | arf -iarb = int | float | fmpz_t | fmpq_t | arf | arb class _MpfLike(Protocol): @@ -279,3 +278,6 @@ class arb(flint_scalar): def coulomb(self, l: iarb, eta: iarb) -> tuple[arb, arb]: ... def coulomb_f(self, l: iarb, eta: iarb) -> arb: ... def coulomb_g(self, l: iarb, eta: iarb) -> arb: ... + + +iarb = int | float | fmpz_t | fmpq_t | arf | arb diff --git a/src/flint/types/arb_poly.pyi b/src/flint/types/arb_poly.pyi index 97459b22..256ebf95 100644 --- a/src/flint/types/arb_poly.pyi +++ b/src/flint/types/arb_poly.pyi @@ -16,7 +16,6 @@ from .fmpz_poly import fmpz_poly ifmpz = int | fmpz ifmpq = int | fmpz | fmpq iarf = int | float | fmpz | fmpq | arb -iarb_poly = arb_poly | int | float | fmpz | fmpq | arb | fmpz_poly | fmpq_poly class arb_poly(flint_poly[arb]): @@ -123,3 +122,6 @@ class arb_poly(flint_poly[arb]): def __call__(self, t: acb | complex, /) -> acb: ... def unique_fmpz_poly(self) -> fmpz_poly | None: ... + + +iarb_poly = arb_poly | int | float | fmpz | fmpq | arb | fmpz_poly | fmpq_poly diff --git a/src/flint/types/arb_series.pyi b/src/flint/types/arb_series.pyi index 0c255b87..f3ce6729 100644 --- a/src/flint/types/arb_series.pyi +++ b/src/flint/types/arb_series.pyi @@ -20,7 +20,6 @@ from .fmpz_series import fmpz_series ifmpz = int | fmpz ifmpq = int | fmpz | fmpq iarf = int | float | fmpz | fmpq | arb -iarf_series = arb_series | iarf | fmpz_poly | fmpq_poly | fmpz_series | fmpq_series | arb_poly iacb_series = acb_series | acb | complex | acb_poly @@ -156,3 +155,6 @@ class arb_series(flint_series[arb]): @staticmethod def find_roots(f: Callable[[arb_series], arb_series], a: iarf, b: iarf, maxn: int = ...) -> list[tuple[arb, arb]]: ... + + +iarf_series = arb_series | iarf | fmpz_poly | fmpq_poly | fmpz_series | fmpq_series | arb_poly diff --git a/src/flint/types/arf.pyi b/src/flint/types/arf.pyi index c008c4da..5b163c18 100644 --- a/src/flint/types/arf.pyi +++ b/src/flint/types/arf.pyi @@ -8,8 +8,6 @@ from .fmpq import fmpq _str = str ifmpz = int | fmpz ifmpq = int | fmpz | fmpq -iarf_cmp = int | float | fmpz | fmpq | arf -iarf_arith = int | float | fmpz | arf class arf(flint_scalar): @@ -55,3 +53,7 @@ class arf(flint_scalar): def __rmul__(self, other: iarf_arith, /) -> arf: ... def __truediv__(self, other: iarf_arith, /) -> arf: ... def __rtruediv__(self, other: iarf_arith, /) -> arf: ... + + +iarf_cmp = int | float | fmpz | fmpq | arf +iarf_arith = int | float | fmpz | arf diff --git a/src/flint/types/fmpq.pyi b/src/flint/types/fmpq.pyi index 269fe2c6..9a44298b 100644 --- a/src/flint/types/fmpq.pyi +++ b/src/flint/types/fmpq.pyi @@ -5,7 +5,6 @@ from .fmpz import fmpz _str = str ifmpz = int | fmpz -ifmpq = int | fmpz | fmpq class fmpq(flint_scalar): @@ -93,3 +92,6 @@ class fmpq(flint_scalar): @staticmethod def dedekind_sum(n: ifmpz, k: ifmpz) -> fmpq: ... + + +ifmpq = int | fmpz | fmpq diff --git a/src/flint/types/fmpq_poly.pyi b/src/flint/types/fmpq_poly.pyi index 5f3848db..c6c9aaf7 100644 --- a/src/flint/types/fmpq_poly.pyi +++ b/src/flint/types/fmpq_poly.pyi @@ -6,9 +6,6 @@ from flint.types.acb import acb from flint.types.fmpz_poly import fmpz_poly, ifmpz_poly -ifmpq_poly = fmpq_poly | ifmpq | ifmpz_poly - - class fmpq_poly(flint_poly[fmpq]): """ The *fmpq_poly* type represents dense univariate polynomials @@ -95,3 +92,6 @@ class fmpq_poly(flint_poly[fmpq]): def euler_poly(n: int, /) -> fmpq_poly: ... @staticmethod def legendre_p(n: int, /) -> fmpq_poly: ... + + +ifmpq_poly = fmpq_poly | ifmpq | ifmpz_poly diff --git a/src/flint/types/fmpq_series.pyi b/src/flint/types/fmpq_series.pyi index 8ac0c3ee..375e18ef 100644 --- a/src/flint/types/fmpq_series.pyi +++ b/src/flint/types/fmpq_series.pyi @@ -6,9 +6,6 @@ from flint.types.fmpq_poly import fmpq_poly from flint.types.fmpz_series import fmpz_series, ifmpz_series -ifmpq_series = fmpq_series | fmpq_poly | ifmpz_series - - class fmpq_series(flint_series[fmpq]): """Approximate truncated power series with rational coefficients.""" @@ -76,3 +73,6 @@ class fmpq_series(flint_series[fmpq]): def sinh(self) -> fmpq_series: ... def cosh(self) -> fmpq_series: ... def tanh(self) -> fmpq_series: ... + + +ifmpq_series = fmpq_series | fmpq_poly | ifmpz_series diff --git a/src/flint/types/fmpz.pyi b/src/flint/types/fmpz.pyi index a94df7b8..7eaca9b7 100644 --- a/src/flint/types/fmpz.pyi +++ b/src/flint/types/fmpz.pyi @@ -5,7 +5,6 @@ from ..flint_base.flint_base import flint_scalar _str = str -ifmpz = int | fmpz class fmpz(flint_scalar): def __init__(self, arg: ifmpz | _str = 0, /): ... @@ -110,3 +109,5 @@ class fmpz(flint_scalar): def root(self, n: int) -> fmpz: ... def jacobi(self, other: ifmpz, /) -> int: ... + +ifmpz = int | fmpz diff --git a/src/flint/types/fmpz_mod.pyi b/src/flint/types/fmpz_mod.pyi index 23f07e6e..f06e6d95 100644 --- a/src/flint/types/fmpz_mod.pyi +++ b/src/flint/types/fmpz_mod.pyi @@ -5,7 +5,6 @@ from .fmpq import fmpq ifmpz = int | fmpz ifmpq = int | fmpz | fmpq -ifmpz_mod = ifmpz | fmpz_mod class fmpz_mod_ctx: @@ -64,3 +63,6 @@ class fmpz_mod(flint_scalar): def __invert__(self) -> fmpz_mod: ... def sqrt(self) -> fmpz_mod: ... + + +ifmpz_mod = ifmpz | fmpz_mod diff --git a/src/flint/types/fmpz_mod_poly.pyi b/src/flint/types/fmpz_mod_poly.pyi index bd863ba6..40634956 100644 --- a/src/flint/types/fmpz_mod_poly.pyi +++ b/src/flint/types/fmpz_mod_poly.pyi @@ -5,8 +5,6 @@ from flint.types.fmpz import fmpz from flint.types.fmpz_poly import fmpz_poly from flint.types.fmpz_mod import fmpz_mod, fmpz_mod_ctx, ifmpz, ifmpz_mod -ifmpz_mod_poly = ifmpz_mod | fmpz_mod_poly | fmpz_poly - class fmpz_mod_poly_ctx: r""" Context object for creating :class:`~.fmpz_mod_poly` initialised @@ -147,3 +145,5 @@ class fmpz_mod_poly(flint_poly[fmpz_mod]): ) -> list[tuple[fmpz_mod, int]]: ... @overload def roots(self, multiplicities: Literal[False]) -> list[fmpz_mod]: ... + +ifmpz_mod_poly = ifmpz_mod | fmpz_mod_poly | fmpz_poly diff --git a/src/flint/types/fmpz_poly.pyi b/src/flint/types/fmpz_poly.pyi index ce2aed07..19961844 100644 --- a/src/flint/types/fmpz_poly.pyi +++ b/src/flint/types/fmpz_poly.pyi @@ -7,8 +7,6 @@ from flint.types.arf import arf from flint.types.arb import arb from flint.types.acb import acb -ifmpz_poly = fmpz_poly | ifmpz - class fmpz_poly(flint_poly[fmpz]): """ The *fmpz_poly* type represents dense univariate polynomials over @@ -94,3 +92,5 @@ class fmpz_poly(flint_poly[fmpz]): @staticmethod def hilbert_class_poly(D: int, /) -> fmpz_poly: ... def height_bits(self, signed: bool = False) -> int: ... + +ifmpz_poly = fmpz_poly | ifmpz diff --git a/src/flint/types/fmpz_series.pyi b/src/flint/types/fmpz_series.pyi index c4f7f91c..494d3e8b 100644 --- a/src/flint/types/fmpz_series.pyi +++ b/src/flint/types/fmpz_series.pyi @@ -4,9 +4,6 @@ from flint.types.fmpz import fmpz, ifmpz from flint.types.fmpz_poly import fmpz_poly, ifmpz_poly -ifmpz_series = fmpz_series | ifmpz_poly - - class fmpz_series(flint_series[fmpz]): def __init__(self, @@ -44,3 +41,6 @@ class fmpz_series(flint_series[fmpz]): def __call__(self, other: ifmpz_series, /) -> fmpz_series: ... def reversion(self) -> fmpz_series: ... + + +ifmpz_series = fmpz_series | ifmpz_poly diff --git a/src/flint/types/fq_default.pyi b/src/flint/types/fq_default.pyi index c2993511..b29bea16 100644 --- a/src/flint/types/fq_default.pyi +++ b/src/flint/types/fq_default.pyi @@ -15,7 +15,6 @@ class fq_default_type(Enum): FMPZ_MOD = 5 ifmpz_mod = ifmpz | fmpz_mod -ifq_default = fq_default | fmpz_mod_poly | nmod_poly | fmpz_poly | ifmpz_mod class fq_default_ctx: r"""Context object for creating :class:`~.fq_default`.""" @@ -72,3 +71,5 @@ class fq_default(flint_scalar): def trace(self) -> fmpz: ... def norm(self) -> fmpz: ... def frobenius(self, e: int = ...) -> fq_default: ... + +ifq_default = fq_default | fmpz_mod_poly | nmod_poly | fmpz_poly | ifmpz_mod diff --git a/src/flint/types/fq_default_poly.pyi b/src/flint/types/fq_default_poly.pyi index 855143a0..f108d4ce 100644 --- a/src/flint/types/fq_default_poly.pyi +++ b/src/flint/types/fq_default_poly.pyi @@ -7,7 +7,6 @@ from .fmpz_mod_poly import fmpz_mod_poly from .fq_default import fq_default_type, fq_default_ctx, fq_default, ifq_default ifmpz_mod = int | fmpz | fmpz_mod -ifq_default_poly = fq_default_poly | ifq_default | ifmpz_poly class fq_default_poly_ctx: r"""Context object for creating :class:`~.fq_default_poly` initialised @@ -141,3 +140,5 @@ class fq_default_poly(flint_poly[fq_default]): ) -> tuple[fq_default, list[tuple[fq_default_poly, int]]]: ... def factor(self) -> tuple[fq_default, list[tuple[fq_default_poly, int]]]: ... def roots(self, multiplicities=True) -> list[tuple[fq_default, int]]: ... + +ifq_default_poly = fq_default_poly | ifq_default | ifmpz_poly diff --git a/src/flint/types/nmod.pyi b/src/flint/types/nmod.pyi index 8dbe8a4e..9947a81c 100644 --- a/src/flint/types/nmod.pyi +++ b/src/flint/types/nmod.pyi @@ -5,7 +5,6 @@ from .fmpq import fmpq _str = str ifmpz = int | fmpz ifmpq = int | fmpz | fmpq -inmod = int | fmpz | fmpq | nmod class nmod(flint_scalar): def __init__(self, val: inmod, mod: int): ... @@ -35,3 +34,5 @@ class nmod(flint_scalar): def __invert__(self) -> nmod: ... def sqrt(self) -> nmod: ... + +inmod = int | fmpz | fmpq | nmod diff --git a/src/flint/types/nmod_poly.pyi b/src/flint/types/nmod_poly.pyi index b6574a03..d8bb2882 100644 --- a/src/flint/types/nmod_poly.pyi +++ b/src/flint/types/nmod_poly.pyi @@ -3,8 +3,6 @@ from flint.flint_base.flint_base import flint_poly from flint.types.nmod import inmod, nmod from flint.types.fmpz_poly import fmpz_poly -inmod_poly = nmod_poly | fmpz_poly | inmod - class nmod_poly(flint_poly[nmod]): """Dense univariate polynomials over Z/nZ for word-size n.""" @@ -73,3 +71,5 @@ class nmod_poly(flint_poly[nmod]): def sqrt(self) -> nmod_poly: ... def deflation(self) -> tuple[nmod_poly, int]: ... def roots(self) -> list[tuple[nmod, int]]: ... + +inmod_poly = nmod_poly | fmpz_poly | inmod From c5696988679bff0f20410ad17e447231a5806bda Mon Sep 17 00:00:00 2001 From: Ilia Gradina Date: Tue, 13 Oct 2026 15:04:24 +0300 Subject: [PATCH 2/3] Add release note for gh-433 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 15939642..bc8a2fd8 100644 --- a/README.md +++ b/README.md @@ -169,9 +169,14 @@ Contributors (0.10.0): - Vitaly Magerya (VM) - Oscar Benjamin (OB) +- Ilia Gradina (IG) Changes (0.10.0): +- [gh-433](https://github.com/flintlib/python-flint/pull/433), + Define the input type aliases in the type stubs (such as `iarb` and + `ifmpz`) after the classes they reference, so that the ty type checker + resolves them instead of treating them as `Unknown`. (IG) - [gh-424](https://github.com/flintlib/python-flint/pull/424), Drop support for FLINT versions older than 3.4.0 and remove the associated compatibility code. (OB) From 4ce275e0d560452bf99c94e5f511cf60f154a5c0 Mon Sep 17 00:00:00 2001 From: Ilia Gradina Date: Tue, 13 Oct 2026 16:01:22 +0300 Subject: [PATCH 3/3] Remove unused variable flagged by cython-lint 0.22 cython-lint 0.22.0 now reports unused cdef locals in inline functions defined in .pxd files, so the Lint job fails on main with fmpz.pxd:25:16: 'w' defined but unused. The variable has been unused since the from_bytes/to_bytes conversion rewrite (f349183). --- src/flint/types/fmpz.pxd | 1 - 1 file changed, 1 deletion(-) diff --git a/src/flint/types/fmpz.pxd b/src/flint/types/fmpz.pxd index 165f8abc..d8b7af60 100644 --- a/src/flint/types/fmpz.pxd +++ b/src/flint/types/fmpz.pxd @@ -22,7 +22,6 @@ cdef inline int fmpz_set_pylong(fmpz_t x, obj): cdef slong longval cdef slong size cdef bytes b - cdef ulong w cdef ulong *words cdef int i