void main() {
const list = [1, 2, 3];
const string = 'This is a $list'; // Error
}
When I can't assign list a new value and modify any of its elements, why can't I then use the list in my string literal?
void main() {
const list = [1, 2, 3];
const string = 'This is a $list'; // Error
}
When I can't assign list a new value and modify any of its elements, why can't I then use the list in my string literal?
Dart doesn't have a concept of saying that a method call can be evaluated at compilation time (in contrast to constexpr in C++). Therefore Dart cannot guarantee that calling a method on a const object returns another const object, and that includes the implicit call to .toString() when doing string interpolation.
For example, this is perfectly legal:
import 'dart:math';
final random = Random();
class Foo {
const Foo();
// Returns a string that is clearly not a compile-time constant.
@override
String toString() => random.nextInt(100).toString();
}
void main() {
const foo = Foo();
print('$foo');
const list = [foo, foo, foo];
print('$list');
}
Note that this doesn't apply to .toString() implementations for some built-in types (e.g. null, numeric, string, and boolean types) since they are known to produce constant values and because Dart does not allow creating derived classes from those types, so they cannot be overridden to do shenanigans like the above example.
It's an interesting question, because some const things can be interpolated into const strings. I checked out the Language Tour, and it gives this example, which is very close to your question:
// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];
const validConstString = '$aConstNum $aConstBool $aConstString';
// const invalidConstString = '$aNum $aBool $aString $aConstList';
The explanation given is that
Literal strings are compile-time constants, as long as any interpolated expression is a compile-time constant that evaluates to null or a numeric, string, or boolean value.
They don't explain why (what the technical reasons are, or the motivations for making the language work this way), but it's clear that a const list does not evaluate to "null or a numeric, string, or boolean value." So it just doesn't matter that your list is const—the string resulting from interpolation with that will not be a compile-time constant, so you can't use const with that string.