-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
void type can be used as an generic #53179
Comments
Here's another problem, maybe they are related. import 'dart:async';
void main() async {
final testX = TestX();
try {
testX.init().ignore();
await testX.isInitialized.timeout(
const Duration(seconds: 4),
onTimeout: () {
return testX.init();
},
);
} on Object catch (error, sk) {
print('Error: $error, \n sk: $sk');
}
}
class TestX {
final _completer = Completer<bool>();
TestX();
Future<void> init() async {
if (_completer.isCompleted) {
return;
}
await Future<void>.delayed(const Duration(seconds: 5));
_completer.complete(true);
}
Future<void> get isInitialized => _completer.future;
}
here is what is output to the console: Error: type '() => Future<void>' is not a subtype of type '(() => FutureOr<bool>)?' of 'onTimeout',
sk: #0 Future.timeout (dart:async/future_impl.dart)
#1 main (package:untitled/main.dart:11:31)
#2 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:297:19)
#3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12) |
Everything here looks like it's working as intended. The It's special cased such that a static type of |
@Vorkytaka wrote:
As @lrhn already mentioned, the rules that prevent (or rather: introduce some resistance against) using a value of type There is some further discussions about this design choice in the section about 'Void Soundness' in the language specification. In short, we decided that this kind of protection must not give rise to any run-time costs in code where the type This is indeed working as intended. PS: The language specification updates about null safety are still in review, so the description in the language specification fits the pre-null-safety version of Dart. |
@wwwhttpru wrote:
The error that occurs in your program is caused by dynamically checked covariance. See dart-lang/language#524 for an approach, declaration-site variance, that allows this kind of situation to be detected statically (and vote for that issue if you want support for this kind of static checking). Note, though, that the given example cannot directly use declaration-site variance because it requires changes to some classes that are provided by the platform (such as The problem in the example program is that the static type of However, the run-time type of In fact, you're passing an object of type (Declaration-site variance is all about reporting that error at compile time rather than generating code to throw an exception at run time.) If So this is a completely different topic, but still working as designed. ;-) |
(Just to be up-front here: if I cannot make |
Ok, I've got that this is expected for the compiler. For me, still, pretty strange that i cannot use void a = 10;
print(a); // compile time error
f(a); // no error at all It's looks like we should not have ability to use it in this case too. |
@Vorkytaka wrote:
This is because it is not an error to pass the value of a |
@lrhn wrote:
Like this?: abstract interface class Future<out T> {
factory Future(FutureOr<T> computation()) =>
throw 'Not implemented';
factory Future.microtask(FutureOr<T> computation()) =>
throw 'Not implemented';
factory Future.sync(FutureOr<T> computation()) =>
throw 'Implementation omitted';
factory Future.value([FutureOr<T>? value]) =>
throw 'Implementation omitted';
factory Future.error(Object error, [StackTrace? stackTrace]) =>
throw 'Implementation omitted';
factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) =>
throw 'Implementation omitted';
Future<R> then<R>(FutureOr<R> onValue(T value), {Function? onError});
Future<T> catchError(Function onError, {bool test(Object error)?});
Future<T> whenComplete(FutureOr<void> action());
Stream<T> asStream();
Future<T> timeout(Duration timeLimit, {covariant FutureOr<T> onTimeout()?});
} |
Hello!
As we know,
void
is the type that indicates that a value shouldn't be used.For example:
This code won't be compiled because of error
But, if we will use
void a
with a generic function, then this will compile and even work.This code will print us this output:
So, as we can see, generic type is void, but this works fine.
But, if we will change generic in the function to the
<T extends Object>
or will usedynamic a
instead of generic, then we will get expected type errors.Also, if we will use
<T extends Object?>
, then it also compile fine.So, is this an bug and compiler should know that void should not be used as a generic, or this is expected behaviour?
The text was updated successfully, but these errors were encountered: