Repository: sagemath/sage

Issue:
bugs in LazySeries over non-integral domains
### Steps To Reproduce

```
sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
sage: f = L(constant=2)
sage: f
2 + 2*z + 2*z^2 + O(z^3)
sage: 2*f
...
AssertionError: Stream_exact should only be used for non-zero streams
```

### Expected Behavior

```
sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
sage: f = L(constant=2)
sage: f
2 + 2*z + 2*z^2 + O(z^3)
sage: 2*f
0
```

### Actual Behavior

There is an error.

### Additional Information

_No response_

### Environment

```markdown
irrelevant
```


### Checklist

- [X] I have searched the existing issues for a bug report that matches the one I want to file, without success.
- [X] I have read the documentation and troubleshoot guide


Discussion:

Resolving patch:
diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py
--- a/src/sage/rings/lazy_series.py
+++ b/src/sage/rings/lazy_series.py
@@ -625,11 +625,22 @@ def truncate(self, d):
             sage: M = z + z^2 + z^3 + z^4
             sage: M.truncate(4)
             z + z^2 + z^3
+
+        TESTS:
+
+        Check that :issue:`36154` is fixed::
+
+            sage: L.<z> = LazyPowerSeriesRing(QQ)
+            sage: f = L([0,1,2])
+            sage: f.truncate(1)
+            0
         """
         P = self.parent()
         coeff_stream = self._coeff_stream
         v = coeff_stream._approximate_order
         initial_coefficients = [coeff_stream[i] for i in range(v, d)]
+        if not any(initial_coefficients):
+            return P.zero()
         return P.element_class(P, Stream_exact(initial_coefficients, order=v))
 
     def shift(self, n):
@@ -1838,6 +1849,14 @@ def _acted_upon_(self, scalar, self_on_left):
             sage: 1 * M is M
             True
 
+        TESTS:
+
+        Check that :issue:`36154` is fixed::
+
+            sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
+            sage: f = L(constant=2)
+            sage: 2*f
+            0
         """
         # With the current design, the coercion model does not have
         # enough information to detect a priori that this method only
@@ -1872,6 +1891,8 @@ def _acted_upon_(self, scalar, self_on_left):
             else:
                 c = scalar * coeff_stream._constant
                 initial_coefficients = [scalar * val for val in init_coeffs]
+            if not any(initial_coefficients) and not c:
+                return P.zero()
             return P.element_class(P, Stream_exact(initial_coefficients,
                                                    order=v,
                                                    constant=c,
@@ -2816,6 +2837,14 @@ def _mul_(self, other):
 
             sage: (1+z) * L([1,0,1], constant=1)
             1 + z + z^2 + 2*z^3 + 2*z^4 + 2*z^5 + O(z^6)
+
+        Check that :issue:`36154` is fixed::
+
+            sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
+            sage: f = L(constant=2, valuation=0)
+            sage: g = L([2])
+            sage: f * g
+            0
         """
         P = self.parent()
         left = self._coeff_stream
@@ -2874,6 +2903,8 @@ def _mul_(self, other):
                 c += left._constant * ir[-1]
             else:
                 c = left._constant  # this is zero
+            if not any(initial_coefficients) and not c:
+                return P.zero()
             coeff_stream = Stream_exact(initial_coefficients,
                                         order=lv + rv,
                                         constant=c)
@@ -2939,6 +2970,14 @@ def __pow__(self, n):
             sage: (1 + z)^(1 + z)
             1 + z + z^2 + 1/2*z^3 + 1/3*z^4 + 1/12*z^5 + 3/40*z^6 + O(z^7)
 
+        TESTS:
+
+        Check that :issue:`36154` is fixed::
+
+            sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
+            sage: f = L([2])
+            sage: f^2
+            0
         """
         if n == 0:
             return self.parent().one()
@@ -2951,6 +2990,8 @@ def __pow__(self, n):
             # return P(self.finite_part() ** ZZ(n))
             P = self.parent()
             ret = cs._polynomial_part(P._internal_poly_ring) ** ZZ(n)
+            if not ret:
+                return P.zero()
             val = ret.valuation()
             deg = ret.degree() + 1
             initial_coefficients = [ret[i] for i in range(val, deg)]
@@ -2958,7 +2999,6 @@ def __pow__(self, n):
                                                    constant=cs._constant,
                                                    degree=deg,
                                                    order=val))
-
         return super().__pow__(n)
 
     def __invert__(self):
@@ -3806,6 +3846,17 @@ def __call__(self, g, *, check=True):
             sage: g = L.undefined(valuation=0)
             sage: f(g) == f.polynomial()(g)
             True
+
+        TESTS:
+
+        Check that :issue:`36154` is fixed::
+
+            sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
+            sage: f = L([0,2])
+            sage: g = L([2])
+            sage: f(g)
+            0
+
         """
         # Find a good parent for the result
         from sage.structure.element import get_coercion_model
@@ -3850,6 +3901,8 @@ def __call__(self, g, *, check=True):
                 except (ValueError, TypeError):  # the result is not a Laurent polynomial
                     ret = None
                 if ret is not None and ret.parent() is R:
+                    if not ret:
+                        return P.zero()
                     val = ret.valuation()
                     deg = ret.degree() + 1
                     initial_coefficients = [ret[i] for i in range(val, deg)]
@@ -4164,6 +4217,12 @@ def derivative(self, *args):
             sage: f.derivative(q)[3]
             3*q^2 - 2
 
+        Check that :issue:`36154` is fixed::
+
+            sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
+            sage: f = L([0,0,2])
+            sage: f.derivative()
+            0
         """
         P = self.parent()
         R = P._laurent_poly_ring
@@ -4191,6 +4250,8 @@ def derivative(self, *args):
                 coeffs = [prod(i-k for k in range(order)) * c
                           for i, c in enumerate(coeff_stream._initial_coefficients,
                                                 coeff_stream._approximate_order)]
+            if not any(coeffs):
+                return P.zero()
             coeff_stream = Stream_exact(coeffs,
                                         order=coeff_stream._approximate_order - order,
                                         constant=coeff_stream._constant)
@@ -4993,6 +5054,14 @@ def derivative(self, *args):
              + (6*q^5*x^6+(-30*q^4)*x^5*y+60*q^3*x^4*y^2+(-60*q^2)*x^3*y^3+30*q*x^2*y^4+(-6)*x*y^5)
              + O(x,y)^7
 
+        TESTS:
+
+        Check that :issue:`36154` is fixed::
+
+            sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
+            sage: f = L([0,0,2])
+            sage: f.derivative()
+            0
         """
         P = self.parent()
         R = P._laurent_poly_ring
@@ -5038,6 +5107,8 @@ def derivative(self, *args):
                 coeffs = [prod(i-k for k in range(order)) * c
                           for i, c in enumerate(coeff_stream._initial_coefficients,
                                                 coeff_stream._approximate_order)]
+            if not any(coeffs):
+                return P.zero()
             coeff_stream = Stream_exact(coeffs,
                                         order=coeff_stream._approximate_order - order,
                                         constant=coeff_stream._constant)


Test patch: