def _sentry_safe_cast(fromty, toty):
    """Check and raise TypingError if *fromty* cannot be safely cast to *toty*
    """
    tyctxt = cpu_target.typing_context
    fromty, toty = map(types.unliteral, (fromty, toty))
    by = tyctxt.can_convert(fromty, toty)

    def warn():
        m = 'unsafe cast from {} to {}. Precision may be lost.'
        warnings.warn(m.format(fromty, toty),
                      category=NumbaTypeSafetyWarning)

    isint = lambda x: isinstance(x, types.Integer)
    isflt = lambda x: isinstance(x, types.Float)
    iscmplx = lambda x: isinstance(x, types.Complex)
    isdict = lambda x: isinstance(x, types.DictType)
    # Only check against numeric types.
    if by is None or by > Conversion.safe:
        if isint(fromty) and isint(toty):
            # Accept if both types are ints
            warn()
        elif isint(fromty) and isflt(toty):
            # Accept if ints to floats
            warn()
        elif isflt(fromty) and isflt(toty):
            # Accept if floats to floats
            warn()
        elif iscmplx(fromty) and iscmplx(toty):
            # Accept if complex to complex
            warn()
        elif isdict(fromty) and isdict(toty):
            pass # it's complaining about initial values being different
        elif not isinstance(toty, types.Number):
            # Non-numbers
            warn()
        else:
            # Make it a hard error for numeric type that changes domain.
            m = 'cannot safely cast {} to {}. Please cast explicitly.'
            raise TypingError(m.format(fromty, toty))
Check and raise TypingError if *fromty* cannot be safely cast to *toty*
    
numba/typed/typedobjectutils.py