Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hvec_map::insert has a non-standard behavior #4389

Closed
asl opened this issue Feb 4, 2024 · 2 comments
Closed

hvec_map::insert has a non-standard behavior #4389

asl opened this issue Feb 4, 2024 · 2 comments
Assignees
Labels
bug This behavior is unintended and should be fixed. core Topics concerning the core segments of the compiler (frontend, midend, parser) fixed This topic is considered to be fixed.

Comments

@asl
Copy link
Contributor

asl commented Feb 4, 2024

hvec_map::insert looks like this:

    std::pair<iterator, bool> insert(const value_type &v) {
        bool new_key = false;
        size_t idx = hv_insert(&v.first);
        if (idx >= data.size()) {
            idx = data.size();
            data.push_back(v);
            new_key = true;
        } else {
            if ((new_key = erased[idx])) {
                erased[idx] = 0;
                const_cast<KEY &>(data[idx].first) = v.first;
                data[idx].second = v.second;
            } else {
                data[idx].second = v.second;
            }
        }
        return std::make_pair(iterator(*this, idx), new_key);
    }

Note that regardless whether element existed in the map or not, value is replaced. The bool result indicates whether the key was replaced and this is non-standard as well. Normally we expect from map inserts: a pair consisting of an iterator to the inserted element (or to the element that prevented the insertion) and a bool value set to true if and only if the insertion took place.

Such behavior could lead to very subtle bugs in common pattern insert-or-merge, e.g.:

hvec_map<key, value> m;
auto [it, inserted] = m.insert({something, something_else});
if (!inserted)
 merge(it->second, something_else);

hvec_map::emplace has the same problem.

@asl
Copy link
Contributor Author

asl commented Feb 4, 2024

Tagging @ChrisDodd

I think the else in if ((new_key = erased[idx])) { should be removed to fix the issue. We cannot override value for non-erased entries.

@fruffy fruffy added bug This behavior is unintended and should be fixed. core Topics concerning the core segments of the compiler (frontend, midend, parser) labels Feb 4, 2024
@ChrisDodd ChrisDodd added the fixed This topic is considered to be fixed. label Feb 26, 2024
@ChrisDodd
Copy link
Contributor

Fixed by #4458

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This behavior is unintended and should be fixed. core Topics concerning the core segments of the compiler (frontend, midend, parser) fixed This topic is considered to be fixed.
Projects
None yet
Development

No branches or pull requests

3 participants