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

Equality subclasses unnecessarily allow null arguments #214

Open
natebosch opened this issue Sep 14, 2021 · 2 comments · Fixed by #215
Open

Equality subclasses unnecessarily allow null arguments #214

natebosch opened this issue Sep 14, 2021 · 2 comments · Fixed by #215
Labels
next-breaking-release Issues that are worth doing but need to wait for a breaking version bump

Comments

@natebosch
Copy link
Member

When we migrated to null safety we introduced a discrepancy and unnecessarily expanded the argument types for equals and hash.

We declare most of the classes to implements Equality<T>, but allow a T? for equals and hash, so when they are used directly they allow null arguments, but when used as an Equality the functionality is unnecessary.

For _UnorderedEquality this came from making T unnecessarily nullable, and in other subclasses the class level generics are fine but the method arguments are still expanded to allow null.

This entire test should be static errors in my opinion:

test('Equality accepts null', () {
var ie = IterableEquality();
var le = ListEquality();
var se = SetEquality();
var me = MapEquality();
expect(ie.equals(null, null), true);
expect(ie.equals([], null), false);
expect(ie.equals(null, []), false);
expect(ie.hash(null), null.hashCode);
expect(le.equals(null, null), true);
expect(le.equals([], null), false);
expect(le.equals(null, []), false);
expect(le.hash(null), null.hashCode);
expect(se.equals(null, null), true);
expect(se.equals({}, null), false);
expect(se.equals(null, {}), false);
expect(se.hash(null), null.hashCode);
expect(me.equals(null, null), true);
expect(me.equals({}, null), false);
expect(me.equals(null, {}), false);
expect(me.hash(null), null.hashCode);
});

Changing the arguments to non-nullable (with some extra handling of the nulls that flow from libraries that have not migrated to null safety) is a better design, but the impact of the breaking change is likely higher.

Changing the implements to implements Equality<T?> gives a more accurate interface and expands the places these classes can be used, but is still breaking.

See #161 (comment)

@natebosch natebosch added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label Sep 14, 2021
@natebosch
Copy link
Member Author

We could also keep the nullable arguments but leave the implemented interface as non-nullable and exclusively fix the generics of _UnorderedEquality to fix the issue discussed in #161

This is the least likely to break anything and does make some potential usage a bit better I think. I'll check how much it breaks internally to get an idea of the feasibility.

natebosch added a commit that referenced this issue Sep 14, 2021
Closes #214

The nullable `T` in `Equality<T>` changes the assignability and
introduces a difference between the other collection equality
implementations and the unordered implementations.

Prior to this change `SetEquality<T>` could not be statically assigned
to a `Equality<Set<T>>`, instead it had to be assigned to
`Equality<Set<T>?>`, while `ListEquality<T>` was assignable to
`Equality<List<T>>`. Now both are assignable.
natebosch added a commit that referenced this issue Sep 15, 2021
Towards #214

The nullable `T` in `Equality<T>` changes the assignability and
introduces a difference between the other collection equality
implementations and the unordered implementations.

Prior to this change `SetEquality<T>` could not be statically assigned
to a `Equality<Set<T>>`, instead it had to be assigned to
`Equality<Set<T>?>`, while `ListEquality<T>` was assignable to
`Equality<List<T>>`. Now both are assignable.
@natebosch natebosch reopened this Sep 15, 2021
@natebosch natebosch added next-breaking-release Issues that are worth doing but need to wait for a breaking version bump and removed type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) labels Sep 15, 2021
@natebosch
Copy link
Member Author

Keeping this open to consider whether we should remove the nullable argument types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
next-breaking-release Issues that are worth doing but need to wait for a breaking version bump
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant