Skip to content

Type propagation: just because something is const doesn't mean it automatically matches the type #115859

@Fidget-Spinner

Description

@Fidget-Spinner

Bug report

Bug description:

See log files for failure:

https://github.com/python/cpython/actions/runs/8021737661/job/21914497578

An example failure from my Windows machine:

Assertion failed: PyFloat_CheckExact(sym_get_const(left)), file C:\Users\Ken\Documents\GitHub\cpython\Python\tier2_redundancy_eliminator_cases.c.h, line 279
Fatal Python error: Aborted

Just because a constant is present, doesn't mean it's the right type. In such a case, I think we should bail from the abstract interpreter, because it's a guaranteed deopt.

E.g.

    op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) {
        if (sym_matches_type(left, &PyFloat_Type) &&
            sym_matches_type(right, &PyFloat_Type)) {
            REPLACE_OP(this_instr, _NOP, 0 ,0);
        }
        sym_set_type(left, &PyFloat_Type);
        sym_set_type(right, &PyFloat_Type);
    }

should become

    op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) {
        if (sym_matches_type(left, &PyFloat_Type) &&
            sym_matches_type(right, &PyFloat_Type)) {
            REPLACE_OP(this_instr, _NOP, 0 ,0);
        }
        if (sym_is_const(left)) {
            if (!sym_const_is_type(left, &PyFloat_Type) goto guaranteed_deopt;
        }
        if (sym_is_const(right)) {
            if (!sym_const_is_type(right, &PyFloat_Type) goto guaranteed_deopt;
        }
        sym_set_type(left, &PyFloat_Type);
        sym_set_type(right, &PyFloat_Type);
    }

While

    op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) {
        if (sym_is_const(left) && sym_is_const(right)) {
            assert(PyFloat_CheckExact(sym_get_const(left)));
            assert(PyFloat_CheckExact(sym_get_const(right)));
            PyObject *temp = PyFloat_FromDouble(
                PyFloat_AS_DOUBLE(sym_get_const(left)) +
                PyFloat_AS_DOUBLE(sym_get_const(right)));
            ERROR_IF(temp == NULL, error);
            OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp));
            // TODO gh-115506:
            // replace opcode with constant propagated one and update tests!
        }
        else {
            OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type));
        }
    }

should become

    op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) {
        if (sym_is_const(left) && sym_is_const(right)) {
            if(!PyFloat_CheckExact(sym_get_const(left))) {
                goto guaranteed_deopt;
            }
            if(!PyFloat_CheckExact(sym_get_const(right))) {
                goto guaranteed_deopt;
            }
            PyObject *temp = PyFloat_FromDouble(
                PyFloat_AS_DOUBLE(sym_get_const(left)) +
                PyFloat_AS_DOUBLE(sym_get_const(right)));
            ERROR_IF(temp == NULL, error);
            OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp));
            // TODO gh-115506:
            // replace opcode with constant propagated one and update tests!
        }
        else {
            OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyFloat_Type));
        }
    }

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Labels

type-bugAn unexpected behavior, bug, or error

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions