You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The goal is to catch more error-prone code during static analysis; for example, code which is guaranteed to error at runtime. This often two secondary effects: (1) reducing errors in developer understanding of such code, and (2) reducing dynamic dispatch in code where a developer did not think dynamic dispatch was occurring.
We define a "raw type" as a type with omitted type argument(s). Dart fills in such types with their bounds, or dynamic if there are no bounds. Here are some examples:
voidmain() {
List a = [1, 2, 3];
a.forEach((n) =>print(n.isEven));
fn(a);
}
voidfn(List strings) => strings.forEach((s) =>print(s.toUpperCase()));
On the first line of main, a is declared as a List<dynamic>. The type of [1, 2, 3] is inferred from List<dynamic>. There is no implicit cast. On the second line, n.isEven is a dynamic dispatch call, since the elements of a are treated as dynamic. On the third line, when fn is called, the runtime will throw a NoSuchMethodError, trying to call toUpperCase on the numbers. There are currently no compile-time, static analysis checks that would reveal a problem.
The proposed "strict-raw-types" mode will report errors (e.g. Hints in the analyzer) at the declaration of most types with omitted type arguments. Here are some examples of "raw types" that would be reported:
A variable declaration, like List a = [1, 2, 3];
A type argument, like Future<List> a;
A function parameter, like main(List args) {}, typedef cb = void Function(Future)
A function return type, like Future main() {}, typedef cb = Future Function()
A class declaration, like class MyList extends List {}, mixin Foo on List
There are some cases where a type will not be considered a "raw type":
Omitted type arguments on types which are annotated with @optionalTypeArgs from the meta package. There are some classes which are often used in ways where type arguments are not known statically, or they are found in heterogeneous collections. If such a class is annotated with @optionalTypeArgs, then it will not be reported as a "raw type."
A type on the right side of an is or as expression; in experiments it was found that this just forced developers to write is List<dynamic> and as Map<dynamic, dynamic> over and over and over. This increases verbosity, without improving correctness or understandability.
Raw types are currently one type of static analysis report found with the "implicit-dynamic: false" static analysis mode. However, multiple attempts to enable this mode on large code bases have shown it to be too onerous to comply with; "strict raw types" are just one piece of "inplicit-dynamic: false", and should be must easier to comply with.
The goal is to catch more error-prone code during static analysis; for example, code which is guaranteed to error at runtime. This often two secondary effects: (1) reducing errors in developer understanding of such code, and (2) reducing dynamic dispatch in code where a developer did not think dynamic dispatch was occurring.
We define a "raw type" as a type with omitted type argument(s). Dart fills in such types with their bounds, or dynamic if there are no bounds. Here are some examples:
On the first line of
main
,a
is declared as aList<dynamic>
. The type of[1, 2, 3]
is inferred fromList<dynamic>
. There is no implicit cast. On the second line,n.isEven
is a dynamic dispatch call, since the elements ofa
are treated as dynamic. On the third line, whenfn
is called, the runtime will throw a NoSuchMethodError, trying to calltoUpperCase
on the numbers. There are currently no compile-time, static analysis checks that would reveal a problem.The proposed "strict-raw-types" mode will report errors (e.g. Hints in the analyzer) at the declaration of most types with omitted type arguments. Here are some examples of "raw types" that would be reported:
List a = [1, 2, 3];
Future<List> a;
main(List args) {}
,typedef cb = void Function(Future)
Future main() {}
,typedef cb = Future Function()
class MyList extends List {}
,mixin Foo on List
There are some cases where a type will not be considered a "raw type":
@optionalTypeArgs
from the meta package. There are some classes which are often used in ways where type arguments are not known statically, or they are found in heterogeneous collections. If such a class is annotated with@optionalTypeArgs
, then it will not be reported as a "raw type."is
oras
expression; in experiments it was found that this just forced developers to writeis List<dynamic>
andas Map<dynamic, dynamic>
over and over and over. This increases verbosity, without improving correctness or understandability.Raw types are currently one type of static analysis report found with the "implicit-dynamic: false" static analysis mode. However, multiple attempts to enable this mode on large code bases have shown it to be too onerous to comply with; "strict raw types" are just one piece of "inplicit-dynamic: false", and should be must easier to comply with.
This issue is a continuation of dart-lang/sdk#33749. Thanks to @munificent, @leafpetersen, and @matanlurey for specifying most of the above.
The text was updated successfully, but these errors were encountered: