From d52fe19dee6e7157595e13a003ade428101406d4 Mon Sep 17 00:00:00 2001 From: Robert Nystrom Date: Fri, 10 Mar 2023 02:39:28 +0000 Subject: [PATCH] Add tests for non-primitive equality in switch cases. Even when a switch case only contains a constant (and not some more complex pattern), Dart 3.0 changes the semantics and allows constants of types that don't have primitive equality. Add some tests for that. Change-Id: Id3578d017822695451d7e44590fa349a8191a310 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/287663 Commit-Queue: Bob Nystrom Auto-Submit: Bob Nystrom Reviewed-by: Erik Ernst --- .../switch/equality_side_effect_test.dart | 46 +++++++++++ .../switch/non_primitive_equality_test.dart | 77 +++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 tests/language/switch/equality_side_effect_test.dart create mode 100644 tests/language/switch/non_primitive_equality_test.dart diff --git a/tests/language/switch/equality_side_effect_test.dart b/tests/language/switch/equality_side_effect_test.dart new file mode 100644 index 00000000000..79d7a31e0ee --- /dev/null +++ b/tests/language/switch/equality_side_effect_test.dart @@ -0,0 +1,46 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// SharedOptions=--enable-experiment=patterns,records + +// Switch cases may call user-defined `==` methods, which can have arbitrary +// side effects. Test that the cases are tried in order. + +import "package:expect/expect.dart"; + +class SideEffect { + static final effects = []; + + static String test(int value) { + effects.clear(); + + switch (SideEffect(value)) { + case const SideEffect(1): + effects.add('match one'); + case const SideEffect(2): + effects.add('match two'); + default: + effects.add('no match'); + } + + return effects.join(', '); + } + + final int value; + + const SideEffect(this.value); + + String toString() => 'S($value)'; + + bool operator ==(Object other) { + effects.add('$this == $other'); + return other is SideEffect && value == other.value; + } +} + +main() { + Expect.equals('S(1) == S(1), match one', SideEffect.test(1)); + Expect.equals('S(1) == S(2), S(2) == S(2), match two', SideEffect.test(2)); + Expect.equals('S(1) == S(3), S(2) == S(3), no match', SideEffect.test(3)); +} diff --git a/tests/language/switch/non_primitive_equality_test.dart b/tests/language/switch/non_primitive_equality_test.dart new file mode 100644 index 00000000000..6efdc08bf4f --- /dev/null +++ b/tests/language/switch/non_primitive_equality_test.dart @@ -0,0 +1,77 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// SharedOptions=--enable-experiment=patterns,records + +// With Dart 3.0, switch cases are pattersn and constants in cases are no +// longer required to have primitive equality. + +import "package:expect/expect.dart"; + +class ValueType { + static String test(int value) { + switch (ValueType(value)) { + case const ValueType(1): + return 'one'; + case const ValueType(2): + return 'two'; + default: + return 'other'; + } + } + + final int value; + + const ValueType(this.value); + + bool operator ==(Object other) => other is ValueType && value == other.value; +} + +class EquatableToString { + static String test(String value) { + switch (value) { + case const EquatableToString('ape'): + return 'primate'; + case const EquatableToString('bat'): + return 'chiroptera'; + default: + return 'other'; + } + } + + final String value; + + const EquatableToString(this.value); + + bool operator ==(Object other) => other is String && value == other; +} + +String testDouble(double value) { + switch (value) { + case 0.0: + return 'nothing'; + case 1.1: + return 'one-ish'; + case 2.2: + return 'two-ish'; + default: + return 'other'; + } +} + +main() { + Expect.equals('one', ValueType.test(1)); + Expect.equals('two', ValueType.test(2)); + Expect.equals('other', ValueType.test(3)); + + Expect.equals('primate', EquatableToString.test('ape')); + Expect.equals('chiroptera', EquatableToString.test('bat')); + Expect.equals('other', EquatableToString.test('cat')); + + Expect.equals('nothing', testDouble(0.0)); + Expect.equals('nothing', testDouble(-0.0)); + Expect.equals('one-ish', testDouble(1.1)); + Expect.equals('two-ish', testDouble(2.2)); + Expect.equals('other', testDouble(3.3)); +}