dart-lang / dart-lang/language

`const` Constructor parameters are never considered `const`

Open
#2,000 15 comments 1 reaction 0 assignees View on GitHub
enhanced-const request
Dominant language
TeX
Stars
2.9k
Forks
239
Avg merge
2d 18h
Merged PRs (30d)
14

Description

If a class defines a `const` constructor, it can be created either as `const` or as regular internally `final` object.
Should this `const-in-const-context` notion not apply to the parameters as well?

Take e.g.:
```dart
class CanConst {
final int value;
const CanConst(this.value);
}
```

Here `const v = 1; const CanConst(1)` works but `(int v) => const CanConst(v);` does not.
=> parameter must be constant when used in constant context.

Where as `const v = 1; CanConst(1)` and `(int v) => CanConst(v);` both work.
=> parameter must not be constant when used outside constant context.

==> parameter behaves like it is `const-in-const-context`

______
Since the parameter is currently not `const-in-const-context`, we get e.g. the following:

```dart
const canConst = CanConst(1);
const canNotConst = CanNotConst(1); // Error
const canNotConstContainer = CanNotConstContainer(CanNotConst(1)); // Error

class CanConst {
final int value;
const CanConst(this.value);
}

class CanNotConst {
final int value;
CanNotConst(this.value);
}

class CanNotConstContainer {
final CanNotConst cnc;
const CanNotConstContainer(this.cnc); // No Error
}
```
Which I think should be warned about in `const CanNotConstContainer(this.cnc)` since `CanNotConst` will never be able to be `const`.

_________

Further, we get counter-intuitive (at least to me) behaviour with trying to make classes constant:

Starting with this non-constant class:
```dart
class MyClass {
final int value;
final MyOtherClass other;

MyClass(this.value, this.other);
MyClass.sameOther(int value)
: this.value = value,
other = MyOtherClass(value);
}

class MyOtherClass {
final in value;
const MyOtherClass(this.value);
}
```

We can make the default constructor `const` since `MyOtherClass` has a const constructor:
```dart
class MyClass {
// ...
const MyClass(this.value, this.other);
}
const myConst = MyClass(1, MyOtherClass(1));
```

However, we cant do:

```dart
class MyClass {
// ...
const MyClass.sameOther(int value)
// why does this work ...
: this.value = value,
// ... but this does not
other = MyOtherClass(value);
// ----------^^^^^^^^^^^^^^^^^^^^^
// Invalid const value
}
```

_____
Since the `const` part of the constructor is only used in `const` context, I had the following mental model:

Used in `const` context.
```dart
class MyClass {
const int value;
const MyOtherClass other;

const MyClass(this.value, this.other);
const MyClass.sameOther(const int value)
: this.value = value,
other = const MyOtherClass(value);
}
```

Used outside of `const` context.
```dart
class MyClass {
final int value;
final MyOtherClass other;

MyClass(this.value, this.other);
MyClass.sameOther(int value)
: this.value = value,
other = MyOtherClass(value);
}
```

_____
P.S.
I recently assumed that fields of an object created via `const` would be `const` as well, which might be related (even if only in my wrong mental model)
(https://github.com/dart-lang/language/issues/1868#issuecomment-925587460)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.