blob: c837627af5f252ba147309642d4ca9bd0fb79eab [file] [log] [blame]
// 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.
/// Test various places that implicit casts from dynamic can be inserted in
/// patterns and what happens when those casts succeed and fail.
import "package:expect/expect.dart";
main() {
testRelational();
testTypedVariable();
testListPattern();
testMapPattern();
testObjectPattern();
testListDestructure();
testMapDestructure();
testObjectDestructure();
}
class C {
int get knownInt => 123;
dynamic get dynamicInt => 123;
dynamic get dynamicString => 'wrong type';
}
void testRelational() {
// Test casts from dynamic on the right operand to a relational operator.
const dynamic big = 234;
// Matches in refutable context if type matches and operation is true.
if (123 case < big) {
// OK.
} else {
Expect.fail('Should have matched.');
}
}
void testTypedVariable() {
// Succeeds if cast succeeds.
var (int x) = 123 as dynamic;
Expect.equals(123, x);
// Throws in irrefutable context if cast fails.
Expect.throws(() {
var (int x) = 'wrong type' as dynamic;
});
// Matches in refutable context if type matches.
if (123 as dynamic case int x) {
Expect.equals(123, x);
} else {
Expect.fail('Should have matched.');
}
// Refuted in refutable context if type doesn't match.
if ('wrong type' as dynamic case int x) {
Expect.fail('Should not have matched.');
} else {
// OK.
}
}
void testListPattern() {
// Succeeds if cast to List succeeds.
var [x] = [123] as dynamic;
Expect.equals(123, x);
// Throws in irrefutable context if cast fails.
Expect.throws(() {
var [x] = 'wrong type' as dynamic;
});
// Matches in refutable context if type matches.
if ([123] as dynamic case [var x]) {
Expect.equals(123, x);
} else {
Expect.fail('Should have matched.');
}
// Refuted in refutable context if type doesn't match.
if ('wrong type' as dynamic case [var x]) {
Expect.fail('Should not have matched.');
} else {
// OK.
}
}
void testMapPattern() {
// Succeeds if cast to Map succeeds.
var {'x': x} = {'x': 123} as dynamic;
Expect.equals(123, x);
// Throws in irrefutable context if cast fails.
Expect.throws(() {
var {'x': x} = 'wrong type' as dynamic;
});
// Matches in refutable context if type matches.
if ({'x': 123} as dynamic case {'x': var x}) {
Expect.equals(123, x);
} else {
Expect.fail('Should have matched.');
}
// Refuted in refutable context if type doesn't match.
if ('wrong type' as dynamic case {'x': var x}) {
Expect.fail('Should not have matched.');
} else {
// OK.
}
}
void testObjectPattern() {
// Succeeds if cast to C succeeds.
var C(knownInt: x) = C() as dynamic;
Expect.equals(123, x);
// Throws in irrefutable context if cast fails.
Expect.throws(() {
var C(knownInt: x) = 'wrong type' as dynamic;
});
// Matches in refutable context if type matches.
if (C() as dynamic case C(knownInt: var x)) {
Expect.equals(123, x);
} else {
Expect.fail('Should have matched.');
}
// Refuted in refutable context if type doesn't match.
if ('wrong type' as dynamic case C(knownInt: var x)) {
Expect.fail('Should not have matched.');
} else {
// OK.
}
}
void testListDestructure() {
// Test when a destructured list element of type dynamic is matched by a
// subpattern that expects a type.
// Succeeds if cast succeeds.
var [int x] = <dynamic>[123];
Expect.equals(123, x);
// Throws in irrefutable context if cast fails.
Expect.throws(() {
var [int x] = <dynamic>['wrong type'];
});
// Matches in refutable context if type matches.
if (<dynamic>[123] case [int x]) {
Expect.equals(123, x);
} else {
Expect.fail('Should have matched.');
}
// Refuted in refutable context if type doesn't match.
if (<dynamic>['wrong type'] case [int x]) {
Expect.fail('Should not have matched.');
} else {
// OK.
}
}
void testMapDestructure() {
// Test when a destructured map value of type dynamic is matched by a
// subpattern that expects a type.
// Succeeds if cast succeeds.
var {'x': int x} = <String, dynamic>{'x': 123};
Expect.equals(123, x);
// Throws in irrefutable context if cast fails.
Expect.throws(() {
var {'x': int x} = <String, dynamic>{'x': 'wrong type'};
});
// Matches in refutable context if type matches.
if (<String, dynamic>{'x': 123} case {'x': int x}) {
Expect.equals(123, x);
} else {
Expect.fail('Should have matched.');
}
// Refuted in refutable context if type doesn't match.
if (<String, dynamic>{'x': 'wrong type'} case {'x': int x}) {
Expect.fail('Should not have matched.');
} else {
// OK.
}
}
void testObjectDestructure() {
// Test when a destructured object getter of type dynamic is matched by a
// subpattern that expects a type.
// Succeeds if cast succeeds.
var C(dynamicInt: int x) = C();
Expect.equals(123, x);
// Throws in irrefutable context if cast fails.
Expect.throws(() {
var C(dynamicString: int x) = C();
});
// Matches in refutable context if type matches.
if (C() case C(dynamicInt: int x)) {
Expect.equals(123, x);
} else {
Expect.fail('Should have matched.');
}
// Refuted in refutable context if type doesn't match.
if (C() case C(dynamicString: int x)) {
Expect.fail('Should not have matched.');
} else {
// OK.
}
}