18f37dd8f3
We use an extension getter instead of an instance getter because it doesn't conflict with any potential existing or future enums which want an element named `name`. Keeping the namespace for enum elements open is a priority. We currently only reserve `index` and `values`. BUG: https://github.com/dart-lang/language/issues/1511 Fixes language issue #1511, which is a long-standing request, and should replace a number of alternative implementations which are based on parsing the `toString()`. This version has two fields on the shared superclass, the index and private name, and has a separate `toString` for each `enum` class which hard-codes that enum's class name. An earlier version had both `"name"` and `"ClassName.name"` as fields to be able to reuse the same `toString` method on all enum classes, but that cost too much for JS compiled code. Even having just `ClassName.` as a field and then combining inside `toString` requires more code to create the enum instances. Instead this version hardcodes the `ClassName.` string once in the `toString` method, which means each enum class has its own toString (which can *potentially* be tree-shaken then.) This still tree-shakes slightly worse than the previous implementation where every enum class had its own `index` and `_name` fields independent of each other, which could then be tree-shaken independently. However, the `index` was already made an interface member with the addition of the `Enum` interface, so code which accesses `.index` on something of the `Enum` supertype could prevent tree-shaking of all enum classes' `index` fields. Likewise any general access to the "name" of an enum would necessarily do the same for the name. This CL makes up for some of that by sharing more implementation between enum classes. DartVM AOT CodeSize impact: ~0.15% regression on gallery (little less on big g3 app) TEST= New tests added to enum_test.dart Change-Id: Id25334e6c987f470f558de3c141d0e3ff542b020 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210480 Commit-Queue: Lasse R.H. Nielsen <lrn@google.com> Reviewed-by: Stephen Adams <sra@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
468 lines
10 KiB
Dart
468 lines
10 KiB
Dart
// 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.
|
|
|
|
// @dart = 2.7
|
|
|
|
/*member: main:
|
|
static=[
|
|
testAbstractClassWithField(0),
|
|
testEnum(0),
|
|
testForwardingConstructor(0),
|
|
testForwardingConstructorGeneric(0),
|
|
testForwardingConstructorTyped(0),
|
|
testGenericMixinInstantiation(0),
|
|
testGenericNamedMixinInstantiation(0),
|
|
testInstanceGenericMethod(0),
|
|
testMixinInstantiation(0),
|
|
testNamedMixinInstantiation(0),
|
|
testStaticGenericMethod(0),
|
|
testSuperCall(0),
|
|
testSuperClosurization(0),
|
|
testSuperFieldSet(0),
|
|
testSuperGet(0),
|
|
testSuperSetterSet(0)]
|
|
*/
|
|
main() {
|
|
testSuperCall();
|
|
testSuperGet();
|
|
testSuperFieldSet();
|
|
testSuperSetterSet();
|
|
testSuperClosurization();
|
|
testForwardingConstructor();
|
|
testForwardingConstructorTyped();
|
|
testForwardingConstructorGeneric();
|
|
testEnum();
|
|
testStaticGenericMethod();
|
|
testInstanceGenericMethod();
|
|
testAbstractClassWithField();
|
|
testMixinInstantiation();
|
|
testNamedMixinInstantiation();
|
|
testGenericMixinInstantiation();
|
|
testGenericNamedMixinInstantiation();
|
|
}
|
|
|
|
/*member: Super1.:static=[Object.(0)]*/
|
|
class Super1 {
|
|
/*member: Super1.foo:*/
|
|
foo() {}
|
|
}
|
|
|
|
class Sub1 extends Super1 {
|
|
/*member: Sub1.:static=[Super1.(0),Super1.foo(0)]*/
|
|
Sub1() {
|
|
super.foo();
|
|
}
|
|
}
|
|
|
|
/*member: testSuperCall:static=[Sub1.(0)]*/
|
|
testSuperCall() => new Sub1();
|
|
|
|
/*member: Super2.:static=[Object.(0)]*/
|
|
class Super2 {
|
|
/*member: Super2.foo:type=[inst:JSNull]*/
|
|
var foo;
|
|
}
|
|
|
|
class Sub2 extends Super2 {
|
|
/*member: Sub2.:static=[Super2.(0),Super2.foo]*/
|
|
Sub2() {
|
|
super.foo;
|
|
}
|
|
}
|
|
|
|
/*member: testSuperGet:static=[Sub2.(0)]*/
|
|
testSuperGet() => new Sub2();
|
|
|
|
/*member: Super3.:static=[Object.(0)]*/
|
|
class Super3 {
|
|
/*member: Super3.foo:type=[inst:JSNull]*/
|
|
var foo;
|
|
}
|
|
|
|
class Sub3 extends Super3 {
|
|
/*member: Sub3.:static=[Super3.(0),set:Super3.foo],type=[inst:JSBool]*/
|
|
Sub3() {
|
|
super.foo = true;
|
|
}
|
|
}
|
|
|
|
/*member: testSuperFieldSet:static=[Sub3.(0)]*/
|
|
testSuperFieldSet() => new Sub3();
|
|
|
|
/*member: Super4.:static=[Object.(0)]*/
|
|
class Super4 {
|
|
/*member: Super4.foo=:*/
|
|
set foo(_) {}
|
|
}
|
|
|
|
class Sub4 extends Super4 {
|
|
/*member: Sub4.:static=[Super4.(0),set:Super4.foo],type=[inst:JSBool]*/
|
|
Sub4() {
|
|
super.foo = true;
|
|
}
|
|
}
|
|
|
|
/*member: testSuperSetterSet:static=[Sub4.(0)]*/
|
|
testSuperSetterSet() => new Sub4();
|
|
|
|
/*member: Super5.:static=[Object.(0)]*/
|
|
class Super5 {
|
|
/*member: Super5.foo:*/
|
|
foo() {}
|
|
}
|
|
|
|
/*member: Sub5.:static=[Super5.(0),Super5.foo]*/
|
|
class Sub5 extends Super5 {
|
|
Sub5() {
|
|
super.foo;
|
|
}
|
|
}
|
|
|
|
/*member: testSuperClosurization:static=[Sub5.(0)]*/
|
|
testSuperClosurization() => new Sub5();
|
|
|
|
class EmptyMixin {}
|
|
|
|
class ForwardingConstructorSuperClass {
|
|
/*member: ForwardingConstructorSuperClass.:static=[Object.(0)]*/
|
|
ForwardingConstructorSuperClass(arg);
|
|
}
|
|
|
|
class ForwardingConstructorClass = ForwardingConstructorSuperClass
|
|
with EmptyMixin;
|
|
|
|
/*member: testForwardingConstructor:
|
|
static=[ForwardingConstructorClass.(1)],
|
|
type=[inst:JSNull]
|
|
*/
|
|
testForwardingConstructor() => new ForwardingConstructorClass(null);
|
|
|
|
class ForwardingConstructorTypedSuperClass {
|
|
/*member: ForwardingConstructorTypedSuperClass.:
|
|
static=[
|
|
Object.(0),
|
|
Rti._bind(1),
|
|
Rti._eval(1),
|
|
_arrayInstanceType(1),
|
|
_asBool(1),
|
|
_asBoolQ(1),
|
|
_asBoolS(1),
|
|
_asDouble(1),
|
|
_asDoubleQ(1),
|
|
_asDoubleS(1),
|
|
_asInt(1),
|
|
_asIntQ(1),
|
|
_asIntS(1),
|
|
_asNum(1),
|
|
_asNumQ(1),
|
|
_asNumS(1),
|
|
_asObject(1),
|
|
_asString(1),
|
|
_asStringQ(1),
|
|
_asStringS(1),
|
|
_asTop(1),
|
|
_generalAsCheckImplementation(1),
|
|
_generalIsTestImplementation(1),
|
|
_generalNullableAsCheckImplementation(1),
|
|
_generalNullableIsTestImplementation(1),
|
|
_installSpecializedAsCheck(1),
|
|
_installSpecializedIsTest(1),
|
|
_instanceType(1),
|
|
_isBool(1),
|
|
_isInt(1),
|
|
_isNum(1),
|
|
_isObject(1),
|
|
_isString(1),
|
|
_isTop(1),
|
|
findType(1),
|
|
instanceType(1)],
|
|
type=[
|
|
inst:Closure,
|
|
inst:JSBool,
|
|
param:int*]
|
|
*/
|
|
ForwardingConstructorTypedSuperClass(int arg);
|
|
}
|
|
|
|
class ForwardingConstructorTypedClass = ForwardingConstructorTypedSuperClass
|
|
with EmptyMixin;
|
|
|
|
/*member: testForwardingConstructorTyped:
|
|
static=[ForwardingConstructorTypedClass.(1)],
|
|
type=[inst:JSNull]
|
|
*/
|
|
testForwardingConstructorTyped() => new ForwardingConstructorTypedClass(null);
|
|
|
|
class ForwardingConstructorGenericSuperClass<T> {
|
|
/*member: ForwardingConstructorGenericSuperClass.:
|
|
static=[
|
|
Object.(0),
|
|
Rti._bind(1),
|
|
Rti._eval(1),
|
|
_arrayInstanceType(1),
|
|
_asBool(1),
|
|
_asBoolQ(1),
|
|
_asBoolS(1),
|
|
_asDouble(1),
|
|
_asDoubleQ(1),
|
|
_asDoubleS(1),
|
|
_asInt(1),
|
|
_asIntQ(1),
|
|
_asIntS(1),
|
|
_asNum(1),
|
|
_asNumQ(1),
|
|
_asNumS(1),
|
|
_asObject(1),
|
|
_asString(1),
|
|
_asStringQ(1),
|
|
_asStringS(1),
|
|
_asTop(1),
|
|
_generalAsCheckImplementation(1),
|
|
_generalIsTestImplementation(1),
|
|
_generalNullableAsCheckImplementation(1),
|
|
_generalNullableIsTestImplementation(1),
|
|
_installSpecializedAsCheck(1),
|
|
_installSpecializedIsTest(1),
|
|
_instanceType(1),
|
|
_isBool(1),
|
|
_isInt(1),
|
|
_isNum(1),
|
|
_isObject(1),
|
|
_isString(1),
|
|
_isTop(1),
|
|
_setArrayType(2),
|
|
findType(1),
|
|
instanceType(1)],
|
|
type=[
|
|
inst:Closure,
|
|
inst:JSArray<dynamic>,
|
|
inst:JSBool,
|
|
inst:JSExtendableArray<dynamic>,
|
|
inst:JSFixedArray<dynamic>,
|
|
inst:JSMutableArray<dynamic>,
|
|
inst:JSUnmodifiableArray<dynamic>,
|
|
param:ForwardingConstructorGenericSuperClass.T*]
|
|
*/
|
|
ForwardingConstructorGenericSuperClass(T arg);
|
|
}
|
|
|
|
class ForwardingConstructorGenericClass<
|
|
S> = ForwardingConstructorGenericSuperClass<S> with EmptyMixin;
|
|
|
|
/*member: testForwardingConstructorGeneric:
|
|
static=[
|
|
ForwardingConstructorGenericClass.(1),
|
|
checkTypeBound(4)],
|
|
type=[inst:JSNull]
|
|
*/
|
|
testForwardingConstructorGeneric() {
|
|
new ForwardingConstructorGenericClass<int>(null);
|
|
}
|
|
|
|
enum Enum { A }
|
|
|
|
/*member: testEnum:
|
|
static=[
|
|
_Enum._name=StringConstant("A"),
|
|
_Enum.index=IntConstant(0)],
|
|
type=[
|
|
const:Enum,
|
|
inst:JSInt,
|
|
inst:JSNumNotInt,
|
|
inst:JSNumber,
|
|
inst:JSPositiveInt,
|
|
inst:JSString,
|
|
inst:JSUInt31,
|
|
inst:JSUInt32]
|
|
*/
|
|
testEnum() => Enum.A;
|
|
|
|
/*member: staticGenericMethod:
|
|
static=[
|
|
Rti._bind(1),
|
|
Rti._eval(1),
|
|
_arrayInstanceType(1),
|
|
_asBool(1),
|
|
_asBoolQ(1),
|
|
_asBoolS(1),
|
|
_asDouble(1),
|
|
_asDoubleQ(1),
|
|
_asDoubleS(1),
|
|
_asInt(1),
|
|
_asIntQ(1),
|
|
_asIntS(1),
|
|
_asNum(1),
|
|
_asNumQ(1),
|
|
_asNumS(1),
|
|
_asObject(1),
|
|
_asString(1),
|
|
_asStringQ(1),
|
|
_asStringS(1),
|
|
_asTop(1),
|
|
_generalAsCheckImplementation(1),
|
|
_generalIsTestImplementation(1),
|
|
_generalNullableAsCheckImplementation(1),
|
|
_generalNullableIsTestImplementation(1),
|
|
_installSpecializedAsCheck(1),
|
|
_installSpecializedIsTest(1),
|
|
_instanceType(1),
|
|
_isBool(1),
|
|
_isInt(1),
|
|
_isNum(1),
|
|
_isObject(1),
|
|
_isString(1),
|
|
_isTop(1),
|
|
_setArrayType(2),
|
|
findType(1),
|
|
instanceType(1)],
|
|
type=[
|
|
inst:Closure,
|
|
inst:JSArray<dynamic>,
|
|
inst:JSBool,
|
|
inst:JSExtendableArray<dynamic>,
|
|
inst:JSFixedArray<dynamic>,
|
|
inst:JSMutableArray<dynamic>,
|
|
inst:JSUnmodifiableArray<dynamic>,
|
|
inst:List<staticGenericMethod.T*>,
|
|
param:Object*,
|
|
param:staticGenericMethod.T*]
|
|
*/
|
|
List<T> staticGenericMethod<T>(T arg) => [arg];
|
|
|
|
/*member: testStaticGenericMethod:
|
|
static=[staticGenericMethod<bool*>(1)],
|
|
type=[inst:JSBool]
|
|
*/
|
|
testStaticGenericMethod() {
|
|
staticGenericMethod<bool>(true);
|
|
}
|
|
|
|
/*member: testInstanceGenericMethod:
|
|
dynamic=[exact:GenericClass.genericMethod<bool*>(1)],
|
|
static=[
|
|
GenericClass.generative(0),
|
|
checkTypeBound(4)],
|
|
type=[inst:JSBool]
|
|
*/
|
|
testInstanceGenericMethod() {
|
|
new GenericClass<int, String>.generative().genericMethod<bool>(false);
|
|
}
|
|
|
|
abstract class AbstractClass {
|
|
// ignore: UNUSED_FIELD
|
|
final _field;
|
|
|
|
/*member: AbstractClass.:type=[inst:JSNull]*/
|
|
factory AbstractClass() => null;
|
|
}
|
|
|
|
/*member: testAbstractClassWithField:static=[AbstractClass.(0)]*/
|
|
testAbstractClassWithField() => new AbstractClass();
|
|
|
|
/*member: testMixinInstantiation:static=[Sub.(0)]*/
|
|
testMixinInstantiation() => new Sub();
|
|
|
|
/*member: testNamedMixinInstantiation:static=[NamedMixin.(0)]*/
|
|
testNamedMixinInstantiation() => new NamedMixin();
|
|
|
|
/*member: testGenericMixinInstantiation:static=[
|
|
GenericSub.(0),
|
|
checkTypeBound(4)]*/
|
|
testGenericMixinInstantiation() => new GenericSub<int, String>();
|
|
|
|
/*member: testGenericNamedMixinInstantiation:static=[
|
|
GenericNamedMixin.(0),
|
|
checkTypeBound(4)]*/
|
|
testGenericNamedMixinInstantiation() => new GenericNamedMixin<int, String>();
|
|
|
|
class Class {
|
|
/*member: GenericClass.generative:static=[Object.(0)]*/
|
|
const Class.generative();
|
|
}
|
|
|
|
class GenericClass<X, Y> {
|
|
const GenericClass.generative();
|
|
|
|
/*member: GenericClass.genericMethod:
|
|
static=[
|
|
Rti._bind(1),
|
|
Rti._eval(1),
|
|
_arrayInstanceType(1),
|
|
_asBool(1),
|
|
_asBoolQ(1),
|
|
_asBoolS(1),
|
|
_asDouble(1),
|
|
_asDoubleQ(1),
|
|
_asDoubleS(1),
|
|
_asInt(1),
|
|
_asIntQ(1),
|
|
_asIntS(1),
|
|
_asNum(1),
|
|
_asNumQ(1),
|
|
_asNumS(1),
|
|
_asObject(1),
|
|
_asString(1),
|
|
_asStringQ(1),
|
|
_asStringS(1),
|
|
_asTop(1),
|
|
_generalAsCheckImplementation(1),
|
|
_generalIsTestImplementation(1),
|
|
_generalNullableAsCheckImplementation(1),
|
|
_generalNullableIsTestImplementation(1),
|
|
_installSpecializedAsCheck(1),
|
|
_installSpecializedIsTest(1),
|
|
_instanceType(1),
|
|
_isBool(1),
|
|
_isInt(1),
|
|
_isNum(1),
|
|
_isObject(1),
|
|
_isString(1),
|
|
_isTop(1),
|
|
_setArrayType(2),
|
|
findType(1),
|
|
instanceType(1)],
|
|
type=[
|
|
inst:Closure,
|
|
inst:JSArray<dynamic>,
|
|
inst:JSBool,
|
|
inst:JSExtendableArray<dynamic>,
|
|
inst:JSFixedArray<dynamic>,
|
|
inst:JSMutableArray<dynamic>,
|
|
inst:JSNull,
|
|
inst:JSUnmodifiableArray<dynamic>,
|
|
inst:Map<GenericClass.X*,genericMethod.T*>,
|
|
param:Object*,
|
|
param:genericMethod.T*]
|
|
*/
|
|
Map<X, T> genericMethod<T>(T arg) => {null: arg};
|
|
}
|
|
|
|
/*member: Super.:static=[Object.(0)]*/
|
|
class Super {}
|
|
|
|
class Mixin1 {}
|
|
|
|
class Mixin2 {}
|
|
|
|
/*member: Sub.:static=[_Sub&Super&Mixin1&Mixin2.(0)]*/
|
|
class Sub extends Super with Mixin1, Mixin2 {}
|
|
|
|
class NamedMixin = Super with Mixin1, Mixin2;
|
|
|
|
/*member: GenericSuper.:static=[Object.(0)]*/
|
|
class GenericSuper<X1, Y1> {}
|
|
|
|
class GenericMixin1<X2, Y2> {}
|
|
|
|
class GenericMixin2<X3, Y3> {}
|
|
|
|
/*member: GenericSub.:
|
|
static=[_GenericSub&GenericSuper&GenericMixin1&GenericMixin2.(0)]
|
|
*/
|
|
class GenericSub<X4, Y4> extends GenericSuper<X4, Y4>
|
|
with GenericMixin1<X4, Y4>, GenericMixin2<X4, Y4> {}
|
|
|
|
class GenericNamedMixin<X5, Y5> = GenericSuper<X5, Y5>
|
|
with GenericMixin1<X5, Y5>, GenericMixin2<X5, Y5>;
|