blob: 2a35320793c1db04b11d642c3e2a698c93675a17 [file] [log] [blame]
// Copyright (c) 2018, 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 that the value of constant type literals are allowed as
// constant map keys and case expressions, and the value of non-constant type
// literals are not.
import "dart:collection" deferred as prefix;
main(args) {
testSwitch(args);
testMaps(args);
}
const Type numType = num;
const bool fromEnvironment =
const bool.fromEnvironment("foo", defaultValue: true);
Type argumentType<T>() => T;
void testSwitch<T extends MyType>(args) {
var types = [MyType, T, argumentType<MyType>(), argumentType<T>()];
for (int i = 0; i < types.length; i++) {
switch (types[i]) {
// Must be type literal or not override `==`.
case const MyType(0): //# 01: compile-time error
// Must not be type variable.
case T: //# 02: compile-time error
// Must not be deferred type.
case prefix.HashSet: //# 03: compile-time error
// Constant type literals are valid.
case String:
throw "unreachable: String #$i";
case int:
throw "unreachable: int #$i";
case numType:
throw "unreachable: num #$i";
case MyType:
break;
// Must be type literal or not override `==`.
case fromEnvironment ? const MyType(1) : Type: //# 07: compile-time error
default:
throw "unreachable: default #$i";
}
}
}
void testMaps<T extends MyType>(args) {
const map = {
// Must be type literal or not override `==`.
MyType(0): 0, //# 04: compile-time error
// Must not be type variable.
T: 0, //# 05: compile-time error
// Must not be deferred.
prefix.HashSet: 0, //# 06: compile-time error
// Constant type literals are valid.
MyType: 0,
int: 1,
String: 2,
numType: 3,
// Must be type literal or not override `==`.
fromEnvironment ? const MyType(1) : Type: 4, //# 08: compile-time error
};
if (map[MyType] != 0) throw "Map Error: ${MyType} as literal";
if (map[T] != 0) throw "Map Error: ${T} as type argument";
if (map[argumentType<MyType>()] != 0) {
throw "Map Error: ${argumentType<MyType>()} as type argument of literal";
}
if (map[argumentType<T>()] != 0) {
throw "Map Error: ${argumentType<T>()} as type argument of type variable";
}
if (map[num] != 3) throw "Map Error: ${num} -> ${map[num]}";
}
// An implementation of `Type` which overrides `==`,
// but is not the value of a constant type literal.
class MyType implements Type {
final int value;
const MyType(this.value);
int get hashCode => 0;
bool operator ==(Object other) => identical(this, other);
}