dart-lang / dart-lang/language

Allow accessing `Enum.values` inside extensions and mixins

Open
#4,037 8 comments 2 reactions 0 assignees View on GitHub
feature
Dominant language
TeX
Stars
2.9k
Forks
239
Avg merge
2d 18h
Merged PRs (30d)
14

Description

Today, doing this is not allowed. We get: `An instance member named 'values' can't be declared in a class that implements 'Enum'.
Try using a different name. (illegal_enum_values)`

```dart
mixin M1 on Enum {
List get values;
}
```

But when we try to do either of the following we get: `Undefined name 'values'.
Try correcting the name to one that is defined, or defining the name. (undefined_identifier)`

```dart
mixin M2 on Enum {
void foo() {
print(values);
}
}

extension EE1 on T {
void bar() {
print(values);
}
}
```

Although, the following is valid and I believe this is a bug but someone can correct me if I'm wrong or confirm so I can create a new issue:

```dart
extension EE2 on T {
List get values => [];
}
```

With the code above, both `M2` and `EE1` stop warning for `undefined_identifier`.

So what I'm asking here is that we give out the same error for `EE2` and `M1` but allow the user to access `values`. This would help for example if someone wants to do an extension like:

```dart
extension ForwardBackwardExt on T {
T? get next {
final nextIndex = index + 1;
if (nextIndex > (values.length - 1)) return null;
return values[nextIndex];
}

T? get previous {
final previousIndex = index - 1;
if (previousIndex < 0) return null;
return values[previousIndex];
}
}
```

For me, what I did in this case, was the following workaround, but it needs me to implement `ForwardBackwardMixin` in every enum I want this and is not ideal if I'd like this to work on anything:

```dart
mixin ForwardBackwardMixin on Enum {
@protected
List get staticValues;
}

extension ForwardBackwardExt> on T {
T? get next {
final nextIndex = index + 1;
if (nextIndex > (staticValues.length - 1)) return null;
return staticValues[nextIndex];
}

T? get previous {
final previousIndex = index - 1;
if (previousIndex < 0) return null;
return staticValues[previousIndex];
}
}
```

Contributor guide

Open the contributing guide

Research direction

No source files or tests are named. Start by comparing the M1, M2, EE1, and EE2 examples and the ForwardBackwardExt workaround, then investigate the Dart language rules governing Enum, mixins, and extensions; done means the intended values access and diagnostics are specified consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.