-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat/ Add @mustBeConst lint #46287
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Another use case: it looks like I could use this to add const constructors to
Without the annotation this is incorrect because |
This would also be useful to denote functions that end up being sent across isolates. These have to be top-level or static, so effectively constant: Future<T> compute(@mustBeConst FutureOr<T> Function() computation) {
// computation will be sent over a port
}
Future<Isolate> spawn(@mustBeConst Function entrypoint) {
// entrypoint will be passed to Isolate.spawn
} |
Any updates here? |
I'm happy to work on this if no one else is yet. |
@jeffkwoh is investigating with this internally ( b/190345386 ). If that goes well, we'll move it to the public linter. |
Has there been any progress to this? Additionally, I was wondering there have been any considerations made to also enable developers to mark a return of a functions as constant given the parameters passed to it being identical. For instance consider the case of SQL where you might not define all of the queries beforehand but also build some more complex ones. In that case if a deep api function parameter is marked with Consider: abstract class Db {
dynamic execute(@mustBeConst String query, [Map<String, dynamic> parameters]);
}
class Helper {
final Db _db;
Helper(this._db);
List<List<dynamic>> selectFields(
@mustBeConst String table,
@mustBeConst List<String> fields,
) {
// this would indicate an error without List.join being able to indicate
// that given a set of identical parameters the returned result is always
// the same (not necessarily constant (in terms of const constructor))
return _db.execute('SELECT ${fields.join(',')} FROM $table');
}
} To allow better composition it would then make sense to be able to indicate that the result of the function is always the same given identical parameters, which would probably indicated that it doesn't rely on non-constant global state or non constant internal state. Would This would also mean that the function would have to inherit the properties of the given input. So if we consider the following function example: @stableReturn
String join(String str1, String str2) => '$str1$str2';
void safeLog(@mustBeConst String log) => print(log);
void main() {
final log = join('[Info] ', 'Calling main');
safeLog(log);
} it should still work, since because both parameters passed to the I know this is a different feature but I think they compliment each-other well. |
After thinking about this some more, I realised that I was equating For instance, I was thinking this would be allowed: void fn1(@mustBeConst String str, @mustBeConst String str2) => safeLog("$str$str2");
void safeLog(@mustBeConst String string) => print(string); which if I understand the proposal correctly wouldn't be since our But if this were allowed then we would essentially have two types of So the previous example: void fn1(@mustBeLiteral String str, @mustBeLiteral String str2) => safeLog("$str$str2");
void safeLog(@mustBeLiteral String string) => print(string); would work because both This way for instance the literal property could be tracked: void fn(@mustBeLiteral String literal, String anyStr) {
final str1 = 'prefix:$literal'; // is literal
final str2 = '$literal$anyStr'; // is not literal
} But I have to admit I have a hard time imagining what this would mean for datatypes other than String. |
I have a use-case for our JavaScript templating feature sdk/pkg/js_ast/lib/src/builder.dart Lines 199 to 205 in 92972ff
I want to ensure that most uses pass a constant as the
The js_ast library supports interpolation of JavaScript trees (filling in Enforcing that something is a constant is a mechanism used to enforce a policy. There are two variables that I see in use cases.
I suggest that these are made to be parameters of a general const useTreeInterpolation = MustBeConst(reason: r'''
Arguments to `js()` should be constants.
Constructing strings should be avoided. Use tree interpolation instead.
If building a string is unavoidable, use uncachedExpressionTemplate to avoid memory leaks.
''',
restrictions: [MustBeConst.literals, MustBeConst.variables]
); used so: Expression call(@useTreeInterpolation String source, [var arguments]) { When the lint fires, the Regarding what constitutes a constant, I see several levels. For my specific case I would be happy with literals and references to declared I see these tiers of constant complexity:
|
Requiring something to be a constant can be done for different reasons.
The use-cases listed here depend on one of the first two. The If you need deep immutability, it could be Being known at compile-time is really only possible for constants, so |
Slightly different from what is discussed above: a lint to make sure that all the instances of a given class must be Use case: In Flutter, we tree shake icon fonts to remove the glyphs that are not being used in the application. And this is performed by scanning the tree-shaken dill file looking for It would be nice if we can add a |
This was landed in b321254. In the next Dart release (or sooner if you use an unstable release), the analyzer should trigger for |
Add a lint for dart parameters that allows the analyzer to check if parameters are const.
Sample Use cases
When parameters are compile time constants, it provides the guarantee that the parameters cannot be user supplied. This involves the overall security of our applications, and reduces the need for security and privacy reviews when code can be formally verified to be safe. This lead to the following use cases:
Designing API for SQL methods that are guaranteed against SQL injection
Logging libraries can ensure that there is no PII in log messages from prod
dart --version
)google's internal version
Internal link: b/190345386
The text was updated successfully, but these errors were encountered: