[dart2js] Fix #51558 - skip abstract getters

Improve 'enum switch' optimization to not be confused by abstract
getters.

Bug: 51558
Change-Id: Iac4e5238c1884df6afd1611aecc9f158b1a8b167
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286102
Reviewed-by: Nate Biggs <natebiggs@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
Stephen Adams 2023-03-01 16:41:38 +00:00 committed by Commit Queue
parent ed277908ae
commit cfa6d0f735
2 changed files with 51 additions and 4 deletions

View file

@ -1209,10 +1209,21 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
} }
FieldEntity _indexFieldOfEnumClass(ClassEntity enumClass) { FieldEntity _indexFieldOfEnumClass(ClassEntity enumClass) {
final member = _closedWorld.elementEnvironment // We expect the enum class to extend `_Enum`, which has an `index` field,
.lookupClassMember(enumClass, const PublicName('index')); // but that might be shadowed by an abstract getter from the class or a
if (member is FieldEntity) return member; // mixin.
throw StateError('$enumClass should have index field, found $member'); ClassEntity? cls = enumClass;
MemberEntity? foundMember;
while (cls != null) {
final member = _closedWorld.elementEnvironment
.lookupClassMember(cls, const PublicName('index'));
if (member == null) break; // should never happen.
foundMember = member;
if (member is FieldEntity) return member;
if (!member.isAbstract) break;
cls = _closedWorld.elementEnvironment.getSuperClass(cls);
}
throw StateError('$enumClass should have index field, found $foundMember');
} }
IntConstantValue _indexValueOfEnumConstant( IntConstantValue _indexValueOfEnumConstant(

View file

@ -0,0 +1,36 @@
// 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.
import 'package:expect/expect.dart';
// Regression test for http://dartbug.com/51558
//
// Enum classes may have abstract getters in the inheritance chain that, as
// declarations, shadow the `index` of the base class.
abstract class EnumFlag extends Object {
int get index;
int get value => 1 << index;
}
enum EnumXY with EnumFlag { x, y }
extension EnumXTExtensions on EnumXY {
String display() {
switch (this) {
case EnumXY.x:
return 'X';
case EnumXY.y:
return 'Y';
}
}
}
void main() {
Expect.equals('X', EnumXY.x.display());
// This second line is needed so that the abstract getter is resolved.
Expect.equals(0, EnumXY.x.index);
}