Yes that's conversion, but both 0+x and x+0 works because, I think, of lines 979-990 of
sage.structure.coerce.pyx:
# Allow coercion of 0 even if no coercion from Z
if is_Integer(x) and not x and type(yp) is not type:
try:
return yp(0), y
except Exception:
self._record_exception()
if is_Integer(y) and not y and type(xp) is not type:
try:
return x, xp(0)
except Exception:
self._record_exception()
Here is the example on free modules of
#15916:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M')
sage: e = M.basis('e')
sage: x = M([1,-2,3], basis=e) ; x
Element of the Rank-3 free module M over the Integer Ring
sage: x.display()
e_0 - 2 e_1 + 3 e_2
There is conversion of 0 to an element of M, but no coercion of ZZ into M:
sage: M(0)
Element zero of the Rank-3 free module M over the Integer Ring
sage: M.has_coerce_map_from(ZZ)
False
Because of the lines of coerce.pyx listed above, we have:
sage: cm = sage.structure.element.get_coercion_model()
sage: cm.canonical_coercion(0, x)
(Element zero of the Rank-3 free module M over the Integer Ring,
Element of the Rank-3 free module M over the Integer Ring)
sage: cm.canonical_coercion(x, 0)
(Element of the Rank-3 free module M over the Integer Ring,
Element zero of the Rank-3 free module M over the Integer Ring)
so that both x+0 and 0+x works:
sage: s = 0 + x ; s
Element of the Rank-3 free module M over the Integer Ring
sage: s.display()
e_0 - 2 e_1 + 3 e_2
sage: s = x + 0 ; s
Element of the Rank-3 free module M over the Integer Ring
sage: s.display()
e_0 - 2 e_1 + 3 e_2
Because there is "is_Integer(x)" in line 980 of coerce.pyx, this does not work for a 0 different from ZZ(0):
sage: zq = QQ(0)
sage: cm.canonical_coercion(zq, x)
...
TypeError: no common canonical parent for objects with parents: 'Rational Field' and 'Rank-3 free module M over the Integer Ring'
Indeed:
sage: s = zq + x
...
TypeError: unsupported operand parent(s) for '+': 'Rational Field' and 'Rank-3 free module M over the Integer Ring'
Best regards,
Eric.