Description
If a Map or List is const, and a constant, present key or constant, in-bounds index is used, the resulting expression should also be a compile-time constant.
What steps will reproduce the problem?
const Map<String, String> A_CONST_MAP = const {
'foo': 'bar',
'baz': 'bif',
};
const List<String> A_CONST_LIST = const ['foo', 'bar'];
const String A_CONST_STRING = A_CONST_MAP['foo'];
const String ANOTHER_CONST_STRING = A_CONST_LIST[0];
const String YET_ANOTHER_CONST_STRING = A_CONST_MAP[A_CONST_LIST[0]];
What is the expected output?
No compiler error.
What do you see instead?
error: line XX pos YY: initializer is not a valid compile-time constant
const String A_CONST_STRING = A_CONST_MAP['foo'];
^
error: line XX pos YY: initializer is not a valid compile-time constant
const String ANOTHER_CONST_STRING = A_CONST_LIST[0];
^
etc.
What version of the product are you using? On what operating system?
Dart VM version: 1.1.0-dev.5.11 (Wed Jan 15 00:41:27 2014) on "linux_x64"
Please provide any additional information below.
Declaring these "final" quiets the "initializer is not a valid compile-time constant" error:
final String aFinalString = A_CONST_MAP['foo'];
final String anotherFinalString = A_CONST_LIST[0];
However, the resulting Strings are then not usable as default values for named parameters:
error: line XX pos YY: expression is not a valid compile-time constant
void Foo({String val: aFinalString}) {
^
Activity
iposva-google commentedon Apr 23, 2014
cc @gbracha.
Removed Type-Defect label.
Added Type-Enhancement, Area-Language, Triaged labels.
gbracha commentedon Apr 23, 2014
This sounds reasonable. Changing the spec has recently become much harder, because of the standardization process. It might make into the next rev of the Dart standard.
Set owner to @gbracha.
Added Accepted label.
lrhn commentedon Apr 23, 2014
A final field of a const object could also be read/determined at compile time. Would that be possible too? (Or maybe just a special case for String.length/List.length?)
gbracha commentedon Apr 23, 2014
Re #3: this makes the final vs. const distinction a bit murky, but it is certainly possible.
DartBot commentedon Apr 24, 2014
This comment was originally written by @seaneagan
Re #3/#4: You should be required to mark the instance field as "const" instead of "final" for that behavior. This is because the constness makes refactoring to a getter a breaking change since getters can't be const. It must be opt in, just like constructors and static fields must be marked as "const". The instance field would only be const if the constructor was called with "const".
However, getters could also be const with issue #1.
DartBot commentedon May 5, 2014
This comment was originally written by da...@google.com
Would also like to see using a final member of a static const object as a const
class Foo {
final int value;
static const Foo BAR = const Foo.(1);
static const Foo BAZ = const Foo.(2);
const Foo._(this.value);
}
...
switch (x) {
case Foo.BAR.value:
...
break;
case Foo.BAZ.value:
...
break;
}
DartBot commentedon May 5, 2014
This comment was originally written by sophielight...@gmail.com
#7: see #5 for why it should be
const int value
for it to be considered constant.DartBot commentedon May 5, 2014
This comment was originally written by da...@google.com
#8: That's would work, but it's not possible to mark a field in a class const at this point (only static const, which isn't useful here).
This change might be implied in issue #1, but that's not clear from a cursory read, hence this comment.
DartBot commentedon May 5, 2014
This comment was originally written by @seaneagan
I noted in issue #18241 that const instance fields (and operators like List.[] as above) would be some of the methods that could be marked "const".
floitschG commentedon Aug 19, 2014
Issue #20574 has been merged into this issue.
lrhn commentedon Nov 18, 2014
Issue #21625 has been merged into this issue.
munificent commentedon Dec 15, 2016
Duplicate of #3059.