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

Equal LogicValue's may have unequal hash codes #206

Closed
bbracker-int opened this issue Nov 22, 2022 · 1 comment · Fixed by #217
Closed

Equal LogicValue's may have unequal hash codes #206

bbracker-int opened this issue Nov 22, 2022 · 1 comment · Fixed by #217
Assignees
Labels
bug Something isn't working

Comments

@bbracker-int
Copy link

Describe the bug

Two LogicValue's which are equal according to == may have different hash codes.
This creates unintended behavior when LogicValue's are used in data structures which leverage hash codes, such as a Map.

Based on preliminary testing, my very rough guess is that LogicValue flavors which are based on the underlying _LogicValueEnum type have different hash codes than LogicValue flavors which are based on the int and BigInt types.

To Reproduce

I made a test which can be pasted into test/logic_value_test.dart
Try uncommenting the tests that fail to reproduce.

    test('hash', () {
      const lvEnum = LogicValue.one;
      final lvBool = LogicValue.ofBool(true);
      final lvInt = LogicValue.ofInt(1, 1);
      final lvBigInt = LogicValue.ofBigInt(BigInt.one, 1);
      final lvFilled = LogicValue.filled(1, lvEnum);

      // test hash codes directly
      // pass
      expect(lvEnum.hashCode == lvBool.hashCode, equals(true));
      expect(lvEnum.hashCode == lvFilled.hashCode, equals(true));
      expect(lvInt.hashCode == lvBigInt.hashCode, equals(true));
      // fail
      /*
      expect(lvEnum.hashCode == lvInt.hashCode, equals(true));
      expect(lvInt.hashCode == lvFilled.hashCode, equals(true));
      */

      // test hash codes through map usage
      Map<LogicValue, int> myLvMap;
      // pass
      myLvMap = {lvEnum: 7}..remove(lvBool);
      expect(myLvMap.length, equals(0));
      myLvMap = {lvEnum: 7}..remove(lvFilled);
      expect(myLvMap.length, equals(0));
      myLvMap = {lvInt: 7}..remove(lvBigInt);
      expect(myLvMap.length, equals(0));
      // fail
      /*
      myLvMap = {lvEnum: 7}..remove(lvInt);
      expect(myLvMap.length, equals(0));
      myLvMap = {lvInt: 7}..remove(lvFilled);
      expect(myLvMap.length, equals(0));
      */
    });

Expected behavior

Equality of value as judged by == implies equality of hash code.

Actual behavior

Equality of value as judged by == does not imply equality of hash code.

Additional: Dart SDK info

Dart SDK version: 2.18.4 (stable) (Unknown timestamp) on "linux_x64"

Additional: pubspec.yaml

name: rohd
description: The Rapid Open Hardware Development (ROHD) framework, a framework for describing and verifying hardware
version: 0.4.0
homepage: https://github.com/intel/rohd
repository: https://github.com/intel/rohd
issue_tracker: https://github.com/intel/rohd/issues
documentation: https://intel.github.io/rohd/rohd/rohd-library.html

environment:
  sdk: '>=2.18.0 <3.0.0'

dependencies:
  collection: ^1.15.0
  logging: ^1.0.1
  meta: ^1.3.0
  test: ^1.17.3

dev_dependencies:
  benchmark_harness: ^2.2.0

Additional: Context

I reproduced this bug in the most up-to-date version of the ROHD repo, on branch main, where the working directory is completely clean of local changes except for the aforementioned logic_value_test.dart file. That is where the pubspec.yaml comes from.

@bbracker-int bbracker-int added the bug Something isn't working label Nov 22, 2022
@mkorbel1
Copy link
Contributor

mkorbel1 commented Dec 1, 2022

A simple solution could be to use the _bigIntValue and _bigIntInvalid from #215 and compute the hash in LogicValue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants