Skip to content

Commit

Permalink
Turn on the experimental feature inference-update-1.
Browse files Browse the repository at this point in the history
Fixes dart-lang/language#731.

Change-Id: I5fee1470efe7b891b79dcfecd33bc3670590efb3
Tested: trybots, and global presubmit in the internal mono repo
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243530
Reviewed-by: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Liam Appelbe <liama@google.com>
Reviewed-by: Michael Thomsen <mit@google.com>
  • Loading branch information
stereotype441 authored and Commit Bot committed May 24, 2022
1 parent ddad653 commit 0a92b0c
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 33 deletions.
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,52 @@
## 2.18.0

### Language

The following features are new in the Dart 2.18 [language version][]. To use
them, you must set the lower bound on the SDK constraint for your package to
2.18 or greater (`sdk: '>=2.18.0 <3.0.0'`).

[language version]: https://dart.dev/guides/language/evolution

- **[Enhanced type inference for generic invocations with function
literals][]**: Invocations of generic methods/constructors that supply
function literal arguments now have improved type inference. This primarily
affects the `Iterable.fold` method. For example, in previous versions of
Dart, the compiler would fail to infer an appropriate type for the parameter
`a`:

```dart
void main() {
List<int> ints = [1, 2, 3];
var maximum = ints.fold(0, (a, b) => a < b ? b : a);
}
```

With this improvement, `a` receives its type from the initial value, `0`.

On rare occasions, the wrong type will be inferred, leading to a compile-time
error, for example in this code, type inference will infer that `a` has a
type of `Null`:

```dart
void main() {
List<int> ints = [1, 2, 3];
var maximumOrNull = ints.fold(null,
(a, b) => a == null || a < b ? b : a);
}
```

This can be worked around by supplying the appropriate type as an explicit
type argument to `fold`:

```dart
void main() {
List<int> ints = [1, 2, 3];
var maximumOrNull = ints.fold<int?>(null,
(a, b) => a == null || a < b ? b : a);
}
```

### Core libraries

#### `dart:html`
Expand Down
4 changes: 2 additions & 2 deletions pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ class ExperimentalFeatures {
documentation:
'Horizontal type inference for function expressions passed to generic invocations.',
experimentalReleaseVersion: null,
releaseVersion: null,
releaseVersion: Version.parse('2.18.0'),
);

static final inference_update_2 = ExperimentalFeature(
Expand Down Expand Up @@ -350,7 +350,7 @@ class IsEnabledByDefault {
static const bool generic_metadata = true;

/// Default state of the experiment "inference-update-1"
static const bool inference_update_1 = false;
static const bool inference_update_1 = true;

/// Default state of the experiment "inference-update-2"
static const bool inference_update_2 = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class ExperimentalFlag {

static const ExperimentalFlag inferenceUpdate1 = const ExperimentalFlag(
name: 'inference-update-1',
isEnabledByDefault: false,
isEnabledByDefault: true,
isExpired: false,
enabledVersion: const Version(2, 18),
experimentEnabledVersion: const Version(2, 18),
Expand Down
42 changes: 16 additions & 26 deletions runtime/vm/experimental_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,29 @@ namespace dart {

bool GetExperimentalFeatureDefault(ExperimentalFeature feature) {
constexpr bool kFeatureValues[] = {
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true, true, true, true, true, true, true,
true, true, true, true, true, true, true,
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureValues));
return kFeatureValues[static_cast<int>(feature)];
}

const char* GetExperimentalFeatureName(ExperimentalFeature feature) {
constexpr const char* kFeatureNames[] = {
"nonfunction-type-aliases",
"non-nullable",
"extension-methods",
"constant-update-2018",
"control-flow-collections",
"generic-metadata",
"set-literals",
"spread-collections",
"triple-shift",
"constructor-tearoffs",
"enhanced-enums",
"named-arguments-anywhere",
"super-parameters",
"nonfunction-type-aliases",
"non-nullable",
"extension-methods",
"constant-update-2018",
"control-flow-collections",
"generic-metadata",
"set-literals",
"spread-collections",
"triple-shift",
"constructor-tearoffs",
"enhanced-enums",
"named-arguments-anywhere",
"super-parameters",
"inference-update-1",
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureNames));
return kFeatureNames[static_cast<int>(feature)];
Expand Down
1 change: 1 addition & 0 deletions runtime/vm/experimental_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum class ExperimentalFeature {
enhanced_enums,
named_arguments_anywhere,
super_parameters,
inference_update_1,
};

bool GetExperimentalFeatureDefault(ExperimentalFeature feature);
Expand Down
2 changes: 1 addition & 1 deletion tests/corelib/iterable_empty_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ main() {
Expect.throwsRangeError(() => it.elementAt(0), name);
Expect.throwsStateError(() => it.reduce((a, b) => a), name);
Expect.throwsStateError(() => it.singleWhere((_) => true), name);
Expect.equals(42, it.fold(42, (a, b) => "not 42"), name);
Expect.equals(42, it.fold<dynamic>(42, (a, b) => "not 42"), name);
Expect.equals(42, it.firstWhere((v) => true, orElse: () => 42), name);
Expect.equals(42, it.lastWhere((v) => true, orElse: () => 42), name);
Expect.equals("", it.join("separator"), name);
Expand Down
20 changes: 17 additions & 3 deletions tools/experimental_features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,6 @@ features:
macros:
help: "Static meta-programming"

inference-update-1:
help: "Horizontal type inference for function expressions passed to generic invocations."

inference-update-2:
help: "Type promotion for fields"

Expand Down Expand Up @@ -264,3 +261,20 @@ features:
void main(){
print(C('feature enabled').foo);
}
inference-update-1:
help: "Horizontal type inference for function expressions passed to generic invocations."
enabledIn: '2.18.0'
validation: |
void test(List<int> list) {
var a = list.fold(0, (x, y) => x + y);
f(a);
}
void f<T>(T t) {
if (T == int) {
print('feature enabled');
}
}
void main() {
test([1, 2, 3]);
}

0 comments on commit 0a92b0c

Please sign in to comment.