143 lines
4.1 KiB
Plaintext
143 lines
4.1 KiB
Plaintext
Variables of type `void` should not be assigned a value.
|
|
|
|
== Why is this an issue?
|
|
|
|
Unlike other languages where `void` is the absence of a type (and related value), `void` in Dart is a type, which is not compatible with any other type, since it is conceptually a supertype of `Object`.
|
|
|
|
Therefore, in Dart it's possible to write the following code:
|
|
|
|
[source,dart]
|
|
----
|
|
void x = 3; // A variable of type void can be assigned a value of type int
|
|
void f(void x) => x; // A function that takes a void input argument and returns it as output
|
|
----
|
|
|
|
The variable `x` declared above, and the result of `f(x)` are effectively of type `void`. However, while `void` variables can be declared, initialized and even computed, they cannot be used by any function that expects a non-`void` type, by the very definition of `void` type.
|
|
|
|
[source,dart]
|
|
----
|
|
print(x); // Error: This expression has type 'void' and can't be used.
|
|
print(f(x)); // Error: This expression has type 'void' and can't be used.
|
|
----
|
|
|
|
Therefore, assigning a value to a variable of type `void` is almost certainly a mistake.
|
|
|
|
For example, in the cases where the type is not known, the variable should have not been declared as `void`, but as `dynamic`:
|
|
|
|
* `void` variables can be assigned values of any type, but cannot be assigned to any non-`void` variable
|
|
* `dynamic` variables, like `void` ones, can be assigned values of any type, and, unlike `void` variables, can be assigned to any non-`dynamic` variable
|
|
|
|
Notice that, because `void` is a type, it can be used as a valid type parameter for a generic class, and that can lead to indirect or "hidden" `void` assignments:
|
|
|
|
[source,dart]
|
|
----
|
|
class Wrapper<T> {
|
|
T value;
|
|
Wrapper(this.value);
|
|
}
|
|
|
|
void main() {
|
|
Wrapper<void> w = Wrapper(3); // This is a "hidden" assignment to void
|
|
w.value = 3; // This is an explicit assignment to a field of type void
|
|
}
|
|
----
|
|
|
|
Another example of a "hidden" assignment to `void` is when assigning generic unconstrained type parameters in generic methods:
|
|
|
|
[source,dart]
|
|
----
|
|
void f<T>(T x, T y) {
|
|
y = x; // This is a "hidden" assignment to void
|
|
T z;
|
|
z = x; // This too, is a "hidden" assignment to void
|
|
}
|
|
----
|
|
|
|
However, such scenarios are not reported by the rule because for any non-`void` type `T`, the assignment is valid. On the other hand, calling the function `f` with anything other than `void` parameters will be reported as an issue:
|
|
|
|
[source,dart]
|
|
----
|
|
f(42, 'a string'); // Both 1st and 2nd parameters are non compliant
|
|
----
|
|
|
|
== How to fix it
|
|
|
|
Identify the scenario leading to the assignment of a value to a variable of type `void` and correct it:
|
|
|
|
* if the type of the variable is not known, declare it as `dynamic`
|
|
* if the type of the variable was mistakenly declared as `void`, replace it with the correct type
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,dart,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
void x;
|
|
x = 3; // Non compliant
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,dart,diff-id=1,diff-type=compliant]
|
|
----
|
|
dynamic x; // type of x not known
|
|
x = 3;
|
|
----
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,dart,diff-id=2,diff-type=noncompliant]
|
|
----
|
|
void x;
|
|
x = 3; // Non compliant
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,dart,diff-id=2,diff-type=compliant]
|
|
----
|
|
int x; // void mistakenly used instead of the actual type
|
|
x = 3;
|
|
----
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,dart,diff-id=3,diff-type=noncompliant]
|
|
----
|
|
Wrapper<void> w = Wrapper(3); // Non compliant
|
|
w.value = 3; // Non compliant
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,dart,diff-id=3,diff-type=compliant]
|
|
----
|
|
Wrapper<int> w = Wrapper(3);
|
|
w.value = 3;
|
|
----
|
|
|
|
== Resources
|
|
|
|
=== Documentation
|
|
|
|
* Dart Docs - https://dart.dev/tools/linter-rules/void_checks[Dart Linter rule - void_checks]
|
|
* Medium - https://medium.com/dartlang/dart-2-legacy-of-the-void-e7afb5f44df0[Dart 2: Legacy of the `void`]
|
|
* Medium - https://medium.com/flutter-community/the-curious-case-of-void-in-dart-f0535705e529[The curious case of void in Dart]
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Assignment to a variable of type 'void'.
|
|
|
|
=== Highlighting
|
|
|
|
The entire assignment expression: e.g. `x = 3` in `x = 3;`.
|
|
|
|
endif::env-github,rspecator-view[]
|