Skip to content

Explicit num equality comparison doesn't account for records containing nums #211

Description

@Mike278

Repro with version 2.0.8:

import 'package:equatable/equatable.dart';

void main() {
  int i = 1;
  double d = 1.0;
  print(i == d);                                    // prints true
  print(JustNum(i) == JustNum(d));                  // prints true (after PR#189)
  print(NumInList([i]) == NumInList([d]));          // prints true

  final ri = (value: i);
  final rd = (value: d);
  print(ri == rd);                           // prints true (though incorrectly triggers unrelated_type_equality_checks lint, noted in https://github.com/dart-lang/sdk/issues/57962#issuecomment-4215639345)
  print(NumInRecord(ri) == NumInRecord(rd)); // prints false
}

class JustNum with EquatableMixin {
  final num value;
  JustNum(this.value);

  @override
  List<Object?> get props => [value];
}

class NumInRecord with EquatableMixin {
  final ({num value}) value;
  NumInRecord(this.value);

  @override
  List<Object?> get props => [value];
}

class NumInList with EquatableMixin {
  final List<num> value;
  NumInList(this.value);

  @override
  List<Object?> get props => [value];
}

In objectsEquals, would it make sense to do something like this?

/// Determines whether two objects are equal.
@pragma('vm:prefer-inline')
bool objectsEquals(Object? a, Object? b) {
  if (identical(a, b)) return true;
  if (a is num && b is num) {
    return numEquals(a, b);
  } else if (_isEquatable(a) && _isEquatable(b)) {
    return a == b;
  } else if (a is Set && b is Set) {
    return setEquals(a, b);
  } else if (a is Iterable && b is Iterable) {
    return iterableEquals(a, b);
  } else if (a is Map && b is Map) {
    return mapEquals(a, b);
  } else if (a is Record && b is Record) { // dont check runtime type for records
    return a == b;
  } else if (a?.runtimeType != b?.runtimeType) {
    return false;
  } else if (a != b) {
    return false;
  }
  return true;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions